2 Copyright (C) 2006-2016 Ben Kibbey <bjk@luxsci.net>
4 This file is part of libpwmd.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
34 #include <sys/select.h>
36 #include <sys/types.h>
44 #include "util-string.h"
45 #include "util-slist.h"
48 #include <gnutls/gnutls.h>
55 #ifdef HAVE_GETOPT_LONG
60 #include "getopt_long.h"
63 #ifdef HAVE_LIBREADLINE
64 #if defined(HAVE_READLINE_READLINE_H)
65 #include <readline/readline.h>
66 #elif defined(HAVE_READLINE_H)
68 #endif /* !defined(HAVE_READLINE_H) */
69 static int interactive_error
;
70 static int interactive
;
71 #endif /* HAVE_LIBREADLINE */
73 #ifdef HAVE_READLINE_HISTORY
74 #if defined(HAVE_READLINE_HISTORY_H)
75 #include <readline/history.h>
76 #elif defined(HAVE_HISTORY_H)
79 #endif /* HAVE_READLINE_HISTORY */
86 #define N_(msgid) gettext(msgid)
91 #define DEFAULT_STATUS_IGNORE "KEEPALIVE,GPGME,PASSPHRASE_INFO,PASSPHRASE_HINT"
92 #define DEFAULT_PIN_TIMEOUT 30
93 #define DEFAULT_PIN_TRIES 3
95 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
105 static int no_pinentry
;
107 static char *filename
;
110 static char *sign_keyid
;
111 static int symmetric
;
112 static char *keyparams
;
113 static char *keyfile
;
114 static char *new_keyfile
;
115 static char *sign_keyfile
;
117 static int local_pin
;
118 static int inquirefd
;
122 static char **status_ignore
;
129 size_t size
; // from stat(2).
157 struct slist_s
*userids
;
158 struct slist_s
*subkeys
;
161 static gpg_error_t
finalize ();
162 static gpg_error_t
set_inquire (int fd
, const char *line
,
163 struct inquire_s
**result
);
164 static gpg_error_t
parse_dotcommand (const char *line
, char **result
,
165 size_t * len
, struct inquire_s
*inq
);
166 static gpg_error_t
open_command (char *line
);
169 show_error (pwm_t
*h
, gpg_error_t rc
, const char *str
)
173 int e
= pwmd_gnutls_error (h
, &tlsstr
);
176 fprintf(stderr
, "TLS: %s\n", tlsstr
);
180 fprintf (stderr
, "ERR %i: %s%s%s%s", rc
, gpg_strerror (rc
),
181 str
? ": " : "", str
? str
: "", str
? "" : "\n");
188 pwmd_free (new_keyfile
);
189 pwmd_free (sign_keyfile
);
190 keyfile
= new_keyfile
= sign_keyfile
= NULL
;
194 usage (const char *pn
, int status
)
196 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
197 N_("Usage: %s [options] [file]\n"
199 " a url string to connect to (%s, see below)\n"
200 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
201 " --connect-timeout <seconds>\n"
202 " seconds before connecting to a remote host fails (0=disabled, 120)\n"
203 " --socket-timeout <seconds>\n"
204 " seconds before a remote command fails (0=disabled, 300)\n"
207 " --ca-cert <filename>\n"
208 " certificate authority (CA) used to sign the server cert\n"
209 " --client-cert <filename>\n"
210 " client certificate to use for authentication\n"
211 " --client-key <filename>\n"
212 " key file used to protect the client certificate\n"
213 " --tls-priority <string>\n"
214 " compression, cipher and hash algorithm string\n"
215 " (SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0)\n"
217 " disable verifying the hostname against the server certificate\n"
218 " --tls-fingerprint <string>\n"
219 " a SHA-256 hash of the server fingerprint to verify against\n"
223 " disable SSH agent use (enabled when SSH_AUTH_SOCK is set)\n"
224 " --identity, -i <filename>\n"
225 " the ssh identity file to use for authentication\n"
226 " --knownhosts, -k <filename>\n"
227 " the ssh knownhosts file to use (~/.ssh/knownhosts)\n"
228 " --ssh-needs-passphrase\n"
229 " prompt for a passphrase for the SSH identity file\n"
230 " --ssh-passphrase-file <filename>\n"
231 " read the SSH private key passphrase from filename\n"
234 " do not lock the data file upon opening it\n"
235 " --lock-timeout <N>\n"
236 " time in tenths of a second to wait for a locked data file (50)\n"
237 " --name, -n <string>\n"
238 " set the client name\n"
239 " --pinentry <path>\n"
240 " the full path to the pinentry binary\n"
241 " --local-pinentry\n"
242 " force using a local pinentry\n"
244 " disable pinentry both remotely and locally\n"
245 " --ttyname, -y <path>\n"
246 " tty that pinentry will use\n"
247 " --ttytype, -t <string>\n"
248 " pinentry terminal type (default is $TERM)\n"
250 " pinentry display (default is $DISPLAY)\n"
251 " --lc-ctype <string>\n"
252 " locale setting for pinentry\n"
253 " --lc-messages <string>\n"
254 " locale setting for pinentry\n"
256 " number of pinentry tries before failing (3)\n"
257 " --timeout <seconds>\n"
258 " pinentry timeout\n"
259 " --inquire <COMMAND>\n"
260 " the specified command (with any options) uses a server inquire while\n"
261 " command data is read via the inquire file descriptor (stdin)\n"
262 " --inquire-line, -L <STRING>\n"
263 " the initial line to send (i.e., element path) before the inquire data\n"
264 " --inquire-fd <FD>\n"
265 " read inquire data from the specified file descriptor (stdin)\n"
266 " --inquire-file <filename>\n"
267 " read inquire data from the specified filename\n"
268 " --output-fd <FD>\n"
269 " redirect command output to the specified file descriptor\n"
271 " send the SAVE command before exiting\n"
272 " --passphrase-file <filename>\n"
273 " obtain the passphrase from the specified filename\n"
274 " --new-passphrase-file <filename>\n"
275 " obtain the passphrase to save with from the specified filename\n"
276 " --sign-passphrase-file <filename>\n"
277 " obtain the passphrase to sign with from the specified filename\n"
278 " --key-params <filename>\n"
279 " key parameters to use for key generation (pwmd default)\n"
280 " --keyid <recipient>[,<recipient>]\n"
281 " the public key ID to u\n"
282 " --sign-keyid <string>\n"
283 " the key ID to sign the data file with\n"
285 " use conventional encryption with optional signer(s) for new files\n"
287 " disable showing of status messages from the server\n"
289 " enable receiving of client STATE status messages\n"
290 " --status-fd <FD>\n"
291 " redirect status messages to the specified file descriptor\n"
292 " --status-ignore <string[,...]>\n"
293 " prevent parsing of the specified status message keywords\n"
295 " disable showing of extra messages (implies --no-status)\n"
296 #ifdef HAVE_LIBREADLINE
297 " --no-interactive\n"
298 " disable interactive mode\n"
303 #ifdef DEFAULT_PWMD_SOCKET
309 fprintf (status
== EXIT_FAILURE
? stderr
: stdout
,
311 "An optional url may be in the form of:\n"
312 " --url /path/to/socket\n"
313 " --url file://[/path/to/socket]\n"
316 " --url ssh[46]://[username@]hostname[:port] (uses ssh-agent)\n"
317 " -i identity_file --url ssh[46]://[username@]hostname[:port]\n"
321 " --url tls[46]://hostname[:port] --ca-cert filename --client-cert filename\n"
322 " --client-key filename\n"
324 #ifdef HAVE_LIBREADLINE
326 "Interactive mode is used when input is from a terminal.\n"
333 inquire_cb (void *user
, const char *keyword
, gpg_error_t rc
,
334 char **data
, size_t * size
)
336 struct inquire_s
*inq
= user
;
338 int is_newpassword
= 0;
348 if (!strcmp (keyword
, "PASSPHRASE"))
350 else if (!strcmp (keyword
, "SIGN_PASSPHRASE"))
352 else if (!strcmp (keyword
, "NEW_PASSPHRASE"))
354 #ifdef HAVE_LIBREADLINE
355 else if (!strcmp (keyword
, "KEYPARAM") && !interactive
)
358 else if (!strcmp (keyword
, "KEYPARAM"))
362 if (!keyparams
|| !*keyparams
)
363 return gpg_error (GPG_ERR_INV_PARAMETER
);
365 fd
= open (keyparams
, O_RDONLY
);
368 fprintf (stderr
, "%s: %s\n", keyparams
, strerror (errno
));
369 return gpg_error_from_syserror ();
372 rc
= set_inquire (fd
, NULL
, &inq
);
380 fprintf (stderr
, N_("Using file '%s' as %s.\n"), keyparams
, keyword
);
385 if ((is_password
&& !keyfile
) || (is_newpassword
&& !new_keyfile
)
386 || (sign
&& !sign_keyfile
))
391 /* Try to use the local pinentry between inquires (new/sign/passphrase).
392 * If --no-pinentry was specified then the passphrase is read from the
393 * terminal as usual. */
394 pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local
);
395 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, 1);
396 rc
= pwmd_password (pwm
, keyword
, &tmp
, &inq
->len
);
397 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local
);
398 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
401 pwmd_free (inq
->line
);
405 return gpg_error (GPG_ERR_EOF
);
407 else if ((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
408 || (sign
&& sign_keyfile
))
413 fd
= open (sign_keyfile
, O_RDONLY
);
415 fd
= open (is_password
|| sign
? keyfile
: new_keyfile
, O_RDONLY
);
420 fprintf (stderr
, "%s: %s\n", sign_keyfile
, strerror (errno
));
422 fprintf (stderr
, "%s: %s\n", is_newpassword
? new_keyfile
423 : keyfile
, strerror (errno
));
424 return gpg_error_from_syserror ();
427 rc
= set_inquire (fd
, NULL
, &inq
);
435 fprintf (stderr
, N_("Using keyfile '%s' as %s.\n"),
436 sign
? sign_keyfile
: is_newpassword
? new_keyfile
439 #ifdef HAVE_LIBREADLINE
440 else if ((!inq
->last_keyword
|| strcmp (keyword
, inq
->last_keyword
))
441 && interactive
&& inq
->fd
== STDIN_FILENO
)
445 ("%sPress CTRL-D to send the current line. Press twice to end. %s:\n"),
446 inq
->last_keyword
? "\n" : "", keyword
);
447 pwmd_free (inq
->last_keyword
);
448 inq
->last_keyword
= pwmd_strdup (keyword
);
452 /* The first part of the command data. */
458 return inq
->fd
== -1 ? gpg_error (GPG_ERR_EOF
) : 0;
461 *size
= read (inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
465 return gpg_error (gpg_error_from_syserror ());
469 else if (inq
->fd
!= STDIN_FILENO
&&
470 (is_newpassword
|| is_password
|| sign
|| is_keyparam
))
478 if (((is_newpassword
&& new_keyfile
) || (is_password
&& keyfile
)
479 || (sign
&& sign_keyfile
) || (keyparams
&& is_keyparam
))
480 && *size
== inq
->size
)
481 return gpg_error (GPG_ERR_EOF
);
483 return *size
? 0 : gpg_error (GPG_ERR_EOF
);
487 status_msg_cb (void *data
, const char *line
)
489 char *p
= strchr (line
, ' ');
494 /* Ignore status messages specified by the client via --status-ignore. */
495 for (s
= status_ignore
; s
&& *s
; s
++)
497 char *tmp
= strchr (line
, ' ');
498 size_t len
= tmp
? strlen (line
) - strlen (tmp
) : strlen (line
);
500 if (!strncmp (line
, *s
, len
) && len
== strlen (*s
))
504 #ifdef HAVE_LIBREADLINE
505 if (interactive
&& !strncmp (line
, "XFER ", 5)
507 if (!strncmp (line
, "XFER ", 5)
509 && *line
!= '#' && p
&& strchr (p
, ' ') && *++p
)
511 char *p1
= strchr (p
, ' ');
512 int a
= strtol (p
, NULL
, 10);
514 if (isdigit (*p
) && p1
)
516 int b
= strtol (p1
, NULL
, 10);
518 int t
= a
&& b
? a
* 100 / b
: 0;
520 strncpy (l
, line
, strlen (line
) - strlen (p
) - 1);
521 fprintf (statusfp
, "\rS:%s %i/%i %i%%%s", l
, a
, b
, t
,
528 fprintf (statusfp
, "S:%s\n", line
);
530 #ifdef HAVE_LIBREADLINE
539 return pwmd_process (pwm
);
542 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
544 is_remote_url (const char *str
)
547 return PWMD_SOCKET_LOCAL
;
550 if (strstr (str
, "ssh://") || strstr (str
, "ssh4://")
551 || strstr (str
, "ssh6://"))
552 return PWMD_SOCKET_SSH
;
556 if (strstr (str
, "tls://") || strstr (str
, "tls4://")
557 || strstr (str
, "tls6://"))
558 return PWMD_SOCKET_TLS
;
561 return PWMD_SOCKET_LOCAL
;
566 escape (const char *str
)
569 char *buf
= pwmd_malloc (ASSUAN_LINELENGTH
+ 1), *b
= buf
;
572 for (p
= str
; *p
; p
++, len
++)
574 if (len
== ASSUAN_LINELENGTH
)
618 free_inquire (struct inquire_s
*inq
)
623 pwmd_free (inq
->line
);
625 if (inq
->fd
!= -1 && inq
->fd
!= STDIN_FILENO
)
628 pwmd_free (inq
->last_keyword
);
632 /* When *result is not NULL it is updated to the new values and not
635 set_inquire (int fd
, const char *line
, struct inquire_s
**result
)
637 struct inquire_s inq
= { 0 };
638 struct stat st
= { 0 };
643 if (fstat (fd
, &st
) == -1)
644 return gpg_error_from_syserror ();
646 inq
.size
= st
.st_size
;
650 inq
.line
= pwmd_calloc (1, ASSUAN_LINELENGTH
);
652 return GPG_ERR_ENOMEM
;
656 char *s
= escape (line
);
660 pwmd_free (inq
.line
);
661 return GPG_ERR_ENOMEM
;
664 if (strlen (s
) >= ASSUAN_LINELENGTH
)
666 pwmd_free (inq
.line
);
668 return GPG_ERR_LINE_TOO_LONG
;
671 strncpy (inq
.line
, s
, ASSUAN_LINELENGTH
- 1);
672 inq
.len
= strlen (s
);
676 rc
= pwmd_setopt (pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
677 st
.st_size
? st
.st_size
+ strlen (inq
.line
) : 0);
680 pwmd_free (inq
.line
);
685 *result
= pwmd_malloc (sizeof (struct inquire_s
));
688 if ((*result
)->fd
!= -1 && (*result
)->fd
!= STDIN_FILENO
)
689 close ((*result
)->fd
);
691 pwmd_free ((*result
)->line
);
692 (*result
)->line
= NULL
;
697 memcpy (*result
, &inq
, sizeof (struct inquire_s
));
698 memset (&inq
, 0, sizeof (struct inquire_s
));
702 #ifdef HAVE_LIBREADLINE
704 interactive_hook (void)
706 interactive_error
= process_cmd ();
708 if (interactive_error
)
709 rl_event_hook
= NULL
;
715 get_readline_char (FILE *fp
)
718 && (!strncmp (rl_line_buffer
, ".set passphrase-file ", 16)
719 || !strncmp (rl_line_buffer
, ".set new-passphrase-file ", 20)
720 || !strncmp (rl_line_buffer
, ".set sign-passphrase-file ", 21)))
721 rl_inhibit_completion
= 0;
722 else if (rl_line_buffer
723 && !strncmp (rl_line_buffer
, ".redir ", 7))
725 char *p
= strchr (rl_line_buffer
, ' ');
727 if (p
&& strchr (++p
, ' '))
728 rl_inhibit_completion
= 1;
730 rl_inhibit_completion
= 0;
732 else if (rl_line_buffer
733 && !strncmp (rl_line_buffer
, ".read ", 6))
735 char *p
= rl_line_buffer
+ 6;
737 if (strstr (p
, "--prefix "))
739 p
= strstr (p
, "--prefix ");
746 if (!p
|| strchr (p
, ' '))
747 rl_inhibit_completion
= 1;
749 rl_inhibit_completion
= 0;
752 rl_inhibit_completion
= 1;
762 ("------------------------------------------------------------\n"
763 "Elements are TAB delimited. Type HELP for protocol commands.\n"
764 "Type .help for pwmc commands. Press CTRL-D to quit.\n"
765 "------------------------------------------------------------\n"));
770 parse_arg (const char *src
, char *dst
, size_t len
)
776 for (; s
&& *s
&& *s
!= ' ' && n
< len
; s
++, n
++)
784 parse_opt (char **line
, const char *opt
, gpg_error_t
* rc
)
786 static char result
[ASSUAN_LINELENGTH
] = { 0 }, *r
= result
;
787 char *s
= strstr (*line
, opt
);
797 size_t rlen
= strlen (opt
);
801 while (*p
&& *p
== ' ')
807 for (; *p
&& len
< sizeof (result
) - 1; p
++, rlen
++)
809 if (isspace (*p
) && !quote
)
812 if (*p
== '\"' && lastc
!= '\\')
825 if (len
>= sizeof (result
) - 1)
826 *rc
= GPG_ERR_LINE_TOO_LONG
;
831 while (*p
&& *p
== ' ')
842 read_command (const char *line
, char **result
, size_t * len
)
847 struct inquire_s
*inq
= NULL
;
848 char *p
= (char *) line
;
849 const char *prefix
= parse_opt (&p
, "--prefix", &rc
);
850 char filebuf
[ASSUAN_LINELENGTH
];
859 while (*p
&& isspace (*p
))
862 file
= parse_arg (p
, filebuf
, sizeof (filebuf
));
865 p
+= strlen (file
) + 1;
867 while (*p
&& isspace (*p
))
879 ("Usage: .read [--prefix <string>] <filename> <command> [args]\n"));
882 ("Use '\\' to escape special characters in the --prefix (\\t = TAB, \\\\ = \\)\n"));
886 fd
= open (file
, O_RDONLY
);
888 return gpg_error_from_syserror ();
890 rc
= set_inquire (fd
, prefix
&& *prefix
? prefix
: NULL
, &inq
);
897 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", p
);
903 redir_command (const char *line
)
905 const char *p
= line
;
907 gpg_error_t rc
= GPG_ERR_SYNTAX
;
909 struct inquire_s
*inq
= NULL
;
912 char filebuf
[ASSUAN_LINELENGTH
];
916 file
= parse_arg (p
, filebuf
, sizeof (filebuf
));
919 p
+= strlen (file
) + 1;
921 while (*p
&& isspace (*p
))
931 fprintf (stderr
, N_("Usage: .redir <filename> <command> [args]\n"));
935 fd
= open (file
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
937 return gpg_error_from_syserror ();
939 #ifdef HAVE_LIBREADLINE
940 rc
= set_inquire (interactive
? STDIN_FILENO
: inquirefd
, NULL
, &inq
);
942 rc
= set_inquire (inquirefd
, NULL
, &inq
);
950 rc
= parse_dotcommand (p
, &result
, &len
, inq
);
951 if (!rc
&& result
&& len
--)
952 { // null byte which is always appended
953 if (write (fd
, result
, len
) != len
)
954 rc
= GPG_ERR_TOO_SHORT
;
964 help_command (const char *line
)
968 N_("Type HELP for protocol commands. Available pwmc commands:\n\n"
969 " .redir <filename> <command>\n"
970 " redirect the output of a command to the specified file\n"
972 " .open <filename>\n"
973 " open the specified filename losing any changes to the current one\n"
975 " .read [--prefix <string>] <filename> <command> [args]\n"
976 " obtain data from the specified filename for an inquire command\n"
978 " .set help | <name> [<value>]\n"
979 " set option <name> to <value>\n"
982 " generate a new key\n"
985 " write changes of the file to disk\n"
988 " change the passphrase of a data file\n"
990 " .listkeys [--options] [pattern[,..]]\n"
991 " show human readable output of the LISTKEYS command\n"
994 " this help text\n"));
999 open_command (char *line
)
1001 struct inquire_s
*inq
= NULL
;
1006 while (file
&& isspace (*file
))
1011 char *p
= strrchr (file
, ' ');
1015 while (isspace (*p
))
1018 file
= pwmd_strdup (file
+ (strlen (file
)-strlen (p
)));
1022 if (!file
|| !*file
)
1025 fprintf (stderr
, N_("Usage: .open <filename>\n"));
1026 return GPG_ERR_SYNTAX
;
1029 #ifdef HAVE_LIBREADLINE
1030 if (interactive
|| !quiet
)
1034 fprintf (stderr
, N_("Opening data file \"%s\" ...\n"), file
);
1036 #ifdef HAVE_LIBREADLINE
1037 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1039 rc
= set_inquire (-1, NULL
, &inq
);
1047 pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local
);
1051 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1053 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, 1);
1056 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1059 rc
= pwmd_open (pwm
, file
, inquire_cb
, inq
);
1061 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local
);
1063 #ifdef HAVE_LIBREADLINE
1069 if (!rc
&& file
!= filename
)
1071 pwmd_free (filename
);
1076 pwmd_free (filename
);
1084 set_command (const char *line
)
1087 char name
[256] = { 0 };
1088 char value
[512] = { 0 };
1091 const char *p
= line
;
1093 while (p
&& *p
&& isspace (*p
))
1096 namep
= parse_arg (p
, name
, sizeof (name
));
1097 if (!namep
|| !*namep
)
1099 fprintf (stderr
, N_("Usage: .set help | <name> [<value>]\n"));
1100 return GPG_ERR_SYNTAX
;
1103 p
+= strlen (namep
);
1104 while (p
&& *p
&& isspace (*p
))
1107 valuep
= parse_arg (p
, value
, sizeof (value
));
1109 if (!strcmp (name
, "passphrase-file") || !strcmp (name
, "new-passphrase-file")
1110 || !strcmp (name
, "sign-passphrase-file"))
1112 int is_newkeyfile
= 1;
1113 int sign
= !strcmp (name
, "sign-passphrase-file");
1115 if (!strcmp (name
, "passphrase-file") || sign
)
1120 pwmd_free (new_keyfile
);
1125 pwmd_free (sign_keyfile
);
1126 sign_keyfile
= NULL
;
1130 pwmd_free (keyfile
);
1137 new_keyfile
= pwmd_strdup (value
);
1139 sign_keyfile
= pwmd_strdup (value
);
1141 keyfile
= pwmd_strdup (value
);
1143 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1145 else if (!local_pin
&& !no_pinentry
)
1149 pwmd_socket_type (pwm
, &t
);
1150 if (t
== PWMD_SOCKET_LOCAL
)
1151 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1154 else if (!strcmp(name
, "pinentry-timeout"))
1157 int n
= strtol(valuep
, &e
, 10);
1160 return gpg_error (GPG_ERR_INV_VALUE
);
1163 n
= DEFAULT_PIN_TIMEOUT
;
1165 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, n
);
1167 else if (!strcmp (name
, "help"))
1171 ("Set a libpwmd or pwmc option. The option name and optional value is space\n"
1172 "delimited. When no value is specified the option is unset.\n\n"
1173 "passphrase-file [<filename>]\n"
1174 " set or unset the file to be used when a passphrase is required (*)\n"
1176 "new-passphrase-file [<filename>]\n"
1177 " set or unset the file to be used when a new passphrase is required (*)\n"
1179 "sign-passphrase-file [<filename>]\n"
1180 " set or unset the file to be used when a passphrase is required for\n"
1181 " signing (symmetric) (*)\n"
1183 "pinentry-timeout <seconds>\n"
1184 " the amount of seconds before pinentry gives up waiting for input\n"
1186 "* = the next protocol command will unset this value\n"
1190 rc
= GPG_ERR_UNKNOWN_OPTION
;
1196 do_save_passwd_command (const char *line
, int which
)
1198 struct inquire_s
*inq
= NULL
;
1202 #ifdef HAVE_LIBREADLINE
1203 rc
= set_inquire (interactive
? STDIN_FILENO
: -1, NULL
, &inq
);
1205 rc
= set_inquire (-1, NULL
, &inq
);
1210 pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local
);
1212 if (new_keyfile
|| keyfile
|| sign_keyfile
)
1214 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 1);
1216 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, 1);
1219 rc
= pwmd_setopt (pwm
, PWMD_OPTION_OVERRIDE_INQUIRE
, 0);
1223 if (which
== SAVE_WHICH_SAVE
)
1224 rc
= pwmd_save (pwm
, line
, inquire_cb
, inq
);
1225 else if (which
== SAVE_WHICH_PASSWD
)
1226 rc
= pwmd_passwd (pwm
, line
, inquire_cb
, inq
);
1228 rc
= pwmd_genkey (pwm
, line
, inquire_cb
, inq
);
1231 pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local
);
1233 #ifdef HAVE_LIBREADLINE
1243 save_command (const char *line
)
1245 return do_save_passwd_command (line
, SAVE_WHICH_SAVE
);
1249 search_and_replace (char *str
, const char *s
, const char r
)
1253 p
= strstr (str
, s
);
1259 search_and_replace (str
, s
, r
);
1265 openpgp_unescape (char *str
)
1267 search_and_replace (str
, "\\x3a", ':');
1268 search_and_replace (str
, "\\x5c", '\\');
1273 free_listkeys (struct slist_s
*keys
)
1277 t
= slist_length (keys
);
1278 for (i
= 0; i
< t
; i
++)
1280 struct keyid_s
*key
= slist_nth_data (keys
, i
);
1283 nt
= slist_length (key
->userids
);
1284 for (n
= 0; n
< nt
; n
++)
1286 struct userid_s
*userid
= slist_nth_data (key
->userids
, n
);
1288 pwmd_free (userid
->userid
);
1289 pwmd_free (userid
->name
);
1290 pwmd_free (userid
->email
);
1291 pwmd_free (userid
->comment
);
1295 slist_free (key
->userids
);
1296 nt
= slist_length (key
->subkeys
);
1297 for (n
= 0; n
< nt
; n
++)
1299 struct keyid_s
*sub
= slist_nth_data (key
->subkeys
, n
);
1301 pwmd_free (sub
->keyid
);
1302 pwmd_free (sub
->fpr
);
1303 pwmd_free (sub
->grip
);
1304 pwmd_free (sub
->card
);
1305 pwmd_free (sub
->curve
);
1309 slist_free (key
->subkeys
);
1317 openpgp_algorithm (struct keyid_s
*key
)
1338 return N_("Unknown");
1342 display_listkeys (struct slist_s
*keys
)
1346 t
= slist_length (keys
);
1347 for (i
= 0; i
< t
; i
++)
1349 struct keyid_s
*key
= slist_nth_data (keys
, i
);
1350 unsigned st
= slist_length (key
->subkeys
);
1352 unsigned ut
= slist_length (key
->userids
);
1355 for (u
= 0; u
< ut
; u
++)
1357 struct userid_s
*userid
= slist_nth_data (key
->userids
, u
);
1359 fprintf(stdout
, N_("User ID: %s\n"), userid
->userid
);
1362 for (s
= 0; s
< st
; s
++)
1364 struct keyid_s
*sub
= slist_nth_data (key
->subkeys
, s
);
1366 const char *caps
= NULL
;
1367 char expires
[11] = { 0 };
1368 char created
[11] = { 0 };
1372 tmp
= localtime (&sub
->expires
);
1373 strftime (expires
, sizeof (expires
), "%F", tmp
);
1376 tmp
= localtime (&sub
->created
);
1377 strftime (created
, sizeof (created
), "%F", tmp
);
1379 if (sub
->can_encrypt
)
1381 else if (sub
->can_sign
)
1383 else if (sub
->can_auth
)
1385 else if (sub
->can_certify
)
1389 " Subkey %u: %s [%s]%s%s %s-%u%s%s\n"
1390 " Created: %s %s%s\n"
1391 " Fingerprint: %s\n"
1397 sub
->secret
|| sub
->card
? "[P]" : "",
1398 sub
->revoked
? "[R]" : "",
1399 openpgp_algorithm (sub
),
1401 sub
->curve
? "-" : "",
1402 sub
->curve
? sub
->curve
: "",
1404 sub
->expired
? N_("Expired: ") : expires
[0] ? N_("Expires: ") : "",
1405 sub
->expired
|| expires
[0] ? expires
: "",
1408 sub
->card
? N_(" Card: ") : "",
1409 sub
->card
? sub
->card
: "",
1410 sub
->card
? "\n" : "");
1414 fprintf (stdout
, "\n");
1419 listkeys_command (const char *pattern
)
1423 char **lines
= NULL
, **p
;
1424 struct slist_s
*keys
= NULL
;
1426 rc
= pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
, "LISTKEYS %s", pattern
);
1430 lines
= str_split (result
, "\n", 0);
1433 return GPG_ERR_ENOMEM
;
1435 for (p
= lines
; *p
; p
++)
1437 struct keyid_s
*key
;
1438 char **fields
= str_split (*p
, ":", 0);
1441 unsigned n_subkeys
= 0;
1442 struct slist_s
*tlist
;
1446 rc
= GPG_ERR_ENOMEM
;
1450 key
= pwmd_calloc (1, sizeof (struct keyid_s
));
1454 rc
= GPG_ERR_ENOMEM
;
1458 for (f
= i
= 0; i
< 17; i
++, f
++)
1463 b
= atoi (fields
[f
]) != 0;
1467 case 0: key
->revoked
= b
; break;
1468 case 1: key
->expired
= b
; break;
1469 case 4: key
->can_encrypt
= b
; break;
1470 case 5: key
->can_sign
= b
; break;
1471 case 7: key
->secret
= b
; break;
1472 case 16: n_subkeys
= strtoul (fields
[f
], NULL
, 10); break;
1478 for (s
= 0; s
< n_subkeys
; s
++)
1480 struct keyid_s
*sub
;
1483 sub
= pwmd_calloc (1, sizeof (struct keyid_s
));
1487 rc
= GPG_ERR_ENOMEM
;
1491 for (i
= 0; i
< 20; i
++, f
++)
1494 b
= atoi (fields
[f
]) != 0;
1498 case 0: sub
->revoked
= b
; break;
1499 case 1: sub
->expired
= b
; break;
1500 case 4: sub
->can_encrypt
= b
; break;
1501 case 5: sub
->can_sign
= b
; break;
1502 case 6: sub
->can_certify
= b
; break;
1503 case 7: sub
->secret
= b
; break;
1504 case 8: sub
->can_auth
= b
; break;
1505 case 11: sub
->algo
= atoi (fields
[f
]); break;
1506 case 12: sub
->bits
= atoi (fields
[f
]); break;
1507 case 13: sub
->keyid
= pwmd_strdup (fields
[f
]); break;
1508 case 14: sub
->fpr
= pwmd_strdup (fields
[f
]); break;
1509 case 15: sub
->grip
= pwmd_strdup (fields
[f
]); break;
1510 case 16: sub
->created
= strtoul (fields
[f
], NULL
, 10); break;
1511 case 17: sub
->expires
= strtoul (fields
[f
], NULL
, 10); break;
1512 case 18: sub
->card
= fields
[f
] && strlen(fields
[f
]) > 1
1513 ? pwmd_strdup (fields
[f
]) : NULL
; break;
1514 case 19: sub
->curve
= strlen (fields
[f
]) > 1 ? pwmd_strdup (openpgp_unescape(fields
[f
])) : NULL
; break;
1520 tlist
= slist_append (key
->subkeys
, sub
);
1523 rc
= GPG_ERR_ENOMEM
;
1527 key
->subkeys
= tlist
;
1536 // Re-create a line containing the userIds.
1537 for (; f
< strv_length (fields
); f
++)
1539 struct userid_s
*userid
;
1541 userid
= pwmd_calloc (1, sizeof (struct userid_s
));
1544 rc
= GPG_ERR_ENOMEM
;
1555 userid
->userid
= pwmd_strdup (openpgp_unescape (fields
[f
++]));
1556 userid
->name
= pwmd_strdup (openpgp_unescape (fields
[f
++]));
1557 userid
->email
= pwmd_strdup (openpgp_unescape (fields
[f
++]));
1558 userid
->comment
= pwmd_strdup (openpgp_unescape (fields
[f
]));
1560 tlist
= slist_append (key
->userids
, userid
);
1563 rc
= GPG_ERR_ENOMEM
;
1567 key
->userids
= tlist
;
1574 tlist
= slist_append (keys
, key
);
1577 rc
= GPG_ERR_ENOMEM
;
1587 display_listkeys (keys
);
1589 free_listkeys (keys
);
1594 parse_dotcommand (const char *line
, char **result
,
1595 size_t * len
, struct inquire_s
*inq
)
1597 const char *p
= line
;
1600 if (!strncmp (p
, ".read", 5))
1601 rc
= read_command (p
+ 5, result
, len
);
1602 else if (!strncmp (p
, ".redir", 6))
1603 rc
= redir_command (p
+ 6);
1604 else if (!strncmp (p
, ".help", 5))
1605 rc
= help_command (p
+ 5);
1606 else if (!strncmp (p
, ".open", 5))
1607 rc
= open_command ((char *)p
+ 5);
1608 else if (!strncmp (p
, ".set", 4))
1609 rc
= set_command (p
+ 4);
1610 else if (!strncmp (p
, ".save", 5))
1611 rc
= do_save_passwd_command (p
+ 5, SAVE_WHICH_SAVE
);
1612 else if (!strncmp (p
, ".passwd", 7))
1613 rc
= do_save_passwd_command (p
+ 7, SAVE_WHICH_PASSWD
);
1614 else if (!strncmp (p
, ".genkey", 7))
1615 rc
= do_save_passwd_command (p
+ 7, SAVE_WHICH_GENKEY
);
1616 else if (!strncmp (p
, ".listkeys", 9))
1617 rc
= listkeys_command (p
+9);
1620 rc
= pwmd_command (pwm
, result
, len
, inquire_cb
, inq
, "%s", line
);
1621 #ifdef HAVE_LIBREADLINE
1626 #ifdef HAVE_LIBREADLINE
1630 if (!rc
&& !strncasecmp (line
, "RESET", 5))
1632 pwmd_free (filename
);
1640 #ifdef HAVE_LIBREADLINE
1641 #ifdef HAVE_READLINE_HISTORY
1643 add_history_item (const char *line
)
1645 HIST_ENTRY
**list
, *p
= NULL
;
1648 list
= history_list ();
1649 for (i
= 0; list
&& list
[i
]; i
++)
1651 if (!strcmp (list
[i
]->line
, line
))
1662 p
= remove_history (i
);
1663 #ifdef HAVE_FREE_HISTORY_ENTRY
1664 s
= free_history_entry (p
);
1677 struct inquire_s
*inq
= NULL
;
1680 rc
= process_cmd ();
1684 rc
= set_inquire (STDIN_FILENO
, NULL
, &inq
);
1689 N_("WARNING: interactive mode doesn't use secure memory!\n"));
1691 rl_event_hook
= &interactive_hook
;
1692 rl_getc_function
= get_readline_char
;
1693 rl_set_keyboard_input_timeout (100000);
1698 char *result
= NULL
;
1703 snprintf (buf
, sizeof (buf
), "pwmc%s%s> ",
1704 filename
? ":" : "", filename
? filename
: "");
1705 line
= readline (buf
);
1706 if (interactive_error
)
1709 rc
= interactive_error
;
1719 if (gpg_err_code (rc
) != GPG_ERR_CANCELED
&&
1720 gpg_err_code (rc
) != GPG_ERR_EOF
)
1721 fprintf (stderr
, "ERR %i: %s\n", rc
, gpg_strerror (rc
));
1731 #ifdef HAVE_READLINE_HISTORY
1732 add_history_item (line
);
1734 rc
= parse_dotcommand (line
, &result
, &len
, inq
);
1740 if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
1741 (void) pwmd_command (pwm
, &tmp
, NULL
, NULL
, NULL
,
1742 "GETINFO last_error");
1744 show_error (pwm
, rc
, tmp
);
1747 else if (result
&& len
)
1748 printf ("%s%s", result
, result
[len
- 1] != '\n' ? "\n" : "");
1762 #ifdef HAVE_LIBREADLINE
1769 fprintf (stderr
, "\n");
1777 ("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
1778 p
= fgets (buf
, sizeof (buf
), stdin
);
1792 return GPG_ERR_CANCELED
;
1796 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1797 "CLEARCACHE %s", filename
);
1801 interactive_hook ();
1817 if (save
&& !filename
)
1821 ("No filename was specified on the command line. Aborting.\n"));
1822 return GPG_ERR_CANCELED
;
1825 if (save
&& filename
)
1828 pwmd_strdup_printf ("%s %s%s %s%s %s",
1829 symmetric
? "--symmetric" : "",
1830 keyid
? "--keyid=" : "",
1832 sign_keyid
? "--sign-keyid=" : "",
1833 sign_keyid
? sign_keyid
: "",
1834 keyparams
? "--inquire-keyparam" : "");
1836 #ifdef HAVE_LIBREADLINE
1837 if (!quiet
|| interactive
)
1843 fprintf (stderr
, "\n");
1844 fprintf (stderr
, N_("Saving changes ...\n"));
1847 rc
= save_command (args
);
1851 #ifdef HAVE_LIBREADLINE
1853 return rc
? rc
: quit
? 0 : GPG_ERR_CANCELED
;
1860 parse_status_ignore (char *str
)
1865 for (p
= status_ignore
; p
&& *p
; p
++)
1868 pwmd_free (status_ignore
);
1869 status_ignore
= NULL
;
1873 while ((s
= strsep (&str
, ",")))
1875 p
= pwmd_realloc (status_ignore
, (n
+ 2) * sizeof (char *));
1876 p
[n
++] = pwmd_strdup (s
);
1883 main (int argc
, char *argv
[])
1886 int status_state
= 0;
1889 char command
[ASSUAN_LINELENGTH
], *p
= NULL
;
1890 char *result
= NULL
;
1892 char *pinentry_path
= NULL
;
1893 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
;
1894 char *lcctype
= NULL
, *lcmessages
= NULL
;
1895 int outfd
= STDOUT_FILENO
;
1896 FILE *outfp
= stdout
;
1897 FILE *inquirefp
= stdin
;
1898 int show_status
= 1;
1899 const char *clientname
= "pwmc";
1900 char *inquire
= NULL
;
1901 char *inquire_line
= NULL
;
1904 int use_ssh_agent
= -1;
1905 char *knownhosts
= NULL
;
1906 char *identity
= NULL
;
1907 int needs_passphrase
= 0;
1908 char *ssh_passphrase_file
= NULL
;
1911 char *cacert
= NULL
;
1912 char *clientcert
= NULL
;
1913 char *clientkey
= NULL
;
1915 int tls_verify
= -1;
1916 char *tls_fingerprint
= NULL
;
1918 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1919 pwmd_socket_t socktype
;
1920 long socket_timeout
= 300;
1921 int connect_timeout
= 120;
1923 #ifdef HAVE_LIBREADLINE
1924 int no_interactive
= 0;
1926 int lock_on_open
= -1;
1927 long lock_timeout
= 50;
1930 /* The order is important. */
1933 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1934 OPT_SOCKET_TIMEOUT
, OPT_CONNECT_TIMEOUT
,
1937 OPT_USE_SSH_AGENT
, OPT_IDENTITY
, OPT_KNOWNHOSTS
, OPT_SSH_NEEDS_PASSPHRASE
,
1938 OPT_SSH_PASSPHRASE_FILE
,
1941 OPT_CACERT
, OPT_CLIENTCERT
, OPT_CLIENTKEY
, OPT_PRIORITY
, OPT_VERIFY
,
1944 OPT_URL
, OPT_LOCAL
, OPT_TTYNAME
, OPT_TTYTYPE
, OPT_DISPLAY
, OPT_LC_CTYPE
,
1945 OPT_LC_MESSAGES
, OPT_TIMEOUT
, OPT_TRIES
, OPT_PINENTRY
, OPT_KEYFILE
,
1946 OPT_PASSPHRASE_FILE
, OPT_NEW_KEYFILE
, OPT_NEW_PASSPHRASE_FILE
,
1947 OPT_SIGN_KEYFILE
, OPT_SIGN_PASSPHRASE_FILE
, OPT_NOLOCK
, OPT_LOCK_TIMEOUT
,
1948 OPT_SAVE
, OPT_OUTPUT_FD
, OPT_INQUIRE
, OPT_INQUIRE_FD
, OPT_INQUIRE_FILE
,
1949 OPT_INQUIRE_LINE
, OPT_NO_STATUS
, OPT_STATUS_IGNORE
, OPT_STATUSFD
, OPT_NAME
,
1950 OPT_VERSION
, OPT_HELP
, OPT_KEYID
, OPT_SIGN_KEYID
, OPT_SYMMETRIC
,
1951 OPT_KEYPARAMS
, OPT_NO_PINENTRY
, OPT_QUIET
, OPT_STATUS_STATE
,
1952 #ifdef HAVE_LIBREADLINE
1956 const struct option long_opts
[] = {
1957 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1958 {"socket-timeout", 1, 0, 0},
1959 {"connect-timeout", 1, 0, 0},
1963 {"no-ssh-agent", 0, 0, 0},
1964 {"identity", 1, 0, 'i'},
1965 {"knownhosts", 1, 0, 'k'},
1966 {"ssh-needs-passphrase", 0, 0, 0},
1967 {"ssh-passphrase-file", 1, 0, 0},
1970 {"ca-cert", 1, 0, 0},
1971 {"client-cert", 1, 0, 0},
1972 {"client-key", 1, 0, 0},
1973 {"tls-priority", 1, 0, 0},
1974 {"no-tls-verify", 0, 0, 0},
1975 {"tls-fingerprint", 1, 0, 0},
1978 {"local-pinentry", 0, 0},
1979 {"ttyname", 1, 0, 'y'},
1980 {"ttytype", 1, 0, 't'},
1981 {"display", 1, 0, 'd'},
1982 {"lc-ctype", 1, 0, 0},
1983 {"lc-messages", 1, 0, 0},
1984 {"timeout", 1, 0, 0},
1986 {"pinentry", 1, 0, 0},
1987 {"key-file", 1, 0, 0},
1988 {"passphrase-file", 1, 0, 0},
1989 {"new-key-file", 1, 0, 0},
1990 {"new-passphrase-file", 1, 0, 0},
1991 {"sign-key-file", 1, 0, 0},
1992 {"sign-passphrase-file", 1, 0, 0},
1993 {"no-lock", 0, 0, 0},
1994 {"lock-timeout", 1, 0, 0},
1995 {"save", 0, 0, 'S'},
1996 {"output-fd", 1, 0, 0},
1997 {"inquire", 1, 0, 0},
1998 {"inquire-fd", 1, 0, 0},
1999 {"inquire-file", 1, 0, 0},
2000 {"inquire-line", 1, 0, 'L'},
2001 {"no-status", 0, 0, 0},
2002 {"status-ignore", 1, 0, 0},
2003 {"status-fd", 1, 0, 0},
2004 {"name", 1, 0, 'n'},
2005 {"version", 0, 0, 0},
2008 {"sign-keyid", 1, 0, 0},
2009 {"symmetric", 0, 0, 0},
2010 {"key-params", 1, 0, 0},
2011 {"no-pinentry", 0, 0, 0},
2013 {"status-state", 0, 0, 0},
2014 #ifdef HAVE_LIBREADLINE
2015 {"no-interactive", 0, 0},
2020 const char *optstring
= "L:y:t:d:P:I:Sn:i:k:s";
2022 const char *optstring
= "L:y:t:d:P:I:Sn:s";
2027 setlocale (LC_ALL
, "");
2028 bindtextdomain ("libpwmd", LOCALEDIR
);
2031 tries
= DEFAULT_PIN_TRIES
;
2032 inquirefd
= STDIN_FILENO
;
2033 statusfd
= STDERR_FILENO
;
2035 tmp
= pwmd_strdup (DEFAULT_STATUS_IGNORE
);
2036 parse_status_ignore (tmp
);
2042 getopt_long (argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1)
2046 /* Handle long options without a short option part. */
2050 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2051 case OPT_SOCKET_TIMEOUT
:
2052 socket_timeout
= strtol (optarg
, &p
, 10);
2054 case OPT_CONNECT_TIMEOUT
:
2055 connect_timeout
= strtol (optarg
, &p
, 10);
2059 case OPT_USE_SSH_AGENT
:
2062 case OPT_SSH_NEEDS_PASSPHRASE
:
2063 needs_passphrase
= 1;
2065 case OPT_SSH_PASSPHRASE_FILE
:
2066 ssh_passphrase_file
= optarg
;
2073 case OPT_CLIENTCERT
:
2074 clientcert
= optarg
;
2086 tls_fingerprint
= optarg
;
2096 case OPT_PASSPHRASE_FILE
:
2097 keyfile
= pwmd_strdup (optarg
);
2099 case OPT_NEW_KEYFILE
:
2100 case OPT_NEW_PASSPHRASE_FILE
:
2101 new_keyfile
= pwmd_strdup (optarg
);
2103 case OPT_SIGN_KEYFILE
:
2104 case OPT_SIGN_PASSPHRASE_FILE
:
2105 sign_keyfile
= pwmd_strdup (optarg
);
2110 case OPT_LOCK_TIMEOUT
:
2111 lock_timeout
= strtol (optarg
, &p
, 10);
2120 lcctype
= pwmd_strdup (optarg
);
2122 case OPT_LC_MESSAGES
:
2123 lcmessages
= pwmd_strdup (optarg
);
2126 timeout
= strtol (optarg
, &p
, 10);
2129 tries
= strtol (optarg
, &p
, 10);
2132 inquire
= escape (optarg
);
2134 case OPT_INQUIRE_FD
:
2135 inquirefd
= strtol (optarg
, &p
, 10);
2138 inquirefp
= fdopen (inquirefd
, "r");
2140 err (EXIT_FAILURE
, "%i", inquirefd
);
2143 case OPT_INQUIRE_FILE
:
2144 inquirefd
= open (optarg
, O_RDONLY
);
2145 if (inquirefd
== -1)
2146 err (EXIT_FAILURE
, "%s", optarg
);
2147 inquirefp
= fdopen (inquirefd
, "r");
2150 outfd
= strtol (optarg
, &p
, 10);
2153 outfp
= fdopen (outfd
, "w");
2155 err (EXIT_FAILURE
, "%i", outfd
);
2162 statusfd
= strtol (optarg
, &p
, 10);
2165 statusfp
= fdopen (statusfd
, "w");
2167 err (EXIT_FAILURE
, "%i", statusfd
);
2170 case OPT_STATUS_IGNORE
:
2171 parse_status_ignore (optarg
);
2174 printf ("%s (pwmc)\n\n"
2175 "Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016\n"
2177 "Released under the terms of the LGPL v2.1. Use at your own risk.\n\n"
2178 "Compile-time features:\n"
2179 #ifdef HAVE_LIBREADLINE
2194 #ifdef WITH_PINENTRY
2209 "\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
2210 exit (EXIT_SUCCESS
);
2212 pinentry_path
= optarg
;
2215 usage (argv
[0], EXIT_SUCCESS
);
2219 case OPT_SIGN_KEYID
:
2220 sign_keyid
= optarg
;
2226 case OPT_STATUS_STATE
:
2229 case OPT_NO_PINENTRY
:
2232 #ifdef HAVE_LIBREADLINE
2233 case OPT_NO_INTERACTIVE
:
2238 usage (argv
[0], EXIT_FAILURE
);
2243 fprintf (stderr
, N_("%s: invalid argument for option '--%s'\n"),
2244 argv
[0], long_opts
[opt_index
].name
);
2245 usage (argv
[0], EXIT_FAILURE
);
2254 knownhosts
= optarg
;
2258 inquire_line
= optarg
;
2273 clientname
= optarg
;
2276 usage (argv
[0], EXIT_FAILURE
);
2280 #ifdef HAVE_LIBREADLINE
2281 if (isatty (STDIN_FILENO
) && !inquire
&& !inquire_line
&& !no_interactive
)
2286 rc
= pwmd_new (clientname
, &pwm
);
2290 filename
= argv
[optind
] ? pwmd_strdup (argv
[optind
]) : NULL
;
2291 if (no_pinentry
!= -1)
2292 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, no_pinentry
);
2294 rc
= pwmd_getopt (pwm
, PWMD_OPTION_NO_PINENTRY
, &no_pinentry
);
2298 if (local_pin
!= -1)
2299 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, local_pin
);
2301 rc
= pwmd_getopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, &local_pin
);
2305 pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
2307 fprintf (stderr
, N_("Connecting ...\n"));
2309 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2310 socktype
= is_remote_url (url
);
2311 if (socktype
!= PWMD_SOCKET_LOCAL
)
2314 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2315 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, connect_timeout
);
2320 if (socktype
== PWMD_SOCKET_SSH
)
2323 if (use_ssh_agent
== -1)
2324 rc
= pwmd_getopt (pwm
, PWMD_OPTION_SSH_AGENT
, &use_ssh_agent
);
2328 if (!getenv ("SSH_AUTH_SOCK") || identity
)
2331 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, use_ssh_agent
);
2338 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_NEEDS_PASSPHRASE
,
2343 if (ssh_passphrase_file
)
2348 if (stat (ssh_passphrase_file
, &st
) == -1)
2350 rc
= gpg_error_from_syserror ();
2351 fprintf(stderr
, "%s: %s\n", ssh_passphrase_file
,
2356 result
= pwmd_calloc (1, st
.st_size
+1);
2359 rc
= GPG_ERR_ENOMEM
;
2363 fd
= open (ssh_passphrase_file
, O_RDONLY
);
2366 len
= read (fd
, result
, st
.st_size
);
2367 if (len
== st
.st_size
)
2368 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_PASSPHRASE
, result
);
2370 rc
= gpg_error_from_syserror ();
2375 rc
= gpg_error_from_syserror ();
2383 fprintf(stderr
, "%s: %s\n", ssh_passphrase_file
,
2389 rc
= pwmd_connect (pwm
, url
, identity
, knownhosts
);
2395 if (tls_verify
!= -1)
2397 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, tls_verify
);
2403 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_PRIORITY
, prio
);
2406 rc
= pwmd_connect (pwm
, url
, clientcert
, clientkey
, cacert
,
2412 rc
= pwmd_connect (pwm
, url
);
2414 rc
= pwmd_connect (pwm
, url
);
2420 fprintf (stderr
, N_("Connected.\n"));
2423 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
2424 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, socket_timeout
);
2431 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
2432 "OPTION LOCK-TIMEOUT=%li", lock_timeout
);
2439 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION CLIENT-STATE=1");
2444 if (lock_on_open
!= -1)
2446 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, lock_on_open
);
2451 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DESC
, NULL
, NULL
);
2457 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
2464 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
2471 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
2478 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
2485 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
2492 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
2499 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, lcmessages
);
2506 rc
= pwmd_setopt (pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
2513 rc
= open_command (filename
);
2518 #ifdef HAVE_LIBREADLINE
2521 rc
= do_interactive ();
2529 struct inquire_s
*inq
= NULL
;
2531 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2533 rc
= pwmd_command (pwm
, &result
, &len
, inquire_cb
, inq
, "%s", inquire
);
2539 if (fcntl (STDIN_FILENO
, F_SETFL
, O_NONBLOCK
) == -1)
2541 rc
= gpg_error_from_errno (errno
);
2549 rc
= process_cmd ();
2554 n
= read (STDIN_FILENO
, command
, sizeof (command
)-1);
2557 if (errno
== EAGAIN
)
2563 rc
= gpg_error_from_errno (errno
);
2574 if (!p
|| !*p
|| !strcasecmp (p
, "BYE"))
2578 struct inquire_s
*inq
= NULL
;
2579 rc
= set_inquire (inquirefd
, inquire_line
, &inq
);
2582 rc
= parse_dotcommand (command
, &result
, &len
, inq
);
2592 fwrite (result
, 1, result
[len
- 1] == 0 ? len
- 1 : len
, outfp
);
2600 else if (gpg_err_code (rc
) == GPG_ERR_BAD_DATA
)
2601 (void) pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
,
2602 "GETINFO last_error");
2604 #ifdef HAVE_LIBREADLINE
2607 wipememory (command
, 0, sizeof (command
));
2610 show_error (pwm
, rc
, result
);
2616 pwmd_free (filename
);
2617 parse_status_ignore (NULL
);
2618 if (connected
&& !quiet
)
2619 fprintf (stderr
, N_("Connection closed.\n"));
2621 exit (rc
? EXIT_FAILURE
: EXIT_SUCCESS
);