2008-01-15 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / server.c
blobb9fe2a25e57f6cd09cbb08b7e01f732869f9f795
1 /* server.c - Server mode and main entry point
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
3 * 2007 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include <unistd.h>
30 #include <assuan.h>
32 #include "gpgsm.h"
33 #include "sysutils.h"
35 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
38 /* The filepointer for status message used in non-server mode */
39 static FILE *statusfp;
41 /* Data used to assuciate an Assuan context with local server data */
42 struct server_local_s {
43 assuan_context_t assuan_ctx;
44 int message_fd;
45 int list_internal;
46 int list_external;
47 int list_to_output; /* Write keylistings to the output fd. */
48 int enable_audit_log; /* Use an audit log. */
49 certlist_t recplist;
50 certlist_t signerlist;
51 certlist_t default_recplist; /* As set by main() - don't release. */
55 /* Cookie definition for assuan data line output. */
56 static ssize_t data_line_cookie_write (void *cookie,
57 const void *buffer, size_t size);
58 static int data_line_cookie_close (void *cookie);
59 static es_cookie_io_functions_t data_line_cookie_functions =
61 NULL,
62 data_line_cookie_write,
63 NULL,
64 data_line_cookie_close
70 /* Note that it is sufficient to allocate the target string D as
71 long as the source string S, i.e.: strlen(s)+1; */
72 static void
73 strcpy_escaped_plus (char *d, const char *s)
75 while (*s)
77 if (*s == '%' && s[1] && s[2])
79 s++;
80 *d++ = xtoi_2 (s);
81 s += 2;
83 else if (*s == '+')
84 *d++ = ' ', s++;
85 else
86 *d++ = *s++;
88 *d = 0;
92 /* Skip over options.
93 Blanks after the options are also removed. */
94 static char *
95 skip_options (const char *line)
97 while (spacep (line))
98 line++;
99 while ( *line == '-' && line[1] == '-' )
101 while (*line && !spacep (line))
102 line++;
103 while (spacep (line))
104 line++;
106 return (char*)line;
110 /* Check whether the option NAME appears in LINE */
111 static int
112 has_option (const char *line, const char *name)
114 const char *s;
115 int n = strlen (name);
117 s = strstr (line, name);
118 if (s && s >= skip_options (line))
119 return 0;
120 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
124 /* A write handler used by es_fopencookie to write assuan data
125 lines. */
126 static ssize_t
127 data_line_cookie_write (void *cookie, const void *buffer, size_t size)
129 assuan_context_t ctx = cookie;
131 if (assuan_send_data (ctx, buffer, size))
133 errno = EIO;
134 return -1;
137 return size;
140 static int
141 data_line_cookie_close (void *cookie)
143 assuan_context_t ctx = cookie;
145 if (assuan_send_data (ctx, NULL, 0))
147 errno = EIO;
148 return -1;
151 return 0;
155 static void
156 close_message_fd (ctrl_t ctrl)
158 if (ctrl->server_local->message_fd != -1)
160 close (ctrl->server_local->message_fd);
161 ctrl->server_local->message_fd = -1;
166 /* Start a new audit session if this has been enabled. */
167 static gpg_error_t
168 start_audit_session (ctrl_t ctrl)
170 audit_release (ctrl->audit);
171 ctrl->audit = NULL;
172 if (ctrl->server_local->enable_audit_log && !(ctrl->audit = audit_new ()) )
173 return gpg_error_from_syserror ();
175 return 0;
179 static int
180 option_handler (assuan_context_t ctx, const char *key, const char *value)
182 ctrl_t ctrl = assuan_get_pointer (ctx);
184 if (!strcmp (key, "include-certs"))
186 int i = *value? atoi (value) : -1;
187 if (ctrl->include_certs < -2)
188 return gpg_error (GPG_ERR_ASS_PARAMETER);
189 ctrl->include_certs = i;
191 else if (!strcmp (key, "display"))
193 if (opt.display)
194 free (opt.display);
195 opt.display = strdup (value);
196 if (!opt.display)
197 return out_of_core ();
199 else if (!strcmp (key, "ttyname"))
201 if (opt.ttyname)
202 free (opt.ttyname);
203 opt.ttyname = strdup (value);
204 if (!opt.ttyname)
205 return out_of_core ();
207 else if (!strcmp (key, "ttytype"))
209 if (opt.ttytype)
210 free (opt.ttytype);
211 opt.ttytype = strdup (value);
212 if (!opt.ttytype)
213 return out_of_core ();
215 else if (!strcmp (key, "lc-ctype"))
217 if (opt.lc_ctype)
218 free (opt.lc_ctype);
219 opt.lc_ctype = strdup (value);
220 if (!opt.lc_ctype)
221 return out_of_core ();
223 else if (!strcmp (key, "lc-messages"))
225 if (opt.lc_messages)
226 free (opt.lc_messages);
227 opt.lc_messages = strdup (value);
228 if (!opt.lc_messages)
229 return out_of_core ();
231 else if (!strcmp (key, "xauthority"))
233 if (opt.xauthority)
234 free (opt.xauthority);
235 opt.xauthority = strdup (value);
236 if (!opt.xauthority)
237 return out_of_core ();
239 else if (!strcmp (key, "pinentry-user-data"))
241 if (opt.pinentry_user_data)
242 free (opt.pinentry_user_data);
243 opt.pinentry_user_data = strdup (value);
244 if (!opt.pinentry_user_data)
245 return out_of_core ();
247 else if (!strcmp (key, "list-mode"))
249 int i = *value? atoi (value) : 0;
250 if (!i || i == 1) /* default and mode 1 */
252 ctrl->server_local->list_internal = 1;
253 ctrl->server_local->list_external = 0;
255 else if (i == 2)
257 ctrl->server_local->list_internal = 0;
258 ctrl->server_local->list_external = 1;
260 else if (i == 3)
262 ctrl->server_local->list_internal = 1;
263 ctrl->server_local->list_external = 1;
265 else
266 return gpg_error (GPG_ERR_ASS_PARAMETER);
268 else if (!strcmp (key, "list-to-output"))
270 int i = *value? atoi (value) : 0;
271 ctrl->server_local->list_to_output = i;
273 else if (!strcmp (key, "with-validation"))
275 int i = *value? atoi (value) : 0;
276 ctrl->with_validation = i;
278 else if (!strcmp (key, "validation-model"))
280 int i = gpgsm_parse_validation_model (value);
281 if ( i >= 0 && i <= 1 )
282 ctrl->validation_model = i;
283 else
284 return gpg_error (GPG_ERR_ASS_PARAMETER);
286 else if (!strcmp (key, "with-key-data"))
288 opt.with_key_data = 1;
290 else if (!strcmp (key, "enable-audit-log"))
292 int i = *value? atoi (value) : 0;
293 ctrl->server_local->enable_audit_log = i;
295 else
296 return gpg_error (GPG_ERR_UNKNOWN_OPTION);
298 return 0;
304 static void
305 reset_notify (assuan_context_t ctx)
307 ctrl_t ctrl = assuan_get_pointer (ctx);
309 gpgsm_release_certlist (ctrl->server_local->recplist);
310 gpgsm_release_certlist (ctrl->server_local->signerlist);
311 ctrl->server_local->recplist = NULL;
312 ctrl->server_local->signerlist = NULL;
313 close_message_fd (ctrl);
314 assuan_close_input_fd (ctx);
315 assuan_close_output_fd (ctx);
319 static void
320 input_notify (assuan_context_t ctx, const char *line)
322 ctrl_t ctrl = assuan_get_pointer (ctx);
324 ctrl->autodetect_encoding = 0;
325 ctrl->is_pem = 0;
326 ctrl->is_base64 = 0;
327 if (strstr (line, "--armor"))
328 ctrl->is_pem = 1;
329 else if (strstr (line, "--base64"))
330 ctrl->is_base64 = 1;
331 else if (strstr (line, "--binary"))
333 else
334 ctrl->autodetect_encoding = 1;
337 static void
338 output_notify (assuan_context_t ctx, const char *line)
340 ctrl_t ctrl = assuan_get_pointer (ctx);
342 ctrl->create_pem = 0;
343 ctrl->create_base64 = 0;
344 if (strstr (line, "--armor"))
345 ctrl->create_pem = 1;
346 else if (strstr (line, "--base64"))
347 ctrl->create_base64 = 1; /* just the raw output */
352 /* RECIPIENT <userID>
354 Set the recipient for the encryption. <userID> should be the
355 internal representation of the key; the server may accept any other
356 way of specification [we will support this]. If this is a valid and
357 trusted recipient the server does respond with OK, otherwise the
358 return is an ERR with the reason why the recipient can't be used,
359 the encryption will then not be done for this recipient. If the
360 policy is not to encrypt at all if not all recipients are valid, the
361 client has to take care of this. All RECIPIENT commands are
362 cumulative until a RESET or an successful ENCRYPT command. */
363 static int
364 cmd_recipient (assuan_context_t ctx, char *line)
366 ctrl_t ctrl = assuan_get_pointer (ctx);
367 int rc;
369 if (!ctrl->audit)
370 rc = start_audit_session (ctrl);
371 else
372 rc = 0;
374 if (!rc)
375 rc = gpgsm_add_to_certlist (ctrl, line, 0,
376 &ctrl->server_local->recplist, 0);
377 if (rc)
379 gpg_err_code_t r = gpg_err_code (rc);
380 gpgsm_status2 (ctrl, STATUS_INV_RECP,
381 r == -1? "1":
382 r == GPG_ERR_NO_PUBKEY? "1":
383 r == GPG_ERR_AMBIGUOUS_NAME? "2":
384 r == GPG_ERR_WRONG_KEY_USAGE? "3":
385 r == GPG_ERR_CERT_REVOKED? "4":
386 r == GPG_ERR_CERT_EXPIRED? "5":
387 r == GPG_ERR_NO_CRL_KNOWN? "6":
388 r == GPG_ERR_CRL_TOO_OLD? "7":
389 r == GPG_ERR_NO_POLICY_MATCH? "8":
390 r == GPG_ERR_MISSING_CERT? "11":
391 "0",
392 line, NULL);
395 return rc;
398 /* SIGNER <userID>
400 Set the signer's keys for the signature creation. <userID> should
401 be the internal representation of the key; the server may accept any
402 other way of specification [we will support this]. If this is a
403 valid and usable signing key the server does respond with OK,
404 otherwise it returns an ERR with the reason why the key can't be
405 used, the signing will then not be done for this key. If the policy
406 is not to sign at all if not all signer keys are valid, the client
407 has to take care of this. All SIGNER commands are cumulative until
408 a RESET but they are *not* reset by an SIGN command becuase it can
409 be expected that set of signers are used for more than one sign
410 operation.
412 Note that this command returns an INV_RECP status which is a bit
413 strange, but they are very similar. */
414 static int
415 cmd_signer (assuan_context_t ctx, char *line)
417 ctrl_t ctrl = assuan_get_pointer (ctx);
418 int rc;
420 rc = gpgsm_add_to_certlist (ctrl, line, 1,
421 &ctrl->server_local->signerlist, 0);
422 if (rc)
424 gpg_err_code_t r = gpg_err_code (rc);
425 gpgsm_status2 (ctrl, STATUS_INV_RECP,
426 r == -1? "1":
427 r == GPG_ERR_NO_PUBKEY? "1":
428 r == GPG_ERR_AMBIGUOUS_NAME? "2":
429 r == GPG_ERR_WRONG_KEY_USAGE? "3":
430 r == GPG_ERR_CERT_REVOKED? "4":
431 r == GPG_ERR_CERT_EXPIRED? "5":
432 r == GPG_ERR_NO_CRL_KNOWN? "6":
433 r == GPG_ERR_CRL_TOO_OLD? "7":
434 r == GPG_ERR_NO_POLICY_MATCH? "8":
435 r == GPG_ERR_NO_SECKEY? "9":
436 r == GPG_ERR_MISSING_CERT? "11":
437 "0",
438 line, NULL);
440 return rc;
444 /* ENCRYPT
446 Do the actual encryption process. Takes the plaintext from the INPUT
447 command, writes to the ciphertext to the file descriptor set with
448 the OUTPUT command, take the recipients form all the recipients set
449 so far. If this command fails the clients should try to delete all
450 output currently done or otherwise mark it as invalid. GPGSM does
451 ensure that there won't be any security problem with leftover data
452 on the output in this case.
454 This command should in general not fail, as all necessary checks
455 have been done while setting the recipients. The input and output
456 pipes are closed. */
457 static int
458 cmd_encrypt (assuan_context_t ctx, char *line)
460 ctrl_t ctrl = assuan_get_pointer (ctx);
461 certlist_t cl;
462 int inp_fd, out_fd;
463 FILE *out_fp;
464 int rc;
466 inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
467 if (inp_fd == -1)
468 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
469 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
470 if (out_fd == -1)
471 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
473 out_fp = fdopen (dup (out_fd), "w");
474 if (!out_fp)
475 return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
477 /* Now add all encrypt-to marked recipients from the default
478 list. */
479 rc = 0;
480 if (!opt.no_encrypt_to)
482 for (cl=ctrl->server_local->default_recplist; !rc && cl; cl = cl->next)
483 if (cl->is_encrypt_to)
484 rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert,
485 &ctrl->server_local->recplist, 1);
487 if (!rc)
488 rc = ctrl->audit? 0 : start_audit_session (ctrl);
489 if (!rc)
490 rc = gpgsm_encrypt (assuan_get_pointer (ctx),
491 ctrl->server_local->recplist,
492 inp_fd, out_fp);
493 fclose (out_fp);
495 gpgsm_release_certlist (ctrl->server_local->recplist);
496 ctrl->server_local->recplist = NULL;
497 /* Close and reset the fd */
498 close_message_fd (ctrl);
499 assuan_close_input_fd (ctx);
500 assuan_close_output_fd (ctx);
501 return rc;
505 /* DECRYPT
507 This performs the decrypt operation after doing some check on the
508 internal state. (e.g. that only needed data has been set). Because
509 it utilizes the GPG-Agent for the session key decryption, there is
510 no need to ask the client for a protecting passphrase - GpgAgent
511 does take care of this by requesting this from the user. */
512 static int
513 cmd_decrypt (assuan_context_t ctx, char *line)
515 ctrl_t ctrl = assuan_get_pointer (ctx);
516 int inp_fd, out_fd;
517 FILE *out_fp;
518 int rc;
520 inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
521 if (inp_fd == -1)
522 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
523 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
524 if (out_fd == -1)
525 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
527 out_fp = fdopen (dup(out_fd), "w");
528 if (!out_fp)
529 return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
531 rc = start_audit_session (ctrl);
532 if (!rc)
533 rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
534 fclose (out_fp);
536 /* close and reset the fd */
537 close_message_fd (ctrl);
538 assuan_close_input_fd (ctx);
539 assuan_close_output_fd (ctx);
541 return rc;
545 /* VERIFY
547 This does a verify operation on the message send to the input-FD.
548 The result is written out using status lines. If an output FD was
549 given, the signed text will be written to that.
551 If the signature is a detached one, the server will inquire about
552 the signed material and the client must provide it.
554 static int
555 cmd_verify (assuan_context_t ctx, char *line)
557 int rc;
558 ctrl_t ctrl = assuan_get_pointer (ctx);
559 int fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
560 int out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
561 FILE *out_fp = NULL;
563 if (fd == -1)
564 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
566 if (out_fd != -1)
568 out_fp = fdopen ( dup(out_fd), "w");
569 if (!out_fp)
570 return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
573 rc = start_audit_session (ctrl);
574 if (!rc)
575 rc = gpgsm_verify (assuan_get_pointer (ctx), fd,
576 ctrl->server_local->message_fd, out_fp);
577 if (out_fp)
578 fclose (out_fp);
580 /* close and reset the fd */
581 close_message_fd (ctrl);
582 assuan_close_input_fd (ctx);
583 assuan_close_output_fd (ctx);
585 return rc;
589 /* SIGN [--detached]
591 Sign the data set with the INPUT command and write it to the sink
592 set by OUTPUT. With "--detached" specified, a detached signature is
593 created (surprise). */
594 static int
595 cmd_sign (assuan_context_t ctx, char *line)
597 ctrl_t ctrl = assuan_get_pointer (ctx);
598 int inp_fd, out_fd;
599 FILE *out_fp;
600 int detached;
601 int rc;
603 inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
604 if (inp_fd == -1)
605 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
606 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
607 if (out_fd == -1)
608 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
610 detached = has_option (line, "--detached");
612 out_fp = fdopen ( dup(out_fd), "w");
613 if (!out_fp)
614 return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
616 rc = start_audit_session (ctrl);
617 if (!rc)
618 rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
619 inp_fd, detached, out_fp);
620 fclose (out_fp);
622 /* close and reset the fd */
623 close_message_fd (ctrl);
624 assuan_close_input_fd (ctx);
625 assuan_close_output_fd (ctx);
627 return rc;
631 /* IMPORT
633 Import the certificates read form the input-fd, return status
634 message for each imported one. The import checks the validity of
635 the certificate but not of the entire chain. It is possible to
636 import expired certificates. */
637 static int
638 cmd_import (assuan_context_t ctx, char *line)
640 ctrl_t ctrl = assuan_get_pointer (ctx);
641 int rc;
642 int fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
644 if (fd == -1)
645 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
647 rc = gpgsm_import (assuan_get_pointer (ctx), fd);
649 /* close and reset the fd */
650 close_message_fd (ctrl);
651 assuan_close_input_fd (ctx);
652 assuan_close_output_fd (ctx);
654 return rc;
658 /* EXPORT [--data [--armor|--base64]] [--] pattern
662 static int
663 cmd_export (assuan_context_t ctx, char *line)
665 ctrl_t ctrl = assuan_get_pointer (ctx);
666 char *p;
667 strlist_t list, sl;
668 int use_data;
670 use_data = has_option (line, "--data");
672 if (use_data)
674 /* We need to override any possible setting done by an OUTPUT command. */
675 ctrl->create_pem = has_option (line, "--armor");
676 ctrl->create_base64 = has_option (line, "--base64");
679 line = skip_options (line);
681 /* Break the line down into an strlist_t. */
682 list = NULL;
683 for (p=line; *p; line = p)
685 while (*p && *p != ' ')
686 p++;
687 if (*p)
688 *p++ = 0;
689 if (*line)
691 sl = xtrymalloc (sizeof *sl + strlen (line));
692 if (!sl)
694 free_strlist (list);
695 return out_of_core ();
697 sl->flags = 0;
698 strcpy_escaped_plus (sl->d, line);
699 sl->next = list;
700 list = sl;
704 if (use_data)
706 estream_t stream;
708 stream = es_fopencookie (ctx, "w", data_line_cookie_functions);
709 if (!stream)
711 free_strlist (list);
712 return set_error (GPG_ERR_ASS_GENERAL,
713 "error setting up a data stream");
715 gpgsm_export (ctrl, list, NULL, stream);
716 es_fclose (stream);
718 else
720 int fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
721 FILE *out_fp;
723 if (fd == -1)
725 free_strlist (list);
726 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
728 out_fp = fdopen ( dup(fd), "w");
729 if (!out_fp)
731 free_strlist (list);
732 return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
735 gpgsm_export (ctrl, list, out_fp, NULL);
736 fclose (out_fp);
739 free_strlist (list);
740 /* Close and reset the fds. */
741 close_message_fd (ctrl);
742 assuan_close_input_fd (ctx);
743 assuan_close_output_fd (ctx);
744 return 0;
748 static int
749 cmd_delkeys (assuan_context_t ctx, char *line)
751 ctrl_t ctrl = assuan_get_pointer (ctx);
752 char *p;
753 strlist_t list, sl;
754 int rc;
756 /* break the line down into an strlist_t */
757 list = NULL;
758 for (p=line; *p; line = p)
760 while (*p && *p != ' ')
761 p++;
762 if (*p)
763 *p++ = 0;
764 if (*line)
766 sl = xtrymalloc (sizeof *sl + strlen (line));
767 if (!sl)
769 free_strlist (list);
770 return out_of_core ();
772 sl->flags = 0;
773 strcpy_escaped_plus (sl->d, line);
774 sl->next = list;
775 list = sl;
779 rc = gpgsm_delete (ctrl, list);
780 free_strlist (list);
782 /* close and reset the fd */
783 close_message_fd (ctrl);
784 assuan_close_input_fd (ctx);
785 assuan_close_output_fd (ctx);
787 return rc;
792 /* MESSAGE FD=<n>
794 Set the file descriptor to read a message which is used with
795 detached signatures */
796 static int
797 cmd_message (assuan_context_t ctx, char *line)
799 int rc;
800 gnupg_fd_t sysfd;
801 int fd;
802 ctrl_t ctrl = assuan_get_pointer (ctx);
804 rc = assuan_command_parse_fd (ctx, line, &sysfd);
805 if (rc)
806 return rc;
807 fd = translate_sys2libc_fd (sysfd, 0);
808 if (fd == -1)
809 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
810 ctrl->server_local->message_fd = fd;
811 return 0;
814 /* LISTKEYS [<patterns>]
815 DUMPKEYS [<patterns>]
816 LISTSECRETKEYS [<patterns>]
817 DUMPSECRETKEYS [<patterns>]
819 static int
820 do_listkeys (assuan_context_t ctx, char *line, int mode)
822 ctrl_t ctrl = assuan_get_pointer (ctx);
823 estream_t fp;
824 char *p;
825 strlist_t list, sl;
826 unsigned int listmode;
827 gpg_error_t err;
829 /* Break the line down into an strlist. */
830 list = NULL;
831 for (p=line; *p; line = p)
833 while (*p && *p != ' ')
834 p++;
835 if (*p)
836 *p++ = 0;
837 if (*line)
839 sl = xtrymalloc (sizeof *sl + strlen (line));
840 if (!sl)
842 free_strlist (list);
843 return out_of_core ();
845 sl->flags = 0;
846 strcpy_escaped_plus (sl->d, line);
847 sl->next = list;
848 list = sl;
852 if (ctrl->server_local->list_to_output)
854 int outfd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
856 if ( outfd == -1 )
857 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
858 fp = es_fdopen ( dup (outfd), "w");
859 if (!fp)
860 return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen() failed");
862 else
864 fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
865 if (!fp)
866 return set_error (GPG_ERR_ASS_GENERAL,
867 "error setting up a data stream");
870 ctrl->with_colons = 1;
871 listmode = mode;
872 if (ctrl->server_local->list_internal)
873 listmode |= (1<<6);
874 if (ctrl->server_local->list_external)
875 listmode |= (1<<7);
876 err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode);
877 free_strlist (list);
878 es_fclose (fp);
879 if (ctrl->server_local->list_to_output)
880 assuan_close_output_fd (ctx);
881 return err;
884 static int
885 cmd_listkeys (assuan_context_t ctx, char *line)
887 return do_listkeys (ctx, line, 3);
890 static int
891 cmd_dumpkeys (assuan_context_t ctx, char *line)
893 return do_listkeys (ctx, line, 259);
896 static int
897 cmd_listsecretkeys (assuan_context_t ctx, char *line)
899 return do_listkeys (ctx, line, 2);
902 static int
903 cmd_dumpsecretkeys (assuan_context_t ctx, char *line)
905 return do_listkeys (ctx, line, 258);
909 /* GENKEY
911 Read the parameters in native format from the input fd and write a
912 certificate request to the output.
914 static int
915 cmd_genkey (assuan_context_t ctx, char *line)
917 ctrl_t ctrl = assuan_get_pointer (ctx);
918 int inp_fd, out_fd;
919 FILE *out_fp;
920 int rc;
921 estream_t in_stream;
923 inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
924 if (inp_fd == -1)
925 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
926 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
927 if (out_fd == -1)
928 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
930 in_stream = es_fdopen_nc (inp_fd, "r");
931 if (!in_stream)
932 return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen failed");
934 out_fp = fdopen ( dup(out_fd), "w");
935 if (!out_fp)
937 es_fclose (in_stream);
938 return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
940 rc = gpgsm_genkey (ctrl, in_stream, out_fp);
941 fclose (out_fp);
943 /* close and reset the fds */
944 assuan_close_input_fd (ctx);
945 assuan_close_output_fd (ctx);
947 return rc;
952 /* GETAUDITLOG [--data] [--html]
954 !!!WORK in PROGRESS!!!
956 If --data is used, the output is send using D-lines and not to the
957 source given by an OUTPUT command.
959 If --html is used the output is formated as an XHTML block. This is
960 designed to be incorporated into a HTML document.
962 static int
963 cmd_getauditlog (assuan_context_t ctx, char *line)
965 ctrl_t ctrl = assuan_get_pointer (ctx);
966 int out_fd;
967 estream_t out_stream;
968 int opt_data, opt_html;
969 int rc;
971 opt_data = has_option (line, "--data");
972 opt_html = has_option (line, "--html");
973 line = skip_options (line);
975 if (!ctrl->audit)
976 return gpg_error (GPG_ERR_NO_DATA);
978 if (opt_data)
980 out_stream = es_fopencookie (ctx, "w", data_line_cookie_functions);
981 if (!out_stream)
982 return set_error (GPG_ERR_ASS_GENERAL,
983 "error setting up a data stream");
985 else
987 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
988 if (out_fd == -1)
989 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
991 out_stream = es_fdopen_nc ( dup (out_fd), "w");
992 if (!out_stream)
994 return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen() failed");
998 audit_print_result (ctrl->audit, out_stream, opt_html);
999 rc = 0;
1001 es_fclose (out_stream);
1003 /* Close and reset the fd. */
1004 if (!opt_data)
1005 assuan_close_output_fd (ctx);
1006 return rc;
1013 /* Tell the assuan library about our commands */
1014 static int
1015 register_commands (assuan_context_t ctx)
1017 static struct {
1018 const char *name;
1019 int (*handler)(assuan_context_t, char *line);
1020 } table[] = {
1021 { "RECIPIENT", cmd_recipient },
1022 { "SIGNER", cmd_signer },
1023 { "ENCRYPT", cmd_encrypt },
1024 { "DECRYPT", cmd_decrypt },
1025 { "VERIFY", cmd_verify },
1026 { "SIGN", cmd_sign },
1027 { "IMPORT", cmd_import },
1028 { "EXPORT", cmd_export },
1029 { "INPUT", NULL },
1030 { "OUTPUT", NULL },
1031 { "MESSAGE", cmd_message },
1032 { "LISTKEYS", cmd_listkeys },
1033 { "DUMPKEYS", cmd_dumpkeys },
1034 { "LISTSECRETKEYS",cmd_listsecretkeys },
1035 { "DUMPSECRETKEYS",cmd_dumpsecretkeys },
1036 { "GENKEY", cmd_genkey },
1037 { "DELKEYS", cmd_delkeys },
1038 { "GETAUDITLOG", cmd_getauditlog },
1039 { NULL }
1041 int i, rc;
1043 for (i=0; table[i].name; i++)
1045 rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1046 if (rc)
1047 return rc;
1049 return 0;
1052 /* Startup the server. DEFAULT_RECPLIST is the list of recipients as
1053 set from the command line or config file. We only require those
1054 marked as encrypt-to. */
1055 void
1056 gpgsm_server (certlist_t default_recplist)
1058 int rc;
1059 int filedes[2];
1060 assuan_context_t ctx;
1061 struct server_control_s ctrl;
1062 static const char hello[] = ("GNU Privacy Guard's S/M server "
1063 VERSION " ready");
1065 memset (&ctrl, 0, sizeof ctrl);
1066 gpgsm_init_default_ctrl (&ctrl);
1068 /* We use a pipe based server so that we can work from scripts.
1069 assuan_init_pipe_server will automagically detect when we are
1070 called with a socketpair and ignore FIELDES in this case. */
1071 filedes[0] = 0;
1072 filedes[1] = 1;
1073 rc = assuan_init_pipe_server (&ctx, filedes);
1074 if (rc)
1076 log_error ("failed to initialize the server: %s\n",
1077 gpg_strerror (rc));
1078 gpgsm_exit (2);
1080 rc = register_commands (ctx);
1081 if (rc)
1083 log_error ("failed to the register commands with Assuan: %s\n",
1084 gpg_strerror(rc));
1085 gpgsm_exit (2);
1087 if (opt.verbose || opt.debug)
1089 char *tmp = NULL;
1090 const char *s1 = getenv ("GPG_AGENT_INFO");
1091 const char *s2 = getenv ("DIRMNGR_INFO");
1093 if (asprintf (&tmp,
1094 "Home: %s\n"
1095 "Config: %s\n"
1096 "AgentInfo: %s\n"
1097 "DirmngrInfo: %s\n"
1098 "%s",
1099 opt.homedir,
1100 opt.config_filename,
1101 s1?s1:"[not set]",
1102 s2?s2:"[not set]",
1103 hello) > 0)
1105 assuan_set_hello_line (ctx, tmp);
1106 free (tmp);
1109 else
1110 assuan_set_hello_line (ctx, hello);
1112 assuan_register_reset_notify (ctx, reset_notify);
1113 assuan_register_input_notify (ctx, input_notify);
1114 assuan_register_output_notify (ctx, output_notify);
1115 assuan_register_option_handler (ctx, option_handler);
1117 assuan_set_pointer (ctx, &ctrl);
1118 ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1119 ctrl.server_local->assuan_ctx = ctx;
1120 ctrl.server_local->message_fd = -1;
1121 ctrl.server_local->list_internal = 1;
1122 ctrl.server_local->list_external = 0;
1123 ctrl.server_local->default_recplist = default_recplist;
1125 if (DBG_ASSUAN)
1126 assuan_set_log_stream (ctx, log_get_stream ());
1128 for (;;)
1130 rc = assuan_accept (ctx);
1131 if (rc == -1)
1133 break;
1135 else if (rc)
1137 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1138 break;
1141 rc = assuan_process (ctx);
1142 if (rc)
1144 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1145 continue;
1149 gpgsm_release_certlist (ctrl.server_local->recplist);
1150 ctrl.server_local->recplist = NULL;
1151 gpgsm_release_certlist (ctrl.server_local->signerlist);
1152 ctrl.server_local->signerlist = NULL;
1153 xfree (ctrl.server_local);
1155 audit_release (ctrl.audit);
1156 ctrl.audit = NULL;
1158 assuan_deinit_server (ctx);
1163 gpg_error_t
1164 gpgsm_status2 (ctrl_t ctrl, int no, ...)
1166 gpg_error_t err = 0;
1167 va_list arg_ptr;
1168 const char *text;
1170 va_start (arg_ptr, no);
1172 if (ctrl->no_server && ctrl->status_fd == -1)
1173 ; /* No status wanted. */
1174 else if (ctrl->no_server)
1176 if (!statusfp)
1178 if (ctrl->status_fd == 1)
1179 statusfp = stdout;
1180 else if (ctrl->status_fd == 2)
1181 statusfp = stderr;
1182 else
1183 statusfp = fdopen (ctrl->status_fd, "w");
1185 if (!statusfp)
1187 log_fatal ("can't open fd %d for status output: %s\n",
1188 ctrl->status_fd, strerror(errno));
1192 fputs ("[GNUPG:] ", statusfp);
1193 fputs (get_status_string (no), statusfp);
1195 while ( (text = va_arg (arg_ptr, const char*) ))
1197 putc ( ' ', statusfp );
1198 for (; *text; text++)
1200 if (*text == '\n')
1201 fputs ( "\\n", statusfp );
1202 else if (*text == '\r')
1203 fputs ( "\\r", statusfp );
1204 else
1205 putc ( *(const byte *)text, statusfp );
1208 putc ('\n', statusfp);
1209 fflush (statusfp);
1211 else
1213 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1214 char buf[950], *p;
1215 size_t n;
1217 p = buf;
1218 n = 0;
1219 while ( (text = va_arg (arg_ptr, const char *)) )
1221 if (n)
1223 *p++ = ' ';
1224 n++;
1226 for ( ; *text && n < DIM (buf)-2; n++)
1227 *p++ = *text++;
1229 *p = 0;
1230 err = assuan_write_status (ctx, get_status_string (no), buf);
1233 va_end (arg_ptr);
1234 return err;
1237 gpg_error_t
1238 gpgsm_status (ctrl_t ctrl, int no, const char *text)
1240 return gpgsm_status2 (ctrl, no, text, NULL);
1243 gpg_error_t
1244 gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text,
1245 gpg_err_code_t ec)
1247 char buf[30];
1249 sprintf (buf, "%u", (unsigned int)ec);
1250 if (text)
1251 return gpgsm_status2 (ctrl, no, text, buf, NULL);
1252 else
1253 return gpgsm_status2 (ctrl, no, buf, NULL);