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