* trustlist.c: New.
[gnupg.git] / agent / command.c
1 /* command.c - gpg-agent command handler
2  *      Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /* 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 #include <errno.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31
32 #include "agent.h"
33 #include "../assuan/assuan.h"
34
35 /* maximum allowed size of the inquired ciphertext */
36 #define MAXLEN_CIPHERTEXT 4096
37 /* maximum allowed size of the key parameters */
38 #define MAXLEN_KEYPARAM 1024
39
40 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
41
42
43 #if MAX_DIGEST_LEN < 20
44 #error MAX_DIGEST_LEN shorter than keygrip
45 #endif
46
47 /* Data used to associate an Assuan context with local server data */
48 struct server_local_s {
49   ASSUAN_CONTEXT assuan_ctx;
50   int message_fd;
51 };
52
53
54
55
56 \f
57 static void
58 reset_notify (ASSUAN_CONTEXT ctx)
59 {
60   CTRL ctrl = assuan_get_pointer (ctx);
61
62   memset (ctrl->keygrip, 0, 20);
63   ctrl->have_keygrip = 0;
64   ctrl->digest.valuelen = 0;
65 }
66
67 /* ISTRUSTED <hexstring_with_fingerprint>
68
69    Return OK when we have an entry with this fingerprint in our
70    trustlist */
71 static int
72 cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
73 {
74   int rc, n, i;
75   char *p;
76   char fpr[41];
77
78   /* parse the fingerprint value */
79   for (p=line,n=0; hexdigitp (p); p++, n++)
80     ;
81   if (*p || !(n == 40 || n == 32))
82     return set_error (Parameter_Error, "invalid fingerprint");
83   i = 0;
84   if (n==32)
85     {
86       strcpy (fpr, "00000000");
87       i += 8;
88     }
89   for (p=line; i < 40; p++, i++)
90     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
91   fpr[i] = 0;
92   rc = agent_istrusted (fpr);
93   if (!rc)
94     return 0;
95   else if (rc == -1)
96     return ASSUAN_Not_Trusted;
97   else
98     return map_to_assuan_status (rc);
99 }
100
101 /* LISTTRUSTED 
102
103    List all entries from the trustlist */
104 static int
105 cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
106 {
107   return map_to_assuan_status (agent_listtrusted (ctx));
108 }
109
110
111 /* MARKTRUSTED <hexstring_with_fingerprint> <flag>
112
113    Store a new key in into the trustlist*/
114 static int
115 cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
116 {
117   return ASSUAN_Not_Implemented;
118 }
119
120
121
122 \f
123 /* SIGKEY <hexstring_with_keygrip>
124    SETKEY <hexstring_with_keygrip>
125   
126    Set the  key used for a sign or decrypt operation */
127 static int
128 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
129 {
130   int n;
131   char *p;
132   CTRL ctrl = assuan_get_pointer (ctx);
133   unsigned char *buf;
134
135   /* parse the hash value */
136   for (p=line,n=0; hexdigitp (p); p++, n++)
137     ;
138   if (*p)
139     return set_error (Parameter_Error, "invalid hexstring");
140   if ((n&1))
141     return set_error (Parameter_Error, "odd number of digits");
142   n /= 2;
143   if (n != 20)
144     return set_error (Parameter_Error, "invalid length of keygrip");
145
146   buf = ctrl->keygrip;
147   for (p=line, n=0; n < 20; p += 2, n++)
148     buf[n] = xtoi_2 (p);
149   ctrl->have_keygrip = 1;
150   return 0;
151 }
152
153 /* SETHASH <algonumber> <hexstring> 
154
155   The client can use this command to tell the server about the data
156   (which usually is a hash) to be signed. */
157 static int
158 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
159 {
160   int n;
161   char *p;
162   CTRL ctrl = assuan_get_pointer (ctx);
163   unsigned char *buf;
164   char *endp;
165   int algo;
166
167   /* parse the algo number and check it */
168   algo = (int)strtoul (line, &endp, 10);
169   for (line = endp; *line == ' ' || *line == '\t'; line++)
170     ;
171   if (!algo || gcry_md_test_algo (algo))
172     return set_error (Unsupported_Algorithm, NULL);
173   ctrl->digest.algo = algo;
174
175   /* parse the hash value */
176   for (p=line,n=0; hexdigitp (p); p++, n++)
177     ;
178   if (*p)
179     return set_error (Parameter_Error, "invalid hexstring");
180   if ((n&1))
181     return set_error (Parameter_Error, "odd number of digits");
182   n /= 2;
183   if (n != 16 && n != 20 && n != 24 && n != 32)
184     return set_error (Parameter_Error, "unsupported length of hash");
185   if (n > MAX_DIGEST_LEN)
186     return set_error (Parameter_Error, "hash value to long");
187
188   buf = ctrl->digest.value;
189   ctrl->digest.valuelen = n;
190   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
191     buf[n] = xtoi_2 (p);
192   for (; n < ctrl->digest.valuelen; n++)
193     buf[n] = 0;
194   return 0;
195 }
196
197
198 /* PKSIGN <options>
199
200    Perform the actual sign operation. Neither input nor output are
201    sensitive to eavesdropping */
202 static int
203 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
204 {
205   int rc;
206   CTRL ctrl = assuan_get_pointer (ctx);
207
208   rc = agent_pksign (ctrl, assuan_get_data_fp (ctx));
209   return map_to_assuan_status (rc);
210 }
211
212 /* PKDECRYPT <options>
213
214    Perform the actual decrypt operation.  Input is not 
215    sensitive to eavesdropping */
216 static int
217 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
218 {
219   int rc;
220   CTRL ctrl = assuan_get_pointer (ctx);
221   char *value;
222   size_t valuelen;
223
224   /* First inquire the data to decrypt */
225   rc = assuan_inquire (ctx, "CIPHERTEXT",
226                        &value, &valuelen, MAXLEN_CIPHERTEXT);
227   if (rc)
228     return rc;
229
230   rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
231   xfree (value);
232   return map_to_assuan_status (rc);
233 }
234
235
236 /* GENKEY
237
238    Generate a new key, store the secret part and return the public
239    part.  Here is an example transaction:
240
241    C: GENKEY
242    S: INQUIRE KEYPARM
243    C: D (genkey (rsa (nbits  1024)))
244    C: END
245    S: D (public-key
246    S: D   (rsa (n 326487324683264) (e 10001)))
247    S  OK key created
248 */
249
250 static int
251 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
252 {
253   CTRL ctrl = assuan_get_pointer (ctx);
254   int rc;
255   char *value;
256   size_t valuelen;
257
258   /* First inquire the parameters */
259   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
260   if (rc)
261     return rc;
262
263   rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx));
264   xfree (value);
265   return map_to_assuan_status (rc);
266 }
267
268
269 /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
270
271    This function is usually used to ask for a passphrase to be used
272    for conventional encryption, but may aslo be used by programs which
273    need specal handling of passphrases.  This command uses a syntax
274    which helps clients to use the agent with minimum effort.  The
275    agent either returns with an error or with a OK followed by the hex
276    encoded passphrase.  Note that the length of the strings is
277    implicitly limited by the maximum length of a command.
278 */
279
280 static int
281 cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
282 {
283   int rc;
284   char *response;
285   char *desc, *prompt, *errtext;
286
287   /* FIXME: Parse that stuff */
288   desc = "We need a passphrase";
289   prompt = NULL;
290   errtext = "try again";
291
292   rc = agent_get_passphrase (&response, desc, prompt, errtext);
293   if (!rc)
294     {
295       rc = assuan_set_okay_line (ctx, response);
296       xfree (response);
297     }
298
299   return map_to_assuan_status (rc);
300 }
301
302
303 /* CLEAR_PASSPHRASE <cache_id>
304
305    may be used to invalidate the cache entry for a passphrase.  The
306    function returns with OK even when ther eis no cached passphrase.
307 */
308
309 static int
310 cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
311 {
312   int rc;
313
314   /* fixme: no caching yet. so return with OK */
315   rc = 0;
316
317   return map_to_assuan_status (rc);
318 }
319
320
321 \f
322 /* Tell the assuan library about our commands */
323 static int
324 register_commands (ASSUAN_CONTEXT ctx)
325 {
326   static struct {
327     const char *name;
328     int cmd_id;
329     int (*handler)(ASSUAN_CONTEXT, char *line);
330   } table[] = {
331     { "ISTRUSTED",  0,  cmd_istrusted },
332     { "SIGKEY",     0,  cmd_sigkey },
333     { "SETKEY",     0,  cmd_sigkey },
334     { "SETHASH",    0,  cmd_sethash },
335     { "PKSIGN",     0,  cmd_pksign },
336     { "PKDECRYPT",  0,  cmd_pkdecrypt },
337     { "GENKEY",     0,  cmd_genkey },
338     { "GET_PASSPHRASE",0, cmd_get_passphrase },
339     { "CLEAR_PASSPHRASE",0, cmd_clear_passphrase },
340     { "LISTTRUSTED",  0,  cmd_listtrusted },
341     { "MARKTRUSTED",  0,  cmd_marktrusted },
342     { "",     ASSUAN_CMD_INPUT, NULL }, 
343     { "",     ASSUAN_CMD_OUTPUT, NULL }, 
344     { NULL }
345   };
346   int i, j, rc;
347
348   for (i=j=0; table[i].name; i++)
349     {
350       rc = assuan_register_command (ctx,
351                                     table[i].cmd_id? table[i].cmd_id
352                                                    : (ASSUAN_CMD_USER + j++),
353                                     table[i].name, table[i].handler);
354       if (rc)
355         return rc;
356     } 
357   assuan_register_reset_notify (ctx, reset_notify);
358   return 0;
359 }
360
361
362 /* Startup the server */
363 void
364 start_command_handler (void)
365 {
366   int rc;
367   int filedes[2];
368   ASSUAN_CONTEXT ctx;
369   struct server_control_s ctrl;
370
371   memset (&ctrl, 0, sizeof ctrl);
372
373   /* For now we use a simple pipe based server so that we can work
374      from scripts.  We will later add options to run as a daemon and
375      wait for requests on a Unix domain socket */
376   filedes[0] = 0;
377   filedes[1] = 1;
378   rc = assuan_init_pipe_server (&ctx, filedes);
379   if (rc)
380     {
381       log_error ("failed to initialize the server: %s\n",
382                  assuan_strerror(rc));
383       agent_exit (2);
384     }
385   rc = register_commands (ctx);
386   if (rc)
387     {
388       log_error ("failed to the register commands with Assuan: %s\n",
389                  assuan_strerror(rc));
390       agent_exit (2);
391     }
392
393   assuan_set_pointer (ctx, &ctrl);
394   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
395   ctrl.server_local->assuan_ctx = ctx;
396   ctrl.server_local->message_fd = -1;
397
398   for (;;)
399     {
400       rc = assuan_accept (ctx);
401       if (rc == -1)
402         {
403           break;
404         }
405       else if (rc)
406         {
407           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
408           break;
409         }
410       
411       rc = assuan_process (ctx);
412       if (rc)
413         {
414           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
415           continue;
416         }
417     }
418
419
420   assuan_deinit_pipe_server (ctx);
421 }
422