Adjust for assuan_register_command change.
[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 (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 (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 (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   FILE *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 = fdopen ( dup (FD2INT (out_fd)), "w");
416       if (!out_fp)
417         return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
418     }
419
420   log_debug ("WARNING: The server mode is WORK "
421              "iN PROGRESS and not ready for use\n");
422
423   /* Need to dup it because it might get closed and libassuan won't
424      know about it then. */
425   rc = gpg_verify (ctrl,
426                    dup ( FD2INT (fd)), 
427                    dup ( FD2INT (ctrl->server_local->message_fd)),
428                    out_fp);
429
430   if (out_fp)
431     fclose (out_fp);
432   close_message_fd (ctrl);
433   assuan_close_input_fd (ctx);
434   assuan_close_output_fd (ctx);
435
436   if (rc)
437     log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
438   return rc;
439 }
440
441
442 \f
443 /*  SIGN [--detached]
444
445    Sign the data set with the INPUT command and write it to the sink
446    set by OUTPUT.  With "--detached" specified, a detached signature
447    is created.  */
448 static gpg_error_t
449 cmd_sign (assuan_context_t ctx, char *line)
450 {
451   (void)ctx;
452   (void)line;
453   return gpg_error (GPG_ERR_NOT_SUPPORTED);
454 }
455
456
457 \f
458 /*  IMPORT
459
460   Import keys as read from the input-fd, return status message for
461   each imported one.  The import checks the validity of the key.  */
462 static gpg_error_t
463 cmd_import (assuan_context_t ctx, char *line)
464 {
465   (void)ctx;
466   (void)line;
467   return gpg_error (GPG_ERR_NOT_SUPPORTED);
468 }
469
470
471 \f
472 /*  EXPORT [--data [--armor|--base64]] [--] pattern
473
474    Similar to the --export command line command, this command exports
475    public keys matching PATTERN.  The output is send to the output fd
476    unless the --data option has been used in which case the output
477    gets send inline using regular data lines.  The options "--armor"
478    and "--base" ospecify an output format if "--data" has been used.
479    Recall that in general the output format is set with the OUTPUT
480    command.
481  */
482 static gpg_error_t
483 cmd_export (assuan_context_t ctx, char *line)
484 {
485   (void)ctx;
486   (void)line;
487   return gpg_error (GPG_ERR_NOT_SUPPORTED);
488 }
489
490
491 \f
492 /*  DELKEYS
493
494     Fixme
495 */
496 static gpg_error_t
497 cmd_delkeys (assuan_context_t ctx, char *line)
498 {
499   (void)ctx;
500   (void)line;
501   return gpg_error (GPG_ERR_NOT_SUPPORTED);
502 }
503
504
505 \f
506 /*  MESSAGE FD[=<n>]
507
508    Set the file descriptor to read a message which is used with
509    detached signatures.  */
510 static gpg_error_t
511 cmd_message (assuan_context_t ctx, char *line)
512 {
513   int rc;
514   gnupg_fd_t fd;
515   ctrl_t ctrl = assuan_get_pointer (ctx);
516
517   rc = assuan_command_parse_fd (ctx, line, &fd);
518   if (rc)
519     return rc;
520   if (fd == GNUPG_INVALID_FD)
521     return gpg_error (GPG_ERR_ASS_NO_INPUT);
522   ctrl->server_local->message_fd = fd;
523   return 0;
524 }
525
526
527 \f
528 /* LISTKEYS [<patterns>]
529    LISTSECRETKEYS [<patterns>]
530
531    fixme
532 */
533 static gpg_error_t
534 do_listkeys (assuan_context_t ctx, char *line, int mode)
535 {
536   (void)ctx;
537   (void)line;
538   (void)mode;
539
540   return gpg_error (GPG_ERR_NOT_SUPPORTED);
541 }
542
543
544 static gpg_error_t
545 cmd_listkeys (assuan_context_t ctx, char *line)
546 {
547   return do_listkeys (ctx, line, 3);
548 }
549
550
551 static gpg_error_t
552 cmd_listsecretkeys (assuan_context_t ctx, char *line)
553 {
554   return do_listkeys (ctx, line, 2);
555 }
556
557
558 \f
559 /* GENKEY
560
561    Read the parameters in native format from the input fd and create a
562    new OpenPGP key.
563  */
564 static gpg_error_t
565 cmd_genkey (assuan_context_t ctx, char *line)
566 {
567   (void)ctx;
568   (void)line;
569   return gpg_error (GPG_ERR_NOT_SUPPORTED);
570 }
571
572
573 /* GETINFO <what>
574
575    Multipurpose function to return a variety of information.
576    Supported values for WHAT are:
577
578      version     - Return the version of the program.
579      pid         - Return the process id of the server.
580
581  */
582 static gpg_error_t
583 cmd_getinfo (assuan_context_t ctx, char *line)
584 {
585   int rc;
586
587   if (!strcmp (line, "version"))
588     {
589       const char *s = VERSION;
590       rc = assuan_send_data (ctx, s, strlen (s));
591     }
592   else if (!strcmp (line, "pid"))
593     {
594       char numbuf[50];
595
596       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
597       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
598     }
599   else
600     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
601   return rc;
602 }
603
604
605 \f
606 /* Helper to register our commands with libassuan. */
607 static int
608 register_commands (assuan_context_t ctx)
609 {
610   static struct 
611   {
612     const char *name;
613     assuan_handler_t handler;
614   } table[] = {
615     { "RECIPIENT",     cmd_recipient },
616     { "SIGNER",        cmd_signer    },
617     { "ENCRYPT",       cmd_encrypt   },
618     { "DECRYPT",       cmd_decrypt   },
619     { "VERIFY",        cmd_verify    },
620     { "SIGN",          cmd_sign      },
621     { "IMPORT",        cmd_import    },
622     { "EXPORT",        cmd_export    },
623     { "INPUT",         NULL          }, 
624     { "OUTPUT",        NULL          }, 
625     { "MESSAGE",       cmd_message   },
626     { "LISTKEYS",      cmd_listkeys  },
627     { "LISTSECRETKEYS",cmd_listsecretkeys },
628     { "GENKEY",        cmd_genkey    },
629     { "DELKEYS",       cmd_delkeys   },
630     { "GETINFO",       cmd_getinfo   },
631     { NULL }
632   };
633   int i, rc;
634
635   for (i=0; table[i].name; i++)
636     {
637       rc = assuan_register_command (ctx, table[i].name, table[i].handler, NULL);
638       if (rc)
639         return rc;
640     } 
641   return 0;
642 }
643
644
645
646 \f
647 /* Startup the server.  CTRL must have been allocated by the caller
648    and set to the default values. */
649 int
650 gpg_server (ctrl_t ctrl)
651 {
652   int rc;
653   int filedes[2];
654   assuan_context_t ctx = NULL;
655   static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
656                                VERSION " ready");
657
658   /* We use a pipe based server so that we can work from scripts.
659      assuan_init_pipe_server will automagically detect when we are
660      called with a socketpair and ignore FILEDES in this case.  */
661   filedes[0] = 0;
662   filedes[1] = 1;
663   rc = assuan_new (&ctx);
664   if (rc)
665     {
666       log_error ("failed to allocate the assuan context: %s\n",
667                  gpg_strerror (rc));
668       goto leave;
669     }
670   
671   rc = assuan_init_pipe_server (ctx, filedes);
672   if (rc)
673     {
674       log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
675       goto leave;
676     }
677
678   rc = register_commands (ctx);
679   if (rc)
680     {
681       log_error ("failed to the register commands with Assuan: %s\n",
682                  gpg_strerror(rc));
683       goto leave;
684     }
685
686   assuan_set_pointer (ctx, ctrl);
687   if (opt.verbose || opt.debug)
688     {
689       char *tmp = NULL;
690       const char *s1 = getenv ("GPG_AGENT_INFO");
691
692       tmp = xtryasprintf ("Home: %s\n"
693                           "Config: %s\n"
694                           "AgentInfo: %s\n"
695                           "%s",
696                           opt.homedir,
697                           "fixme: need config filename",
698                           s1?s1:"[not set]",
699                           hello);
700       if (tmp)
701         {
702           assuan_set_hello_line (ctx, tmp);
703           xfree (tmp);
704         }
705     }
706   else
707     assuan_set_hello_line (ctx, hello);
708   assuan_register_reset_notify (ctx, reset_notify);
709   assuan_register_input_notify (ctx, input_notify);
710   assuan_register_output_notify (ctx, output_notify);
711   assuan_register_option_handler (ctx, option_handler);
712
713   ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
714   if (!ctrl->server_local)
715     {
716       rc = gpg_error_from_syserror ();
717       goto leave;
718     }
719   ctrl->server_local->assuan_ctx = ctx;
720   ctrl->server_local->message_fd = GNUPG_INVALID_FD;
721
722   if (DBG_ASSUAN)
723     assuan_set_log_stream (ctx, log_get_stream ());
724
725   for (;;)
726     {
727       rc = assuan_accept (ctx);
728       if (rc == -1)
729         {
730           rc = 0;
731           break;
732         }
733       else if (rc)
734         {
735           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
736           break;
737         }
738       
739       rc = assuan_process (ctx);
740       if (rc)
741         {
742           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
743           continue;
744         }
745     }
746
747  leave:
748   if (ctrl->server_local)
749     {
750       release_pk_list (ctrl->server_local->recplist);
751
752       xfree (ctrl->server_local);
753       ctrl->server_local = NULL;
754     }
755   assuan_release (ctx);
756   return rc;
757 }
758