A bunch of minor changes for Windows.
[gnupg.git] / agent / command.c
1 /* command.c - gpg-agent command handler
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2006  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 /* FIXME: we should not use the default assuan buffering but setup
24    some buffering in secure mempory to protect session keys etc. */
25
26 #include <config.h>
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <unistd.h>
34 #include <assert.h>
35
36 #include <assuan.h>
37
38 #include "agent.h"
39
40 /* maximum allowed size of the inquired ciphertext */
41 #define MAXLEN_CIPHERTEXT 4096
42 /* maximum allowed size of the key parameters */
43 #define MAXLEN_KEYPARAM 1024
44
45 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
46
47
48 #if MAX_DIGEST_LEN < 20
49 #error MAX_DIGEST_LEN shorter than keygrip
50 #endif
51
52 /* Data used to associate an Assuan context with local server data */
53 struct server_local_s
54 {
55   assuan_context_t assuan_ctx;
56   int message_fd;
57   int use_cache_for_signing;
58   char *keydesc;  /* Allocated description for the next key
59                      operation. */
60   int pause_io_logging; /* Used to suppress I/O logging during a command */
61 #ifdef HAVE_W32_SYSTEM
62   int stopme;    /* If set to true the agent will be terminated after
63                     the end of this session.  */
64 #endif
65 };
66
67
68 /* An entry for the getval/putval commands. */
69 struct putval_item_s
70 {
71   struct putval_item_s *next;
72   size_t off;  /* Offset to the value into DATA.  */
73   size_t len;  /* Length of the value.  */
74   char d[1];   /* Key | Nul | value.  */ 
75 };
76
77
78 /* A list of key value pairs fpr the getval/putval commands.  */
79 static struct putval_item_s *putval_list;
80
81
82 \f
83 /* To help polling clients, we keep tarck of the number of certain
84    events.  This structure keeps those counters.  The counters are
85    integers and there should be no problem if they are overflowing as
86    callers need to check only whether a counter changed.  The actual
87    values are not meaningful. */
88 struct 
89 {
90   /* Incremented if any of the other counters below changed. */
91   unsigned int any;
92
93   /* Incremented if a key is added or removed from the internal privat
94      key database. */
95   unsigned int key; 
96
97   /* Incremented if a change of the card readers stati has been
98      detected. */
99   unsigned int card;
100
101 } eventcounter;
102
103
104
105
106 \f
107 /* Release the memory buffer MB but first wipe out the used memory. */
108 static void
109 clear_outbuf (membuf_t *mb)
110 {
111   void *p;
112   size_t n;
113
114   p = get_membuf (mb, &n);
115   if (p)
116     {
117       memset (p, 0, n);
118       xfree (p);
119     }
120 }
121
122
123 /* Write the content of memory buffer MB as assuan data to CTX and
124    wipe the buffer out afterwards. */
125 static gpg_error_t
126 write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
127 {
128   assuan_error_t ae;
129   void *p;
130   size_t n;
131
132   p = get_membuf (mb, &n);
133   if (!p)
134     return out_of_core ();
135   ae = assuan_send_data (ctx, p, n);
136   memset (p, 0, n);
137   xfree (p);
138   return ae;
139 }
140
141
142 static void
143 reset_notify (assuan_context_t ctx)
144 {
145   ctrl_t ctrl = assuan_get_pointer (ctx);
146
147   memset (ctrl->keygrip, 0, 20);
148   ctrl->have_keygrip = 0;
149   ctrl->digest.valuelen = 0;
150
151   xfree (ctrl->server_local->keydesc);
152   ctrl->server_local->keydesc = NULL;
153 }
154
155
156 /* Check whether the option NAME appears in LINE */
157 static int
158 has_option (const char *line, const char *name)
159 {
160   const char *s;
161   int n = strlen (name);
162
163   s = strstr (line, name);
164   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
165 }
166
167 /* Same as has_option but does only test for the name of the option
168    and ignores an argument, i.e. with NAME being "--hash" it would
169    return true for "--hash" as well as for "--hash=foo". */
170 static int
171 has_option_name (const char *line, const char *name)
172 {
173   const char *s;
174   int n = strlen (name);
175
176   s = strstr (line, name);
177   return (s && (s == line || spacep (s-1))
178           && (!s[n] || spacep (s+n) || s[n] == '='));
179 }
180
181
182 /* Skip over options.  It is assumed that leading spaces have been
183    removed (this is the case for lines passed to a handler from
184    assuan).  Blanks after the options are also removed. */
185 static char *
186 skip_options (char *line)
187 {
188   while ( *line == '-' && line[1] == '-' )
189     {
190       while (*line && !spacep (line))
191         line++;
192       while (spacep (line))
193         line++;
194     }
195   return line;
196 }
197
198
199 /* Replace all '+' by a blank. */
200 static void
201 plus_to_blank (char *s)
202 {
203   for (; *s; s++)
204     {
205       if (*s == '+')
206         *s = ' ';
207     }
208 }
209
210
211 /* Do the percent and plus/space unescaping in place and return the
212    length of the valid buffer. */
213 static size_t
214 percent_plus_unescape (char *string)
215 {
216   unsigned char *p = (unsigned char *)string;
217   size_t n = 0;
218
219   while (*string)
220     {
221       if (*string == '%' && string[1] && string[2])
222         { 
223           string++;
224           *p++ = xtoi_2 (string);
225           n++;
226           string+= 2;
227         }
228       else if (*string == '+')
229         {
230           *p++ = ' ';
231           n++;
232           string++;
233         }
234       else
235         {
236           *p++ = *string++;
237           n++;
238         }
239     }
240
241   return n;
242 }
243
244
245
246
247 /* Parse a hex string.  Return an Assuan error code or 0 on success and the
248    length of the parsed string in LEN. */
249 static int
250 parse_hexstring (assuan_context_t ctx, const char *string, size_t *len)
251 {
252   const char *p;
253   size_t n;
254
255   /* parse the hash value */
256   for (p=string, n=0; hexdigitp (p); p++, n++)
257     ;
258   if (*p != ' ' && *p != '\t' && *p)
259     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
260   if ((n&1))
261     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
262   *len = n;
263   return 0;
264 }
265
266 /* Parse the keygrip in STRING into the provided buffer BUF.  BUF must
267    provide space for 20 bytes. BUF is not changed if the function
268    returns an error. */
269 static int
270 parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
271 {
272   int rc;
273   size_t n;
274   const unsigned char *p;
275
276   rc = parse_hexstring (ctx, string, &n);
277   if (rc)
278     return rc;
279   n /= 2;
280   if (n != 20)
281     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of keygrip");
282
283   for (p=(const unsigned char*)string, n=0; n < 20; p += 2, n++)
284     buf[n] = xtoi_2 (p);
285
286   return 0;
287 }
288
289
290 /* Write an assuan status line. */
291 gpg_error_t
292 agent_write_status (ctrl_t ctrl, const char *keyword, ...)
293 {
294   gpg_error_t err = 0;
295   va_list arg_ptr;
296   const char *text;
297   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
298   char buf[950], *p;
299   size_t n;
300
301   va_start (arg_ptr, keyword);
302
303   p = buf; 
304   n = 0;
305   while ( (text = va_arg (arg_ptr, const char *)) )
306     {
307       if (n)
308         {
309           *p++ = ' ';
310           n++;
311         }
312       for ( ; *text && n < DIM (buf)-2; n++)
313         *p++ = *text++;
314     }
315   *p = 0;
316   err = assuan_write_status (ctx, keyword, buf);
317
318   va_end (arg_ptr);
319   return err;
320 }
321
322
323 \f
324 /* GETEVENTCOUNTER
325
326    Return a a status line named EVENTCOUNTER with the current values
327    of all event counters.  The values are decimal numbers in the range
328    0 to UINT_MAX and wrapping around to 0.  The actual values should
329    not be relied upon, they shall only be used to detect a change.
330
331    The currently defined counters are:
332
333    ANY  - Incremented with any change of any of the other counters.
334    KEY  - Incremented for added or removed private keys.
335    CARD - Incremented for changes of the card readers stati.
336 */
337 static int
338 cmd_geteventcounter (assuan_context_t ctx, char *line)
339 {
340   ctrl_t ctrl = assuan_get_pointer (ctx);
341   char any_counter[25];
342   char key_counter[25];
343   char card_counter[25];
344
345   snprintf (any_counter, sizeof any_counter, "%u", eventcounter.any);
346   snprintf (key_counter, sizeof key_counter, "%u", eventcounter.key);
347   snprintf (card_counter, sizeof card_counter, "%u", eventcounter.card);
348
349   return agent_write_status (ctrl, "EVENTCOUNTER",
350                              any_counter,
351                              key_counter,
352                              card_counter,
353                              NULL);
354 }
355
356
357 /* This function should be called once for all key removals or
358    additions.  Thus function is assured not to do any context
359    switches. */
360 void
361 bump_key_eventcounter (void)
362 {
363   eventcounter.key++;
364   eventcounter.any++;
365 }
366
367 /* This function should be called for all card reader status
368    changes. Thus function is assured not to do any context
369    switches. */
370 void
371 bump_card_eventcounter (void)
372 {
373   eventcounter.card++;
374   eventcounter.any++;
375 }
376
377
378
379 \f
380 /* ISTRUSTED <hexstring_with_fingerprint>
381
382    Return OK when we have an entry with this fingerprint in our
383    trustlist */
384 static int
385 cmd_istrusted (assuan_context_t ctx, char *line)
386 {
387   ctrl_t ctrl = assuan_get_pointer (ctx);
388   int rc, n, i;
389   char *p;
390   char fpr[41];
391
392   /* Parse the fingerprint value. */
393   for (p=line,n=0; hexdigitp (p); p++, n++)
394     ;
395   if (*p || !(n == 40 || n == 32))
396     return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
397   i = 0;
398   if (n==32)
399     {
400       strcpy (fpr, "00000000");
401       i += 8;
402     }
403   for (p=line; i < 40; p++, i++)
404     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
405   fpr[i] = 0;
406   rc = agent_istrusted (ctrl, fpr);
407   if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
408     return rc;
409   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
410     return gpg_error (GPG_ERR_NOT_TRUSTED);
411   else
412     {
413       log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
414       return rc;
415     }
416 }
417
418 /* LISTTRUSTED 
419
420    List all entries from the trustlist */
421 static int
422 cmd_listtrusted (assuan_context_t ctx, char *line)
423 {
424   int rc = agent_listtrusted (ctx);
425   if (rc)
426     log_error ("command listtrusted failed: %s\n", gpg_strerror (rc));
427   return rc;
428 }
429
430
431 /* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
432
433    Store a new key in into the trustlist*/
434 static int
435 cmd_marktrusted (assuan_context_t ctx, char *line)
436 {
437   ctrl_t ctrl = assuan_get_pointer (ctx);
438   int rc, n, i;
439   char *p;
440   char fpr[41];
441   int flag;
442
443   /* parse the fingerprint value */
444   for (p=line,n=0; hexdigitp (p); p++, n++)
445     ;
446   if (!spacep (p) || !(n == 40 || n == 32))
447     return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
448   i = 0;
449   if (n==32)
450     {
451       strcpy (fpr, "00000000");
452       i += 8;
453     }
454   for (p=line; i < 40; p++, i++)
455     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
456   fpr[i] = 0;
457   
458   while (spacep (p))
459     p++;
460   flag = *p++;
461   if ( (flag != 'S' && flag != 'P') || !spacep (p) )
462     return set_error (GPG_ERR_ASS_PARAMETER, "invalid flag - must be P or S");
463   while (spacep (p))
464     p++;
465
466   rc = agent_marktrusted (ctrl, p, fpr, flag);
467   if (rc)
468     log_error ("command marktrusted failed: %s\n", gpg_strerror (rc));
469   return rc;
470 }
471
472
473
474 \f
475 /* HAVEKEY <hexstring_with_keygrip>
476   
477    Return success when the secret key is available */
478 static int
479 cmd_havekey (assuan_context_t ctx, char *line)
480 {
481   int rc;
482   unsigned char buf[20];
483
484   rc = parse_keygrip (ctx, line, buf);
485   if (rc)
486     return rc;
487
488   if (agent_key_available (buf))
489     return gpg_error (GPG_ERR_NO_SECKEY);
490
491   return 0;
492 }
493
494
495 /* SIGKEY <hexstring_with_keygrip>
496    SETKEY <hexstring_with_keygrip>
497   
498    Set the  key used for a sign or decrypt operation */
499 static int
500 cmd_sigkey (assuan_context_t ctx, char *line)
501 {
502   int rc;
503   ctrl_t ctrl = assuan_get_pointer (ctx);
504
505   rc = parse_keygrip (ctx, line, ctrl->keygrip);
506   if (rc)
507     return rc;
508   ctrl->have_keygrip = 1;
509   return 0;
510 }
511
512
513 /* SETKEYDESC plus_percent_escaped_string
514
515    Set a description to be used for the next PKSIGN or PKDECRYPT
516    operation if this operation requires the entry of a passphrase.  If
517    this command is not used a default text will be used.  Note, that
518    this description implictly selects the label used for the entry
519    box; if the string contains the string PIN (which in general will
520    not be translated), "PIN" is used, otherwise the translation of
521    "passphrase" is used.  The description string should not contain
522    blanks unless they are percent or '+' escaped.
523
524    The description is only valid for the next PKSIGN or PKDECRYPT
525    operation.
526 */
527 static int
528 cmd_setkeydesc (assuan_context_t ctx, char *line)
529 {
530   ctrl_t ctrl = assuan_get_pointer (ctx);
531   char *desc, *p;
532
533   for (p=line; *p == ' '; p++)
534     ;
535   desc = p;
536   p = strchr (desc, ' ');
537   if (p)
538     *p = 0; /* We ignore any garbage; we might late use it for other args. */
539
540   if (!desc || !*desc)
541     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
542
543   /* Note, that we only need to replace the + characters and should
544      leave the other escaping in place because the escaped string is
545      send verbatim to the pinentry which does the unescaping (but not
546      the + replacing) */
547   plus_to_blank (desc);
548
549   xfree (ctrl->server_local->keydesc);
550   ctrl->server_local->keydesc = xtrystrdup (desc);
551   if (!ctrl->server_local->keydesc)
552     return out_of_core ();
553   return 0;
554 }
555
556
557 /* SETHASH --hash=<name>|<algonumber> <hexstring> 
558
559   The client can use this command to tell the server about the data
560   (which usually is a hash) to be signed. */
561 static int
562 cmd_sethash (assuan_context_t ctx, char *line)
563 {
564   int rc;
565   size_t n;
566   char *p;
567   ctrl_t ctrl = assuan_get_pointer (ctx);
568   unsigned char *buf;
569   char *endp;
570   int algo;
571
572   /* Parse the alternative hash options which may be used instead of
573      the algo number.  */
574   if (has_option_name (line, "--hash"))
575     {
576       if (has_option (line, "--hash=sha1"))
577         algo = GCRY_MD_SHA1;
578       else if (has_option (line, "--hash=sha256"))
579         algo = GCRY_MD_SHA256;
580       else if (has_option (line, "--hash=rmd160"))
581         algo = GCRY_MD_RMD160;
582       else if (has_option (line, "--hash=md5"))
583         algo = GCRY_MD_MD5;
584       else if (has_option (line, "--hash=tls-md5sha1"))
585         algo = GCRY_MD_USER_TLS_MD5SHA1;
586       else
587         return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
588     }
589   else
590     algo = 0;
591
592   line = skip_options (line);
593   
594   if (!algo)
595     {
596       /* No hash option has been given: require an algo number instead  */
597       algo = (int)strtoul (line, &endp, 10);
598       for (line = endp; *line == ' ' || *line == '\t'; line++)
599         ;
600       if (!algo || gcry_md_test_algo (algo))
601         return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
602     }
603   ctrl->digest.algo = algo;
604
605   /* Parse the hash value. */
606   rc = parse_hexstring (ctx, line, &n);
607   if (rc)
608     return rc;
609   n /= 2;
610   if (algo == GCRY_MD_USER_TLS_MD5SHA1 && n == 36)
611     ;
612   else if (n != 16 && n != 20 && n != 24 && n != 32)
613     return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
614
615   if (n > MAX_DIGEST_LEN)
616     return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
617
618   buf = ctrl->digest.value;
619   ctrl->digest.valuelen = n;
620   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
621     buf[n] = xtoi_2 (p);
622   for (; n < ctrl->digest.valuelen; n++)
623     buf[n] = 0;
624   return 0;
625 }
626
627
628 /* PKSIGN <options>
629
630    Perform the actual sign operation. Neither input nor output are
631    sensitive to eavesdropping. */
632 static int
633 cmd_pksign (assuan_context_t ctx, char *line)
634 {
635   int rc;
636   cache_mode_t cache_mode = CACHE_MODE_NORMAL;
637   ctrl_t ctrl = assuan_get_pointer (ctx);
638   membuf_t outbuf;
639   
640   if (opt.ignore_cache_for_signing)
641     cache_mode = CACHE_MODE_IGNORE;
642   else if (!ctrl->server_local->use_cache_for_signing)
643     cache_mode = CACHE_MODE_IGNORE;
644
645   init_membuf (&outbuf, 512);
646
647   rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
648                      &outbuf, cache_mode);
649   if (rc)
650     clear_outbuf (&outbuf);
651   else
652     rc = write_and_clear_outbuf (ctx, &outbuf);
653   if (rc)
654     log_error ("command pksign failed: %s\n", gpg_strerror (rc));
655   xfree (ctrl->server_local->keydesc);
656   ctrl->server_local->keydesc = NULL;
657   return rc;
658 }
659
660 /* PKDECRYPT <options>
661
662    Perform the actual decrypt operation.  Input is not 
663    sensitive to eavesdropping */
664 static int
665 cmd_pkdecrypt (assuan_context_t ctx, char *line)
666 {
667   int rc;
668   ctrl_t ctrl = assuan_get_pointer (ctx);
669   unsigned char *value;
670   size_t valuelen;
671   membuf_t outbuf;
672
673   /* First inquire the data to decrypt */
674   rc = assuan_inquire (ctx, "CIPHERTEXT",
675                        &value, &valuelen, MAXLEN_CIPHERTEXT);
676   if (rc)
677     return rc;
678
679   init_membuf (&outbuf, 512);
680
681   rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
682                         value, valuelen, &outbuf);
683   xfree (value);
684   if (rc)
685     clear_outbuf (&outbuf);
686   else
687     rc = write_and_clear_outbuf (ctx, &outbuf);
688   if (rc)
689     log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
690   xfree (ctrl->server_local->keydesc);
691   ctrl->server_local->keydesc = NULL;
692   return rc;
693 }
694
695
696 /* GENKEY
697
698    Generate a new key, store the secret part and return the public
699    part.  Here is an example transaction:
700
701    C: GENKEY
702    S: INQUIRE KEYPARM
703    C: D (genkey (rsa (nbits  1024)))
704    C: END
705    S: D (public-key
706    S: D   (rsa (n 326487324683264) (e 10001)))
707    S  OK key created
708 */
709
710 static int
711 cmd_genkey (assuan_context_t ctx, char *line)
712 {
713   ctrl_t ctrl = assuan_get_pointer (ctx);
714   int rc;
715   unsigned char *value;
716   size_t valuelen;
717   membuf_t outbuf;
718
719   /* First inquire the parameters */
720   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
721   if (rc)
722     return rc;
723
724   init_membuf (&outbuf, 512);
725
726   rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
727   xfree (value);
728   if (rc)
729     clear_outbuf (&outbuf);
730   else
731     rc = write_and_clear_outbuf (ctx, &outbuf);
732   if (rc)
733     log_error ("command genkey failed: %s\n", gpg_strerror (rc));
734   return rc;
735 }
736
737
738
739 \f
740 /* READKEY <hexstring_with_keygrip>
741   
742    Return the public key for the given keygrip.  */
743 static int
744 cmd_readkey (assuan_context_t ctx, char *line)
745 {
746   ctrl_t ctrl = assuan_get_pointer (ctx);
747   int rc;
748   unsigned char grip[20];
749   gcry_sexp_t s_pkey = NULL;
750
751   rc = parse_keygrip (ctx, line, grip);
752   if (rc)
753     return rc; /* Return immediately as this is already an Assuan error code.*/
754
755   rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
756   if (!rc)
757     {
758       size_t len;
759       unsigned char *buf;
760
761       len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
762       assert (len);
763       buf = xtrymalloc (len);
764       if (!buf)
765         rc = gpg_error_from_syserror ();
766       else
767         {
768           len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
769           assert (len);
770           rc = assuan_send_data (ctx, buf, len);
771           xfree (buf);
772         }
773       gcry_sexp_release (s_pkey);
774     }
775
776   if (rc)
777     log_error ("command readkey failed: %s\n", gpg_strerror (rc));
778   return rc;
779 }
780
781
782
783
784
785 \f
786 static int
787 send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
788 {
789   size_t n;
790   int rc;
791
792   assuan_begin_confidential (ctx);
793   n = strlen (pw);
794   if (via_data)
795     rc = assuan_send_data (ctx, pw, n);
796   else
797     {
798       char *p = xtrymalloc_secure (n*2+1);
799       if (!p)
800         rc = gpg_error_from_syserror ();
801       else
802         {
803           bin2hex (pw, n, p);
804           rc = assuan_set_okay_line (ctx, p);
805           xfree (p);
806         }
807     }
808   return rc;
809 }
810
811
812 /* GET_PASSPHRASE [--data] [--check] <cache_id>
813                   [<error_message> <prompt> <description>]
814
815    This function is usually used to ask for a passphrase to be used
816    for conventional encryption, but may also be used by programs which
817    need specal handling of passphrases.  This command uses a syntax
818    which helps clients to use the agent with minimum effort.  The
819    agent either returns with an error or with a OK followed by the hex
820    encoded passphrase.  Note that the length of the strings is
821    implicitly limited by the maximum length of a command.
822
823    If the option "--data" is used the passphrase is returned by usual
824    data lines and not on the okay line.
825
826    If the option "--check" is used the passphrase constraints checks as
827    implemented by gpg-agent are applied.  A check is not done if the
828    passphrase has been found in the cache.
829 */
830
831 static int
832 cmd_get_passphrase (assuan_context_t ctx, char *line)
833 {
834   ctrl_t ctrl = assuan_get_pointer (ctx);
835   int rc;
836   const char *pw;
837   char *response;
838   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
839   char *p;
840   void *cache_marker;
841   int opt_data, opt_check;
842
843   opt_data = has_option (line, "--data");
844   opt_check = has_option (line, "--check");
845   line = skip_options (line);
846
847   cacheid = line;
848   p = strchr (cacheid, ' ');
849   if (p)
850     {
851       *p++ = 0;
852       while (*p == ' ')
853         p++;
854       errtext = p;
855       p = strchr (errtext, ' ');
856       if (p)
857         {
858           *p++ = 0;
859           while (*p == ' ')
860             p++;
861           prompt = p;
862           p = strchr (prompt, ' ');
863           if (p)
864             {
865               *p++ = 0;
866               while (*p == ' ')
867                 p++;
868               desc = p;
869               p = strchr (desc, ' ');
870               if (p)
871                 *p = 0; /* Ignore trailing garbage. */
872             }
873         }
874     }
875   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
876     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
877   if (!desc)
878     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
879
880   if (!strcmp (cacheid, "X"))
881     cacheid = NULL;
882   if (!strcmp (errtext, "X"))
883     errtext = NULL;
884   if (!strcmp (prompt, "X"))
885     prompt = NULL;
886   if (!strcmp (desc, "X"))
887     desc = NULL;
888
889   pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
890                : NULL;
891   if (pw)
892     {
893       rc = send_back_passphrase (ctx, opt_data, pw);
894       agent_unlock_cache_entry (&cache_marker);
895     }
896   else
897     {
898       /* Note, that we only need to replace the + characters and
899          should leave the other escaping in place because the escaped
900          string is send verbatim to the pinentry which does the
901          unescaping (but not the + replacing) */
902       if (errtext)
903         plus_to_blank (errtext);
904       if (prompt)
905         plus_to_blank (prompt);
906       if (desc)
907         plus_to_blank (desc);
908
909       response = NULL;
910       do
911         {
912           xfree (response);
913           rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
914         }
915       while (!rc
916              && opt_check
917              && check_passphrase_constraints (ctrl, response));
918
919       if (!rc)
920         {
921           if (cacheid)
922             agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
923           rc = send_back_passphrase (ctx, opt_data, response);
924           xfree (response);
925         }
926     }
927
928   if (rc)
929     log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
930   return rc;
931 }
932
933
934 /* CLEAR_PASSPHRASE <cache_id>
935
936    may be used to invalidate the cache entry for a passphrase.  The
937    function returns with OK even when there is no cached passphrase.
938 */
939
940 static int
941 cmd_clear_passphrase (assuan_context_t ctx, char *line)
942 {
943   char *cacheid = NULL;
944   char *p;
945
946   /* parse the stuff */
947   for (p=line; *p == ' '; p++)
948     ;
949   cacheid = p;
950   p = strchr (cacheid, ' ');
951   if (p)
952     *p = 0; /* ignore garbage */
953   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
954     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
955
956   agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
957   return 0;
958 }
959
960
961 /* GET_CONFIRMATION <description>
962
963    This command may be used to ask for a simple confirmation.
964    DESCRIPTION is displayed along with a Okay and Cancel button.  This
965    command uses a syntax which helps clients to use the agent with
966    minimum effort.  The agent either returns with an error or with a
967    OK.  Note, that the length of DESCRIPTION is implicitly limited by
968    the maximum length of a command. DESCRIPTION should not contain
969    any spaces, those must be encoded either percent escaped or simply
970    as '+'.
971 */
972
973 static int
974 cmd_get_confirmation (assuan_context_t ctx, char *line)
975 {
976   ctrl_t ctrl = assuan_get_pointer (ctx);
977   int rc;
978   char *desc = NULL;
979   char *p;
980
981   /* parse the stuff */
982   for (p=line; *p == ' '; p++)
983     ;
984   desc = p;
985   p = strchr (desc, ' ');
986   if (p)
987     *p = 0; /* We ignore any garbage -may be later used for other args. */
988
989   if (!desc || !*desc)
990     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
991
992   if (!strcmp (desc, "X"))
993     desc = NULL;
994
995   /* Note, that we only need to replace the + characters and should
996      leave the other escaping in place because the escaped string is
997      send verbatim to the pinentry which does the unescaping (but not
998      the + replacing) */
999   if (desc)
1000     plus_to_blank (desc);
1001
1002   rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
1003   if (rc)
1004     log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
1005   return rc;
1006 }
1007
1008
1009 \f
1010 /* LEARN [--send]
1011
1012    Learn something about the currently inserted smartcard.  With
1013    --send the new certificates are send back.  */
1014 static int
1015 cmd_learn (assuan_context_t ctx, char *line)
1016 {
1017   ctrl_t ctrl = assuan_get_pointer (ctx);
1018   int rc;
1019
1020   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
1021   if (rc)
1022     log_error ("command learn failed: %s\n", gpg_strerror (rc));
1023   return rc;
1024 }
1025
1026
1027 \f
1028 /* PASSWD <hexstring_with_keygrip>
1029   
1030    Change the passphrase/PID for the key identified by keygrip in LINE. */
1031 static int
1032 cmd_passwd (assuan_context_t ctx, char *line)
1033 {
1034   ctrl_t ctrl = assuan_get_pointer (ctx);
1035   int rc;
1036   unsigned char grip[20];
1037   gcry_sexp_t s_skey = NULL;
1038   unsigned char *shadow_info = NULL;
1039
1040   rc = parse_keygrip (ctx, line, grip);
1041   if (rc)
1042     goto leave;
1043
1044   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
1045                             grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey);
1046   if (rc)
1047     ;
1048   else if (!s_skey)
1049     {
1050       log_error ("changing a smartcard PIN is not yet supported\n");
1051       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1052     }
1053   else
1054     rc = agent_protect_and_store (ctrl, s_skey);
1055
1056   xfree (ctrl->server_local->keydesc);
1057   ctrl->server_local->keydesc = NULL;
1058
1059  leave:
1060   gcry_sexp_release (s_skey);
1061   xfree (shadow_info);
1062   if (rc)
1063     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1064   return rc;
1065 }
1066
1067 /* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <hexstring>
1068   
1069    Set the cached passphrase/PIN for the key identified by the keygrip
1070    to passwd for the given time, where -1 means infinite and 0 means
1071    the default (currently only a timeout of -1 is allowed, which means
1072    to never expire it).  If passwd is not provided, ask for it via the
1073    pinentry module.  */
1074 static int
1075 cmd_preset_passphrase (assuan_context_t ctx, char *line)
1076 {
1077   int rc;
1078   unsigned char grip[20];
1079   char *grip_clear = NULL;
1080   char *passphrase = NULL;
1081   int ttl;
1082   size_t len;
1083
1084   if (!opt.allow_preset_passphrase)
1085     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1086
1087   rc = parse_keygrip (ctx, line, grip);
1088   if (rc)
1089     return rc;
1090
1091   /* FIXME: parse_keygrip should return a tail pointer.  */
1092   grip_clear = line;
1093   while (*line && (*line != ' ' && *line != '\t'))
1094     line++;
1095   if (!*line)
1096     return gpg_error (GPG_ERR_MISSING_VALUE);
1097   *line = '\0';
1098   line++;
1099   while (*line && (*line == ' ' || *line == '\t'))
1100     line++;
1101   
1102   /* Currently, only infinite timeouts are allowed.  */
1103   ttl = -1;
1104   if (line[0] != '-' || line[1] != '1')
1105     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1106   line++;
1107   line++;
1108   while (!(*line != ' ' && *line != '\t'))
1109     line++;
1110
1111   /* Syntax check the hexstring.  */
1112   rc = parse_hexstring (ctx, line, &len);
1113   if (rc)
1114     return rc;
1115   line[len] = '\0';
1116
1117   /* If there is a passphrase, use it.  Currently, a passphrase is
1118      required.  */
1119   if (*line)
1120     passphrase = line;
1121   else
1122     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1123
1124   rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
1125
1126   if (rc)
1127     log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc));
1128
1129   return rc;
1130 }
1131
1132 \f
1133 /* SCD <commands to pass to the scdaemon>
1134   
1135    This is a general quote command to redirect everything to the
1136    SCDAEMON. */
1137 static int
1138 cmd_scd (assuan_context_t ctx, char *line)
1139 {
1140   ctrl_t ctrl = assuan_get_pointer (ctx);
1141   int rc;
1142
1143   rc = divert_generic_cmd (ctrl, line, ctx);
1144
1145   return rc;
1146 }
1147
1148
1149 \f
1150 /* GETVAL <key>
1151
1152    Return the value for KEY from the special environment as created by
1153    PUTVAL.
1154  */
1155 static int
1156 cmd_getval (assuan_context_t ctx, char *line)
1157 {
1158   int rc = 0;
1159   char *key = NULL;
1160   char *p;
1161   struct putval_item_s *vl;
1162
1163   for (p=line; *p == ' '; p++)
1164     ;
1165   key = p;
1166   p = strchr (key, ' ');
1167   if (p)
1168     {
1169       *p++ = 0; 
1170       for (; *p == ' '; p++)
1171         ;
1172       if (*p)
1173         return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
1174     }
1175   if (!key || !*key)
1176     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1177
1178
1179   for (vl=putval_list; vl; vl = vl->next)
1180     if ( !strcmp (vl->d, key) )
1181       break;
1182
1183   if (vl) /* Got an entry. */
1184     rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
1185   else
1186     return gpg_error (GPG_ERR_NO_DATA);
1187
1188   if (rc)
1189     log_error ("command getval failed: %s\n", gpg_strerror (rc));
1190   return rc;
1191 }
1192
1193
1194 /* PUTVAL <key> [<percent_escaped_value>]
1195
1196    The gpg-agent maintains a kind of environment which may be used to
1197    store key/value pairs in it, so that they can be retrieved later.
1198    This may be used by helper daemons to daemonize themself on
1199    invocation and register them with gpg-agent.  Callers of the
1200    daemon's service may now first try connect to get the information
1201    for that service from gpg-agent through the GETVAL command and then
1202    try to connect to that daemon.  Only if that fails they may start
1203    an own instance of the service daemon. 
1204
1205    KEY is an an arbitrary symbol with the same syntax rules as keys
1206    for shell environment variables.  PERCENT_ESCAPED_VALUE is the
1207    corresponsing value; they should be similar to the values of
1208    envronment variables but gpg-agent does not enforce any
1209    restrictions.  If that value is not given any value under that KEY
1210    is removed from this special environment.
1211 */
1212 static int
1213 cmd_putval (assuan_context_t ctx, char *line)
1214 {
1215   int rc = 0;
1216   char *key = NULL;
1217   char *value = NULL;
1218   size_t valuelen = 0;
1219   char *p;
1220   struct putval_item_s *vl, *vlprev;
1221
1222   for (p=line; *p == ' '; p++)
1223     ;
1224   key = p;
1225   p = strchr (key, ' ');
1226   if (p)
1227     {
1228       *p++ = 0; 
1229       for (; *p == ' '; p++)
1230         ;
1231       if (*p)
1232         {
1233           value = p;
1234           p = strchr (value, ' ');
1235           if (p)
1236             *p = 0;
1237           valuelen = percent_plus_unescape (value);
1238         }
1239     }
1240   if (!key || !*key)
1241     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1242
1243
1244   for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
1245     if ( !strcmp (vl->d, key) )
1246       break;
1247
1248   if (vl) /* Delete old entry. */
1249     {
1250       if (vlprev)
1251         vlprev->next = vl->next;
1252       else
1253         putval_list = vl->next;
1254       xfree (vl);
1255     }
1256
1257   if (valuelen) /* Add entry. */  
1258     {
1259       vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
1260       if (!vl)
1261         rc = gpg_error_from_syserror ();
1262       else
1263         {
1264           vl->len = valuelen;
1265           vl->off = strlen (key) + 1;
1266           strcpy (vl->d, key);
1267           memcpy (vl->d + vl->off, value, valuelen);
1268           vl->next = putval_list;
1269           putval_list = vl;
1270         }
1271     }
1272
1273   if (rc)
1274     log_error ("command putval failed: %s\n", gpg_strerror (rc));
1275   return rc;
1276 }
1277
1278
1279
1280 \f
1281 /* UPDATESTARTUPTTY 
1282   
1283   Set startup TTY and X DISPLAY variables to the values of this
1284   session.  This command is useful to pull future pinentries to
1285   another screen.  It is only required because there is no way in the
1286   ssh-agent protocol to convey this information.  */
1287 static int
1288 cmd_updatestartuptty (assuan_context_t ctx, char *line)
1289 {
1290   ctrl_t ctrl = assuan_get_pointer (ctx);
1291
1292   xfree (opt.startup_display); opt.startup_display = NULL;
1293   xfree (opt.startup_ttyname); opt.startup_ttyname = NULL;
1294   xfree (opt.startup_ttytype); opt.startup_ttytype = NULL;
1295   xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL;
1296   xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL;
1297
1298   if (ctrl->display)
1299     opt.startup_display = xtrystrdup (ctrl->display);
1300   if (ctrl->ttyname)
1301     opt.startup_ttyname = xtrystrdup (ctrl->ttyname);
1302   if (ctrl->ttytype)
1303     opt.startup_ttytype = xtrystrdup (ctrl->ttytype);
1304   if (ctrl->lc_ctype) 
1305     opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype);
1306   if (ctrl->lc_messages)
1307     opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages);
1308
1309   return 0;
1310 }
1311
1312
1313 \f
1314 #ifdef HAVE_W32_SYSTEM
1315 /* KILLAGENT
1316
1317    Under Windows we start the agent on the fly.  Thus it also make
1318    sense to allow a client to stop the agent. */
1319 static int
1320 cmd_killagent (assuan_context_t ctx, char *line)
1321 {
1322   ctrl_t ctrl = assuan_get_pointer (ctx);
1323   ctrl->server_local->stopme = 1;
1324   return 0;
1325 }
1326
1327 /* RELOADAGENT
1328
1329    As signals are inconvenient under Windows, we provide this command
1330    to allow reloading of the configuration.  */
1331 static int
1332 cmd_reloadagent (assuan_context_t ctx, char *line)
1333 {
1334   agent_sighup_action ();
1335   return 0;
1336 }
1337 #endif /*HAVE_W32_SYSTEM*/
1338
1339
1340 \f
1341 /* GETINFO <what>
1342
1343    Multipurpose function to return a variety of information.
1344    Supported values for WHAT are:
1345
1346      version     - Return the version of the program.
1347      socket_name - Return the name of the socket.
1348      ssh_socket_name - Return the name of the ssh socket.
1349
1350  */
1351 static int
1352 cmd_getinfo (assuan_context_t ctx, char *line)
1353 {
1354   int rc = 0;
1355
1356   if (!strcmp (line, "version"))
1357     {
1358       const char *s = VERSION;
1359       rc = assuan_send_data (ctx, s, strlen (s));
1360     }
1361   else if (!strcmp (line, "socket_name"))
1362     {
1363       const char *s = get_agent_socket_name ();
1364
1365       if (s)
1366         rc = assuan_send_data (ctx, s, strlen (s));
1367       else
1368         rc = gpg_error (GPG_ERR_NO_DATA);
1369     }
1370   else if (!strcmp (line, "ssh_socket_name"))
1371     {
1372       const char *s = get_agent_ssh_socket_name ();
1373
1374       if (s)
1375         rc = assuan_send_data (ctx, s, strlen (s));
1376       else
1377         rc = gpg_error (GPG_ERR_NO_DATA);
1378     }
1379   else
1380     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1381   return rc;
1382 }
1383
1384
1385 \f
1386 static int
1387 option_handler (assuan_context_t ctx, const char *key, const char *value)
1388 {
1389   ctrl_t ctrl = assuan_get_pointer (ctx);
1390
1391   if (!strcmp (key, "display"))
1392     {
1393       if (ctrl->display)
1394         free (ctrl->display);
1395       ctrl->display = strdup (value);
1396       if (!ctrl->display)
1397         return out_of_core ();
1398     }
1399   else if (!strcmp (key, "ttyname"))
1400     {
1401       if (!opt.keep_tty)
1402         {
1403           if (ctrl->ttyname)
1404             free (ctrl->ttyname);
1405           ctrl->ttyname = strdup (value);
1406           if (!ctrl->ttyname)
1407             return out_of_core ();
1408         }
1409     }
1410   else if (!strcmp (key, "ttytype"))
1411     {
1412       if (!opt.keep_tty)
1413         {
1414           if (ctrl->ttytype)
1415             free (ctrl->ttytype);
1416           ctrl->ttytype = strdup (value);
1417           if (!ctrl->ttytype)
1418             return out_of_core ();
1419         }
1420     }
1421   else if (!strcmp (key, "lc-ctype"))
1422     {
1423       if (ctrl->lc_ctype)
1424         free (ctrl->lc_ctype);
1425       ctrl->lc_ctype = strdup (value);
1426       if (!ctrl->lc_ctype)
1427         return out_of_core ();
1428     }
1429   else if (!strcmp (key, "lc-messages"))
1430     {
1431       if (ctrl->lc_messages)
1432         free (ctrl->lc_messages);
1433       ctrl->lc_messages = strdup (value);
1434       if (!ctrl->lc_messages)
1435         return out_of_core ();
1436     }
1437   else if (!strcmp (key, "use-cache-for-signing"))
1438     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
1439   else
1440     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
1441
1442   return 0;
1443 }
1444
1445
1446
1447 \f
1448 /* Called by libassuan after all commands. ERR is the error from the
1449    last assuan operation and not the one returned from the command. */
1450 static void
1451 post_cmd_notify (assuan_context_t ctx, int err)
1452 {
1453   ctrl_t ctrl = assuan_get_pointer (ctx);
1454
1455   /* Switch off any I/O monitor controlled logging pausing. */
1456   ctrl->server_local->pause_io_logging = 0;
1457 }
1458
1459
1460 /* This function is called by libassuan for all I/O.  We use it here
1461    to disable logging for the GETEVENTCOUNTER commands.  This is so
1462    that the debug output won't get cluttered by this primitive
1463    command.  */
1464 static unsigned int
1465 io_monitor (assuan_context_t ctx, int direction,
1466             const char *line, size_t linelen)
1467 {
1468   ctrl_t ctrl = assuan_get_pointer (ctx);
1469
1470   /* Note that we only check for the uppercase name.  This allows to
1471      see the logging for debugging if using a non-upercase command
1472      name. */
1473   if (ctx && !direction 
1474       && linelen >= 15
1475       && !strncmp (line, "GETEVENTCOUNTER", 15)
1476       && (linelen == 15 || spacep (line+15)))
1477     {
1478       ctrl->server_local->pause_io_logging = 1;
1479     }
1480
1481   return ctrl->server_local->pause_io_logging? 1:0;
1482 }
1483
1484
1485 /* Tell the assuan library about our commands */
1486 static int
1487 register_commands (assuan_context_t ctx)
1488 {
1489   static struct {
1490     const char *name;
1491     int (*handler)(assuan_context_t, char *line);
1492   } table[] = {
1493     { "GETEVENTCOUNTER",cmd_geteventcounter },
1494     { "ISTRUSTED",      cmd_istrusted },
1495     { "HAVEKEY",        cmd_havekey },
1496     { "SIGKEY",         cmd_sigkey },
1497     { "SETKEY",         cmd_sigkey },
1498     { "SETKEYDESC",     cmd_setkeydesc },
1499     { "SETHASH",        cmd_sethash },
1500     { "PKSIGN",         cmd_pksign },
1501     { "PKDECRYPT",      cmd_pkdecrypt },
1502     { "GENKEY",         cmd_genkey },
1503     { "READKEY",        cmd_readkey },
1504     { "GET_PASSPHRASE", cmd_get_passphrase },
1505     { "PRESET_PASSPHRASE", cmd_preset_passphrase },
1506     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
1507     { "GET_CONFIRMATION", cmd_get_confirmation },
1508     { "LISTTRUSTED",    cmd_listtrusted },
1509     { "MARKTRUSTED",    cmd_marktrusted },
1510     { "LEARN",          cmd_learn },
1511     { "PASSWD",         cmd_passwd },
1512     { "INPUT",          NULL }, 
1513     { "OUTPUT",         NULL }, 
1514     { "SCD",            cmd_scd },
1515     { "GETVAL",         cmd_getval },
1516     { "PUTVAL",         cmd_putval },
1517     { "UPDATESTARTUPTTY",  cmd_updatestartuptty },
1518 #ifdef HAVE_W32_SYSTEM
1519     { "KILLAGENT",      cmd_killagent },
1520     { "RELOADAGENT",    cmd_reloadagent },
1521 #endif
1522     { "GETINFO",        cmd_getinfo },
1523     { NULL }
1524   };
1525   int i, rc;
1526
1527   for (i=0; table[i].name; i++)
1528     {
1529       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1530       if (rc)
1531         return rc;
1532     } 
1533 #ifdef HAVE_ASSUAN_SET_IO_MONITOR
1534   assuan_register_post_cmd_notify (ctx, post_cmd_notify);
1535 #endif
1536   assuan_register_reset_notify (ctx, reset_notify);
1537   assuan_register_option_handler (ctx, option_handler);
1538   return 0;
1539 }
1540
1541
1542 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a
1543    simple piper server, otherwise it is a regular server.  CTRL is the
1544    control structure for this connection; it has only the basic
1545    intialization. */
1546 void
1547 start_command_handler (ctrl_t ctrl, int listen_fd, int fd)
1548 {
1549   int rc;
1550   assuan_context_t ctx;
1551
1552   if (listen_fd == -1 && fd == -1)
1553     {
1554       int filedes[2];
1555
1556       filedes[0] = 0;
1557       filedes[1] = 1;
1558       rc = assuan_init_pipe_server (&ctx, filedes);
1559     }
1560   else if (listen_fd != -1)
1561     {
1562       rc = assuan_init_socket_server_ext (&ctx, listen_fd, 0);
1563     }
1564   else 
1565     {
1566       rc = assuan_init_socket_server_ext (&ctx, fd, 2);
1567       ctrl->connection_fd = fd;
1568     }
1569   if (rc)
1570     {
1571       log_error ("failed to initialize the server: %s\n",
1572                  gpg_strerror(rc));
1573       agent_exit (2);
1574     }
1575   rc = register_commands (ctx);
1576   if (rc)
1577     {
1578       log_error ("failed to register commands with Assuan: %s\n",
1579                  gpg_strerror(rc));
1580       agent_exit (2);
1581     }
1582
1583   assuan_set_pointer (ctx, ctrl);
1584   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1585   ctrl->server_local->assuan_ctx = ctx;
1586   ctrl->server_local->message_fd = -1;
1587   ctrl->server_local->use_cache_for_signing = 1;
1588   ctrl->digest.raw_value = 0;
1589
1590   if (DBG_ASSUAN)
1591     assuan_set_log_stream (ctx, log_get_stream ());
1592
1593 #ifdef HAVE_ASSUAN_SET_IO_MONITOR
1594   assuan_set_io_monitor (ctx, io_monitor);
1595 #endif
1596
1597   for (;;)
1598     {
1599       rc = assuan_accept (ctx);
1600       if (rc == -1)
1601         {
1602           break;
1603         }
1604       else if (rc)
1605         {
1606           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1607           break;
1608         }
1609       
1610       rc = assuan_process (ctx);
1611       if (rc)
1612         {
1613           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1614           continue;
1615         }
1616     }
1617
1618   /* Reset the SCD if needed. */
1619   agent_reset_scd (ctrl);
1620
1621   /* Reset the pinentry (in case of popup messages). */
1622   agent_reset_query (ctrl);
1623
1624   /* Cleanup.  */
1625   assuan_deinit_server (ctx);
1626 #ifdef HAVE_W32_SYSTEM
1627   if (ctrl->server_local->stopme)
1628     agent_exit (0);
1629 #endif
1630   xfree (ctrl->server_local);
1631   ctrl->server_local = NULL;
1632 }
1633