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 <http://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/sysutils.h"
36 : #include "status.h"
37 :
38 :
39 : #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
40 :
41 :
42 : /* Data used to associate an Assuan context with local server data. */
43 : struct server_local_s
44 : {
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;
49 :
50 : /* List of prepared recipients. */
51 : pk_list_t recplist;
52 :
53 : /* Set if pinentry notifications should be passed back to the
54 : client. */
55 : int allow_pinentry_notify;
56 : };
57 :
58 :
59 :
60 : /* Helper to close the message fd if it is open. */
61 : static void
62 0 : close_message_fd (ctrl_t ctrl)
63 : {
64 0 : if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
65 : {
66 0 : assuan_sock_close (ctrl->server_local->message_fd);
67 0 : ctrl->server_local->message_fd = GNUPG_INVALID_FD;
68 : }
69 0 : }
70 :
71 :
72 : /* Skip over options. Blanks after the options are also removed. */
73 : static char *
74 0 : skip_options (const char *line)
75 : {
76 0 : while (spacep (line))
77 0 : line++;
78 0 : while ( *line == '-' && line[1] == '-' )
79 : {
80 0 : while (*line && !spacep (line))
81 0 : line++;
82 0 : while (spacep (line))
83 0 : line++;
84 : }
85 0 : return (char*)line;
86 : }
87 :
88 :
89 : /* Check whether the option NAME appears in LINE. */
90 : static int
91 0 : has_option (const char *line, const char *name)
92 : {
93 : const char *s;
94 0 : int n = strlen (name);
95 :
96 0 : s = strstr (line, name);
97 0 : if (s && s >= skip_options (line))
98 0 : return 0;
99 0 : return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
100 : }
101 :
102 :
103 :
104 :
105 :
106 : /* Called by libassuan for Assuan options. See the Assuan manual for
107 : details. */
108 : static gpg_error_t
109 0 : option_handler (assuan_context_t ctx, const char *key, const char *value)
110 : {
111 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
112 :
113 : (void)value;
114 :
115 : /* Fixme: Implement the tty and locale args. */
116 0 : if (!strcmp (key, "display"))
117 : {
118 : }
119 0 : else if (!strcmp (key, "ttyname"))
120 : {
121 : }
122 0 : else if (!strcmp (key, "ttytype"))
123 : {
124 : }
125 0 : else if (!strcmp (key, "lc-ctype"))
126 : {
127 : }
128 0 : else if (!strcmp (key, "lc-messages"))
129 : {
130 : }
131 0 : else if (!strcmp (key, "xauthority"))
132 : {
133 : }
134 0 : else if (!strcmp (key, "pinentry_user_data"))
135 : {
136 : }
137 0 : else if (!strcmp (key, "list-mode"))
138 : {
139 : /* This is for now a dummy option. */
140 : }
141 0 : else if (!strcmp (key, "allow-pinentry-notify"))
142 : {
143 0 : ctrl->server_local->allow_pinentry_notify = 1;
144 : }
145 : else
146 0 : return gpg_error (GPG_ERR_UNKNOWN_OPTION);
147 :
148 0 : return 0;
149 : }
150 :
151 :
152 : /* Called by libassuan for RESET commands. */
153 : static gpg_error_t
154 0 : reset_notify (assuan_context_t ctx, char *line)
155 : {
156 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
157 :
158 : (void)line;
159 :
160 0 : release_pk_list (ctrl->server_local->recplist);
161 0 : ctrl->server_local->recplist = NULL;
162 :
163 0 : close_message_fd (ctrl);
164 0 : assuan_close_input_fd (ctx);
165 0 : assuan_close_output_fd (ctx);
166 0 : return 0;
167 : }
168 :
169 :
170 : /* Called by libassuan for INPUT commands. */
171 : static gpg_error_t
172 0 : input_notify (assuan_context_t ctx, char *line)
173 : {
174 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
175 :
176 : (void)ctx;
177 :
178 0 : if (strstr (line, "--armor"))
179 : ; /* FIXME */
180 0 : else if (strstr (line, "--base64"))
181 : ; /* FIXME */
182 0 : else if (strstr (line, "--binary"))
183 : ;
184 : else
185 : {
186 : /* FIXME (autodetect encoding) */
187 : }
188 0 : return 0;
189 : }
190 :
191 :
192 : /* Called by libassuan for OUTPUT commands. */
193 : static gpg_error_t
194 0 : output_notify (assuan_context_t ctx, char *line)
195 : {
196 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
197 :
198 : (void)ctx;
199 :
200 0 : if (strstr (line, "--armor"))
201 : ; /* FIXME */
202 0 : else if (strstr (line, "--base64"))
203 : {
204 : /* FIXME */
205 : }
206 0 : return 0;
207 : }
208 :
209 :
210 :
211 :
212 : /* RECIPIENT [--hidden] <userID>
213 :
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. */
223 : static gpg_error_t
224 0 : cmd_recipient (assuan_context_t ctx, char *line)
225 : {
226 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
227 : gpg_error_t err;
228 : int hidden;
229 :
230 0 : hidden = has_option (line,"--hidden");
231 0 : line = skip_options (line);
232 :
233 : /* FIXME: Expand groups
234 : if (opt.grouplist)
235 : remusr = expand_group (rcpts);
236 : else
237 : remusr = rcpts;
238 : */
239 :
240 0 : err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden,
241 0 : &ctrl->server_local->recplist);
242 :
243 0 : if (err)
244 0 : log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
245 0 : return err;
246 : }
247 :
248 :
249 :
250 : /* SIGNER <userID>
251 :
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 becuase it can be expected that
261 : set of signers are used for more than one sign operation.
262 :
263 : Note that this command returns an INV_RECP status which is a bit
264 : strange, but they are very similar. */
265 : static gpg_error_t
266 0 : cmd_signer (assuan_context_t ctx, char *line)
267 : {
268 : (void)ctx;
269 : (void)line;
270 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
271 : }
272 :
273 :
274 :
275 : /* ENCRYPT
276 :
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.
281 :
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
285 : output in this case.
286 :
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).
291 :
292 : The input, output and message pipes are closed after this
293 : command. */
294 : static gpg_error_t
295 0 : cmd_encrypt (assuan_context_t ctx, char *line)
296 : {
297 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
298 : gpg_error_t err;
299 : int inp_fd, out_fd;
300 :
301 : (void)line; /* LINE is not used. */
302 :
303 0 : if ( !ctrl->server_local->recplist )
304 : {
305 0 : write_status_text (STATUS_NO_RECP, "0");
306 0 : err = gpg_error (GPG_ERR_NO_USER_ID);
307 0 : goto leave;
308 : }
309 :
310 0 : inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
311 0 : if (inp_fd == -1)
312 : {
313 0 : err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
314 0 : goto leave;
315 : }
316 0 : out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
317 0 : if (out_fd == -1)
318 : {
319 0 : err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
320 0 : goto leave;
321 : }
322 :
323 :
324 : /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
325 : from the default list. */
326 :
327 : /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
328 :
329 0 : err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
330 0 : ctrl->server_local->recplist,
331 : out_fd);
332 :
333 : leave:
334 : /* Release the recipient list on success. */
335 0 : if (!err)
336 : {
337 0 : release_pk_list (ctrl->server_local->recplist);
338 0 : ctrl->server_local->recplist = NULL;
339 : }
340 :
341 : /* Close and reset the fds. */
342 0 : close_message_fd (ctrl);
343 0 : assuan_close_input_fd (ctx);
344 0 : assuan_close_output_fd (ctx);
345 :
346 0 : if (err)
347 0 : log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
348 0 : return err;
349 : }
350 :
351 :
352 :
353 : /* DECRYPT
354 :
355 : This performs the decrypt operation. */
356 : static gpg_error_t
357 0 : cmd_decrypt (assuan_context_t ctx, char *line)
358 : {
359 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
360 : gpg_error_t err;
361 : int inp_fd, out_fd;
362 :
363 : (void)line; /* LINE is not used. */
364 :
365 0 : inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
366 0 : if (inp_fd == -1)
367 0 : return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
368 0 : out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
369 0 : if (out_fd == -1)
370 0 : return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
371 :
372 0 : glo_ctrl.lasterr = 0;
373 0 : err = decrypt_message_fd (ctrl, inp_fd, out_fd);
374 0 : if (!err)
375 0 : err = glo_ctrl.lasterr;
376 :
377 : /* Close and reset the fds. */
378 0 : close_message_fd (ctrl);
379 0 : assuan_close_input_fd (ctx);
380 0 : assuan_close_output_fd (ctx);
381 :
382 0 : if (err)
383 0 : log_error ("command '%s' failed: %s\n", "DECRYPT", gpg_strerror (err));
384 0 : return err;
385 : }
386 :
387 :
388 :
389 : /* VERIFY
390 :
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.
394 :
395 : If the signature is a detached one, the server will inquire about
396 : the signed material and the client must provide it.
397 : */
398 : static gpg_error_t
399 0 : cmd_verify (assuan_context_t ctx, char *line)
400 : {
401 : int rc;
402 : #ifdef HAVE_W32_SYSTEM
403 : (void)ctx;
404 : (void)line;
405 : rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
406 : #else
407 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
408 0 : gnupg_fd_t fd = assuan_get_input_fd (ctx);
409 0 : gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
410 0 : estream_t out_fp = NULL;
411 :
412 : /* FIXME: Revamp this code it is nearly to 3 years old and was only
413 : intended as a quick test. */
414 :
415 : (void)line;
416 :
417 0 : if (fd == GNUPG_INVALID_FD)
418 0 : return gpg_error (GPG_ERR_ASS_NO_INPUT);
419 :
420 0 : if (out_fd != GNUPG_INVALID_FD)
421 : {
422 : es_syshd_t syshd;
423 :
424 : #ifdef HAVE_W32_SYSTEM
425 : syshd.type = ES_SYSHD_HANDLE;
426 : syshd.u.handle = out_fd;
427 : #else
428 0 : syshd.type = ES_SYSHD_FD;
429 0 : syshd.u.fd = out_fd;
430 : #endif
431 0 : out_fp = es_sysopen_nc (&syshd, "w");
432 0 : if (!out_fp)
433 0 : return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
434 : }
435 :
436 0 : log_debug ("WARNING: The server mode is WORK "
437 : "IN PROGRESS and not ready for use\n");
438 :
439 0 : rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);
440 :
441 0 : es_fclose (out_fp);
442 0 : close_message_fd (ctrl);
443 0 : assuan_close_input_fd (ctx);
444 0 : assuan_close_output_fd (ctx);
445 : #endif
446 :
447 0 : if (rc)
448 0 : log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
449 0 : return rc;
450 : }
451 :
452 :
453 :
454 : /* SIGN [--detached]
455 :
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
458 : is created. */
459 : static gpg_error_t
460 0 : cmd_sign (assuan_context_t ctx, char *line)
461 : {
462 : (void)ctx;
463 : (void)line;
464 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
465 : }
466 :
467 :
468 :
469 : /* IMPORT
470 :
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. */
473 : static gpg_error_t
474 0 : cmd_import (assuan_context_t ctx, char *line)
475 : {
476 : (void)ctx;
477 : (void)line;
478 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
479 : }
480 :
481 :
482 :
483 : /* EXPORT [--data [--armor|--base64]] [--] pattern
484 :
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
491 : command.
492 : */
493 : static gpg_error_t
494 0 : cmd_export (assuan_context_t ctx, char *line)
495 : {
496 : (void)ctx;
497 : (void)line;
498 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
499 : }
500 :
501 :
502 :
503 : /* DELKEYS
504 :
505 : Fixme
506 : */
507 : static gpg_error_t
508 0 : cmd_delkeys (assuan_context_t ctx, char *line)
509 : {
510 : (void)ctx;
511 : (void)line;
512 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
513 : }
514 :
515 :
516 :
517 : /* MESSAGE FD[=<n>]
518 :
519 : Set the file descriptor to read a message which is used with
520 : detached signatures. */
521 : static gpg_error_t
522 0 : cmd_message (assuan_context_t ctx, char *line)
523 : {
524 : int rc;
525 : gnupg_fd_t fd;
526 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
527 :
528 0 : rc = assuan_command_parse_fd (ctx, line, &fd);
529 0 : if (rc)
530 0 : return rc;
531 0 : if (fd == GNUPG_INVALID_FD)
532 0 : return gpg_error (GPG_ERR_ASS_NO_INPUT);
533 0 : ctrl->server_local->message_fd = fd;
534 0 : return 0;
535 : }
536 :
537 :
538 :
539 : /* LISTKEYS [<patterns>]
540 : LISTSECRETKEYS [<patterns>]
541 :
542 : fixme
543 : */
544 : static gpg_error_t
545 0 : do_listkeys (assuan_context_t ctx, char *line, int mode)
546 : {
547 : (void)ctx;
548 : (void)line;
549 : (void)mode;
550 :
551 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
552 : }
553 :
554 :
555 : static gpg_error_t
556 0 : cmd_listkeys (assuan_context_t ctx, char *line)
557 : {
558 0 : return do_listkeys (ctx, line, 3);
559 : }
560 :
561 :
562 : static gpg_error_t
563 0 : cmd_listsecretkeys (assuan_context_t ctx, char *line)
564 : {
565 0 : return do_listkeys (ctx, line, 2);
566 : }
567 :
568 :
569 :
570 : /* GENKEY
571 :
572 : Read the parameters in native format from the input fd and create a
573 : new OpenPGP key.
574 : */
575 : static gpg_error_t
576 0 : cmd_genkey (assuan_context_t ctx, char *line)
577 : {
578 : (void)ctx;
579 : (void)line;
580 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
581 : }
582 :
583 :
584 : /* GETINFO <what>
585 :
586 : Multipurpose function to return a variety of information.
587 : Supported values for WHAT are:
588 :
589 : version - Return the version of the program.
590 : pid - Return the process id of the server.
591 :
592 : */
593 : static gpg_error_t
594 0 : cmd_getinfo (assuan_context_t ctx, char *line)
595 : {
596 : int rc;
597 :
598 0 : if (!strcmp (line, "version"))
599 : {
600 0 : const char *s = VERSION;
601 0 : rc = assuan_send_data (ctx, s, strlen (s));
602 : }
603 0 : else if (!strcmp (line, "pid"))
604 : {
605 : char numbuf[50];
606 :
607 0 : snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
608 0 : rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
609 : }
610 : else
611 0 : rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
612 0 : return rc;
613 : }
614 :
615 : static const char hlp_passwd[] =
616 : "PASSWD <userID>\n"
617 : "\n"
618 : "Change the passphrase of the secret key for USERID.";
619 : static gpg_error_t
620 0 : cmd_passwd (assuan_context_t ctx, char *line)
621 : {
622 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
623 : gpg_error_t err;
624 :
625 : (void)ctx;
626 0 : line = skip_options (line);
627 :
628 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
629 :
630 0 : return err;
631 : }
632 :
633 :
634 :
635 :
636 : /* Helper to register our commands with libassuan. */
637 : static int
638 0 : register_commands (assuan_context_t ctx)
639 : {
640 : static struct
641 : {
642 : const char *name;
643 : assuan_handler_t handler;
644 : const char * const help;
645 : } table[] = {
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 },
654 : { "INPUT", NULL },
655 : { "OUTPUT", NULL },
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},
663 : { NULL }
664 : };
665 : int i, rc;
666 :
667 0 : for (i=0; table[i].name; i++)
668 : {
669 0 : rc = assuan_register_command (ctx, table[i].name,
670 : table[i].handler, table[i].help);
671 0 : if (rc)
672 0 : return rc;
673 : }
674 0 : return 0;
675 : }
676 :
677 :
678 :
679 :
680 : /* Startup the server. CTRL must have been allocated by the caller
681 : and set to the default values. */
682 : int
683 0 : gpg_server (ctrl_t ctrl)
684 : {
685 : int rc;
686 : #ifndef HAVE_W32_SYSTEM
687 : int filedes[2];
688 : #endif
689 0 : assuan_context_t ctx = NULL;
690 : static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
691 : VERSION " ready");
692 :
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 0 : filedes[0] = assuan_fdopen (0);
698 0 : filedes[1] = assuan_fdopen (1);
699 : #endif
700 0 : rc = assuan_new (&ctx);
701 0 : if (rc)
702 : {
703 0 : log_error ("failed to allocate the assuan context: %s\n",
704 : gpg_strerror (rc));
705 0 : goto leave;
706 : }
707 :
708 : #ifdef HAVE_W32_SYSTEM
709 : rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
710 : #else
711 0 : rc = assuan_init_pipe_server (ctx, filedes);
712 : #endif
713 0 : if (rc)
714 : {
715 0 : log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
716 0 : goto leave;
717 : }
718 :
719 0 : rc = register_commands (ctx);
720 0 : if (rc)
721 : {
722 0 : log_error ("failed to the register commands with Assuan: %s\n",
723 : gpg_strerror(rc));
724 0 : goto leave;
725 : }
726 :
727 0 : assuan_set_pointer (ctx, ctrl);
728 0 : if (opt.verbose || opt.debug)
729 0 : {
730 0 : char *tmp = NULL;
731 :
732 0 : tmp = xtryasprintf ("Home: %s\n"
733 : "Config: %s\n"
734 : "%s",
735 : opt.homedir,
736 : "fixme: need config filename",
737 : hello);
738 0 : if (tmp)
739 : {
740 0 : assuan_set_hello_line (ctx, tmp);
741 0 : xfree (tmp);
742 : }
743 : }
744 : else
745 0 : assuan_set_hello_line (ctx, hello);
746 0 : assuan_register_reset_notify (ctx, reset_notify);
747 0 : assuan_register_input_notify (ctx, input_notify);
748 0 : assuan_register_output_notify (ctx, output_notify);
749 0 : assuan_register_option_handler (ctx, option_handler);
750 :
751 0 : ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
752 0 : if (!ctrl->server_local)
753 : {
754 0 : rc = gpg_error_from_syserror ();
755 0 : goto leave;
756 : }
757 0 : ctrl->server_local->assuan_ctx = ctx;
758 0 : ctrl->server_local->message_fd = GNUPG_INVALID_FD;
759 :
760 : for (;;)
761 : {
762 0 : rc = assuan_accept (ctx);
763 0 : if (rc == -1)
764 : {
765 0 : rc = 0;
766 0 : break;
767 : }
768 0 : else if (rc)
769 : {
770 0 : log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
771 0 : break;
772 : }
773 :
774 0 : rc = assuan_process (ctx);
775 0 : if (rc)
776 : {
777 0 : log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
778 0 : continue;
779 : }
780 0 : }
781 :
782 : leave:
783 0 : if (ctrl->server_local)
784 : {
785 0 : release_pk_list (ctrl->server_local->recplist);
786 :
787 0 : xfree (ctrl->server_local);
788 0 : ctrl->server_local = NULL;
789 : }
790 0 : assuan_release (ctx);
791 0 : return rc;
792 : }
793 :
794 :
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
799 : code. */
800 : gpg_error_t
801 0 : gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
802 : {
803 0 : if (!ctrl || !ctrl->server_local
804 0 : || !ctrl->server_local->allow_pinentry_notify)
805 : {
806 0 : 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 0 : if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
809 0 : && (line[17]==' '||!line[17]))
810 : {
811 0 : for (line += 17; *line && spacep (line); line++)
812 : ;
813 0 : write_status_text (STATUS_PINENTRY_LAUNCHED, line);
814 : }
815 0 : return 0;
816 : }
817 0 : return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
818 : }
|