Exporting secret keys via gpg-agent is now basically supported.
[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
30 #include "gpg.h"
31 #include <assuan.h>
32 #include "util.h"
33 #include "i18n.h"
34 #include "options.h"
35 #include "../common/sysutils.h"
36 #include "status.h"
37
38
39 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
40
41
42 /* Data used to associate an Assuan context with local server data.  */
43 struct server_local_s 
44 {
45   /* Our current Assuan context. */
46   assuan_context_t assuan_ctx;  
47   /* File descriptor as set by the MESSAGE command. */
48   gnupg_fd_t message_fd;               
49
50   /* List of prepared recipients.  */
51   pk_list_t recplist;
52
53 };
54
55
56 \f
57 /* Helper to close the message fd if it is open. */
58 static void 
59 close_message_fd (ctrl_t ctrl)
60 {
61   if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
62     {
63       assuan_sock_close (ctrl->server_local->message_fd);
64       ctrl->server_local->message_fd = GNUPG_INVALID_FD;
65     } 
66 }
67
68
69 /* Skip over options.  Blanks after the options are also removed.  */
70 static char *
71 skip_options (const char *line)
72 {
73   while (spacep (line))
74     line++;
75   while ( *line == '-' && line[1] == '-' )
76     {
77       while (*line && !spacep (line))
78         line++;
79       while (spacep (line))
80         line++;
81     }
82   return (char*)line;
83 }
84
85
86 /* Check whether the option NAME appears in LINE.  */
87 static int
88 has_option (const char *line, const char *name)
89 {
90   const char *s;
91   int n = strlen (name);
92   
93   s = strstr (line, name);
94   if (s && s >= skip_options (line))
95     return 0;
96   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
97 }
98
99
100
101
102 \f
103 /* Called by libassuan for Assuan options.  See the Assuan manual for
104    details. */
105 static gpg_error_t
106 option_handler (assuan_context_t ctx, const char *key, const char *value)
107 {
108 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
109
110   (void)ctx;
111   (void)value;
112
113   /* Fixme: Implement the tty and locale args. */
114   if (!strcmp (key, "display"))
115     {
116     }
117   else if (!strcmp (key, "ttyname"))
118     {
119     }
120   else if (!strcmp (key, "ttytype"))
121     {
122     }
123   else if (!strcmp (key, "lc-ctype"))
124     {
125     }
126   else if (!strcmp (key, "lc-messages"))
127     {
128     }
129   else if (!strcmp (key, "xauthority"))
130     {
131     }
132   else if (!strcmp (key, "pinentry_user_data"))
133     {
134     }
135   else if (!strcmp (key, "list-mode"))
136     {
137       /* This is for now a dummy option. */
138     }
139   else
140     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
141
142   return 0;
143 }
144
145
146 /* Called by libassuan for RESET commands. */
147 static gpg_error_t
148 reset_notify (assuan_context_t ctx, char *line)
149 {
150   ctrl_t ctrl = assuan_get_pointer (ctx);
151
152   (void)line;
153
154   release_pk_list (ctrl->server_local->recplist);
155   ctrl->server_local->recplist = NULL;
156
157   close_message_fd (ctrl);
158   assuan_close_input_fd (ctx);
159   assuan_close_output_fd (ctx);
160   return 0;
161 }
162
163
164 /* Called by libassuan for INPUT commands. */
165 static gpg_error_t
166 input_notify (assuan_context_t ctx, char *line)
167 {
168 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
169
170   (void)ctx;
171
172   if (strstr (line, "--armor"))
173     ; /* FIXME */
174   else if (strstr (line, "--base64"))
175     ; /* FIXME */
176   else if (strstr (line, "--binary"))
177     ;
178   else
179     {
180       /* FIXME (autodetect encoding) */
181     }
182   return 0;
183 }
184
185
186 /* Called by libassuan for OUTPUT commands. */
187 static gpg_error_t
188 output_notify (assuan_context_t ctx, char *line)
189 {
190 /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
191   
192   (void)ctx;
193
194   if (strstr (line, "--armor"))
195     ; /* FIXME */
196   else if (strstr (line, "--base64"))
197     {
198       /* FIXME */
199     }
200   return 0;
201 }
202
203
204
205 \f
206 /*  RECIPIENT [--hidden] <userID>
207
208    Set the recipient for the encryption.  <userID> should be the
209    internal representation of the key; the server may accept any other
210    way of specification.  If this is a valid and trusted recipient the
211    server does respond with OK, otherwise the return is an ERR with
212    the reason why the recipient can't be used, the encryption will
213    then not be done for this recipient.  If the policy is not to
214    encrypt at all if not all recipients are valid, the client has to
215    take care of this.  All RECIPIENT commands are cumulative until a
216    RESET or an successful ENCRYPT command.  */
217 static gpg_error_t
218 cmd_recipient (assuan_context_t ctx, char *line)
219 {
220   ctrl_t ctrl = assuan_get_pointer (ctx);
221   gpg_error_t err;
222   int hidden;
223
224   hidden = has_option (line,"--hidden");
225   line = skip_options (line);
226
227   /* FIXME: Expand groups
228   if (opt.grouplist)
229     remusr = expand_group (rcpts);
230   else
231     remusr = rcpts;
232   */
233
234   err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden, 
235                             &ctrl->server_local->recplist);
236   
237   if (err)
238     log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
239   return err;
240 }
241
242
243 \f
244 /*  SIGNER <userID>
245
246    Set the signer's keys for the signature creation.  <userID> should
247    be the internal representation of the key; the server may accept
248    any other way of specification.  If this is a valid and usable
249    signing key the server does respond with OK, otherwise it returns
250    an ERR with the reason why the key can't be used, the signing will
251    then not be done for this key.  If the policy is not to sign at all
252    if not all signer keys are valid, the client has to take care of
253    this.  All SIGNER commands are cumulative until a RESET but they
254    are *not* reset by an SIGN command becuase it can be expected that
255    set of signers are used for more than one sign operation.
256
257    Note that this command returns an INV_RECP status which is a bit
258    strange, but they are very similar.  */
259 static gpg_error_t
260 cmd_signer (assuan_context_t ctx, char *line)
261 {
262   (void)ctx;
263   (void)line;
264   return gpg_error (GPG_ERR_NOT_SUPPORTED);
265 }
266
267
268 \f
269 /*  ENCRYPT 
270
271    Do the actual encryption process.  Takes the plaintext from the
272    INPUT command, writes the ciphertext to the file descriptor set
273    with the OUTPUT command, take the recipients from all the
274    recipients set so far with RECIPIENTS.
275
276    If this command fails the clients should try to delete all output
277    currently done or otherwise mark it as invalid.  GPG does ensure
278    that there won't be any security problem with leftover data on the
279    output in this case.
280
281    In most cases this command won't fail because most necessary checks
282    have been done while setting the recipients.  However some checks
283    can only be done right here and thus error may occur anyway (for
284    example, no recipients at all).
285
286    The input, output and message pipes are closed after this
287    command.  */
288 static gpg_error_t
289 cmd_encrypt (assuan_context_t ctx, char *line)
290 {
291   ctrl_t ctrl = assuan_get_pointer (ctx);
292   gpg_error_t err;
293   int inp_fd, out_fd;
294
295   (void)line; /* LINE is not used.  */
296
297   if ( !ctrl->server_local->recplist ) 
298     {
299       write_status_text (STATUS_NO_RECP, "0");
300       err = gpg_error (GPG_ERR_NO_USER_ID);
301       goto leave;
302     }
303
304   inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
305   if (inp_fd == -1)
306     {
307       err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
308       goto leave;
309     }
310   out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
311   if (out_fd == -1)
312     {
313       err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
314       goto leave;
315     }
316
317   /* Fixme: Check that we are using real files and not pipes if in
318      PGP-2 mode.  Do all the other checks we do in gpg.c for aEncr.
319      Maybe we should drop the PGP2 compatibility. */
320
321   
322   /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
323      from the default list. */
324
325   /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
326     
327   err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
328                        ctrl->server_local->recplist,
329                        out_fd);
330
331  leave:
332   /* Release the recipient list on success.  */
333   if (!err)
334     {
335       release_pk_list (ctrl->server_local->recplist);
336       ctrl->server_local->recplist = NULL;
337     }
338
339   /* Close and reset the fds. */
340   close_message_fd (ctrl);
341   assuan_close_input_fd (ctx);
342   assuan_close_output_fd (ctx);
343
344   if (err)
345     log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
346   return err;
347 }
348
349
350 \f
351 /*  DECRYPT
352
353     This performs the decrypt operation.  */
354 static gpg_error_t
355 cmd_decrypt (assuan_context_t ctx, char *line)
356 {
357   ctrl_t ctrl = assuan_get_pointer (ctx);
358   gpg_error_t err;
359   int inp_fd, out_fd;
360
361   (void)line; /* LINE is not used.  */
362
363   inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
364   if (inp_fd == -1)
365     return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
366   out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
367   if (out_fd == -1)
368     return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
369
370   glo_ctrl.lasterr = 0;
371   err = decrypt_message_fd (ctrl, inp_fd, out_fd);
372   if (!err)
373     err = glo_ctrl.lasterr;
374
375   /* Close and reset the fds. */
376   close_message_fd (ctrl);
377   assuan_close_input_fd (ctx);
378   assuan_close_output_fd (ctx);
379
380   if (err)
381     log_error ("command '%s' failed: %s\n", "DECRYPT", gpg_strerror (err));
382   return err;
383 }
384
385
386 \f
387 /*  VERIFY
388
389    This does a verify operation on the message send to the input-FD.
390    The result is written out using status lines.  If an output FD was
391    given, the signed text will be written to that.
392   
393    If the signature is a detached one, the server will inquire about
394    the signed material and the client must provide it.
395  */
396 static gpg_error_t
397 cmd_verify (assuan_context_t ctx, char *line)
398 {
399   int rc;
400   ctrl_t ctrl = assuan_get_pointer (ctx);
401   gnupg_fd_t fd = assuan_get_input_fd (ctx);
402   gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
403   estream_t out_fp = NULL;
404
405   /* FIXME: Revamp this code it is nearly to 3 years old and was only
406      intended as a quick test.  */
407   
408   (void)line;
409
410   if (fd == GNUPG_INVALID_FD)
411     return gpg_error (GPG_ERR_ASS_NO_INPUT);
412
413   if (out_fd != GNUPG_INVALID_FD)
414     {
415       out_fp = es_fdopen_nc (out_fd, "w");
416       if (!out_fp)
417         return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
418     }
419
420   log_debug ("WARNING: The server mode is WORK "
421              "iN PROGRESS and not ready for use\n");
422
423   rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);
424
425   es_fclose (out_fp);
426   close_message_fd (ctrl);
427   assuan_close_input_fd (ctx);
428   assuan_close_output_fd (ctx);
429
430   if (rc)
431     log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
432   return rc;
433 }
434
435
436 \f
437 /*  SIGN [--detached]
438
439    Sign the data set with the INPUT command and write it to the sink
440    set by OUTPUT.  With "--detached" specified, a detached signature
441    is created.  */
442 static gpg_error_t
443 cmd_sign (assuan_context_t ctx, char *line)
444 {
445   (void)ctx;
446   (void)line;
447   return gpg_error (GPG_ERR_NOT_SUPPORTED);
448 }
449
450
451 \f
452 /*  IMPORT
453
454   Import keys as read from the input-fd, return status message for
455   each imported one.  The import checks the validity of the key.  */
456 static gpg_error_t
457 cmd_import (assuan_context_t ctx, char *line)
458 {
459   (void)ctx;
460   (void)line;
461   return gpg_error (GPG_ERR_NOT_SUPPORTED);
462 }
463
464
465 \f
466 /*  EXPORT [--data [--armor|--base64]] [--] pattern
467
468    Similar to the --export command line command, this command exports
469    public keys matching PATTERN.  The output is send to the output fd
470    unless the --data option has been used in which case the output
471    gets send inline using regular data lines.  The options "--armor"
472    and "--base" ospecify an output format if "--data" has been used.
473    Recall that in general the output format is set with the OUTPUT
474    command.
475  */
476 static gpg_error_t
477 cmd_export (assuan_context_t ctx, char *line)
478 {
479   (void)ctx;
480   (void)line;
481   return gpg_error (GPG_ERR_NOT_SUPPORTED);
482 }
483
484
485 \f
486 /*  DELKEYS
487
488     Fixme
489 */
490 static gpg_error_t
491 cmd_delkeys (assuan_context_t ctx, char *line)
492 {
493   (void)ctx;
494   (void)line;
495   return gpg_error (GPG_ERR_NOT_SUPPORTED);
496 }
497
498
499 \f
500 /*  MESSAGE FD[=<n>]
501
502    Set the file descriptor to read a message which is used with
503    detached signatures.  */
504 static gpg_error_t
505 cmd_message (assuan_context_t ctx, char *line)
506 {
507   int rc;
508   gnupg_fd_t fd;
509   ctrl_t ctrl = assuan_get_pointer (ctx);
510
511   rc = assuan_command_parse_fd (ctx, line, &fd);
512   if (rc)
513     return rc;
514   if (fd == GNUPG_INVALID_FD)
515     return gpg_error (GPG_ERR_ASS_NO_INPUT);
516   ctrl->server_local->message_fd = fd;
517   return 0;
518 }
519
520
521 \f
522 /* LISTKEYS [<patterns>]
523    LISTSECRETKEYS [<patterns>]
524
525    fixme
526 */
527 static gpg_error_t
528 do_listkeys (assuan_context_t ctx, char *line, int mode)
529 {
530   (void)ctx;
531   (void)line;
532   (void)mode;
533
534   return gpg_error (GPG_ERR_NOT_SUPPORTED);
535 }
536
537
538 static gpg_error_t
539 cmd_listkeys (assuan_context_t ctx, char *line)
540 {
541   return do_listkeys (ctx, line, 3);
542 }
543
544
545 static gpg_error_t
546 cmd_listsecretkeys (assuan_context_t ctx, char *line)
547 {
548   return do_listkeys (ctx, line, 2);
549 }
550
551
552 \f
553 /* GENKEY
554
555    Read the parameters in native format from the input fd and create a
556    new OpenPGP key.
557  */
558 static gpg_error_t
559 cmd_genkey (assuan_context_t ctx, char *line)
560 {
561   (void)ctx;
562   (void)line;
563   return gpg_error (GPG_ERR_NOT_SUPPORTED);
564 }
565
566
567 /* GETINFO <what>
568
569    Multipurpose function to return a variety of information.
570    Supported values for WHAT are:
571
572      version     - Return the version of the program.
573      pid         - Return the process id of the server.
574
575  */
576 static gpg_error_t
577 cmd_getinfo (assuan_context_t ctx, char *line)
578 {
579   int rc;
580
581   if (!strcmp (line, "version"))
582     {
583       const char *s = VERSION;
584       rc = assuan_send_data (ctx, s, strlen (s));
585     }
586   else if (!strcmp (line, "pid"))
587     {
588       char numbuf[50];
589
590       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
591       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
592     }
593   else
594     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
595   return rc;
596 }
597
598 static const char hlp_passwd[] =
599   "PASSWD <userID>\n"
600   "\n"
601   "Change the passphrase of the secret key for USERID.";
602 static gpg_error_t
603 cmd_passwd (assuan_context_t ctx, char *line)
604 {
605   /* ctrl_t ctrl = assuan_get_pointer (ctx); */
606   gpg_error_t err;
607
608   (void)ctx;
609   line = skip_options (line);
610
611   err = gpg_error (GPG_ERR_NOT_SUPPORTED);
612
613   return err;
614 }
615
616
617
618 \f
619 /* Helper to register our commands with libassuan. */
620 static int
621 register_commands (assuan_context_t ctx)
622 {
623   static struct 
624   {
625     const char *name;
626     assuan_handler_t handler;
627     const char * const help;
628   } table[] = {
629     { "RECIPIENT",     cmd_recipient },
630     { "SIGNER",        cmd_signer    },
631     { "ENCRYPT",       cmd_encrypt   },
632     { "DECRYPT",       cmd_decrypt   },
633     { "VERIFY",        cmd_verify    },
634     { "SIGN",          cmd_sign      },
635     { "IMPORT",        cmd_import    },
636     { "EXPORT",        cmd_export    },
637     { "INPUT",         NULL          }, 
638     { "OUTPUT",        NULL          }, 
639     { "MESSAGE",       cmd_message   },
640     { "LISTKEYS",      cmd_listkeys  },
641     { "LISTSECRETKEYS",cmd_listsecretkeys },
642     { "GENKEY",        cmd_genkey    },
643     { "DELKEYS",       cmd_delkeys   },
644     { "GETINFO",       cmd_getinfo   },
645     { "PASSWD",        cmd_passwd,  hlp_passwd},
646     { NULL }
647   };
648   int i, rc;
649
650   for (i=0; table[i].name; i++)
651     {
652       rc = assuan_register_command (ctx, table[i].name,
653                                     table[i].handler, table[i].help);
654       if (rc)
655         return rc;
656     } 
657   return 0;
658 }
659
660
661
662 \f
663 /* Startup the server.  CTRL must have been allocated by the caller
664    and set to the default values. */
665 int
666 gpg_server (ctrl_t ctrl)
667 {
668   int rc;
669   int filedes[2];
670   assuan_context_t ctx = NULL;
671   static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
672                                VERSION " ready");
673
674   /* We use a pipe based server so that we can work from scripts.
675      assuan_init_pipe_server will automagically detect when we are
676      called with a socketpair and ignore FILEDES in this case.  */
677   filedes[0] = assuan_fdopen (0);
678   filedes[1] = assuan_fdopen (1);
679   rc = assuan_new (&ctx);
680   if (rc)
681     {
682       log_error ("failed to allocate the assuan context: %s\n",
683                  gpg_strerror (rc));
684       goto leave;
685     }
686   
687   rc = assuan_init_pipe_server (ctx, filedes);
688   if (rc)
689     {
690       log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
691       goto leave;
692     }
693
694   rc = register_commands (ctx);
695   if (rc)
696     {
697       log_error ("failed to the register commands with Assuan: %s\n",
698                  gpg_strerror(rc));
699       goto leave;
700     }
701
702   assuan_set_pointer (ctx, ctrl);
703   if (opt.verbose || opt.debug)
704     {
705       char *tmp = NULL;
706       const char *s1 = getenv ("GPG_AGENT_INFO");
707
708       tmp = xtryasprintf ("Home: %s\n"
709                           "Config: %s\n"
710                           "AgentInfo: %s\n"
711                           "%s",
712                           opt.homedir,
713                           "fixme: need config filename",
714                           s1?s1:"[not set]",
715                           hello);
716       if (tmp)
717         {
718           assuan_set_hello_line (ctx, tmp);
719           xfree (tmp);
720         }
721     }
722   else
723     assuan_set_hello_line (ctx, hello);
724   assuan_register_reset_notify (ctx, reset_notify);
725   assuan_register_input_notify (ctx, input_notify);
726   assuan_register_output_notify (ctx, output_notify);
727   assuan_register_option_handler (ctx, option_handler);
728
729   ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
730   if (!ctrl->server_local)
731     {
732       rc = gpg_error_from_syserror ();
733       goto leave;
734     }
735   ctrl->server_local->assuan_ctx = ctx;
736   ctrl->server_local->message_fd = GNUPG_INVALID_FD;
737
738   for (;;)
739     {
740       rc = assuan_accept (ctx);
741       if (rc == -1)
742         {
743           rc = 0;
744           break;
745         }
746       else if (rc)
747         {
748           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
749           break;
750         }
751       
752       rc = assuan_process (ctx);
753       if (rc)
754         {
755           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
756           continue;
757         }
758     }
759
760  leave:
761   if (ctrl->server_local)
762     {
763       release_pk_list (ctrl->server_local->recplist);
764
765       xfree (ctrl->server_local);
766       ctrl->server_local = NULL;
767     }
768   assuan_release (ctx);
769   return rc;
770 }
771