Send SIGINT rather than SIGTERM to terminate the local pinentry.
[libpwmd.git] / src / pwmc.c
blob8f39549d95750accf3cfa624c48647c5d3616229
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of libpwmd.
7 Libpwmd 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 2 of the License, or
10 (at your option) any later version.
12 Libpwmd 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 Libpwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <stdint.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <libpwmd.h>
32 #include <assuan.h>
33 #include <sys/select.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <libgen.h>
38 #include <termios.h>
39 #include <limits.h>
40 #include <ctype.h>
42 #ifdef HAVE_LOCALE_H
43 #include <locale.h>
44 #endif
46 #ifdef HAVE_GETOPT_LONG
47 #ifdef HAVE_GETOPT_H
48 #include <getopt.h>
49 #endif
50 #else
51 #include "getopt_long.h"
52 #endif
54 #ifdef HAVE_LIBREADLINE
55 #if defined(HAVE_READLINE_READLINE_H)
56 #include <readline/readline.h>
57 #elif defined(HAVE_READLINE_H)
58 #include <readline.h>
59 #endif /* !defined(HAVE_READLINE_H) */
60 static int interactive_error;
61 static int interactive;
62 #endif /* HAVE_LIBREADLINE */
64 #ifdef HAVE_READLINE_HISTORY
65 #if defined(HAVE_READLINE_HISTORY_H)
66 #include <readline/history.h>
67 #elif defined(HAVE_HISTORY_H)
68 #include <history.h>
69 #endif
70 #endif /* HAVE_READLINE_HISTORY */
72 #ifndef LINE_MAX
73 #define LINE_MAX 2048
74 #endif
76 #include "gettext.h"
77 #define N_(msgid) gettext(msgid)
79 #include "mem.h"
81 #define DEFAULT_PIN_TRIES 3
82 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
83 ? gpg_error(rc) : rc
85 static int no_pinentry;
86 static pwm_t *pwm;
87 static char *filename;
88 static int save;
89 static int force_save;
90 static int no_passphrase;
91 static char *cipher;
92 static char *keygrip;
93 static char *sign_keygrip;
94 static char *keyparams;
95 static char *password;
96 static char *keyfile;
97 static char *new_keyfile;
98 static unsigned long s2k_count;
99 static uint64_t iterations;
100 static int iterations_arg;
101 static int tries;
102 static int local_pin;
103 static int inquirefd;
104 static int quiet;
105 static int no_gpg_agent;
107 struct inquire_s
109 int fd;
110 char *line;
111 size_t len;
112 size_t size; // from stat(2).
113 int header;
116 static gpg_error_t finalize ();
117 static gpg_error_t set_inquire (int fd, const char *line,
118 struct inquire_s **result);
119 static gpg_error_t parse_dotcommand (const char *line, char **result,
120 size_t * len, struct inquire_s *inq);
121 static gpg_error_t open_command (const char *line);
122 #ifdef WITH_SSH
123 static gpg_error_t get_password (char **result, pwmd_pinentry_t w, int echo);
124 #endif
126 static void
127 show_error (gpg_error_t rc, const char *str)
129 fprintf (stderr, "ERR %i: %s%s%s%s", rc, gpg_strerror (rc),
130 str ? ": " : "", str ? str : "", str ? "" : "\n");
133 static void
134 usage (const char *pn, int status)
136 fprintf (status == EXIT_FAILURE ? stderr : stdout,
137 N_("Read a PWMD protocol command from standard input.\n\n"
138 "Usage: pwmc [options] [file]\n"
139 " --url <string>\n"
140 " a url string to connect to (see below)\n"
141 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
142 " --connect-timeout <seconds>\n"
143 " seconds before connecting to a remote host fails (120)\n"
144 " --socket-timeout <seconds>\n"
145 " seconds before a remote command fails (0=disabled, default=300)\n"
146 #endif
147 #ifdef WITH_GNUTLS
148 " --ca-cert <filename>\n"
149 " certificate authority (CA) used to sign the server cert\n"
150 " --client-cert <filename>\n"
151 " client certificate to use for authentication\n"
152 " --client-key <filename>\n"
153 " key file used to protect the client certificate\n"
154 " --tls-priority <string>\n"
155 " compression, cipher and hash algorithm string (SECURE256)\n"
156 " --tls-verify\n"
157 " verify the hostname against the server certificate\n"
158 " --tls-fingerprint <string>\n"
159 " a SHA-1 hash of the server fingerprint to verify against\n"
160 #endif
161 #ifdef WITH_SSH
162 " --no-ssh-agent\n"
163 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
164 " --identity, -i <filename>\n"
165 " the ssh identity file to use for authentication\n"
166 " --knownhosts, -k <filename>\n"
167 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
168 #endif
169 " --no-lock\n"
170 " do not lock the data file upon opening it\n"
171 " --lock-timeout <N>\n"
172 " time in tenths of a second to wait for a locked data file\n"
173 " --name, -n <string>\n"
174 " set the client name\n"
175 " --pinentry <path>\n"
176 " the full path to the pinentry binary (server default)\n"
177 " --local-pinentry\n"
178 " force using a local pinentry\n"
179 " --no-pinentry\n"
180 " disable pinentry both remotely and locally\n"
181 " --ttyname, -y <path>\n"
182 " tty that pinentry will use\n"
183 " --ttytype, -t <string>\n"
184 " pinentry terminal type (default is $TERM)\n"
185 " --display, -d\n"
186 " pinentry display (default is $DISPLAY)\n"
187 " --lc-ctype <string>\n"
188 " locale setting for pinentry\n"
189 " --lc-messages <string>\n"
190 " locale setting for pinentry\n"
191 " --tries <N>\n"
192 " number of pinentry tries before failing (3)\n"
193 " --timeout <seconds>\n"
194 " pinentry timeout\n"
195 " --inquire <COMMAND>\n"
196 " the specified command (with any options) uses a server inquire while\n"
197 " command data is read via the inquire file descriptor (stdin)\n"
198 " --inquire-line, -L <STRING>\n"
199 " the initial line to send (i.e., element path) before the inquire data\n"
200 " --inquire-fd <FD>\n"
201 " read inquire data from the specified file descriptor (stdin)\n"
202 " --inquire-file <filename>\n"
203 " read inquire data from the specified filename\n"
204 " --output-fd <FD>\n"
205 " redirect command output to the specified file descriptor\n"
206 " --save, -S\n"
207 " send the SAVE command before exiting\n"
208 " --force-save\n"
209 " like --save but always ask for a passphrase\n"
210 " --no-passphrase\n"
211 " do not require a passphrase when saving a new file\n"
212 " --no-gpg-agent\n"
213 " disable use of gpg-agent when saving to a new file\n"
214 " --key-file <filename>\n"
215 " obtain the passphrase from the specified filename\n"
216 " --new-key-file <filename>\n"
217 " obtain the passphrase to save with from the specified filename\n"
218 " --cipher <string>\n"
219 " the cipher to use when saving (see pwmd(1))\n"
220 " --cipher-iterations <N>\n"
221 " the number of times to encrypt the XML data (N+1)\n"
222 " --key-params <string>\n"
223 " the key parameters to use when saving a new file (pwmd default)\n"
224 " --keygrip <string>\n"
225 " the hex string of the keygrip to save to\n"
226 " --sign-keygrip <string>\n"
227 " the hex string of the keygrip to sign with\n"
228 " --s2k-count <N>\n"
229 " the number of times to hash the passphrase for a new file\n"
230 " --no-status\n"
231 " disable showing of status messages from the server\n"
232 " --quiet\n"
233 " disable showing of extra messages (implies --no-status)\n"
234 #ifdef HAVE_LIBREADLINE
235 " --interactive\n"
236 " use a shell like interface to pwmd (allows more than one command)\n"
237 #endif
238 " --version\n"
239 " --help\n"));
240 fprintf (status == EXIT_FAILURE ? stderr : stdout,
241 N_("\n"
242 "An optional url may be in the form of:\n"
243 " --url /path/to/socket\n"
244 " --url file://[path/to/socket]\n"
245 #ifdef WITH_SSH
246 " or\n"
247 " --url ssh[46]://[username@]hostname[:port]\n"
248 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
249 #endif
250 #ifdef WITH_GNUTLS
251 " or\n"
252 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
253 " --client-key filename\n"
254 #endif
256 exit (status);
259 static gpg_error_t
260 inquire_cb (void *user, const char *keyword, gpg_error_t rc,
261 char **data, size_t * size)
263 struct inquire_s *inq = user;
264 int is_password = 0;
265 int is_newpassword = 0;
267 *data = NULL;
268 *size = 0;
270 if (rc)
271 return rc;
273 if (!strcmp (keyword, "PASSPHRASE"))
274 is_password = 1;
275 else if (!strcmp (keyword, "NEW_PASSPHRASE"))
276 is_newpassword = 1;
277 #ifdef HAVE_LIBREADLINE
278 else if (!strcmp (keyword, "KEYPARAM") && !interactive)
280 #else
281 else if (!strcmp (keyword, "KEYPARAM"))
283 #endif
284 if (!keyparams || !*keyparams)
285 return gpg_error (GPG_ERR_INV_PARAMETER);
287 *data = keyparams;
288 *size = strlen (keyparams);
289 return gpg_error (GPG_ERR_EOF);
292 if ((is_newpassword && new_keyfile) || (is_password && keyfile))
294 int fd = open (is_password ? keyfile : new_keyfile, O_RDONLY);
296 if (fd == -1)
298 fprintf (stderr, "%s: %s\n", is_newpassword ? new_keyfile : keyfile,
299 strerror (errno));
300 return gpg_error_from_syserror ();
303 rc = set_inquire (fd, NULL, &inq);
304 if (rc)
306 close (fd);
307 return rc;
310 if (!quiet)
311 fprintf (stderr, N_("Using keyfile '%s' as %s.\n"),
312 is_newpassword ? new_keyfile : keyfile, keyword);
314 if (!new_keyfile || is_newpassword)
316 pwmd_socket_t t;
318 pwmd_socket_type (pwm, &t);
319 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
320 if (!no_pinentry && t == PWMD_SOCKET_LOCAL)
321 pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 0);
324 else if (is_password && !keyfile)
326 char *tmp;
328 rc = pwmd_password (pwm, keyword, &tmp, &inq->len);
329 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
330 return rc;
332 pwmd_free (inq->line);
333 inq->line = tmp;
334 *data = inq->line;
335 *size = inq->len;
336 return gpg_error (GPG_ERR_EOF);
338 #ifdef HAVE_LIBREADLINE
339 else if (!inq->header && interactive)
341 fprintf (stderr,
343 ("Press CTRL-D to send the current line. Press twice to end. %s:\n"),
344 keyword);
345 inq->header = 1;
347 #endif
349 /* The first part of the command data. */
350 if (inq->len)
352 *data = inq->line;
353 *size = inq->len;
354 inq->len = 0;
355 return inq->fd == -1 ? gpg_error (GPG_ERR_EOF) : 0;
358 *size = read (inq->fd, inq->line, ASSUAN_LINELENGTH);
359 if (*size == -1)
361 *size = 0;
362 return gpg_error (gpg_error_from_syserror ());
364 else if (*size)
365 *data = inq->line;
366 else if (inq->fd != STDIN_FILENO && (is_newpassword || is_password))
368 *inq->line = 0;
369 inq->size = 1;
370 *data = inq->line;
371 *size = 1;
374 if (((is_newpassword && new_keyfile) || (is_password && keyfile))
375 && *size == inq->size)
376 return gpg_error (GPG_ERR_EOF);
378 return *size ? 0 : gpg_error (GPG_ERR_EOF);
381 static int
382 status_msg_cb (void *data, const char *line)
384 char *p = strchr (line, ' ');
386 if (!strcmp (line, "KEEPALIVE"))
387 return 0;
389 if (*line != '#' && p && strchr (p, ' ') && *++p)
391 char *p1 = strchr (p, ' ');
392 int a = strtol (p, NULL, 10);
394 if (isdigit (*p) && p1)
396 int b = strtol (p1, NULL, 10);
397 char l[64] = { 0 };
398 int t = a && b ? a * 100 / b : 0;
400 strncpy (l, line, strlen (line) - strlen (p) - 1);
401 fprintf (stderr, "\r%s %i/%i %i%%%s", l, a, b, t,
402 a == b ? "\n" : "");
403 fflush (stderr);
404 return 0;
408 fprintf (stderr, "%s\n", line);
409 fflush (stderr);
410 #ifdef HAVE_LIBREADLINE
411 rl_on_new_line ();
412 #endif
413 return 0;
416 static gpg_error_t
417 process_cmd ()
419 return pwmd_process (pwm);
422 #ifdef WITH_SSH
423 static gpg_error_t
424 get_password (char **result, pwmd_pinentry_t w, int echo)
426 char buf[LINE_MAX] = { 0 }, *p;
427 struct termios told, tnew;
428 char *key = NULL;
430 *result = NULL;
432 if (!isatty (STDIN_FILENO))
434 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
435 return GPG_ERR_ENOTTY;
438 if (!echo)
440 if (tcgetattr (STDIN_FILENO, &told) == -1)
441 return gpg_error_from_syserror ();
443 memcpy (&tnew, &told, sizeof (struct termios));
444 tnew.c_lflag &= ~(ECHO);
445 tnew.c_lflag |= ICANON | ECHONL;
447 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
449 int n = errno;
451 tcsetattr (STDIN_FILENO, TCSANOW, &told);
452 return gpg_error_from_errno (n);
456 switch (w)
458 case PWMD_PINENTRY_OPEN:
459 fprintf (stderr, N_("Password for %s: "), filename);
460 break;
461 case PWMD_PINENTRY_OPEN_FAILED:
462 fprintf (stderr, N_("Invalid password. Password for %s: "), filename);
463 break;
464 case PWMD_PINENTRY_SAVE:
465 fprintf (stderr, N_("New password for %s: "), filename);
466 break;
467 case PWMD_PINENTRY_SAVE_CONFIRM:
468 fprintf (stderr, N_("Confirm password: "));
469 break;
470 default:
471 break;
474 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
476 tcsetattr (STDIN_FILENO, TCSANOW, &told);
477 return 0;
480 if (!echo)
481 tcsetattr (STDIN_FILENO, TCSANOW, &told);
483 if (feof (stdin))
485 clearerr (stdin);
486 return GPG_ERR_CANCELED;
489 p[strlen (p) - 1] = 0;
491 if (buf[0])
493 key = pwmd_strdup_printf ("%s", p);
494 memset (&buf, 0, sizeof (buf));
496 if (!key)
497 return GPG_ERR_ENOMEM;
500 *result = key;
501 return 0;
504 static gpg_error_t
505 knownhost_cb (void *data, const char *host, const char *key, size_t len)
507 gpg_error_t rc;
508 char *buf =
509 pwmd_strdup_printf (N_
510 ("Password Manager Daemon: %s\n\nWhile attempting an SSH connection to %s there was a problem verifying it's hostkey against the known and trusted hosts file because it's hostkey was not found.\n\nWould you like to treat this connection as trusted for this and future connections by adding %s's hostkey to the known hosts file?"),
511 (char *) data, host, host);
513 if (no_pinentry && !isatty (STDIN_FILENO))
515 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
516 pwmd_free (buf);
517 return GPG_ERR_ENOTTY;
519 else if (no_pinentry)
521 for (char *p = buf, len = 0; *p; p++, len++)
523 if (*p == '\n')
524 len = 0;
526 if (len == 78)
528 char *t = p;
530 while (!isspace (*(--p)));
531 *p = '\n';
532 p = t;
533 len = 0;
537 fprintf (stderr, "%s\n\n", buf);
538 pwmd_free (buf);
542 char *result;
544 fprintf (stderr, N_("Trust this connection [y/N]: "));
545 fflush (stderr);
546 rc = get_password (&result, PWMD_PINENTRY_CONFIRM, 1);
548 if (rc)
549 return rc;
551 if (!result || !*result || *result == 'n' || *result == 'N')
553 if (result && *result)
554 pwmd_free (result);
556 return GPG_ERR_NOT_CONFIRMED;
559 if ((*result == 'y' || *result == 'Y') && *(result + 1) == 0)
561 pwmd_free (result);
562 return 0;
565 while (1);
568 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DESC, buf);
569 pwmd_free (buf);
571 if (rc)
572 return rc;
574 return pwmd_getpin (pwm, NULL, NULL, NULL, PWMD_PINENTRY_CONFIRM);
576 #endif
578 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
579 static pwmd_socket_t
580 is_remote_url (const char *str)
582 if (!str)
583 return PWMD_SOCKET_LOCAL;
585 #ifdef WITH_SSH
586 if (strstr (str, "ssh://") || strstr (str, "ssh4://")
587 || strstr (str, "ssh6://"))
588 return PWMD_SOCKET_SSH;
589 #endif
591 #ifdef WITH_GNUTLS
592 if (strstr (str, "tls://") || strstr (str, "tls4://")
593 || strstr (str, "tls6://"))
594 return PWMD_SOCKET_TLS;
595 #endif
597 return PWMD_SOCKET_LOCAL;
599 #endif
601 static char *
602 escape (const char *str)
604 const char *p;
605 char *buf = pwmd_malloc (ASSUAN_LINELENGTH + 1), *b = buf;
606 size_t len = 0;
608 for (p = str; *p; p++, len++)
610 if (len == ASSUAN_LINELENGTH)
611 break;
613 if (*p == '\\')
615 switch (*++p)
617 case 't':
618 *b++ = '\t';
619 break;
620 case 'n':
621 *b++ = '\n';
622 break;
623 case 'v':
624 *b++ = '\v';
625 break;
626 case 'b':
627 *b++ = '\b';
628 break;
629 case 'f':
630 *b++ = '\f';
631 break;
632 case 'r':
633 *b++ = '\r';
634 break;
635 default:
636 *b++ = *p;
637 break;
640 if (!*p)
641 break;
643 continue;
646 *b++ = *p;
649 *b = 0;
650 return buf;
653 static void
654 free_inquire (struct inquire_s *inq)
656 if (!inq)
657 return;
659 pwmd_free (inq->line);
661 if (inq->fd != -1 && inq->fd != STDIN_FILENO)
662 close (inq->fd);
664 pwmd_free (inq);
667 /* When *result is not NULL it is updated to the new values and not
668 * reallocated. */
669 static gpg_error_t
670 set_inquire (int fd, const char *line, struct inquire_s **result)
672 struct inquire_s inq = { 0 };
673 struct stat st = { 0 };
674 gpg_error_t rc;
676 if (fd != -1)
678 if (fstat (fd, &st) == -1)
679 return gpg_error_from_syserror ();
681 inq.size = st.st_size;
684 inq.fd = fd;
685 inq.line = pwmd_calloc (1, ASSUAN_LINELENGTH);
686 if (!inq.line)
687 return GPG_ERR_ENOMEM;
689 if (line)
691 char *s = escape (line);
693 if (!s)
695 pwmd_free (inq.line);
696 return GPG_ERR_ENOMEM;
699 if (strlen (s) >= ASSUAN_LINELENGTH)
701 pwmd_free (inq.line);
702 pwmd_free (s);
703 return GPG_ERR_LINE_TOO_LONG;
706 strncpy (inq.line, s, ASSUAN_LINELENGTH - 1);
707 inq.len = strlen (s);
708 pwmd_free (s);
711 rc = pwmd_setopt (pwm, PWMD_OPTION_INQUIRE_TOTAL,
712 st.st_size ? st.st_size + strlen (inq.line) : 0);
713 if (rc)
715 pwmd_free (inq.line);
716 return rc;
719 if (*result == NULL)
720 *result = pwmd_malloc (sizeof (struct inquire_s));
721 else
723 if ((*result)->fd != -1 && (*result)->fd != STDIN_FILENO)
724 close ((*result)->fd);
726 pwmd_free ((*result)->line);
727 (*result)->line = NULL;
728 (*result)->fd = -1;
729 (*result)->len = 0;
732 memcpy (*result, &inq, sizeof (struct inquire_s));
733 memset (&inq, 0, sizeof (struct inquire_s));
734 return rc;
737 #ifdef HAVE_LIBREADLINE
738 static int
739 interactive_hook (void)
741 interactive_error = process_cmd ();
743 if (interactive_error)
744 rl_event_hook = NULL;
746 return 0;
749 static void
750 print_help ()
752 fprintf (stderr,
754 ("------------------------------------------------------------------------------\n"
755 "Elements are TAB delimited. Press CTRL-V then TAB to insert from the prompt.\n"
756 "\n"
757 "Type HELP for protocol commands. Type .help for pwmc commands. Press CTRL-D\n"
758 "to quit.\n"
759 "------------------------------------------------------------------------------\n"));
761 #endif
763 static char *
764 parse_arg (const char *src, char *dst, size_t len)
766 char *p = dst;
767 const char *s = src;
768 size_t n = 0;
770 for (; s && *s && *s != ' ' && n < len; s++, n++)
771 *p++ = *s;
773 *p = 0;
774 return dst;
777 static char *
778 parse_opt (char **line, const char *opt, gpg_error_t * rc)
780 static char result[ASSUAN_LINELENGTH] = { 0 }, *r = result;
781 size_t len = 0;
782 char *s = strstr (*line, opt);
784 *rc = 0;
785 result[0] = 0;
786 r = result;
788 if (s)
790 int quote = 0;
791 size_t rlen = strlen (opt);
792 char *p = s + rlen;
793 int lastc = 0;
795 while (*p && *p == ' ')
797 rlen++;
798 p++;
801 for (; *p && len < sizeof (result) - 1; p++, rlen++)
803 if (isspace (*p) && !quote)
804 break;
806 if (*p == '\"' && lastc != '\\')
808 quote = !quote;
809 lastc = *p;
810 continue;
813 *r++ = lastc = *p;
814 len++;
817 *r = 0;
819 if (len >= sizeof (result) - 1)
820 *rc = GPG_ERR_LINE_TOO_LONG;
821 else
823 p = s + rlen;
825 while (*p && *p == ' ')
826 p++;
828 *line = p;
832 return result;
835 static gpg_error_t
836 read_command (const char *line, char **result, size_t * len)
838 int fd;
839 gpg_error_t rc = 0;
840 char filebuf[ASSUAN_LINELENGTH];
841 char *filename = NULL;
842 struct inquire_s *inq = NULL;
843 char *p = (char *) line;
844 const char *prefix = parse_opt (&p, "--prefix", &rc);
846 if (rc)
847 return rc;
849 rc = GPG_ERR_SYNTAX;
851 if (p && *p)
853 while (*p && isspace (*p))
854 p++;
856 filename = parse_arg (p, filebuf, sizeof (filebuf));
857 if (filename && *filename)
859 p += strlen (filename) + 1;
861 while (*p && isspace (*p))
862 p++;
864 if (*p)
865 rc = 0;
869 if (rc)
871 fprintf (stderr,
873 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
874 fprintf (stderr,
876 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\" = \")\n"));
877 return rc;
880 fd = open (filename, O_RDONLY);
881 if (fd == -1)
882 return gpg_error_from_syserror ();
884 rc = set_inquire (fd, prefix && *prefix ? prefix : NULL, &inq);
885 if (rc)
887 close (fd);
888 return rc;
891 inq->header = 1;
892 rc = pwmd_command (pwm, result, len, inquire_cb, inq, p);
893 free_inquire (inq);
894 return rc;
897 static gpg_error_t
898 redir_command (const char *line)
900 const char *p = line;
901 int fd;
902 gpg_error_t rc = GPG_ERR_SYNTAX;
903 char filebuf[ASSUAN_LINELENGTH];
904 char *filename = NULL;
905 struct inquire_s *inq = NULL;
906 char *result = NULL;
907 size_t len = 0;
909 if (p && *p && *++p)
911 filename = parse_arg (p, filebuf, sizeof (filebuf));
912 if (filename && *filename)
914 p += strlen (filename) + 1;
916 while (*p && isspace (*p))
917 p++;
919 if (*p)
920 rc = 0;
924 if (rc)
926 fprintf (stderr, N_("Usage: .redir <filename> <command> [args]\n"));
927 return rc;
930 fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
931 if (fd == -1)
932 return gpg_error_from_syserror ();
934 #ifdef HAVE_LIBREADLINE
935 rc = set_inquire (interactive ? STDIN_FILENO : inquirefd, NULL, &inq);
936 #else
937 rc = set_inquire (inquirefd, NULL, &inq);
938 #endif
939 if (rc)
941 close (fd);
942 return rc;
945 rc = parse_dotcommand (p, &result, &len, inq);
946 if (!rc && result && len--)
947 { // null byte which is always appended
948 if (write (fd, result, len) != len)
949 rc = GPG_ERR_TOO_SHORT;
950 pwmd_free (result);
953 free_inquire (inq);
954 close (fd);
955 return rc;
958 static gpg_error_t
959 help_command (const char *line)
961 fprintf (stderr,
962 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
963 " .redir <filename> <command>\n"
964 " redirect the output of a command to the specified file\n"
965 "\n" " .open <filename>\n"
966 " open the specified filename losing any changes to the current one\n"
967 "\n" " .read [--prefix <string>] <filename> <command> [args]\n"
968 " obtain data from the specified filename for an inquire command\n"
969 "\n" " .set help | <name> [<value>]\n"
970 " set option <name> to <value>\n" "\n" " .help\n"
971 " this help text\n"));
972 return 0;
975 static gpg_error_t
976 open_command (const char *line)
978 struct inquire_s *inq = NULL;
979 const char *filename = line;
980 gpg_error_t rc;
982 while (filename && isspace (*filename))
983 filename++;
985 if (!filename || !*filename)
987 fprintf (stderr, N_("Usage: .open <filename>\n"));
988 return GPG_ERR_SYNTAX;
991 #ifdef HAVE_LIBREADLINE
992 if (interactive || !quiet)
993 #else
994 if (!quiet)
995 #endif
996 fprintf (stderr, N_("Opening data file \"%s\" ...\n"), filename);
998 #ifdef HAVE_LIBREADLINE
999 rc = set_inquire (interactive ? STDIN_FILENO : -1, NULL, &inq);
1000 #else
1001 rc = set_inquire (-1, NULL, &inq);
1002 #endif
1003 if (rc)
1004 return rc;
1006 if (keyfile)
1007 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1009 #ifdef HAVE_LIBREADLINE
1010 // For safety. This file may be a different one. Make the user set it
1011 // again if needed.
1012 if (interactive)
1014 pwmd_free (new_keyfile);
1015 new_keyfile = NULL;
1017 #endif
1019 rc = pwmd_open (pwm, filename, inquire_cb, inq);
1020 free_inquire (inq);
1021 return rc;
1024 static gpg_error_t
1025 set_command (const char *line)
1027 gpg_error_t rc = 0;
1028 char name[256] = { 0 };
1029 char value[512] = { 0 };
1030 char *namep;
1031 char *valuep;
1032 const char *p = line;
1034 while (p && *p && isspace (*p))
1035 p++;
1037 namep = parse_arg (p, name, sizeof (name));
1038 if (!namep || !*namep)
1040 fprintf (stderr, N_("Usage: .set help | <name> [<value>]\n"));
1041 return GPG_ERR_SYNTAX;
1044 p += strlen (namep);
1045 while (p && *p && isspace (*p))
1046 p++;
1048 valuep = parse_arg (p, value, sizeof (value));
1050 if (!strcmp (name, "keyfile") || !strcmp (name, "new-keyfile"))
1052 int is_newkeyfile = 1;
1053 int is_pkcs = 1;
1054 char datafile[256];
1056 if (!strcmp (name, "keyfile"))
1057 is_newkeyfile = 0;
1059 if (is_newkeyfile)
1061 pwmd_free (new_keyfile);
1062 new_keyfile = NULL;
1064 else
1066 pwmd_free (keyfile);
1067 keyfile = NULL;
1070 p += strlen (valuep);
1071 while (p && *p && isspace (*p))
1072 p++;
1074 valuep = (char *) p;
1075 if (*valuep)
1077 memcpy (datafile, value, sizeof (datafile));
1078 valuep = parse_arg (p, value, sizeof (value));
1079 rc =
1080 pwmd_command (pwm, NULL, NULL, NULL, NULL, "KEYGRIP %s",
1081 datafile);
1082 if (gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
1084 rc = 0;
1085 is_pkcs = 0;
1087 else if (!rc)
1088 is_pkcs = 1;
1091 if (!rc && *valuep)
1093 if (is_newkeyfile)
1094 new_keyfile = pwmd_strdup (value);
1095 else
1096 keyfile = pwmd_strdup (value);
1098 if (!is_pkcs)
1099 rc = 0;
1100 else
1101 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1102 "AGENT option pinentry-mode=loopback");
1104 if (!rc)
1106 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 1);
1107 rc = pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1110 else if (!local_pin && !no_pinentry)
1112 pwmd_socket_t t;
1114 pwmd_socket_type (pwm, &t);
1115 if (t == PWMD_SOCKET_LOCAL)
1117 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 0);
1118 rc = pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
1122 else if (!strcmp (name, "help"))
1124 fprintf (stderr,
1126 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1127 "delimited. When no value is specified the option is unset.\n\n"
1128 "keyfile <datafile> [<filename>]\n"
1129 " set or unset the keyfile to be used when a passphrase is required\n"
1130 "\n" "new-keyfile <datafile> [<filename>]\n"
1131 " set or unset the keyfile to be used when a new passphrase is required\n"));
1133 else
1134 rc = GPG_ERR_UNKNOWN_OPTION;
1136 return rc;
1139 static gpg_error_t
1140 parse_dotcommand (const char *line, char **result,
1141 size_t * len, struct inquire_s *inq)
1143 const char *p = line;
1144 gpg_error_t rc = 0;
1146 if (!strncmp (p, ".read", 5))
1147 rc = read_command (p + 5, result, len);
1148 else if (!strncmp (p, ".redir", 6))
1149 rc = redir_command (p + 6);
1150 else if (!strncmp (p, ".help", 5))
1151 rc = help_command (p + 5);
1152 else if (!strncmp (p, ".open", 5))
1153 rc = open_command (p + 5);
1154 else if (!strncmp (p, ".set", 4))
1155 rc = set_command (p + 4);
1156 else
1157 rc = pwmd_command (pwm, result, len, inquire_cb, inq, line);
1159 return FINISH (rc);
1162 #ifdef HAVE_LIBREADLINE
1163 static gpg_error_t
1164 do_interactive ()
1166 gpg_error_t rc;
1167 struct inquire_s *inq = NULL;
1169 rl_initialize ();
1170 rc = process_cmd ();
1171 if (rc)
1172 return rc;
1174 rc = set_inquire (STDIN_FILENO, NULL, &inq);
1175 if (rc)
1176 return rc;
1178 fprintf (stderr,
1179 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1180 print_help ();
1181 rl_event_hook = &interactive_hook;
1182 rl_set_keyboard_input_timeout (100000);
1184 for (;;)
1186 char *line;
1187 char *result = NULL;
1188 size_t len;
1190 rc = 0;
1191 line = readline ("pwm> ");
1192 if (interactive_error)
1194 rc = interactive_error;
1195 break;
1198 if (!line)
1200 rc = finalize ();
1201 if (!rc)
1202 break;
1204 if (gpg_err_code (rc) != GPG_ERR_CANCELED &&
1205 gpg_err_code (rc) != GPG_ERR_EOF)
1206 fprintf (stderr, "ERR %i: %s\n", rc, gpg_strerror (rc));
1208 continue;
1210 else if (!*line)
1212 free (line);
1213 continue;
1216 #ifdef HAVE_READLINE_HISTORY
1217 add_history (line);
1218 #endif
1219 inq->header = 0;
1220 rc = parse_dotcommand (line, &result, &len, inq);
1221 free (line);
1222 if (rc)
1224 char *tmp = NULL;
1226 if (gpg_err_code (rc) == GPG_ERR_BAD_DATA)
1227 (void) pwmd_command (pwm, &tmp, NULL, NULL, NULL,
1228 "GETINFO last_error");
1230 show_error (rc, tmp);
1231 pwmd_free (tmp);
1233 else if (result && len)
1234 printf ("%s%s", result, result[len - 1] != '\n' ? "\n" : "");
1236 pwmd_free (result);
1239 free_inquire (inq);
1240 return rc;
1242 #endif
1244 static char *
1245 itoa (long long int n)
1247 static char buf[64];
1249 snprintf (buf, sizeof (buf), "%llu", n);
1250 return buf;
1253 static gpg_error_t
1254 finalize ()
1256 gpg_error_t rc = 0;
1257 #ifdef HAVE_LIBREADLINE
1258 int quit = 0;
1260 if (!force_save && interactive)
1262 char *p, buf[16];
1263 int finished = 0;
1265 fprintf (stderr, "\n");
1269 fprintf (stderr,
1271 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1272 p = fgets (buf, sizeof (buf), stdin);
1274 if (feof (stdin))
1276 clearerr (stdin);
1277 return GPG_ERR_EOF;
1280 switch (*p)
1282 case 'h':
1283 print_help ();
1284 break;
1285 case 'c':
1286 return GPG_ERR_CANCELED;
1287 case 'Q':
1288 return 0;
1289 case 'f':
1290 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1291 "CLEARCACHE %s", filename);
1292 if (rc)
1293 return rc;
1295 interactive_hook ();
1296 break;
1297 case 'S':
1298 quit = 1;
1299 case 's':
1300 save = 1;
1301 finished = 1;
1302 break;
1303 default:
1304 break;
1307 while (!finished);
1309 #endif
1311 if (save && !filename)
1313 fprintf (stderr,
1315 ("No filename was specified on the command line. Aborting.\n"));
1316 return GPG_ERR_CANCELED;
1319 if (save && filename)
1321 char *args =
1322 pwmd_strdup_printf ("%s%s %s%s %s %s%s %s%s %s --s2k-count=%lu",
1323 keygrip ? "--keygrip=" : "",
1324 keygrip ? keygrip : "",
1325 sign_keygrip ? "--sign-keygrip=" : "",
1326 sign_keygrip ? sign_keygrip : "",
1327 no_passphrase ? "--no-passphrase" : "",
1328 cipher ? "--cipher=" : "", cipher ? cipher : "",
1329 iterations_arg ? "--cipher-iterations=" : "",
1330 iterations_arg ? itoa (iterations) : "",
1331 no_gpg_agent ? "--no-agent" : "",
1332 s2k_count);
1334 #ifdef HAVE_LIBREADLINE
1335 if (!quiet || interactive)
1337 #else
1338 if (!quiet)
1340 #endif
1341 fprintf (stderr, "\n");
1342 fprintf (stderr, N_("Saving changes ...\n"));
1345 rc = pwmd_save (pwm, args, inquire_cb, NULL);
1346 pwmd_free (args);
1348 if (!rc)
1349 no_passphrase = 0; // reset to avoid usage error on the next SAVE
1352 #ifdef HAVE_LIBREADLINE
1353 if (interactive)
1354 return rc ? rc : quit ? 0 : GPG_ERR_CANCELED;
1355 #endif
1357 return rc;
1361 main (int argc, char *argv[])
1363 int connected = 0;
1364 gpg_error_t rc;
1365 int opt;
1366 char command[ASSUAN_LINELENGTH], *p = NULL;
1367 char *result = NULL;
1368 size_t len;
1369 char *pinentry_path = NULL;
1370 char *display = NULL, *tty = NULL, *ttytype = NULL;
1371 char *lcctype = NULL, *lcmessages = NULL;
1372 int outfd = STDOUT_FILENO;
1373 FILE *outfp = stdout;
1374 FILE *inquirefp = stdin;
1375 int show_status = 1;
1376 char *clientname = "pwmc";
1377 char *inquire = NULL;
1378 char *inquire_line = NULL;
1379 int timeout = 0;
1380 #ifdef WITH_SSH
1381 int use_ssh_agent = 1;
1382 char *knownhosts = NULL;
1383 char *identity = NULL;
1384 #endif
1385 #ifdef WITH_GNUTLS
1386 char *cacert = NULL;
1387 char *clientcert = NULL;
1388 char *clientkey = NULL;
1389 char *prio = NULL;
1390 int tls_verify = 0;
1391 char *tls_fingerprint = NULL;
1392 #endif
1393 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1394 pwmd_socket_t socktype;
1395 long socket_timeout = 300;
1396 int connect_timeout = 120;
1397 #endif
1398 int lock_on_open = 1;
1399 long lock_timeout = 0;
1400 char *url = NULL;
1401 /* The order is important. */
1402 enum
1404 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1405 OPT_SOCKET_TIMEOUT, OPT_CONNECT_TIMEOUT,
1406 #endif
1407 #ifdef WITH_SSH
1408 OPT_USE_SSH_AGENT, OPT_IDENTITY, OPT_KNOWNHOSTS,
1409 #endif
1410 #ifdef WITH_GNUTLS
1411 OPT_CACERT, OPT_CLIENTCERT, OPT_CLIENTKEY, OPT_PRIORITY, OPT_VERIFY,
1412 OPT_SERVER_FP,
1413 #endif
1414 OPT_URL, OPT_LOCAL, OPT_FORCE_SAVE, OPT_TTYNAME, OPT_TTYTYPE,
1415 OPT_DISPLAY, OPT_LC_CTYPE, OPT_LC_MESSAGES, OPT_TIMEOUT, OPT_TRIES,
1416 OPT_PINENTRY, OPT_KEYFILE, OPT_NEW_KEYFILE, OPT_NOLOCK,
1417 OPT_LOCK_TIMEOUT, OPT_SAVE, OPT_OUTPUT_FD, OPT_INQUIRE,
1418 OPT_INQUIRE_FD, OPT_INQUIRE_FILE, OPT_INQUIRE_LINE, OPT_NO_STATUS,
1419 OPT_NAME, OPT_VERSION, OPT_HELP, OPT_KEYGRIP, OPT_SIGN_KEYGRIP,
1420 OPT_NOPASSPHRASE, OPT_CIPHER, OPT_KEYPARAMS, OPT_NO_PINENTRY,
1421 OPT_S2K_COUNT, OPT_ITERATIONS, OPT_QUIET, OPT_NO_GPG_AGENT,
1422 #ifdef HAVE_LIBREADLINE
1423 OPT_INTERACTIVE,
1424 #endif
1426 const struct option long_opts[] = {
1427 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1428 {"socket-timeout", 1, 0, 0},
1429 {"connect-timeout", 1, 0, 0},
1430 #endif
1432 #ifdef WITH_SSH
1433 {"no-ssh-agent", 0, 0, 0},
1434 {"identity", 1, 0, 'i'},
1435 {"knownhosts", 1, 0, 'k'},
1436 #endif
1437 #ifdef WITH_GNUTLS
1438 {"ca-cert", 1, 0, 0},
1439 {"client-cert", 1, 0, 0},
1440 {"client-key", 1, 0, 0},
1441 {"tls-priority", 1, 0, 0},
1442 {"tls-verify", 0, 0, 0},
1443 {"tls-fingerprint", 1, 0, 0},
1444 #endif
1445 {"url", 1, 0, 0},
1446 {"local-pinentry", 0, 0},
1447 {"force-save", 0, 0},
1448 {"ttyname", 1, 0, 'y'},
1449 {"ttytype", 1, 0, 't'},
1450 {"display", 1, 0, 'd'},
1451 {"lc-ctype", 1, 0, 0},
1452 {"lc-messages", 1, 0, 0},
1453 {"timeout", 1, 0, 0},
1454 {"tries", 1, 0, 0},
1455 {"pinentry", 1, 0, 0},
1456 {"key-file", 1, 0, 0},
1457 {"new-key-file", 1, 0, 0},
1458 {"no-lock", 0, 0, 0},
1459 {"lock-timeout", 1, 0, 0},
1460 {"save", 0, 0, 'S'},
1461 {"output-fd", 1, 0, 0},
1462 {"inquire", 1, 0, 0},
1463 {"inquire-fd", 1, 0, 0},
1464 {"inquire-file", 1, 0, 0},
1465 {"inquire-line", 1, 0, 'L'},
1466 {"no-status", 0, 0, 0},
1467 {"name", 1, 0, 'n'},
1468 {"version", 0, 0, 0},
1469 {"help", 0, 0, 0},
1470 {"keygrip", 1, 0, 0},
1471 {"sign-keygrip", 1, 0, 0},
1472 {"no-passphrase", 0, 0, 0},
1473 {"cipher", 1, 0, 0},
1474 {"key-params", 1, 0, 0},
1475 {"no-pinentry", 0, 0, 0},
1476 {"s2k-count", 1, 0, 0},
1477 {"cipher-iterations", 1, 0, 0},
1478 {"quiet", 0, 0, 0},
1479 {"no-gpg-agent", 0, 0, 0},
1480 #ifdef HAVE_LIBREADLINE
1481 {"interactive", 0, 0},
1482 #endif
1483 {0, 0, 0, 0}
1485 #ifdef WITH_SSH
1486 const char *optstring = "L:y:t:d:P:I:Sn:i:k:";
1487 #else
1488 const char *optstring = "L:y:t:d:P:I:Sn:";
1489 #endif
1490 int opt_index = 0;
1492 #ifdef ENABLE_NLS
1493 setlocale (LC_ALL, "");
1494 bindtextdomain ("libpwmd", LOCALEDIR);
1495 #endif
1497 tries = DEFAULT_PIN_TRIES;
1498 inquirefd = STDIN_FILENO;
1500 while ((opt =
1501 getopt_long (argc, argv, optstring, long_opts, &opt_index)) != -1)
1503 switch (opt)
1505 /* Handle long options without a short option part. */
1506 case 0:
1507 switch (opt_index)
1509 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1510 case OPT_SOCKET_TIMEOUT:
1511 socket_timeout = strtol (optarg, &p, 10);
1512 break;
1513 case OPT_CONNECT_TIMEOUT:
1514 connect_timeout = strtol (optarg, &p, 10);
1515 break;
1516 #endif
1517 #ifdef WITH_SSH
1518 case OPT_USE_SSH_AGENT:
1519 use_ssh_agent = 0;
1520 break;
1521 #endif
1522 #ifdef WITH_GNUTLS
1523 case OPT_CACERT:
1524 cacert = optarg;
1525 break;
1526 case OPT_CLIENTCERT:
1527 clientcert = optarg;
1528 break;
1529 case OPT_CLIENTKEY:
1530 clientkey = optarg;
1531 break;
1532 case OPT_PRIORITY:
1533 prio = optarg;
1534 break;
1535 case OPT_VERIFY:
1536 tls_verify = 1;
1537 break;
1538 case OPT_SERVER_FP:
1539 tls_fingerprint = optarg;
1540 break;
1541 #endif
1542 case OPT_NO_GPG_AGENT:
1543 no_gpg_agent = 1;
1544 break;
1545 case OPT_KEYPARAMS:
1546 keyparams = optarg;
1547 break;
1548 case OPT_KEYFILE:
1549 keyfile = pwmd_strdup (optarg);
1550 break;
1551 case OPT_NEW_KEYFILE:
1552 new_keyfile = pwmd_strdup (optarg);
1553 break;
1554 case OPT_NOLOCK:
1555 lock_on_open = 0;
1556 break;
1557 case OPT_LOCK_TIMEOUT:
1558 lock_timeout = strtol (optarg, &p, 10);
1559 break;
1560 case OPT_URL:
1561 url = optarg;
1562 break;
1563 case OPT_LOCAL:
1564 local_pin = 1;
1565 break;
1566 case OPT_FORCE_SAVE:
1567 save = force_save = 1;
1568 break;
1569 case OPT_LC_CTYPE:
1570 lcctype = pwmd_strdup (optarg);
1571 break;
1572 case OPT_LC_MESSAGES:
1573 lcmessages = pwmd_strdup (optarg);
1574 break;
1575 case OPT_TIMEOUT:
1576 timeout = strtol (optarg, &p, 10);
1577 break;
1578 case OPT_TRIES:
1579 tries = strtol (optarg, &p, 10);
1580 break;
1581 case OPT_INQUIRE:
1582 inquire = optarg;
1583 break;
1584 case OPT_INQUIRE_FD:
1585 inquirefd = strtol (optarg, &p, 10);
1586 if (!p)
1588 inquirefp = fdopen (inquirefd, "r");
1589 if (!inquirefp)
1591 pwmd_free (password);
1592 err (EXIT_FAILURE, "%i", inquirefd);
1595 break;
1596 case OPT_INQUIRE_FILE:
1597 inquirefd = open (optarg, O_RDONLY);
1598 if (inquirefd == -1)
1600 pwmd_free (password);
1601 err (EXIT_FAILURE, "%s", optarg);
1603 inquirefp = fdopen (inquirefd, "r");
1604 break;
1605 case OPT_OUTPUT_FD:
1606 outfd = strtol (optarg, &p, 10);
1607 if (!p)
1609 outfp = fdopen (outfd, "w");
1610 if (!outfp)
1612 pwmd_free (password);
1613 err (EXIT_FAILURE, "%i", outfd);
1616 break;
1617 case OPT_NO_STATUS:
1618 show_status = 0;
1619 break;
1620 case OPT_VERSION:
1621 pwmd_free (password);
1622 printf ("%s (pwmc)\n\n"
1623 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013\n"
1624 "%s\n"
1625 "Released under the terms of the GPL v2. Use at your own risk.\n\n"
1626 "Compile-time features:\n"
1627 #ifdef HAVE_LIBREADLINE
1628 "+INTERACTIVE "
1629 #else
1630 "-INTERACTIVE "
1631 #endif
1632 #ifdef WITH_SSH
1633 "+SSH "
1634 #else
1635 "-SSH "
1636 #endif
1637 #ifdef WITH_GNUTLS
1638 "+GNUTLS "
1639 #else
1640 "-GNUTLS "
1641 #endif
1642 #ifdef WITH_PINENTRY
1643 "+PINENTRY "
1644 #else
1645 "-PINENTRY "
1646 #endif
1647 #ifdef WITH_QUALITY
1648 "+CRACK "
1649 #else
1650 "-CRACK "
1651 #endif
1652 #ifdef MEM_DEBUG
1653 "+MEM_DEBUG "
1654 #else
1655 "-MEM_DEBUG "
1656 #endif
1657 "\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
1658 exit (EXIT_SUCCESS);
1659 case OPT_PINENTRY:
1660 pinentry_path = optarg;
1661 break;
1662 case OPT_HELP:
1663 usage (argv[0], EXIT_SUCCESS);
1664 case OPT_KEYGRIP:
1665 keygrip = optarg;
1666 break;
1667 case OPT_SIGN_KEYGRIP:
1668 sign_keygrip = optarg;
1669 break;
1670 case OPT_S2K_COUNT:
1671 s2k_count = strtoul (optarg, &p, 10);
1672 break;
1673 case OPT_ITERATIONS:
1674 iterations = strtoull (optarg, &p, 10);
1675 iterations_arg = 1;
1676 break;
1677 case OPT_QUIET:
1678 quiet = 1;
1679 show_status = 0;
1680 break;
1681 case OPT_NOPASSPHRASE:
1682 no_passphrase = 1;
1683 break;
1684 case OPT_CIPHER:
1685 cipher = optarg;
1686 break;
1687 case OPT_NO_PINENTRY:
1688 no_pinentry = 1;
1689 break;
1690 #ifdef HAVE_LIBREADLINE
1691 case OPT_INTERACTIVE:
1692 interactive = 1;
1693 break;
1694 #endif
1695 default:
1696 usage (argv[0], EXIT_FAILURE);
1699 if (p && *p)
1701 fprintf (stderr, N_("%s: invalid argument for option '--%s'\n"),
1702 argv[0], long_opts[opt_index].name);
1703 usage (argv[0], EXIT_FAILURE);
1706 break;
1707 #ifdef WITH_SSH
1708 case 'i':
1709 identity = optarg;
1710 break;
1711 case 'k':
1712 knownhosts = optarg;
1713 break;
1714 #endif
1715 case 'L':
1716 inquire_line = optarg;
1717 break;
1718 case 'y':
1719 tty = optarg;
1720 break;
1721 case 't':
1722 ttytype = optarg;
1723 break;
1724 case 'd':
1725 display = optarg;
1726 break;
1727 case 'S':
1728 save = 1;
1729 break;
1730 case 'n':
1731 clientname = optarg;
1732 break;
1733 default:
1734 pwmd_free (password);
1735 usage (argv[0], EXIT_FAILURE);
1739 #ifdef HAVE_LIBREADLINE
1740 if (interactive && !isatty (STDIN_FILENO))
1742 pwmd_free (password);
1743 usage (argv[0], EXIT_FAILURE);
1745 else if (isatty (STDIN_FILENO) && !inquire && !inquire_line)
1746 interactive = 1;
1747 #endif
1749 filename = argv[optind];
1750 #ifdef WITH_GNUTLS
1751 gnutls_global_set_mem_functions (pwmd_malloc, pwmd_malloc, NULL,
1752 pwmd_realloc, pwmd_free);
1753 #endif
1754 pwmd_init ();
1755 rc = pwmd_new (clientname, &pwm);
1756 if (rc)
1757 goto done;
1759 pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TRIES, tries);
1760 if (!quiet)
1761 fprintf (stderr, N_("Connecting ...\n"));
1763 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1764 socktype = is_remote_url (url);
1765 if (socktype != PWMD_SOCKET_LOCAL)
1767 local_pin = 1;
1768 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1769 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, connect_timeout);
1770 if (rc)
1771 goto done;
1772 #endif
1774 if (socktype == PWMD_SOCKET_SSH)
1776 #ifdef WITH_SSH
1777 rc = pwmd_setopt (pwm, PWMD_OPTION_KNOWNHOST_CB, knownhost_cb);
1778 if (rc)
1779 goto done;
1781 rc = pwmd_setopt (pwm, PWMD_OPTION_KNOWNHOST_DATA, clientname);
1782 if (rc)
1783 goto done;
1785 if (!getenv ("SSH_AUTH_SOCK") || identity)
1786 use_ssh_agent = 0;
1788 rc = pwmd_setopt (pwm, PWMD_OPTION_SSH_AGENT, use_ssh_agent);
1789 if (rc)
1790 goto done;
1792 rc = pwmd_connect (pwm, url, identity, knownhosts);
1793 #endif
1795 #ifdef WITH_GNUTLS
1796 else
1798 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_VERIFY, tls_verify);
1799 if (rc)
1800 goto done;
1802 rc = pwmd_connect (pwm, url, clientcert, clientkey, cacert, prio,
1803 tls_fingerprint);
1805 #endif
1807 else
1808 rc = pwmd_connect (pwm, url);
1809 #else
1810 rc = pwmd_connect (pwm, url);
1811 #endif
1812 if (rc)
1813 goto done;
1815 if (!quiet)
1816 fprintf (stderr, N_("Connected.\n"));
1818 connected = 1;
1819 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1820 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, socket_timeout);
1821 if (rc)
1822 goto done;
1823 #endif
1825 if (lock_timeout)
1827 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1828 "OPTION LOCK-TIMEOUT=%li", lock_timeout);
1829 if (rc)
1830 goto done;
1833 if (lock_on_open)
1835 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCK_ON_OPEN, 1);
1836 if (rc)
1837 goto done;
1840 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DESC, NULL);
1841 if (rc)
1842 goto done;
1844 if (timeout > 0)
1846 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TIMEOUT, timeout);
1847 if (rc)
1848 goto done;
1851 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, no_pinentry);
1852 if (rc)
1853 goto done;
1855 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCAL_PINENTRY,
1856 (local_pin || keyfile || new_keyfile));
1857 if (rc)
1858 goto done;
1860 if (pinentry_path)
1862 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_PATH, pinentry_path);
1863 if (rc)
1864 goto done;
1867 if (display)
1869 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, display);
1870 if (rc)
1871 goto done;
1874 if (tty)
1876 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, tty);
1877 if (rc)
1878 goto done;
1881 if (ttytype)
1883 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, ttytype);
1884 if (rc)
1885 goto done;
1888 if (lcctype)
1890 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_CTYPE, lcctype);
1891 if (rc)
1892 goto done;
1895 if (lcmessages)
1897 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_MESSAGES, lcmessages);
1898 if (rc)
1899 goto done;
1902 if (show_status)
1904 rc = pwmd_setopt (pwm, PWMD_OPTION_STATUS_CB, status_msg_cb);
1905 if (rc)
1906 goto done;
1909 if (filename)
1911 rc = open_command (filename);
1912 if (rc)
1913 goto done;
1916 #ifdef HAVE_LIBREADLINE
1917 if (interactive)
1919 if (!force_save)
1920 save = 0;
1922 rc = do_interactive ();
1923 result = NULL;
1924 goto do_exit;
1926 #endif
1928 if (inquire)
1930 struct inquire_s *inq = NULL;
1932 rc = set_inquire (inquirefd, inquire_line, &inq);
1933 if (!rc)
1934 rc = pwmd_command (pwm, &result, &len, inquire_cb, inq, inquire);
1936 free_inquire (inq);
1937 goto done;
1940 fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
1941 ssize_t n;
1943 for (;;)
1945 rc = process_cmd ();
1947 if (rc)
1948 goto done;
1950 n = read (STDIN_FILENO, command, sizeof (command));
1951 if (n == -1)
1953 if (errno == EAGAIN)
1955 usleep (100000);
1956 continue;
1959 rc = gpg_error_from_errno (errno);
1960 goto done;
1962 else if (!n)
1963 goto done;
1965 p = command;
1966 command[n] = 0;
1967 break;
1970 if (!p || !*p || !strcasecmp (p, "BYE"))
1971 goto done;
1974 struct inquire_s *inq = NULL;
1975 rc = set_inquire (inquirefd, inquire_line, &inq);
1976 if (!rc)
1978 rc = parse_dotcommand (command, &result, &len, inq);
1979 free_inquire (inq);
1982 if (rc)
1983 goto done;
1985 done:
1986 if (result)
1988 fwrite (result, 1, result[len - 1] == 0 ? len - 1 : len, outfp);
1989 fflush (outfp);
1990 pwmd_free (result);
1993 pwmd_free (password);
1994 password = result = NULL;
1995 if (!rc)
1996 rc = finalize ();
1997 else if (gpg_err_code (rc) == GPG_ERR_BAD_DATA)
1998 (void) pwmd_command (pwm, &result, NULL, NULL, NULL,
1999 "GETINFO last_error");
2001 #ifdef HAVE_LIBREADLINE
2002 do_exit:
2003 #endif
2004 memset (command, 0, sizeof (command));
2005 pwmd_close (pwm);
2006 pwmd_free (keyfile);
2007 pwmd_free (new_keyfile);
2008 pwmd_deinit ();
2010 if (rc && !quiet)
2011 show_error (rc, result);
2013 pwmd_free (result);
2014 if (connected && !quiet)
2015 fprintf (stderr, N_("Connection closed.\n"));
2017 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);