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/>.
33 #include <sys/select.h>
35 #include <sys/types.h>
46 #ifdef HAVE_GETOPT_LONG
51 #include "getopt_long.h"
54 #ifdef HAVE_LIBREADLINE
55 #if defined(HAVE_READLINE_READLINE_H)
56 #include <readline/readline.h>
57 #elif defined(HAVE_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)
70 #endif /* HAVE_READLINE_HISTORY */
77 #define N_(msgid) gettext(msgid)
81 #define DEFAULT_PIN_TRIES 3
82 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
85 static int no_pinentry
;
87 static char *filename
;
89 static int force_save
;
90 static int no_passphrase
;
93 static char *sign_keygrip
;
94 static char *keyparams
;
95 static char *password
;
97 static char *new_keyfile
;
98 static unsigned long s2k_count
;
99 static uint64_t iterations
;
100 static int iterations_arg
;
102 static int local_pin
;
103 static int inquirefd
;
111 size_t size
; // from stat(2).
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
);
122 static gpg_error_t
get_password (char **result
, pwmd_pinentry_t w
, int echo
);
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");
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"
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"
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"
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"
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"
170 " disable showing of status messages from the server\n"
172 " disable showing of extra messages (implies --no-status)\n"
173 " --name, -n <string>\n"
174 " set the client name\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"
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"
192 " number of pinentry tries before failing (3)\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"
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
210 " use a shell like interface to pwmd (allows more than one command)\n"
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"
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"
230 " like --save but always ask for a passphrase\n"
231 " --version\n" " --help\n"));
232 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
234 "An optional url may be in the form of:\n"
235 " --url /path/to/socket\n"
236 " --url file://[path/to/socket]\n"
239 " --url ssh[46]://[username@]hostname[:port]\n"
240 " --no-ssh-agent -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
244 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
245 " --client-key filename\n"
252 inquire_cb (void *user
, const char *keyword
, gpg_error_t rc
,
253 char **data
, size_t * size
)
255 struct inquire_s
*inq
= user
;
257 int is_newpassword
= 0;
265 if (!strcmp (keyword
, "PASSPHRASE"))
267 else if (!strcmp (keyword
, "NEW_PASSPHRASE"))
269 #ifdef HAVE_LIBREADLINE
270 else if (!strcmp (keyword
, "KEYPARAM") && !interactive
)
273 else if (!strcmp (keyword
, "KEYPARAM"))
276 if (!keyparams
|| !*keyparams
)
277 return gpg_error (GPG_ERR_INV_PARAMETER
);
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
);
290 fprintf (stderr
, "%s: %s\n", is_newpassword
? new_keyfile
: keyfile
,
292 return gpg_error_from_syserror ();
295 rc
= set_inquire (fd
, NULL
, &inq
);
303 fprintf (stderr
, N_("Using keyfile '%s' as %s.\n"),
304 is_newpassword
? new_keyfile
: keyfile
, keyword
);
306 if (!new_keyfile
|| is_newpassword
)
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
)
320 rc
= pwmd_password (pwm
, keyword
, &tmp
, &inq
->len
);
321 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
324 pwmd_free (inq
->line
);
328 return gpg_error (GPG_ERR_EOF
);
330 #ifdef HAVE_LIBREADLINE
331 else if (!inq
->header
&& interactive
)
335 ("Press CTRL-D to send the current line. Press twice to end. %s:\n"),
341 /* The first part of the command data. */
347 return inq
->fd
== -1 ? gpg_error (GPG_ERR_EOF
) : 0;
350 *size
= read (inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
354 return gpg_error (gpg_error_from_syserror ());
358 else if (inq
->fd
!= STDIN_FILENO
&& (is_newpassword
|| is_password
))
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
);
374 status_msg_cb (void *data
, const char *line
)
376 char *p
= strchr (line
, ' ');
378 if (!strcmp (line
, "KEEPALIVE"))
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);
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
,
400 fprintf (stderr
, "%s\n", line
);
402 #ifdef HAVE_LIBREADLINE
411 return pwmd_process (pwm
);
416 get_password (char **result
, pwmd_pinentry_t w
, int echo
)
418 char buf
[LINE_MAX
] = { 0 }, *p
;
419 struct termios told
, tnew
;
424 if (!isatty (STDIN_FILENO
))
426 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
427 return GPG_ERR_ENOTTY
;
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)
443 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
444 return gpg_error_from_errno (n
);
450 case PWMD_PINENTRY_OPEN
:
451 fprintf (stderr
, N_("Password for %s: "), filename
);
453 case PWMD_PINENTRY_OPEN_FAILED
:
454 fprintf (stderr
, N_("Invalid password. Password for %s: "), filename
);
456 case PWMD_PINENTRY_SAVE
:
457 fprintf (stderr
, N_("New password for %s: "), filename
);
459 case PWMD_PINENTRY_SAVE_CONFIRM
:
460 fprintf (stderr
, N_("Confirm password: "));
466 if ((p
= fgets (buf
, sizeof (buf
), stdin
)) == NULL
)
468 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
473 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
478 return GPG_ERR_CANCELED
;
481 p
[strlen (p
) - 1] = 0;
485 key
= pwmd_strdup_printf ("%s", p
);
486 memset (&buf
, 0, sizeof (buf
));
489 return GPG_ERR_ENOMEM
;
497 knownhost_cb (void *data
, const char *host
, const char *key
, size_t len
)
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"));
509 return GPG_ERR_ENOTTY
;
511 else if (no_pinentry
)
513 for (char *p
= buf
, len
= 0; *p
; p
++, len
++)
522 while (!isspace (*(--p
)));
529 fprintf (stderr
, "%s\n\n", buf
);
536 fprintf (stderr
, N_("Trust this connection [y/N]: "));
538 rc
= get_password (&result
, PWMD_PINENTRY_CONFIRM
, 1);
543 if (!result
|| !*result
|| *result
== 'n' || *result
== 'N')
545 if (result
&& *result
)
548 return GPG_ERR_NOT_CONFIRMED
;
551 if ((*result
== 'y' || *result
== 'Y') && *(result
+ 1) == 0)
560 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, buf
);
566 return pwmd_getpin (pwm
, NULL
, NULL
, NULL
, PWMD_PINENTRY_CONFIRM
);
570 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
572 is_remote_url (const char *str
)
575 return PWMD_SOCKET_LOCAL
;
578 if (strstr (str
, "ssh://") || strstr (str
, "ssh4://")
579 || strstr (str
, "ssh6://"))
580 return PWMD_SOCKET_SSH
;
584 if (strstr (str
, "tls://") || strstr (str
, "tls4://")
585 || strstr (str
, "tls6://"))
586 return PWMD_SOCKET_TLS
;
589 return PWMD_SOCKET_LOCAL
;
594 escape (const char *str
)
597 char *buf
= pwmd_malloc (ASSUAN_LINELENGTH
+ 1), *b
= buf
;
600 for (p
= str
; *p
; p
++, len
++)
602 if (len
== ASSUAN_LINELENGTH
)
646 free_inquire (struct inquire_s
*inq
)
651 pwmd_free (inq
->line
);
653 if (inq
->fd
!= -1 && inq
->fd
!= STDIN_FILENO
)
659 /* When *result is not NULL it is updated to the new values and not
662 set_inquire (int fd
, const char *line
, struct inquire_s
**result
)
664 struct inquire_s inq
= { 0 };
665 struct stat st
= { 0 };
670 if (fstat (fd
, &st
) == -1)
671 return gpg_error_from_syserror ();
673 inq
.size
= st
.st_size
;
677 inq
.line
= pwmd_calloc (1, ASSUAN_LINELENGTH
);
679 return GPG_ERR_ENOMEM
;
683 char *s
= escape (line
);
687 pwmd_free (inq
.line
);
688 return GPG_ERR_ENOMEM
;
691 if (strlen (s
) >= ASSUAN_LINELENGTH
)
693 pwmd_free (inq
.line
);
695 return GPG_ERR_LINE_TOO_LONG
;
698 strncpy (inq
.line
, s
, ASSUAN_LINELENGTH
- 1);
699 inq
.len
= strlen (s
);
703 rc
= pwmd_setopt (pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
704 st
.st_size
? st
.st_size
+ strlen (inq
.line
) : 0);
707 pwmd_free (inq
.line
);
712 *result
= pwmd_malloc (sizeof (struct inquire_s
));
715 if ((*result
)->fd
!= -1 && (*result
)->fd
!= STDIN_FILENO
)
716 close ((*result
)->fd
);
718 pwmd_free ((*result
)->line
);
719 (*result
)->line
= NULL
;
724 memcpy (*result
, &inq
, sizeof (struct inquire_s
));
725 memset (&inq
, 0, sizeof (struct inquire_s
));
729 #ifdef HAVE_LIBREADLINE
731 interactive_hook (void)
733 interactive_error
= process_cmd ();
735 if (interactive_error
)
736 rl_event_hook
= NULL
;
746 ("------------------------------------------------------------------------------\n"
747 "Elements are TAB delimited. Press CTRL-V then TAB to insert from the prompt.\n"
749 "Type HELP for protocol commands. Type .help for pwmc commands. Press CTRL-D\n"
751 "------------------------------------------------------------------------------\n"));
756 parse_arg (const char *src
, char *dst
, size_t len
)
762 for (; s
&& *s
&& *s
!= ' ' && n
< len
; s
++, n
++)
770 parse_opt (char **line
, const char *opt
, gpg_error_t
* rc
)
772 static char result
[ASSUAN_LINELENGTH
] = { 0 }, *r
= result
;
774 char *s
= strstr (*line
, opt
);
783 size_t rlen
= strlen (opt
);
787 while (*p
&& *p
== ' ')
793 for (; *p
&& len
< sizeof (result
) - 1; p
++, rlen
++)
795 if (isspace (*p
) && !quote
)
798 if (*p
== '\"' && lastc
!= '\\')
811 if (len
>= sizeof (result
) - 1)
812 *rc
= GPG_ERR_LINE_TOO_LONG
;
817 while (*p
&& *p
== ' ')
828 read_command (const char *line
, char **result
, size_t * len
)
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
);
845 while (*p
&& isspace (*p
))
848 filename
= parse_arg (p
, filebuf
, sizeof (filebuf
));
849 if (filename
&& *filename
)
851 p
+= strlen (filename
) + 1;
853 while (*p
&& isspace (*p
))
865 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
868 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\" = \")\n"));
872 fd
= open (filename
, O_RDONLY
);
874 return gpg_error_from_syserror ();
876 rc
= set_inquire (fd
, prefix
&& *prefix
? prefix
: NULL
, &inq
);
884 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, p
);
890 redir_command (const char *line
)
892 const char *p
= line
;
894 gpg_error_t rc
= GPG_ERR_SYNTAX
;
895 char filebuf
[ASSUAN_LINELENGTH
];
896 char *filename
= NULL
;
897 struct inquire_s
*inq
= NULL
;
903 filename
= parse_arg (p
, filebuf
, sizeof (filebuf
));
904 if (filename
&& *filename
)
906 p
+= strlen (filename
) + 1;
908 while (*p
&& isspace (*p
))
918 fprintf (stderr
, N_("Usage: .redir <filename> <command> [args]\n"));
922 fd
= open (filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
924 return gpg_error_from_syserror ();
926 #ifdef HAVE_LIBREADLINE
927 rc
= set_inquire (interactive
? STDIN_FILENO
: inquirefd
, NULL
, &inq
);
929 rc
= set_inquire (inquirefd
, NULL
, &inq
);
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
;
951 help_command (const char *line
)
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"));
968 open_command (const char *line
)
970 struct inquire_s
*inq
= NULL
;
971 const char *filename
= line
;
974 while (filename
&& isspace (*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
)
988 fprintf (stderr
, N_("Opening data file \"%s\" ...\n"), filename
);
990 #ifdef HAVE_LIBREADLINE
991 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
993 rc
= set_inquire (-1, NULL
, &inq
);
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
1006 pwmd_free (new_keyfile
);
1011 rc
= pwmd_open (pwm
, filename
, inquire_cb
, inq
);
1017 set_command (const char *line
)
1020 char name
[256] = { 0 };
1021 char value
[512] = { 0 };
1024 const char *p
= line
;
1026 while (p
&& *p
&& isspace (*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
))
1040 valuep
= parse_arg (p
, value
, sizeof (value
));
1042 if (!strcmp (name
, "keyfile") || !strcmp (name
, "new-keyfile"))
1044 int is_newkeyfile
= 1;
1048 if (!strcmp (name
, "keyfile"))
1053 pwmd_free (new_keyfile
);
1058 pwmd_free (keyfile
);
1062 p
+= strlen (valuep
);
1063 while (p
&& *p
&& isspace (*p
))
1066 valuep
= (char *) p
;
1069 memcpy (datafile
, value
, sizeof (datafile
));
1070 valuep
= parse_arg (p
, value
, sizeof (value
));
1072 pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "KEYGRIP %s",
1074 if (gpg_err_code (rc
) == GPG_ERR_NOT_SUPPORTED
)
1086 new_keyfile
= pwmd_strdup (value
);
1088 keyfile
= pwmd_strdup (value
);
1093 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1094 "AGENT option pinentry-mode=loopback");
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
)
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"))
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"));
1126 rc
= GPG_ERR_UNKNOWN_OPTION
;
1132 parse_dotcommand (const char *line
, char **result
,
1133 size_t * len
, struct inquire_s
*inq
)
1135 const char *p
= line
;
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);
1149 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, line
);
1154 #ifdef HAVE_LIBREADLINE
1159 struct inquire_s
*inq
= NULL
;
1162 rc
= process_cmd ();
1166 rc
= set_inquire (STDIN_FILENO
, NULL
, &inq
);
1171 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1173 rl_event_hook
= &interactive_hook
;
1174 rl_set_keyboard_input_timeout (100000);
1179 char *result
= NULL
;
1183 line
= readline ("pwm> ");
1184 if (interactive_error
)
1186 rc
= interactive_error
;
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
));
1208 #ifdef HAVE_READLINE_HISTORY
1212 rc
= parse_dotcommand (line
, &result
, &len
, inq
);
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
);
1225 else if (result
&& len
)
1226 printf ("%s%s", result
, result
[len
- 1] != '\n' ? "\n" : "");
1237 itoa (long long int n
)
1239 static char buf
[64];
1241 snprintf (buf
, sizeof (buf
), "%llu", n
);
1249 #ifdef HAVE_LIBREADLINE
1252 if (!force_save
&& interactive
)
1257 fprintf (stderr
, "\n");
1263 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1264 p
= fgets (buf
, sizeof (buf
), stdin
);
1278 return GPG_ERR_CANCELED
;
1282 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1283 "CLEARCACHE %s", filename
);
1287 interactive_hook ();
1303 if (save
&& !filename
)
1307 ("No filename was specified on the command line. Aborting.\n"));
1308 return GPG_ERR_CANCELED
;
1311 if (save
&& filename
)
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
) : "",
1325 #ifdef HAVE_LIBREADLINE
1326 if (!quiet
|| interactive
)
1332 fprintf (stderr
, "\n");
1333 fprintf (stderr
, N_("Saving changes ...\n"));
1336 rc
= pwmd_save (pwm
, args
, inquire_cb
, NULL
);
1340 no_passphrase
= 0; // reset to avoid usage error on the next SAVE
1343 #ifdef HAVE_LIBREADLINE
1345 return rc
? rc
: quit
? 0 : GPG_ERR_CANCELED
;
1352 main (int argc
, char *argv
[])
1357 char command
[ASSUAN_LINELENGTH
], *p
= NULL
;
1358 char *result
= NULL
;
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
;
1372 int use_ssh_agent
= 1;
1373 char *knownhosts
= NULL
;
1374 char *identity
= NULL
;
1377 char *cacert
= NULL
;
1378 char *clientcert
= NULL
;
1379 char *clientkey
= NULL
;
1382 char *tls_fingerprint
= NULL
;
1384 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1385 pwmd_socket_t socktype
;
1386 long socket_timeout
= 0;
1388 int lock_on_open
= 1;
1389 long lock_timeout
= 0;
1391 /* The order is important. */
1394 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1398 OPT_USE_SSH_AGENT
, OPT_IDENTITY
, OPT_KNOWNHOSTS
,
1401 OPT_CACERT
, OPT_CLIENTCERT
, OPT_CLIENTKEY
, OPT_PRIORITY
, OPT_VERIFY
,
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
1416 const struct option long_opts
[] = {
1417 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1418 {"socket-timeout", 1, 0, 0},
1422 {"no-ssh-agent", 0, 0, 0},
1423 {"identity", 1, 0, 'i'},
1424 {"knownhosts", 1, 0, 'k'},
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},
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},
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},
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},
1468 #ifdef HAVE_LIBREADLINE
1469 {"interactive", 0, 0},
1474 const char *optstring
= "L:y:t:d:P:I:Sn:i:k:";
1476 const char *optstring
= "L:y:t:d:P:I:Sn:";
1481 setlocale (LC_ALL
, "");
1482 bindtextdomain ("libpwmd", LOCALEDIR
);
1485 #ifdef HAVE_LIBREADLINE
1486 if (!strcmp (basename (argv
[0]), "pwmsh"))
1490 tries
= DEFAULT_PIN_TRIES
;
1491 inquirefd
= STDIN_FILENO
;
1494 getopt_long (argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1)
1498 /* Handle long options without a short option part. */
1502 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1503 case OPT_SOCKET_TIMEOUT
:
1504 socket_timeout
= strtol (optarg
, &p
, 10);
1508 case OPT_USE_SSH_AGENT
:
1516 case OPT_CLIENTCERT
:
1517 clientcert
= optarg
;
1529 tls_fingerprint
= optarg
;
1536 keyfile
= pwmd_strdup (optarg
);
1538 case OPT_NEW_KEYFILE
:
1539 new_keyfile
= pwmd_strdup (optarg
);
1544 case OPT_LOCK_TIMEOUT
:
1545 lock_timeout
= strtol (optarg
, &p
, 10);
1553 case OPT_FORCE_SAVE
:
1554 save
= force_save
= 1;
1557 lcctype
= pwmd_strdup (optarg
);
1559 case OPT_LC_MESSAGES
:
1560 lcmessages
= pwmd_strdup (optarg
);
1563 timeout
= strtol (optarg
, &p
, 10);
1566 tries
= strtol (optarg
, &p
, 10);
1571 case OPT_INQUIRE_FD
:
1572 inquirefd
= strtol (optarg
, &p
, 10);
1575 inquirefp
= fdopen (inquirefd
, "r");
1578 pwmd_free (password
);
1579 err (EXIT_FAILURE
, "%i", inquirefd
);
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");
1593 outfd
= strtol (optarg
, &p
, 10);
1596 outfp
= fdopen (outfd
, "w");
1599 pwmd_free (password
);
1600 err (EXIT_FAILURE
, "%i", outfd
);
1608 pwmd_free (password
);
1609 printf ("%s (pwmc)\n\n"
1610 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013\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
1629 #ifdef WITH_PINENTRY
1644 "\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
1645 exit (EXIT_SUCCESS
);
1647 pinentry_path
= optarg
;
1650 usage (argv
[0], EXIT_SUCCESS
);
1654 case OPT_SIGN_KEYGRIP
:
1655 sign_keygrip
= optarg
;
1658 s2k_count
= strtoul (optarg
, &p
, 10);
1660 case OPT_ITERATIONS
:
1661 iterations
= strtoull (optarg
, &p
, 10);
1668 case OPT_NOPASSPHRASE
:
1674 case OPT_NO_PINENTRY
:
1677 #ifdef HAVE_LIBREADLINE
1678 case OPT_INTERACTIVE
:
1683 usage (argv
[0], EXIT_FAILURE
);
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
);
1699 knownhosts
= optarg
;
1703 inquire_line
= optarg
;
1718 clientname
= optarg
;
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
)
1736 filename
= argv
[optind
];
1738 gnutls_global_set_mem_functions (pwmd_malloc
, pwmd_malloc
, NULL
,
1739 pwmd_realloc
, pwmd_free
);
1742 rc
= pwmd_new (clientname
, &pwm
);
1746 pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
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
)
1755 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1756 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, socket_timeout
);
1761 if (socktype
== PWMD_SOCKET_SSH
)
1764 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_CB
, knownhost_cb
);
1768 rc
= pwmd_setopt (pwm
, PWMD_OPTION_KNOWNHOST_DATA
, clientname
);
1772 if (!getenv ("SSH_AUTH_SOCK") || identity
)
1775 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, use_ssh_agent
);
1779 rc
= pwmd_connect (pwm
, url
, identity
, knownhosts
);
1785 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, tls_verify
);
1789 rc
= pwmd_connect (pwm
, url
, clientcert
, clientkey
, cacert
, prio
,
1795 rc
= pwmd_connect (pwm
, url
);
1797 rc
= pwmd_connect (pwm
, url
);
1803 fprintf (stderr
, N_("Connected.\n"));
1808 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1809 "OPTION LOCK-TIMEOUT=%li", lock_timeout
);
1816 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, 1);
1821 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, NULL
);
1827 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
1832 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
1836 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
,
1837 (local_pin
|| keyfile
|| new_keyfile
));
1843 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
1850 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
1857 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
1864 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
1871 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
1878 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, lcmessages
);
1885 rc
= pwmd_setopt (pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
1892 rc
= open_command (filename
);
1897 #ifdef HAVE_LIBREADLINE
1903 rc
= do_interactive ();
1911 struct inquire_s
*inq
= NULL
;
1913 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
1915 rc
= pwmd_command (pwm
, &result
, &len
, inquire_cb
, inq
, inquire
);
1921 fcntl (STDIN_FILENO
, F_SETFL
, O_NONBLOCK
);
1926 rc
= process_cmd ();
1931 n
= read (STDIN_FILENO
, command
, sizeof (command
));
1934 if (errno
== EAGAIN
)
1940 rc
= gpg_error_from_errno (errno
);
1951 if (!p
|| !*p
|| !strcasecmp (p
, "BYE"))
1955 struct inquire_s
*inq
= NULL
;
1956 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
1959 rc
= parse_dotcommand (command
, &result
, &len
, inq
);
1969 fwrite (result
, 1, result
[len
- 1] == 0 ? len
- 1 : len
, outfp
);
1974 pwmd_free (password
);
1975 password
= result
= NULL
;
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
1985 memset (command
, 0, sizeof (command
));
1987 pwmd_free (keyfile
);
1988 pwmd_free (new_keyfile
);
1992 show_error (rc
, result
);
1995 if (connected
&& !quiet
)
1996 fprintf (stderr
, N_("Connection closed.\n"));
1998 exit (rc
? EXIT_FAILURE
: EXIT_SUCCESS
);