1 /* server.c - Server mode and main entry point
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
3 * 2007, 2008 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
73 /* Note that it is sufficient to allocate the target string D as
74 long as the source string S, i.e.: strlen(s)+1; */
76 strcpy_escaped_plus (char *d
, const char *s
)
80 if (*s
== '%' && s
[1] && s
[2])
96 Blanks after the options are also removed. */
98 skip_options (const char *line
)
100 while (spacep (line
))
102 while ( *line
== '-' && line
[1] == '-' )
104 while (*line
&& !spacep (line
))
106 while (spacep (line
))
113 /* Check whether the option NAME appears in LINE */
115 has_option (const char *line
, const char *name
)
118 int n
= strlen (name
);
120 s
= strstr (line
, name
);
121 if (s
&& s
>= skip_options (line
))
123 return (s
&& (s
== line
|| spacep (s
-1)) && (!s
[n
] || spacep (s
+n
)));
127 /* A write handler used by es_fopencookie to write assuan data
130 data_line_cookie_write (void *cookie
, const void *buffer
, size_t size
)
132 assuan_context_t ctx
= cookie
;
134 if (assuan_send_data (ctx
, buffer
, size
))
144 data_line_cookie_close (void *cookie
)
146 assuan_context_t ctx
= cookie
;
148 if (assuan_send_data (ctx
, NULL
, 0))
159 close_message_fd (ctrl_t ctrl
)
161 if (ctrl
->server_local
->message_fd
!= -1)
163 close (ctrl
->server_local
->message_fd
);
164 ctrl
->server_local
->message_fd
= -1;
169 /* Start a new audit session if this has been enabled. */
171 start_audit_session (ctrl_t ctrl
)
173 audit_release (ctrl
->audit
);
175 if (ctrl
->server_local
->enable_audit_log
&& !(ctrl
->audit
= audit_new ()) )
176 return gpg_error_from_syserror ();
183 option_handler (assuan_context_t ctx
, const char *key
, const char *value
)
185 ctrl_t ctrl
= assuan_get_pointer (ctx
);
187 if (!strcmp (key
, "include-certs"))
189 int i
= *value
? atoi (value
) : -1;
190 if (ctrl
->include_certs
< -2)
191 return gpg_error (GPG_ERR_ASS_PARAMETER
);
192 ctrl
->include_certs
= i
;
194 else if (!strcmp (key
, "display"))
198 opt
.display
= strdup (value
);
200 return out_of_core ();
202 else if (!strcmp (key
, "ttyname"))
206 opt
.ttyname
= strdup (value
);
208 return out_of_core ();
210 else if (!strcmp (key
, "ttytype"))
214 opt
.ttytype
= strdup (value
);
216 return out_of_core ();
218 else if (!strcmp (key
, "lc-ctype"))
222 opt
.lc_ctype
= strdup (value
);
224 return out_of_core ();
226 else if (!strcmp (key
, "lc-messages"))
229 free (opt
.lc_messages
);
230 opt
.lc_messages
= strdup (value
);
231 if (!opt
.lc_messages
)
232 return out_of_core ();
234 else if (!strcmp (key
, "xauthority"))
237 free (opt
.xauthority
);
238 opt
.xauthority
= strdup (value
);
240 return out_of_core ();
242 else if (!strcmp (key
, "pinentry-user-data"))
244 if (opt
.pinentry_user_data
)
245 free (opt
.pinentry_user_data
);
246 opt
.pinentry_user_data
= strdup (value
);
247 if (!opt
.pinentry_user_data
)
248 return out_of_core ();
250 else if (!strcmp (key
, "list-mode"))
252 int i
= *value
? atoi (value
) : 0;
253 if (!i
|| i
== 1) /* default and mode 1 */
255 ctrl
->server_local
->list_internal
= 1;
256 ctrl
->server_local
->list_external
= 0;
260 ctrl
->server_local
->list_internal
= 0;
261 ctrl
->server_local
->list_external
= 1;
265 ctrl
->server_local
->list_internal
= 1;
266 ctrl
->server_local
->list_external
= 1;
269 return gpg_error (GPG_ERR_ASS_PARAMETER
);
271 else if (!strcmp (key
, "list-to-output"))
273 int i
= *value
? atoi (value
) : 0;
274 ctrl
->server_local
->list_to_output
= i
;
276 else if (!strcmp (key
, "with-validation"))
278 int i
= *value
? atoi (value
) : 0;
279 ctrl
->with_validation
= i
;
281 else if (!strcmp (key
, "validation-model"))
283 int i
= gpgsm_parse_validation_model (value
);
284 if ( i
>= 0 && i
<= 1 )
285 ctrl
->validation_model
= i
;
287 return gpg_error (GPG_ERR_ASS_PARAMETER
);
289 else if (!strcmp (key
, "with-key-data"))
291 opt
.with_key_data
= 1;
293 else if (!strcmp (key
, "enable-audit-log"))
295 int i
= *value
? atoi (value
) : 0;
296 ctrl
->server_local
->enable_audit_log
= i
;
298 else if (!strcmp (key
, "allow-pinentry-notify"))
299 ctrl
->server_local
->allow_pinentry_notify
= 1;
300 else if (!strcmp (key
, "with-ephemeral-keys"))
302 int i
= *value
? atoi (value
) : 0;
303 ctrl
->with_ephemeral_keys
= i
;
305 else if (!strcmp (key
, "no-encrypt-to"))
307 ctrl
->server_local
->no_encrypt_to
= 1;
310 return gpg_error (GPG_ERR_UNKNOWN_OPTION
);
317 reset_notify (assuan_context_t ctx
)
319 ctrl_t ctrl
= assuan_get_pointer (ctx
);
321 gpgsm_release_certlist (ctrl
->server_local
->recplist
);
322 gpgsm_release_certlist (ctrl
->server_local
->signerlist
);
323 ctrl
->server_local
->recplist
= NULL
;
324 ctrl
->server_local
->signerlist
= NULL
;
325 close_message_fd (ctrl
);
326 assuan_close_input_fd (ctx
);
327 assuan_close_output_fd (ctx
);
332 input_notify (assuan_context_t ctx
, const char *line
)
334 ctrl_t ctrl
= assuan_get_pointer (ctx
);
336 ctrl
->autodetect_encoding
= 0;
339 if (strstr (line
, "--armor"))
341 else if (strstr (line
, "--base64"))
343 else if (strstr (line
, "--binary"))
346 ctrl
->autodetect_encoding
= 1;
350 output_notify (assuan_context_t ctx
, const char *line
)
352 ctrl_t ctrl
= assuan_get_pointer (ctx
);
354 ctrl
->create_pem
= 0;
355 ctrl
->create_base64
= 0;
356 if (strstr (line
, "--armor"))
357 ctrl
->create_pem
= 1;
358 else if (strstr (line
, "--base64"))
359 ctrl
->create_base64
= 1; /* just the raw output */
364 /* RECIPIENT <userID>
366 Set the recipient for the encryption. <userID> should be the
367 internal representation of the key; the server may accept any other
368 way of specification [we will support this]. If this is a valid and
369 trusted recipient the server does respond with OK, otherwise the
370 return is an ERR with the reason why the recipient can't be used,
371 the encryption will then not be done for this recipient. If the
372 policy is not to encrypt at all if not all recipients are valid, the
373 client has to take care of this. All RECIPIENT commands are
374 cumulative until a RESET or an successful ENCRYPT command. */
376 cmd_recipient (assuan_context_t ctx
, char *line
)
378 ctrl_t ctrl
= assuan_get_pointer (ctx
);
382 rc
= start_audit_session (ctrl
);
387 rc
= gpgsm_add_to_certlist (ctrl
, line
, 0,
388 &ctrl
->server_local
->recplist
, 0);
391 gpg_err_code_t r
= gpg_err_code (rc
);
392 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
394 r
== GPG_ERR_NO_PUBKEY
? "1":
395 r
== GPG_ERR_AMBIGUOUS_NAME
? "2":
396 r
== GPG_ERR_WRONG_KEY_USAGE
? "3":
397 r
== GPG_ERR_CERT_REVOKED
? "4":
398 r
== GPG_ERR_CERT_EXPIRED
? "5":
399 r
== GPG_ERR_NO_CRL_KNOWN
? "6":
400 r
== GPG_ERR_CRL_TOO_OLD
? "7":
401 r
== GPG_ERR_NO_POLICY_MATCH
? "8":
402 r
== GPG_ERR_MISSING_CERT
? "11":
412 Set the signer's keys for the signature creation. <userID> should
413 be the internal representation of the key; the server may accept any
414 other way of specification [we will support this]. If this is a
415 valid and usable signing key the server does respond with OK,
416 otherwise it returns an ERR with the reason why the key can't be
417 used, the signing will then not be done for this key. If the policy
418 is not to sign at all if not all signer keys are valid, the client
419 has to take care of this. All SIGNER commands are cumulative until
420 a RESET but they are *not* reset by an SIGN command becuase it can
421 be expected that set of signers are used for more than one sign
424 Note that this command returns an INV_RECP status which is a bit
425 strange, but they are very similar. */
427 cmd_signer (assuan_context_t ctx
, char *line
)
429 ctrl_t ctrl
= assuan_get_pointer (ctx
);
432 rc
= gpgsm_add_to_certlist (ctrl
, line
, 1,
433 &ctrl
->server_local
->signerlist
, 0);
436 gpg_err_code_t r
= gpg_err_code (rc
);
437 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
439 r
== GPG_ERR_NO_PUBKEY
? "1":
440 r
== GPG_ERR_AMBIGUOUS_NAME
? "2":
441 r
== GPG_ERR_WRONG_KEY_USAGE
? "3":
442 r
== GPG_ERR_CERT_REVOKED
? "4":
443 r
== GPG_ERR_CERT_EXPIRED
? "5":
444 r
== GPG_ERR_NO_CRL_KNOWN
? "6":
445 r
== GPG_ERR_CRL_TOO_OLD
? "7":
446 r
== GPG_ERR_NO_POLICY_MATCH
? "8":
447 r
== GPG_ERR_NO_SECKEY
? "9":
448 r
== GPG_ERR_MISSING_CERT
? "11":
458 Do the actual encryption process. Takes the plaintext from the INPUT
459 command, writes to the ciphertext to the file descriptor set with
460 the OUTPUT command, take the recipients form all the recipients set
461 so far. If this command fails the clients should try to delete all
462 output currently done or otherwise mark it as invalid. GPGSM does
463 ensure that there won't be any security problem with leftover data
464 on the output in this case.
466 This command should in general not fail, as all necessary checks
467 have been done while setting the recipients. The input and output
470 cmd_encrypt (assuan_context_t ctx
, char *line
)
472 ctrl_t ctrl
= assuan_get_pointer (ctx
);
480 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
482 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
483 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
485 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
487 out_fp
= fdopen (dup (out_fd
), "w");
489 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
491 /* Now add all encrypt-to marked recipients from the default
494 if (!opt
.no_encrypt_to
&& !ctrl
->server_local
->no_encrypt_to
)
496 for (cl
=ctrl
->server_local
->default_recplist
; !rc
&& cl
; cl
= cl
->next
)
497 if (cl
->is_encrypt_to
)
498 rc
= gpgsm_add_cert_to_certlist (ctrl
, cl
->cert
,
499 &ctrl
->server_local
->recplist
, 1);
502 rc
= ctrl
->audit
? 0 : start_audit_session (ctrl
);
504 rc
= gpgsm_encrypt (assuan_get_pointer (ctx
),
505 ctrl
->server_local
->recplist
,
509 gpgsm_release_certlist (ctrl
->server_local
->recplist
);
510 ctrl
->server_local
->recplist
= NULL
;
511 /* Close and reset the fd */
512 close_message_fd (ctrl
);
513 assuan_close_input_fd (ctx
);
514 assuan_close_output_fd (ctx
);
521 This performs the decrypt operation after doing some check on the
522 internal state. (e.g. that only needed data has been set). Because
523 it utilizes the GPG-Agent for the session key decryption, there is
524 no need to ask the client for a protecting passphrase - GpgAgent
525 does take care of this by requesting this from the user. */
527 cmd_decrypt (assuan_context_t ctx
, char *line
)
529 ctrl_t ctrl
= assuan_get_pointer (ctx
);
536 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
538 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
539 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
541 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
543 out_fp
= fdopen (dup(out_fd
), "w");
545 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
547 rc
= start_audit_session (ctrl
);
549 rc
= gpgsm_decrypt (ctrl
, inp_fd
, out_fp
);
552 /* close and reset the fd */
553 close_message_fd (ctrl
);
554 assuan_close_input_fd (ctx
);
555 assuan_close_output_fd (ctx
);
563 This does a verify operation on the message send to the input-FD.
564 The result is written out using status lines. If an output FD was
565 given, the signed text will be written to that.
567 If the signature is a detached one, the server will inquire about
568 the signed material and the client must provide it.
571 cmd_verify (assuan_context_t ctx
, char *line
)
574 ctrl_t ctrl
= assuan_get_pointer (ctx
);
575 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
576 int out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
582 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
586 out_fp
= fdopen ( dup(out_fd
), "w");
588 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
591 rc
= start_audit_session (ctrl
);
593 rc
= gpgsm_verify (assuan_get_pointer (ctx
), fd
,
594 ctrl
->server_local
->message_fd
, out_fp
);
598 /* close and reset the fd */
599 close_message_fd (ctrl
);
600 assuan_close_input_fd (ctx
);
601 assuan_close_output_fd (ctx
);
609 Sign the data set with the INPUT command and write it to the sink
610 set by OUTPUT. With "--detached" specified, a detached signature is
611 created (surprise). */
613 cmd_sign (assuan_context_t ctx
, char *line
)
615 ctrl_t ctrl
= assuan_get_pointer (ctx
);
621 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
623 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
624 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
626 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
628 detached
= has_option (line
, "--detached");
630 out_fp
= fdopen ( dup(out_fd
), "w");
632 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
634 rc
= start_audit_session (ctrl
);
636 rc
= gpgsm_sign (assuan_get_pointer (ctx
), ctrl
->server_local
->signerlist
,
637 inp_fd
, detached
, out_fp
);
640 /* close and reset the fd */
641 close_message_fd (ctrl
);
642 assuan_close_input_fd (ctx
);
643 assuan_close_output_fd (ctx
);
651 Import the certificates read form the input-fd, return status
652 message for each imported one. The import checks the validity of
653 the certificate but not of the entire chain. It is possible to
654 import expired certificates. */
656 cmd_import (assuan_context_t ctx
, char *line
)
658 ctrl_t ctrl
= assuan_get_pointer (ctx
);
660 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
665 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
667 rc
= gpgsm_import (assuan_get_pointer (ctx
), fd
);
669 /* close and reset the fd */
670 close_message_fd (ctrl
);
671 assuan_close_input_fd (ctx
);
672 assuan_close_output_fd (ctx
);
678 /* EXPORT [--data [--armor|--base64]] [--] pattern
683 cmd_export (assuan_context_t ctx
, char *line
)
685 ctrl_t ctrl
= assuan_get_pointer (ctx
);
690 use_data
= has_option (line
, "--data");
694 /* We need to override any possible setting done by an OUTPUT command. */
695 ctrl
->create_pem
= has_option (line
, "--armor");
696 ctrl
->create_base64
= has_option (line
, "--base64");
699 line
= skip_options (line
);
701 /* Break the line down into an strlist_t. */
703 for (p
=line
; *p
; line
= p
)
705 while (*p
&& *p
!= ' ')
711 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
715 return out_of_core ();
718 strcpy_escaped_plus (sl
->d
, line
);
728 stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
732 return set_error (GPG_ERR_ASS_GENERAL
,
733 "error setting up a data stream");
735 gpgsm_export (ctrl
, list
, NULL
, stream
);
740 int fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
746 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
748 out_fp
= fdopen ( dup(fd
), "w");
752 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
755 gpgsm_export (ctrl
, list
, out_fp
, NULL
);
760 /* Close and reset the fds. */
761 close_message_fd (ctrl
);
762 assuan_close_input_fd (ctx
);
763 assuan_close_output_fd (ctx
);
769 cmd_delkeys (assuan_context_t ctx
, char *line
)
771 ctrl_t ctrl
= assuan_get_pointer (ctx
);
776 /* break the line down into an strlist_t */
778 for (p
=line
; *p
; line
= p
)
780 while (*p
&& *p
!= ' ')
786 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
790 return out_of_core ();
793 strcpy_escaped_plus (sl
->d
, line
);
799 rc
= gpgsm_delete (ctrl
, list
);
802 /* close and reset the fd */
803 close_message_fd (ctrl
);
804 assuan_close_input_fd (ctx
);
805 assuan_close_output_fd (ctx
);
814 Set the file descriptor to read a message which is used with
815 detached signatures */
817 cmd_message (assuan_context_t ctx
, char *line
)
822 ctrl_t ctrl
= assuan_get_pointer (ctx
);
824 rc
= assuan_command_parse_fd (ctx
, line
, &sysfd
);
827 fd
= translate_sys2libc_fd (sysfd
, 0);
829 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
830 ctrl
->server_local
->message_fd
= fd
;
834 /* LISTKEYS [<patterns>]
835 DUMPKEYS [<patterns>]
836 LISTSECRETKEYS [<patterns>]
837 DUMPSECRETKEYS [<patterns>]
840 do_listkeys (assuan_context_t ctx
, char *line
, int mode
)
842 ctrl_t ctrl
= assuan_get_pointer (ctx
);
846 unsigned int listmode
;
849 /* Break the line down into an strlist. */
851 for (p
=line
; *p
; line
= p
)
853 while (*p
&& *p
!= ' ')
859 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
863 return out_of_core ();
866 strcpy_escaped_plus (sl
->d
, line
);
872 if (ctrl
->server_local
->list_to_output
)
874 int outfd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
877 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
878 fp
= es_fdopen ( dup (outfd
), "w");
880 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
884 fp
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
886 return set_error (GPG_ERR_ASS_GENERAL
,
887 "error setting up a data stream");
890 ctrl
->with_colons
= 1;
892 if (ctrl
->server_local
->list_internal
)
894 if (ctrl
->server_local
->list_external
)
896 err
= gpgsm_list_keys (assuan_get_pointer (ctx
), list
, fp
, listmode
);
899 if (ctrl
->server_local
->list_to_output
)
900 assuan_close_output_fd (ctx
);
905 cmd_listkeys (assuan_context_t ctx
, char *line
)
907 return do_listkeys (ctx
, line
, 3);
911 cmd_dumpkeys (assuan_context_t ctx
, char *line
)
913 return do_listkeys (ctx
, line
, 259);
917 cmd_listsecretkeys (assuan_context_t ctx
, char *line
)
919 return do_listkeys (ctx
, line
, 2);
923 cmd_dumpsecretkeys (assuan_context_t ctx
, char *line
)
925 return do_listkeys (ctx
, line
, 258);
931 Read the parameters in native format from the input fd and write a
932 certificate request to the output.
935 cmd_genkey (assuan_context_t ctx
, char *line
)
937 ctrl_t ctrl
= assuan_get_pointer (ctx
);
945 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
947 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
948 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
950 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
952 in_stream
= es_fdopen_nc (inp_fd
, "r");
954 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen failed");
956 out_fp
= fdopen ( dup(out_fd
), "w");
959 es_fclose (in_stream
);
960 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
962 rc
= gpgsm_genkey (ctrl
, in_stream
, out_fp
);
965 /* close and reset the fds */
966 assuan_close_input_fd (ctx
);
967 assuan_close_output_fd (ctx
);
974 /* GETAUDITLOG [--data] [--html]
976 !!!WORK in PROGRESS!!!
978 If --data is used, the output is send using D-lines and not to the
979 source given by an OUTPUT command.
981 If --html is used the output is formated as an XHTML block. This is
982 designed to be incorporated into a HTML document.
985 cmd_getauditlog (assuan_context_t ctx
, char *line
)
987 ctrl_t ctrl
= assuan_get_pointer (ctx
);
989 estream_t out_stream
;
990 int opt_data
, opt_html
;
993 opt_data
= has_option (line
, "--data");
994 opt_html
= has_option (line
, "--html");
995 line
= skip_options (line
);
998 return gpg_error (GPG_ERR_NO_DATA
);
1002 out_stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
1004 return set_error (GPG_ERR_ASS_GENERAL
,
1005 "error setting up a data stream");
1009 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
1011 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
1013 out_stream
= es_fdopen_nc ( dup (out_fd
), "w");
1016 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
1020 audit_print_result (ctrl
->audit
, out_stream
, opt_html
);
1023 es_fclose (out_stream
);
1025 /* Close and reset the fd. */
1027 assuan_close_output_fd (ctx
);
1034 Multipurpose function to return a variety of information.
1035 Supported values for WHAT are:
1037 version - Return the version of the program.
1038 pid - Return the process id of the server.
1039 agent-check - Return success if the agent is running.
1043 cmd_getinfo (assuan_context_t ctx
, char *line
)
1047 if (!strcmp (line
, "version"))
1049 const char *s
= VERSION
;
1050 rc
= assuan_send_data (ctx
, s
, strlen (s
));
1052 else if (!strcmp (line
, "pid"))
1056 snprintf (numbuf
, sizeof numbuf
, "%lu", (unsigned long)getpid ());
1057 rc
= assuan_send_data (ctx
, numbuf
, strlen (numbuf
));
1059 else if (!strcmp (line
, "agent-check"))
1061 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1062 rc
= gpgsm_agent_send_nop (ctrl
);
1065 rc
= set_error (GPG_ERR_ASS_PARAMETER
, "unknown value for WHAT");
1071 /* Tell the assuan library about our commands */
1073 register_commands (assuan_context_t ctx
)
1077 int (*handler
)(assuan_context_t
, char *line
);
1079 { "RECIPIENT", cmd_recipient
},
1080 { "SIGNER", cmd_signer
},
1081 { "ENCRYPT", cmd_encrypt
},
1082 { "DECRYPT", cmd_decrypt
},
1083 { "VERIFY", cmd_verify
},
1084 { "SIGN", cmd_sign
},
1085 { "IMPORT", cmd_import
},
1086 { "EXPORT", cmd_export
},
1089 { "MESSAGE", cmd_message
},
1090 { "LISTKEYS", cmd_listkeys
},
1091 { "DUMPKEYS", cmd_dumpkeys
},
1092 { "LISTSECRETKEYS",cmd_listsecretkeys
},
1093 { "DUMPSECRETKEYS",cmd_dumpsecretkeys
},
1094 { "GENKEY", cmd_genkey
},
1095 { "DELKEYS", cmd_delkeys
},
1096 { "GETAUDITLOG", cmd_getauditlog
},
1097 { "GETINFO", cmd_getinfo
},
1102 for (i
=0; table
[i
].name
; i
++)
1104 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
1111 /* Startup the server. DEFAULT_RECPLIST is the list of recipients as
1112 set from the command line or config file. We only require those
1113 marked as encrypt-to. */
1115 gpgsm_server (certlist_t default_recplist
)
1119 assuan_context_t ctx
;
1120 struct server_control_s ctrl
;
1121 static const char hello
[] = ("GNU Privacy Guard's S/M server "
1124 memset (&ctrl
, 0, sizeof ctrl
);
1125 gpgsm_init_default_ctrl (&ctrl
);
1127 /* We use a pipe based server so that we can work from scripts.
1128 assuan_init_pipe_server will automagically detect when we are
1129 called with a socketpair and ignore FIELDES in this case. */
1132 rc
= assuan_init_pipe_server (&ctx
, filedes
);
1135 log_error ("failed to initialize the server: %s\n",
1139 rc
= register_commands (ctx
);
1142 log_error ("failed to the register commands with Assuan: %s\n",
1146 if (opt
.verbose
|| opt
.debug
)
1149 const char *s1
= getenv ("GPG_AGENT_INFO");
1150 const char *s2
= getenv ("DIRMNGR_INFO");
1159 opt
.config_filename
,
1164 assuan_set_hello_line (ctx
, tmp
);
1169 assuan_set_hello_line (ctx
, hello
);
1171 assuan_register_reset_notify (ctx
, reset_notify
);
1172 assuan_register_input_notify (ctx
, input_notify
);
1173 assuan_register_output_notify (ctx
, output_notify
);
1174 assuan_register_option_handler (ctx
, option_handler
);
1176 assuan_set_pointer (ctx
, &ctrl
);
1177 ctrl
.server_local
= xcalloc (1, sizeof *ctrl
.server_local
);
1178 ctrl
.server_local
->assuan_ctx
= ctx
;
1179 ctrl
.server_local
->message_fd
= -1;
1180 ctrl
.server_local
->list_internal
= 1;
1181 ctrl
.server_local
->list_external
= 0;
1182 ctrl
.server_local
->default_recplist
= default_recplist
;
1185 assuan_set_log_stream (ctx
, log_get_stream ());
1189 rc
= assuan_accept (ctx
);
1196 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc
));
1200 rc
= assuan_process (ctx
);
1203 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc
));
1208 gpgsm_release_certlist (ctrl
.server_local
->recplist
);
1209 ctrl
.server_local
->recplist
= NULL
;
1210 gpgsm_release_certlist (ctrl
.server_local
->signerlist
);
1211 ctrl
.server_local
->signerlist
= NULL
;
1212 xfree (ctrl
.server_local
);
1214 audit_release (ctrl
.audit
);
1217 assuan_deinit_server (ctx
);
1223 gpgsm_status2 (ctrl_t ctrl
, int no
, ...)
1225 gpg_error_t err
= 0;
1229 va_start (arg_ptr
, no
);
1231 if (ctrl
->no_server
&& ctrl
->status_fd
== -1)
1232 ; /* No status wanted. */
1233 else if (ctrl
->no_server
)
1237 if (ctrl
->status_fd
== 1)
1239 else if (ctrl
->status_fd
== 2)
1242 statusfp
= fdopen (ctrl
->status_fd
, "w");
1246 log_fatal ("can't open fd %d for status output: %s\n",
1247 ctrl
->status_fd
, strerror(errno
));
1251 fputs ("[GNUPG:] ", statusfp
);
1252 fputs (get_status_string (no
), statusfp
);
1254 while ( (text
= va_arg (arg_ptr
, const char*) ))
1256 putc ( ' ', statusfp
);
1257 for (; *text
; text
++)
1260 fputs ( "\\n", statusfp
);
1261 else if (*text
== '\r')
1262 fputs ( "\\r", statusfp
);
1264 putc ( *(const byte
*)text
, statusfp
);
1267 putc ('\n', statusfp
);
1272 assuan_context_t ctx
= ctrl
->server_local
->assuan_ctx
;
1278 while ( (text
= va_arg (arg_ptr
, const char *)) )
1285 for ( ; *text
&& n
< DIM (buf
)-2; n
++)
1289 err
= assuan_write_status (ctx
, get_status_string (no
), buf
);
1297 gpgsm_status (ctrl_t ctrl
, int no
, const char *text
)
1299 return gpgsm_status2 (ctrl
, no
, text
, NULL
);
1303 gpgsm_status_with_err_code (ctrl_t ctrl
, int no
, const char *text
,
1308 sprintf (buf
, "%u", (unsigned int)ec
);
1310 return gpgsm_status2 (ctrl
, no
, text
, buf
, NULL
);
1312 return gpgsm_status2 (ctrl
, no
, buf
, NULL
);
1316 /* Helper to notify the client about Pinentry events. Because that
1317 might disturb some older clients, this is only done when enabled
1318 via an option. Returns an gpg error code. */
1320 gpgsm_proxy_pinentry_notify (ctrl_t ctrl
, const unsigned char *line
)
1322 if (!ctrl
|| !ctrl
->server_local
1323 || !ctrl
->server_local
->allow_pinentry_notify
)
1325 return assuan_inquire (ctrl
->server_local
->assuan_ctx
, line
, NULL
, NULL
, 0);