Return value from do_interactive().
[libpwmd.git] / src / pwmc.c
blob3d8ed2c719fcc840febc1405be11b299f07f33a2
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;
106 struct inquire_s
108 int fd;
109 char *line;
110 size_t len;
111 size_t size; // from stat(2).
112 int header;
115 static gpg_error_t finalize ();
116 static gpg_error_t set_inquire (int fd, const char *line,
117 struct inquire_s **result);
118 static gpg_error_t parse_dotcommand (const char *line, char **result,
119 size_t * len, struct inquire_s *inq);
120 static gpg_error_t open_command (const char *line);
121 #ifdef WITH_SSH
122 static gpg_error_t get_password (char **result, pwmd_pinentry_t w, int echo);
123 #endif
125 static void
126 show_error (gpg_error_t rc, const char *str)
128 fprintf (stderr, "ERR %i: %s%s%s%s", rc, gpg_strerror (rc),
129 str ? ": " : "", str ? str : "", str ? "" : "\n");
132 static void
133 usage (const char *pn, int status)
135 fprintf (status == EXIT_FAILURE ? stderr : stdout,
136 N_("Read a PWMD protocol command from standard input.\n\n"
137 "Usage: pwmc [options] [file]\n" " --url <string>\n"
138 " a url string to connect to (see below)\n"
139 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
140 " --socket-timeout <seconds>\n"
141 " timeout before a remote command fails (0=disabled, default)\n"
142 #endif
143 #ifdef WITH_SSH
144 " --no-ssh-agent\n"
145 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
146 " --identity, -i <filename>\n"
147 " the ssh identity file to use for authentication\n"
148 " --knownhosts, -k <filename>\n"
149 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
150 #endif
151 #ifdef WITH_GNUTLS
152 " --ca-cert <filename>\n"
153 " certificate authority (CA) used to sign the server cert\n"
154 " --client-cert <filename>\n"
155 " client certificate to use for authentication\n"
156 " --client-key <filename>\n"
157 " key file used to protect the client certificate\n"
158 " --tls-priority <string>\n"
159 " compression, cipher and hash algorithm string (SECURE256)\n"
160 " --tls-verify\n"
161 " verify the hostname against the server certificate\n"
162 " --tls-fingerprint <string>\n"
163 " a SHA-1 hash of the server fingerprint to verify against\n"
164 #endif
165 " --no-lock\n"
166 " do not lock the data file upon opening it\n"
167 " --lock-timeout <N>\n"
168 " time in tenths of a second to wait for a locked data file\n"
169 " --no-status\n"
170 " disable showing of status messages from the server\n"
171 " --quiet\n"
172 " disable showing of extra messages (implies --no-status)\n"
173 " --name, -n <string>\n"
174 " set the client name\n"
175 " --no-passphrase\n"
176 " do not require a passphrase when saving a new file\n"
177 " --keygrip <string>\n"
178 " the hex string of the keygrip to save to\n"
179 " --sign-keygrip <string>\n"
180 " the hex string of the keygrip to sign with\n"
181 " --key-file <filename>\n"
182 " obtain the passphrase from the specified filename\n"
183 " --new-key-file <filename>\n"
184 " obtain the passphrase to save with from the specified filename\n"
185 " --s2k-count <N>\n"
186 " the number of times to hash the passphrase for a new file\n"
187 " --cipher-iterations <N>\n"
188 " the number of times to encrypt the XML data (N+1)\n"
189 " --timeout <seconds>\n"
190 " pinentry timeout\n"
191 " --tries <N>\n"
192 " number of pinentry tries before failing (3)\n"
193 " --no-pinentry\n"
194 " disable pinentry both remotely and locally\n"
195 " --pinentry <path>\n"
196 " the full path to the pinentry binary (server default)\n"
197 " --ttyname, -y <path>\n"
198 " tty that pinentry will use\n"
199 " --ttytype, -t <string>\n"
200 " pinentry terminal type (default is $TERM)\n"
201 " --display, -d\n"
202 " pinentry display (default is $DISPLAY)\n"
203 " --lc-ctype <string>\n"
204 " locale setting for pinentry\n"
205 " --lc-messages <string>\n"
206 " locale setting for pinentry\n"
207 " --local-pinentry\n" " force using a local pinentry\n"
208 #ifdef HAVE_LIBREADLINE
209 " --interactive\n"
210 " use a shell like interface to pwmd (allows more than one command)\n"
211 #endif
212 " --output-fd <FD>\n"
213 " redirect command output to the specified file descriptor\n"
214 " --inquire <COMMAND>\n"
215 " the specified command (with any options) uses a server inquire while\n"
216 " command data is read via the inquire file descriptor (stdin)\n"
217 " --inquire-fd <FD>\n"
218 " read inquire data from the specified file descriptor (stdin)\n"
219 " --inquire-file <filename>\n"
220 " read inquire data from the specified filename\n"
221 " --inquire-line, -L <STRING>\n"
222 " the initial line to send (i.e., element path) before the inquire data\n"
223 " --cipher <string>\n"
224 " the cipher to use when saving (see pwmd(1))\n"
225 " --save, -S\n"
226 " send the SAVE command before exiting\n"
227 " --key-params <string>\n"
228 " the key parameters to use when saving a new file (pwmd default)\n"
229 " --force-save\n"
230 " like --save but always ask for a passphrase\n"
231 " --version\n" " --help\n"));
232 fprintf (status == EXIT_FAILURE ? stderr : stdout,
233 N_("\n"
234 "An optional url may be in the form of:\n"
235 " --url /path/to/socket\n"
236 " --url file://[path/to/socket]\n"
237 #ifdef WITH_SSH
238 " or\n"
239 " --url ssh[46]://[username@]hostname[:port]\n"
240 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
241 #endif
242 #ifdef WITH_GNUTLS
243 " or\n"
244 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
245 " --client-key filename\n"
246 #endif
248 exit (status);
251 static gpg_error_t
252 inquire_cb (void *user, const char *keyword, gpg_error_t rc,
253 char **data, size_t * size)
255 struct inquire_s *inq = user;
256 int is_password = 0;
257 int is_newpassword = 0;
259 *data = NULL;
260 *size = 0;
262 if (rc)
263 return rc;
265 if (!strcmp (keyword, "PASSPHRASE"))
266 is_password = 1;
267 else if (!strcmp (keyword, "NEW_PASSPHRASE"))
268 is_newpassword = 1;
269 #ifdef HAVE_LIBREADLINE
270 else if (!strcmp (keyword, "KEYPARAM") && !interactive)
272 #else
273 else if (!strcmp (keyword, "KEYPARAM"))
275 #endif
276 if (!keyparams || !*keyparams)
277 return gpg_error (GPG_ERR_INV_PARAMETER);
279 *data = keyparams;
280 *size = strlen (keyparams);
281 return gpg_error (GPG_ERR_EOF);
284 if ((is_newpassword && new_keyfile) || (is_password && keyfile))
286 int fd = open (is_password ? keyfile : new_keyfile, O_RDONLY);
288 if (fd == -1)
290 fprintf (stderr, "%s: %s\n", is_newpassword ? new_keyfile : keyfile,
291 strerror (errno));
292 return gpg_error_from_syserror ();
295 rc = set_inquire (fd, NULL, &inq);
296 if (rc)
298 close (fd);
299 return rc;
302 if (!quiet)
303 fprintf (stderr, N_("Using keyfile '%s' as %s.\n"),
304 is_newpassword ? new_keyfile : keyfile, keyword);
306 if (!new_keyfile || is_newpassword)
308 pwmd_socket_t t;
310 pwmd_socket_type (pwm, &t);
311 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
312 if (!no_pinentry && t == PWMD_SOCKET_LOCAL)
313 pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 0);
316 else if (is_password && !keyfile)
318 char *tmp;
320 rc = pwmd_password (pwm, keyword, &tmp, &inq->len);
321 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
322 return rc;
324 pwmd_free (inq->line);
325 inq->line = tmp;
326 *data = inq->line;
327 *size = inq->len;
328 return gpg_error (GPG_ERR_EOF);
330 #ifdef HAVE_LIBREADLINE
331 else if (!inq->header && interactive)
333 fprintf (stderr,
335 ("Press CTRL-D to send the current line. Press twice to end. %s:\n"),
336 keyword);
337 inq->header = 1;
339 #endif
341 /* The first part of the command data. */
342 if (inq->len)
344 *data = inq->line;
345 *size = inq->len;
346 inq->len = 0;
347 return inq->fd == -1 ? gpg_error (GPG_ERR_EOF) : 0;
350 *size = read (inq->fd, inq->line, ASSUAN_LINELENGTH);
351 if (*size == -1)
353 *size = 0;
354 return gpg_error (gpg_error_from_syserror ());
356 else if (*size)
357 *data = inq->line;
358 else if (inq->fd != STDIN_FILENO && (is_newpassword || is_password))
360 *inq->line = 0;
361 inq->size = 1;
362 *data = inq->line;
363 *size = 1;
366 if (((is_newpassword && new_keyfile) || (is_password && keyfile))
367 && *size == inq->size)
368 return gpg_error (GPG_ERR_EOF);
370 return *size ? 0 : gpg_error (GPG_ERR_EOF);
373 static int
374 status_msg_cb (void *data, const char *line)
376 char *p = strchr (line, ' ');
378 if (!strcmp (line, "KEEPALIVE"))
379 return 0;
381 if (*line != '#' && p && strchr (p, ' ') && *++p)
383 char *p1 = strchr (p, ' ');
384 int a = strtol (p, NULL, 10);
386 if (isdigit (*p) && p1)
388 int b = strtol (p1, NULL, 10);
389 char l[64] = { 0 };
390 int t = a && b ? a * 100 / b : 0;
392 strncpy (l, line, strlen (line) - strlen (p) - 1);
393 fprintf (stderr, "\r%s %i/%i %i%%%s", l, a, b, t,
394 a == b ? "\n" : "");
395 fflush (stderr);
396 return 0;
400 fprintf (stderr, "%s\n", line);
401 fflush (stderr);
402 #ifdef HAVE_LIBREADLINE
403 rl_on_new_line ();
404 #endif
405 return 0;
408 static gpg_error_t
409 process_cmd ()
411 return pwmd_process (pwm);
414 #ifdef WITH_SSH
415 static gpg_error_t
416 get_password (char **result, pwmd_pinentry_t w, int echo)
418 char buf[LINE_MAX] = { 0 }, *p;
419 struct termios told, tnew;
420 char *key = NULL;
422 *result = NULL;
424 if (!isatty (STDIN_FILENO))
426 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
427 return GPG_ERR_ENOTTY;
430 if (!echo)
432 if (tcgetattr (STDIN_FILENO, &told) == -1)
433 return gpg_error_from_syserror ();
435 memcpy (&tnew, &told, sizeof (struct termios));
436 tnew.c_lflag &= ~(ECHO);
437 tnew.c_lflag |= ICANON | ECHONL;
439 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
441 int n = errno;
443 tcsetattr (STDIN_FILENO, TCSANOW, &told);
444 return gpg_error_from_errno (n);
448 switch (w)
450 case PWMD_PINENTRY_OPEN:
451 fprintf (stderr, N_("Password for %s: "), filename);
452 break;
453 case PWMD_PINENTRY_OPEN_FAILED:
454 fprintf (stderr, N_("Invalid password. Password for %s: "), filename);
455 break;
456 case PWMD_PINENTRY_SAVE:
457 fprintf (stderr, N_("New password for %s: "), filename);
458 break;
459 case PWMD_PINENTRY_SAVE_CONFIRM:
460 fprintf (stderr, N_("Confirm password: "));
461 break;
462 default:
463 break;
466 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
468 tcsetattr (STDIN_FILENO, TCSANOW, &told);
469 return 0;
472 if (!echo)
473 tcsetattr (STDIN_FILENO, TCSANOW, &told);
475 if (feof (stdin))
477 clearerr (stdin);
478 return GPG_ERR_CANCELED;
481 p[strlen (p) - 1] = 0;
483 if (buf[0])
485 key = pwmd_strdup_printf ("%s", p);
486 memset (&buf, 0, sizeof (buf));
488 if (!key)
489 return GPG_ERR_ENOMEM;
492 *result = key;
493 return 0;
496 static gpg_error_t
497 knownhost_cb (void *data, const char *host, const char *key, size_t len)
499 gpg_error_t rc;
500 char *buf =
501 pwmd_strdup_printf (N_
502 ("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?"),
503 (char *) data, host, host);
505 if (no_pinentry && !isatty (STDIN_FILENO))
507 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
508 pwmd_free (buf);
509 return GPG_ERR_ENOTTY;
511 else if (no_pinentry)
513 for (char *p = buf, len = 0; *p; p++, len++)
515 if (*p == '\n')
516 len = 0;
518 if (len == 78)
520 char *t = p;
522 while (!isspace (*(--p)));
523 *p = '\n';
524 p = t;
525 len = 0;
529 fprintf (stderr, "%s\n\n", buf);
530 pwmd_free (buf);
534 char *result;
536 fprintf (stderr, N_("Trust this connection [y/N]: "));
537 fflush (stderr);
538 rc = get_password (&result, PWMD_PINENTRY_CONFIRM, 1);
540 if (rc)
541 return rc;
543 if (!result || !*result || *result == 'n' || *result == 'N')
545 if (result && *result)
546 pwmd_free (result);
548 return GPG_ERR_NOT_CONFIRMED;
551 if ((*result == 'y' || *result == 'Y') && *(result + 1) == 0)
553 pwmd_free (result);
554 return 0;
557 while (1);
560 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DESC, buf);
561 pwmd_free (buf);
563 if (rc)
564 return rc;
566 return pwmd_getpin (pwm, NULL, NULL, NULL, PWMD_PINENTRY_CONFIRM);
568 #endif
570 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
571 static pwmd_socket_t
572 is_remote_url (const char *str)
574 if (!str)
575 return PWMD_SOCKET_LOCAL;
577 #ifdef WITH_SSH
578 if (strstr (str, "ssh://") || strstr (str, "ssh4://")
579 || strstr (str, "ssh6://"))
580 return PWMD_SOCKET_SSH;
581 #endif
583 #ifdef WITH_GNUTLS
584 if (strstr (str, "tls://") || strstr (str, "tls4://")
585 || strstr (str, "tls6://"))
586 return PWMD_SOCKET_TLS;
587 #endif
589 return PWMD_SOCKET_LOCAL;
591 #endif
593 static char *
594 escape (const char *str)
596 const char *p;
597 char *buf = pwmd_malloc (ASSUAN_LINELENGTH + 1), *b = buf;
598 size_t len = 0;
600 for (p = str; *p; p++, len++)
602 if (len == ASSUAN_LINELENGTH)
603 break;
605 if (*p == '\\')
607 switch (*++p)
609 case 't':
610 *b++ = '\t';
611 break;
612 case 'n':
613 *b++ = '\n';
614 break;
615 case 'v':
616 *b++ = '\v';
617 break;
618 case 'b':
619 *b++ = '\b';
620 break;
621 case 'f':
622 *b++ = '\f';
623 break;
624 case 'r':
625 *b++ = '\r';
626 break;
627 default:
628 *b++ = *p;
629 break;
632 if (!*p)
633 break;
635 continue;
638 *b++ = *p;
641 *b = 0;
642 return buf;
645 static void
646 free_inquire (struct inquire_s *inq)
648 if (!inq)
649 return;
651 pwmd_free (inq->line);
653 if (inq->fd != -1 && inq->fd != STDIN_FILENO)
654 close (inq->fd);
656 pwmd_free (inq);
659 /* When *result is not NULL it is updated to the new values and not
660 * reallocated. */
661 static gpg_error_t
662 set_inquire (int fd, const char *line, struct inquire_s **result)
664 struct inquire_s inq = { 0 };
665 struct stat st = { 0 };
666 gpg_error_t rc;
668 if (fd != -1)
670 if (fstat (fd, &st) == -1)
671 return gpg_error_from_syserror ();
673 inq.size = st.st_size;
676 inq.fd = fd;
677 inq.line = pwmd_calloc (1, ASSUAN_LINELENGTH);
678 if (!inq.line)
679 return GPG_ERR_ENOMEM;
681 if (line)
683 char *s = escape (line);
685 if (!s)
687 pwmd_free (inq.line);
688 return GPG_ERR_ENOMEM;
691 if (strlen (s) >= ASSUAN_LINELENGTH)
693 pwmd_free (inq.line);
694 pwmd_free (s);
695 return GPG_ERR_LINE_TOO_LONG;
698 strncpy (inq.line, s, ASSUAN_LINELENGTH - 1);
699 inq.len = strlen (s);
700 pwmd_free (s);
703 rc = pwmd_setopt (pwm, PWMD_OPTION_INQUIRE_TOTAL,
704 st.st_size ? st.st_size + strlen (inq.line) : 0);
705 if (rc)
707 pwmd_free (inq.line);
708 return rc;
711 if (*result == NULL)
712 *result = pwmd_malloc (sizeof (struct inquire_s));
713 else
715 if ((*result)->fd != -1 && (*result)->fd != STDIN_FILENO)
716 close ((*result)->fd);
718 pwmd_free ((*result)->line);
719 (*result)->line = NULL;
720 (*result)->fd = -1;
721 (*result)->len = 0;
724 memcpy (*result, &inq, sizeof (struct inquire_s));
725 memset (&inq, 0, sizeof (struct inquire_s));
726 return rc;
729 #ifdef HAVE_LIBREADLINE
730 static int
731 interactive_hook (void)
733 interactive_error = process_cmd ();
735 if (interactive_error)
736 rl_event_hook = NULL;
738 return 0;
741 static void
742 print_help ()
744 fprintf (stderr,
746 ("------------------------------------------------------------------------------\n"
747 "Elements are TAB delimited. Press CTRL-V then TAB to insert from the prompt.\n"
748 "\n"
749 "Type HELP for protocol commands. Type .help for pwmc commands. Press CTRL-D\n"
750 "to quit.\n"
751 "------------------------------------------------------------------------------\n"));
753 #endif
755 static char *
756 parse_arg (const char *src, char *dst, size_t len)
758 char *p = dst;
759 const char *s = src;
760 size_t n = 0;
762 for (; s && *s && *s != ' ' && n < len; s++, n++)
763 *p++ = *s;
765 *p = 0;
766 return dst;
769 static char *
770 parse_opt (char **line, const char *opt, gpg_error_t * rc)
772 static char result[ASSUAN_LINELENGTH] = { 0 }, *r = result;
773 size_t len = 0;
774 char *s = strstr (*line, opt);
776 *rc = 0;
777 result[0] = 0;
778 r = result;
780 if (s)
782 int quote = 0;
783 size_t rlen = strlen (opt);
784 char *p = s + rlen;
785 int lastc = 0;
787 while (*p && *p == ' ')
789 rlen++;
790 p++;
793 for (; *p && len < sizeof (result) - 1; p++, rlen++)
795 if (isspace (*p) && !quote)
796 break;
798 if (*p == '\"' && lastc != '\\')
800 quote = !quote;
801 lastc = *p;
802 continue;
805 *r++ = lastc = *p;
806 len++;
809 *r = 0;
811 if (len >= sizeof (result) - 1)
812 *rc = GPG_ERR_LINE_TOO_LONG;
813 else
815 p = s + rlen;
817 while (*p && *p == ' ')
818 p++;
820 *line = p;
824 return result;
827 static gpg_error_t
828 read_command (const char *line, char **result, size_t * len)
830 int fd;
831 gpg_error_t rc = 0;
832 char filebuf[ASSUAN_LINELENGTH];
833 char *filename = NULL;
834 struct inquire_s *inq = NULL;
835 char *p = (char *) line;
836 const char *prefix = parse_opt (&p, "--prefix", &rc);
838 if (rc)
839 return rc;
841 rc = GPG_ERR_SYNTAX;
843 if (p && *p)
845 while (*p && isspace (*p))
846 p++;
848 filename = parse_arg (p, filebuf, sizeof (filebuf));
849 if (filename && *filename)
851 p += strlen (filename) + 1;
853 while (*p && isspace (*p))
854 p++;
856 if (*p)
857 rc = 0;
861 if (rc)
863 fprintf (stderr,
865 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
866 fprintf (stderr,
868 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\" = \")\n"));
869 return rc;
872 fd = open (filename, O_RDONLY);
873 if (fd == -1)
874 return gpg_error_from_syserror ();
876 rc = set_inquire (fd, prefix && *prefix ? prefix : NULL, &inq);
877 if (rc)
879 close (fd);
880 return rc;
883 inq->header = 1;
884 rc = pwmd_command (pwm, result, len, inquire_cb, inq, p);
885 free_inquire (inq);
886 return rc;
889 static gpg_error_t
890 redir_command (const char *line)
892 const char *p = line;
893 int fd;
894 gpg_error_t rc = GPG_ERR_SYNTAX;
895 char filebuf[ASSUAN_LINELENGTH];
896 char *filename = NULL;
897 struct inquire_s *inq = NULL;
898 char *result = NULL;
899 size_t len = 0;
901 if (p && *p && *++p)
903 filename = parse_arg (p, filebuf, sizeof (filebuf));
904 if (filename && *filename)
906 p += strlen (filename) + 1;
908 while (*p && isspace (*p))
909 p++;
911 if (*p)
912 rc = 0;
916 if (rc)
918 fprintf (stderr, N_("Usage: .redir <filename> <command> [args]\n"));
919 return rc;
922 fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
923 if (fd == -1)
924 return gpg_error_from_syserror ();
926 #ifdef HAVE_LIBREADLINE
927 rc = set_inquire (interactive ? STDIN_FILENO : inquirefd, NULL, &inq);
928 #else
929 rc = set_inquire (inquirefd, NULL, &inq);
930 #endif
931 if (rc)
933 close (fd);
934 return rc;
937 rc = parse_dotcommand (p, &result, &len, inq);
938 if (!rc && result && len--)
939 { // null byte which is always appended
940 if (write (fd, result, len) != len)
941 rc = GPG_ERR_TOO_SHORT;
942 pwmd_free (result);
945 free_inquire (inq);
946 close (fd);
947 return rc;
950 static gpg_error_t
951 help_command (const char *line)
953 fprintf (stderr,
954 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
955 " .redir <filename> <command>\n"
956 " redirect the output of a command to the specified file\n"
957 "\n" " .open <filename>\n"
958 " open the specified filename losing any changes to the current one\n"
959 "\n" " .read [--prefix <string>] <filename> <command> [args]\n"
960 " obtain data from the specified filename for an inquire command\n"
961 "\n" " .set help | <name> [<value>]\n"
962 " set option <name> to <value>\n" "\n" " .help\n"
963 " this help text\n"));
964 return 0;
967 static gpg_error_t
968 open_command (const char *line)
970 struct inquire_s *inq = NULL;
971 const char *filename = line;
972 gpg_error_t rc;
974 while (filename && isspace (*filename))
975 filename++;
977 if (!filename || !*filename)
979 fprintf (stderr, N_("Usage: .open <filename>\n"));
980 return GPG_ERR_SYNTAX;
983 #ifdef HAVE_LIBREADLINE
984 if (interactive || !quiet)
985 #else
986 if (!quiet)
987 #endif
988 fprintf (stderr, N_("Opening data file \"%s\" ...\n"), filename);
990 #ifdef HAVE_LIBREADLINE
991 rc = set_inquire (interactive ? STDIN_FILENO : -1, NULL, &inq);
992 #else
993 rc = set_inquire (-1, NULL, &inq);
994 #endif
995 if (rc)
996 return rc;
998 if (keyfile)
999 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1001 #ifdef HAVE_LIBREADLINE
1002 // For safety. This file may be a different one. Make the user set it
1003 // again if needed.
1004 if (interactive)
1006 pwmd_free (new_keyfile);
1007 new_keyfile = NULL;
1009 #endif
1011 rc = pwmd_open (pwm, filename, inquire_cb, inq);
1012 free_inquire (inq);
1013 return rc;
1016 static gpg_error_t
1017 set_command (const char *line)
1019 gpg_error_t rc = 0;
1020 char name[256] = { 0 };
1021 char value[512] = { 0 };
1022 char *namep;
1023 char *valuep;
1024 const char *p = line;
1026 while (p && *p && isspace (*p))
1027 p++;
1029 namep = parse_arg (p, name, sizeof (name));
1030 if (!namep || !*namep)
1032 fprintf (stderr, N_("Usage: .set help | <name> [<value>]\n"));
1033 return GPG_ERR_SYNTAX;
1036 p += strlen (namep);
1037 while (p && *p && isspace (*p))
1038 p++;
1040 valuep = parse_arg (p, value, sizeof (value));
1042 if (!strcmp (name, "keyfile") || !strcmp (name, "new-keyfile"))
1044 int is_newkeyfile = 1;
1045 int is_pkcs = 1;
1046 char datafile[256];
1048 if (!strcmp (name, "keyfile"))
1049 is_newkeyfile = 0;
1051 if (is_newkeyfile)
1053 pwmd_free (new_keyfile);
1054 new_keyfile = NULL;
1056 else
1058 pwmd_free (keyfile);
1059 keyfile = NULL;
1062 p += strlen (valuep);
1063 while (p && *p && isspace (*p))
1064 p++;
1066 valuep = (char *) p;
1067 if (*valuep)
1069 memcpy (datafile, value, sizeof (datafile));
1070 valuep = parse_arg (p, value, sizeof (value));
1071 rc =
1072 pwmd_command (pwm, NULL, NULL, NULL, NULL, "KEYGRIP %s",
1073 datafile);
1074 if (gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
1076 rc = 0;
1077 is_pkcs = 0;
1079 else if (!rc)
1080 is_pkcs = 1;
1083 if (!rc && *valuep)
1085 if (is_newkeyfile)
1086 new_keyfile = pwmd_strdup (value);
1087 else
1088 keyfile = pwmd_strdup (value);
1090 if (!is_pkcs)
1091 rc = 0;
1092 else
1093 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1094 "AGENT option pinentry-mode=loopback");
1096 if (!rc)
1098 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 1);
1099 rc = pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1102 else if (!local_pin && !no_pinentry)
1104 pwmd_socket_t t;
1106 pwmd_socket_type (pwm, &t);
1107 if (t == PWMD_SOCKET_LOCAL)
1109 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 0);
1110 rc = pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
1114 else if (!strcmp (name, "help"))
1116 fprintf (stderr,
1118 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1119 "delimited. When no value is specified the option is unset.\n\n"
1120 "keyfile <datafile> [<filename>]\n"
1121 " set or unset the keyfile to be used when a passphrase is required\n"
1122 "\n" "new-keyfile <datafile> [<filename>]\n"
1123 " set or unset the keyfile to be used when a new passphrase is required\n"));
1125 else
1126 rc = GPG_ERR_UNKNOWN_OPTION;
1128 return rc;
1131 static gpg_error_t
1132 parse_dotcommand (const char *line, char **result,
1133 size_t * len, struct inquire_s *inq)
1135 const char *p = line;
1136 gpg_error_t rc = 0;
1138 if (!strncmp (p, ".read", 5))
1139 rc = read_command (p + 5, result, len);
1140 else if (!strncmp (p, ".redir", 6))
1141 rc = redir_command (p + 6);
1142 else if (!strncmp (p, ".help", 5))
1143 rc = help_command (p + 5);
1144 else if (!strncmp (p, ".open", 5))
1145 rc = open_command (p + 5);
1146 else if (!strncmp (p, ".set", 4))
1147 rc = set_command (p + 4);
1148 else
1149 rc = pwmd_command (pwm, result, len, inquire_cb, inq, line);
1151 return FINISH (rc);
1154 #ifdef HAVE_LIBREADLINE
1155 static gpg_error_t
1156 do_interactive ()
1158 gpg_error_t rc;
1159 struct inquire_s *inq = NULL;
1161 rl_initialize ();
1162 rc = process_cmd ();
1163 if (rc)
1164 return rc;
1166 rc = set_inquire (STDIN_FILENO, NULL, &inq);
1167 if (rc)
1168 return rc;
1170 fprintf (stderr,
1171 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1172 print_help ();
1173 rl_event_hook = &interactive_hook;
1174 rl_set_keyboard_input_timeout (100000);
1176 for (;;)
1178 char *line;
1179 char *result = NULL;
1180 size_t len;
1182 rc = 0;
1183 line = readline ("pwm> ");
1184 if (interactive_error)
1186 rc = interactive_error;
1187 break;
1190 if (!line)
1192 rc = finalize ();
1193 if (!rc)
1194 break;
1196 if (gpg_err_code (rc) != GPG_ERR_CANCELED &&
1197 gpg_err_code (rc) != GPG_ERR_EOF)
1198 fprintf (stderr, "ERR %i: %s\n", rc, gpg_strerror (rc));
1200 continue;
1202 else if (!*line)
1204 free (line);
1205 continue;
1208 #ifdef HAVE_READLINE_HISTORY
1209 add_history (line);
1210 #endif
1211 inq->header = 0;
1212 rc = parse_dotcommand (line, &result, &len, inq);
1213 free (line);
1214 if (rc)
1216 char *tmp = NULL;
1218 if (gpg_err_code (rc) == GPG_ERR_BAD_DATA)
1219 (void) pwmd_command (pwm, &tmp, NULL, NULL, NULL,
1220 "GETINFO last_error");
1222 show_error (rc, tmp);
1223 pwmd_free (tmp);
1225 else if (result && len)
1226 printf ("%s%s", result, result[len - 1] != '\n' ? "\n" : "");
1228 pwmd_free (result);
1231 free_inquire (inq);
1232 return rc;
1234 #endif
1236 static char *
1237 itoa (long long int n)
1239 static char buf[64];
1241 snprintf (buf, sizeof (buf), "%llu", n);
1242 return buf;
1245 static gpg_error_t
1246 finalize ()
1248 gpg_error_t rc = 0;
1249 #ifdef HAVE_LIBREADLINE
1250 int quit = 0;
1252 if (!force_save && interactive)
1254 char *p, buf[16];
1255 int finished = 0;
1257 fprintf (stderr, "\n");
1261 fprintf (stderr,
1263 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1264 p = fgets (buf, sizeof (buf), stdin);
1266 if (feof (stdin))
1268 clearerr (stdin);
1269 return GPG_ERR_EOF;
1272 switch (*p)
1274 case 'h':
1275 print_help ();
1276 break;
1277 case 'c':
1278 return GPG_ERR_CANCELED;
1279 case 'Q':
1280 return 0;
1281 case 'f':
1282 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1283 "CLEARCACHE %s", filename);
1284 if (rc)
1285 return rc;
1287 interactive_hook ();
1288 break;
1289 case 'S':
1290 quit = 1;
1291 case 's':
1292 save = 1;
1293 finished = 1;
1294 break;
1295 default:
1296 break;
1299 while (!finished);
1301 #endif
1303 if (save && !filename)
1305 fprintf (stderr,
1307 ("No filename was specified on the command line. Aborting.\n"));
1308 return GPG_ERR_CANCELED;
1311 if (save && filename)
1313 char *args =
1314 pwmd_strdup_printf ("%s%s %s%s %s %s%s %s%s --s2k-count=%lu",
1315 keygrip ? "--keygrip=" : "",
1316 keygrip ? keygrip : "",
1317 sign_keygrip ? "--sign-keygrip=" : "",
1318 sign_keygrip ? sign_keygrip : "",
1319 no_passphrase ? "--no-passphrase" : "",
1320 cipher ? "--cipher=" : "", cipher ? cipher : "",
1321 iterations_arg ? "--cipher-iterations=" : "",
1322 iterations_arg ? itoa (iterations) : "",
1323 s2k_count);
1325 #ifdef HAVE_LIBREADLINE
1326 if (!quiet || interactive)
1328 #else
1329 if (!quiet)
1331 #endif
1332 fprintf (stderr, "\n");
1333 fprintf (stderr, N_("Saving changes ...\n"));
1336 rc = pwmd_save (pwm, args, inquire_cb, NULL);
1337 pwmd_free (args);
1339 if (!rc)
1340 no_passphrase = 0; // reset to avoid usage error on the next SAVE
1343 #ifdef HAVE_LIBREADLINE
1344 if (interactive)
1345 return rc ? rc : quit ? 0 : GPG_ERR_CANCELED;
1346 #endif
1348 return rc;
1352 main (int argc, char *argv[])
1354 int connected = 0;
1355 gpg_error_t rc;
1356 int opt;
1357 char command[ASSUAN_LINELENGTH], *p = NULL;
1358 char *result = NULL;
1359 size_t len;
1360 char *pinentry_path = NULL;
1361 char *display = NULL, *tty = NULL, *ttytype = NULL;
1362 char *lcctype = NULL, *lcmessages = NULL;
1363 int outfd = STDOUT_FILENO;
1364 FILE *outfp = stdout;
1365 FILE *inquirefp = stdin;
1366 int show_status = 1;
1367 char *clientname = "pwmc";
1368 char *inquire = NULL;
1369 char *inquire_line = NULL;
1370 int timeout = 0;
1371 #ifdef WITH_SSH
1372 int use_ssh_agent = 1;
1373 char *knownhosts = NULL;
1374 char *identity = NULL;
1375 #endif
1376 #ifdef WITH_GNUTLS
1377 char *cacert = NULL;
1378 char *clientcert = NULL;
1379 char *clientkey = NULL;
1380 char *prio = NULL;
1381 int tls_verify = 0;
1382 char *tls_fingerprint = NULL;
1383 #endif
1384 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1385 pwmd_socket_t socktype;
1386 long socket_timeout = 0;
1387 #endif
1388 int lock_on_open = 1;
1389 long lock_timeout = 0;
1390 char *url = NULL;
1391 /* The order is important. */
1392 enum
1394 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1395 OPT_SOCKET_TIMEOUT,
1396 #endif
1397 #ifdef WITH_SSH
1398 OPT_USE_SSH_AGENT, OPT_IDENTITY, OPT_KNOWNHOSTS,
1399 #endif
1400 #ifdef WITH_GNUTLS
1401 OPT_CACERT, OPT_CLIENTCERT, OPT_CLIENTKEY, OPT_PRIORITY, OPT_VERIFY,
1402 OPT_SERVER_FP,
1403 #endif
1404 OPT_URL, OPT_LOCAL, OPT_FORCE_SAVE, OPT_TTYNAME, OPT_TTYTYPE,
1405 OPT_DISPLAY, OPT_LC_CTYPE, OPT_LC_MESSAGES, OPT_TIMEOUT, OPT_TRIES,
1406 OPT_PINENTRY, OPT_KEYFILE, OPT_NEW_KEYFILE, OPT_NOLOCK,
1407 OPT_LOCK_TIMEOUT, OPT_SAVE, OPT_OUTPUT_FD, OPT_INQUIRE,
1408 OPT_INQUIRE_FD, OPT_INQUIRE_FILE, OPT_INQUIRE_LINE, OPT_NO_STATUS,
1409 OPT_NAME, OPT_VERSION, OPT_HELP, OPT_KEYGRIP, OPT_SIGN_KEYGRIP,
1410 OPT_NOPASSPHRASE, OPT_CIPHER, OPT_KEYPARAMS, OPT_NO_PINENTRY,
1411 OPT_S2K_COUNT, OPT_ITERATIONS, OPT_QUIET,
1412 #ifdef HAVE_LIBREADLINE
1413 OPT_INTERACTIVE,
1414 #endif
1416 const struct option long_opts[] = {
1417 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1418 {"socket-timeout", 1, 0, 0},
1419 #endif
1421 #ifdef WITH_SSH
1422 {"no-ssh-agent", 0, 0, 0},
1423 {"identity", 1, 0, 'i'},
1424 {"knownhosts", 1, 0, 'k'},
1425 #endif
1426 #ifdef WITH_GNUTLS
1427 {"ca-cert", 1, 0, 0},
1428 {"client-cert", 1, 0, 0},
1429 {"client-key", 1, 0, 0},
1430 {"tls-priority", 1, 0, 0},
1431 {"tls-verify", 0, 0, 0},
1432 {"tls-fingerprint", 1, 0, 0},
1433 #endif
1434 {"url", 1, 0, 0},
1435 {"local-pinentry", 0, 0},
1436 {"force-save", 0, 0},
1437 {"ttyname", 1, 0, 'y'},
1438 {"ttytype", 1, 0, 't'},
1439 {"display", 1, 0, 'd'},
1440 {"lc-ctype", 1, 0, 0},
1441 {"lc-messages", 1, 0, 0},
1442 {"timeout", 1, 0, 0},
1443 {"tries", 1, 0, 0},
1444 {"pinentry", 1, 0, 0},
1445 {"key-file", 1, 0, 0},
1446 {"new-key-file", 1, 0, 0},
1447 {"no-lock", 0, 0, 0},
1448 {"lock-timeout", 1, 0, 0},
1449 {"save", 0, 0, 'S'},
1450 {"output-fd", 1, 0, 0},
1451 {"inquire", 1, 0, 0},
1452 {"inquire-fd", 1, 0, 0},
1453 {"inquire-file", 1, 0, 0},
1454 {"inquire-line", 1, 0, 'L'},
1455 {"no-status", 0, 0, 0},
1456 {"name", 1, 0, 'n'},
1457 {"version", 0, 0, 0},
1458 {"help", 0, 0, 0},
1459 {"keygrip", 1, 0, 0},
1460 {"sign-keygrip", 1, 0, 0},
1461 {"no-passphrase", 0, 0, 0},
1462 {"cipher", 1, 0, 0},
1463 {"key-params", 1, 0, 0},
1464 {"no-pinentry", 0, 0, 0},
1465 {"s2k-count", 1, 0, 0},
1466 {"cipher-iterations", 1, 0, 0},
1467 {"quiet", 0, 0, 0},
1468 #ifdef HAVE_LIBREADLINE
1469 {"interactive", 0, 0},
1470 #endif
1471 {0, 0, 0, 0}
1473 #ifdef WITH_SSH
1474 const char *optstring = "L:y:t:d:P:I:Sn:i:k:";
1475 #else
1476 const char *optstring = "L:y:t:d:P:I:Sn:";
1477 #endif
1478 int opt_index = 0;
1480 #ifdef ENABLE_NLS
1481 setlocale (LC_ALL, "");
1482 bindtextdomain ("libpwmd", LOCALEDIR);
1483 #endif
1485 #ifdef HAVE_LIBREADLINE
1486 if (!strcmp (basename (argv[0]), "pwmsh"))
1487 interactive = 1;
1488 #endif
1490 tries = DEFAULT_PIN_TRIES;
1491 inquirefd = STDIN_FILENO;
1493 while ((opt =
1494 getopt_long (argc, argv, optstring, long_opts, &opt_index)) != -1)
1496 switch (opt)
1498 /* Handle long options without a short option part. */
1499 case 0:
1500 switch (opt_index)
1502 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1503 case OPT_SOCKET_TIMEOUT:
1504 socket_timeout = strtol (optarg, &p, 10);
1505 break;
1506 #endif
1507 #ifdef WITH_SSH
1508 case OPT_USE_SSH_AGENT:
1509 use_ssh_agent = 0;
1510 break;
1511 #endif
1512 #ifdef WITH_GNUTLS
1513 case OPT_CACERT:
1514 cacert = optarg;
1515 break;
1516 case OPT_CLIENTCERT:
1517 clientcert = optarg;
1518 break;
1519 case OPT_CLIENTKEY:
1520 clientkey = optarg;
1521 break;
1522 case OPT_PRIORITY:
1523 prio = optarg;
1524 break;
1525 case OPT_VERIFY:
1526 tls_verify = 1;
1527 break;
1528 case OPT_SERVER_FP:
1529 tls_fingerprint = optarg;
1530 break;
1531 #endif
1532 case OPT_KEYPARAMS:
1533 keyparams = optarg;
1534 break;
1535 case OPT_KEYFILE:
1536 keyfile = pwmd_strdup (optarg);
1537 break;
1538 case OPT_NEW_KEYFILE:
1539 new_keyfile = pwmd_strdup (optarg);
1540 break;
1541 case OPT_NOLOCK:
1542 lock_on_open = 0;
1543 break;
1544 case OPT_LOCK_TIMEOUT:
1545 lock_timeout = strtol (optarg, &p, 10);
1546 break;
1547 case OPT_URL:
1548 url = optarg;
1549 break;
1550 case OPT_LOCAL:
1551 local_pin = 1;
1552 break;
1553 case OPT_FORCE_SAVE:
1554 save = force_save = 1;
1555 break;
1556 case OPT_LC_CTYPE:
1557 lcctype = pwmd_strdup (optarg);
1558 break;
1559 case OPT_LC_MESSAGES:
1560 lcmessages = pwmd_strdup (optarg);
1561 break;
1562 case OPT_TIMEOUT:
1563 timeout = strtol (optarg, &p, 10);
1564 break;
1565 case OPT_TRIES:
1566 tries = strtol (optarg, &p, 10);
1567 break;
1568 case OPT_INQUIRE:
1569 inquire = optarg;
1570 break;
1571 case OPT_INQUIRE_FD:
1572 inquirefd = strtol (optarg, &p, 10);
1573 if (!p)
1575 inquirefp = fdopen (inquirefd, "r");
1576 if (!inquirefp)
1578 pwmd_free (password);
1579 err (EXIT_FAILURE, "%i", inquirefd);
1582 break;
1583 case OPT_INQUIRE_FILE:
1584 inquirefd = open (optarg, O_RDONLY);
1585 if (inquirefd == -1)
1587 pwmd_free (password);
1588 err (EXIT_FAILURE, "%s", optarg);
1590 inquirefp = fdopen (inquirefd, "r");
1591 break;
1592 case OPT_OUTPUT_FD:
1593 outfd = strtol (optarg, &p, 10);
1594 if (!p)
1596 outfp = fdopen (outfd, "w");
1597 if (!outfp)
1599 pwmd_free (password);
1600 err (EXIT_FAILURE, "%i", outfd);
1603 break;
1604 case OPT_NO_STATUS:
1605 show_status = 0;
1606 break;
1607 case OPT_VERSION:
1608 pwmd_free (password);
1609 printf ("%s (pwmc)\n\n"
1610 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013\n"
1611 "%s\n"
1612 "Released under the terms of the GPL v2. Use at your own risk.\n\n"
1613 "Compile-time features:\n"
1614 #ifdef HAVE_LIBREADLINE
1615 "+INTERACTIVE "
1616 #else
1617 "-INTERACTIVE "
1618 #endif
1619 #ifdef WITH_SSH
1620 "+SSH "
1621 #else
1622 "-SSH "
1623 #endif
1624 #ifdef WITH_GNUTLS
1625 "+GNUTLS "
1626 #else
1627 "-GNUTLS "
1628 #endif
1629 #ifdef WITH_PINENTRY
1630 "+PINENTRY "
1631 #else
1632 "-PINENTRY "
1633 #endif
1634 #ifdef WITH_QUALITY
1635 "+CRACK "
1636 #else
1637 "-CRACK "
1638 #endif
1639 #ifdef MEM_DEBUG
1640 "+MEM_DEBUG "
1641 #else
1642 "-MEM_DEBUG "
1643 #endif
1644 "\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
1645 exit (EXIT_SUCCESS);
1646 case OPT_PINENTRY:
1647 pinentry_path = optarg;
1648 break;
1649 case OPT_HELP:
1650 usage (argv[0], EXIT_SUCCESS);
1651 case OPT_KEYGRIP:
1652 keygrip = optarg;
1653 break;
1654 case OPT_SIGN_KEYGRIP:
1655 sign_keygrip = optarg;
1656 break;
1657 case OPT_S2K_COUNT:
1658 s2k_count = strtoul (optarg, &p, 10);
1659 break;
1660 case OPT_ITERATIONS:
1661 iterations = strtoull (optarg, &p, 10);
1662 iterations_arg = 1;
1663 break;
1664 case OPT_QUIET:
1665 quiet = 1;
1666 show_status = 0;
1667 break;
1668 case OPT_NOPASSPHRASE:
1669 no_passphrase = 1;
1670 break;
1671 case OPT_CIPHER:
1672 cipher = optarg;
1673 break;
1674 case OPT_NO_PINENTRY:
1675 no_pinentry = 1;
1676 break;
1677 #ifdef HAVE_LIBREADLINE
1678 case OPT_INTERACTIVE:
1679 interactive = 1;
1680 break;
1681 #endif
1682 default:
1683 usage (argv[0], EXIT_FAILURE);
1686 if (p && *p)
1688 fprintf (stderr, N_("%s: invalid argument for option '--%s'\n"),
1689 argv[0], long_opts[opt_index].name);
1690 usage (argv[0], EXIT_FAILURE);
1693 break;
1694 #ifdef WITH_SSH
1695 case 'i':
1696 identity = optarg;
1697 break;
1698 case 'k':
1699 knownhosts = optarg;
1700 break;
1701 #endif
1702 case 'L':
1703 inquire_line = optarg;
1704 break;
1705 case 'y':
1706 tty = optarg;
1707 break;
1708 case 't':
1709 ttytype = optarg;
1710 break;
1711 case 'd':
1712 display = optarg;
1713 break;
1714 case 'S':
1715 save = 1;
1716 break;
1717 case 'n':
1718 clientname = optarg;
1719 break;
1720 default:
1721 pwmd_free (password);
1722 usage (argv[0], EXIT_FAILURE);
1726 #ifdef HAVE_LIBREADLINE
1727 if (interactive && !isatty (STDIN_FILENO))
1729 pwmd_free (password);
1730 usage (argv[0], EXIT_FAILURE);
1732 else if (isatty (STDIN_FILENO) && !inquire && !inquire_line)
1733 interactive = 1;
1734 #endif
1736 filename = argv[optind];
1737 #ifdef WITH_GNUTLS
1738 gnutls_global_set_mem_functions (pwmd_malloc, pwmd_malloc, NULL,
1739 pwmd_realloc, pwmd_free);
1740 #endif
1741 pwmd_init ();
1742 rc = pwmd_new (clientname, &pwm);
1743 if (rc)
1744 goto done;
1746 pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TRIES, tries);
1747 if (!quiet)
1748 fprintf (stderr, N_("Connecting ...\n"));
1750 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1751 socktype = is_remote_url (url);
1752 if (socktype != PWMD_SOCKET_LOCAL)
1754 local_pin = 1;
1755 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1756 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, socket_timeout);
1757 if (rc)
1758 goto done;
1759 #endif
1761 if (socktype == PWMD_SOCKET_SSH)
1763 #ifdef WITH_SSH
1764 rc = pwmd_setopt (pwm, PWMD_OPTION_KNOWNHOST_CB, knownhost_cb);
1765 if (rc)
1766 goto done;
1768 rc = pwmd_setopt (pwm, PWMD_OPTION_KNOWNHOST_DATA, clientname);
1769 if (rc)
1770 goto done;
1772 if (!getenv ("SSH_AUTH_SOCK") || identity)
1773 use_ssh_agent = 0;
1775 rc = pwmd_setopt (pwm, PWMD_OPTION_SSH_AGENT, use_ssh_agent);
1776 if (rc)
1777 goto done;
1779 rc = pwmd_connect (pwm, url, identity, knownhosts);
1780 #endif
1782 #ifdef WITH_GNUTLS
1783 else
1785 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_VERIFY, tls_verify);
1786 if (rc)
1787 goto done;
1789 rc = pwmd_connect (pwm, url, clientcert, clientkey, cacert, prio,
1790 tls_fingerprint);
1792 #endif
1794 else
1795 rc = pwmd_connect (pwm, url);
1796 #else
1797 rc = pwmd_connect (pwm, url);
1798 #endif
1799 if (rc)
1800 goto done;
1802 if (!quiet)
1803 fprintf (stderr, N_("Connected.\n"));
1805 connected = 1;
1806 if (lock_timeout)
1808 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1809 "OPTION LOCK-TIMEOUT=%li", lock_timeout);
1810 if (rc)
1811 goto done;
1814 if (lock_on_open)
1816 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCK_ON_OPEN, 1);
1817 if (rc)
1818 goto done;
1821 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DESC, NULL);
1822 if (rc)
1823 goto done;
1825 if (timeout > 0)
1827 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TIMEOUT, timeout);
1828 if (rc)
1829 goto done;
1832 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, no_pinentry);
1833 if (rc)
1834 goto done;
1836 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCAL_PINENTRY,
1837 (local_pin || keyfile || new_keyfile));
1838 if (rc)
1839 goto done;
1841 if (pinentry_path)
1843 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_PATH, pinentry_path);
1844 if (rc)
1845 goto done;
1848 if (display)
1850 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, display);
1851 if (rc)
1852 goto done;
1855 if (tty)
1857 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, tty);
1858 if (rc)
1859 goto done;
1862 if (ttytype)
1864 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, ttytype);
1865 if (rc)
1866 goto done;
1869 if (lcctype)
1871 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_CTYPE, lcctype);
1872 if (rc)
1873 goto done;
1876 if (lcmessages)
1878 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_MESSAGES, lcmessages);
1879 if (rc)
1880 goto done;
1883 if (show_status)
1885 rc = pwmd_setopt (pwm, PWMD_OPTION_STATUS_CB, status_msg_cb);
1886 if (rc)
1887 goto done;
1890 if (filename)
1892 rc = open_command (filename);
1893 if (rc)
1894 goto done;
1897 #ifdef HAVE_LIBREADLINE
1898 if (interactive)
1900 if (!force_save)
1901 save = 0;
1903 rc = do_interactive ();
1904 result = NULL;
1905 goto do_exit;
1907 #endif
1909 if (inquire)
1911 struct inquire_s *inq = NULL;
1913 rc = set_inquire (inquirefd, inquire_line, &inq);
1914 if (!rc)
1915 rc = pwmd_command (pwm, &result, &len, inquire_cb, inq, inquire);
1917 free_inquire (inq);
1918 goto done;
1921 fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
1922 ssize_t n;
1924 for (;;)
1926 rc = process_cmd ();
1928 if (rc)
1929 goto done;
1931 n = read (STDIN_FILENO, command, sizeof (command));
1932 if (n == -1)
1934 if (errno == EAGAIN)
1936 usleep (100000);
1937 continue;
1940 rc = gpg_error_from_errno (errno);
1941 goto done;
1943 else if (!n)
1944 goto done;
1946 p = command;
1947 command[n] = 0;
1948 break;
1951 if (!p || !*p || !strcasecmp (p, "BYE"))
1952 goto done;
1955 struct inquire_s *inq = NULL;
1956 rc = set_inquire (inquirefd, inquire_line, &inq);
1957 if (!rc)
1959 rc = parse_dotcommand (command, &result, &len, inq);
1960 free_inquire (inq);
1963 if (rc)
1964 goto done;
1966 done:
1967 if (result)
1969 fwrite (result, 1, result[len - 1] == 0 ? len - 1 : len, outfp);
1970 fflush (outfp);
1971 pwmd_free (result);
1974 pwmd_free (password);
1975 password = result = NULL;
1976 if (!rc)
1977 rc = finalize ();
1978 else if (gpg_err_code (rc) == GPG_ERR_BAD_DATA)
1979 (void) pwmd_command (pwm, &result, NULL, NULL, NULL,
1980 "GETINFO last_error");
1982 #ifdef HAVE_LIBREADLINE
1983 do_exit:
1984 #endif
1985 memset (command, 0, sizeof (command));
1986 pwmd_close (pwm);
1987 pwmd_free (keyfile);
1988 pwmd_free (new_keyfile);
1989 pwmd_deinit ();
1991 if (rc && !quiet)
1992 show_error (rc, result);
1994 pwmd_free (result);
1995 if (connected && !quiet)
1996 fprintf (stderr, N_("Connection closed.\n"));
1998 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);