Line data Source code
1 : /* server.c - server mode for gpg
2 : * Copyright (C) 2006, 2008 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
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.
10 : *
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.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include <config.h>
21 : #include <errno.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <stdarg.h>
26 : #include <ctype.h>
27 : #include <unistd.h>
28 :
29 :
30 : #include "gpg.h"
31 : #include <assuan.h>
32 : #include "util.h"
33 : #include "i18n.h"
34 : #include "options.h"
35 : #include "../common/server-help.h"
36 : #include "../common/sysutils.h"
37 : #include "status.h"
38 :
39 :
40 : #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
41 :
42 :
43 : /* Data used to associate an Assuan context with local server data. */
44 : struct server_local_s
45 : {
46 : /* Our current Assuan context. */
47 : assuan_context_t assuan_ctx;
48 : /* File descriptor as set by the MESSAGE command. */
49 : gnupg_fd_t message_fd;
50 :
51 : /* List of prepared recipients. */
52 : pk_list_t recplist;
53 :
54 : /* Set if pinentry notifications should be passed back to the
55 : client. */
56 : int allow_pinentry_notify;
57 : };
58 :
59 :
60 :
61 : /* Helper to close the message fd if it is open. */
62 : static void
63 0 : close_message_fd (ctrl_t ctrl)
64 : {
65 0 : if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
66 : {
67 0 : assuan_sock_close (ctrl->server_local->message_fd);
68 0 : ctrl->server_local->message_fd = GNUPG_INVALID_FD;
69 : }
70 0 : }
71 :
72 :
73 : /* Called by libassuan for Assuan options. See the Assuan manual for
74 : details. */
75 : static gpg_error_t
76 0 : option_handler (assuan_context_t ctx, const char *key, const char *value)
77 : {
78 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
79 :
80 : (void)value;
81 :
82 : /* Fixme: Implement the tty and locale args. */
83 0 : if (!strcmp (key, "display"))
84 : {
85 : }
86 0 : else if (!strcmp (key, "ttyname"))
87 : {
88 : }
89 0 : else if (!strcmp (key, "ttytype"))
90 : {
91 : }
92 0 : else if (!strcmp (key, "lc-ctype"))
93 : {
94 : }
95 0 : else if (!strcmp (key, "lc-messages"))
96 : {
97 : }
98 0 : else if (!strcmp (key, "xauthority"))
99 : {
100 : }
101 0 : else if (!strcmp (key, "pinentry_user_data"))
102 : {
103 : }
104 0 : else if (!strcmp (key, "list-mode"))
105 : {
106 : /* This is for now a dummy option. */
107 : }
108 0 : else if (!strcmp (key, "allow-pinentry-notify"))
109 : {
110 0 : ctrl->server_local->allow_pinentry_notify = 1;
111 : }
112 : else
113 0 : return gpg_error (GPG_ERR_UNKNOWN_OPTION);
114 :
115 0 : return 0;
116 : }
117 :
118 :
119 : /* Called by libassuan for RESET commands. */
120 : static gpg_error_t
121 0 : reset_notify (assuan_context_t ctx, char *line)
122 : {
123 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
124 :
125 : (void)line;
126 :
127 0 : release_pk_list (ctrl->server_local->recplist);
128 0 : ctrl->server_local->recplist = NULL;
129 :
130 0 : close_message_fd (ctrl);
131 0 : assuan_close_input_fd (ctx);
132 0 : assuan_close_output_fd (ctx);
133 0 : return 0;
134 : }
135 :
136 :
137 : /* Called by libassuan for INPUT commands. */
138 : static gpg_error_t
139 0 : input_notify (assuan_context_t ctx, char *line)
140 : {
141 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
142 :
143 : (void)ctx;
144 :
145 0 : if (strstr (line, "--armor"))
146 : ; /* FIXME */
147 0 : else if (strstr (line, "--base64"))
148 : ; /* FIXME */
149 0 : else if (strstr (line, "--binary"))
150 : ;
151 : else
152 : {
153 : /* FIXME (autodetect encoding) */
154 : }
155 0 : return 0;
156 : }
157 :
158 :
159 : /* Called by libassuan for OUTPUT commands. */
160 : static gpg_error_t
161 0 : output_notify (assuan_context_t ctx, char *line)
162 : {
163 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
164 :
165 : (void)ctx;
166 :
167 0 : if (strstr (line, "--armor"))
168 : ; /* FIXME */
169 0 : else if (strstr (line, "--base64"))
170 : {
171 : /* FIXME */
172 : }
173 0 : return 0;
174 : }
175 :
176 :
177 :
178 :
179 : /* RECIPIENT [--hidden] <userID>
180 : RECIPIENT [--hidden] --file <filename>
181 :
182 : Set the recipient for the encryption. <userID> should be the
183 : internal representation of the key; the server may accept any other
184 : way of specification. If this is a valid and trusted recipient the
185 : server does respond with OK, otherwise the return is an ERR with
186 : the reason why the recipient can't be used, the encryption will
187 : then not be done for this recipient. If the policy is not to
188 : encrypt at all if not all recipients are valid, the client has to
189 : take care of this. All RECIPIENT commands are cumulative until a
190 : RESET or an successful ENCRYPT command. */
191 : static gpg_error_t
192 0 : cmd_recipient (assuan_context_t ctx, char *line)
193 : {
194 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
195 : gpg_error_t err;
196 : int hidden, file;
197 :
198 0 : hidden = has_option (line,"--hidden");
199 0 : file = has_option (line,"--file");
200 0 : line = skip_options (line);
201 :
202 : /* FIXME: Expand groups
203 : if (opt.grouplist)
204 : remusr = expand_group (rcpts);
205 : else
206 : remusr = rcpts;
207 : */
208 :
209 0 : err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden, file,
210 0 : &ctrl->server_local->recplist);
211 :
212 0 : if (err)
213 0 : log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
214 0 : return err;
215 : }
216 :
217 :
218 :
219 : /* SIGNER <userID>
220 :
221 : Set the signer's keys for the signature creation. <userID> should
222 : be the internal representation of the key; the server may accept
223 : any other way of specification. If this is a valid and usable
224 : signing key the server does respond with OK, otherwise it returns
225 : an ERR with the reason why the key can't be used, the signing will
226 : then not be done for this key. If the policy is not to sign at all
227 : if not all signer keys are valid, the client has to take care of
228 : this. All SIGNER commands are cumulative until a RESET but they
229 : are *not* reset by an SIGN command because it can be expected that
230 : set of signers are used for more than one sign operation.
231 :
232 : Note that this command returns an INV_RECP status which is a bit
233 : strange, but they are very similar. */
234 : static gpg_error_t
235 0 : cmd_signer (assuan_context_t ctx, char *line)
236 : {
237 : (void)ctx;
238 : (void)line;
239 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
240 : }
241 :
242 :
243 :
244 : /* ENCRYPT
245 :
246 : Do the actual encryption process. Takes the plaintext from the
247 : INPUT command, writes the ciphertext to the file descriptor set
248 : with the OUTPUT command, take the recipients from all the
249 : recipients set so far with RECIPIENTS.
250 :
251 : If this command fails the clients should try to delete all output
252 : currently done or otherwise mark it as invalid. GPG does ensure
253 : that there won't be any security problem with leftover data on the
254 : output in this case.
255 :
256 : In most cases this command won't fail because most necessary checks
257 : have been done while setting the recipients. However some checks
258 : can only be done right here and thus error may occur anyway (for
259 : example, no recipients at all).
260 :
261 : The input, output and message pipes are closed after this
262 : command. */
263 : static gpg_error_t
264 0 : cmd_encrypt (assuan_context_t ctx, char *line)
265 : {
266 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
267 : gpg_error_t err;
268 : int inp_fd, out_fd;
269 :
270 : (void)line; /* LINE is not used. */
271 :
272 0 : if ( !ctrl->server_local->recplist )
273 : {
274 0 : write_status_text (STATUS_NO_RECP, "0");
275 0 : err = gpg_error (GPG_ERR_NO_USER_ID);
276 0 : goto leave;
277 : }
278 :
279 0 : inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
280 0 : if (inp_fd == -1)
281 : {
282 0 : err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
283 0 : goto leave;
284 : }
285 0 : out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
286 0 : if (out_fd == -1)
287 : {
288 0 : err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
289 0 : goto leave;
290 : }
291 :
292 :
293 : /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
294 : from the default list. */
295 :
296 : /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
297 :
298 0 : err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
299 0 : ctrl->server_local->recplist,
300 : out_fd);
301 :
302 : leave:
303 : /* Release the recipient list on success. */
304 0 : if (!err)
305 : {
306 0 : release_pk_list (ctrl->server_local->recplist);
307 0 : ctrl->server_local->recplist = NULL;
308 : }
309 :
310 : /* Close and reset the fds. */
311 0 : close_message_fd (ctrl);
312 0 : assuan_close_input_fd (ctx);
313 0 : assuan_close_output_fd (ctx);
314 :
315 0 : if (err)
316 0 : log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
317 0 : return err;
318 : }
319 :
320 :
321 :
322 : /* DECRYPT
323 :
324 : This performs the decrypt operation. */
325 : static gpg_error_t
326 0 : cmd_decrypt (assuan_context_t ctx, char *line)
327 : {
328 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
329 : gpg_error_t err;
330 : int inp_fd, out_fd;
331 :
332 : (void)line; /* LINE is not used. */
333 :
334 0 : inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
335 0 : if (inp_fd == -1)
336 0 : return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
337 0 : out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
338 0 : if (out_fd == -1)
339 0 : return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
340 :
341 0 : glo_ctrl.lasterr = 0;
342 0 : err = decrypt_message_fd (ctrl, inp_fd, out_fd);
343 0 : if (!err)
344 0 : err = glo_ctrl.lasterr;
345 :
346 : /* Close and reset the fds. */
347 0 : close_message_fd (ctrl);
348 0 : assuan_close_input_fd (ctx);
349 0 : assuan_close_output_fd (ctx);
350 :
351 0 : if (err)
352 0 : log_error ("command '%s' failed: %s\n", "DECRYPT", gpg_strerror (err));
353 0 : return err;
354 : }
355 :
356 :
357 :
358 : /* VERIFY
359 :
360 : This does a verify operation on the message send to the input-FD.
361 : The result is written out using status lines. If an output FD was
362 : given, the signed text will be written to that.
363 :
364 : If the signature is a detached one, the server will inquire about
365 : the signed material and the client must provide it.
366 : */
367 : static gpg_error_t
368 0 : cmd_verify (assuan_context_t ctx, char *line)
369 : {
370 : int rc;
371 : #ifdef HAVE_W32_SYSTEM
372 : (void)ctx;
373 : (void)line;
374 : rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
375 : #else
376 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
377 0 : gnupg_fd_t fd = assuan_get_input_fd (ctx);
378 0 : gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
379 0 : estream_t out_fp = NULL;
380 :
381 : /* FIXME: Revamp this code it is nearly to 3 years old and was only
382 : intended as a quick test. */
383 :
384 : (void)line;
385 :
386 0 : if (fd == GNUPG_INVALID_FD)
387 0 : return gpg_error (GPG_ERR_ASS_NO_INPUT);
388 :
389 0 : if (out_fd != GNUPG_INVALID_FD)
390 : {
391 : es_syshd_t syshd;
392 :
393 : #ifdef HAVE_W32_SYSTEM
394 : syshd.type = ES_SYSHD_HANDLE;
395 : syshd.u.handle = out_fd;
396 : #else
397 0 : syshd.type = ES_SYSHD_FD;
398 0 : syshd.u.fd = out_fd;
399 : #endif
400 0 : out_fp = es_sysopen_nc (&syshd, "w");
401 0 : if (!out_fp)
402 0 : return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
403 : }
404 :
405 0 : log_debug ("WARNING: The server mode is WORK "
406 : "IN PROGRESS and not ready for use\n");
407 :
408 0 : rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);
409 :
410 0 : es_fclose (out_fp);
411 0 : close_message_fd (ctrl);
412 0 : assuan_close_input_fd (ctx);
413 0 : assuan_close_output_fd (ctx);
414 : #endif
415 :
416 0 : if (rc)
417 0 : log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
418 0 : return rc;
419 : }
420 :
421 :
422 :
423 : /* SIGN [--detached]
424 :
425 : Sign the data set with the INPUT command and write it to the sink
426 : set by OUTPUT. With "--detached" specified, a detached signature
427 : is created. */
428 : static gpg_error_t
429 0 : cmd_sign (assuan_context_t ctx, char *line)
430 : {
431 : (void)ctx;
432 : (void)line;
433 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
434 : }
435 :
436 :
437 :
438 : /* IMPORT
439 :
440 : Import keys as read from the input-fd, return status message for
441 : each imported one. The import checks the validity of the key. */
442 : static gpg_error_t
443 0 : cmd_import (assuan_context_t ctx, char *line)
444 : {
445 : (void)ctx;
446 : (void)line;
447 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
448 : }
449 :
450 :
451 :
452 : /* EXPORT [--data [--armor|--base64]] [--] pattern
453 :
454 : Similar to the --export command line command, this command exports
455 : public keys matching PATTERN. The output is send to the output fd
456 : unless the --data option has been used in which case the output
457 : gets send inline using regular data lines. The options "--armor"
458 : and "--base" ospecify an output format if "--data" has been used.
459 : Recall that in general the output format is set with the OUTPUT
460 : command.
461 : */
462 : static gpg_error_t
463 0 : cmd_export (assuan_context_t ctx, char *line)
464 : {
465 : (void)ctx;
466 : (void)line;
467 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
468 : }
469 :
470 :
471 :
472 : /* DELKEYS
473 :
474 : Fixme
475 : */
476 : static gpg_error_t
477 0 : cmd_delkeys (assuan_context_t ctx, char *line)
478 : {
479 : (void)ctx;
480 : (void)line;
481 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
482 : }
483 :
484 :
485 :
486 : /* MESSAGE FD[=<n>]
487 :
488 : Set the file descriptor to read a message which is used with
489 : detached signatures. */
490 : static gpg_error_t
491 0 : cmd_message (assuan_context_t ctx, char *line)
492 : {
493 : int rc;
494 : gnupg_fd_t fd;
495 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
496 :
497 0 : rc = assuan_command_parse_fd (ctx, line, &fd);
498 0 : if (rc)
499 0 : return rc;
500 0 : if (fd == GNUPG_INVALID_FD)
501 0 : return gpg_error (GPG_ERR_ASS_NO_INPUT);
502 0 : ctrl->server_local->message_fd = fd;
503 0 : return 0;
504 : }
505 :
506 :
507 :
508 : /* LISTKEYS [<patterns>]
509 : LISTSECRETKEYS [<patterns>]
510 :
511 : fixme
512 : */
513 : static gpg_error_t
514 0 : do_listkeys (assuan_context_t ctx, char *line, int mode)
515 : {
516 : (void)ctx;
517 : (void)line;
518 : (void)mode;
519 :
520 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
521 : }
522 :
523 :
524 : static gpg_error_t
525 0 : cmd_listkeys (assuan_context_t ctx, char *line)
526 : {
527 0 : return do_listkeys (ctx, line, 3);
528 : }
529 :
530 :
531 : static gpg_error_t
532 0 : cmd_listsecretkeys (assuan_context_t ctx, char *line)
533 : {
534 0 : return do_listkeys (ctx, line, 2);
535 : }
536 :
537 :
538 :
539 : /* GENKEY
540 :
541 : Read the parameters in native format from the input fd and create a
542 : new OpenPGP key.
543 : */
544 : static gpg_error_t
545 0 : cmd_genkey (assuan_context_t ctx, char *line)
546 : {
547 : (void)ctx;
548 : (void)line;
549 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
550 : }
551 :
552 :
553 : /* GETINFO <what>
554 :
555 : Multipurpose function to return a variety of information.
556 : Supported values for WHAT are:
557 :
558 : version - Return the version of the program.
559 : pid - Return the process id of the server.
560 :
561 : */
562 : static gpg_error_t
563 0 : cmd_getinfo (assuan_context_t ctx, char *line)
564 : {
565 : int rc;
566 :
567 0 : if (!strcmp (line, "version"))
568 : {
569 0 : const char *s = VERSION;
570 0 : rc = assuan_send_data (ctx, s, strlen (s));
571 : }
572 0 : else if (!strcmp (line, "pid"))
573 : {
574 : char numbuf[50];
575 :
576 0 : snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
577 0 : rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
578 : }
579 : else
580 0 : rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
581 0 : return rc;
582 : }
583 :
584 : static const char hlp_passwd[] =
585 : "PASSWD <userID>\n"
586 : "\n"
587 : "Change the passphrase of the secret key for USERID.";
588 : static gpg_error_t
589 0 : cmd_passwd (assuan_context_t ctx, char *line)
590 : {
591 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
592 : gpg_error_t err;
593 :
594 : (void)ctx;
595 : (void)line;
596 : /* line = skip_options (line); */
597 :
598 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
599 :
600 0 : return err;
601 : }
602 :
603 :
604 :
605 :
606 : /* Helper to register our commands with libassuan. */
607 : static int
608 0 : register_commands (assuan_context_t ctx)
609 : {
610 : static struct
611 : {
612 : const char *name;
613 : assuan_handler_t handler;
614 : const char * const help;
615 : } table[] = {
616 : { "RECIPIENT", cmd_recipient },
617 : { "SIGNER", cmd_signer },
618 : { "ENCRYPT", cmd_encrypt },
619 : { "DECRYPT", cmd_decrypt },
620 : { "VERIFY", cmd_verify },
621 : { "SIGN", cmd_sign },
622 : { "IMPORT", cmd_import },
623 : { "EXPORT", cmd_export },
624 : { "INPUT", NULL },
625 : { "OUTPUT", NULL },
626 : { "MESSAGE", cmd_message },
627 : { "LISTKEYS", cmd_listkeys },
628 : { "LISTSECRETKEYS",cmd_listsecretkeys },
629 : { "GENKEY", cmd_genkey },
630 : { "DELKEYS", cmd_delkeys },
631 : { "GETINFO", cmd_getinfo },
632 : { "PASSWD", cmd_passwd, hlp_passwd},
633 : { NULL }
634 : };
635 : int i, rc;
636 :
637 0 : for (i=0; table[i].name; i++)
638 : {
639 0 : rc = assuan_register_command (ctx, table[i].name,
640 : table[i].handler, table[i].help);
641 0 : if (rc)
642 0 : return rc;
643 : }
644 0 : return 0;
645 : }
646 :
647 :
648 :
649 :
650 : /* Startup the server. CTRL must have been allocated by the caller
651 : and set to the default values. */
652 : int
653 0 : gpg_server (ctrl_t ctrl)
654 : {
655 : int rc;
656 : #ifndef HAVE_W32_SYSTEM
657 : int filedes[2];
658 : #endif
659 0 : assuan_context_t ctx = NULL;
660 : static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
661 : VERSION " ready");
662 :
663 : /* We use a pipe based server so that we can work from scripts.
664 : assuan_init_pipe_server will automagically detect when we are
665 : called with a socketpair and ignore FILEDES in this case. */
666 : #ifndef HAVE_W32_SYSTEM
667 0 : filedes[0] = assuan_fdopen (0);
668 0 : filedes[1] = assuan_fdopen (1);
669 : #endif
670 0 : rc = assuan_new (&ctx);
671 0 : if (rc)
672 : {
673 0 : log_error ("failed to allocate the assuan context: %s\n",
674 : gpg_strerror (rc));
675 0 : goto leave;
676 : }
677 :
678 : #ifdef HAVE_W32_SYSTEM
679 : rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
680 : #else
681 0 : rc = assuan_init_pipe_server (ctx, filedes);
682 : #endif
683 0 : if (rc)
684 : {
685 0 : log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
686 0 : goto leave;
687 : }
688 :
689 0 : rc = register_commands (ctx);
690 0 : if (rc)
691 : {
692 0 : log_error ("failed to the register commands with Assuan: %s\n",
693 : gpg_strerror(rc));
694 0 : goto leave;
695 : }
696 :
697 0 : assuan_set_pointer (ctx, ctrl);
698 0 : if (opt.verbose || opt.debug)
699 0 : {
700 : char *tmp;
701 :
702 0 : tmp = xtryasprintf ("Home: %s\n"
703 : "Config: %s\n"
704 : "%s",
705 : gnupg_homedir (),
706 : "fixme: need config filename",
707 : hello);
708 0 : if (tmp)
709 : {
710 0 : assuan_set_hello_line (ctx, tmp);
711 0 : xfree (tmp);
712 : }
713 : }
714 : else
715 0 : assuan_set_hello_line (ctx, hello);
716 0 : assuan_register_reset_notify (ctx, reset_notify);
717 0 : assuan_register_input_notify (ctx, input_notify);
718 0 : assuan_register_output_notify (ctx, output_notify);
719 0 : assuan_register_option_handler (ctx, option_handler);
720 :
721 0 : ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
722 0 : if (!ctrl->server_local)
723 : {
724 0 : rc = gpg_error_from_syserror ();
725 0 : goto leave;
726 : }
727 0 : ctrl->server_local->assuan_ctx = ctx;
728 0 : ctrl->server_local->message_fd = GNUPG_INVALID_FD;
729 :
730 : for (;;)
731 : {
732 0 : rc = assuan_accept (ctx);
733 0 : if (rc == -1)
734 : {
735 0 : rc = 0;
736 0 : break;
737 : }
738 0 : else if (rc)
739 : {
740 0 : log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
741 0 : break;
742 : }
743 :
744 0 : rc = assuan_process (ctx);
745 0 : if (rc)
746 : {
747 0 : log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
748 0 : continue;
749 : }
750 0 : }
751 :
752 : leave:
753 0 : if (ctrl->server_local)
754 : {
755 0 : release_pk_list (ctrl->server_local->recplist);
756 :
757 0 : xfree (ctrl->server_local);
758 0 : ctrl->server_local = NULL;
759 : }
760 0 : assuan_release (ctx);
761 0 : return rc;
762 : }
763 :
764 :
765 : /* Helper to notify the client about Pinentry events. Because that
766 : might disturb some older clients, this is only done when enabled
767 : via an option. If it is not enabled we tell Windows to allow
768 : setting the foreground window right here. Returns an gpg error
769 : code. */
770 : gpg_error_t
771 5 : gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
772 : {
773 5 : if (opt.verbose)
774 : {
775 0 : char *linecopy = xtrystrdup (line);
776 : char *fields[4];
777 :
778 0 : if (linecopy
779 0 : && split_fields (linecopy, fields, DIM (fields)) >= 4
780 0 : && !strcmp (fields[0], "PINENTRY_LAUNCHED"))
781 0 : log_info (_("pinentry launched (pid %s, flavor %s, version %s)\n"),
782 : fields[1], fields[2], fields[3]);
783 :
784 0 : xfree (linecopy);
785 : }
786 :
787 5 : if (!ctrl || !ctrl->server_local
788 0 : || !ctrl->server_local->allow_pinentry_notify)
789 : {
790 5 : gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
791 : /* Client might be interested in that event - send as status line. */
792 5 : if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
793 5 : && (line[17]==' '||!line[17]))
794 : {
795 5 : for (line += 17; *line && spacep (line); line++)
796 : ;
797 5 : write_status_text (STATUS_PINENTRY_LAUNCHED, line);
798 : }
799 5 : return 0;
800 : }
801 0 : return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
802 : }
|