pwmc: add the '.passwd' command.
[libpwmd.git] / src / pwmc.c
blobc2a79c25cee48f377011570c6d8aa87726aa88f5
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 *keyfile;
96 static char *new_keyfile;
97 static unsigned long s2k_count;
98 static uint64_t iterations;
99 static int iterations_arg;
100 static int tries;
101 static int local_pin;
102 static int inquirefd;
103 static int quiet;
104 static int no_gpg_agent;
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_("Usage: pwmc [options] [file]\n"
137 " --url <string>\n"
138 " a url string to connect to (~/.pwmd/socket, see below)\n"
139 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
140 " --connect-timeout <seconds>\n"
141 " seconds before connecting to a remote host fails (0=disabled, 120)\n"
142 " --socket-timeout <seconds>\n"
143 " seconds before a remote command fails (0=disabled, 300)\n"
144 #endif
145 #ifdef WITH_GNUTLS
146 " --ca-cert <filename>\n"
147 " certificate authority (CA) used to sign the server cert\n"
148 " --client-cert <filename>\n"
149 " client certificate to use for authentication\n"
150 " --client-key <filename>\n"
151 " key file used to protect the client certificate\n"
152 " --tls-priority <string>\n"
153 " compression, cipher and hash algorithm string (SECURE256)\n"
154 " --tls-verify\n"
155 " verify the hostname against the server certificate\n"
156 " --tls-fingerprint <string>\n"
157 " a SHA-1 hash of the server fingerprint to verify against\n"
158 #endif
159 #ifdef WITH_SSH
160 " --no-ssh-agent\n"
161 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
162 " --identity, -i <filename>\n"
163 " the ssh identity file to use for authentication\n"
164 " --knownhosts, -k <filename>\n"
165 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
166 #endif
167 " --no-lock\n"
168 " do not lock the data file upon opening it\n"
169 " --lock-timeout <N>\n"
170 " time in tenths of a second to wait for a locked data file (50)\n"
171 " --name, -n <string>\n"
172 " set the client name\n"
173 " --pinentry <path>\n"
174 " the full path to the pinentry binary (server default)\n"
175 " --local-pinentry\n"
176 " force using a local pinentry\n"
177 " --no-pinentry\n"
178 " disable pinentry both remotely and locally\n"
179 " --ttyname, -y <path>\n"
180 " tty that pinentry will use\n"
181 " --ttytype, -t <string>\n"
182 " pinentry terminal type (default is $TERM)\n"
183 " --display, -d\n"
184 " pinentry display (default is $DISPLAY)\n"
185 " --lc-ctype <string>\n"
186 " locale setting for pinentry\n"
187 " --lc-messages <string>\n"
188 " locale setting for pinentry\n"
189 " --tries <N>\n"
190 " number of pinentry tries before failing (3)\n"
191 " --timeout <seconds>\n"
192 " pinentry timeout\n"
193 " --inquire <COMMAND>\n"
194 " the specified command (with any options) uses a server inquire while\n"
195 " command data is read via the inquire file descriptor (stdin)\n"
196 " --inquire-line, -L <STRING>\n"
197 " the initial line to send (i.e., element path) before the inquire data\n"
198 " --inquire-fd <FD>\n"
199 " read inquire data from the specified file descriptor (stdin)\n"
200 " --inquire-file <filename>\n"
201 " read inquire data from the specified filename\n"
202 " --output-fd <FD>\n"
203 " redirect command output to the specified file descriptor\n"
204 " --save, -S\n"
205 " send the SAVE command before exiting\n"
206 " --force-save\n"
207 " like --save but always ask for a passphrase\n"
208 " --no-passphrase\n"
209 " do not require a passphrase when saving a new file\n"
210 " --no-gpg-agent\n"
211 " disable use of gpg-agent when saving to a new file\n"
212 " --key-file <filename>\n"
213 " obtain the passphrase from the specified filename\n"
214 " --new-key-file <filename>\n"
215 " obtain the passphrase to save with from the specified filename\n"
216 " --cipher <string>\n"
217 " the cipher to use when saving (see pwmd(1))\n"
218 " --cipher-iterations <N>\n"
219 " the number of times to encrypt the XML data (N+1)\n"
220 " --key-params <string>\n"
221 " the key parameters to use when saving a new file (pwmd default)\n"
222 " --keygrip <string>\n"
223 " the hex string of the keygrip to save to\n"
224 " --sign-keygrip <string>\n"
225 " the hex string of the keygrip to sign with\n"
226 " --s2k-count <N>\n"
227 " the number of times to hash the passphrase for a new file\n"
228 " --no-status\n"
229 " disable showing of status messages from the server\n"
230 " --quiet\n"
231 " disable showing of extra messages (implies --no-status)\n"
232 #ifdef HAVE_LIBREADLINE
233 " --interactive\n"
234 " use a shell like interface to pwmd (allows more than one command)\n"
235 #endif
236 " --version\n"
237 " --help\n"));
238 fprintf (status == EXIT_FAILURE ? stderr : stdout,
239 N_("\n"
240 "An optional url may be in the form of:\n"
241 " --url /path/to/socket\n"
242 " --url file://[path/to/socket]\n"
243 #ifdef WITH_SSH
244 " or\n"
245 " --url ssh[46]://[username@]hostname[:port]\n"
246 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
247 #endif
248 #ifdef WITH_GNUTLS
249 " or\n"
250 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
251 " --client-key filename\n"
252 #endif
253 #ifdef HAVE_LIBREADLINE
254 "\n"
255 "Interactive mode is used when input is from a terminal.\n"
256 #endif
258 exit (status);
261 static gpg_error_t
262 inquire_cb (void *user, const char *keyword, gpg_error_t rc,
263 char **data, size_t * size)
265 struct inquire_s *inq = user;
266 int is_password = 0;
267 int is_newpassword = 0;
269 *data = NULL;
270 *size = 0;
272 if (rc)
273 return rc;
275 if (!strcmp (keyword, "PASSPHRASE"))
276 is_password = 1;
277 else if (!strcmp (keyword, "NEW_PASSPHRASE"))
278 is_newpassword = 1;
279 #ifdef HAVE_LIBREADLINE
280 else if (!strcmp (keyword, "KEYPARAM") && !interactive)
282 #else
283 else if (!strcmp (keyword, "KEYPARAM"))
285 #endif
286 if (!keyparams || !*keyparams)
287 return gpg_error (GPG_ERR_INV_PARAMETER);
289 *data = keyparams;
290 *size = strlen (keyparams);
291 return gpg_error (GPG_ERR_EOF);
294 if ((is_newpassword && new_keyfile) || (is_password && keyfile))
296 int fd = open (is_password ? keyfile : new_keyfile, O_RDONLY);
298 if (fd == -1)
300 fprintf (stderr, "%s: %s\n", is_newpassword ? new_keyfile : keyfile,
301 strerror (errno));
302 return gpg_error_from_syserror ();
305 rc = set_inquire (fd, NULL, &inq);
306 if (rc)
308 close (fd);
309 return rc;
312 if (!quiet)
313 fprintf (stderr, N_("Using keyfile '%s' as %s.\n"),
314 is_newpassword ? new_keyfile : keyfile, keyword);
316 if (!new_keyfile || is_newpassword)
318 pwmd_socket_t t;
320 pwmd_socket_type (pwm, &t);
321 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
322 if (!no_pinentry && t == PWMD_SOCKET_LOCAL)
323 pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 0);
326 else if ((is_password && !keyfile) || (is_newpassword && !new_keyfile))
328 char *tmp;
330 rc = pwmd_password (pwm, keyword, &tmp, &inq->len);
331 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
332 return rc;
334 pwmd_free (inq->line);
335 inq->line = tmp;
336 *data = inq->line;
337 *size = inq->len;
338 return gpg_error (GPG_ERR_EOF);
340 #ifdef HAVE_LIBREADLINE
341 else if (!inq->header && interactive)
343 fprintf (stderr,
345 ("Press CTRL-D to send the current line. Press twice to end. %s:\n"),
346 keyword);
347 inq->header = 1;
349 #endif
351 /* The first part of the command data. */
352 if (inq->len)
354 *data = inq->line;
355 *size = inq->len;
356 inq->len = 0;
357 return inq->fd == -1 ? gpg_error (GPG_ERR_EOF) : 0;
360 *size = read (inq->fd, inq->line, ASSUAN_LINELENGTH);
361 if (*size == -1)
363 *size = 0;
364 return gpg_error (gpg_error_from_syserror ());
366 else if (*size)
367 *data = inq->line;
368 else if (inq->fd != STDIN_FILENO && (is_newpassword || is_password))
370 *inq->line = 0;
371 inq->size = 1;
372 *data = inq->line;
373 *size = 1;
376 if (((is_newpassword && new_keyfile) || (is_password && keyfile))
377 && *size == inq->size)
378 return gpg_error (GPG_ERR_EOF);
380 return *size ? 0 : gpg_error (GPG_ERR_EOF);
383 static int
384 status_msg_cb (void *data, const char *line)
386 char *p = strchr (line, ' ');
388 if (!strcmp (line, "KEEPALIVE"))
389 return 0;
391 if (*line != '#' && p && strchr (p, ' ') && *++p)
393 char *p1 = strchr (p, ' ');
394 int a = strtol (p, NULL, 10);
396 if (isdigit (*p) && p1)
398 int b = strtol (p1, NULL, 10);
399 char l[64] = { 0 };
400 int t = a && b ? a * 100 / b : 0;
402 strncpy (l, line, strlen (line) - strlen (p) - 1);
403 fprintf (stderr, "\r%s %i/%i %i%%%s", l, a, b, t,
404 a == b ? "\n" : "");
405 fflush (stderr);
406 return 0;
410 fprintf (stderr, "%s\n", line);
411 fflush (stderr);
412 #ifdef HAVE_LIBREADLINE
413 rl_on_new_line ();
414 #endif
415 return 0;
418 static gpg_error_t
419 process_cmd ()
421 return pwmd_process (pwm);
424 #ifdef WITH_SSH
425 static gpg_error_t
426 get_password (char **result, pwmd_pinentry_t w, int echo)
428 char buf[LINE_MAX] = { 0 }, *p;
429 struct termios told, tnew;
430 char *key = NULL;
432 *result = NULL;
434 if (!isatty (STDIN_FILENO))
436 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
437 return GPG_ERR_ENOTTY;
440 if (!echo)
442 if (tcgetattr (STDIN_FILENO, &told) == -1)
443 return gpg_error_from_syserror ();
445 memcpy (&tnew, &told, sizeof (struct termios));
446 tnew.c_lflag &= ~(ECHO);
447 tnew.c_lflag |= ICANON | ECHONL;
449 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
451 int n = errno;
453 tcsetattr (STDIN_FILENO, TCSANOW, &told);
454 return gpg_error_from_errno (n);
458 switch (w)
460 case PWMD_PINENTRY_OPEN:
461 fprintf (stderr, N_("Password for %s: "), filename);
462 break;
463 case PWMD_PINENTRY_OPEN_FAILED:
464 fprintf (stderr, N_("Invalid password. Password for %s: "), filename);
465 break;
466 case PWMD_PINENTRY_SAVE:
467 fprintf (stderr, N_("New password for %s: "), filename);
468 break;
469 case PWMD_PINENTRY_SAVE_CONFIRM:
470 fprintf (stderr, N_("Confirm password: "));
471 break;
472 default:
473 break;
476 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
478 tcsetattr (STDIN_FILENO, TCSANOW, &told);
479 return 0;
482 if (!echo)
483 tcsetattr (STDIN_FILENO, TCSANOW, &told);
485 if (feof (stdin))
487 clearerr (stdin);
488 return GPG_ERR_CANCELED;
491 p[strlen (p) - 1] = 0;
493 if (buf[0])
495 key = pwmd_strdup_printf ("%s", p);
496 memset (&buf, 0, sizeof (buf));
498 if (!key)
499 return GPG_ERR_ENOMEM;
502 *result = key;
503 return 0;
506 static gpg_error_t
507 knownhost_cb (void *data, const char *host, const char *key, size_t len)
509 gpg_error_t rc;
510 char *buf =
511 pwmd_strdup_printf (N_
512 ("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?"),
513 (char *) data, host, host);
515 if (no_pinentry && !isatty (STDIN_FILENO))
517 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
518 pwmd_free (buf);
519 return GPG_ERR_ENOTTY;
521 else if (no_pinentry)
523 for (char *p = buf, len = 0; *p; p++, len++)
525 if (*p == '\n')
526 len = 0;
528 if (len == 78)
530 char *t = p;
532 while (!isspace (*(--p)));
533 *p = '\n';
534 p = t;
535 len = 0;
539 fprintf (stderr, "%s\n\n", buf);
540 pwmd_free (buf);
544 char *result;
546 fprintf (stderr, N_("Trust this connection [y/N]: "));
547 fflush (stderr);
548 rc = get_password (&result, PWMD_PINENTRY_CONFIRM, 1);
550 if (rc)
551 return rc;
553 if (!result || !*result || *result == 'n' || *result == 'N')
555 if (result && *result)
556 pwmd_free (result);
558 return GPG_ERR_NOT_CONFIRMED;
561 if ((*result == 'y' || *result == 'Y') && *(result + 1) == 0)
563 pwmd_free (result);
564 return 0;
567 while (1);
570 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DESC, buf);
571 pwmd_free (buf);
573 if (rc)
574 return rc;
576 return pwmd_getpin (pwm, NULL, NULL, NULL, PWMD_PINENTRY_CONFIRM);
578 #endif
580 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
581 static pwmd_socket_t
582 is_remote_url (const char *str)
584 if (!str)
585 return PWMD_SOCKET_LOCAL;
587 #ifdef WITH_SSH
588 if (strstr (str, "ssh://") || strstr (str, "ssh4://")
589 || strstr (str, "ssh6://"))
590 return PWMD_SOCKET_SSH;
591 #endif
593 #ifdef WITH_GNUTLS
594 if (strstr (str, "tls://") || strstr (str, "tls4://")
595 || strstr (str, "tls6://"))
596 return PWMD_SOCKET_TLS;
597 #endif
599 return PWMD_SOCKET_LOCAL;
601 #endif
603 static char *
604 escape (const char *str)
606 const char *p;
607 char *buf = pwmd_malloc (ASSUAN_LINELENGTH + 1), *b = buf;
608 size_t len = 0;
610 for (p = str; *p; p++, len++)
612 if (len == ASSUAN_LINELENGTH)
613 break;
615 if (*p == '\\')
617 switch (*++p)
619 case 't':
620 *b++ = '\t';
621 break;
622 case 'n':
623 *b++ = '\n';
624 break;
625 case 'v':
626 *b++ = '\v';
627 break;
628 case 'b':
629 *b++ = '\b';
630 break;
631 case 'f':
632 *b++ = '\f';
633 break;
634 case 'r':
635 *b++ = '\r';
636 break;
637 default:
638 *b++ = *p;
639 break;
642 if (!*p)
643 break;
645 continue;
648 *b++ = *p;
651 *b = 0;
652 return buf;
655 static void
656 free_inquire (struct inquire_s *inq)
658 if (!inq)
659 return;
661 pwmd_free (inq->line);
663 if (inq->fd != -1 && inq->fd != STDIN_FILENO)
664 close (inq->fd);
666 pwmd_free (inq);
669 /* When *result is not NULL it is updated to the new values and not
670 * reallocated. */
671 static gpg_error_t
672 set_inquire (int fd, const char *line, struct inquire_s **result)
674 struct inquire_s inq = { 0 };
675 struct stat st = { 0 };
676 gpg_error_t rc;
678 if (fd != -1)
680 if (fstat (fd, &st) == -1)
681 return gpg_error_from_syserror ();
683 inq.size = st.st_size;
686 inq.fd = fd;
687 inq.line = pwmd_calloc (1, ASSUAN_LINELENGTH);
688 if (!inq.line)
689 return GPG_ERR_ENOMEM;
691 if (line)
693 char *s = escape (line);
695 if (!s)
697 pwmd_free (inq.line);
698 return GPG_ERR_ENOMEM;
701 if (strlen (s) >= ASSUAN_LINELENGTH)
703 pwmd_free (inq.line);
704 pwmd_free (s);
705 return GPG_ERR_LINE_TOO_LONG;
708 strncpy (inq.line, s, ASSUAN_LINELENGTH - 1);
709 inq.len = strlen (s);
710 pwmd_free (s);
713 rc = pwmd_setopt (pwm, PWMD_OPTION_INQUIRE_TOTAL,
714 st.st_size ? st.st_size + strlen (inq.line) : 0);
715 if (rc)
717 pwmd_free (inq.line);
718 return rc;
721 if (*result == NULL)
722 *result = pwmd_malloc (sizeof (struct inquire_s));
723 else
725 if ((*result)->fd != -1 && (*result)->fd != STDIN_FILENO)
726 close ((*result)->fd);
728 pwmd_free ((*result)->line);
729 (*result)->line = NULL;
730 (*result)->fd = -1;
731 (*result)->len = 0;
734 memcpy (*result, &inq, sizeof (struct inquire_s));
735 memset (&inq, 0, sizeof (struct inquire_s));
736 return rc;
739 #ifdef HAVE_LIBREADLINE
740 static int
741 interactive_hook (void)
743 interactive_error = process_cmd ();
745 if (interactive_error)
746 rl_event_hook = NULL;
748 return 0;
751 static void
752 print_help ()
754 fprintf (stderr,
756 ("------------------------------------------------------------------------------\n"
757 "Elements are TAB delimited. Press CTRL-V then TAB to insert from the prompt.\n"
758 "\n"
759 "Type HELP for protocol commands. Type .help for pwmc commands. Press CTRL-D\n"
760 "to quit.\n"
761 "------------------------------------------------------------------------------\n"));
763 #endif
765 static char *
766 parse_arg (const char *src, char *dst, size_t len)
768 char *p = dst;
769 const char *s = src;
770 size_t n = 0;
772 for (; s && *s && *s != ' ' && n < len; s++, n++)
773 *p++ = *s;
775 *p = 0;
776 return dst;
779 static char *
780 parse_opt (char **line, const char *opt, gpg_error_t * rc)
782 static char result[ASSUAN_LINELENGTH] = { 0 }, *r = result;
783 size_t len = 0;
784 char *s = strstr (*line, opt);
786 *rc = 0;
787 result[0] = 0;
788 r = result;
790 if (s)
792 int quote = 0;
793 size_t rlen = strlen (opt);
794 char *p = s + rlen;
795 int lastc = 0;
797 while (*p && *p == ' ')
799 rlen++;
800 p++;
803 for (; *p && len < sizeof (result) - 1; p++, rlen++)
805 if (isspace (*p) && !quote)
806 break;
808 if (*p == '\"' && lastc != '\\')
810 quote = !quote;
811 lastc = *p;
812 continue;
815 *r++ = lastc = *p;
816 len++;
819 *r = 0;
821 if (len >= sizeof (result) - 1)
822 *rc = GPG_ERR_LINE_TOO_LONG;
823 else
825 p = s + rlen;
827 while (*p && *p == ' ')
828 p++;
830 *line = p;
834 return result;
837 static gpg_error_t
838 read_command (const char *line, char **result, size_t * len)
840 int fd;
841 gpg_error_t rc = 0;
842 char filebuf[ASSUAN_LINELENGTH];
843 char *filename = NULL;
844 struct inquire_s *inq = NULL;
845 char *p = (char *) line;
846 const char *prefix = parse_opt (&p, "--prefix", &rc);
848 if (rc)
849 return rc;
851 rc = GPG_ERR_SYNTAX;
853 if (p && *p)
855 while (*p && isspace (*p))
856 p++;
858 filename = parse_arg (p, filebuf, sizeof (filebuf));
859 if (filename && *filename)
861 p += strlen (filename) + 1;
863 while (*p && isspace (*p))
864 p++;
866 if (*p)
867 rc = 0;
871 if (rc)
873 fprintf (stderr,
875 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
876 fprintf (stderr,
878 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\" = \")\n"));
879 return rc;
882 fd = open (filename, O_RDONLY);
883 if (fd == -1)
884 return gpg_error_from_syserror ();
886 rc = set_inquire (fd, prefix && *prefix ? prefix : NULL, &inq);
887 if (rc)
889 close (fd);
890 return rc;
893 inq->header = 1;
894 rc = pwmd_command (pwm, result, len, inquire_cb, inq, p);
895 free_inquire (inq);
896 return rc;
899 static gpg_error_t
900 redir_command (const char *line)
902 const char *p = line;
903 int fd;
904 gpg_error_t rc = GPG_ERR_SYNTAX;
905 char filebuf[ASSUAN_LINELENGTH];
906 char *filename = NULL;
907 struct inquire_s *inq = NULL;
908 char *result = NULL;
909 size_t len = 0;
911 if (p && *p && *++p)
913 filename = parse_arg (p, filebuf, sizeof (filebuf));
914 if (filename && *filename)
916 p += strlen (filename) + 1;
918 while (*p && isspace (*p))
919 p++;
921 if (*p)
922 rc = 0;
926 if (rc)
928 fprintf (stderr, N_("Usage: .redir <filename> <command> [args]\n"));
929 return rc;
932 fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
933 if (fd == -1)
934 return gpg_error_from_syserror ();
936 #ifdef HAVE_LIBREADLINE
937 rc = set_inquire (interactive ? STDIN_FILENO : inquirefd, NULL, &inq);
938 #else
939 rc = set_inquire (inquirefd, NULL, &inq);
940 #endif
941 if (rc)
943 close (fd);
944 return rc;
947 rc = parse_dotcommand (p, &result, &len, inq);
948 if (!rc && result && len--)
949 { // null byte which is always appended
950 if (write (fd, result, len) != len)
951 rc = GPG_ERR_TOO_SHORT;
952 pwmd_free (result);
955 free_inquire (inq);
956 close (fd);
957 return rc;
960 static gpg_error_t
961 help_command (const char *line)
963 fprintf (stderr,
964 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
965 " .redir <filename> <command>\n"
966 " redirect the output of a command to the specified file\n"
967 "\n"
968 " .open <filename>\n"
969 " open the specified filename losing any changes to the current one\n"
970 "\n"
971 " .read [--prefix <string>] <filename> <command> [args]\n"
972 " obtain data from the specified filename for an inquire command\n"
973 "\n"
974 " .set help | <name> [<value>]\n"
975 " set option <name> to <value>\n"
976 "\n"
977 " .save [args]\n"
978 " write changes of the file to disk\n"
979 "\n"
980 " .passwd [args]\n"
981 " change the passphrase of a data file\n"
982 "\n"
983 " .help\n"
984 " this help text\n"));
985 return 0;
988 static gpg_error_t
989 open_command (const char *line)
991 struct inquire_s *inq = NULL;
992 const char *filename = line;
993 gpg_error_t rc;
995 while (filename && isspace (*filename))
996 filename++;
998 if (!filename || !*filename)
1000 fprintf (stderr, N_("Usage: .open <filename>\n"));
1001 return GPG_ERR_SYNTAX;
1004 #ifdef HAVE_LIBREADLINE
1005 if (interactive || !quiet)
1006 #else
1007 if (!quiet)
1008 #endif
1009 fprintf (stderr, N_("Opening data file \"%s\" ...\n"), filename);
1011 #ifdef HAVE_LIBREADLINE
1012 rc = set_inquire (interactive ? STDIN_FILENO : -1, NULL, &inq);
1013 #else
1014 rc = set_inquire (-1, NULL, &inq);
1015 #endif
1016 if (rc)
1017 return rc;
1019 if (keyfile)
1020 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1022 rc = pwmd_open (pwm, filename, inquire_cb, inq);
1023 free_inquire (inq);
1024 return rc;
1027 static gpg_error_t
1028 set_command (const char *line)
1030 gpg_error_t rc = 0;
1031 char name[256] = { 0 };
1032 char value[512] = { 0 };
1033 char *namep;
1034 char *valuep;
1035 const char *p = line;
1037 while (p && *p && isspace (*p))
1038 p++;
1040 namep = parse_arg (p, name, sizeof (name));
1041 if (!namep || !*namep)
1043 fprintf (stderr, N_("Usage: .set help | <name> [<value>]\n"));
1044 return GPG_ERR_SYNTAX;
1047 p += strlen (namep);
1048 while (p && *p && isspace (*p))
1049 p++;
1051 valuep = parse_arg (p, value, sizeof (value));
1053 if (!strcmp (name, "keyfile") || !strcmp (name, "new-keyfile"))
1055 int is_newkeyfile = 1;
1056 int is_pkcs = 1;
1057 char datafile[256];
1059 if (!strcmp (name, "keyfile"))
1060 is_newkeyfile = 0;
1062 if (is_newkeyfile)
1064 pwmd_free (new_keyfile);
1065 new_keyfile = NULL;
1067 else
1069 pwmd_free (keyfile);
1070 keyfile = NULL;
1073 p += strlen (valuep);
1074 while (p && *p && isspace (*p))
1075 p++;
1077 valuep = (char *) p;
1078 if (*valuep)
1080 memcpy (datafile, value, sizeof (datafile));
1081 valuep = parse_arg (p, value, sizeof (value));
1082 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "KEYGRIP %s",
1083 datafile);
1084 if (gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED
1085 || (gpg_err_source (rc) == GPG_ERR_SOURCE_USER_1
1086 && gpg_err_code (rc) == GPG_ERR_ENOENT))
1088 rc = 0;
1089 is_pkcs = 0;
1091 else if (!rc)
1092 is_pkcs = 1;
1095 if (!rc && *valuep)
1097 if (is_newkeyfile)
1098 new_keyfile = pwmd_strdup (value);
1099 else
1100 keyfile = pwmd_strdup (value);
1102 if (!is_pkcs)
1103 rc = 0;
1104 else
1105 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1106 "AGENT option pinentry-mode=loopback");
1108 if (!rc)
1110 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 1);
1111 rc = pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1114 else if (!local_pin && !no_pinentry)
1116 pwmd_socket_t t;
1118 pwmd_socket_type (pwm, &t);
1119 if (t == PWMD_SOCKET_LOCAL)
1121 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, 0);
1122 rc = pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
1126 else if (!strcmp (name, "help"))
1128 fprintf (stderr,
1130 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1131 "delimited. When no value is specified the option is unset.\n\n"
1132 "keyfile <datafile> [<filename>]\n"
1133 " set or unset the keyfile to be used when a passphrase is required (*)\n"
1134 "\n"
1135 "new-keyfile <datafile> [<filename>]\n"
1136 " set or unset the keyfile to be used when a new passphrase is required (*)\n"
1137 "\n"
1138 "* = the next protocol command will unset this value\n"
1141 else
1142 rc = GPG_ERR_UNKNOWN_OPTION;
1144 return rc;
1147 static gpg_error_t
1148 save_command (const char *line)
1150 struct inquire_s *inq = NULL;
1151 gpg_error_t rc;
1153 #ifdef HAVE_LIBREADLINE
1154 rc = set_inquire (interactive ? STDIN_FILENO : -1, NULL, &inq);
1155 #else
1156 rc = set_inquire (-1, NULL, &inq);
1157 #endif
1158 if (rc)
1159 return rc;
1161 if (new_keyfile || keyfile)
1162 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1164 rc = pwmd_save (pwm, line, inquire_cb, inq);
1165 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
1166 free_inquire (inq);
1167 return rc;
1170 static gpg_error_t
1171 do_save_passwd_command (const char *line, int save)
1173 struct inquire_s *inq = NULL;
1174 gpg_error_t rc;
1176 #ifdef HAVE_LIBREADLINE
1177 rc = set_inquire (interactive ? STDIN_FILENO : -1, NULL, &inq);
1178 #else
1179 rc = set_inquire (-1, NULL, &inq);
1180 #endif
1181 if (rc)
1182 return rc;
1184 if (new_keyfile || keyfile)
1185 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 1);
1187 if (save)
1188 rc = pwmd_save (pwm, line, inquire_cb, inq);
1189 else
1190 rc = pwmd_passwd (pwm, line, inquire_cb, inq);
1192 pwmd_setopt (pwm, PWMD_OPTION_OVERRIDE_INQUIRE, 0);
1193 free_inquire (inq);
1194 return rc;
1197 static gpg_error_t
1198 parse_dotcommand (const char *line, char **result,
1199 size_t * len, struct inquire_s *inq)
1201 const char *p = line;
1202 gpg_error_t rc = 0;
1204 if (!strncmp (p, ".read", 5))
1205 rc = read_command (p + 5, result, len);
1206 else if (!strncmp (p, ".redir", 6))
1207 rc = redir_command (p + 6);
1208 else if (!strncmp (p, ".help", 5))
1209 rc = help_command (p + 5);
1210 else if (!strncmp (p, ".open", 5))
1211 rc = open_command (p + 5);
1212 else if (!strncmp (p, ".set", 4))
1213 rc = set_command (p + 4);
1214 else if (!strncmp (p, ".save", 5))
1215 rc = do_save_passwd_command (p + 5, 1);
1216 else if (!strncmp (p, ".passwd", 7))
1217 rc = do_save_passwd_command (p + 7, 0);
1218 else
1220 rc = pwmd_command (pwm, result, len, inquire_cb, inq, line);
1221 #ifdef HAVE_LIBREADLINE
1222 if (interactive)
1224 #endif
1225 pwmd_free (keyfile);
1226 pwmd_free (new_keyfile);
1227 keyfile = new_keyfile = NULL;
1228 #ifdef HAVE_LIBREADLINE
1230 #endif
1233 return FINISH (rc);
1236 #ifdef HAVE_LIBREADLINE
1237 static gpg_error_t
1238 do_interactive ()
1240 gpg_error_t rc;
1241 struct inquire_s *inq = NULL;
1243 rl_initialize ();
1244 rc = process_cmd ();
1245 if (rc)
1246 return rc;
1248 rc = set_inquire (STDIN_FILENO, NULL, &inq);
1249 if (rc)
1250 return rc;
1252 fprintf (stderr,
1253 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1254 print_help ();
1255 rl_event_hook = &interactive_hook;
1256 rl_set_keyboard_input_timeout (100000);
1258 for (;;)
1260 char *line;
1261 char *result = NULL;
1262 size_t len;
1264 rc = 0;
1265 line = readline ("pwm> ");
1266 if (interactive_error)
1268 rc = interactive_error;
1269 break;
1272 if (!line)
1274 rc = finalize ();
1275 if (!rc)
1276 break;
1278 if (gpg_err_code (rc) != GPG_ERR_CANCELED &&
1279 gpg_err_code (rc) != GPG_ERR_EOF)
1280 fprintf (stderr, "ERR %i: %s\n", rc, gpg_strerror (rc));
1282 continue;
1284 else if (!*line)
1286 free (line);
1287 continue;
1290 #ifdef HAVE_READLINE_HISTORY
1291 add_history (line);
1292 #endif
1293 inq->header = 0;
1294 rc = parse_dotcommand (line, &result, &len, inq);
1295 free (line);
1296 if (rc)
1298 char *tmp = NULL;
1300 if (gpg_err_code (rc) == GPG_ERR_BAD_DATA)
1301 (void) pwmd_command (pwm, &tmp, NULL, NULL, NULL,
1302 "GETINFO last_error");
1304 show_error (rc, tmp);
1305 pwmd_free (tmp);
1307 else if (result && len)
1308 printf ("%s%s", result, result[len - 1] != '\n' ? "\n" : "");
1310 pwmd_free (result);
1313 free_inquire (inq);
1314 return rc;
1316 #endif
1318 static char *
1319 itoa (long long int n)
1321 static char buf[64];
1323 snprintf (buf, sizeof (buf), "%llu", n);
1324 return buf;
1327 static gpg_error_t
1328 finalize ()
1330 gpg_error_t rc = 0;
1331 #ifdef HAVE_LIBREADLINE
1332 int quit = 0;
1334 if (!force_save && interactive)
1336 char *p, buf[16];
1337 int finished = 0;
1339 fprintf (stderr, "\n");
1343 fprintf (stderr,
1345 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1346 p = fgets (buf, sizeof (buf), stdin);
1348 if (feof (stdin))
1350 clearerr (stdin);
1351 return GPG_ERR_EOF;
1354 switch (*p)
1356 case 'h':
1357 print_help ();
1358 break;
1359 case 'c':
1360 return GPG_ERR_CANCELED;
1361 case 'Q':
1362 return 0;
1363 case 'f':
1364 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1365 "CLEARCACHE %s", filename);
1366 if (rc)
1367 return rc;
1369 interactive_hook ();
1370 break;
1371 case 'S':
1372 quit = 1;
1373 case 's':
1374 save = 1;
1375 finished = 1;
1376 break;
1377 default:
1378 break;
1381 while (!finished);
1383 #endif
1385 if (save && !filename)
1387 fprintf (stderr,
1389 ("No filename was specified on the command line. Aborting.\n"));
1390 return GPG_ERR_CANCELED;
1393 if (save && filename)
1395 char *args =
1396 pwmd_strdup_printf ("%s%s %s%s %s %s%s %s%s %s %s %s --s2k-count=%lu",
1397 keygrip ? "--keygrip=" : "",
1398 keygrip ? keygrip : "",
1399 sign_keygrip ? "--sign-keygrip=" : "",
1400 sign_keygrip ? sign_keygrip : "",
1401 no_passphrase ? "--no-passphrase" : "",
1402 cipher ? "--cipher=" : "", cipher ? cipher : "",
1403 iterations_arg ? "--cipher-iterations=" : "",
1404 iterations_arg ? itoa (iterations) : "",
1405 no_gpg_agent ? "--no-agent" : "",
1406 keyparams ? "--inquire-keyparam" : "",
1407 force_save ? "--reset" : "", s2k_count);
1409 #ifdef HAVE_LIBREADLINE
1410 if (!quiet || interactive)
1412 #else
1413 if (!quiet)
1415 #endif
1416 fprintf (stderr, "\n");
1417 fprintf (stderr, N_("Saving changes ...\n"));
1420 rc = save_command (args);
1421 pwmd_free (args);
1422 if (!rc)
1423 no_passphrase = 0; // reset to avoid usage error on the next SAVE
1426 #ifdef HAVE_LIBREADLINE
1427 if (interactive)
1428 return rc ? rc : quit ? 0 : GPG_ERR_CANCELED;
1429 #endif
1431 return rc;
1435 main (int argc, char *argv[])
1437 int connected = 0;
1438 gpg_error_t rc;
1439 int opt;
1440 char command[ASSUAN_LINELENGTH], *p = NULL;
1441 char *result = NULL;
1442 size_t len;
1443 char *pinentry_path = NULL;
1444 char *display = NULL, *tty = NULL, *ttytype = NULL;
1445 char *lcctype = NULL, *lcmessages = NULL;
1446 int outfd = STDOUT_FILENO;
1447 FILE *outfp = stdout;
1448 FILE *inquirefp = stdin;
1449 int show_status = 1;
1450 char *clientname = "pwmc";
1451 char *inquire = NULL;
1452 char *inquire_line = NULL;
1453 int timeout = 0;
1454 #ifdef WITH_SSH
1455 int use_ssh_agent = 1;
1456 char *knownhosts = NULL;
1457 char *identity = NULL;
1458 #endif
1459 #ifdef WITH_GNUTLS
1460 char *cacert = NULL;
1461 char *clientcert = NULL;
1462 char *clientkey = NULL;
1463 char *prio = NULL;
1464 int tls_verify = 0;
1465 char *tls_fingerprint = NULL;
1466 #endif
1467 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1468 pwmd_socket_t socktype;
1469 long socket_timeout = 300;
1470 int connect_timeout = 120;
1471 #endif
1472 int lock_on_open = 1;
1473 long lock_timeout = 50;
1474 char *url = NULL;
1475 /* The order is important. */
1476 enum
1478 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1479 OPT_SOCKET_TIMEOUT, OPT_CONNECT_TIMEOUT,
1480 #endif
1481 #ifdef WITH_SSH
1482 OPT_USE_SSH_AGENT, OPT_IDENTITY, OPT_KNOWNHOSTS,
1483 #endif
1484 #ifdef WITH_GNUTLS
1485 OPT_CACERT, OPT_CLIENTCERT, OPT_CLIENTKEY, OPT_PRIORITY, OPT_VERIFY,
1486 OPT_SERVER_FP,
1487 #endif
1488 OPT_URL, OPT_LOCAL, OPT_FORCE_SAVE, OPT_TTYNAME, OPT_TTYTYPE,
1489 OPT_DISPLAY, OPT_LC_CTYPE, OPT_LC_MESSAGES, OPT_TIMEOUT, OPT_TRIES,
1490 OPT_PINENTRY, OPT_KEYFILE, OPT_NEW_KEYFILE, OPT_NOLOCK,
1491 OPT_LOCK_TIMEOUT, OPT_SAVE, OPT_OUTPUT_FD, OPT_INQUIRE,
1492 OPT_INQUIRE_FD, OPT_INQUIRE_FILE, OPT_INQUIRE_LINE, OPT_NO_STATUS,
1493 OPT_NAME, OPT_VERSION, OPT_HELP, OPT_KEYGRIP, OPT_SIGN_KEYGRIP,
1494 OPT_NOPASSPHRASE, OPT_CIPHER, OPT_KEYPARAMS, OPT_NO_PINENTRY,
1495 OPT_S2K_COUNT, OPT_ITERATIONS, OPT_QUIET, OPT_NO_GPG_AGENT,
1496 #ifdef HAVE_LIBREADLINE
1497 OPT_INTERACTIVE,
1498 #endif
1500 const struct option long_opts[] = {
1501 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1502 {"socket-timeout", 1, 0, 0},
1503 {"connect-timeout", 1, 0, 0},
1504 #endif
1506 #ifdef WITH_SSH
1507 {"no-ssh-agent", 0, 0, 0},
1508 {"identity", 1, 0, 'i'},
1509 {"knownhosts", 1, 0, 'k'},
1510 #endif
1511 #ifdef WITH_GNUTLS
1512 {"ca-cert", 1, 0, 0},
1513 {"client-cert", 1, 0, 0},
1514 {"client-key", 1, 0, 0},
1515 {"tls-priority", 1, 0, 0},
1516 {"tls-verify", 0, 0, 0},
1517 {"tls-fingerprint", 1, 0, 0},
1518 #endif
1519 {"url", 1, 0, 0},
1520 {"local-pinentry", 0, 0},
1521 {"force-save", 0, 0},
1522 {"ttyname", 1, 0, 'y'},
1523 {"ttytype", 1, 0, 't'},
1524 {"display", 1, 0, 'd'},
1525 {"lc-ctype", 1, 0, 0},
1526 {"lc-messages", 1, 0, 0},
1527 {"timeout", 1, 0, 0},
1528 {"tries", 1, 0, 0},
1529 {"pinentry", 1, 0, 0},
1530 {"key-file", 1, 0, 0},
1531 {"new-key-file", 1, 0, 0},
1532 {"no-lock", 0, 0, 0},
1533 {"lock-timeout", 1, 0, 0},
1534 {"save", 0, 0, 'S'},
1535 {"output-fd", 1, 0, 0},
1536 {"inquire", 1, 0, 0},
1537 {"inquire-fd", 1, 0, 0},
1538 {"inquire-file", 1, 0, 0},
1539 {"inquire-line", 1, 0, 'L'},
1540 {"no-status", 0, 0, 0},
1541 {"name", 1, 0, 'n'},
1542 {"version", 0, 0, 0},
1543 {"help", 0, 0, 0},
1544 {"keygrip", 1, 0, 0},
1545 {"sign-keygrip", 1, 0, 0},
1546 {"no-passphrase", 0, 0, 0},
1547 {"cipher", 1, 0, 0},
1548 {"key-params", 1, 0, 0},
1549 {"no-pinentry", 0, 0, 0},
1550 {"s2k-count", 1, 0, 0},
1551 {"cipher-iterations", 1, 0, 0},
1552 {"quiet", 0, 0, 0},
1553 {"no-gpg-agent", 0, 0, 0},
1554 #ifdef HAVE_LIBREADLINE
1555 {"interactive", 0, 0},
1556 #endif
1557 {0, 0, 0, 0}
1559 #ifdef WITH_SSH
1560 const char *optstring = "L:y:t:d:P:I:Sn:i:k:";
1561 #else
1562 const char *optstring = "L:y:t:d:P:I:Sn:";
1563 #endif
1564 int opt_index = 0;
1566 #ifdef ENABLE_NLS
1567 setlocale (LC_ALL, "");
1568 bindtextdomain ("libpwmd", LOCALEDIR);
1569 #endif
1571 tries = DEFAULT_PIN_TRIES;
1572 inquirefd = STDIN_FILENO;
1574 while ((opt =
1575 getopt_long (argc, argv, optstring, long_opts, &opt_index)) != -1)
1577 switch (opt)
1579 /* Handle long options without a short option part. */
1580 case 0:
1581 switch (opt_index)
1583 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1584 case OPT_SOCKET_TIMEOUT:
1585 socket_timeout = strtol (optarg, &p, 10);
1586 break;
1587 case OPT_CONNECT_TIMEOUT:
1588 connect_timeout = strtol (optarg, &p, 10);
1589 break;
1590 #endif
1591 #ifdef WITH_SSH
1592 case OPT_USE_SSH_AGENT:
1593 use_ssh_agent = 0;
1594 break;
1595 #endif
1596 #ifdef WITH_GNUTLS
1597 case OPT_CACERT:
1598 cacert = optarg;
1599 break;
1600 case OPT_CLIENTCERT:
1601 clientcert = optarg;
1602 break;
1603 case OPT_CLIENTKEY:
1604 clientkey = optarg;
1605 break;
1606 case OPT_PRIORITY:
1607 prio = optarg;
1608 break;
1609 case OPT_VERIFY:
1610 tls_verify = 1;
1611 break;
1612 case OPT_SERVER_FP:
1613 tls_fingerprint = optarg;
1614 break;
1615 #endif
1616 case OPT_NO_GPG_AGENT:
1617 no_gpg_agent = 1;
1618 break;
1619 case OPT_KEYPARAMS:
1620 keyparams = optarg;
1621 break;
1622 case OPT_KEYFILE:
1623 keyfile = pwmd_strdup (optarg);
1624 break;
1625 case OPT_NEW_KEYFILE:
1626 new_keyfile = pwmd_strdup (optarg);
1627 break;
1628 case OPT_NOLOCK:
1629 lock_on_open = 0;
1630 break;
1631 case OPT_LOCK_TIMEOUT:
1632 lock_timeout = strtol (optarg, &p, 10);
1633 break;
1634 case OPT_URL:
1635 url = optarg;
1636 break;
1637 case OPT_LOCAL:
1638 local_pin = 1;
1639 break;
1640 case OPT_FORCE_SAVE:
1641 save = force_save = 1;
1642 break;
1643 case OPT_LC_CTYPE:
1644 lcctype = pwmd_strdup (optarg);
1645 break;
1646 case OPT_LC_MESSAGES:
1647 lcmessages = pwmd_strdup (optarg);
1648 break;
1649 case OPT_TIMEOUT:
1650 timeout = strtol (optarg, &p, 10);
1651 break;
1652 case OPT_TRIES:
1653 tries = strtol (optarg, &p, 10);
1654 break;
1655 case OPT_INQUIRE:
1656 inquire = escape (optarg);
1657 break;
1658 case OPT_INQUIRE_FD:
1659 inquirefd = strtol (optarg, &p, 10);
1660 if (!p)
1662 inquirefp = fdopen (inquirefd, "r");
1663 if (!inquirefp)
1664 err (EXIT_FAILURE, "%i", inquirefd);
1666 break;
1667 case OPT_INQUIRE_FILE:
1668 inquirefd = open (optarg, O_RDONLY);
1669 if (inquirefd == -1)
1670 err (EXIT_FAILURE, "%s", optarg);
1671 inquirefp = fdopen (inquirefd, "r");
1672 break;
1673 case OPT_OUTPUT_FD:
1674 outfd = strtol (optarg, &p, 10);
1675 if (!p)
1677 outfp = fdopen (outfd, "w");
1678 if (!outfp)
1679 err (EXIT_FAILURE, "%i", outfd);
1681 break;
1682 case OPT_NO_STATUS:
1683 show_status = 0;
1684 break;
1685 case OPT_VERSION:
1686 printf ("%s (pwmc)\n\n"
1687 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013\n"
1688 "%s\n"
1689 "Released under the terms of the GPL v2. Use at your own risk.\n\n"
1690 "Compile-time features:\n"
1691 #ifdef HAVE_LIBREADLINE
1692 "+INTERACTIVE "
1693 #else
1694 "-INTERACTIVE "
1695 #endif
1696 #ifdef WITH_SSH
1697 "+SSH "
1698 #else
1699 "-SSH "
1700 #endif
1701 #ifdef WITH_GNUTLS
1702 "+GNUTLS "
1703 #else
1704 "-GNUTLS "
1705 #endif
1706 #ifdef WITH_PINENTRY
1707 "+PINENTRY "
1708 #else
1709 "-PINENTRY "
1710 #endif
1711 #ifdef WITH_QUALITY
1712 "+CRACK "
1713 #else
1714 "-CRACK "
1715 #endif
1716 #ifdef MEM_DEBUG
1717 "+MEM_DEBUG "
1718 #else
1719 "-MEM_DEBUG "
1720 #endif
1721 "\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
1722 exit (EXIT_SUCCESS);
1723 case OPT_PINENTRY:
1724 pinentry_path = optarg;
1725 break;
1726 case OPT_HELP:
1727 usage (argv[0], EXIT_SUCCESS);
1728 case OPT_KEYGRIP:
1729 keygrip = optarg;
1730 break;
1731 case OPT_SIGN_KEYGRIP:
1732 sign_keygrip = optarg;
1733 break;
1734 case OPT_S2K_COUNT:
1735 s2k_count = strtoul (optarg, &p, 10);
1736 break;
1737 case OPT_ITERATIONS:
1738 iterations = strtoull (optarg, &p, 10);
1739 iterations_arg = 1;
1740 break;
1741 case OPT_QUIET:
1742 quiet = 1;
1743 show_status = 0;
1744 break;
1745 case OPT_NOPASSPHRASE:
1746 no_passphrase = 1;
1747 break;
1748 case OPT_CIPHER:
1749 cipher = optarg;
1750 break;
1751 case OPT_NO_PINENTRY:
1752 no_pinentry = 1;
1753 break;
1754 #ifdef HAVE_LIBREADLINE
1755 case OPT_INTERACTIVE:
1756 interactive = 1;
1757 break;
1758 #endif
1759 default:
1760 usage (argv[0], EXIT_FAILURE);
1763 if (p && *p)
1765 fprintf (stderr, N_("%s: invalid argument for option '--%s'\n"),
1766 argv[0], long_opts[opt_index].name);
1767 usage (argv[0], EXIT_FAILURE);
1770 break;
1771 #ifdef WITH_SSH
1772 case 'i':
1773 identity = optarg;
1774 break;
1775 case 'k':
1776 knownhosts = optarg;
1777 break;
1778 #endif
1779 case 'L':
1780 inquire_line = optarg;
1781 break;
1782 case 'y':
1783 tty = optarg;
1784 break;
1785 case 't':
1786 ttytype = optarg;
1787 break;
1788 case 'd':
1789 display = optarg;
1790 break;
1791 case 'S':
1792 save = 1;
1793 break;
1794 case 'n':
1795 clientname = optarg;
1796 break;
1797 default:
1798 usage (argv[0], EXIT_FAILURE);
1802 #ifdef HAVE_LIBREADLINE
1803 if (interactive && !isatty (STDIN_FILENO))
1804 usage (argv[0], EXIT_FAILURE);
1805 else if (isatty (STDIN_FILENO) && !inquire && !inquire_line)
1806 interactive = 1;
1807 #endif
1809 filename = argv[optind];
1810 #ifdef WITH_GNUTLS
1811 gnutls_global_set_mem_functions (pwmd_malloc, pwmd_malloc, NULL,
1812 pwmd_realloc, pwmd_free);
1813 #endif
1814 pwmd_init ();
1815 rc = pwmd_new (clientname, &pwm);
1816 if (rc)
1817 goto done;
1819 pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TRIES, tries);
1820 if (!quiet)
1821 fprintf (stderr, N_("Connecting ...\n"));
1823 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1824 socktype = is_remote_url (url);
1825 if (socktype != PWMD_SOCKET_LOCAL)
1827 local_pin = 1;
1828 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1829 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, connect_timeout);
1830 if (rc)
1831 goto done;
1832 #endif
1834 if (socktype == PWMD_SOCKET_SSH)
1836 #ifdef WITH_SSH
1837 rc = pwmd_setopt (pwm, PWMD_OPTION_KNOWNHOST_CB, knownhost_cb);
1838 if (rc)
1839 goto done;
1841 rc = pwmd_setopt (pwm, PWMD_OPTION_KNOWNHOST_DATA, clientname);
1842 if (rc)
1843 goto done;
1845 if (!getenv ("SSH_AUTH_SOCK") || identity)
1846 use_ssh_agent = 0;
1848 rc = pwmd_setopt (pwm, PWMD_OPTION_SSH_AGENT, use_ssh_agent);
1849 if (rc)
1850 goto done;
1852 rc = pwmd_connect (pwm, url, identity, knownhosts);
1853 #endif
1855 #ifdef WITH_GNUTLS
1856 else
1858 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_VERIFY, tls_verify);
1859 if (rc)
1860 goto done;
1862 rc = pwmd_connect (pwm, url, clientcert, clientkey, cacert, prio,
1863 tls_fingerprint);
1865 #endif
1867 else
1868 rc = pwmd_connect (pwm, url);
1869 #else
1870 rc = pwmd_connect (pwm, url);
1871 #endif
1872 if (rc)
1873 goto done;
1875 if (!quiet)
1876 fprintf (stderr, N_("Connected.\n"));
1878 connected = 1;
1879 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1880 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, socket_timeout);
1881 if (rc)
1882 goto done;
1883 #endif
1885 if (lock_timeout)
1887 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1888 "OPTION LOCK-TIMEOUT=%li", lock_timeout);
1889 if (rc)
1890 goto done;
1893 if (lock_on_open)
1895 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCK_ON_OPEN, 1);
1896 if (rc)
1897 goto done;
1900 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DESC, NULL);
1901 if (rc)
1902 goto done;
1904 if (timeout > 0)
1906 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TIMEOUT, timeout);
1907 if (rc)
1908 goto done;
1911 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, no_pinentry);
1912 if (rc)
1913 goto done;
1915 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCAL_PINENTRY,
1916 (local_pin || keyfile || new_keyfile));
1917 if (rc)
1918 goto done;
1920 if (pinentry_path)
1922 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_PATH, pinentry_path);
1923 if (rc)
1924 goto done;
1927 if (display)
1929 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, display);
1930 if (rc)
1931 goto done;
1934 if (tty)
1936 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, tty);
1937 if (rc)
1938 goto done;
1941 if (ttytype)
1943 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, ttytype);
1944 if (rc)
1945 goto done;
1948 if (lcctype)
1950 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_CTYPE, lcctype);
1951 if (rc)
1952 goto done;
1955 if (lcmessages)
1957 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_MESSAGES, lcmessages);
1958 if (rc)
1959 goto done;
1962 if (show_status)
1964 rc = pwmd_setopt (pwm, PWMD_OPTION_STATUS_CB, status_msg_cb);
1965 if (rc)
1966 goto done;
1969 if (filename)
1971 rc = open_command (filename);
1972 if (rc)
1973 goto done;
1976 #ifdef HAVE_LIBREADLINE
1977 if (interactive)
1979 if (!force_save)
1980 save = 0;
1982 rc = do_interactive ();
1983 result = NULL;
1984 goto do_exit;
1986 #endif
1988 if (inquire)
1990 struct inquire_s *inq = NULL;
1992 rc = set_inquire (inquirefd, inquire_line, &inq);
1993 if (!rc)
1994 rc = pwmd_command (pwm, &result, &len, inquire_cb, inq, inquire);
1996 free_inquire (inq);
1997 goto done;
2000 fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
2001 ssize_t n;
2003 for (;;)
2005 rc = process_cmd ();
2007 if (rc)
2008 goto done;
2010 n = read (STDIN_FILENO, command, sizeof (command));
2011 if (n == -1)
2013 if (errno == EAGAIN)
2015 usleep (100000);
2016 continue;
2019 rc = gpg_error_from_errno (errno);
2020 goto done;
2022 else if (!n)
2023 goto done;
2025 p = command;
2026 command[n] = 0;
2027 break;
2030 if (!p || !*p || !strcasecmp (p, "BYE"))
2031 goto done;
2034 struct inquire_s *inq = NULL;
2035 rc = set_inquire (inquirefd, inquire_line, &inq);
2036 if (!rc)
2038 rc = parse_dotcommand (command, &result, &len, inq);
2039 free_inquire (inq);
2042 if (rc)
2043 goto done;
2045 done:
2046 if (result)
2048 fwrite (result, 1, result[len - 1] == 0 ? len - 1 : len, outfp);
2049 fflush (outfp);
2050 pwmd_free (result);
2053 result = NULL;
2054 if (!rc)
2055 rc = finalize ();
2056 else if (gpg_err_code (rc) == GPG_ERR_BAD_DATA)
2057 (void) pwmd_command (pwm, &result, NULL, NULL, NULL,
2058 "GETINFO last_error");
2060 #ifdef HAVE_LIBREADLINE
2061 do_exit:
2062 #endif
2063 memset (command, 0, sizeof (command));
2064 pwmd_close (pwm);
2065 pwmd_free (keyfile);
2066 pwmd_free (new_keyfile);
2067 pwmd_deinit ();
2069 if (rc && !quiet)
2070 show_error (rc, result);
2072 pwmd_free (result);
2073 if (connected && !quiet)
2074 fprintf (stderr, N_("Connection closed.\n"));
2076 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);