Ask for the keysize when generating a new card key.
[gnupg.git] / g10 / server.c
1 /* server.c - server mode for gpg
2  * Copyright (C) 2006, 2008  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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <ctype.h>
27 #include <unistd.h>
28
29 #include <assuan.h>
30
31 #include "gpg.h"
32 #include "util.h"
33 #include "i18n.h"
34 #include "options.h"
35 #include "../common/sysutils.h"
36
37
38 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
39
40
41 /* Data used to associate an Assuan context with local server data.  */
42 struct server_local_s 
43 {
44   /* Our current Assuan context. */
45   assuan_context_t assuan_ctx;  
46   /* File descriptor as set by the MESSAGE command. */
47   gnupg_fd_t message_fd;               
48 };
49
50
51 \f
52 /* Helper to close the message fd if it is open. */
53 static void 
54 close_message_fd (ctrl_t ctrl)
55 {
56   if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
57     {
58       assuan_sock_close (ctrl->server_local->message_fd);
59       ctrl->server_local->message_fd = GNUPG_INVALID_FD;
60     } 
61 }
62
63
64 \f
65 /* Called by libassuan for Assuan options.  See the Assuan manual for
66    details. */
67 static int
68 option_handler (assuan_context_t ctx, const char *key, const char *value)
69 {
70 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
71
72   (void)ctx;
73   (void)value;
74
75   /* Fixme: Implement the tty and locale args. */
76   if (!strcmp (key, "display"))
77     {
78     }
79   else if (!strcmp (key, "ttyname"))
80     {
81     }
82   else if (!strcmp (key, "ttytype"))
83     {
84     }
85   else if (!strcmp (key, "lc-ctype"))
86     {
87     }
88   else if (!strcmp (key, "lc-messages"))
89     {
90     }
91   else if (!strcmp (key, "xauthority"))
92     {
93     }
94   else if (!strcmp (key, "pinentry_user_data"))
95     {
96     }
97   else if (!strcmp (key, "list-mode"))
98     {
99       /* This is for now a dummy option. */
100     }
101   else
102     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
103
104   return 0;
105 }
106
107
108 /* Called by libassuan for RESET commands. */
109 static void
110 reset_notify (assuan_context_t ctx)
111 {
112   ctrl_t ctrl = assuan_get_pointer (ctx);
113
114   close_message_fd (ctrl);
115   assuan_close_input_fd (ctx);
116   assuan_close_output_fd (ctx);
117 }
118
119
120 /* Called by libassuan for INPUT commands. */
121 static void
122 input_notify (assuan_context_t ctx, const char *line)
123 {
124 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
125
126   (void)ctx;
127
128   if (strstr (line, "--armor"))
129     ; /* FIXME */
130   else if (strstr (line, "--base64"))
131     ; /* FIXME */
132   else if (strstr (line, "--binary"))
133     ;
134   else
135     {
136       /* FIXME (autodetect encoding) */
137     }
138 }
139
140
141 /* Called by libassuan for OUTPUT commands. */
142 static void
143 output_notify (assuan_context_t ctx, const char *line)
144 {
145 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
146   
147   (void)ctx;
148
149   if (strstr (line, "--armor"))
150     ; /* FIXME */
151   else if (strstr (line, "--base64"))
152     {
153       /* FIXME */
154     }
155 }
156
157
158
159 \f
160 /*  RECIPIENT <userID>
161
162    Set the recipient for the encryption.  <userID> should be the
163    internal representation of the key; the server may accept any other
164    way of specification.  If this is a valid and trusted recipient the
165    server does respond with OK, otherwise the return is an ERR with
166    the reason why the recipient can't be used, the encryption will
167    then not be done for this recipient.  If the policy is not to
168    encrypt at all if not all recipients are valid, the client has to
169    take care of this.  All RECIPIENT commands are cumulative until a
170    RESET or an successful ENCRYPT command.  */
171 static int 
172 cmd_recipient (assuan_context_t ctx, char *line)
173 {
174   (void)ctx;
175   (void)line;
176   return gpg_error (GPG_ERR_NOT_SUPPORTED);
177 }
178
179
180 \f
181 /*  SIGNER <userID>
182
183    Set the signer's keys for the signature creation.  <userID> should
184    be the internal representation of the key; the server may accept
185    any other way of specification.  If this is a valid and usable
186    signing key the server does respond with OK, otherwise it returns
187    an ERR with the reason why the key can't be used, the signing will
188    then not be done for this key.  If the policy is not to sign at all
189    if not all signer keys are valid, the client has to take care of
190    this.  All SIGNER commands are cumulative until a RESET but they
191    are *not* reset by an SIGN command becuase it can be expected that
192    set of signers are used for more than one sign operation.
193
194    Note that this command returns an INV_RECP status which is a bit
195    strange, but they are very similar.  */
196 static int 
197 cmd_signer (assuan_context_t ctx, char *line)
198 {
199   (void)ctx;
200   (void)line;
201   return gpg_error (GPG_ERR_NOT_SUPPORTED);
202 }
203
204
205 \f
206 /*  ENCRYPT 
207
208    Do the actual encryption process.  Takes the plaintext from the
209    INPUT command, writes to the ciphertext to the file descriptor set
210    with the OUTPUT command, take the recipients form all the
211    recipients set so far.  If this command fails the clients should
212    try to delete all output currently done or otherwise mark it as
213    invalid.  GPG does ensure that there won't be any security problem
214    with leftover data on the output in this case.
215
216    This command should in general not fail, as all necessary checks
217    have been done while setting the recipients.  The input and output
218    pipes are closed.  */
219 static int 
220 cmd_encrypt (assuan_context_t ctx, char *line)
221 {
222   (void)ctx;
223   (void)line;
224   return gpg_error (GPG_ERR_NOT_SUPPORTED);
225 }
226
227
228 \f
229 /*  DECRYPT
230
231    This performs the decrypt operation after doing some checks on the
232    internal state (e.g. that only needed data has been set).   */
233 static int 
234 cmd_decrypt (assuan_context_t ctx, char *line)
235 {
236   (void)ctx;
237   (void)line;
238   return gpg_error (GPG_ERR_NOT_SUPPORTED);
239 }
240
241
242 \f
243 /*  VERIFY
244
245    This does a verify operation on the message send to the input-FD.
246    The result is written out using status lines.  If an output FD was
247    given, the signed text will be written to that.
248   
249    If the signature is a detached one, the server will inquire about
250    the signed material and the client must provide it.
251  */
252 static int 
253 cmd_verify (assuan_context_t ctx, char *line)
254 {
255   int rc;
256   ctrl_t ctrl = assuan_get_pointer (ctx);
257   gnupg_fd_t fd = assuan_get_input_fd (ctx);
258   gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
259   FILE *out_fp = NULL;
260
261   (void)line;
262
263   if (fd == GNUPG_INVALID_FD)
264     return gpg_error (GPG_ERR_ASS_NO_INPUT);
265
266   if (out_fd != GNUPG_INVALID_FD)
267     {
268       out_fp = fdopen ( dup (FD2INT (out_fd)), "w");
269       if (!out_fp)
270         return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
271     }
272
273   log_debug ("WARNING: The server mode work "
274              "in progress and not ready for use\n");
275
276   /* Need to dup it because it might get closed and libassuan won't
277      know about it then. */
278   rc = gpg_verify (ctrl,
279                    dup ( FD2INT (fd)), 
280                    dup ( FD2INT (ctrl->server_local->message_fd)),
281                    out_fp);
282
283   if (out_fp)
284     fclose (out_fp);
285   close_message_fd (ctrl);
286   assuan_close_input_fd (ctx);
287   assuan_close_output_fd (ctx);
288
289   return rc;
290 }
291
292
293 \f
294 /*  SIGN [--detached]
295
296    Sign the data set with the INPUT command and write it to the sink
297    set by OUTPUT.  With "--detached" specified, a detached signature
298    is created.  */
299 static int 
300 cmd_sign (assuan_context_t ctx, char *line)
301 {
302   (void)ctx;
303   (void)line;
304   return gpg_error (GPG_ERR_NOT_SUPPORTED);
305 }
306
307
308 \f
309 /*  IMPORT
310
311   Import keys as read from the input-fd, return status message for
312   each imported one.  The import checks the validity of the key.  */
313 static int 
314 cmd_import (assuan_context_t ctx, char *line)
315 {
316   (void)ctx;
317   (void)line;
318   return gpg_error (GPG_ERR_NOT_SUPPORTED);
319 }
320
321
322 \f
323 /*  EXPORT [--data [--armor|--base64]] [--] pattern
324
325    Similar to the --export command line command, this command exports
326    public keys matching PATTERN.  The output is send to the output fd
327    unless the --data option has been used in which case the output
328    gets send inline using regular data lines.  The options "--armor"
329    and "--base" ospecify an output format if "--data" has been used.
330    Recall that in general the output format is set with the OUTPUT
331    command.
332  */
333 static int 
334 cmd_export (assuan_context_t ctx, char *line)
335 {
336   (void)ctx;
337   (void)line;
338   return gpg_error (GPG_ERR_NOT_SUPPORTED);
339 }
340
341
342 \f
343 /*  DELKEYS
344
345     Fixme
346 */
347 static int 
348 cmd_delkeys (assuan_context_t ctx, char *line)
349 {
350   (void)ctx;
351   (void)line;
352   return gpg_error (GPG_ERR_NOT_SUPPORTED);
353 }
354
355
356 \f
357 /*  MESSAGE FD[=<n>]
358
359    Set the file descriptor to read a message which is used with
360    detached signatures.  */
361 static int 
362 cmd_message (assuan_context_t ctx, char *line)
363 {
364   int rc;
365   gnupg_fd_t fd;
366   ctrl_t ctrl = assuan_get_pointer (ctx);
367
368   rc = assuan_command_parse_fd (ctx, line, &fd);
369   if (rc)
370     return rc;
371   if (fd == GNUPG_INVALID_FD)
372     return gpg_error (GPG_ERR_ASS_NO_INPUT);
373   ctrl->server_local->message_fd = fd;
374   return 0;
375 }
376
377
378 \f
379 /* LISTKEYS [<patterns>]
380    LISTSECRETKEYS [<patterns>]
381
382    fixme
383 */
384 static int 
385 do_listkeys (assuan_context_t ctx, char *line, int mode)
386 {
387   (void)ctx;
388   (void)line;
389   (void)mode;
390
391   return gpg_error (GPG_ERR_NOT_SUPPORTED);
392 }
393
394
395 static int 
396 cmd_listkeys (assuan_context_t ctx, char *line)
397 {
398   return do_listkeys (ctx, line, 3);
399 }
400
401
402 static int 
403 cmd_listsecretkeys (assuan_context_t ctx, char *line)
404 {
405   return do_listkeys (ctx, line, 2);
406 }
407
408
409 \f
410 /* GENKEY
411
412    Read the parameters in native format from the input fd and create a
413    new OpenPGP key.
414  */
415 static int 
416 cmd_genkey (assuan_context_t ctx, char *line)
417 {
418   (void)ctx;
419   (void)line;
420   return gpg_error (GPG_ERR_NOT_SUPPORTED);
421 }
422
423
424 /* GETINFO <what>
425
426    Multipurpose function to return a variety of information.
427    Supported values for WHAT are:
428
429      version     - Return the version of the program.
430      pid         - Return the process id of the server.
431
432  */
433 static int
434 cmd_getinfo (assuan_context_t ctx, char *line)
435 {
436   int rc;
437
438   if (!strcmp (line, "version"))
439     {
440       const char *s = VERSION;
441       rc = assuan_send_data (ctx, s, strlen (s));
442     }
443   else if (!strcmp (line, "pid"))
444     {
445       char numbuf[50];
446
447       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
448       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
449     }
450   else
451     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
452   return rc;
453 }
454
455
456 \f
457 /* Helper to register our commands with libassuan. */
458 static int
459 register_commands (assuan_context_t ctx)
460 {
461   static struct 
462   {
463     const char *name;
464     int (*handler)(assuan_context_t, char *line);
465   } table[] = {
466     { "RECIPIENT",     cmd_recipient },
467     { "SIGNER",        cmd_signer    },
468     { "ENCRYPT",       cmd_encrypt   },
469     { "DECRYPT",       cmd_decrypt   },
470     { "VERIFY",        cmd_verify    },
471     { "SIGN",          cmd_sign      },
472     { "IMPORT",        cmd_import    },
473     { "EXPORT",        cmd_export    },
474     { "INPUT",         NULL          }, 
475     { "OUTPUT",        NULL          }, 
476     { "MESSAGE",       cmd_message   },
477     { "LISTKEYS",      cmd_listkeys  },
478     { "LISTSECRETKEYS",cmd_listsecretkeys },
479     { "GENKEY",        cmd_genkey    },
480     { "DELKEYS",       cmd_delkeys   },
481     { "GETINFO",       cmd_getinfo   },
482     { NULL }
483   };
484   int i, rc;
485
486   for (i=0; table[i].name; i++)
487     {
488       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
489       if (rc)
490         return rc;
491     } 
492   return 0;
493 }
494
495
496
497 \f
498 /* Startup the server.  CTRL must have been allocated by the caller
499    and set to the default values. */
500 int
501 gpg_server (ctrl_t ctrl)
502 {
503   int rc;
504   int filedes[2];
505   assuan_context_t ctx;
506   static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
507                                VERSION " ready");
508
509   /* We use a pipe based server so that we can work from scripts.
510      assuan_init_pipe_server will automagically detect when we are
511      called with a socketpair and ignore FILEDES in this case.  */
512   filedes[0] = 0;
513   filedes[1] = 1;
514   rc = assuan_init_pipe_server (&ctx, filedes);
515   if (rc)
516     {
517       log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
518       goto leave;
519     }
520
521   rc = register_commands (ctx);
522   if (rc)
523     {
524       log_error ("failed to the register commands with Assuan: %s\n",
525                  gpg_strerror(rc));
526       goto leave;
527     }
528
529   assuan_set_pointer (ctx, ctrl);
530   if (opt.verbose || opt.debug)
531     {
532       char *tmp = NULL;
533       const char *s1 = getenv ("GPG_AGENT_INFO");
534
535       if (asprintf (&tmp,
536                     "Home: %s\n"
537                     "Config: %s\n"
538                     "AgentInfo: %s\n"
539                     "%s",
540                     opt.homedir,
541                     "fixme: need config filename",
542                     s1?s1:"[not set]",
543                     hello) > 0)
544         {
545           assuan_set_hello_line (ctx, tmp);
546           free (tmp);
547         }
548     }
549   else
550     assuan_set_hello_line (ctx, hello);
551   assuan_register_reset_notify (ctx, reset_notify);
552   assuan_register_input_notify (ctx, input_notify);
553   assuan_register_output_notify (ctx, output_notify);
554   assuan_register_option_handler (ctx, option_handler);
555
556   ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
557   if (!ctrl->server_local)
558     {
559       rc = gpg_error_from_syserror ();
560       goto leave;
561     }
562   ctrl->server_local->assuan_ctx = ctx;
563   ctrl->server_local->message_fd = GNUPG_INVALID_FD;
564
565   if (DBG_ASSUAN)
566     assuan_set_log_stream (ctx, log_get_stream ());
567
568   for (;;)
569     {
570       rc = assuan_accept (ctx);
571       if (rc == -1)
572         {
573           rc = 0;
574           break;
575         }
576       else if (rc)
577         {
578           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
579           break;
580         }
581       
582       rc = assuan_process (ctx);
583       if (rc)
584         {
585           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
586           continue;
587         }
588     }
589
590  leave:
591   xfree (ctrl->server_local);
592   ctrl->server_local = NULL;
593   assuan_deinit_server (ctx);
594   return rc;
595 }
596