Updated to use the new LIBSSH2_KNOWNHOST API from libssh2. This requires
[libpwmd.git] / src / pwmc.c
blobae0004d52b48864397a0db04e8a07855da2ca50e
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2007-2009 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <err.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <libpwmd.h>
26 #include <assuan.h>
27 #ifdef DEBUG
28 #include <sys/select.h>
29 #endif
30 #include <fcntl.h>
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
36 #ifdef HAVE_LOCALE_H
37 #include <locale.h>
38 #endif
40 #ifdef HAVE_GETOPT_LONG
41 #ifdef HAVE_GETOPT_H
42 #include <getopt.h>
43 #endif
44 #else
45 #include "getopt_long.h"
46 #endif
48 #include "gettext.h"
49 #define N_(msgid) gettext(msgid)
51 #include "mem.h"
53 #define DEFAULT_PORT 22
54 pwm_t *pwm;
56 static void show_error(gpg_error_t error)
58 fprintf(stderr, "ERR %i %s\n", gpg_err_code(error), pwmd_strerror(error));
61 static void usage(const char *pn, int status)
63 fprintf(status == EXIT_FAILURE ? stderr : stdout, N_(
64 "Read a PWMD protocol command from standard input.\n\n"
65 "Usage: pwmc [options] [file]\n"
66 #ifdef DEBUG
67 " --debug <N>\n"
68 " pinentry method (0=pwmd, 1=libpwmd, 2=pwmd async, "
69 "3=libpwmd async)\n"
70 #endif
71 "\n"
72 #ifdef WITH_TCP
73 " --host, -h <hostname>\n"
74 " connect to the specified hostname\n"
75 "\n"
76 " --port\n"
77 " alterate port (22)\n"
78 "\n"
79 " --user\n"
80 " SSH username (default is the invoking user)\n"
81 "\n"
82 " --identity, -i <filename>\n"
83 " SSH identity file\n"
84 "\n"
85 " --known-hosts, -k <filename>\n"
86 " known host's file (for server validation)\n"
87 "\n"
88 " --get-hostkey, -g\n"
89 " retrieve the remote SSH host key and exit\n"
90 "\n"
91 " --ipv4, -4\n"
92 " try connecting via IPv4 only\n"
93 "\n"
94 " --ipv6, -6\n"
95 " try connecting via IPv6 only\n"
96 "\n"
97 #endif
98 " --url <string>\n"
99 " a url string to parse\n"
100 "\n"
101 " --no-status\n"
102 " disable showing of status messages from the server\n"
103 "\n"
104 " --name, -n <string>\n"
105 " set the client name\n"
106 "\n"
107 " --socket <filename>\n"
108 " local socket to connect to (~/.pwmd/socket)\n"
109 "\n"
110 " --passphrase, -P <string>\n"
111 " passphrase to use (disables pinentry use)\n"
112 "\n"
113 " --timeout <seconds>\n"
114 " pinentry timeout\n"
115 "\n"
116 " --tries <N>\n"
117 " number of pinentry tries before failing (3)\n"
118 "\n"
119 " --pinentry <path>\n"
120 " the full path to the pinentry binary (server default)\n"
121 "\n"
122 " --ttyname, -y <path>\n"
123 " tty that pinentry will use\n"
124 "\n"
125 " --ttytype, -t <string>\n"
126 " pinentry terminal type (default is TERM)\n"
127 "\n"
128 " --display, -d\n"
129 " pinentry display (default is DISPLAY)\n"
130 "\n"
131 " --lc-ctype <string>\n"
132 " locale setting for pinentry\n"
133 "\n"
134 " --lc-messages <string>\n"
135 " locale setting for pinentry\n"
136 "\n"
138 " --local-pinentry\n"
139 " force using a local pinentry\n"
140 "\n"
141 " --output-fd <FD>\n"
142 " redirect command output to the specified file descriptor\n"
143 "\n"
144 " --inquire-fd <FD>\n"
145 " read inquire data from the specified file descriptor\n"
146 "\n"
147 " --save, -S\n"
148 " send the SAVE command before exiting\n"
149 "\n"
150 " --force-save\n"
151 " like --save, but ask for a passphrase\n"
152 "\n"
153 " --iterations, -I <N>\n"
154 " encrypt with the specified number of iterations when saving\n"
155 "\n"
156 " --version\n"
157 " --help\n"));
158 fprintf(status == EXIT_FAILURE ? stderr : stdout, N_(
159 "\n"
160 "A url string (specified with --url) may be in the form of:\n"
161 " file://[path/to/socket]\n"
162 #ifdef WITH_TCP
163 " ssh[46]://[username@]hostname[:port],identity,known_hosts\n"
164 #endif
166 exit(status);
169 struct inquire_s {
170 FILE *fp;
171 char *data;
174 static gpg_error_t do_inquire(void *data, const char *keyword, gpg_error_t rc,
175 char **result, size_t *result_len)
177 int c;
178 static char buf[ASSUAN_LINELENGTH];
179 char *p;
180 size_t len = 0;
181 struct inquire_s *inq = (struct inquire_s *)data;
183 if (rc) {
184 memset(buf, 0, sizeof(buf));
185 return rc;
188 buf[0] = 0;
189 p = buf;
191 if (inq->data) {
192 snprintf(buf, sizeof(buf), "%s", inq->data);
193 pwmd_free(inq->data);
194 inq->data = NULL;
195 len = strlen(buf);
196 p = buf + len;
199 while ((c = fgetc(inq->fp)) != EOF) {
200 if (len == sizeof(buf)) {
201 ungetc(c, inq->fp);
202 break;
205 *p++ = c;
206 len++;
209 if (!buf[0]) {
210 memset(buf, 0, sizeof(buf));
211 return GPG_ERR_EOF;
214 *result = buf;
215 *result_len = len;
216 return 0;
219 static int status_msg_cb(void *data, const char *line)
221 fprintf(stderr, "%s\n", line);
222 return 0;
225 static gpg_error_t process_cmd(pwm_t *pwm, char **result, int input)
227 gpg_error_t rc;
228 pwmd_async_t s;
230 do {
231 int i, n;
232 fd_set rfds;
233 int nfds = 5;
234 pwmd_fd_t pfds[nfds];
236 FD_ZERO(&rfds);
237 rc = pwmd_get_fds(pwm, pfds, &nfds);
239 if (rc)
240 return rc;
242 if (!nfds)
243 return 0;
245 for (i = 0, n = 0; i < nfds; i++) {
246 FD_SET(pfds[i].fd, &rfds);
247 n = pfds[i].fd > n ? pfds[i].fd : n;
250 if (input)
251 FD_SET(STDIN_FILENO, &rfds);
253 nfds = select(n+1, &rfds, NULL, NULL, NULL);
255 if (nfds == -1) {
256 rc = gpg_error_from_errno(errno);
257 return rc;
260 if (input && FD_ISSET(STDIN_FILENO, &rfds))
261 return 0;
263 s = pwmd_process(pwm, &rc, result);
264 } while (s == ASYNC_PROCESS);
266 return rc;
269 static gpg_error_t knownhost_cb(void *data, const char *host, const char *key,
270 size_t len)
272 gpg_error_t rc;
273 char *buf = pwmd_strdup_printf(N_("Password Manager Daemon: %s\n\nWhile attepting an SSH connection to %s, there was a problem verifying it's hostkey against the list of known and trusted hosts file. Would you like to treat this connection as trusted for this and future connections?"), (char *)data, host);
275 rc = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TITLE, buf);
276 pwmd_free(buf);
278 if (rc)
279 return rc;
281 return pwmd_getpin(pwm, NULL, NULL, PWMD_PINENTRY_CONFIRM);
284 int main(int argc, char *argv[])
286 int opt;
287 char *password = NULL;
288 char *filename = NULL;
289 char *socketpath = NULL;
290 char command[ASSUAN_LINELENGTH], *p;
291 int ret = EXIT_SUCCESS;
292 gpg_error_t error;
293 char *result = NULL;
294 int save = 0;
295 char *pinentry_path = NULL;
296 char *display = NULL, *tty = NULL, *ttytype = NULL, *lcctype = NULL,
297 *lcmessages = NULL;
298 int outfd = STDOUT_FILENO;
299 FILE *outfp = stdout;
300 int inquirefd = STDIN_FILENO;
301 FILE *inquirefp = stdin;
302 int show_status = 1;
303 char *clientname = "pwmc";
304 char *inquire = NULL;
305 long iter = -2;
306 int have_iter = 0;
307 int timeout = 0;
308 int local_pin = 0;
309 int force_save = 0;
310 #ifdef WITH_TCP
311 char *host = NULL;
312 int port = DEFAULT_PORT;
313 char *username = NULL;
314 char *ident = NULL;
315 char *known_hosts = NULL;
316 int get = 0;
317 int prot = PWMD_IP_ANY;
318 #endif
319 int tries = 0;
320 int local_tries = 3;
321 int try = 0;
322 pwmd_socket_t s;
323 #ifdef DEBUG
324 int method = 0;
325 fd_set rfds;
326 #endif
327 char *url_string = NULL;
328 /* The order is important. */
329 enum {
330 #ifdef DEBUG
331 OPT_DEBUG,
332 #endif
333 #ifdef WITH_TCP
334 OPT_HOST, OPT_PORT, OPT_IDENTITY, OPT_KNOWN_HOSTS, OPT_USER,
335 OPT_GET_HOSTKEY, OPT_IPV4, OPT_IPV6,
336 #endif
337 OPT_URL, OPT_LOCAL, OPT_FORCE_SAVE, OPT_TTYNAME, OPT_TTYTYPE,
338 OPT_DISPLAY, OPT_LC_CTYPE, OPT_LC_MESSAGES, OPT_TIMEOUT, OPT_TRIES,
339 OPT_PINENTRY, OPT_PASSPHRASE, OPT_SOCKET, OPT_SAVE, OPT_ITERATIONS,
340 OPT_OUTPUT_FD, OPT_INQUIRE_FD, OPT_NO_STATUS, OPT_NAME, OPT_VERSION,
341 OPT_HELP,
343 const struct option long_opts[] = {
344 #ifdef DEBUG
345 { "debug", 1, 0, 0 },
346 #endif
347 #ifdef WITH_TCP
348 { "host", 1, 0, 'h' },
349 { "port", 1, 0, 'p' },
350 { "identity", 1, 0, 'i' },
351 { "known-hosts", 1, 0, 'k' },
352 { "user", 1, 0, 'u' },
353 { "get-hostkey", 0, 0, 'g' },
354 { "ipv4", 0, 0, '4' },
355 { "ipv6", 0, 0, '6' },
356 #endif
357 { "url", 1, 0, 0 },
358 { "local-pinentry", 0, 0 },
359 { "force-save", 0, 0 },
360 { "ttyname", 1, 0, 'y' },
361 { "ttytype", 1, 0, 't' },
362 { "display", 1, 0, 'd' },
363 { "lc-ctype", 1, 0, 0 },
364 { "lc-messages", 1, 0, 0 },
365 { "timeout", 1, 0, 0 },
366 { "tries", 1, 0, 0 },
367 { "pinentry", 1, 0, 0 },
368 { "passphrase", 1, 0, 'P' },
369 { "socket", 1, 0, 0 },
370 { "save", 0, 0, 'S' },
371 { "iterations", 1, 0, 'I' },
372 { "output-fd", 1, 0, 0 },
373 { "inquire-fd", 1, 0, 0 },
374 { "no-status", 0, 0, 0 },
375 { "name", 1, 0, 'n' },
376 { "version", 0, 0, 0 },
377 { "help", 0, 0, 0 },
378 { 0, 0, 0, 0}
380 #ifdef WITH_TCP
381 const char *optstring = "46h:p:i:k:u:gy:t:d:P:I:Sn:";
382 #else
383 const char *optstring = "y:t:d:P:I:Sn:";
384 #endif
385 int opt_index = 0;
387 #ifdef ENABLE_NLS
388 setlocale(LC_ALL, "");
389 bindtextdomain("libpwmd", LOCALEDIR);
390 #endif
392 while ((opt = getopt_long(argc, argv, optstring, long_opts, &opt_index)) != -1) {
393 switch (opt) {
394 /* Handle long options without a short option part. */
395 case 0:
396 switch (opt_index) {
397 #ifdef DEBUG
398 case OPT_DEBUG:
399 method = atoi(optarg);
401 if (method > 3)
402 method = 3;
403 break;
404 #endif
405 case OPT_URL:
406 url_string = optarg;
407 break;
408 case OPT_LOCAL:
409 local_pin = 1;
410 break;
411 case OPT_FORCE_SAVE:
412 save = force_save = 1;
413 break;
414 case OPT_LC_CTYPE:
415 lcctype = pwmd_strdup(optarg);
416 break;
417 case OPT_LC_MESSAGES:
418 lcmessages = pwmd_strdup(optarg);
419 break;
420 case OPT_TIMEOUT:
421 timeout = atoi(optarg);
422 break;
423 case OPT_TRIES:
424 tries = atoi(optarg);
425 local_tries = tries;
426 break;
427 case OPT_SOCKET:
428 socketpath = pwmd_strdup(optarg);
429 break;
430 case OPT_INQUIRE_FD:
431 inquirefd = atoi(optarg);
432 inquirefp = fdopen(inquirefd, "r");
434 if (!inquirefp) {
435 pwmd_free(password);
436 err(EXIT_FAILURE, "%i", inquirefd);
438 break;
439 case OPT_OUTPUT_FD:
440 outfd = atoi(optarg);
441 outfp = fdopen(outfd, "w");
443 if (!outfp) {
444 pwmd_free(password);
445 err(EXIT_FAILURE, "%i", outfd);
447 break;
448 case OPT_NO_STATUS:
449 show_status = 0;
450 break;
451 case OPT_VERSION:
452 pwmd_free(password);
453 printf("%s (pwmc)\n%s\n\n"
454 "Compile-time features:\n"
455 #ifdef WITH_TCP
456 "+SSH "
457 #else
458 "-SSH "
459 #endif
460 #ifdef WITH_PINENTRY
461 "+PINENTRY "
462 #else
463 "-PINENTRY "
464 #endif
465 #ifdef WITH_QUALITY
466 "+QUALITY "
467 #else
468 "-QUALITY "
469 #endif
470 #ifdef MEM_DEBUG
471 "+MEM_DEBUG "
472 #else
473 "-MEM_DEBUG "
474 #endif
475 "\n"
476 , PACKAGE_STRING, PACKAGE_BUGREPORT);
477 exit(EXIT_SUCCESS);
478 case OPT_PINENTRY:
479 pinentry_path = optarg;
480 break;
481 case OPT_HELP:
482 usage(argv[0], EXIT_SUCCESS);
483 default:
484 usage(argv[0], EXIT_FAILURE);
487 break;
488 #ifdef WITH_TCP
489 case '4':
490 prot = PWMD_IPV4;
491 break;
492 case '6':
493 prot = PWMD_IPV6;
494 break;
495 case 'h':
496 host = pwmd_strdup(optarg);
497 break;
498 case 'p':
499 port = atoi(optarg);
500 break;
501 case 'i':
502 ident = pwmd_strdup(optarg);
503 break;
504 case 'u':
505 username = pwmd_strdup(optarg);
506 break;
507 case 'k':
508 known_hosts = pwmd_strdup(optarg);
509 break;
510 case 'g':
511 get = 1;
512 break;
513 #endif
514 case 'y':
515 tty = optarg;
516 break;
517 case 't':
518 ttytype = optarg;
519 break;
520 case 'd':
521 display = optarg;
522 break;
523 case 'S':
524 save = 1;
525 break;
526 case 'I':
527 iter = strtol(optarg, NULL, 10);
528 have_iter = 1;
529 break;
530 case 'P':
531 password = pwmd_strdup(optarg);
532 memset(optarg, 0, strlen(optarg));
533 break;
534 case 'n':
535 clientname = optarg;
536 break;
537 default:
538 pwmd_free(password);
539 usage(argv[0], EXIT_FAILURE);
543 #ifdef DEBUG
544 if (!url_string) {
545 #endif
546 #ifdef WITH_TCP
547 if (host && !get && (!known_hosts || !ident)) {
548 pwmd_free(password);
549 usage(argv[0], EXIT_FAILURE);
552 if (get && !host) {
553 pwmd_free(password);
554 usage(argv[0], EXIT_FAILURE);
556 #endif
557 #ifdef DEBUG
559 #endif
561 filename = argv[optind];
562 pwmd_init();
563 pwm = pwmd_new(clientname);
564 #ifdef DEBUG
565 FD_ZERO(&rfds);
566 #endif
568 #ifdef WITH_TCP
569 if (host) {
570 if (prot != PWMD_IP_ANY) {
571 error = pwmd_setopt(pwm, PWMD_OPTION_IP_VERSION, prot);
573 if (error)
574 goto done;
577 error = pwmd_setopt(pwm, PWMD_OPTION_KNOWNHOST_CB, knownhost_cb);
579 if (error)
580 goto done;
582 error = pwmd_setopt(pwm, PWMD_OPTION_KNOWNHOST_DATA, clientname);
584 if (error)
585 goto done;
587 #ifdef DEBUG
588 if (method >= 2) {
589 if (get) {
590 char *hostkey;
592 error = pwmd_get_hostkey_async(pwm, host, port);
594 if (error)
595 errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error));
597 error = process_cmd(pwm, &hostkey, 0);
599 if (error)
600 goto done;
602 printf("%s", hostkey);
603 pwmd_free(hostkey);
604 pwmd_free(password);
605 pwmd_close(pwm);
606 exit(EXIT_SUCCESS);
609 if (url_string)
610 error = pwmd_connect_url_async(pwm, url_string);
611 else
612 error = pwmd_ssh_connect_async(pwm, host, port, ident, username,
613 known_hosts);
615 if (error)
616 goto done;
618 error = process_cmd(pwm, NULL, 0);
620 if (error)
621 goto done;
623 else {
624 #endif
625 if (get) {
626 char *hostkey;
628 error = pwmd_get_hostkey(pwm, host, port, &hostkey);
630 if (error)
631 goto done;
633 printf("%s", hostkey);
634 pwmd_free(hostkey);
635 pwmd_free(password);
636 pwmd_close(pwm);
637 exit(EXIT_SUCCESS);
640 if (url_string)
641 error = pwmd_connect_url(pwm, url_string);
642 else
643 error = pwmd_ssh_connect(pwm, host, port, ident, username, known_hosts);
645 if (error)
646 goto done;
647 #ifdef DEBUG
649 #endif
651 else {
652 #endif
653 if (url_string)
654 error = pwmd_connect_url(pwm, url_string);
655 else
656 error = pwmd_connect(pwm, socketpath);
658 if (error)
659 goto done;
660 #ifdef WITH_TCP
662 #endif
664 error = pwmd_socket_type(pwm, &s);
666 if (error)
667 goto done;
669 if (s == PWMD_SOCKET_SSH && force_save && !local_pin) {
670 error = GPG_ERR_WRONG_KEY_USAGE;
671 goto done;
674 if (have_iter) {
675 error = pwmd_command(pwm, &result, "VERSION");
677 if (error)
678 goto done;
680 pwmd_free(result);
682 if (iter < 0) {
683 pwmd_free(password);
684 pwmd_close(pwm);
685 usage(argv[0], EXIT_FAILURE);
689 if (timeout > 0) {
690 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TIMEOUT, timeout);
692 if (error)
693 goto done;
696 if (local_pin && filename) {
697 error = pwmd_command(pwm, NULL, "ISCACHED %s", filename);
699 if (error == GPG_ERR_NOT_FOUND) {
700 local_password:
701 if (try++ == local_tries)
702 goto done;
704 if (password)
705 pwmd_free(password);
707 password = NULL;
709 if (try > 1)
710 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TIMEOUT, 0);
712 error = pwmd_getpin(pwm, filename, &password,
713 try > 1 ? PWMD_PINENTRY_OPEN_FAILED : PWMD_PINENTRY_OPEN);
715 if (error)
716 goto done;
718 error = pwmd_setopt(pwm, PWMD_OPTION_PASSPHRASE, password);
720 if (error)
721 goto done;
723 if (try > 1)
724 goto do_open;
726 else if (error && error != GPG_ERR_ENOENT)
727 goto done;
730 if (password) {
731 error = pwmd_setopt(pwm, PWMD_OPTION_PASSPHRASE, password);
733 if (error)
734 goto done;
736 else {
737 if (pinentry_path) {
738 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_PATH, pinentry_path);
740 if (error)
741 goto done;
744 if (display) {
745 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_DISPLAY, display);
747 if (error)
748 goto done;
751 if (tty) {
752 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TTY, tty);
754 if (error)
755 goto done;
758 if (ttytype) {
759 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TERM, ttytype);
761 if (error)
762 goto done;
765 if (lcctype) {
766 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_LC_CTYPE, lcctype);
768 if (error)
769 goto done;
772 if (lcmessages) {
773 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_LC_MESSAGES,
774 lcmessages);
776 if (error)
777 goto done;
780 if (tries > 0) {
781 error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TRIES, tries);
783 if (error)
784 goto done;
788 if (show_status) {
789 error = pwmd_setopt(pwm, PWMD_OPTION_STATUS_CB, status_msg_cb);
791 if (error)
792 goto done;
795 do_open:
796 if (filename) {
797 #ifdef DEBUG
798 switch (method) {
799 case 0:
800 error = pwmd_open(pwm, filename);
801 break;
802 case 1:
803 error = pwmd_open2(pwm, filename);
804 break;
805 case 2:
806 error = pwmd_open_async(pwm, filename);
808 break;
809 case 3:
810 error = pwmd_open_async2(pwm, filename);
811 break;
814 if (error && local_pin && error == GPG_ERR_INV_PASSPHRASE)
815 goto local_password;
817 if (error)
818 goto done;
820 if (method >= 2)
821 error = process_cmd(pwm, &result, 0);
822 #else
823 error = pwmd_open(pwm, filename);
825 if (error && local_pin && error == GPG_ERR_INV_PASSPHRASE)
826 goto local_password;
827 #endif
829 if (error)
830 goto done;
833 if (filename) {
834 error = pwmd_command(pwm, &result, "LOCK");
836 if (error)
837 goto done;
840 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
842 for (;;) {
843 ssize_t n;
845 error = process_cmd(pwm, NULL, 1);
847 if (error)
848 goto done;
850 n = read(STDIN_FILENO, command, sizeof(command));
852 if (n == -1) {
853 if (errno == EAGAIN)
854 continue;
856 error = gpg_error_from_errno(errno);
857 goto done;
859 else if (!n)
860 goto done;
862 command[n] = 0;
864 if (n && command[strlen(command)-1] == '\n')
865 command[strlen(command)-1] = 0;
867 p = command;
868 break;
871 if (!p || !*p)
872 goto done;
875 * This is a known INQUIRE command. We use pwmd_inquire() to send the
876 * data from the do_inquire() callback function.
878 if (strncasecmp(p, "STORE ", 6) == 0) {
879 p += 6;
880 inquire = (char *)"STORE";
882 else if (strncasecmp(p, "IMPORT ", 7) == 0) {
883 p += 7;
884 inquire = (char *)"IMPORT";
887 if (inquire) {
888 struct inquire_s *inq = (struct inquire_s *)pwmd_malloc(sizeof(struct inquire_s));
890 if (!inq) {
891 error = gpg_error_from_errno(ENOMEM);
892 goto done;
895 inq->data = pwmd_strdup(p);
896 inq->fp = inquirefp;
897 error = pwmd_inquire(pwm, inquire, do_inquire, inq);
898 pwmd_free(inq);
899 goto done;
902 if (strcasecmp(p, "BYE") == 0)
903 goto done;
905 error = pwmd_command(pwm, &result, command);
906 memset(command, 0, sizeof(command));
908 if (error)
909 goto done;
911 if (result) {
912 fwrite(result, 1, strlen(result), outfp);
913 pwmd_free(result);
916 done:
917 memset(command, 0, sizeof(command));
918 pwmd_free(password);
919 password = NULL;
921 if (!error && save && filename) {
922 if (iter != -2) {
923 error = pwmd_command(pwm, &result, "SET ITERATIONS=%i", iter);
925 if (error)
926 goto done;
929 if (local_pin) {
930 char *p1;
931 again:
932 if (!force_save) {
933 error = pwmd_command(pwm, NULL, "ISCACHED %s", filename);
935 if (error && error != GPG_ERR_NOT_FOUND &&
936 error != GPG_ERR_ENOENT)
937 goto done;
938 else if (!error)
939 goto do_save;
942 error = pwmd_getpin(pwm, filename, &p1, PWMD_PINENTRY_SAVE);
944 if (error)
945 goto done;
947 error = pwmd_getpin(pwm, filename, &password,
948 PWMD_PINENTRY_SAVE_CONFIRM);
950 if (error) {
951 pwmd_free(p1);
952 goto done;
955 if ((p1 || password) && ((!p1 && password) || (!password && p1) ||
956 strcmp(p1, password))) {
957 pwmd_free(p1);
958 pwmd_free(password);
959 password = NULL;
960 goto again;
963 if (p1)
964 pwmd_free(p1);
966 error = pwmd_setopt(pwm, PWMD_OPTION_PASSPHRASE, password);
968 if (password)
969 pwmd_free(password);
971 if (error)
972 goto done;
975 if (force_save) {
976 error = pwmd_command(pwm, NULL, "CLEARCACHE %s", filename);
978 if (error)
979 goto done;
981 if (!local_pin) {
982 error = pwmd_setopt(pwm, PWMD_OPTION_PASSPHRASE, NULL);
984 if (error)
985 goto done;
989 do_save:
990 #ifdef DEBUG
991 switch (method) {
992 case 0:
993 error = pwmd_save(pwm);
994 break;
995 case 1:
996 error = pwmd_save2(pwm);
997 break;
998 case 2:
999 error = pwmd_save_async(pwm);
1000 break;
1001 case 3:
1002 error = pwmd_save_async2(pwm);
1003 break;
1006 if (!error && method >= 2)
1007 error = process_cmd(pwm, NULL, 0);
1009 #else
1010 error = pwmd_save(pwm);
1011 #endif
1014 if (!error && filename)
1015 error = pwmd_command(pwm, &result, "UNLOCK");
1017 if (error) {
1018 show_error(error);
1019 ret = EXIT_FAILURE;
1022 pwmd_close(pwm);
1024 if (socketpath)
1025 pwmd_free(socketpath);
1027 exit(ret);