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/>.
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. */
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
=
62 data_line_cookie_write
,
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; */
73 strcpy_escaped_plus (char *d
, const char *s
)
77 if (*s
== '%' && s
[1] && s
[2])
93 Blanks after the options are also removed. */
95 skip_options (const char *line
)
99 while ( *line
== '-' && line
[1] == '-' )
101 while (*line
&& !spacep (line
))
103 while (spacep (line
))
110 /* Check whether the option NAME appears in LINE */
112 has_option (const char *line
, const char *name
)
115 int n
= strlen (name
);
117 s
= strstr (line
, name
);
118 if (s
&& s
>= skip_options (line
))
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
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
))
141 data_line_cookie_close (void *cookie
)
143 assuan_context_t ctx
= cookie
;
145 if (assuan_send_data (ctx
, NULL
, 0))
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. */
168 start_audit_session (ctrl_t ctrl
)
170 audit_release (ctrl
->audit
);
172 if (ctrl
->server_local
->enable_audit_log
&& !(ctrl
->audit
= audit_new ()) )
173 return gpg_error_from_syserror ();
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"))
195 opt
.display
= strdup (value
);
197 return out_of_core ();
199 else if (!strcmp (key
, "ttyname"))
203 opt
.ttyname
= strdup (value
);
205 return out_of_core ();
207 else if (!strcmp (key
, "ttytype"))
211 opt
.ttytype
= strdup (value
);
213 return out_of_core ();
215 else if (!strcmp (key
, "lc-ctype"))
219 opt
.lc_ctype
= strdup (value
);
221 return out_of_core ();
223 else if (!strcmp (key
, "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"))
234 free (opt
.xauthority
);
235 opt
.xauthority
= strdup (value
);
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;
257 ctrl
->server_local
->list_internal
= 0;
258 ctrl
->server_local
->list_external
= 1;
262 ctrl
->server_local
->list_internal
= 1;
263 ctrl
->server_local
->list_external
= 1;
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
;
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
;
296 return gpg_error (GPG_ERR_UNKNOWN_OPTION
);
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
);
320 input_notify (assuan_context_t ctx
, const char *line
)
322 ctrl_t ctrl
= assuan_get_pointer (ctx
);
324 ctrl
->autodetect_encoding
= 0;
327 if (strstr (line
, "--armor"))
329 else if (strstr (line
, "--base64"))
331 else if (strstr (line
, "--binary"))
334 ctrl
->autodetect_encoding
= 1;
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. */
364 cmd_recipient (assuan_context_t ctx
, char *line
)
366 ctrl_t ctrl
= assuan_get_pointer (ctx
);
370 rc
= start_audit_session (ctrl
);
375 rc
= gpgsm_add_to_certlist (ctrl
, line
, 0,
376 &ctrl
->server_local
->recplist
, 0);
379 gpg_err_code_t r
= gpg_err_code (rc
);
380 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
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":
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
412 Note that this command returns an INV_RECP status which is a bit
413 strange, but they are very similar. */
415 cmd_signer (assuan_context_t ctx
, char *line
)
417 ctrl_t ctrl
= assuan_get_pointer (ctx
);
420 rc
= gpgsm_add_to_certlist (ctrl
, line
, 1,
421 &ctrl
->server_local
->signerlist
, 0);
424 gpg_err_code_t r
= gpg_err_code (rc
);
425 gpgsm_status2 (ctrl
, STATUS_INV_RECP
,
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":
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
458 cmd_encrypt (assuan_context_t ctx
, char *line
)
460 ctrl_t ctrl
= assuan_get_pointer (ctx
);
466 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
468 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
469 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
471 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
473 out_fp
= fdopen (dup (out_fd
), "w");
475 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
477 /* Now add all encrypt-to marked recipients from the default
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);
488 rc
= ctrl
->audit
? 0 : start_audit_session (ctrl
);
490 rc
= gpgsm_encrypt (assuan_get_pointer (ctx
),
491 ctrl
->server_local
->recplist
,
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
);
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. */
513 cmd_decrypt (assuan_context_t ctx
, char *line
)
515 ctrl_t ctrl
= assuan_get_pointer (ctx
);
520 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
522 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
523 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
525 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
527 out_fp
= fdopen (dup(out_fd
), "w");
529 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
531 rc
= start_audit_session (ctrl
);
533 rc
= gpgsm_decrypt (ctrl
, inp_fd
, 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
);
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.
555 cmd_verify (assuan_context_t ctx
, char *line
)
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);
564 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
568 out_fp
= fdopen ( dup(out_fd
), "w");
570 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
573 rc
= start_audit_session (ctrl
);
575 rc
= gpgsm_verify (assuan_get_pointer (ctx
), fd
,
576 ctrl
->server_local
->message_fd
, 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
);
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). */
595 cmd_sign (assuan_context_t ctx
, char *line
)
597 ctrl_t ctrl
= assuan_get_pointer (ctx
);
603 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
605 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
606 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 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");
614 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
616 rc
= start_audit_session (ctrl
);
618 rc
= gpgsm_sign (assuan_get_pointer (ctx
), ctrl
->server_local
->signerlist
,
619 inp_fd
, detached
, 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
);
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. */
638 cmd_import (assuan_context_t ctx
, char *line
)
640 ctrl_t ctrl
= assuan_get_pointer (ctx
);
642 int fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
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
);
658 /* EXPORT [--data [--armor|--base64]] [--] pattern
663 cmd_export (assuan_context_t ctx
, char *line
)
665 ctrl_t ctrl
= assuan_get_pointer (ctx
);
670 use_data
= has_option (line
, "--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. */
683 for (p
=line
; *p
; line
= p
)
685 while (*p
&& *p
!= ' ')
691 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
695 return out_of_core ();
698 strcpy_escaped_plus (sl
->d
, line
);
708 stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
712 return set_error (GPG_ERR_ASS_GENERAL
,
713 "error setting up a data stream");
715 gpgsm_export (ctrl
, list
, NULL
, stream
);
720 int fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
726 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
728 out_fp
= fdopen ( dup(fd
), "w");
732 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
735 gpgsm_export (ctrl
, list
, out_fp
, NULL
);
740 /* Close and reset the fds. */
741 close_message_fd (ctrl
);
742 assuan_close_input_fd (ctx
);
743 assuan_close_output_fd (ctx
);
749 cmd_delkeys (assuan_context_t ctx
, char *line
)
751 ctrl_t ctrl
= assuan_get_pointer (ctx
);
756 /* break the line down into an strlist_t */
758 for (p
=line
; *p
; line
= p
)
760 while (*p
&& *p
!= ' ')
766 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
770 return out_of_core ();
773 strcpy_escaped_plus (sl
->d
, line
);
779 rc
= gpgsm_delete (ctrl
, list
);
782 /* close and reset the fd */
783 close_message_fd (ctrl
);
784 assuan_close_input_fd (ctx
);
785 assuan_close_output_fd (ctx
);
794 Set the file descriptor to read a message which is used with
795 detached signatures */
797 cmd_message (assuan_context_t ctx
, char *line
)
802 ctrl_t ctrl
= assuan_get_pointer (ctx
);
804 rc
= assuan_command_parse_fd (ctx
, line
, &sysfd
);
807 fd
= translate_sys2libc_fd (sysfd
, 0);
809 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
810 ctrl
->server_local
->message_fd
= fd
;
814 /* LISTKEYS [<patterns>]
815 DUMPKEYS [<patterns>]
816 LISTSECRETKEYS [<patterns>]
817 DUMPSECRETKEYS [<patterns>]
820 do_listkeys (assuan_context_t ctx
, char *line
, int mode
)
822 ctrl_t ctrl
= assuan_get_pointer (ctx
);
826 unsigned int listmode
;
829 /* Break the line down into an strlist. */
831 for (p
=line
; *p
; line
= p
)
833 while (*p
&& *p
!= ' ')
839 sl
= xtrymalloc (sizeof *sl
+ strlen (line
));
843 return out_of_core ();
846 strcpy_escaped_plus (sl
->d
, line
);
852 if (ctrl
->server_local
->list_to_output
)
854 int outfd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
857 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
858 fp
= es_fdopen ( dup (outfd
), "w");
860 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
864 fp
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
866 return set_error (GPG_ERR_ASS_GENERAL
,
867 "error setting up a data stream");
870 ctrl
->with_colons
= 1;
872 if (ctrl
->server_local
->list_internal
)
874 if (ctrl
->server_local
->list_external
)
876 err
= gpgsm_list_keys (assuan_get_pointer (ctx
), list
, fp
, listmode
);
879 if (ctrl
->server_local
->list_to_output
)
880 assuan_close_output_fd (ctx
);
885 cmd_listkeys (assuan_context_t ctx
, char *line
)
887 return do_listkeys (ctx
, line
, 3);
891 cmd_dumpkeys (assuan_context_t ctx
, char *line
)
893 return do_listkeys (ctx
, line
, 259);
897 cmd_listsecretkeys (assuan_context_t ctx
, char *line
)
899 return do_listkeys (ctx
, line
, 2);
903 cmd_dumpsecretkeys (assuan_context_t ctx
, char *line
)
905 return do_listkeys (ctx
, line
, 258);
911 Read the parameters in native format from the input fd and write a
912 certificate request to the output.
915 cmd_genkey (assuan_context_t ctx
, char *line
)
917 ctrl_t ctrl
= assuan_get_pointer (ctx
);
923 inp_fd
= translate_sys2libc_fd (assuan_get_input_fd (ctx
), 0);
925 return set_error (GPG_ERR_ASS_NO_INPUT
, NULL
);
926 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
928 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
930 in_stream
= es_fdopen_nc (inp_fd
, "r");
932 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen failed");
934 out_fp
= fdopen ( dup(out_fd
), "w");
937 es_fclose (in_stream
);
938 return set_error (GPG_ERR_ASS_GENERAL
, "fdopen() failed");
940 rc
= gpgsm_genkey (ctrl
, in_stream
, out_fp
);
943 /* close and reset the fds */
944 assuan_close_input_fd (ctx
);
945 assuan_close_output_fd (ctx
);
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.
963 cmd_getauditlog (assuan_context_t ctx
, char *line
)
965 ctrl_t ctrl
= assuan_get_pointer (ctx
);
967 estream_t out_stream
;
968 int opt_data
, opt_html
;
971 opt_data
= has_option (line
, "--data");
972 opt_html
= has_option (line
, "--html");
973 line
= skip_options (line
);
976 return gpg_error (GPG_ERR_NO_DATA
);
980 out_stream
= es_fopencookie (ctx
, "w", data_line_cookie_functions
);
982 return set_error (GPG_ERR_ASS_GENERAL
,
983 "error setting up a data stream");
987 out_fd
= translate_sys2libc_fd (assuan_get_output_fd (ctx
), 1);
989 return set_error (GPG_ERR_ASS_NO_OUTPUT
, NULL
);
991 out_stream
= es_fdopen_nc ( dup (out_fd
), "w");
994 return set_error (GPG_ERR_ASS_GENERAL
, "es_fdopen() failed");
998 audit_print_result (ctrl
->audit
, out_stream
, opt_html
);
1001 es_fclose (out_stream
);
1003 /* Close and reset the fd. */
1005 assuan_close_output_fd (ctx
);
1013 /* Tell the assuan library about our commands */
1015 register_commands (assuan_context_t ctx
)
1019 int (*handler
)(assuan_context_t
, char *line
);
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
},
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
},
1043 for (i
=0; table
[i
].name
; i
++)
1045 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
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. */
1056 gpgsm_server (certlist_t default_recplist
)
1060 assuan_context_t ctx
;
1061 struct server_control_s ctrl
;
1062 static const char hello
[] = ("GNU Privacy Guard's S/M server "
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. */
1073 rc
= assuan_init_pipe_server (&ctx
, filedes
);
1076 log_error ("failed to initialize the server: %s\n",
1080 rc
= register_commands (ctx
);
1083 log_error ("failed to the register commands with Assuan: %s\n",
1087 if (opt
.verbose
|| opt
.debug
)
1090 const char *s1
= getenv ("GPG_AGENT_INFO");
1091 const char *s2
= getenv ("DIRMNGR_INFO");
1100 opt
.config_filename
,
1105 assuan_set_hello_line (ctx
, tmp
);
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
;
1126 assuan_set_log_stream (ctx
, log_get_stream ());
1130 rc
= assuan_accept (ctx
);
1137 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc
));
1141 rc
= assuan_process (ctx
);
1144 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc
));
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
);
1158 assuan_deinit_server (ctx
);
1164 gpgsm_status2 (ctrl_t ctrl
, int no
, ...)
1166 gpg_error_t err
= 0;
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
)
1178 if (ctrl
->status_fd
== 1)
1180 else if (ctrl
->status_fd
== 2)
1183 statusfp
= fdopen (ctrl
->status_fd
, "w");
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
++)
1201 fputs ( "\\n", statusfp
);
1202 else if (*text
== '\r')
1203 fputs ( "\\r", statusfp
);
1205 putc ( *(const byte
*)text
, statusfp
);
1208 putc ('\n', statusfp
);
1213 assuan_context_t ctx
= ctrl
->server_local
->assuan_ctx
;
1219 while ( (text
= va_arg (arg_ptr
, const char *)) )
1226 for ( ; *text
&& n
< DIM (buf
)-2; n
++)
1230 err
= assuan_write_status (ctx
, get_status_string (no
), buf
);
1238 gpgsm_status (ctrl_t ctrl
, int no
, const char *text
)
1240 return gpgsm_status2 (ctrl
, no
, text
, NULL
);
1244 gpgsm_status_with_err_code (ctrl_t ctrl
, int no
, const char *text
,
1249 sprintf (buf
, "%u", (unsigned int)ec
);
1251 return gpgsm_status2 (ctrl
, no
, text
, buf
, NULL
);
1253 return gpgsm_status2 (ctrl
, no
, buf
, NULL
);