1 /* server.c - Server mode and main entry point
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
3 * 2007, 2008, 2009 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/>.
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
;
47 int list_to_output
; /* Write keylistings to the output fd. */
48 int enable_audit_log
; /* Use an audit log. */
50 certlist_t signerlist
;
51 certlist_t default_recplist
; /* As set by main() - don't release. */
52 int allow_pinentry_notify
; /* Set if pinentry notifications should
53 be passed back to the client. */
54 int no_encrypt_to
; /* Local version of option. */
58 /* Cookie definition for assuan data line output. */
59 static ssize_t
data_line_cookie_write (void *cookie
,
60 const void *buffer
, size_t size
);
61 static int data_line_cookie_close (void *cookie
);
62 static es_cookie_io_functions_t data_line_cookie_functions
=
65 data_line_cookie_write
,
67 data_line_cookie_close
72 static int command_has_option (const char *cmd
, const char *cmdopt
);
77 /* Note that it is sufficient to allocate the target string D as
78 long as the source string S, i.e.: strlen(s)+1; */
80 strcpy_escaped_plus (char *d
, const char *s
)
84 if (*s
== '%' && s
[1] && s
[2])
100 Blanks after the options are also removed. */
102 skip_options (const char *line
)
104 while (spacep (line
))
106 while ( *line
== '-' && line
[1] == '-' )
108 while (*line
&& !spacep (line
))
110 while (spacep (line
))
117 /* Check whether the option NAME appears in LINE */
119 has_option (const char *line
, const char *name
)
122 int n
= strlen (name
);
124 s
= strstr (line
, name
);
125 if (s
&& s
>= skip_options (line
))
127 return (s
&& (s
== line
|| spacep (s
-1)) && (!s
[n
] || spacep (s
+n
)));
131 /* A write handler used by es_fopencookie to write assuan data
134 data_line_cookie_write (void *cookie
, const void *buffer
, size_t size
)
136 assuan_context_t ctx
= cookie
;
138 if (assuan_send_data (ctx
, buffer
, size
))
148 data_line_cookie_close (void *cookie
)
150 assuan_context_t ctx
= cookie
;
152 if (assuan_send_data (ctx
, NULL
, 0))
163 close_message_fd (ctrl_t ctrl
)
165 if (ctrl
->server_local
->message_fd
!= -1)
167 close (ctrl
->server_local
->message_fd
);
168 ctrl
->server_local
->message_fd
= -1;
173 /* Start a new audit session if this has been enabled. */
175 start_audit_session (ctrl_t ctrl
)
177 audit_release (ctrl
->audit
);
179 if (ctrl
->server_local
->enable_audit_log
&& !(ctrl
->audit
= audit_new ()) )
180 return gpg_error_from_syserror ();
187 option_handler (assuan_context_t ctx
, const char *key
, const char *value
)
189 ctrl_t ctrl
= assuan_get_pointer (ctx
);
192 if (!strcmp (key
, "putenv"))
194 /* Change the session's environment to be used for the
195 Pinentry. Valid values are:
196 <NAME> Delete envvar NAME
197 <KEY>= Set envvar NAME to the empty string
198 <KEY>=<VALUE> Set envvar NAME to VALUE
200 err
= session_env_putenv (opt
.session_env
, value
);
202 else if (!strcmp (key
, "display"))
204 err
= session_env_setenv (opt
.session_env
, "DISPLAY", value
);
206 else if (!strcmp (key
, "ttyname"))
208 err
= session_env_setenv (opt
.session_env
, "GPG_TTY", value
);
210 else if (!strcmp (key
, "ttytype"))
212 err
= session_env_setenv (opt
.session_env
, "TERM", value
);
214 else if (!strcmp (key
, "lc-ctype"))
216 xfree (opt
.lc_ctype
);
217 opt
.lc_ctype
= xtrystrdup (value
);
219 err
= gpg_error_from_syserror ();
221 else if (!strcmp (key
, "lc-messages"))
223 xfree (opt
.lc_messages
);
224 opt
.lc_messages
= xtrystrdup (value
);
225 if (!opt
.lc_messages
)
226 err
= gpg_error_from_syserror ();
228 else if (!strcmp (key
, "xauthority"))
230 err
= session_env_setenv (opt
.session_env
, "XAUTHORITY", value
);
232 else if (!strcmp (key
, "pinentry-user-data"))
234 err
= session_env_setenv (opt
.session_env
, "PINENTRY_USER_DATA", value
);
236 else if (!strcmp (key
, "include-certs"))
238 int i
= *value
? atoi (value
) : -1;
239 if (ctrl
->include_certs
< -2)
240 err
= gpg_error (GPG_ERR_ASS_PARAMETER
);
242 ctrl
->include_certs
= i
;
244 else if (!strcmp (key
, "list-mode"))
246 int i
= *value
? atoi (value
) : 0;
247 if (!i
|| i
== 1) /* default and mode 1 */
249 ctrl
->server_local
->list_internal
= 1;
250 ctrl
->server_local
->list_external
= 0;
254 ctrl
->server_local
->list_internal
= 0;
255 ctrl
->server_local
->list_external
= 1;
259 ctrl
->server_local
->list_internal
= 1;
260 ctrl
->server_local
->list_external
= 1;
263 err
= gpg_error (GPG_ERR_ASS_PARAMETER
);
265 else if (!strcmp (key
, "list-to-output"))
267 int i
= *value
? atoi (value
) : 0;
268 ctrl
->server_local
->list_to_output
= i
;
270 else if (!strcmp (key
, "with-validation"))
272 int i
= *value
? atoi (value
) : 0;
273 ctrl
->with_validation
= i
;
275 else if (!strcmp (key
, "validation-model"))
277 int i
= gpgsm_parse_validation_model (value
);
278 if ( i
>= 0 && i
<= 1 )
279 ctrl
->validation_model
= i
;
281 err
= gpg_error (GPG_ERR_ASS_PARAMETER
);
283 else if (!strcmp (key
, "with-key-data"))
285 opt
.with_key_data
= 1;
287 else if (!strcmp (key
, "enable-audit-log"))
289 int i
= *value
? atoi (value
) : 0;
290 ctrl
->server_local
->enable_audit_log
= i
;
292 else if (!strcmp (key
, "allow-pinentry-notify"))
294 ctrl
->server_local
->allow_pinentry_notify
= 1;
296 else if (!strcmp (key
, "with-ephemeral-keys"))
298 int i
= *value
? atoi (value
) : 0;
299 ctrl
->with_ephemeral_keys
= i
;
301 else if (!strcmp (key
, "no-encrypt-to"))
303 ctrl
->server_local
->no_encrypt_to
= 1;
306 err
= gpg_error (GPG_ERR_UNKNOWN_OPTION
);
313 reset_notify (assuan_context_t ctx
)
315 ctrl_t ctrl
= assuan_get_pointer (ctx
);
317 gpgsm_release_certlist (ctrl
->server_local
->recplist
);
318 gpgsm_release_certlist (ctrl
->server_local
->signerlist
);
319 ctrl
->server_local
->recplist
= NULL
;
320 ctrl
->server_local
->signerlist
= NULL
;
321 close_message_fd (ctrl
);
322 assuan_close_input_fd (ctx
);
323 assuan_close_output_fd (ctx
);
328 input_notify (assuan_context_t ctx
, const char *line
)
330 ctrl_t ctrl
= assuan_get_pointer (ctx
);
332 ctrl
->autodetect_encoding
= 0;
335 if (strstr (line
, "--armor"))
337 else if (strstr (line
, "--base64"))
339 else if (strstr (line
, "--binary"))
342 ctrl
->autodetect_encoding
= 1;
346 output_notify (assuan_context_t ctx
, const char *line
)
348 ctrl_t ctrl
= assuan_get_pointer (ctx
);
350 ctrl
->create_pem
= 0;
351 ctrl
->create_base64
= 0;
352 if (strstr (line
, "--armor"))
353 ctrl
->create_pem
= 1;
354 else if (strstr (line
, "--base64"))
355 ctrl
->create_base64
= 1; /* just the raw output */
360 /* RECIPIENT <userID>
362 Set the recipient for the encryption. <userID> should be the
363 internal representation of the key; the server may accept any other
364 way of specification [we will support this]. If this is a valid and
365 trusted recipient the server does respond with OK, otherwise the
366 return is an ERR with the reason why the recipient can't be used,
367 the encryption will then not be done for this recipient. If the
368 policy is not to encrypt at all if not all recipients are valid, the
369 client has to take care of this. All RECIPIENT commands are
370 cumulative until a RESET or an successful ENCRYPT command. */
372 cmd_recipient (assuan_context_t ctx
, char *line
)
374 ctrl_t ctrl
= assuan_get_pointer (ctx
);
378 rc
= start_audit_session (ctrl
);
383 rc
= gpgsm_add_to_certlist (ctrl
, line
, 0,
384 &ctrl
->server_local
->recplist
, 0);
387 gpg_err_code_t r
= gpg_err_code (rc
);
388 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
390 r
== GPG_ERR_NO_PUBKEY
? "1":
391 r
== GPG_ERR_AMBIGUOUS_NAME
? "2":
392 r
== GPG_ERR_WRONG_KEY_USAGE
? "3":
393 r
== GPG_ERR_CERT_REVOKED
? "4":
394 r
== GPG_ERR_CERT_EXPIRED
? "5":
395 r
== GPG_ERR_NO_CRL_KNOWN
? "6":
396 r
== GPG_ERR_CRL_TOO_OLD
? "7":
397 r
== GPG_ERR_NO_POLICY_MATCH
? "8":
398 r
== GPG_ERR_MISSING_CERT
? "11":
408 Set the signer's keys for the signature creation. <userID> should
409 be the internal representation of the key; the server may accept any
410 other way of specification [we will support this]. If this is a
411 valid and usable signing key the server does respond with OK,
412 otherwise it returns an ERR with the reason why the key can't be
413 used, the signing will then not be done for this key. If the policy
414 is not to sign at all if not all signer keys are valid, the client
415 has to take care of this. All SIGNER commands are cumulative until
416 a RESET but they are *not* reset by an SIGN command becuase it can
417 be expected that set of signers are used for more than one sign
420 Note that this command returns an INV_RECP status which is a bit
421 strange, but they are very similar. */
423 cmd_signer (assuan_context_t ctx
, char *line
)
425 ctrl_t ctrl
= assuan_get_pointer (ctx
);
428 rc
= gpgsm_add_to_certlist (ctrl
, line
, 1,
429 &ctrl
->server_local
->signerlist
, 0);
432 gpg_err_code_t r
= gpg_err_code (rc
);
433 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
435 r
== GPG_ERR_NO_PUBKEY
? "1":
436 r
== GPG_ERR_AMBIGUOUS_NAME
? "2":
437 r
== GPG_ERR_WRONG_KEY_USAGE
? "3":
438 r
== GPG_ERR_CERT_REVOKED
? "4":
439 r
== GPG_ERR_CERT_EXPIRED
? "5":
440 r
== GPG_ERR_NO_CRL_KNOWN
? "6":
441 r
== GPG_ERR_CRL_TOO_OLD
? "7":
442 r
== GPG_ERR_NO_POLICY_MATCH
? "8":
443 r
== GPG_ERR_NO_SECKEY
? "9":
444 r
== GPG_ERR_MISSING_CERT
? "11":
454 Do the actual encryption process. Takes the plaintext from the INPUT
455 command, writes to the ciphertext to the file descriptor set with
456 the OUTPUT command, take the recipients form all the recipients set
457 so far. If this command fails the clients should try to delete all
458 output currently done or otherwise mark it as invalid. GPGSM does
459 ensure that there won't be any security problem with leftover data
460 on the output in this case.
462 This command should in general not fail, as all necessary checks
463 have been done while setting the recipients. The input and output
466 cmd_encrypt (assuan_context_t ctx
, char *line
)
468 ctrl_t ctrl
= assuan_get_pointer (ctx
);
476 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
478 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
479 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
481 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
483 out_fp
= fdopen (dup (out_fd
), "w");
485 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
487 /* Now add all encrypt-to marked recipients from the default
490 if (!opt
.no_encrypt_to
&& !ctrl
->server_local
->no_encrypt_to
)
492 for (cl
=ctrl
->server_local
->default_recplist
; !rc
&& cl
; cl
= cl
->next
)
493 if (cl
->is_encrypt_to
)
494 rc
= gpgsm_add_cert_to_certlist (ctrl
, cl
->cert
,
495 &ctrl
->server_local
->recplist
, 1);
498 rc
= ctrl
->audit
? 0 : start_audit_session (ctrl
);
500 rc
= gpgsm_encrypt (assuan_get_pointer (ctx
),
501 ctrl
->server_local
->recplist
,
505 gpgsm_release_certlist (ctrl
->server_local
->recplist
);
506 ctrl
->server_local
->recplist
= NULL
;
507 /* Close and reset the fd */
508 close_message_fd (ctrl
);
509 assuan_close_input_fd (ctx
);
510 assuan_close_output_fd (ctx
);
517 This performs the decrypt operation after doing some check on the
518 internal state. (e.g. that only needed data has been set). Because
519 it utilizes the GPG-Agent for the session key decryption, there is
520 no need to ask the client for a protecting passphrase - GpgAgent
521 does take care of this by requesting this from the user. */
523 cmd_decrypt (assuan_context_t ctx
, char *line
)
525 ctrl_t ctrl
= assuan_get_pointer (ctx
);
532 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
534 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
535 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
537 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
539 out_fp
= fdopen (dup(out_fd
), "w");
541 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
543 rc
= start_audit_session (ctrl
);
545 rc
= gpgsm_decrypt (ctrl
, inp_fd
, out_fp
);
548 /* close and reset the fd */
549 close_message_fd (ctrl
);
550 assuan_close_input_fd (ctx
);
551 assuan_close_output_fd (ctx
);
559 This does a verify operation on the message send to the input-FD.
560 The result is written out using status lines. If an output FD was
561 given, the signed text will be written to that.
563 If the signature is a detached one, the server will inquire about
564 the signed material and the client must provide it.
567 cmd_verify (assuan_context_t ctx
, char *line
)
570 ctrl_t ctrl
= assuan_get_pointer (ctx
);
571 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
572 int out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
578 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
582 out_fp
= fdopen ( dup(out_fd
), "w");
584 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
587 rc
= start_audit_session (ctrl
);
589 rc
= gpgsm_verify (assuan_get_pointer (ctx
), fd
,
590 ctrl
->server_local
->message_fd
, out_fp
);
594 /* close and reset the fd */
595 close_message_fd (ctrl
);
596 assuan_close_input_fd (ctx
);
597 assuan_close_output_fd (ctx
);
605 Sign the data set with the INPUT command and write it to the sink
606 set by OUTPUT. With "--detached" specified, a detached signature is
607 created (surprise). */
609 cmd_sign (assuan_context_t ctx
, char *line
)
611 ctrl_t ctrl
= assuan_get_pointer (ctx
);
617 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
619 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
620 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
622 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
624 detached
= has_option (line
, "--detached");
626 out_fp
= fdopen ( dup(out_fd
), "w");
628 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
630 rc
= start_audit_session (ctrl
);
632 rc
= gpgsm_sign (assuan_get_pointer (ctx
), ctrl
->server_local
->signerlist
,
633 inp_fd
, detached
, out_fp
);
636 /* close and reset the fd */
637 close_message_fd (ctrl
);
638 assuan_close_input_fd (ctx
);
639 assuan_close_output_fd (ctx
);
645 /* IMPORT [--re-import]
647 Import the certificates read form the input-fd, return status
648 message for each imported one. The import checks the validity of
649 the certificate but not of the entire chain. It is possible to
650 import expired certificates.
652 With the option --re-import the input data is expected to a be a LF
653 separated list of fingerprints. The command will re-import these
654 certificates, meaning that they are made permanent by removing
655 their ephemeral flag. */
657 cmd_import (assuan_context_t ctx
, char *line
)
659 ctrl_t ctrl
= assuan_get_pointer (ctx
);
661 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
662 int reimport
= has_option (line
, "--re-import");
667 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
669 rc
= gpgsm_import (assuan_get_pointer (ctx
), fd
, reimport
);
671 /* close and reset the fd */
672 close_message_fd (ctrl
);
673 assuan_close_input_fd (ctx
);
674 assuan_close_output_fd (ctx
);
680 /* EXPORT [--data [--armor|--base64]] [--] pattern
685 cmd_export (assuan_context_t ctx
, char *line
)
687 ctrl_t ctrl
= assuan_get_pointer (ctx
);
692 use_data
= has_option (line
, "--data");
696 /* We need to override any possible setting done by an OUTPUT command. */
697 ctrl
->create_pem
= has_option (line
, "--armor");
698 ctrl
->create_base64
= has_option (line
, "--base64");
701 line
= skip_options (line
);
703 /* Break the line down into an strlist_t. */
705 for (p
=line
; *p
; line
= p
)
707 while (*p
&& *p
!= ' ')
713 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
717 return out_of_core ();
720 strcpy_escaped_plus (sl
->d
, line
);
730 stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
734 return set_error (GPG_ERR_ASS_GENERAL
,
735 "error setting up a data stream");
737 gpgsm_export (ctrl
, list
, NULL
, stream
);
742 int fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
748 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
750 out_fp
= fdopen ( dup(fd
), "w");
754 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
757 gpgsm_export (ctrl
, list
, out_fp
, NULL
);
762 /* Close and reset the fds. */
763 close_message_fd (ctrl
);
764 assuan_close_input_fd (ctx
);
765 assuan_close_output_fd (ctx
);
771 cmd_delkeys (assuan_context_t ctx
, char *line
)
773 ctrl_t ctrl
= assuan_get_pointer (ctx
);
778 /* break the line down into an strlist_t */
780 for (p
=line
; *p
; line
= p
)
782 while (*p
&& *p
!= ' ')
788 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
792 return out_of_core ();
795 strcpy_escaped_plus (sl
->d
, line
);
801 rc
= gpgsm_delete (ctrl
, list
);
804 /* close and reset the fd */
805 close_message_fd (ctrl
);
806 assuan_close_input_fd (ctx
);
807 assuan_close_output_fd (ctx
);
816 Set the file descriptor to read a message which is used with
817 detached signatures */
819 cmd_message (assuan_context_t ctx
, char *line
)
824 ctrl_t ctrl
= assuan_get_pointer (ctx
);
826 rc
= assuan_command_parse_fd (ctx
, line
, &sysfd
);
829 fd
= translate_sys2libc_fd (sysfd
, 0);
831 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
832 ctrl
->server_local
->message_fd
= fd
;
836 /* LISTKEYS [<patterns>]
837 DUMPKEYS [<patterns>]
838 LISTSECRETKEYS [<patterns>]
839 DUMPSECRETKEYS [<patterns>]
842 do_listkeys (assuan_context_t ctx
, char *line
, int mode
)
844 ctrl_t ctrl
= assuan_get_pointer (ctx
);
848 unsigned int listmode
;
851 /* Break the line down into an strlist. */
853 for (p
=line
; *p
; line
= p
)
855 while (*p
&& *p
!= ' ')
861 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
865 return out_of_core ();
868 strcpy_escaped_plus (sl
->d
, line
);
874 if (ctrl
->server_local
->list_to_output
)
876 int outfd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
879 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
880 fp
= es_fdopen ( dup (outfd
), "w");
882 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
886 fp
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
888 return set_error (GPG_ERR_ASS_GENERAL
,
889 "error setting up a data stream");
892 ctrl
->with_colons
= 1;
894 if (ctrl
->server_local
->list_internal
)
896 if (ctrl
->server_local
->list_external
)
898 err
= gpgsm_list_keys (assuan_get_pointer (ctx
), list
, fp
, listmode
);
901 if (ctrl
->server_local
->list_to_output
)
902 assuan_close_output_fd (ctx
);
907 cmd_listkeys (assuan_context_t ctx
, char *line
)
909 return do_listkeys (ctx
, line
, 3);
913 cmd_dumpkeys (assuan_context_t ctx
, char *line
)
915 return do_listkeys (ctx
, line
, 259);
919 cmd_listsecretkeys (assuan_context_t ctx
, char *line
)
921 return do_listkeys (ctx
, line
, 2);
925 cmd_dumpsecretkeys (assuan_context_t ctx
, char *line
)
927 return do_listkeys (ctx
, line
, 258);
933 Read the parameters in native format from the input fd and write a
934 certificate request to the output.
937 cmd_genkey (assuan_context_t ctx
, char *line
)
939 ctrl_t ctrl
= assuan_get_pointer (ctx
);
947 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
949 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
950 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
952 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
954 in_stream
= es_fdopen_nc (inp_fd
, "r");
956 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen failed");
958 out_fp
= fdopen ( dup(out_fd
), "w");
961 es_fclose (in_stream
);
962 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
964 rc
= gpgsm_genkey (ctrl
, in_stream
, out_fp
);
967 /* close and reset the fds */
968 assuan_close_input_fd (ctx
);
969 assuan_close_output_fd (ctx
);
976 /* GETAUDITLOG [--data] [--html]
978 !!!WORK in PROGRESS!!!
980 If --data is used, the output is send using D-lines and not to the
981 source given by an OUTPUT command.
983 If --html is used the output is formated as an XHTML block. This is
984 designed to be incorporated into a HTML document.
987 cmd_getauditlog (assuan_context_t ctx
, char *line
)
989 ctrl_t ctrl
= assuan_get_pointer (ctx
);
991 estream_t out_stream
;
992 int opt_data
, opt_html
;
995 opt_data
= has_option (line
, "--data");
996 opt_html
= has_option (line
, "--html");
997 line
= skip_options (line
);
1000 return gpg_error (GPG_ERR_NO_DATA
);
1004 out_stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
1006 return set_error (GPG_ERR_ASS_GENERAL
,
1007 "error setting up a data stream");
1011 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
1013 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
1015 out_stream
= es_fdopen_nc ( dup (out_fd
), "w");
1018 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
1022 audit_print_result (ctrl
->audit
, out_stream
, opt_html
);
1025 es_fclose (out_stream
);
1027 /* Close and reset the fd. */
1029 assuan_close_output_fd (ctx
);
1036 Multipurpose function to return a variety of information.
1037 Supported values for WHAT are:
1039 version - Return the version of the program.
1040 pid - Return the process id of the server.
1041 agent-check - Return success if the agent is running.
1042 cmd_has_option CMD OPT
1043 - Returns OK if the command CMD implements the option OPT.
1047 cmd_getinfo (assuan_context_t ctx
, char *line
)
1051 if (!strcmp (line
, "version"))
1053 const char *s
= VERSION
;
1054 rc
= assuan_send_data (ctx
, s
, strlen (s
));
1056 else if (!strcmp (line
, "pid"))
1060 snprintf (numbuf
, sizeof numbuf
, "%lu", (unsigned long)getpid ());
1061 rc
= assuan_send_data (ctx
, numbuf
, strlen (numbuf
));
1063 else if (!strcmp (line
, "agent-check"))
1065 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1066 rc
= gpgsm_agent_send_nop (ctrl
);
1068 else if (!strncmp (line
, "cmd_has_option", 14)
1069 && (line
[14] == ' ' || line
[14] == '\t' || !line
[14]))
1073 while (*line
== ' ' || *line
== '\t')
1076 rc
= gpg_error (GPG_ERR_MISSING_VALUE
);
1080 while (*line
&& (*line
!= ' ' && *line
!= '\t'))
1083 rc
= gpg_error (GPG_ERR_MISSING_VALUE
);
1087 while (*line
== ' ' || *line
== '\t')
1090 rc
= gpg_error (GPG_ERR_MISSING_VALUE
);
1094 if (!command_has_option (cmd
, cmdopt
))
1095 rc
= gpg_error (GPG_ERR_GENERAL
);
1101 rc
= set_error (GPG_ERR_ASS_PARAMETER
, "unknown value for WHAT");
1108 /* Return true if the command CMD implements the option OPT. */
1110 command_has_option (const char *cmd
, const char *cmdopt
)
1112 if (!strcmp (cmd
, "IMPORT"))
1114 if (!strcmp (cmdopt
, "re-import"))
1122 /* Tell the assuan library about our commands */
1124 register_commands (assuan_context_t ctx
)
1128 int (*handler
)(assuan_context_t
, char *line
);
1130 { "RECIPIENT", cmd_recipient
},
1131 { "SIGNER", cmd_signer
},
1132 { "ENCRYPT", cmd_encrypt
},
1133 { "DECRYPT", cmd_decrypt
},
1134 { "VERIFY", cmd_verify
},
1135 { "SIGN", cmd_sign
},
1136 { "IMPORT", cmd_import
},
1137 { "EXPORT", cmd_export
},
1140 { "MESSAGE", cmd_message
},
1141 { "LISTKEYS", cmd_listkeys
},
1142 { "DUMPKEYS", cmd_dumpkeys
},
1143 { "LISTSECRETKEYS",cmd_listsecretkeys
},
1144 { "DUMPSECRETKEYS",cmd_dumpsecretkeys
},
1145 { "GENKEY", cmd_genkey
},
1146 { "DELKEYS", cmd_delkeys
},
1147 { "GETAUDITLOG", cmd_getauditlog
},
1148 { "GETINFO", cmd_getinfo
},
1153 for (i
=0; table
[i
].name
; i
++)
1155 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
1162 /* Startup the server. DEFAULT_RECPLIST is the list of recipients as
1163 set from the command line or config file. We only require those
1164 marked as encrypt-to. */
1166 gpgsm_server (certlist_t default_recplist
)
1170 assuan_context_t ctx
;
1171 struct server_control_s ctrl
;
1172 static const char hello
[] = ("GNU Privacy Guard's S/M server "
1175 memset (&ctrl
, 0, sizeof ctrl
);
1176 gpgsm_init_default_ctrl (&ctrl
);
1178 /* We use a pipe based server so that we can work from scripts.
1179 assuan_init_pipe_server will automagically detect when we are
1180 called with a socketpair and ignore FIELDES in this case. */
1183 rc
= assuan_init_pipe_server (&ctx
, filedes
);
1186 log_error ("failed to initialize the server: %s\n",
1190 rc
= register_commands (ctx
);
1193 log_error ("failed to the register commands with Assuan: %s\n",
1197 if (opt
.verbose
|| opt
.debug
)
1200 const char *s1
= getenv ("GPG_AGENT_INFO");
1201 const char *s2
= getenv ("DIRMNGR_INFO");
1210 opt
.config_filename
,
1215 assuan_set_hello_line (ctx
, tmp
);
1220 assuan_set_hello_line (ctx
, hello
);
1222 assuan_register_reset_notify (ctx
, reset_notify
);
1223 assuan_register_input_notify (ctx
, input_notify
);
1224 assuan_register_output_notify (ctx
, output_notify
);
1225 assuan_register_option_handler (ctx
, option_handler
);
1227 assuan_set_pointer (ctx
, &ctrl
);
1228 ctrl
.server_local
= xcalloc (1, sizeof *ctrl
.server_local
);
1229 ctrl
.server_local
->assuan_ctx
= ctx
;
1230 ctrl
.server_local
->message_fd
= -1;
1231 ctrl
.server_local
->list_internal
= 1;
1232 ctrl
.server_local
->list_external
= 0;
1233 ctrl
.server_local
->default_recplist
= default_recplist
;
1236 assuan_set_log_stream (ctx
, log_get_stream ());
1240 rc
= assuan_accept (ctx
);
1247 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc
));
1251 rc
= assuan_process (ctx
);
1254 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc
));
1259 gpgsm_release_certlist (ctrl
.server_local
->recplist
);
1260 ctrl
.server_local
->recplist
= NULL
;
1261 gpgsm_release_certlist (ctrl
.server_local
->signerlist
);
1262 ctrl
.server_local
->signerlist
= NULL
;
1263 xfree (ctrl
.server_local
);
1265 audit_release (ctrl
.audit
);
1268 assuan_deinit_server (ctx
);
1274 gpgsm_status2 (ctrl_t ctrl
, int no
, ...)
1276 gpg_error_t err
= 0;
1280 va_start (arg_ptr
, no
);
1282 if (ctrl
->no_server
&& ctrl
->status_fd
== -1)
1283 ; /* No status wanted. */
1284 else if (ctrl
->no_server
)
1288 if (ctrl
->status_fd
== 1)
1290 else if (ctrl
->status_fd
== 2)
1293 statusfp
= fdopen (ctrl
->status_fd
, "w");
1297 log_fatal ("can't open fd %d for status output: %s\n",
1298 ctrl
->status_fd
, strerror(errno
));
1302 fputs ("[GNUPG:] ", statusfp
);
1303 fputs (get_status_string (no
), statusfp
);
1305 while ( (text
= va_arg (arg_ptr
, const char*) ))
1307 putc ( ' ', statusfp
);
1308 for (; *text
; text
++)
1311 fputs ( "\\n", statusfp
);
1312 else if (*text
== '\r')
1313 fputs ( "\\r", statusfp
);
1315 putc ( *(const byte
*)text
, statusfp
);
1318 putc ('\n', statusfp
);
1323 assuan_context_t ctx
= ctrl
->server_local
->assuan_ctx
;
1329 while ( (text
= va_arg (arg_ptr
, const char *)) )
1336 for ( ; *text
&& n
< DIM (buf
)-2; n
++)
1340 err
= assuan_write_status (ctx
, get_status_string (no
), buf
);
1348 gpgsm_status (ctrl_t ctrl
, int no
, const char *text
)
1350 return gpgsm_status2 (ctrl
, no
, text
, NULL
);
1354 gpgsm_status_with_err_code (ctrl_t ctrl
, int no
, const char *text
,
1359 sprintf (buf
, "%u", (unsigned int)ec
);
1361 return gpgsm_status2 (ctrl
, no
, text
, buf
, NULL
);
1363 return gpgsm_status2 (ctrl
, no
, buf
, NULL
);
1367 /* Helper to notify the client about Pinentry events. Because that
1368 might disturb some older clients, this is only done when enabled
1369 via an option. Returns an gpg error code. */
1371 gpgsm_proxy_pinentry_notify (ctrl_t ctrl
, const unsigned char *line
)
1373 if (!ctrl
|| !ctrl
->server_local
1374 || !ctrl
->server_local
->allow_pinentry_notify
)
1376 return assuan_inquire (ctrl
->server_local
->assuan_ctx
, line
, NULL
, NULL
, 0);