1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2007-2010 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
31 #include <sys/select.h>
33 #include <sys/types.h>
43 #ifdef HAVE_GETOPT_LONG
48 #include "getopt_long.h"
51 #ifdef HAVE_LIBREADLINE
52 # if defined(HAVE_READLINE_READLINE_H)
53 # include <readline/readline.h>
54 # elif defined(HAVE_READLINE_H)
55 # include <readline.h>
56 # endif /* !defined(HAVE_READLINE_H) */
57 static int interactive_error
;
58 static int interactive
;
59 #endif /* HAVE_LIBREADLINE */
61 #ifdef HAVE_READLINE_HISTORY
62 # if defined(HAVE_READLINE_HISTORY_H)
63 # include <readline/history.h>
64 # elif defined(HAVE_HISTORY_H)
67 #endif /* HAVE_READLINE_HISTORY */
70 #define N_(msgid) gettext(msgid)
74 #define DEFAULT_PORT 22
76 static int in_keyfile
;
77 static int no_pinentry
;
79 static char *filename
;
82 static int force_save
;
85 static char *password
;
100 static gpg_error_t
finalize();
102 static void show_error(gpg_error_t error
)
104 fprintf(stderr
, "ERR %i %s\n", gpg_err_code(error
), pwmd_strerror(error
));
107 static void usage(const char *pn
, int status
)
109 fprintf(status
== EXIT_FAILURE
? stderr
: stdout
, N_(
110 "Read a PWMD protocol command from standard input.\n\n"
111 "Usage: pwmc [options] [file]\n"
114 " pinentry method (0=pwmd, 1=libpwmd, 2=pwmd async, "
119 " --host, -h <hostname>\n"
120 " connect to the specified hostname\n"
123 " alterate port (22)\n"
125 " --user <username>\n"
126 " SSH username (default is the invoking user)\n"
129 " use the SSH agent for authentication\n"
131 " --identity, -i <filename>\n"
132 " SSH identity file (if not using the SSH agent)\n"
134 " --known-hosts, -k <filename>\n"
135 " known hosts file (~/.ssh/known_hosts)\n"
137 " --get-hostkey, -g\n"
138 " retrieve the remote SSH host key and exit\n"
141 " try connecting via IPv4 only\n"
144 " try connecting via IPv6 only\n"
148 " a url string to parse (see below)\n"
151 " disable showing of status messages from the server\n"
153 " --name, -n <string>\n"
154 " set the client name\n"
156 " --socket <filename>\n"
157 " local socket to connect to (~/.pwmd/socket)\n"
159 " --passphrase, -P <string>\n"
160 " passphrase to use (disables pinentry use)\n"
162 " --key-file <filename>\n"
163 " obtain the passphrase from the specified filename\n"
166 " the passphrase is base64 encoded\n"
168 " --timeout <seconds>\n"
169 " pinentry timeout\n"
172 " number of pinentry tries before failing (3)\n"
175 " disable pinentry both remotely and locally\n"
177 " --pinentry <path>\n"
178 " the full path to the pinentry binary (server default)\n"
180 " --ttyname, -y <path>\n"
181 " tty that pinentry will use\n"
183 " --ttytype, -t <string>\n"
184 " pinentry terminal type (default is $TERM)\n"
187 " pinentry display (default is $DISPLAY)\n"
189 " --lc-ctype <string>\n"
190 " locale setting for pinentry\n"
192 " --lc-messages <string>\n"
193 " locale setting for pinentry\n"
195 " --local-pinentry\n"
196 " force using a local pinentry\n"
199 " use a shell like interface to pwmd (allows more than one command)\n"
201 " --output-fd <FD>\n"
202 " redirect command output to the specified file descriptor\n"
204 " --inquire <COMMAND>\n"
205 " the specified command (with any options) uses a server inquire while\n"
206 " command data is read via the inquire file descriptor (stdin)\n"
208 " --inquire-fd <FD>\n"
209 " read inquire data from the specified file descriptor (stdin)\n"
211 " --inquire-line, -L <STRING>\n"
212 " the initial line to send (i.e., element path) before the inquire data\n"
214 " --cipher <string>\n"
215 " the cipher to use when saving (see pwmd(1))\n"
218 " send the SAVE command before exiting\n"
221 " like --save but always ask for a passphrase\n"
223 " --iterations, -I <N>\n"
224 " encrypt with the specified number of iterations\n"
228 fprintf(status
== EXIT_FAILURE
? stderr
: stdout
, N_(
230 "A url string (specified with --url) may be in the form of:\n"
231 " file://[path/to/socket]\n"
233 " ssh[46]://[username@]hostname[:port],identity[,known_hosts]\n"
235 " ssh[46]://[username@]hostname[:port][,,known_hosts] --use-agent\n"
241 static gpg_error_t
inquire_cb(void *user
, const char *cmd
, gpg_error_t rc
,
242 char **data
, size_t *len
)
244 struct inquire_s
*inq
= user
;
254 "------------------------------------------------------------------------------\n"
255 "Press CTRL-D to end. Press twice on a non-empty line. Pressing ENTER after\n"
256 "each line during the inquire will send that line including the newline\n"
258 "------------------------------------------------------------------------------\n"
262 /* The first part of the command data. */
270 *len
= read(inq
->fd
, inq
->line
, ASSUAN_LINELENGTH
);
273 return gpg_error_from_syserror();
278 return *len
? 0 : GPG_ERR_EOF
;
281 static int status_msg_cb(void *data
, const char *line
)
283 char *p
= strchr(line
, ' ');
285 if (p
&& strchr(p
, ' ') && *++p
) {
286 char *p1
= strchr(p
, ' ');
292 int t
= a
&& b
? a
*100/b
: 0;
294 strncpy(l
, line
, strlen(line
)-strlen(p
)-1);
295 fprintf(stderr
, "\r%s %i/%i %i%%%s", l
, a
, b
, t
, a
== b
? "\n" : "");
301 fprintf(stderr
, "%s\n", line
);
306 static gpg_error_t
process_cmd(pwm_t
*pwm
, char **result
, int input
, int once
)
315 pwmd_fd_t pfds
[nfds
];
316 struct timeval tv
= {0, 50000};
319 rc
= pwmd_get_fds(pwm
, pfds
, &nfds
);
325 s
= pwmd_process(pwm
, &rc
, result
);
329 for (i
= 0, n
= 0; i
< nfds
; i
++) {
330 FD_SET(pfds
[i
].fd
, &rfds
);
331 n
= pfds
[i
].fd
> n
? pfds
[i
].fd
: n
;
335 FD_SET(STDIN_FILENO
, &rfds
);
337 nfds
= select(n
+1, &rfds
, NULL
, NULL
, &tv
);
340 rc
= gpg_error_from_errno(errno
);
344 if (input
&& FD_ISSET(STDIN_FILENO
, &rfds
))
347 s
= pwmd_process(pwm
, &rc
, result
);
351 } while (s
== ASYNC_PROCESS
);
356 static gpg_error_t
get_password(char **result
, pwmd_pinentry_t w
, int echo
)
358 char buf
[LINE_MAX
] = {0}, *p
;
359 struct termios told
, tnew
;
364 if (!isatty(STDIN_FILENO
)) {
365 fprintf(stderr
, N_("Input is not from a terminal! Failing.\n"));
366 return GPG_ERR_ENOTTY
;
370 if (tcgetattr(STDIN_FILENO
, &told
) == -1)
371 return gpg_error_from_syserror();
373 memcpy(&tnew
, &told
, sizeof(struct termios
));
374 tnew
.c_lflag
&= ~(ECHO
);
375 tnew
.c_lflag
|= ICANON
|ECHONL
;
377 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tnew
) == -1) {
380 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
381 return gpg_error_from_errno(n
);
386 case PWMD_PINENTRY_OPEN
:
387 fprintf(stderr
, N_("Password for %s: "), filename
);
389 case PWMD_PINENTRY_OPEN_FAILED
:
390 fprintf(stderr
, N_("Invalid password. Password for %s: "), filename
);
392 case PWMD_PINENTRY_SAVE
:
393 fprintf(stderr
, N_("New password for %s: "), filename
);
395 case PWMD_PINENTRY_SAVE_CONFIRM
:
396 fprintf(stderr
, N_("Confirm password: "));
402 if ((p
= fgets(buf
, sizeof(buf
), stdin
)) == NULL
) {
403 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
408 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
412 return GPG_ERR_CANCELED
;
415 p
[strlen(p
) - 1] = 0;
418 key
= pwmd_strdup_printf("%s", p
);
419 memset(&buf
, 0, sizeof(buf
));
422 return GPG_ERR_ENOMEM
;
430 static gpg_error_t
knownhost_cb(void *data
, const char *host
, const char *key
,
434 char *buf
= pwmd_strdup_printf(N_("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?"), (char *)data
, host
, host
);
436 if (no_pinentry
&& !isatty(STDIN_FILENO
)) {
437 fprintf(stderr
, N_("Input is not from a terminal! Failing.\n"));
439 return GPG_ERR_ENOTTY
;
441 else if (no_pinentry
) {
442 for (char *p
= buf
, len
= 0; *p
; p
++, len
++) {
449 while (!isspace(*(--p
)));
456 fprintf(stderr
, "%s\n\n", buf
);
462 fprintf(stderr
, N_("Trust this connection [y/N]: "));
464 rc
= get_password(&result
, PWMD_PINENTRY_CONFIRM
, 1);
469 if (!result
|| !*result
|| *result
== 'n' || *result
== 'N') {
470 if (result
&& *result
)
473 return GPG_ERR_NOT_CONFIRMED
;
476 if ((*result
== 'y' || *result
== 'Y') && *(result
+1) == 0) {
483 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TITLE
, buf
);
489 return pwmd_getpin(pwm
, NULL
, NULL
, PWMD_PINENTRY_CONFIRM
);
492 static int is_remote_url(const char *str
)
494 if (str
&& (strstr(str
, "file://") || strstr(str
, "local://")))
501 static char *escape(const char *str
)
504 char *buf
= pwmd_malloc(ASSUAN_LINELENGTH
+1), *b
= buf
;
507 for (p
= str
; *p
; p
++, len
++) {
508 if (len
== ASSUAN_LINELENGTH
)
549 static gpg_error_t
send_inquire(int fd
, const char *command
, const char *line
)
551 struct inquire_s inq
;
555 if (fstat(fd
, &st
) == -1)
556 return gpg_error_from_syserror();
558 memset(&inq
, 0, sizeof(inq
));
560 inq
.line
= pwmd_calloc(1, ASSUAN_LINELENGTH
);
564 return GPG_ERR_ENOMEM
;
567 char *s
= escape(line
);
569 strncpy(inq
.line
, s
, ASSUAN_LINELENGTH
-1);
574 rc
= pwmd_setopt(pwm
, PWMD_OPTION_INQUIRE_TOTAL
,
575 st
.st_size
? st
.st_size
+strlen(inq
.line
) : 0);
580 rc
= pwmd_inquire(pwm
, command
, inquire_cb
, &inq
);
585 #ifdef HAVE_LIBREADLINE
586 static int interactive_hook(void)
588 interactive_error
= process_cmd(pwm
, NULL
, 0, 1);
590 if (interactive_error
)
591 rl_event_hook
= NULL
;
596 static void print_help()
599 "------------------------------------------------------------------------------\n"
600 "Type HELP for protocol command help (since pwmd 2.19). Commands which use a\n"
601 "server inquire need a non-protocol command to send the data. These commands\n"
602 "including any options are:\n"
604 " INQUIRE <command> - to read from the terminal\n"
605 " INQUIRE_FILE <filename> <command> - to read the specified filename\n"
607 "Elements are TAB delimited. Press CTRL-V then TAB to insert from the prompt.\n"
609 "Press CTRL-D to quit.\n"
610 "------------------------------------------------------------------------------\n"
614 static gpg_error_t
do_interactive()
616 gpg_error_t rc
= process_cmd(pwm
, NULL
, 0, 1);
621 fprintf(stderr
, N_("WARNING: interactive mode doesn't use secure memory!\n"));
624 rl_event_hook
= &interactive_hook
;
625 rl_set_keyboard_input_timeout(100000);
631 line
= readline("pwm> ");
633 if (interactive_error
)
634 return interactive_error
;
642 if (rc
!= GPG_ERR_CANCELED
&& rc
!= GPG_ERR_EOF
)
643 fprintf(stderr
, "ERR %i: %s\n", rc
, pwmd_strerror(rc
));
652 #ifdef HAVE_READLINE_HISTORY
656 /* INQUIRE <COMMAND [options ...]> */
657 if (!strncasecmp(line
, "inquire ", 8))
658 rc
= send_inquire(STDIN_FILENO
, line
+8, NULL
);
659 /* INQUIRE_FILE <FILENAME> <COMMAND [options ...]> */
660 else if (!strncasecmp(line
, "inquire_file ", 13)) {
661 char *p
= strchr(line
+13, ' ');
662 char *f
= p
? line
+13 : NULL
;
665 if (!f
|| !*f
|| !*p
) {
666 fprintf(stderr
, N_("Syntax error. Usage: INQUIRE_FILE <filename> <command>\n"));
671 f
[strlen(f
) - strlen(p
++)] = 0;
672 fd
= open(f
, O_RDONLY
);
675 fprintf(stderr
, "%s\n", strerror(errno
));
680 rc
= send_inquire(fd
, p
, NULL
);
685 rc
= pwmd_command(pwm
, &result
, line
);
690 fprintf(stderr
, "ERR %i: %s\n", rc
, pwmd_strerror(rc
));
691 else if (result
&& *result
)
692 printf("%s%s", result
, result
[strlen(result
)-1] != '\n' ? "\n" : "");
702 static gpg_error_t
finalize()
707 #ifdef HAVE_LIBREADLINE
708 if (!force_save
&& interactive
&& filename
) {
712 fprintf(stderr
, "\n");
715 fprintf(stderr
, N_("(c)ancel/(f)orget password/(s)ave/(Q)uit/(S)ave and quit/(h)elp?: "));
716 p
= fgets(buf
, sizeof(buf
), stdin
);
728 return GPG_ERR_CANCELED
;
732 rc
= pwmd_command(pwm
, NULL
, "CLEARCACHE %s", filename
);
752 if (save
&& filename
) {
753 fprintf(stderr
, "\n");
754 fprintf(stderr
, N_("Saving changes ...\n"));
757 rc
= pwmd_setopt(pwm
, PWMD_OPTION_ITERATIONS
, iter
);
764 rc
= pwmd_setopt(pwm
, PWMD_OPTION_CIPHER
, cipher
);
770 if (local_pin
|| no_pinentry
) {
774 rc
= pwmd_command(pwm
, NULL
, "ISCACHED %s", filename
);
776 if (rc
&& rc
!= GPG_ERR_NOT_FOUND
&&
777 rc
!= GPG_ERR_ENOENT
)
784 rc
= pwmd_getpin(pwm
, filename
, &p1
, PWMD_PINENTRY_SAVE
);
789 rc
= pwmd_getpin(pwm
, filename
, &password
,
790 PWMD_PINENTRY_SAVE_CONFIRM
);
798 rc
= get_password(&p1
, PWMD_PINENTRY_SAVE
, 0);
803 rc
= get_password(&password
, PWMD_PINENTRY_SAVE_CONFIRM
, 0);
813 if ((p1
|| password
) && ((!p1
&& password
) || (!password
&& p1
) ||
814 strcmp(p1
, password
))) {
824 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, password
);
834 rc
= pwmd_command(pwm
, NULL
, "CLEARCACHE %s", filename
);
840 rc
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, NULL
);
848 if (keyfile
&& !local_pin
) {
849 struct inquire_s inq
;
851 memset(&inq
, 0, sizeof(inq
));
852 inq
.fd
= open(keyfile
, O_RDONLY
);
855 rc
= gpg_error_from_syserror();
859 inq
.line
= pwmd_calloc(1, ASSUAN_LINELENGTH
);
866 rc
= pwmd_save_inquire(pwm
, inquire_cb
, &inq
);
877 rc
= pwmd_save2(pwm
);
880 rc
= pwmd_save_async(pwm
);
883 rc
= pwmd_save_async2(pwm
);
887 if (!rc
&& method
>= 2)
888 rc
= process_cmd(pwm
, NULL
, 0, 0);
891 #if defined(WITH_PINENTRY) && defined(WITH_TCP)
893 rc
= pwmd_save2(pwm
);
902 return rc
? rc
: quit
? 0 : GPG_ERR_CANCELED
;
907 int main(int argc
, char *argv
[])
913 char *socketpath
= NULL
;
914 char command
[ASSUAN_LINELENGTH
], *p
;
915 int ret
= EXIT_SUCCESS
;
917 char *pinentry_path
= NULL
;
918 char *display
= NULL
, *tty
= NULL
, *ttytype
= NULL
, *lcctype
= NULL
,
920 int outfd
= STDOUT_FILENO
;
921 FILE *outfp
= stdout
;
922 int inquirefd
= STDIN_FILENO
;
923 FILE *inquirefp
= stdin
;
925 char *clientname
= "pwmc";
926 char *inquire
= NULL
;
927 char *inquire_line
= NULL
;
932 int port
= DEFAULT_PORT
;
933 char *username
= NULL
;
935 char *known_hosts
= NULL
;
937 int prot
= PWMD_IP_ANY
;
944 int lock_on_open
= 1;
948 char *url_string
= NULL
;
949 /* The order is important. */
955 OPT_HOST
, OPT_PORT
, OPT_IDENTITY
, OPT_KNOWN_HOSTS
, OPT_USER
,
956 OPT_GET_HOSTKEY
, OPT_IPV4
, OPT_IPV6
, OPT_USE_AGENT
,
958 OPT_URL
, OPT_LOCAL
, OPT_FORCE_SAVE
, OPT_TTYNAME
, OPT_TTYTYPE
,
959 OPT_DISPLAY
, OPT_LC_CTYPE
, OPT_LC_MESSAGES
, OPT_TIMEOUT
, OPT_TRIES
,
960 OPT_PINENTRY
, OPT_PASSPHRASE
, OPT_KEYFILE
, OPT_BASE64
, OPT_SOCKET
,
961 OPT_NOLOCK
, OPT_SAVE
, OPT_ITERATIONS
, OPT_OUTPUT_FD
, OPT_INQUIRE
,
962 OPT_INQUIRE_FD
, OPT_INQUIRE_LINE
, OPT_NO_STATUS
, OPT_NAME
,
963 OPT_VERSION
, OPT_HELP
, OPT_CIPHER
, OPT_NO_PINENTRY
,
964 #ifdef HAVE_LIBREADLINE
968 const struct option long_opts
[] = {
970 { "debug", 1, 0, 0 },
973 { "host", 1, 0, 'h' },
974 { "port", 1, 0, 'p' },
975 { "identity", 1, 0, 'i' },
976 { "known-hosts", 1, 0, 'k' },
977 { "user", 1, 0, 'u' },
978 { "get-hostkey", 0, 0, 'g' },
979 { "ipv4", 0, 0, '4' },
980 { "ipv6", 0, 0, '6' },
981 { "use-agent", 0, 0, 0 },
984 { "local-pinentry", 0, 0 },
985 { "force-save", 0, 0 },
986 { "ttyname", 1, 0, 'y' },
987 { "ttytype", 1, 0, 't' },
988 { "display", 1, 0, 'd' },
989 { "lc-ctype", 1, 0, 0 },
990 { "lc-messages", 1, 0, 0 },
991 { "timeout", 1, 0, 0 },
992 { "tries", 1, 0, 0 },
993 { "pinentry", 1, 0, 0 },
994 { "passphrase", 1, 0, 'P' },
995 { "key-file", 1, 0, 0 },
996 { "base64", 0, 0, 0 },
997 { "socket", 1, 0, 0 },
998 { "no-lock", 0, 0, 0 },
999 { "save", 0, 0, 'S' },
1000 { "iterations", 1, 0, 'I' },
1001 { "output-fd", 1, 0, 0 },
1002 { "inquire", 1, 0, 0 },
1003 { "inquire-fd", 1, 0, 0 },
1004 { "inquire-line", 1, 0, 'L' },
1005 { "no-status", 0, 0, 0 },
1006 { "name", 1, 0, 'n' },
1007 { "version", 0, 0, 0 },
1008 { "help", 0, 0, 0 },
1009 { "cipher", 1, 0, 0 },
1010 { "no-pinentry", 0, 0, 0 },
1011 #ifdef HAVE_LIBREADLINE
1012 { "interactive", 0, 0 },
1017 const char *optstring
= "L:46h:p:i:k:u:gy:t:d:P:I:Sn:";
1019 const char *optstring
= "L:y:t:d:P:I:Sn:";
1024 setlocale(LC_ALL
, "");
1025 bindtextdomain("libpwmd", LOCALEDIR
);
1028 #ifdef HAVE_LIBREADLINE
1029 if (!strcmp(basename(argv
[0]), "pwmsh"))
1035 while ((opt
= getopt_long(argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1) {
1037 /* Handle long options without a short option part. */
1039 switch (opt_index
) {
1042 method
= atoi(optarg
);
1063 url_string
= optarg
;
1068 case OPT_FORCE_SAVE
:
1069 save
= force_save
= 1;
1072 lcctype
= pwmd_strdup(optarg
);
1074 case OPT_LC_MESSAGES
:
1075 lcmessages
= pwmd_strdup(optarg
);
1078 timeout
= atoi(optarg
);
1081 tries
= atoi(optarg
);
1082 local_tries
= tries
;
1085 socketpath
= pwmd_strdup(optarg
);
1090 case OPT_INQUIRE_FD
:
1091 inquirefd
= atoi(optarg
);
1092 inquirefp
= fdopen(inquirefd
, "r");
1095 pwmd_free(password
);
1096 err(EXIT_FAILURE
, "%i", inquirefd
);
1100 outfd
= atoi(optarg
);
1101 outfp
= fdopen(outfd
, "w");
1104 pwmd_free(password
);
1105 err(EXIT_FAILURE
, "%i", outfd
);
1112 pwmd_free(password
);
1113 printf("%s (pwmc)\n%s\n\n"
1114 "Compile-time features:\n"
1120 #ifdef WITH_PINENTRY
1135 #ifdef HAVE_LIBREADLINE
1141 , PACKAGE_STRING
, PACKAGE_BUGREPORT
);
1144 pinentry_path
= optarg
;
1147 usage(argv
[0], EXIT_SUCCESS
);
1151 case OPT_NO_PINENTRY
:
1154 #ifdef HAVE_LIBREADLINE
1155 case OPT_INTERACTIVE
:
1160 usage(argv
[0], EXIT_FAILURE
);
1172 host
= pwmd_strdup(optarg
);
1175 port
= atoi(optarg
);
1178 ident
= pwmd_strdup(optarg
);
1181 username
= pwmd_strdup(optarg
);
1184 known_hosts
= pwmd_strdup(optarg
);
1191 inquire_line
= optarg
;
1206 iter
= strtol(optarg
, NULL
, 10);
1210 password
= pwmd_strdup(optarg
);
1211 memset(optarg
, 0, strlen(optarg
));
1214 clientname
= optarg
;
1217 pwmd_free(password
);
1218 usage(argv
[0], EXIT_FAILURE
);
1222 #ifdef HAVE_LIBREADLINE
1223 if (interactive
&& !isatty(STDIN_FILENO
)) {
1224 pwmd_free(password
);
1225 usage(argv
[0], EXIT_FAILURE
);
1233 if (host
&& !get
&& !ident
) {
1234 pwmd_free(password
);
1235 usage(argv
[0], EXIT_FAILURE
);
1239 pwmd_free(password
);
1240 usage(argv
[0], EXIT_FAILURE
);
1247 filename
= argv
[optind
];
1249 pwm
= pwmd_new(clientname
);
1255 if (host
|| is_remote_url(url_string
)) {
1256 #ifndef WITH_PINENTRY
1263 if (prot
!= PWMD_IP_ANY
) {
1264 error
= pwmd_setopt(pwm
, PWMD_OPTION_IP_VERSION
, prot
);
1270 error
= pwmd_setopt(pwm
, PWMD_OPTION_KNOWNHOST_CB
, knownhost_cb
);
1275 error
= pwmd_setopt(pwm
, PWMD_OPTION_KNOWNHOST_DATA
, clientname
);
1280 error
= pwmd_setopt(pwm
, PWMD_OPTION_SSH_AGENT
, use_agent
);
1285 fprintf(stderr
, N_("Connecting ...\n"));
1292 error
= pwmd_get_hostkey_async(pwm
, host
, port
);
1295 errx(EXIT_FAILURE
, "%s: %s", host
, pwmd_strerror(error
));
1297 error
= process_cmd(pwm
, &hostkey
, 0, 0);
1302 printf("%s", hostkey
);
1304 pwmd_free(password
);
1310 error
= pwmd_connect_url_async(pwm
, url_string
);
1312 error
= pwmd_ssh_connect_async(pwm
, host
, port
, ident
, username
,
1318 error
= process_cmd(pwm
, NULL
, 0, 0);
1328 error
= pwmd_get_hostkey(pwm
, host
, port
, &hostkey
);
1333 printf("%s", hostkey
);
1335 pwmd_free(password
);
1341 error
= pwmd_connect_url(pwm
, url_string
);
1343 error
= pwmd_ssh_connect(pwm
, host
, port
, ident
, username
, known_hosts
);
1354 error
= pwmd_connect_url(pwm
, url_string
);
1356 error
= pwmd_connect(pwm
, socketpath
);
1364 fprintf(stderr
, N_("Connected.\n"));
1366 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TITLE
, NULL
);
1367 error
= pwmd_socket_type(pwm
, &s
);
1373 if (s
== PWMD_SOCKET_SSH
&& force_save
&& !local_pin
) {
1374 error
= GPG_ERR_WRONG_KEY_USAGE
;
1380 error
= pwmd_command(pwm
, &result
, "VERSION");
1388 pwmd_free(password
);
1390 usage(argv
[0], EXIT_FAILURE
);
1394 if (filename
&& lock_on_open
) {
1395 error
= pwmd_setopt(pwm
, PWMD_OPTION_LOCK_ON_OPEN
, 1);
1402 error
= pwmd_setopt(pwm
, PWMD_OPTION_BASE64
, 1);
1409 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, timeout
);
1416 error
= pwmd_setopt(pwm
, PWMD_OPTION_NO_PINENTRY
, 1);
1422 if ((no_pinentry
|| local_pin
) && filename
&& !keyfile
&& !password
) {
1423 error
= pwmd_command(pwm
, NULL
, "ISCACHED %s", filename
);
1425 if (error
== GPG_ERR_NOT_FOUND
) {
1427 if (try++ == local_tries
)
1431 pwmd_free(password
);
1438 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, 0);
1440 error
= pwmd_getpin(pwm
, filename
, &password
,
1441 try > 1 ? PWMD_PINENTRY_OPEN_FAILED
: PWMD_PINENTRY_OPEN
);
1447 password
= pwmd_strdup("");
1450 error
= get_password(&password
,try > 1 ? PWMD_PINENTRY_OPEN_FAILED
: PWMD_PINENTRY_OPEN
, 0);
1456 error
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, password
);
1464 else if (error
&& error
!= GPG_ERR_ENOENT
)
1468 error
= pwmd_setopt(pwm
, PWMD_OPTION_PASSPHRASE
, password
);
1474 if (pinentry_path
) {
1475 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_PATH
, pinentry_path
);
1482 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, display
);
1489 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TTY
, tty
);
1496 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TERM
, ttytype
);
1503 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, lcctype
);
1510 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
,
1518 error
= pwmd_setopt(pwm
, PWMD_OPTION_PINENTRY_TRIES
, tries
);
1526 error
= pwmd_setopt(pwm
, PWMD_OPTION_STATUS_CB
, status_msg_cb
);
1534 fprintf(stderr
, N_("Opening data file \"%s\" ...\n"), filename
);
1537 if (keyfile
&& (!local_pin
|| host
|| is_remote_url(url_string
))) {
1538 struct inquire_s inq
;
1540 memset(&inq
, 0, sizeof(inq
));
1541 inq
.fd
= open(keyfile
, O_RDONLY
);
1544 error
= gpg_error_from_syserror();
1548 inq
.line
= pwmd_calloc(1, ASSUAN_LINELENGTH
);
1551 error
= GPG_ERR_ENOMEM
;
1556 error
= pwmd_open_inquire(pwm
, filename
, inquire_cb
, &inq
);
1558 pwmd_free(inq
.line
);
1570 error
= pwmd_open(pwm
, filename
);
1573 error
= pwmd_open2(pwm
, filename
);
1576 error
= pwmd_open_async(pwm
, filename
);
1580 error
= pwmd_open_async2(pwm
, filename
);
1584 if (error
&& (local_pin
|| no_pinentry
) &&
1585 error
== GPG_ERR_INV_PASSPHRASE
)
1586 goto local_password
;
1592 error
= process_cmd(pwm
, &result
, 0, 0);
1594 #if defined(WITH_PINENTRY) && defined(WITH_TCP)
1596 error
= pwmd_open2(pwm
, filename
);
1599 error
= pwmd_open(pwm
, filename
);
1601 if (error
&& (local_pin
|| no_pinentry
) &&
1602 error
== GPG_ERR_INV_PASSPHRASE
)
1603 goto local_password
;
1613 #ifdef HAVE_LIBREADLINE
1618 error
= do_interactive();
1624 int fd
= fileno(inquirefp
);
1627 error
= gpg_error_from_syserror();
1631 error
= send_inquire(fd
, inquire
, inquire_line
);
1636 fcntl(STDIN_FILENO
, F_SETFL
, O_NONBLOCK
);
1640 error
= process_cmd(pwm
, NULL
, 1, 0);
1645 n
= read(STDIN_FILENO
, command
, sizeof(command
));
1648 if (errno
== EAGAIN
)
1651 error
= gpg_error_from_errno(errno
);
1665 if (strcasecmp(p
, "BYE") == 0)
1668 error
= pwmd_command(pwm
, &result
, command
);
1674 fwrite(result
, 1, strlen(result
), outfp
);
1681 pwmd_free(password
);
1689 memset(command
, 0, sizeof(command
));
1699 fprintf(stderr
, N_("Connection closed.\n"));
1702 pwmd_free(socketpath
);