Key generation and signing using the OpenPGP card does rudimentary work.
[gnupg.git] / scd / command.c
1 /* command.c - SCdaemon command handler
2  *      Copyright (C) 2001, 2002, 2003 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 2 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <ksba.h>
29
30 #include <assuan.h>
31
32 #include "scdaemon.h"
33 #include "app-common.h"
34
35 /* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */
36 #define MAXLEN_PIN 100
37
38 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
39
40 /* Data used to associate an Assuan context with local server data */
41 struct server_local_s {
42   ASSUAN_CONTEXT assuan_ctx;
43 };
44
45
46 /* Check whether the option NAME appears in LINE */
47 static int
48 has_option (const char *line, const char *name)
49 {
50   const char *s;
51   int n = strlen (name);
52
53   s = strstr (line, name);
54   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
55 }
56
57
58
59 \f
60 /* Note, that this reset_notify is also used for cleanup purposes. */
61 static void
62 reset_notify (ASSUAN_CONTEXT ctx)
63 {
64   CTRL ctrl = assuan_get_pointer (ctx); 
65
66   if (ctrl->card_ctx)
67     {
68       card_close (ctrl->card_ctx);
69       ctrl->card_ctx = NULL;
70       xfree (ctrl->in_data.value);
71       ctrl->in_data.value = NULL;
72     }
73   if (ctrl->app_ctx)
74     {
75       /* FIXME: close the application. */
76       xfree (ctrl->app_ctx);
77       ctrl->app_ctx = NULL;
78     }
79 }
80
81
82 static int
83 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
84 {
85   return 0;
86 }
87
88
89 /* If the card has not yet been opened, do it.  Note that this
90    function returns an Assuan error, so don't map the error a second
91    time */
92 static AssuanError
93 open_card (CTRL ctrl)
94 {
95   if (ctrl->app_ctx)
96     return 0; /* Already initialized for one specific application. */
97   if (ctrl->card_ctx)
98     return 0; /* Already initialized using a card context. */
99
100   ctrl->app_ctx = select_application ();
101   if (!ctrl->app_ctx)
102     { /* No application found - fall back to old mode. */
103       int rc = card_open (&ctrl->card_ctx);
104       if (rc)
105         return map_to_assuan_status (rc);
106     }
107   return 0;
108 }
109
110
111 /* Do the percent and plus/space unescaping in place and return tghe
112    length of the valid buffer. */
113 static size_t
114 percent_plus_unescape (unsigned char *string)
115 {
116   unsigned char *p = string;
117   size_t n = 0;
118
119   while (*string)
120     {
121       if (*string == '%' && string[1] && string[2])
122         { 
123           string++;
124           *p++ = xtoi_2 (string);
125           n++;
126           string+= 2;
127         }
128       else if (*string == '+')
129         {
130           *p++ = ' ';
131           n++;
132           string++;
133         }
134       else
135         {
136           *p++ = *string++;
137           n++;
138         }
139     }
140
141   return n;
142 }
143
144
145
146 /* SERIALNO 
147
148    Return the serial number of the card using a status reponse.  This
149    functon should be used to check for the presence of a card.
150
151    This function is special in that it can be used to reset the card.
152    Most other functions will return an error when a card change has
153    been detected and the use of this function is therefore required.
154
155    Background: We want to keep the client clear of handling card
156    changes between operations; i.e. the client can assume that all
157    operations are done on the same card unless he call this function.
158  */
159 static int
160 cmd_serialno (ASSUAN_CONTEXT ctx, char *line)
161 {
162   CTRL ctrl = assuan_get_pointer (ctx);
163   int rc = 0;
164   char *serial_and_stamp;
165   char *serial;
166   time_t stamp;
167
168   if ((rc = open_card (ctrl)))
169     return rc;
170
171   if (ctrl->app_ctx)
172     rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
173   else
174     rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
175   if (rc)
176     return map_to_assuan_status (rc);
177   rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
178   xfree (serial);
179   if (rc < 0)
180     return ASSUAN_Out_Of_Core;
181   rc = 0;
182   assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
183   free (serial_and_stamp);
184   return 0;
185 }
186
187
188
189
190 /* LEARN [--force]
191
192    Learn all useful information of the currently inserted card.  When
193    used without the force options, the command might do an INQUIRE
194    like this:
195
196       INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp>
197
198    The client should just send an "END" if the processing should go on
199    or a "CANCEL" to force the function to terminate with a Cancel
200    error message.  The response of this command is a list of status
201    lines formatted as this:
202
203      S APPTYPE <apptype>
204
205    This returns the type of the application, currently the strings:
206
207        P15     = PKCS-15 structure used
208        DINSIG  = DIN SIG
209        OPENPGP = OpenPGP card
210  
211    are implemented.  These strings are aliases for the AID
212
213      S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id>
214
215    If there is no certificate yet stored on the card a single "X" is
216    returned as the keygrip.  In addition to the keypair info, information
217    about all certificates stored on the card is also returned:
218
219      S CERTINFO <certtype> <hexstring_with_id>
220
221    Where CERTTYPE is a number indicating the type of certificate:
222       0   := Unknown
223       100 := Regular X.509 cert
224       101 := Trusted X.509 cert
225       102 := Useful X.509 cert
226
227    For certain cards, more information will be returned:
228
229      S KEY-FPR <no> <hexstring>
230
231    For OpenPGP cards this returns the stored fingerprints of the
232    keys. This can be used check whether a key is available on the
233    card.  NO may be 1, 2 or 3.
234
235      S CA-FPR <no> <hexstring>
236
237    Similar to above, these are the fingerprints of keys assumed to be
238    ultimately trusted.
239
240      S DISP-NAME <name_of_card_holder>
241
242    The name of the card holder as stored on the card; percent
243    aescaping takes place, spaces are encoded as '+'
244
245      S PUBKEY-URL <url>
246
247    The URL to be used for locating the entire public key.
248      
249 */
250 static int
251 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
252 {
253   CTRL ctrl = assuan_get_pointer (ctx);
254   int rc = 0;
255   int idx;
256
257   if ((rc = open_card (ctrl)))
258     return rc;
259
260   /* Unless the force option is used we try a shortcut by identifying
261      the card using a serial number and inquiring the client with
262      that. The client may choose to cancel the operation if he already
263      knows about this card */
264   {
265     char *serial_and_stamp;
266     char *serial;
267     time_t stamp;
268
269     if (ctrl->app_ctx)
270       rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp);
271     else
272       rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
273     if (rc)
274       return map_to_assuan_status (rc);
275     rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
276     xfree (serial);
277     if (rc < 0)
278       return ASSUAN_Out_Of_Core;
279     rc = 0;
280     assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
281
282     if (!has_option (line, "--force"))
283       {
284         char *command;
285
286         rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp);
287         if (rc < 0)
288           {
289             free (serial_and_stamp);
290             return ASSUAN_Out_Of_Core;
291           }
292         rc = 0;
293         rc = assuan_inquire (ctx, command, NULL, NULL, 0); 
294         free (command);  /* (must use standard free here) */
295         if (rc)
296           {
297             if (rc != ASSUAN_Canceled)
298               log_error ("inquire KNOWNCARDP failed: %s\n",
299                          assuan_strerror (rc));
300             free (serial_and_stamp);
301             return rc; 
302           }
303         /* not canceled, so we have to proceeed */
304       }
305     free (serial_and_stamp);
306   }
307
308   /* Return information about the certificates. */
309   if (ctrl->app_ctx)
310     rc = -1; /* This information is not yet available for applications. */
311   for (idx=0; !rc; idx++)
312     {
313       char *certid;
314       int certtype;
315
316       rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype);
317       if (!rc)
318         {
319           char *buf;
320
321           buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
322           if (!buf)
323             rc = out_of_core ();
324           else
325             {
326               sprintf (buf, "%d %s", certtype, certid);
327               assuan_write_status (ctx, "CERTINFO", buf);
328               xfree (buf);
329             }
330         }
331       xfree (certid);
332     }
333   if (rc == -1)
334     rc = 0;
335
336
337   /* Return information about the keys. */
338   if (ctrl->app_ctx)
339     rc = -1; /* This information is not yet available for applications. */
340   for (idx=0; !rc; idx++)
341     {
342       unsigned char keygrip[20];
343       char *keyid;
344       int no_cert = 0;
345
346       rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid);
347       if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid)
348         {
349           /* this does happen with an incomplete personalized
350              card; i.e. during the time we have stored the key on the
351              card but not stored the certificate; probably becuase it
352              has not yet been received back from the CA.  Note that we
353              must release KEYID in this case. */
354           rc = 0; 
355           no_cert = 1;
356         }
357       if (!rc)
358         {
359           char *buf, *p;
360
361           buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
362           if (!buf)
363             rc = out_of_core ();
364           else
365             {
366               int i;
367               
368               if (no_cert)
369                 *p++ = 'X';
370               else
371                 {
372                   for (i=0; i < 20; i++, p += 2)
373                     sprintf (p, "%02X", keygrip[i]);
374                 }
375               *p++ = ' ';
376               strcpy (p, keyid);
377               assuan_write_status (ctx, "KEYPAIRINFO", buf);
378               xfree (buf);
379             }
380         }
381       xfree (keyid);
382     }
383   if (rc == -1)
384     rc = 0;
385
386   if (!rc && ctrl->app_ctx)
387     rc = app_write_learn_status (ctrl->app_ctx, ctrl);
388
389
390   return map_to_assuan_status (rc);
391 }
392
393
394 \f
395 /* READCERT <hexified_certid>
396
397  */
398 static int
399 cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
400 {
401   CTRL ctrl = assuan_get_pointer (ctx);
402   int rc;
403   unsigned char *cert;
404   size_t ncert;
405
406   if ((rc = open_card (ctrl)))
407     return rc;
408
409   if (ctrl->app_ctx)
410     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
411
412   rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
413   if (rc)
414     {
415       log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
416     }
417   if (!rc)
418     {
419       rc = assuan_send_data (ctx, cert, ncert);
420       xfree (cert);
421       if (rc)
422         return rc;
423     }
424
425   return map_to_assuan_status (rc);
426 }
427
428
429 /* READKEY <hexified_certid>
430
431    Return the public key for the given cert or key ID as an standard
432    S-Expression.  */
433 static int
434 cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
435 {
436   CTRL ctrl = assuan_get_pointer (ctx);
437   int rc;
438   unsigned char *cert = NULL;
439   size_t ncert, n;
440   KsbaCert kc = NULL;
441   KsbaSexp p;
442
443   if ((rc = open_card (ctrl)))
444     return rc;
445
446   if (ctrl->app_ctx)
447     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
448
449   rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
450   if (rc)
451     {
452       log_error ("card_read_cert failed: %s\n", gpg_strerror (rc));
453       goto leave;
454     }
455       
456   kc = ksba_cert_new ();
457   if (!kc)
458     {
459       rc = out_of_core ();
460       xfree (cert);
461       goto leave;
462     }
463   rc = ksba_cert_init_from_mem (kc, cert, ncert);
464   if (rc)
465     {
466       log_error ("failed to parse the certificate: %s\n", ksba_strerror (rc));
467       rc = map_ksba_err (rc);
468       goto leave;
469     }
470
471   p = ksba_cert_get_public_key (kc);
472   if (!p)
473     {
474       rc = gpg_error (GPG_ERR_NO_PUBKEY);
475       goto leave;
476     }
477
478   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
479   rc = assuan_send_data (ctx, p, n);
480   rc = map_assuan_err (rc);
481   xfree (p);
482
483
484  leave:
485   ksba_cert_release (kc);
486   xfree (cert);
487   return map_to_assuan_status (rc);
488 }
489
490
491 \f
492
493 /* SETDATA <hexstring> 
494
495    The client should use this command to tell us the data he want to
496    sign.  */
497 static int
498 cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
499 {
500   CTRL ctrl = assuan_get_pointer (ctx);
501   int n;
502   char *p;
503   unsigned char *buf;
504
505   /* parse the hexstring */
506   for (p=line,n=0; hexdigitp (p); p++, n++)
507     ;
508   if (*p)
509     return set_error (Parameter_Error, "invalid hexstring");
510   if ((n&1))
511     return set_error (Parameter_Error, "odd number of digits");
512   n /= 2;
513   buf = xtrymalloc (n);
514   if (!buf)
515     return ASSUAN_Out_Of_Core;
516
517   ctrl->in_data.value = buf;
518   ctrl->in_data.valuelen = n;
519   for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
520     buf[n] = xtoi_2 (p);
521   return 0;
522 }
523
524
525
526 static int 
527 pin_cb (void *opaque, const char *info, char **retstr)
528 {
529   ASSUAN_CONTEXT ctx = opaque;
530   char *command;
531   int rc;
532   char *value;
533   size_t valuelen;
534
535   *retstr = NULL;
536   log_debug ("asking for PIN '%s'\n", info);
537
538   rc = asprintf (&command, "NEEDPIN %s", info);
539   if (rc < 0)
540     return out_of_core ();
541
542   /* FIXME: Write an inquire function which returns the result in
543      secure memory */
544   rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); 
545   free (command);  
546   if (rc)
547     return map_assuan_err (rc);
548
549   if (!valuelen || value[valuelen-1])
550     {
551       /* We require that the returned value is an UTF-8 string */
552       xfree (value);
553       return gpg_error (GPG_ERR_INV_RESPONSE);
554     }
555   *retstr = value;
556   return 0;
557 }
558
559
560 /* PKSIGN <hexified_id>
561
562  */
563 static int
564 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
565 {
566   CTRL ctrl = assuan_get_pointer (ctx);
567   int rc;
568   void *outdata;
569   size_t outdatalen;
570   char *keyidstr;
571
572   if ((rc = open_card (ctrl)))
573     return rc;
574
575   /* We have to use a copy of the key ID because the function may use
576      the pin_cb which in turn uses the assuan line buffer and thus
577      overwriting the original line with the keyid */
578   keyidstr = strdup (line);
579   if (!keyidstr)
580     return ASSUAN_Out_Of_Core;
581   
582   if (ctrl->app_ctx)
583     rc = app_sign (ctrl->app_ctx,
584                     keyidstr, GCRY_MD_SHA1,
585                     pin_cb, ctx,
586                     ctrl->in_data.value, ctrl->in_data.valuelen,
587                     &outdata, &outdatalen);
588   else  
589     rc = card_sign (ctrl->card_ctx,
590                     keyidstr, GCRY_MD_SHA1,
591                     pin_cb, ctx,
592                     ctrl->in_data.value, ctrl->in_data.valuelen,
593                     &outdata, &outdatalen);
594   free (keyidstr);
595   if (rc)
596     {
597       log_error ("card_sign failed: %s\n", gpg_strerror (rc));
598     }
599   else
600     {
601       rc = assuan_send_data (ctx, outdata, outdatalen);
602       xfree (outdata);
603       if (rc)
604         return rc; /* that is already an assuan error code */
605     }
606
607   return map_to_assuan_status (rc);
608 }
609
610 /* PKDECRYPT <hexified_id>
611
612  */
613 static int
614 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
615 {
616   CTRL ctrl = assuan_get_pointer (ctx);
617   int rc;
618   void *outdata;
619   size_t outdatalen;
620   char *keyidstr;
621
622   if ((rc = open_card (ctrl)))
623     return rc;
624
625   keyidstr = strdup (line);
626   if (!keyidstr)
627     return ASSUAN_Out_Of_Core;
628   if (ctrl->app_ctx)
629     rc = app_decipher (ctrl->app_ctx,
630                         keyidstr, 
631                         pin_cb, ctx,
632                         ctrl->in_data.value, ctrl->in_data.valuelen,
633                         &outdata, &outdatalen);
634   else
635     rc = card_decipher (ctrl->card_ctx,
636                         keyidstr, 
637                         pin_cb, ctx,
638                         ctrl->in_data.value, ctrl->in_data.valuelen,
639                         &outdata, &outdatalen);
640   free (keyidstr);
641   if (rc)
642     {
643       log_error ("card_create_signature failed: %s\n", gpg_strerror (rc));
644     }
645   else
646     {
647       rc = assuan_send_data (ctx, outdata, outdatalen);
648       xfree (outdata);
649       if (rc)
650         return rc; /* that is already an assuan error code */
651     }
652
653   return map_to_assuan_status (rc);
654 }
655
656
657 /* SETATTR <name> <value> 
658
659    This command is used to store data on a a smartcard.  The allowed
660    names and values are depend on the currently selected smartcard
661    application.  NAME and VALUE must be percent and '+' escaped.
662
663    However, the curent implementation assumes that Name is not escaped;
664    this works as long as noone uses arbitrary escaping. 
665  
666    A PIN will be requested for most NAMEs.  See the corresponding
667    setattr function of the actually used application (app-*.c) for
668    details.  */
669 static int
670 cmd_setattr (ASSUAN_CONTEXT ctx, char *line)
671 {
672   CTRL ctrl = assuan_get_pointer (ctx);
673   int rc;
674   char *keyword;
675   int keywordlen;
676   size_t nbytes;
677
678   if ((rc = open_card (ctrl)))
679     return rc;
680
681   keyword = line;
682   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
683     ;
684   if (*line)
685       *line++ = 0;
686   while (spacep (line))
687     line++;
688   nbytes = percent_plus_unescape (line);
689
690   rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes);
691
692   return map_to_assuan_status (rc);
693 }
694
695 /* GENKEY [--force] <no>
696
697    Generate a key on-card identified by NO, which is application
698    specific.  Return values are application specific.  For OpenPGP
699    cards 2 status lines are returned:
700
701      S KEY-FPR  <hexstring>
702      S KEY-CREATED-AT <seconds_since_epoch>
703      S KEY-DATA [p|n] <hexdata>
704      
705
706    --force is required to overwriet an already existing key.  The
707    KEY-CREATED-AT is required for further processing because it is
708    part of the hashed key material for the fingerprint.
709
710    The public part of the key can also later be retrieved using the
711    READKEY command.
712
713  */
714 static int
715 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
716 {
717   CTRL ctrl = assuan_get_pointer (ctx);
718   int rc;
719   char *keyno;
720   int force = has_option (line, "--force");
721
722   /* Skip over options. */
723   while ( *line == '-' && line[1] == '-' )
724     {
725       while (!spacep (line))
726         line++;
727       while (spacep (line))
728         line++;
729     }
730   if (!*line)
731     return set_error (Parameter_Error, "no key number given");
732   keyno = line;
733   while (!spacep (line))
734     line++;
735   *line = 0;
736
737   if ((rc = open_card (ctrl)))
738     return rc;
739
740   if (!ctrl->app_ctx)
741     return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
742
743   rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx);
744
745   return map_to_assuan_status (rc);
746 }
747
748
749
750
751 \f
752 /* Tell the assuan library about our commands */
753 static int
754 register_commands (ASSUAN_CONTEXT ctx)
755 {
756   static struct {
757     const char *name;
758     int (*handler)(ASSUAN_CONTEXT, char *line);
759   } table[] = {
760     { "SERIALNO",     cmd_serialno },
761     { "LEARN",        cmd_learn },
762     { "READCERT",     cmd_readcert },
763     { "READKEY",      cmd_readkey },
764     { "SETDATA",      cmd_setdata },
765     { "PKSIGN",       cmd_pksign },
766     { "PKDECRYPT",    cmd_pkdecrypt },
767     { "INPUT",        NULL }, 
768     { "OUTPUT",       NULL }, 
769     { "SETATTR",      cmd_setattr },
770     { "GENKEY",       cmd_genkey },
771     { NULL }
772   };
773   int i, rc;
774
775   for (i=0; table[i].name; i++)
776     {
777       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
778       if (rc)
779         return rc;
780     } 
781   assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready");
782
783   assuan_register_reset_notify (ctx, reset_notify);
784   assuan_register_option_handler (ctx, option_handler);
785   return 0;
786 }
787
788
789 /* Startup the server.  If LISTEN_FD is given as -1, this is simple
790    piper server, otherwise it is a regular server */
791 void
792 scd_command_handler (int listen_fd)
793 {
794   int rc;
795   ASSUAN_CONTEXT ctx;
796   struct server_control_s ctrl;
797
798   memset (&ctrl, 0, sizeof ctrl);
799   scd_init_default_ctrl (&ctrl);
800   
801   if (listen_fd == -1)
802     {
803       int filedes[2];
804
805       filedes[0] = 0;
806       filedes[1] = 1;
807       rc = assuan_init_pipe_server (&ctx, filedes);
808     }
809   else
810     {
811       rc = assuan_init_socket_server (&ctx, listen_fd);
812     }
813   if (rc)
814     {
815       log_error ("failed to initialize the server: %s\n",
816                  assuan_strerror(rc));
817       scd_exit (2);
818     }
819   rc = register_commands (ctx);
820   if (rc)
821     {
822       log_error ("failed to register commands with Assuan: %s\n",
823                  assuan_strerror(rc));
824       scd_exit (2);
825     }
826   assuan_set_pointer (ctx, &ctrl);
827   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
828   ctrl.server_local->assuan_ctx = ctx;
829
830   if (DBG_ASSUAN)
831     assuan_set_log_stream (ctx, log_get_stream ());
832
833   for (;;)
834     {
835       rc = assuan_accept (ctx);
836       if (rc == -1)
837         {
838           break;
839         }
840       else if (rc)
841         {
842           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
843           break;
844         }
845       
846       rc = assuan_process (ctx);
847       if (rc)
848         {
849           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
850           continue;
851         }
852     }
853   reset_notify (ctx); /* used for cleanup */
854
855   assuan_deinit_server (ctx);
856 }
857
858
859 /* Send a line with status information via assuan and escape all given
860    buffers. The variable elements are pairs of (char *, size_t),
861    terminated with a (NULL, 0). */
862 void
863 send_status_info (CTRL ctrl, const char *keyword, ...)
864 {
865   va_list arg_ptr;
866   const unsigned char *value;
867   size_t valuelen;
868   char buf[950], *p;
869   size_t n;
870   ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx;
871   
872   va_start (arg_ptr, keyword);
873
874   p = buf; 
875   n = 0;
876   while ( (value = va_arg (arg_ptr, const unsigned char *)) )
877     {
878       valuelen = va_arg (arg_ptr, size_t);
879       if (!valuelen)
880         continue; /* empty buffer */
881       if (n)
882         {
883           *p++ = ' ';
884           n++;
885         }
886       for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++)
887         {
888           if (*value < ' ' || *value == '+')
889             {
890               sprintf (p, "%%%02X", *value);
891               p += 3;
892             }
893           else if (*value == ' ')
894             *p++ = '+';
895           else
896             *p++ = *value;
897         }
898     }
899   *p = 0;
900   assuan_write_status (ctx, keyword, buf);
901
902   va_end (arg_ptr);
903 }
904