Imported Upstream version 2.1.11
[platform/upstream/gpg2.git] / g10 / server.c
1 /* server.c - server mode for gpg
2  * Copyright (C) 2006, 2008  Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <ctype.h>
27 #include <unistd.h>
28
29
30 #include "gpg.h"
31 #include <assuan.h>
32 #include "util.h"
33 #include "i18n.h"
34 #include "options.h"
35 #include "../common/sysutils.h"
36 #include "status.h"
37
38
39 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
40
41
42 /* Data used to associate an Assuan context with local server data.  */
43 struct server_local_s
44 {
45   /* Our current Assuan context. */
46   assuan_context_t assuan_ctx;
47   /* File descriptor as set by the MESSAGE command. */
48   gnupg_fd_t message_fd;
49
50   /* List of prepared recipients.  */
51   pk_list_t recplist;
52
53   /* Set if pinentry notifications should be passed back to the
54      client. */
55   int allow_pinentry_notify;
56 };
57
58
59 \f
60 /* Helper to close the message fd if it is open. */
61 static void
62 close_message_fd (ctrl_t ctrl)
63 {
64   if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
65     {
66       assuan_sock_close (ctrl->server_local->message_fd);
67       ctrl->server_local->message_fd = GNUPG_INVALID_FD;
68     }
69 }
70
71
72 /* Skip over options.  Blanks after the options are also removed.  */
73 static char *
74 skip_options (const char *line)
75 {
76   while (spacep (line))
77     line++;
78   while ( *line == '-' && line[1] == '-' )
79     {
80       while (*line && !spacep (line))
81         line++;
82       while (spacep (line))
83         line++;
84     }
85   return (char*)line;
86 }
87
88
89 /* Check whether the option NAME appears in LINE.  */
90 static int
91 has_option (const char *line, const char *name)
92 {
93   const char *s;
94   int n = strlen (name);
95
96   s = strstr (line, name);
97   if (s && s >= skip_options (line))
98     return 0;
99   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
100 }
101
102
103
104
105 \f
106 /* Called by libassuan for Assuan options.  See the Assuan manual for
107    details. */
108 static gpg_error_t
109 option_handler (assuan_context_t ctx, const char *key, const char *value)
110 {
111   ctrl_t ctrl = assuan_get_pointer (ctx);
112
113   (void)value;
114
115   /* Fixme: Implement the tty and locale args. */
116   if (!strcmp (key, "display"))
117     {
118     }
119   else if (!strcmp (key, "ttyname"))
120     {
121     }
122   else if (!strcmp (key, "ttytype"))
123     {
124     }
125   else if (!strcmp (key, "lc-ctype"))
126     {
127     }
128   else if (!strcmp (key, "lc-messages"))
129     {
130     }
131   else if (!strcmp (key, "xauthority"))
132     {
133     }
134   else if (!strcmp (key, "pinentry_user_data"))
135     {
136     }
137   else if (!strcmp (key, "list-mode"))
138     {
139       /* This is for now a dummy option. */
140     }
141   else if (!strcmp (key, "allow-pinentry-notify"))
142     {
143       ctrl->server_local->allow_pinentry_notify = 1;
144     }
145   else
146     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
147
148   return 0;
149 }
150
151
152 /* Called by libassuan for RESET commands. */
153 static gpg_error_t
154 reset_notify (assuan_context_t ctx, char *line)
155 {
156   ctrl_t ctrl = assuan_get_pointer (ctx);
157
158   (void)line;
159
160   release_pk_list (ctrl->server_local->recplist);
161   ctrl->server_local->recplist = NULL;
162
163   close_message_fd (ctrl);
164   assuan_close_input_fd (ctx);
165   assuan_close_output_fd (ctx);
166   return 0;
167 }
168
169
170 /* Called by libassuan for INPUT commands. */
171 static gpg_error_t
172 input_notify (assuan_context_t ctx, char *line)
173 {
174 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
175
176   (void)ctx;
177
178   if (strstr (line, "--armor"))
179     ; /* FIXME */
180   else if (strstr (line, "--base64"))
181     ; /* FIXME */
182   else if (strstr (line, "--binary"))
183     ;
184   else
185     {
186       /* FIXME (autodetect encoding) */
187     }
188   return 0;
189 }
190
191
192 /* Called by libassuan for OUTPUT commands. */
193 static gpg_error_t
194 output_notify (assuan_context_t ctx, char *line)
195 {
196 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
197
198   (void)ctx;
199
200   if (strstr (line, "--armor"))
201     ; /* FIXME */
202   else if (strstr (line, "--base64"))
203     {
204       /* FIXME */
205     }
206   return 0;
207 }
208
209
210
211 \f
212 /*  RECIPIENT [--hidden] <userID>
213
214    Set the recipient for the encryption.  <userID> should be the
215    internal representation of the key; the server may accept any other
216    way of specification.  If this is a valid and trusted recipient the
217    server does respond with OK, otherwise the return is an ERR with
218    the reason why the recipient can't be used, the encryption will
219    then not be done for this recipient.  If the policy is not to
220    encrypt at all if not all recipients are valid, the client has to
221    take care of this.  All RECIPIENT commands are cumulative until a
222    RESET or an successful ENCRYPT command.  */
223 static gpg_error_t
224 cmd_recipient (assuan_context_t ctx, char *line)
225 {
226   ctrl_t ctrl = assuan_get_pointer (ctx);
227   gpg_error_t err;
228   int hidden;
229
230   hidden = has_option (line,"--hidden");
231   line = skip_options (line);
232
233   /* FIXME: Expand groups
234   if (opt.grouplist)
235     remusr = expand_group (rcpts);
236   else
237     remusr = rcpts;
238   */
239
240   err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden,
241                             &ctrl->server_local->recplist);
242
243   if (err)
244     log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
245   return err;
246 }
247
248
249 \f
250 /*  SIGNER <userID>
251
252    Set the signer's keys for the signature creation.  <userID> should
253    be the internal representation of the key; the server may accept
254    any other way of specification.  If this is a valid and usable
255    signing key the server does respond with OK, otherwise it returns
256    an ERR with the reason why the key can't be used, the signing will
257    then not be done for this key.  If the policy is not to sign at all
258    if not all signer keys are valid, the client has to take care of
259    this.  All SIGNER commands are cumulative until a RESET but they
260    are *not* reset by an SIGN command because it can be expected that
261    set of signers are used for more than one sign operation.
262
263    Note that this command returns an INV_RECP status which is a bit
264    strange, but they are very similar.  */
265 static gpg_error_t
266 cmd_signer (assuan_context_t ctx, char *line)
267 {
268   (void)ctx;
269   (void)line;
270   return gpg_error (GPG_ERR_NOT_SUPPORTED);
271 }
272
273
274 \f
275 /*  ENCRYPT
276
277    Do the actual encryption process.  Takes the plaintext from the
278    INPUT command, writes the ciphertext to the file descriptor set
279    with the OUTPUT command, take the recipients from all the
280    recipients set so far with RECIPIENTS.
281
282    If this command fails the clients should try to delete all output
283    currently done or otherwise mark it as invalid.  GPG does ensure
284    that there won't be any security problem with leftover data on the
285    output in this case.
286
287    In most cases this command won't fail because most necessary checks
288    have been done while setting the recipients.  However some checks
289    can only be done right here and thus error may occur anyway (for
290    example, no recipients at all).
291
292    The input, output and message pipes are closed after this
293    command.  */
294 static gpg_error_t
295 cmd_encrypt (assuan_context_t ctx, char *line)
296 {
297   ctrl_t ctrl = assuan_get_pointer (ctx);
298   gpg_error_t err;
299   int inp_fd, out_fd;
300
301   (void)line; /* LINE is not used.  */
302
303   if ( !ctrl->server_local->recplist )
304     {
305       write_status_text (STATUS_NO_RECP, "0");
306       err = gpg_error (GPG_ERR_NO_USER_ID);
307       goto leave;
308     }
309
310   inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
311   if (inp_fd == -1)
312     {
313       err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
314       goto leave;
315     }
316   out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
317   if (out_fd == -1)
318     {
319       err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
320       goto leave;
321     }
322
323
324   /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
325      from the default list. */
326
327   /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
328
329   err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
330                        ctrl->server_local->recplist,
331                        out_fd);
332
333  leave:
334   /* Release the recipient list on success.  */
335   if (!err)
336     {
337       release_pk_list (ctrl->server_local->recplist);
338       ctrl->server_local->recplist = NULL;
339     }
340
341   /* Close and reset the fds. */
342   close_message_fd (ctrl);
343   assuan_close_input_fd (ctx);
344   assuan_close_output_fd (ctx);
345
346   if (err)
347     log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
348   return err;
349 }
350
351
352 \f
353 /*  DECRYPT
354
355     This performs the decrypt operation.  */
356 static gpg_error_t
357 cmd_decrypt (assuan_context_t ctx, char *line)
358 {
359   ctrl_t ctrl = assuan_get_pointer (ctx);
360   gpg_error_t err;
361   int inp_fd, out_fd;
362
363   (void)line; /* LINE is not used.  */
364
365   inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
366   if (inp_fd == -1)
367     return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
368   out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
369   if (out_fd == -1)
370     return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
371
372   glo_ctrl.lasterr = 0;
373   err = decrypt_message_fd (ctrl, inp_fd, out_fd);
374   if (!err)
375     err = glo_ctrl.lasterr;
376
377   /* Close and reset the fds. */
378   close_message_fd (ctrl);
379   assuan_close_input_fd (ctx);
380   assuan_close_output_fd (ctx);
381
382   if (err)
383     log_error ("command '%s' failed: %s\n", "DECRYPT", gpg_strerror (err));
384   return err;
385 }
386
387
388 \f
389 /*  VERIFY
390
391    This does a verify operation on the message send to the input-FD.
392    The result is written out using status lines.  If an output FD was
393    given, the signed text will be written to that.
394
395    If the signature is a detached one, the server will inquire about
396    the signed material and the client must provide it.
397  */
398 static gpg_error_t
399 cmd_verify (assuan_context_t ctx, char *line)
400 {
401   int rc;
402 #ifdef HAVE_W32_SYSTEM
403   (void)ctx;
404   (void)line;
405   rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
406 #else
407   ctrl_t ctrl = assuan_get_pointer (ctx);
408   gnupg_fd_t fd = assuan_get_input_fd (ctx);
409   gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
410   estream_t out_fp = NULL;
411
412   /* FIXME: Revamp this code it is nearly to 3 years old and was only
413      intended as a quick test.  */
414
415   (void)line;
416
417   if (fd == GNUPG_INVALID_FD)
418     return gpg_error (GPG_ERR_ASS_NO_INPUT);
419
420   if (out_fd != GNUPG_INVALID_FD)
421     {
422       es_syshd_t syshd;
423
424 #ifdef HAVE_W32_SYSTEM
425       syshd.type = ES_SYSHD_HANDLE;
426       syshd.u.handle = out_fd;
427 #else
428       syshd.type = ES_SYSHD_FD;
429       syshd.u.fd = out_fd;
430 #endif
431       out_fp = es_sysopen_nc (&syshd, "w");
432       if (!out_fp)
433         return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
434     }
435
436   log_debug ("WARNING: The server mode is WORK "
437              "IN PROGRESS and not ready for use\n");
438
439   rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);
440
441   es_fclose (out_fp);
442   close_message_fd (ctrl);
443   assuan_close_input_fd (ctx);
444   assuan_close_output_fd (ctx);
445 #endif
446
447   if (rc)
448     log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
449   return rc;
450 }
451
452
453 \f
454 /*  SIGN [--detached]
455
456    Sign the data set with the INPUT command and write it to the sink
457    set by OUTPUT.  With "--detached" specified, a detached signature
458    is created.  */
459 static gpg_error_t
460 cmd_sign (assuan_context_t ctx, char *line)
461 {
462   (void)ctx;
463   (void)line;
464   return gpg_error (GPG_ERR_NOT_SUPPORTED);
465 }
466
467
468 \f
469 /*  IMPORT
470
471   Import keys as read from the input-fd, return status message for
472   each imported one.  The import checks the validity of the key.  */
473 static gpg_error_t
474 cmd_import (assuan_context_t ctx, char *line)
475 {
476   (void)ctx;
477   (void)line;
478   return gpg_error (GPG_ERR_NOT_SUPPORTED);
479 }
480
481
482 \f
483 /*  EXPORT [--data [--armor|--base64]] [--] pattern
484
485    Similar to the --export command line command, this command exports
486    public keys matching PATTERN.  The output is send to the output fd
487    unless the --data option has been used in which case the output
488    gets send inline using regular data lines.  The options "--armor"
489    and "--base" ospecify an output format if "--data" has been used.
490    Recall that in general the output format is set with the OUTPUT
491    command.
492  */
493 static gpg_error_t
494 cmd_export (assuan_context_t ctx, char *line)
495 {
496   (void)ctx;
497   (void)line;
498   return gpg_error (GPG_ERR_NOT_SUPPORTED);
499 }
500
501
502 \f
503 /*  DELKEYS
504
505     Fixme
506 */
507 static gpg_error_t
508 cmd_delkeys (assuan_context_t ctx, char *line)
509 {
510   (void)ctx;
511   (void)line;
512   return gpg_error (GPG_ERR_NOT_SUPPORTED);
513 }
514
515
516 \f
517 /*  MESSAGE FD[=<n>]
518
519    Set the file descriptor to read a message which is used with
520    detached signatures.  */
521 static gpg_error_t
522 cmd_message (assuan_context_t ctx, char *line)
523 {
524   int rc;
525   gnupg_fd_t fd;
526   ctrl_t ctrl = assuan_get_pointer (ctx);
527
528   rc = assuan_command_parse_fd (ctx, line, &fd);
529   if (rc)
530     return rc;
531   if (fd == GNUPG_INVALID_FD)
532     return gpg_error (GPG_ERR_ASS_NO_INPUT);
533   ctrl->server_local->message_fd = fd;
534   return 0;
535 }
536
537
538 \f
539 /* LISTKEYS [<patterns>]
540    LISTSECRETKEYS [<patterns>]
541
542    fixme
543 */
544 static gpg_error_t
545 do_listkeys (assuan_context_t ctx, char *line, int mode)
546 {
547   (void)ctx;
548   (void)line;
549   (void)mode;
550
551   return gpg_error (GPG_ERR_NOT_SUPPORTED);
552 }
553
554
555 static gpg_error_t
556 cmd_listkeys (assuan_context_t ctx, char *line)
557 {
558   return do_listkeys (ctx, line, 3);
559 }
560
561
562 static gpg_error_t
563 cmd_listsecretkeys (assuan_context_t ctx, char *line)
564 {
565   return do_listkeys (ctx, line, 2);
566 }
567
568
569 \f
570 /* GENKEY
571
572    Read the parameters in native format from the input fd and create a
573    new OpenPGP key.
574  */
575 static gpg_error_t
576 cmd_genkey (assuan_context_t ctx, char *line)
577 {
578   (void)ctx;
579   (void)line;
580   return gpg_error (GPG_ERR_NOT_SUPPORTED);
581 }
582
583
584 /* GETINFO <what>
585
586    Multipurpose function to return a variety of information.
587    Supported values for WHAT are:
588
589      version     - Return the version of the program.
590      pid         - Return the process id of the server.
591
592  */
593 static gpg_error_t
594 cmd_getinfo (assuan_context_t ctx, char *line)
595 {
596   int rc;
597
598   if (!strcmp (line, "version"))
599     {
600       const char *s = VERSION;
601       rc = assuan_send_data (ctx, s, strlen (s));
602     }
603   else if (!strcmp (line, "pid"))
604     {
605       char numbuf[50];
606
607       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
608       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
609     }
610   else
611     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
612   return rc;
613 }
614
615 static const char hlp_passwd[] =
616   "PASSWD <userID>\n"
617   "\n"
618   "Change the passphrase of the secret key for USERID.";
619 static gpg_error_t
620 cmd_passwd (assuan_context_t ctx, char *line)
621 {
622   /* ctrl_t ctrl = assuan_get_pointer (ctx); */
623   gpg_error_t err;
624
625   (void)ctx;
626   (void)line;
627   /* line = skip_options (line); */
628
629   err = gpg_error (GPG_ERR_NOT_SUPPORTED);
630
631   return err;
632 }
633
634
635
636 \f
637 /* Helper to register our commands with libassuan. */
638 static int
639 register_commands (assuan_context_t ctx)
640 {
641   static struct
642   {
643     const char *name;
644     assuan_handler_t handler;
645     const char * const help;
646   } table[] = {
647     { "RECIPIENT",     cmd_recipient },
648     { "SIGNER",        cmd_signer    },
649     { "ENCRYPT",       cmd_encrypt   },
650     { "DECRYPT",       cmd_decrypt   },
651     { "VERIFY",        cmd_verify    },
652     { "SIGN",          cmd_sign      },
653     { "IMPORT",        cmd_import    },
654     { "EXPORT",        cmd_export    },
655     { "INPUT",         NULL          },
656     { "OUTPUT",        NULL          },
657     { "MESSAGE",       cmd_message   },
658     { "LISTKEYS",      cmd_listkeys  },
659     { "LISTSECRETKEYS",cmd_listsecretkeys },
660     { "GENKEY",        cmd_genkey    },
661     { "DELKEYS",       cmd_delkeys   },
662     { "GETINFO",       cmd_getinfo   },
663     { "PASSWD",        cmd_passwd,  hlp_passwd},
664     { NULL }
665   };
666   int i, rc;
667
668   for (i=0; table[i].name; i++)
669     {
670       rc = assuan_register_command (ctx, table[i].name,
671                                     table[i].handler, table[i].help);
672       if (rc)
673         return rc;
674     }
675   return 0;
676 }
677
678
679
680 \f
681 /* Startup the server.  CTRL must have been allocated by the caller
682    and set to the default values. */
683 int
684 gpg_server (ctrl_t ctrl)
685 {
686   int rc;
687 #ifndef HAVE_W32_SYSTEM
688   int filedes[2];
689 #endif
690   assuan_context_t ctx = NULL;
691   static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
692                                VERSION " ready");
693
694   /* We use a pipe based server so that we can work from scripts.
695      assuan_init_pipe_server will automagically detect when we are
696      called with a socketpair and ignore FILEDES in this case.  */
697 #ifndef HAVE_W32_SYSTEM
698   filedes[0] = assuan_fdopen (0);
699   filedes[1] = assuan_fdopen (1);
700 #endif
701   rc = assuan_new (&ctx);
702   if (rc)
703     {
704       log_error ("failed to allocate the assuan context: %s\n",
705                  gpg_strerror (rc));
706       goto leave;
707     }
708
709 #ifdef HAVE_W32_SYSTEM
710   rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
711 #else
712   rc = assuan_init_pipe_server (ctx, filedes);
713 #endif
714   if (rc)
715     {
716       log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
717       goto leave;
718     }
719
720   rc = register_commands (ctx);
721   if (rc)
722     {
723       log_error ("failed to the register commands with Assuan: %s\n",
724                  gpg_strerror(rc));
725       goto leave;
726     }
727
728   assuan_set_pointer (ctx, ctrl);
729   if (opt.verbose || opt.debug)
730     {
731       char *tmp = NULL;
732
733       tmp = xtryasprintf ("Home: %s\n"
734                           "Config: %s\n"
735                           "%s",
736                           opt.homedir,
737                           "fixme: need config filename",
738                           hello);
739       if (tmp)
740         {
741           assuan_set_hello_line (ctx, tmp);
742           xfree (tmp);
743         }
744     }
745   else
746     assuan_set_hello_line (ctx, hello);
747   assuan_register_reset_notify (ctx, reset_notify);
748   assuan_register_input_notify (ctx, input_notify);
749   assuan_register_output_notify (ctx, output_notify);
750   assuan_register_option_handler (ctx, option_handler);
751
752   ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
753   if (!ctrl->server_local)
754     {
755       rc = gpg_error_from_syserror ();
756       goto leave;
757     }
758   ctrl->server_local->assuan_ctx = ctx;
759   ctrl->server_local->message_fd = GNUPG_INVALID_FD;
760
761   for (;;)
762     {
763       rc = assuan_accept (ctx);
764       if (rc == -1)
765         {
766           rc = 0;
767           break;
768         }
769       else if (rc)
770         {
771           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
772           break;
773         }
774
775       rc = assuan_process (ctx);
776       if (rc)
777         {
778           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
779           continue;
780         }
781     }
782
783  leave:
784   if (ctrl->server_local)
785     {
786       release_pk_list (ctrl->server_local->recplist);
787
788       xfree (ctrl->server_local);
789       ctrl->server_local = NULL;
790     }
791   assuan_release (ctx);
792   return rc;
793 }
794
795
796 /* Helper to notify the client about Pinentry events.  Because that
797    might disturb some older clients, this is only done when enabled
798    via an option.  If it is not enabled we tell Windows to allow
799    setting the foreground window right here.  Returns an gpg error
800    code. */
801 gpg_error_t
802 gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
803 {
804   if (!ctrl || !ctrl->server_local
805       || !ctrl->server_local->allow_pinentry_notify)
806     {
807       gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
808       /* Client might be interested in that event - send as status line.  */
809       if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
810           && (line[17]==' '||!line[17]))
811         {
812           for (line += 17; *line && spacep (line); line++)
813             ;
814           write_status_text (STATUS_PINENTRY_LAUNCHED, line);
815         }
816       return 0;
817     }
818   return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
819 }