The Agent does now call the pin entry program; however because we have
[gnupg.git] / agent / command.c
1 /* command.c - gpg-agent command handler
2  *      Copyright (C) 2001 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
38
39 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
40 #define digitp(a) ((a) >= '0' && (a) <= '9')
41 #define hexdigitp(a) (digitp (a)                     \
42                       || ((a) >= 'A' && (a) <= 'F')  \
43                       || ((a) >= 'a' && (a) <= 'f'))
44 #define atoi_1(p)   (*(p) - '0' )
45 #define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
46 /* assumes ASCII and pre-checked values */
47 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
48                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
49 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
50
51 #if MAX_DIGEST_LEN < 20
52 #error MAX_DIGEST_LEN shorter than keygrip
53 #endif
54
55 /* Data used to associate an Assuan context with local server data */
56 struct server_local_s {
57   ASSUAN_CONTEXT assuan_ctx;
58   int message_fd;
59 };
60
61
62 /* Map GNUPG_xxx error codes to Assuan status codes
63    FIXME: duplicated from ../sm/server.c */
64 static int
65 rc_to_assuan_status (int rc)
66 {
67   switch (rc)
68     {
69     case 0: break;
70     case GNUPG_Bad_Certificate:   rc = ASSUAN_Bad_Certificate; break;
71     case GNUPG_Bad_Certificate_Path: rc = ASSUAN_Bad_Certificate_Path; break;
72     case GNUPG_Missing_Certificate: rc = ASSUAN_Missing_Certificate; break;
73     case GNUPG_No_Data:           rc = ASSUAN_No_Data_Available; break;
74     case GNUPG_Bad_Signature:     rc = ASSUAN_Bad_Signature; break;
75     case GNUPG_Not_Implemented:   rc = ASSUAN_Not_Implemented; break;
76     case GNUPG_No_Agent:          rc = ASSUAN_No_Agent; break;
77     case GNUPG_Agent_Error:       rc = ASSUAN_Agent_Error; break;
78     case GNUPG_No_Public_Key:     rc = ASSUAN_No_Public_Key; break;
79     case GNUPG_No_Secret_Key:     rc = ASSUAN_No_Secret_Key; break;
80     case GNUPG_Invalid_Data:      rc = ASSUAN_Invalid_Data; break;
81
82     case GNUPG_Bad_PIN:
83     case GNUPG_Bad_Passphrase:
84       rc = ASSUAN_No_Secret_Key;
85       break;
86
87     case GNUPG_Read_Error: 
88     case GNUPG_Write_Error:
89     case GNUPG_IO_Error: 
90       rc = ASSUAN_Server_IO_Error;
91       break;
92     case GNUPG_Out_Of_Core:    
93     case GNUPG_Resource_Limit: 
94       rc = ASSUAN_Server_Resource_Problem;
95       break;
96     case GNUPG_Bug: 
97     case GNUPG_Internal_Error:   
98       rc = ASSUAN_Server_Bug;
99       break;
100     default: 
101       rc = ASSUAN_Server_Fault;
102       break;
103     }
104   return rc;
105 }
106
107
108 \f
109 static void
110 reset_notify (ASSUAN_CONTEXT ctx)
111 {
112   CTRL ctrl = assuan_get_pointer (ctx);
113
114   memset (ctrl->keygrip, 0, 20);
115   ctrl->have_keygrip = 0;
116   ctrl->digest.valuelen = 0;
117 }
118
119 /* SIGKEY <hexstring_with_keygrip>
120    SETKEY <hexstring_with_keygrip>
121   
122    Set the  key used for a sign or decrypt operation */
123 static int
124 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
125 {
126   int n;
127   char *p;
128   CTRL ctrl = assuan_get_pointer (ctx);
129   unsigned char *buf;
130
131   /* parse the hash value */
132   for (p=line,n=0; hexdigitp (*p); p++, n++)
133     ;
134   if (*p)
135     return set_error (Parameter_Error, "invalid hexstring");
136   if ((n&1))
137     return set_error (Parameter_Error, "odd number of digits");
138   n /= 2;
139   if (n != 20)
140     return set_error (Parameter_Error, "invalid length of keygrip");
141
142   buf = ctrl->keygrip;
143   for (p=line, n=0; n < 20; p += 2, n++)
144     buf[n] = xtoi_2 (p);
145   ctrl->have_keygrip = 1;
146   return 0;
147 }
148
149 /* SETHASH <algonumber> <hexstring> 
150
151   The client can use this command to tell the server about the data
152   (which usually is a hash) to be signed. */
153 static int
154 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
155 {
156   int n;
157   char *p;
158   CTRL ctrl = assuan_get_pointer (ctx);
159   unsigned char *buf;
160   char *endp;
161   int algo;
162
163   /* parse the algo number and check it */
164   algo = (int)strtoul (line, &endp, 10);
165   for (line = endp; *line == ' ' || *line == '\t'; line++)
166     ;
167   if (!algo || gcry_md_test_algo (algo))
168     return set_error (Unsupported_Algorithm, NULL);
169   ctrl->digest.algo = algo;
170
171   /* parse the hash value */
172   for (p=line,n=0; hexdigitp (*p); p++, n++)
173     ;
174   if (*p)
175     return set_error (Parameter_Error, "invalid hexstring");
176   if ((n&1))
177     return set_error (Parameter_Error, "odd number of digits");
178   n /= 2;
179   if (n != 16 && n != 20 && n != 24 && n != 32)
180     return set_error (Parameter_Error, "unsupported length of hash");
181   if (n > MAX_DIGEST_LEN)
182     return set_error (Parameter_Error, "hash value to long");
183
184   buf = ctrl->digest.value;
185   ctrl->digest.valuelen = n;
186   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
187     buf[n] = xtoi_2 (p);
188   for (; n < ctrl->digest.valuelen; n++)
189     buf[n] = 0;
190   return 0;
191 }
192
193
194 /* PKSIGN <options>
195
196    Perform the actual sign operation. Neither input nor output are
197    sensitive to eavesdropping */
198 static int
199 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
200 {
201   int rc;
202   CTRL ctrl = assuan_get_pointer (ctx);
203
204   rc = agent_pksign (ctrl, assuan_get_data_fp (ctx));
205   return rc_to_assuan_status (rc);
206 }
207
208 /* PKDECRYPT <options>
209
210    Perform the actual decrypt operation.  Input is not 
211    sensitive to eavesdropping */
212 static int
213 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
214 {
215   int rc;
216   CTRL ctrl = assuan_get_pointer (ctx);
217   char *value;
218   size_t valuelen;
219
220   /* First inquire the data to decrypt */
221   rc = assuan_inquire (ctx, "CIPHERTEXT",
222                        &value, &valuelen, MAXLEN_CIPHERTEXT);
223   if (rc)
224     return rc;
225
226   rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
227   xfree (value);
228   return rc_to_assuan_status (rc);
229 }
230
231
232 \f
233 /* Tell the assuan library about our commands */
234 static int
235 register_commands (ASSUAN_CONTEXT ctx)
236 {
237   static struct {
238     const char *name;
239     int cmd_id;
240     int (*handler)(ASSUAN_CONTEXT, char *line);
241   } table[] = {
242     { "SIGKEY",     0,  cmd_sigkey },
243     { "SETKEY",     0,  cmd_sigkey },
244     { "SETHASH",    0,  cmd_sethash },
245     { "PKSIGN",     0,  cmd_pksign },
246     { "PKDECRYPT",  0,  cmd_pkdecrypt },
247     { "",     ASSUAN_CMD_INPUT, NULL }, 
248     { "",     ASSUAN_CMD_OUTPUT, NULL }, 
249     { NULL }
250   };
251   int i, j, rc;
252
253   for (i=j=0; table[i].name; i++)
254     {
255       rc = assuan_register_command (ctx,
256                                     table[i].cmd_id? table[i].cmd_id
257                                                    : (ASSUAN_CMD_USER + j++),
258                                     table[i].name, table[i].handler);
259       if (rc)
260         return rc;
261     } 
262   assuan_register_reset_notify (ctx, reset_notify);
263   return 0;
264 }
265
266
267 /* Startup the server */
268 void
269 start_command_handler (void)
270 {
271   int rc;
272   int filedes[2];
273   ASSUAN_CONTEXT ctx;
274   struct server_control_s ctrl;
275
276   memset (&ctrl, 0, sizeof ctrl);
277
278   /* For now we use a simple pipe based server so that we can work
279      from scripts.  We will later add options to run as a daemon and
280      wait for requests on a Unix domain socket */
281   filedes[0] = 0;
282   filedes[1] = 1;
283   rc = assuan_init_pipe_server (&ctx, filedes);
284   if (rc)
285     {
286       log_error ("failed to initialize the server: %s\n",
287                  assuan_strerror(rc));
288       agent_exit (2);
289     }
290   rc = register_commands (ctx);
291   if (rc)
292     {
293       log_error ("failed to the register commands with Assuan: %s\n",
294                  assuan_strerror(rc));
295       agent_exit (2);
296     }
297
298   assuan_set_pointer (ctx, &ctrl);
299   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
300   ctrl.server_local->assuan_ctx = ctx;
301   ctrl.server_local->message_fd = -1;
302
303   for (;;)
304     {
305       rc = assuan_accept (ctx);
306       if (rc == -1)
307         {
308           break;
309         }
310       else if (rc)
311         {
312           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
313           break;
314         }
315       
316       rc = assuan_process (ctx);
317       if (rc)
318         {
319           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
320           continue;
321         }
322     }
323
324
325   assuan_deinit_pipe_server (ctx);
326 }
327