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