1 /* server.c - server mode for gpg
2 * Copyright (C) 2006, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
35 #include "../common/sysutils.h"
39 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
42 /* Data used to associate an Assuan context with local server data. */
45 /* Our current Assuan context. */
46 assuan_context_t assuan_ctx;
47 /* File descriptor as set by the MESSAGE command. */
48 gnupg_fd_t message_fd;
50 /* List of prepared recipients. */
53 /* Set if pinentry notifications should be passed back to the
55 int allow_pinentry_notify;
60 /* Helper to close the message fd if it is open. */
62 close_message_fd (ctrl_t ctrl)
64 if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
66 assuan_sock_close (ctrl->server_local->message_fd);
67 ctrl->server_local->message_fd = GNUPG_INVALID_FD;
72 /* Skip over options. Blanks after the options are also removed. */
74 skip_options (const char *line)
78 while ( *line == '-' && line[1] == '-' )
80 while (*line && !spacep (line))
89 /* Check whether the option NAME appears in LINE. */
91 has_option (const char *line, const char *name)
94 int n = strlen (name);
96 s = strstr (line, name);
97 if (s && s >= skip_options (line))
99 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
106 /* Called by libassuan for Assuan options. See the Assuan manual for
109 option_handler (assuan_context_t ctx, const char *key, const char *value)
111 ctrl_t ctrl = assuan_get_pointer (ctx);
115 /* Fixme: Implement the tty and locale args. */
116 if (!strcmp (key, "display"))
119 else if (!strcmp (key, "ttyname"))
122 else if (!strcmp (key, "ttytype"))
125 else if (!strcmp (key, "lc-ctype"))
128 else if (!strcmp (key, "lc-messages"))
131 else if (!strcmp (key, "xauthority"))
134 else if (!strcmp (key, "pinentry_user_data"))
137 else if (!strcmp (key, "list-mode"))
139 /* This is for now a dummy option. */
141 else if (!strcmp (key, "allow-pinentry-notify"))
143 ctrl->server_local->allow_pinentry_notify = 1;
146 return gpg_error (GPG_ERR_UNKNOWN_OPTION);
152 /* Called by libassuan for RESET commands. */
154 reset_notify (assuan_context_t ctx, char *line)
156 ctrl_t ctrl = assuan_get_pointer (ctx);
160 release_pk_list (ctrl->server_local->recplist);
161 ctrl->server_local->recplist = NULL;
163 close_message_fd (ctrl);
164 assuan_close_input_fd (ctx);
165 assuan_close_output_fd (ctx);
170 /* Called by libassuan for INPUT commands. */
172 input_notify (assuan_context_t ctx, char *line)
174 /* ctrl_t ctrl = assuan_get_pointer (ctx); */
178 if (strstr (line, "--armor"))
180 else if (strstr (line, "--base64"))
182 else if (strstr (line, "--binary"))
186 /* FIXME (autodetect encoding) */
192 /* Called by libassuan for OUTPUT commands. */
194 output_notify (assuan_context_t ctx, char *line)
196 /* ctrl_t ctrl = assuan_get_pointer (ctx); */
200 if (strstr (line, "--armor"))
202 else if (strstr (line, "--base64"))
212 /* RECIPIENT [--hidden] <userID>
214 Set the recipient for the encryption. <userID> should be the
215 internal representation of the key; the server may accept any other
216 way of specification. If this is a valid and trusted recipient the
217 server does respond with OK, otherwise the return is an ERR with
218 the reason why the recipient can't be used, the encryption will
219 then not be done for this recipient. If the policy is not to
220 encrypt at all if not all recipients are valid, the client has to
221 take care of this. All RECIPIENT commands are cumulative until a
222 RESET or an successful ENCRYPT command. */
224 cmd_recipient (assuan_context_t ctx, char *line)
226 ctrl_t ctrl = assuan_get_pointer (ctx);
230 hidden = has_option (line,"--hidden");
231 line = skip_options (line);
233 /* FIXME: Expand groups
235 remusr = expand_group (rcpts);
240 err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden,
241 &ctrl->server_local->recplist);
244 log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
252 Set the signer's keys for the signature creation. <userID> should
253 be the internal representation of the key; the server may accept
254 any other way of specification. If this is a valid and usable
255 signing key the server does respond with OK, otherwise it returns
256 an ERR with the reason why the key can't be used, the signing will
257 then not be done for this key. If the policy is not to sign at all
258 if not all signer keys are valid, the client has to take care of
259 this. All SIGNER commands are cumulative until a RESET but they
260 are *not* reset by an SIGN command because it can be expected that
261 set of signers are used for more than one sign operation.
263 Note that this command returns an INV_RECP status which is a bit
264 strange, but they are very similar. */
266 cmd_signer (assuan_context_t ctx, char *line)
270 return gpg_error (GPG_ERR_NOT_SUPPORTED);
277 Do the actual encryption process. Takes the plaintext from the
278 INPUT command, writes the ciphertext to the file descriptor set
279 with the OUTPUT command, take the recipients from all the
280 recipients set so far with RECIPIENTS.
282 If this command fails the clients should try to delete all output
283 currently done or otherwise mark it as invalid. GPG does ensure
284 that there won't be any security problem with leftover data on the
287 In most cases this command won't fail because most necessary checks
288 have been done while setting the recipients. However some checks
289 can only be done right here and thus error may occur anyway (for
290 example, no recipients at all).
292 The input, output and message pipes are closed after this
295 cmd_encrypt (assuan_context_t ctx, char *line)
297 ctrl_t ctrl = assuan_get_pointer (ctx);
301 (void)line; /* LINE is not used. */
303 if ( !ctrl->server_local->recplist )
305 write_status_text (STATUS_NO_RECP, "0");
306 err = gpg_error (GPG_ERR_NO_USER_ID);
310 inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
313 err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
316 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
319 err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
324 /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
325 from the default list. */
327 /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
329 err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
330 ctrl->server_local->recplist,
334 /* Release the recipient list on success. */
337 release_pk_list (ctrl->server_local->recplist);
338 ctrl->server_local->recplist = NULL;
341 /* Close and reset the fds. */
342 close_message_fd (ctrl);
343 assuan_close_input_fd (ctx);
344 assuan_close_output_fd (ctx);
347 log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
355 This performs the decrypt operation. */
357 cmd_decrypt (assuan_context_t ctx, char *line)
359 ctrl_t ctrl = assuan_get_pointer (ctx);
363 (void)line; /* LINE is not used. */
365 inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
367 return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
368 out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
370 return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
372 glo_ctrl.lasterr = 0;
373 err = decrypt_message_fd (ctrl, inp_fd, out_fd);
375 err = glo_ctrl.lasterr;
377 /* Close and reset the fds. */
378 close_message_fd (ctrl);
379 assuan_close_input_fd (ctx);
380 assuan_close_output_fd (ctx);
383 log_error ("command '%s' failed: %s\n", "DECRYPT", gpg_strerror (err));
391 This does a verify operation on the message send to the input-FD.
392 The result is written out using status lines. If an output FD was
393 given, the signed text will be written to that.
395 If the signature is a detached one, the server will inquire about
396 the signed material and the client must provide it.
399 cmd_verify (assuan_context_t ctx, char *line)
402 #ifdef HAVE_W32_SYSTEM
405 rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
407 ctrl_t ctrl = assuan_get_pointer (ctx);
408 gnupg_fd_t fd = assuan_get_input_fd (ctx);
409 gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
410 estream_t out_fp = NULL;
412 /* FIXME: Revamp this code it is nearly to 3 years old and was only
413 intended as a quick test. */
417 if (fd == GNUPG_INVALID_FD)
418 return gpg_error (GPG_ERR_ASS_NO_INPUT);
420 if (out_fd != GNUPG_INVALID_FD)
424 #ifdef HAVE_W32_SYSTEM
425 syshd.type = ES_SYSHD_HANDLE;
426 syshd.u.handle = out_fd;
428 syshd.type = ES_SYSHD_FD;
431 out_fp = es_sysopen_nc (&syshd, "w");
433 return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
436 log_debug ("WARNING: The server mode is WORK "
437 "IN PROGRESS and not ready for use\n");
439 rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);
442 close_message_fd (ctrl);
443 assuan_close_input_fd (ctx);
444 assuan_close_output_fd (ctx);
448 log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
456 Sign the data set with the INPUT command and write it to the sink
457 set by OUTPUT. With "--detached" specified, a detached signature
460 cmd_sign (assuan_context_t ctx, char *line)
464 return gpg_error (GPG_ERR_NOT_SUPPORTED);
471 Import keys as read from the input-fd, return status message for
472 each imported one. The import checks the validity of the key. */
474 cmd_import (assuan_context_t ctx, char *line)
478 return gpg_error (GPG_ERR_NOT_SUPPORTED);
483 /* EXPORT [--data [--armor|--base64]] [--] pattern
485 Similar to the --export command line command, this command exports
486 public keys matching PATTERN. The output is send to the output fd
487 unless the --data option has been used in which case the output
488 gets send inline using regular data lines. The options "--armor"
489 and "--base" ospecify an output format if "--data" has been used.
490 Recall that in general the output format is set with the OUTPUT
494 cmd_export (assuan_context_t ctx, char *line)
498 return gpg_error (GPG_ERR_NOT_SUPPORTED);
508 cmd_delkeys (assuan_context_t ctx, char *line)
512 return gpg_error (GPG_ERR_NOT_SUPPORTED);
519 Set the file descriptor to read a message which is used with
520 detached signatures. */
522 cmd_message (assuan_context_t ctx, char *line)
526 ctrl_t ctrl = assuan_get_pointer (ctx);
528 rc = assuan_command_parse_fd (ctx, line, &fd);
531 if (fd == GNUPG_INVALID_FD)
532 return gpg_error (GPG_ERR_ASS_NO_INPUT);
533 ctrl->server_local->message_fd = fd;
539 /* LISTKEYS [<patterns>]
540 LISTSECRETKEYS [<patterns>]
545 do_listkeys (assuan_context_t ctx, char *line, int mode)
551 return gpg_error (GPG_ERR_NOT_SUPPORTED);
556 cmd_listkeys (assuan_context_t ctx, char *line)
558 return do_listkeys (ctx, line, 3);
563 cmd_listsecretkeys (assuan_context_t ctx, char *line)
565 return do_listkeys (ctx, line, 2);
572 Read the parameters in native format from the input fd and create a
576 cmd_genkey (assuan_context_t ctx, char *line)
580 return gpg_error (GPG_ERR_NOT_SUPPORTED);
586 Multipurpose function to return a variety of information.
587 Supported values for WHAT are:
589 version - Return the version of the program.
590 pid - Return the process id of the server.
594 cmd_getinfo (assuan_context_t ctx, char *line)
598 if (!strcmp (line, "version"))
600 const char *s = VERSION;
601 rc = assuan_send_data (ctx, s, strlen (s));
603 else if (!strcmp (line, "pid"))
607 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
608 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
611 rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
615 static const char hlp_passwd[] =
618 "Change the passphrase of the secret key for USERID.";
620 cmd_passwd (assuan_context_t ctx, char *line)
622 /* ctrl_t ctrl = assuan_get_pointer (ctx); */
626 line = skip_options (line);
628 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
636 /* Helper to register our commands with libassuan. */
638 register_commands (assuan_context_t ctx)
643 assuan_handler_t handler;
644 const char * const help;
646 { "RECIPIENT", cmd_recipient },
647 { "SIGNER", cmd_signer },
648 { "ENCRYPT", cmd_encrypt },
649 { "DECRYPT", cmd_decrypt },
650 { "VERIFY", cmd_verify },
651 { "SIGN", cmd_sign },
652 { "IMPORT", cmd_import },
653 { "EXPORT", cmd_export },
656 { "MESSAGE", cmd_message },
657 { "LISTKEYS", cmd_listkeys },
658 { "LISTSECRETKEYS",cmd_listsecretkeys },
659 { "GENKEY", cmd_genkey },
660 { "DELKEYS", cmd_delkeys },
661 { "GETINFO", cmd_getinfo },
662 { "PASSWD", cmd_passwd, hlp_passwd},
667 for (i=0; table[i].name; i++)
669 rc = assuan_register_command (ctx, table[i].name,
670 table[i].handler, table[i].help);
680 /* Startup the server. CTRL must have been allocated by the caller
681 and set to the default values. */
683 gpg_server (ctrl_t ctrl)
686 #ifndef HAVE_W32_SYSTEM
689 assuan_context_t ctx = NULL;
690 static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
693 /* We use a pipe based server so that we can work from scripts.
694 assuan_init_pipe_server will automagically detect when we are
695 called with a socketpair and ignore FILEDES in this case. */
696 #ifndef HAVE_W32_SYSTEM
697 filedes[0] = assuan_fdopen (0);
698 filedes[1] = assuan_fdopen (1);
700 rc = assuan_new (&ctx);
703 log_error ("failed to allocate the assuan context: %s\n",
708 #ifdef HAVE_W32_SYSTEM
709 rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
711 rc = assuan_init_pipe_server (ctx, filedes);
715 log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
719 rc = register_commands (ctx);
722 log_error ("failed to the register commands with Assuan: %s\n",
727 assuan_set_pointer (ctx, ctrl);
728 if (opt.verbose || opt.debug)
732 tmp = xtryasprintf ("Home: %s\n"
736 "fixme: need config filename",
740 assuan_set_hello_line (ctx, tmp);
745 assuan_set_hello_line (ctx, hello);
746 assuan_register_reset_notify (ctx, reset_notify);
747 assuan_register_input_notify (ctx, input_notify);
748 assuan_register_output_notify (ctx, output_notify);
749 assuan_register_option_handler (ctx, option_handler);
751 ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
752 if (!ctrl->server_local)
754 rc = gpg_error_from_syserror ();
757 ctrl->server_local->assuan_ctx = ctx;
758 ctrl->server_local->message_fd = GNUPG_INVALID_FD;
762 rc = assuan_accept (ctx);
770 log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
774 rc = assuan_process (ctx);
777 log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
783 if (ctrl->server_local)
785 release_pk_list (ctrl->server_local->recplist);
787 xfree (ctrl->server_local);
788 ctrl->server_local = NULL;
790 assuan_release (ctx);
795 /* Helper to notify the client about Pinentry events. Because that
796 might disturb some older clients, this is only done when enabled
797 via an option. If it is not enabled we tell Windows to allow
798 setting the foreground window right here. Returns an gpg error
801 gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
803 if (!ctrl || !ctrl->server_local
804 || !ctrl->server_local->allow_pinentry_notify)
806 gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
807 /* Client might be interested in that event - send as status line. */
808 if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
809 && (line[17]==' '||!line[17]))
811 for (line += 17; *line && spacep (line); line++)
813 write_status_text (STATUS_PINENTRY_LAUNCHED, line);
817 return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);