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. */
57 /* Cookie definition for assuan data line output. */
58 static ssize_t
data_line_cookie_write (void *cookie
,
59 const void *buffer
, size_t size
);
60 static int data_line_cookie_close (void *cookie
);
61 static es_cookie_io_functions_t data_line_cookie_functions
=
64 data_line_cookie_write
,
66 data_line_cookie_close
72 /* Note that it is sufficient to allocate the target string D as
73 long as the source string S, i.e.: strlen(s)+1; */
75 strcpy_escaped_plus (char *d
, const char *s
)
79 if (*s
== '%' && s
[1] && s
[2])
95 Blanks after the options are also removed. */
97 skip_options (const char *line
)
101 while ( *line
== '-' && line
[1] == '-' )
103 while (*line
&& !spacep (line
))
105 while (spacep (line
))
112 /* Check whether the option NAME appears in LINE */
114 has_option (const char *line
, const char *name
)
117 int n
= strlen (name
);
119 s
= strstr (line
, name
);
120 if (s
&& s
>= skip_options (line
))
122 return (s
&& (s
== line
|| spacep (s
-1)) && (!s
[n
] || spacep (s
+n
)));
126 /* A write handler used by es_fopencookie to write assuan data
129 data_line_cookie_write (void *cookie
, const void *buffer
, size_t size
)
131 assuan_context_t ctx
= cookie
;
133 if (assuan_send_data (ctx
, buffer
, size
))
143 data_line_cookie_close (void *cookie
)
145 assuan_context_t ctx
= cookie
;
147 if (assuan_send_data (ctx
, NULL
, 0))
158 close_message_fd (ctrl_t ctrl
)
160 if (ctrl
->server_local
->message_fd
!= -1)
162 close (ctrl
->server_local
->message_fd
);
163 ctrl
->server_local
->message_fd
= -1;
168 /* Start a new audit session if this has been enabled. */
170 start_audit_session (ctrl_t ctrl
)
172 audit_release (ctrl
->audit
);
174 if (ctrl
->server_local
->enable_audit_log
&& !(ctrl
->audit
= audit_new ()) )
175 return gpg_error_from_syserror ();
182 option_handler (assuan_context_t ctx
, const char *key
, const char *value
)
184 ctrl_t ctrl
= assuan_get_pointer (ctx
);
186 if (!strcmp (key
, "include-certs"))
188 int i
= *value
? atoi (value
) : -1;
189 if (ctrl
->include_certs
< -2)
190 return gpg_error (GPG_ERR_ASS_PARAMETER
);
191 ctrl
->include_certs
= i
;
193 else if (!strcmp (key
, "display"))
197 opt
.display
= strdup (value
);
199 return out_of_core ();
201 else if (!strcmp (key
, "ttyname"))
205 opt
.ttyname
= strdup (value
);
207 return out_of_core ();
209 else if (!strcmp (key
, "ttytype"))
213 opt
.ttytype
= strdup (value
);
215 return out_of_core ();
217 else if (!strcmp (key
, "lc-ctype"))
221 opt
.lc_ctype
= strdup (value
);
223 return out_of_core ();
225 else if (!strcmp (key
, "lc-messages"))
228 free (opt
.lc_messages
);
229 opt
.lc_messages
= strdup (value
);
230 if (!opt
.lc_messages
)
231 return out_of_core ();
233 else if (!strcmp (key
, "xauthority"))
236 free (opt
.xauthority
);
237 opt
.xauthority
= strdup (value
);
239 return out_of_core ();
241 else if (!strcmp (key
, "pinentry-user-data"))
243 if (opt
.pinentry_user_data
)
244 free (opt
.pinentry_user_data
);
245 opt
.pinentry_user_data
= strdup (value
);
246 if (!opt
.pinentry_user_data
)
247 return out_of_core ();
249 else if (!strcmp (key
, "list-mode"))
251 int i
= *value
? atoi (value
) : 0;
252 if (!i
|| i
== 1) /* default and mode 1 */
254 ctrl
->server_local
->list_internal
= 1;
255 ctrl
->server_local
->list_external
= 0;
259 ctrl
->server_local
->list_internal
= 0;
260 ctrl
->server_local
->list_external
= 1;
264 ctrl
->server_local
->list_internal
= 1;
265 ctrl
->server_local
->list_external
= 1;
268 return gpg_error (GPG_ERR_ASS_PARAMETER
);
270 else if (!strcmp (key
, "list-to-output"))
272 int i
= *value
? atoi (value
) : 0;
273 ctrl
->server_local
->list_to_output
= i
;
275 else if (!strcmp (key
, "with-validation"))
277 int i
= *value
? atoi (value
) : 0;
278 ctrl
->with_validation
= i
;
280 else if (!strcmp (key
, "validation-model"))
282 int i
= gpgsm_parse_validation_model (value
);
283 if ( i
>= 0 && i
<= 1 )
284 ctrl
->validation_model
= i
;
286 return gpg_error (GPG_ERR_ASS_PARAMETER
);
288 else if (!strcmp (key
, "with-key-data"))
290 opt
.with_key_data
= 1;
292 else if (!strcmp (key
, "enable-audit-log"))
294 int i
= *value
? atoi (value
) : 0;
295 ctrl
->server_local
->enable_audit_log
= i
;
297 else if (!strcmp (key
, "allow-pinentry-notify"))
298 ctrl
->server_local
->allow_pinentry_notify
= 1;
300 return gpg_error (GPG_ERR_UNKNOWN_OPTION
);
307 reset_notify (assuan_context_t ctx
)
309 ctrl_t ctrl
= assuan_get_pointer (ctx
);
311 gpgsm_release_certlist (ctrl
->server_local
->recplist
);
312 gpgsm_release_certlist (ctrl
->server_local
->signerlist
);
313 ctrl
->server_local
->recplist
= NULL
;
314 ctrl
->server_local
->signerlist
= NULL
;
315 close_message_fd (ctrl
);
316 assuan_close_input_fd (ctx
);
317 assuan_close_output_fd (ctx
);
322 input_notify (assuan_context_t ctx
, const char *line
)
324 ctrl_t ctrl
= assuan_get_pointer (ctx
);
326 ctrl
->autodetect_encoding
= 0;
329 if (strstr (line
, "--armor"))
331 else if (strstr (line
, "--base64"))
333 else if (strstr (line
, "--binary"))
336 ctrl
->autodetect_encoding
= 1;
340 output_notify (assuan_context_t ctx
, const char *line
)
342 ctrl_t ctrl
= assuan_get_pointer (ctx
);
344 ctrl
->create_pem
= 0;
345 ctrl
->create_base64
= 0;
346 if (strstr (line
, "--armor"))
347 ctrl
->create_pem
= 1;
348 else if (strstr (line
, "--base64"))
349 ctrl
->create_base64
= 1; /* just the raw output */
354 /* RECIPIENT <userID>
356 Set the recipient for the encryption. <userID> should be the
357 internal representation of the key; the server may accept any other
358 way of specification [we will support this]. If this is a valid and
359 trusted recipient the server does respond with OK, otherwise the
360 return is an ERR with the reason why the recipient can't be used,
361 the encryption will then not be done for this recipient. If the
362 policy is not to encrypt at all if not all recipients are valid, the
363 client has to take care of this. All RECIPIENT commands are
364 cumulative until a RESET or an successful ENCRYPT command. */
366 cmd_recipient (assuan_context_t ctx
, char *line
)
368 ctrl_t ctrl
= assuan_get_pointer (ctx
);
372 rc
= start_audit_session (ctrl
);
377 rc
= gpgsm_add_to_certlist (ctrl
, line
, 0,
378 &ctrl
->server_local
->recplist
, 0);
381 gpg_err_code_t r
= gpg_err_code (rc
);
382 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
384 r
== GPG_ERR_NO_PUBKEY
? "1":
385 r
== GPG_ERR_AMBIGUOUS_NAME
? "2":
386 r
== GPG_ERR_WRONG_KEY_USAGE
? "3":
387 r
== GPG_ERR_CERT_REVOKED
? "4":
388 r
== GPG_ERR_CERT_EXPIRED
? "5":
389 r
== GPG_ERR_NO_CRL_KNOWN
? "6":
390 r
== GPG_ERR_CRL_TOO_OLD
? "7":
391 r
== GPG_ERR_NO_POLICY_MATCH
? "8":
392 r
== GPG_ERR_MISSING_CERT
? "11":
402 Set the signer's keys for the signature creation. <userID> should
403 be the internal representation of the key; the server may accept any
404 other way of specification [we will support this]. If this is a
405 valid and usable signing key the server does respond with OK,
406 otherwise it returns an ERR with the reason why the key can't be
407 used, the signing will then not be done for this key. If the policy
408 is not to sign at all if not all signer keys are valid, the client
409 has to take care of this. All SIGNER commands are cumulative until
410 a RESET but they are *not* reset by an SIGN command becuase it can
411 be expected that set of signers are used for more than one sign
414 Note that this command returns an INV_RECP status which is a bit
415 strange, but they are very similar. */
417 cmd_signer (assuan_context_t ctx
, char *line
)
419 ctrl_t ctrl
= assuan_get_pointer (ctx
);
422 rc
= gpgsm_add_to_certlist (ctrl
, line
, 1,
423 &ctrl
->server_local
->signerlist
, 0);
426 gpg_err_code_t r
= gpg_err_code (rc
);
427 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
429 r
== GPG_ERR_NO_PUBKEY
? "1":
430 r
== GPG_ERR_AMBIGUOUS_NAME
? "2":
431 r
== GPG_ERR_WRONG_KEY_USAGE
? "3":
432 r
== GPG_ERR_CERT_REVOKED
? "4":
433 r
== GPG_ERR_CERT_EXPIRED
? "5":
434 r
== GPG_ERR_NO_CRL_KNOWN
? "6":
435 r
== GPG_ERR_CRL_TOO_OLD
? "7":
436 r
== GPG_ERR_NO_POLICY_MATCH
? "8":
437 r
== GPG_ERR_NO_SECKEY
? "9":
438 r
== GPG_ERR_MISSING_CERT
? "11":
448 Do the actual encryption process. Takes the plaintext from the INPUT
449 command, writes to the ciphertext to the file descriptor set with
450 the OUTPUT command, take the recipients form all the recipients set
451 so far. If this command fails the clients should try to delete all
452 output currently done or otherwise mark it as invalid. GPGSM does
453 ensure that there won't be any security problem with leftover data
454 on the output in this case.
456 This command should in general not fail, as all necessary checks
457 have been done while setting the recipients. The input and output
460 cmd_encrypt (assuan_context_t ctx
, char *line
)
462 ctrl_t ctrl
= assuan_get_pointer (ctx
);
470 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
472 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
473 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
475 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
477 out_fp
= fdopen (dup (out_fd
), "w");
479 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
481 /* Now add all encrypt-to marked recipients from the default
484 if (!opt
.no_encrypt_to
)
486 for (cl
=ctrl
->server_local
->default_recplist
; !rc
&& cl
; cl
= cl
->next
)
487 if (cl
->is_encrypt_to
)
488 rc
= gpgsm_add_cert_to_certlist (ctrl
, cl
->cert
,
489 &ctrl
->server_local
->recplist
, 1);
492 rc
= ctrl
->audit
? 0 : start_audit_session (ctrl
);
494 rc
= gpgsm_encrypt (assuan_get_pointer (ctx
),
495 ctrl
->server_local
->recplist
,
499 gpgsm_release_certlist (ctrl
->server_local
->recplist
);
500 ctrl
->server_local
->recplist
= NULL
;
501 /* Close and reset the fd */
502 close_message_fd (ctrl
);
503 assuan_close_input_fd (ctx
);
504 assuan_close_output_fd (ctx
);
511 This performs the decrypt operation after doing some check on the
512 internal state. (e.g. that only needed data has been set). Because
513 it utilizes the GPG-Agent for the session key decryption, there is
514 no need to ask the client for a protecting passphrase - GpgAgent
515 does take care of this by requesting this from the user. */
517 cmd_decrypt (assuan_context_t ctx
, char *line
)
519 ctrl_t ctrl
= assuan_get_pointer (ctx
);
526 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
528 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
529 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
531 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
533 out_fp
= fdopen (dup(out_fd
), "w");
535 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
537 rc
= start_audit_session (ctrl
);
539 rc
= gpgsm_decrypt (ctrl
, inp_fd
, out_fp
);
542 /* close and reset the fd */
543 close_message_fd (ctrl
);
544 assuan_close_input_fd (ctx
);
545 assuan_close_output_fd (ctx
);
553 This does a verify operation on the message send to the input-FD.
554 The result is written out using status lines. If an output FD was
555 given, the signed text will be written to that.
557 If the signature is a detached one, the server will inquire about
558 the signed material and the client must provide it.
561 cmd_verify (assuan_context_t ctx
, char *line
)
564 ctrl_t ctrl
= assuan_get_pointer (ctx
);
565 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
566 int out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
572 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
576 out_fp
= fdopen ( dup(out_fd
), "w");
578 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
581 rc
= start_audit_session (ctrl
);
583 rc
= gpgsm_verify (assuan_get_pointer (ctx
), fd
,
584 ctrl
->server_local
->message_fd
, out_fp
);
588 /* close and reset the fd */
589 close_message_fd (ctrl
);
590 assuan_close_input_fd (ctx
);
591 assuan_close_output_fd (ctx
);
599 Sign the data set with the INPUT command and write it to the sink
600 set by OUTPUT. With "--detached" specified, a detached signature is
601 created (surprise). */
603 cmd_sign (assuan_context_t ctx
, char *line
)
605 ctrl_t ctrl
= assuan_get_pointer (ctx
);
611 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
613 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
614 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
616 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
618 detached
= has_option (line
, "--detached");
620 out_fp
= fdopen ( dup(out_fd
), "w");
622 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
624 rc
= start_audit_session (ctrl
);
626 rc
= gpgsm_sign (assuan_get_pointer (ctx
), ctrl
->server_local
->signerlist
,
627 inp_fd
, detached
, out_fp
);
630 /* close and reset the fd */
631 close_message_fd (ctrl
);
632 assuan_close_input_fd (ctx
);
633 assuan_close_output_fd (ctx
);
641 Import the certificates read form the input-fd, return status
642 message for each imported one. The import checks the validity of
643 the certificate but not of the entire chain. It is possible to
644 import expired certificates. */
646 cmd_import (assuan_context_t ctx
, char *line
)
648 ctrl_t ctrl
= assuan_get_pointer (ctx
);
650 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
655 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
657 rc
= gpgsm_import (assuan_get_pointer (ctx
), fd
);
659 /* close and reset the fd */
660 close_message_fd (ctrl
);
661 assuan_close_input_fd (ctx
);
662 assuan_close_output_fd (ctx
);
668 /* EXPORT [--data [--armor|--base64]] [--] pattern
673 cmd_export (assuan_context_t ctx
, char *line
)
675 ctrl_t ctrl
= assuan_get_pointer (ctx
);
680 use_data
= has_option (line
, "--data");
684 /* We need to override any possible setting done by an OUTPUT command. */
685 ctrl
->create_pem
= has_option (line
, "--armor");
686 ctrl
->create_base64
= has_option (line
, "--base64");
689 line
= skip_options (line
);
691 /* Break the line down into an strlist_t. */
693 for (p
=line
; *p
; line
= p
)
695 while (*p
&& *p
!= ' ')
701 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
705 return out_of_core ();
708 strcpy_escaped_plus (sl
->d
, line
);
718 stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
722 return set_error (GPG_ERR_ASS_GENERAL
,
723 "error setting up a data stream");
725 gpgsm_export (ctrl
, list
, NULL
, stream
);
730 int fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
736 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
738 out_fp
= fdopen ( dup(fd
), "w");
742 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
745 gpgsm_export (ctrl
, list
, out_fp
, NULL
);
750 /* Close and reset the fds. */
751 close_message_fd (ctrl
);
752 assuan_close_input_fd (ctx
);
753 assuan_close_output_fd (ctx
);
759 cmd_delkeys (assuan_context_t ctx
, char *line
)
761 ctrl_t ctrl
= assuan_get_pointer (ctx
);
766 /* break the line down into an strlist_t */
768 for (p
=line
; *p
; line
= p
)
770 while (*p
&& *p
!= ' ')
776 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
780 return out_of_core ();
783 strcpy_escaped_plus (sl
->d
, line
);
789 rc
= gpgsm_delete (ctrl
, list
);
792 /* close and reset the fd */
793 close_message_fd (ctrl
);
794 assuan_close_input_fd (ctx
);
795 assuan_close_output_fd (ctx
);
804 Set the file descriptor to read a message which is used with
805 detached signatures */
807 cmd_message (assuan_context_t ctx
, char *line
)
812 ctrl_t ctrl
= assuan_get_pointer (ctx
);
814 rc
= assuan_command_parse_fd (ctx
, line
, &sysfd
);
817 fd
= translate_sys2libc_fd (sysfd
, 0);
819 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
820 ctrl
->server_local
->message_fd
= fd
;
824 /* LISTKEYS [<patterns>]
825 DUMPKEYS [<patterns>]
826 LISTSECRETKEYS [<patterns>]
827 DUMPSECRETKEYS [<patterns>]
830 do_listkeys (assuan_context_t ctx
, char *line
, int mode
)
832 ctrl_t ctrl
= assuan_get_pointer (ctx
);
836 unsigned int listmode
;
839 /* Break the line down into an strlist. */
841 for (p
=line
; *p
; line
= p
)
843 while (*p
&& *p
!= ' ')
849 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
853 return out_of_core ();
856 strcpy_escaped_plus (sl
->d
, line
);
862 if (ctrl
->server_local
->list_to_output
)
864 int outfd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
867 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
868 fp
= es_fdopen ( dup (outfd
), "w");
870 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
874 fp
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
876 return set_error (GPG_ERR_ASS_GENERAL
,
877 "error setting up a data stream");
880 ctrl
->with_colons
= 1;
882 if (ctrl
->server_local
->list_internal
)
884 if (ctrl
->server_local
->list_external
)
886 err
= gpgsm_list_keys (assuan_get_pointer (ctx
), list
, fp
, listmode
);
889 if (ctrl
->server_local
->list_to_output
)
890 assuan_close_output_fd (ctx
);
895 cmd_listkeys (assuan_context_t ctx
, char *line
)
897 return do_listkeys (ctx
, line
, 3);
901 cmd_dumpkeys (assuan_context_t ctx
, char *line
)
903 return do_listkeys (ctx
, line
, 259);
907 cmd_listsecretkeys (assuan_context_t ctx
, char *line
)
909 return do_listkeys (ctx
, line
, 2);
913 cmd_dumpsecretkeys (assuan_context_t ctx
, char *line
)
915 return do_listkeys (ctx
, line
, 258);
921 Read the parameters in native format from the input fd and write a
922 certificate request to the output.
925 cmd_genkey (assuan_context_t ctx
, char *line
)
927 ctrl_t ctrl
= assuan_get_pointer (ctx
);
935 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
937 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
938 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
940 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
942 in_stream
= es_fdopen_nc (inp_fd
, "r");
944 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen failed");
946 out_fp
= fdopen ( dup(out_fd
), "w");
949 es_fclose (in_stream
);
950 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
952 rc
= gpgsm_genkey (ctrl
, in_stream
, out_fp
);
955 /* close and reset the fds */
956 assuan_close_input_fd (ctx
);
957 assuan_close_output_fd (ctx
);
964 /* GETAUDITLOG [--data] [--html]
966 !!!WORK in PROGRESS!!!
968 If --data is used, the output is send using D-lines and not to the
969 source given by an OUTPUT command.
971 If --html is used the output is formated as an XHTML block. This is
972 designed to be incorporated into a HTML document.
975 cmd_getauditlog (assuan_context_t ctx
, char *line
)
977 ctrl_t ctrl
= assuan_get_pointer (ctx
);
979 estream_t out_stream
;
980 int opt_data
, opt_html
;
983 opt_data
= has_option (line
, "--data");
984 opt_html
= has_option (line
, "--html");
985 line
= skip_options (line
);
988 return gpg_error (GPG_ERR_NO_DATA
);
992 out_stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
994 return set_error (GPG_ERR_ASS_GENERAL
,
995 "error setting up a data stream");
999 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
1001 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
1003 out_stream
= es_fdopen_nc ( dup (out_fd
), "w");
1006 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
1010 audit_print_result (ctrl
->audit
, out_stream
, opt_html
);
1013 es_fclose (out_stream
);
1015 /* Close and reset the fd. */
1017 assuan_close_output_fd (ctx
);
1024 Multipurpose function to return a variety of information.
1025 Supported values for WHAT are:
1027 version - Return the version of the program.
1028 pid - Return the process id of the server.
1029 agent-check - Return success if the agent is running.
1033 cmd_getinfo (assuan_context_t ctx
, char *line
)
1037 if (!strcmp (line
, "version"))
1039 const char *s
= VERSION
;
1040 rc
= assuan_send_data (ctx
, s
, strlen (s
));
1042 else if (!strcmp (line
, "pid"))
1046 snprintf (numbuf
, sizeof numbuf
, "%lu", (unsigned long)getpid ());
1047 rc
= assuan_send_data (ctx
, numbuf
, strlen (numbuf
));
1049 else if (!strcmp (line
, "agent-check"))
1051 ctrl_t ctrl
= assuan_get_pointer (ctx
);
1052 rc
= gpgsm_agent_send_nop (ctrl
);
1055 rc
= set_error (GPG_ERR_ASS_PARAMETER
, "unknown value for WHAT");
1061 /* Tell the assuan library about our commands */
1063 register_commands (assuan_context_t ctx
)
1067 int (*handler
)(assuan_context_t
, char *line
);
1069 { "RECIPIENT", cmd_recipient
},
1070 { "SIGNER", cmd_signer
},
1071 { "ENCRYPT", cmd_encrypt
},
1072 { "DECRYPT", cmd_decrypt
},
1073 { "VERIFY", cmd_verify
},
1074 { "SIGN", cmd_sign
},
1075 { "IMPORT", cmd_import
},
1076 { "EXPORT", cmd_export
},
1079 { "MESSAGE", cmd_message
},
1080 { "LISTKEYS", cmd_listkeys
},
1081 { "DUMPKEYS", cmd_dumpkeys
},
1082 { "LISTSECRETKEYS",cmd_listsecretkeys
},
1083 { "DUMPSECRETKEYS",cmd_dumpsecretkeys
},
1084 { "GENKEY", cmd_genkey
},
1085 { "DELKEYS", cmd_delkeys
},
1086 { "GETAUDITLOG", cmd_getauditlog
},
1087 { "GETINFO", cmd_getinfo
},
1092 for (i
=0; table
[i
].name
; i
++)
1094 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
1101 /* Startup the server. DEFAULT_RECPLIST is the list of recipients as
1102 set from the command line or config file. We only require those
1103 marked as encrypt-to. */
1105 gpgsm_server (certlist_t default_recplist
)
1109 assuan_context_t ctx
;
1110 struct server_control_s ctrl
;
1111 static const char hello
[] = ("GNU Privacy Guard's S/M server "
1114 memset (&ctrl
, 0, sizeof ctrl
);
1115 gpgsm_init_default_ctrl (&ctrl
);
1117 /* We use a pipe based server so that we can work from scripts.
1118 assuan_init_pipe_server will automagically detect when we are
1119 called with a socketpair and ignore FIELDES in this case. */
1122 rc
= assuan_init_pipe_server (&ctx
, filedes
);
1125 log_error ("failed to initialize the server: %s\n",
1129 rc
= register_commands (ctx
);
1132 log_error ("failed to the register commands with Assuan: %s\n",
1136 if (opt
.verbose
|| opt
.debug
)
1139 const char *s1
= getenv ("GPG_AGENT_INFO");
1140 const char *s2
= getenv ("DIRMNGR_INFO");
1149 opt
.config_filename
,
1154 assuan_set_hello_line (ctx
, tmp
);
1159 assuan_set_hello_line (ctx
, hello
);
1161 assuan_register_reset_notify (ctx
, reset_notify
);
1162 assuan_register_input_notify (ctx
, input_notify
);
1163 assuan_register_output_notify (ctx
, output_notify
);
1164 assuan_register_option_handler (ctx
, option_handler
);
1166 assuan_set_pointer (ctx
, &ctrl
);
1167 ctrl
.server_local
= xcalloc (1, sizeof *ctrl
.server_local
);
1168 ctrl
.server_local
->assuan_ctx
= ctx
;
1169 ctrl
.server_local
->message_fd
= -1;
1170 ctrl
.server_local
->list_internal
= 1;
1171 ctrl
.server_local
->list_external
= 0;
1172 ctrl
.server_local
->default_recplist
= default_recplist
;
1175 assuan_set_log_stream (ctx
, log_get_stream ());
1179 rc
= assuan_accept (ctx
);
1186 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc
));
1190 rc
= assuan_process (ctx
);
1193 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc
));
1198 gpgsm_release_certlist (ctrl
.server_local
->recplist
);
1199 ctrl
.server_local
->recplist
= NULL
;
1200 gpgsm_release_certlist (ctrl
.server_local
->signerlist
);
1201 ctrl
.server_local
->signerlist
= NULL
;
1202 xfree (ctrl
.server_local
);
1204 audit_release (ctrl
.audit
);
1207 assuan_deinit_server (ctx
);
1213 gpgsm_status2 (ctrl_t ctrl
, int no
, ...)
1215 gpg_error_t err
= 0;
1219 va_start (arg_ptr
, no
);
1221 if (ctrl
->no_server
&& ctrl
->status_fd
== -1)
1222 ; /* No status wanted. */
1223 else if (ctrl
->no_server
)
1227 if (ctrl
->status_fd
== 1)
1229 else if (ctrl
->status_fd
== 2)
1232 statusfp
= fdopen (ctrl
->status_fd
, "w");
1236 log_fatal ("can't open fd %d for status output: %s\n",
1237 ctrl
->status_fd
, strerror(errno
));
1241 fputs ("[GNUPG:] ", statusfp
);
1242 fputs (get_status_string (no
), statusfp
);
1244 while ( (text
= va_arg (arg_ptr
, const char*) ))
1246 putc ( ' ', statusfp
);
1247 for (; *text
; text
++)
1250 fputs ( "\\n", statusfp
);
1251 else if (*text
== '\r')
1252 fputs ( "\\r", statusfp
);
1254 putc ( *(const byte
*)text
, statusfp
);
1257 putc ('\n', statusfp
);
1262 assuan_context_t ctx
= ctrl
->server_local
->assuan_ctx
;
1268 while ( (text
= va_arg (arg_ptr
, const char *)) )
1275 for ( ; *text
&& n
< DIM (buf
)-2; n
++)
1279 err
= assuan_write_status (ctx
, get_status_string (no
), buf
);
1287 gpgsm_status (ctrl_t ctrl
, int no
, const char *text
)
1289 return gpgsm_status2 (ctrl
, no
, text
, NULL
);
1293 gpgsm_status_with_err_code (ctrl_t ctrl
, int no
, const char *text
,
1298 sprintf (buf
, "%u", (unsigned int)ec
);
1300 return gpgsm_status2 (ctrl
, no
, text
, buf
, NULL
);
1302 return gpgsm_status2 (ctrl
, no
, buf
, NULL
);
1306 /* Helper to notify the client about Pinentry events. Because that
1307 might disturb some older clients, this is only done when enabled
1308 via an option. Returns an gpg error code. */
1310 gpgsm_proxy_pinentry_notify (ctrl_t ctrl
, const unsigned char *line
)
1312 if (!ctrl
|| !ctrl
->server_local
1313 || !ctrl
->server_local
->allow_pinentry_notify
)
1315 return assuan_inquire (ctrl
->server_local
->assuan_ctx
, line
, NULL
, NULL
, 0);