1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006-2009 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
30 #include <sys/socket.h>
39 #include <sys/types.h>
41 #include <sys/select.h>
60 static gpg_error_t
send_pinentry_options(pwm_t
*pwm
);
61 static gpg_error_t
_pwmd_process(pwm_t
*pwm
);
62 static gpg_error_t
set_pinentry_retry(pwm_t
*pwm
);
63 static gpg_error_t
get_custom_passphrase(pwm_t
*pwm
, char **result
);
65 static const char *_pwmd_strerror(gpg_error_t e
)
67 gpg_err_code_t code
= gpg_err_code(e
);
69 if (code
>= GPG_ERR_USER_1
&& code
< gpg_err_code(EPWMD_MAX
)) {
72 return N_("No file is open");
74 return N_("General LibXML error");
76 return N_("File modified");
78 return N_("Unknown error");
85 const char *pwmd_strerror(gpg_error_t code
)
87 const char *p
= _pwmd_strerror(code
);
89 return p
? p
: gpg_strerror(code
);
92 int pwmd_strerror_r(gpg_error_t code
, char *buf
, size_t size
)
94 const char *p
= _pwmd_strerror(code
);
97 snprintf(buf
, size
, "%s", p
);
99 if (strlen(p
)+1 > size
)
105 return gpg_strerror_r(code
, buf
, size
);
108 gpg_error_t
pwmd_init()
110 static int initialized
;
119 bindtextdomain("libpwmd", LOCALEDIR
);
125 assuan_set_malloc_hooks(pwmd_malloc
, pwmd_realloc
, pwmd_free
);
126 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT
);
131 gpg_error_t
_connect_finalize(pwm_t
*pwm
)
134 int n
= assuan_get_active_fds(pwm
->ctx
, 0, active
, N_ARRAY(active
));
138 return GPG_ERR_EBADFD
;
144 assuan_set_pointer(pwm
->ctx
, pwm
);
148 pwm
->tcp_conn
->state
= SSH_NONE
;
152 rc
= pwmd_command(pwm
, NULL
, "SET NAME=%s", pwm
->name
);
161 static gpg_error_t
_pwmd_connect_url(pwm_t
*pwm
, const char *url
, int async
)
163 char *p
= (char *)url
;
167 return GPG_ERR_INV_ARG
;
169 if (!p
|| !strncmp(p
, "file://", 7) || !strncmp(p
, "local://", 8)) {
171 if (!strncmp(p
, "file://", 7))
179 else if (!strncmp(p
, "ssh://", 6) || !strncmp(p
, "ssh6://", 7) ||
180 !strncmp(p
, "ssh4://", 7)) {
182 return GPG_ERR_NOT_IMPLEMENTED
;
186 char *identity
= NULL
;
187 char *known_hosts
= NULL
;
188 char *username
= NULL
;
190 if (!strncmp(p
, "ssh6://", 7)) {
191 rc
= pwmd_setopt(pwm
, PWMD_OPTION_IP_VERSION
, PWMD_IPV6
);
194 else if (!strncmp(p
, "ssh4://", 7)) {
195 rc
= pwmd_setopt(pwm
, PWMD_OPTION_IP_VERSION
, PWMD_IPV4
);
199 rc
= pwmd_setopt(pwm
, PWMD_OPTION_IP_VERSION
, PWMD_IP_ANY
);
206 rc
= _parse_ssh_url(p
, &host
, &port
, &username
, &identity
,
213 rc
= pwmd_ssh_connect_async(pwm
, host
, port
, identity
, username
,
216 rc
= pwmd_ssh_connect(pwm
, host
, port
, identity
, username
,
230 pwmd_free(known_hosts
);
237 rc
= pwmd_connect(pwm
, p
);
238 pwm
->state
= ASYNC_DONE
;
242 gpg_error_t
pwmd_connect_url(pwm_t
*pwm
, const char *url
)
244 return _pwmd_connect_url(pwm
, url
, 0);
247 gpg_error_t
pwmd_connect_url_async(pwm_t
*pwm
, const char *url
)
249 return _pwmd_connect_url(pwm
, url
, 1);
252 gpg_error_t
pwmd_connect(pwm_t
*pwm
, const char *path
)
254 char *socketpath
= NULL
;
255 assuan_context_t ctx
;
261 return GPG_ERR_INV_ARG
;
263 pwbuf
= _getpwuid(&pw
);
266 return gpg_error_from_syserror();
269 socketpath
= pwmd_strdup_printf("%s/.pwmd/socket", pw
.pw_dir
);
271 socketpath
= _expand_homedir((char *)path
, &pw
);
276 return GPG_ERR_ENOMEM
;
278 rc
= assuan_socket_connect_ext(&ctx
, socketpath
, -1, 0);
279 pwmd_free(socketpath
);
282 return gpg_err_code(rc
);
285 return _connect_finalize(pwm
);
288 static void disconnect(pwm_t
*pwm
)
290 if (!pwm
|| !pwm
->ctx
)
293 assuan_disconnect(pwm
->ctx
);
298 void pwmd_close(pwm_t
*pwm
)
306 pwmd_free(pwm
->password
);
309 pwmd_free(pwm
->title
);
312 pwmd_free(pwm
->desc
);
315 pwmd_free(pwm
->prompt
);
317 if (pwm
->pinentry_tty
)
318 pwmd_free(pwm
->pinentry_tty
);
320 if (pwm
->pinentry_display
)
321 pwmd_free(pwm
->pinentry_display
);
323 if (pwm
->pinentry_term
)
324 pwmd_free(pwm
->pinentry_term
);
327 pwmd_free(pwm
->lcctype
);
330 pwmd_free(pwm
->lcmessages
);
333 pwmd_free(pwm
->filename
);
336 pwmd_free(pwm
->name
);
339 pwmd_free(pwm
->cipher
);
343 _free_ssh_conn(pwm
->tcp_conn
);
348 _pinentry_disconnect(pwm
);
355 static gpg_error_t
do_async_command(pwm_t
*pwm
, char **result
)
361 s
= pwmd_process(pwm
, &rc
, result
);
363 if (s
!= ASYNC_DONE
) {
370 } while (s
!= ASYNC_DONE
);
376 gpg_error_t
pwmd_ssh_connect_async(pwm_t
*pwm
, const char *host
, int port
,
377 const char *identity
, const char *user
, const char *known_hosts
)
380 return GPG_ERR_NOT_IMPLEMENTED
;
382 return _do_pwmd_ssh_connect_async(pwm
, host
, port
, identity
, user
,
383 known_hosts
, ASYNC_CMD_CONNECT
);
387 gpg_error_t
pwmd_ssh_connect(pwm_t
*pwm
, const char *host
, int port
,
388 const char *identity
, const char *user
, const char *known_hosts
)
391 return GPG_ERR_NOT_IMPLEMENTED
;
395 rc
= _do_pwmd_ssh_connect_async(pwm
, host
, port
, identity
, user
,
396 known_hosts
, ASYNC_CMD_CONNECT
);
397 return rc
? rc
: do_async_command(pwm
, NULL
);
401 gpg_error_t
pwmd_get_hostkey(pwm_t
*pwm
, const char *host
, int port
,
405 return GPG_ERR_NOT_IMPLEMENTED
;
409 rc
= _do_pwmd_ssh_connect_async(pwm
, host
, port
, NULL
, NULL
, NULL
,
412 return rc
? rc
: do_async_command(pwm
, result
);
416 gpg_error_t
pwmd_get_hostkey_async(pwm_t
*pwm
, const char *host
, int port
)
419 return GPG_ERR_NOT_IMPLEMENTED
;
421 return _do_pwmd_ssh_connect_async(pwm
, host
, port
, NULL
, NULL
, NULL
,
426 static int inquire_realloc_cb(void *data
, const void *buffer
, size_t len
)
428 membuf_t
*mem
= (membuf_t
*)data
;
434 if ((p
= pwmd_realloc(mem
->buf
, mem
->len
+ len
)) == NULL
)
435 return GPG_ERR_ENOMEM
;
438 memcpy((char *)mem
->buf
+ mem
->len
, buffer
, len
);
443 static int inquire_cb(void *data
, const char *keyword
)
445 pwm_t
*pwm
= (pwm_t
*)data
;
449 /* Shouldn't get this far without a callback. */
450 if (!pwm
->inquire_func
)
451 return GPG_ERR_INV_ARG
;
458 rc
= pwm
->inquire_func(pwm
->inquire_data
, keyword
, rc
, &result
, &len
);
459 rc
= gpg_err_code(rc
);
461 if (rc
== GPG_ERR_EOF
|| !rc
) {
462 if (len
<= 0 && !result
) {
466 else if ((len
<= 0 && result
) || (len
&& !result
)) {
467 rc
= GPG_ERR_INV_ARG
;
473 arc
= assuan_send_data(pwm
->ctx
, result
, len
);
474 arc
= gpg_err_code(arc
);
476 if (rc
== GPG_ERR_EOF
) {
483 if (rc
== GPG_ERR_EAGAIN
) {
493 pwm
->inquire_sent
+= len
;
495 if (pwm
->status_func
) {
496 char buf
[ASSUAN_LINELENGTH
];
498 snprintf(buf
, sizeof(buf
), "XFER %u %u", pwm
->inquire_sent
,
500 rc
= pwm
->status_func(pwm
->status_data
, buf
);
507 rc
= _pwmd_process(pwm
);
509 if (rc
== GPG_ERR_EAGAIN
)
513 if (!rc
&& is_eagain
) {
523 return gpg_err_code(rc
);
526 static gpg_error_t
do_nb_command(pwm_t
*pwm
, const char *cmd
, ...)
533 if (pwm
->state
== ASYNC_DONE
)
534 pwm
->state
= ASYNC_INIT
;
536 if (pwm
->state
!= ASYNC_INIT
)
537 return GPG_ERR_INV_STATE
;
539 buf
= pwmd_malloc(ASSUAN_LINELENGTH
+1);
542 return GPG_ERR_ENOMEM
;
545 len
= vsnprintf(buf
, ASSUAN_LINELENGTH
+1, cmd
, ap
);
548 if (len
>= ASSUAN_LINELENGTH
+1) {
550 return GPG_ERR_LINE_TOO_LONG
;
553 rc
= assuan_write_line(pwm
->ctx
, buf
);
557 pwm
->state
= ASYNC_PROCESS
;
559 return gpg_err_code(rc
);
562 gpg_error_t
pwmd_open_async(pwm_t
*pwm
, const char *filename
)
565 const char *f
= NULL
;
568 if (!pwm
|| !filename
)
569 return GPG_ERR_INV_ARG
;
572 return GPG_ERR_INV_STATE
;
574 if (pwm
->cmd
!= ASYNC_CMD_NONE
)
575 return GPG_ERR_ASS_NESTED_COMMANDS
;
577 if (pwm
->lastcmd
== ASYNC_CMD_NONE
) {
581 pwmd_free(pwm
->filename
);
583 pwm
->filename
= pwmd_strdup(filename
);
586 return GPG_ERR_ENOMEM
;
588 gpg_error_t rc
= send_pinentry_options(pwm
);
593 rc
= get_custom_passphrase(pwm
, &p
);
595 if (rc
&& rc
!= GPG_ERR_NO_DATA
)
601 else if (pwm
->lastcmd
== ASYNC_CMD_OPEN2
) {
606 else if (pwm
->lastcmd
== ASYNC_CMD_OPEN
) {
607 rc
= set_pinentry_retry(pwm
);
616 return GPG_ERR_INV_STATE
;
618 pwm
->cmd
= ASYNC_CMD_OPEN
;
620 return do_nb_command(pwm
, "OPEN %s%s%s%s %s",
621 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
622 (pwm
->opts
& OPT_LOCK_ON_OPEN
) ? "--lock " : "",
623 pwm
->tcp_conn
? "--pinentry=0 " : "",
626 return do_nb_command(pwm
, "OPEN %s%s%s %s",
627 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
628 (pwm
->opts
& OPT_LOCK_ON_OPEN
) ? "--lock " : "",
633 gpg_error_t
pwmd_save_async(pwm_t
*pwm
)
638 return GPG_ERR_INV_ARG
;
641 return GPG_ERR_INV_STATE
;
643 if (pwm
->cmd
!= ASYNC_CMD_NONE
)
644 return GPG_ERR_ASS_NESTED_COMMANDS
;
646 if (pwm
->lastcmd
!= ASYNC_CMD_SAVE2
) {
647 gpg_error_t rc
= send_pinentry_options(pwm
);
652 rc
= get_custom_passphrase(pwm
, &p
);
654 if (rc
&& rc
!= GPG_ERR_NO_DATA
)
662 pwm
->cmd
= ASYNC_CMD_SAVE
;
664 char *tmp
= pwmd_strdup_printf("%li", pwm
->iterations
);
666 gpg_error_t rc
= do_nb_command(pwm
, "SAVE %s%s--iterations=%s --cipher=%s",
667 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
668 pwm
->tcp_conn
? "--pinentry=0 " : "",
669 pwm
->iterations
!= -1 ? tmp
: "",
670 pwm
->cipher
? pwm
->cipher
: "", p
? p
: "");
672 gpg_error_t rc
= do_nb_command(pwm
, "SAVE %s--iterations=%s --cipher=%s",
673 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
674 pwm
->iterations
!= -1 ? tmp
: "",
675 pwm
->cipher
? pwm
->cipher
: "", p
? p
: "");
682 static gpg_error_t
parse_assuan_line(pwm_t
*pwm
)
688 rc
= assuan_read_line(pwm
->ctx
, &line
, &len
);
691 if (line
[0] == 'O' && line
[1] == 'K' &&
692 (line
[2] == 0 || line
[2] == ' ')) {
693 pwm
->state
= ASYNC_DONE
;
695 else if (line
[0] == '#') {
697 else if (line
[0] == 'S' && (line
[1] == 0 || line
[1] == ' ')) {
698 if (pwm
->status_func
) {
699 rc
= pwm
->status_func(pwm
->status_data
,
700 line
[1] == 0 ? line
+1 : line
+2);
703 else if (line
[0] == 'E' && line
[1] == 'R' && line
[2] == 'R' &&
704 (line
[3] == 0 || line
[3] == ' ')) {
707 pwm
->state
= ASYNC_DONE
;
711 return gpg_err_code(rc
);
714 gpg_error_t
pwmd_pending_line(pwm_t
*pwm
)
717 return GPG_ERR_INV_ARG
;
720 return GPG_ERR_INV_STATE
;
722 return assuan_pending_line(pwm
->ctx
) ? 0 : GPG_ERR_NO_DATA
;
725 static pwmd_async_t
reset_async(pwm_t
*pwm
, int done
)
727 pwm
->state
= ASYNC_INIT
;
728 pwm
->cmd
= pwm
->lastcmd
= ASYNC_CMD_NONE
;
731 if (pwm
->nb_fd
!= -1) {
736 if (pwm
->_password
) {
737 pwmd_free(pwm
->_password
);
738 pwm
->_password
= NULL
;
743 pwm
->tcp_conn
->rc
= 0;
745 if (done
&& pwm
->tcp_conn
) {
746 _free_ssh_conn(pwm
->tcp_conn
);
747 pwm
->tcp_conn
= NULL
;
755 * Used for processing status messages when not in an async command and for
756 * waiting for the result from pwmd_open_async() and pwmd_save_async().
758 static gpg_error_t
_pwmd_process(pwm_t
*pwm
)
762 struct timeval tv
= {0, 0};
766 FD_SET(pwm
->fd
, &fds
);
768 n
= pth_select(pwm
->fd
+1, &fds
, NULL
, NULL
, &tv
);
770 n
= select(pwm
->fd
+1, &fds
, NULL
, NULL
, &tv
);
774 return gpg_error_from_syserror();
777 if (FD_ISSET(pwm
->fd
, &fds
))
778 rc
= parse_assuan_line(pwm
);
781 while (!rc
&& assuan_pending_line(pwm
->ctx
))
782 rc
= parse_assuan_line(pwm
);
784 return gpg_err_code(rc
);
787 static void reset_handle(pwm_t
*h
)
792 _pinentry_disconnect(h
);
800 gpg_error_t
pwmd_disconnect(pwm_t
*pwm
)
803 return GPG_ERR_INV_ARG
;
806 if (pwm
->fd
== -1 && pwm
->tcp_conn
&& pwm
->tcp_conn
->fd
== -1)
810 return GPG_ERR_INV_STATE
;
816 _ssh_disconnect(pwm
);
823 pwmd_async_t
pwmd_process(pwm_t
*pwm
, gpg_error_t
*rc
, char **result
)
825 #if defined(WITH_PINENTRY) || defined(WITH_TCP)
828 struct timeval tv
= {0, 0};
835 return GPG_ERR_INV_ARG
;
840 *rc
= GPG_ERR_INV_ARG
;
843 else if (!pwm
->ctx
) {
846 *rc
= GPG_ERR_INV_STATE
;
850 case ASYNC_CMD_CONNECT
:
851 case ASYNC_CMD_HOSTKEY
:
857 /* When not in a command, this will let libassuan process status messages
858 * by calling PWMD_OPTION_STATUS_FUNC. The client can poll the file
859 * descriptor returned by pwmd_get_fd() to determine when this should be
860 * called or call pwmd_pending_line() to determine whether a buffered line
861 * needs to be processed. */
862 if (pwm
->cmd
== ASYNC_CMD_NONE
) {
863 *rc
= _pwmd_process(pwm
);
867 /* Fixes pwmd_open/save_async2() when there is a cached or new file. */
868 if (pwm
->state
== ASYNC_DONE
) {
869 *rc
= _pwmd_process(pwm
);
870 return reset_async(pwm
, 0);
873 if (pwm
->state
!= ASYNC_PROCESS
) {
874 *rc
= GPG_ERR_INV_STATE
;
879 if (pwm
->cmd
== ASYNC_CMD_DNS
) {
882 if (pwm
->tcp_conn
->rc
) {
883 *rc
= pwm
->tcp_conn
->rc
;
884 return reset_async(pwm
, 1);
889 n
= ares_fds(pwm
->tcp_conn
->chan
, &rfds
, &wfds
);
891 /* Shouldn't happen. */
896 n
= pth_select(n
, &rfds
, &wfds
, NULL
, &tv
);
898 n
= select(n
, &rfds
, &wfds
, NULL
, &tv
);
902 *rc
= gpg_error_from_syserror();
903 return reset_async(pwm
, 1);
907 ares_process(pwm
->tcp_conn
->chan
, &rfds
, &wfds
);
911 else if (pwm
->cmd
== ASYNC_CMD_CONNECT
) {
912 if (pwm
->tcp_conn
->rc
== GPG_ERR_EINPROGRESS
) {
914 socklen_t len
= sizeof(int);
917 FD_SET(pwm
->tcp_conn
->fd
, &fds
);
919 n
= pth_select(pwm
->tcp_conn
->fd
+1, NULL
, &fds
, NULL
, &tv
);
921 n
= select(pwm
->tcp_conn
->fd
+1, NULL
, &fds
, NULL
, &tv
);
924 if (!n
|| !FD_ISSET(pwm
->tcp_conn
->fd
, &fds
))
927 *rc
= gpg_error_from_syserror();
928 return reset_async(pwm
, 1);
931 ret
= getsockopt(pwm
->tcp_conn
->fd
, SOL_SOCKET
, SO_ERROR
, &n
, &len
);
934 *rc
= ret
? gpg_error_from_syserror() : gpg_error_from_errno(n
);
935 return reset_async(pwm
, 1);
938 pwm
->tcp_conn
->state
= SSH_NONE
;
939 pwm
->tcp_conn
->rc
= 0;
940 *rc
= _setup_ssh_session(pwm
);
942 if (*rc
&& *rc
!= GPG_ERR_EAGAIN
)
943 return reset_async(pwm
, 1);
945 else if (pwm
->tcp_conn
->rc
) {
946 *rc
= pwm
->tcp_conn
->rc
;
947 return reset_async(pwm
, 1);
950 switch (pwm
->tcp_conn
->state
) {
952 *rc
= _setup_ssh_init(pwm
);
955 *rc
= _setup_ssh_authlist(pwm
);
958 *rc
= _setup_ssh_auth(pwm
);
961 *rc
= _setup_ssh_agent(pwm
);
964 *rc
= _setup_ssh_channel(pwm
);
967 *rc
= _setup_ssh_shell(pwm
);
973 if (*rc
== GPG_ERR_EAGAIN
) {
975 return ASYNC_PROCESS
;
979 switch (pwm
->tcp_conn
->cmd
) {
980 case ASYNC_CMD_HOSTKEY
:
981 *result
= pwmd_strdup(pwm
->tcp_conn
->hostkey
);
984 *rc
= GPG_ERR_ENOMEM
;
991 return reset_async(pwm
, *rc
? 1 : 0);
996 if (pwm
->cmd
== ASYNC_CMD_OPEN2
|| pwm
->cmd
== ASYNC_CMD_SAVE2
) {
999 if (pwm
->nb_fd
== -1) {
1000 *rc
= GPG_ERR_INV_STATE
;
1001 return reset_async(pwm
, 0);
1005 FD_SET(pwm
->nb_fd
, &fds
);
1006 FD_SET(pwm
->fd
, &fds
);
1008 n
= pth_select(pwm
->nb_fd
+1, &fds
, NULL
, NULL
, &tv
);
1010 n
= select(pwm
->nb_fd
+1, &fds
, NULL
, NULL
, &tv
);
1013 *rc
= gpg_error_from_syserror();
1014 return reset_async(pwm
, 0);
1017 if (n
> 0 && FD_ISSET(pwm
->nb_fd
, &fds
)) {
1018 pwmd_nb_status_t nb
;
1020 size_t len
= pth_read(pwm
->nb_fd
, &nb
, sizeof(nb
));
1022 size_t len
= read(pwm
->nb_fd
, &nb
, sizeof(nb
));
1024 waitpid(pwm
->nb_pid
, &status
, WNOHANG
);
1026 if (len
!= sizeof(nb
)) {
1027 memset(&nb
, 0, sizeof(pwmd_nb_status_t
));
1028 *rc
= gpg_error_from_syserror();
1029 return reset_async(pwm
, 0);
1035 return reset_async(pwm
, 0);
1037 /* Since the non-blocking pinentry returned a success, do a
1038 * non-blocking OPEN or SAVE. */
1039 pwmd_async_cmd_t c
= pwm
->cmd
;
1040 reset_async(pwm
, 0);
1041 pwm
->_password
= pwmd_strdup(nb
.password
);
1042 memset(&nb
, 0, sizeof(pwmd_nb_status_t
));
1045 if (!pwm
->_password
) {
1046 *rc
= GPG_ERR_ENOMEM
;
1047 return reset_async(pwm
, 0);
1050 if (c
== ASYNC_CMD_SAVE2
)
1051 *rc
= pwmd_save_async(pwm
);
1053 *rc
= pwmd_open_async(pwm
, pwm
->filename
);
1056 reset_async(pwm
, 0);
1060 return ASYNC_PROCESS
;
1063 /* Fall through so status messages can be processed during the
1069 *rc
= GPG_ERR_INV_STATE
;
1070 return reset_async(pwm
, 0);
1073 /* This is for pwmd_open_async() and pwmd_save_async(). For pinentry
1075 *rc
= _pwmd_process(pwm
);
1077 if (*rc
&& *rc
!= GPG_ERR_INV_PASSPHRASE
)
1078 return reset_async(pwm
, 0);
1080 if (pwm
->cmd
== ASYNC_CMD_OPEN
&&
1081 *rc
== GPG_ERR_INV_PASSPHRASE
&&
1083 (!pwm
->tcp_conn
|| (pwm
->tcp_conn
&& pwm
->lastcmd
== ASYNC_CMD_OPEN2
)) &&
1085 ++pwm
->pin_try
< pwm
->pinentry_tries
) {
1086 if (!get_custom_passphrase(pwm
, NULL
))
1089 #ifdef WITH_PINENTRY
1090 if (pwm
->_password
) {
1091 reset_async(pwm
, 0);
1092 pwm
->lastcmd
= ASYNC_CMD_OPEN2
;
1093 *rc
= pwmd_open_async2(pwm
, pwm
->filename
);
1097 reset_async(pwm
, 0);
1098 pwm
->lastcmd
= ASYNC_CMD_OPEN
;
1099 *rc
= pwmd_open_async(pwm
, pwm
->filename
);
1100 #ifdef WITH_PINENTRY
1106 if (*rc
|| pwm
->state
== ASYNC_DONE
)
1107 return reset_async(pwm
, 0);
1112 gpg_error_t
_assuan_command(pwm_t
*pwm
, assuan_context_t ctx
,
1113 char **result
, const char *cmd
)
1119 return GPG_ERR_INV_ARG
;
1121 if (strlen(cmd
) >= ASSUAN_LINELENGTH
+1)
1122 return GPG_ERR_LINE_TOO_LONG
;
1126 rc
= assuan_transact(ctx
, cmd
, inquire_realloc_cb
, &data
,
1128 pwm
->pctx
== ctx
? pwm
->_inquire_func
: inquire_cb
,
1129 pwm
->pctx
== ctx
? pwm
->_inquire_data
: pwm
,
1133 pwm
->status_func
, pwm
->status_data
);
1137 pwmd_free(data
.buf
);
1143 inquire_realloc_cb(&data
, "", 1);
1146 pwmd_free(data
.buf
);
1147 rc
= GPG_ERR_INV_ARG
;
1150 *result
= (char *)data
.buf
;
1154 return gpg_err_code(rc
);
1157 gpg_error_t
pwmd_inquire(pwm_t
*pwm
, const char *cmd
, pwmd_inquire_cb_t fn
,
1160 if (!pwm
|| !cmd
|| !fn
)
1161 return GPG_ERR_INV_ARG
;
1164 return GPG_ERR_INV_STATE
;
1166 pwm
->inquire_func
= fn
;
1167 pwm
->inquire_data
= data
;
1168 pwm
->inquire_sent
= 0;
1169 return _assuan_command(pwm
, pwm
->ctx
, NULL
, cmd
);
1172 gpg_error_t
pwmd_command_ap(pwm_t
*pwm
, char **result
, const char *cmd
,
1180 return GPG_ERR_INV_ARG
;
1183 return GPG_ERR_INV_STATE
;
1186 * C99 allows the dst pointer to be null which will calculate the length
1187 * of the would-be result and return it.
1190 len
= vsnprintf(NULL
, 0, cmd
, ap
)+1;
1191 buf
= (char *)pwmd_malloc(len
);
1195 return GPG_ERR_ENOMEM
;
1198 len
= vsnprintf(buf
, len
, cmd
, ap2
);
1201 if (buf
[strlen(buf
)-1] == '\n')
1202 buf
[strlen(buf
)-1] = 0;
1204 if (buf
[strlen(buf
)-1] == '\r')
1205 buf
[strlen(buf
)-1] = 0;
1207 gpg_error_t rc
= _assuan_command(pwm
, pwm
->ctx
, result
, buf
);
1212 gpg_error_t
pwmd_command(pwm_t
*pwm
, char **result
, const char *cmd
, ...)
1217 return GPG_ERR_INV_ARG
;
1220 return GPG_ERR_INV_STATE
;
1226 gpg_error_t rc
= pwmd_command_ap(pwm
, result
, cmd
, ap
);
1231 static gpg_error_t
send_pinentry_options(pwm_t
*pwm
)
1235 if (pwm
->pinentry_path
) {
1236 rc
= pwmd_command(pwm
, NULL
, "SET PINENTRY_PATH=%s",
1237 pwm
->pinentry_path
);
1243 if (pwm
->pinentry_tty
) {
1244 rc
= pwmd_command(pwm
, NULL
, "SET TTYNAME=%s", pwm
->pinentry_tty
);
1250 if (pwm
->pinentry_term
) {
1251 rc
= pwmd_command(pwm
, NULL
, "SET TTYTYPE=%s", pwm
->pinentry_term
);
1257 if (pwm
->pinentry_display
) {
1258 rc
= pwmd_command(pwm
, NULL
, "SET DISPLAY=%s",
1259 pwm
->pinentry_display
);
1266 rc
= pwmd_command(pwm
, NULL
, "SET TITLE=%s", pwm
->title
);
1273 rc
= pwmd_command(pwm
, NULL
, "SET DESC=%s", pwm
->desc
);
1280 rc
= pwmd_command(pwm
, NULL
, "SET PROMPT=%s", pwm
->prompt
);
1287 rc
= pwmd_command(pwm
, NULL
, "SET LC_CTYPE=%s", pwm
->lcctype
);
1293 if (pwm
->lcmessages
) {
1294 rc
= pwmd_command(pwm
, NULL
, "SET LC_MESSAGES=%s", pwm
->lcmessages
);
1300 if (pwm
->pinentry_timeout
>= 0 && !pwm
->pin_try
) {
1301 rc
= pwmd_command(pwm
, NULL
, "SET PINENTRY_TIMEOUT=%i",
1302 pwm
->pinentry_timeout
);
1311 gpg_error_t
pwmd_socket_type(pwm_t
*pwm
, pwmd_socket_t
*result
)
1313 if (!pwm
|| !result
)
1314 return GPG_ERR_INV_ARG
;
1317 if ((pwm
->fd
== -1 && !pwm
->tcp_conn
) ||
1318 (pwm
->fd
== -1 && pwm
->tcp_conn
&& pwm
->tcp_conn
->fd
== -1))
1322 return GPG_ERR_INV_STATE
;
1325 *result
= pwm
->tcp_conn
? PWMD_SOCKET_SSH
: PWMD_SOCKET_LOCAL
;
1327 *result
= PWMD_SOCKET_LOCAL
;
1332 static gpg_error_t
set_pinentry_retry(pwm_t
*pwm
)
1336 if (pwm
->pin_try
== 1) {
1337 rc
= pwmd_command(pwm
, NULL
, "SET TITLE=%s",
1338 N_("Invalid passphrase, please try again."));
1343 rc
= pwmd_command(pwm
, NULL
, "SET PINENTRY_TIMEOUT=0");
1349 static gpg_error_t
get_custom_passphrase(pwm_t
*pwm
, char **result
)
1351 gpg_error_t rc
= GPG_ERR_NO_DATA
;
1356 if (pwm
->password
|| pwm
->passfunc
)
1360 if (pwm
->password
) {
1362 *result
= pwm
->password
;
1364 else if (pwm
->passfunc
)
1365 rc
= pwm
->passfunc(pwm
->passdata
, result
);
1370 static gpg_error_t
do_pwmd_open(pwm_t
*pwm
, const char *filename
, int nb
,
1373 char *result
= NULL
;
1374 char *password
= NULL
;
1376 int no_pinentry
= 0;
1378 if (pwm
->lastcmd
!= ASYNC_CMD_OPEN2
)
1381 if (!pwm
|| !filename
|| !*filename
)
1382 return GPG_ERR_INV_ARG
;
1385 return GPG_ERR_INV_STATE
;
1388 * Avoid calling pinentry if the password is cached on the server or if
1389 * this is a new file.
1391 rc
= pwmd_command(pwm
, &result
, "ISCACHED %s", filename
);
1393 if (rc
== GPG_ERR_ENOENT
)
1396 if (rc
&& rc
!= GPG_ERR_NOT_FOUND
)
1399 if (rc
== GPG_ERR_NOT_FOUND
) {
1400 rc
= get_custom_passphrase(pwm
, &password
);
1402 if (rc
&& rc
!= GPG_ERR_NO_DATA
)
1404 else if (rc
== GPG_ERR_NO_DATA
)
1405 rc
= GPG_ERR_NOT_FOUND
;
1410 #ifdef WITH_PINENTRY
1411 if (rc
== GPG_ERR_NOT_FOUND
&& local_pinentry
) {
1412 /* Prevent pwmd from using it's pinentry if the passphrase fails. */
1416 rc
= _pinentry_open(pwm
, filename
, &password
, nb
);
1418 /* pwmd_process() should be called if using a non-blocking local
1420 if (rc
|| (!rc
&& nb
))
1426 reset_async(pwm
, 0);
1429 if (!local_pinentry
&& !pwm
->tcp_conn
&& !pwm
->pin_try
) {
1431 if (!local_pinentry
&& !pwm
->pin_try
) {
1433 rc
= send_pinentry_options(pwm
);
1439 rc
= pwmd_command(pwm
, NULL
, "OPEN %s%s%s%s %s",
1440 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
1441 (pwm
->opts
& OPT_LOCK_ON_OPEN
) ? "--lock " : "",
1442 no_pinentry
? "--pinentry=0 " : "",
1443 filename
, password
? password
: "");
1446 * Keep the user defined password set with pwmd_setopt(). The password may
1447 * be needed later (pwmd_save()) depending on the pwmd file cache settings.
1449 if (!pwm
->passfunc
&& password
&& password
!= pwm
->password
)
1450 pwmd_free(password
);
1452 if (rc
== GPG_ERR_INV_PASSPHRASE
) {
1453 if (++pwm
->pin_try
< pwm
->pinentry_tries
) {
1454 if (!get_custom_passphrase(pwm
, NULL
))
1457 #ifdef WITH_PINENTRY
1459 if (pwm
->tcp_conn
&& !local_pinentry
)
1461 else if (local_pinentry
)
1462 rc
= _getpin(pwm
, &password
, PWMD_PINENTRY_OPEN_FAILED
);
1466 rc
= _getpin(pwm
, &password
, PWMD_PINENTRY_OPEN_FAILED
);
1476 rc
= set_pinentry_retry(pwm
);
1483 #ifdef WITH_PINENTRY
1484 else if (local_pinentry
)
1485 _pinentry_disconnect(pwm
);
1491 #ifdef WITH_PINENTRY
1492 else if (rc
&& local_pinentry
)
1493 _pinentry_disconnect(pwm
);
1498 pwmd_free(pwm
->filename
);
1500 pwm
->filename
= pwmd_strdup(filename
);
1506 gpg_error_t
pwmd_open2(pwm_t
*pwm
, const char *filename
)
1508 #ifndef WITH_PINENTRY
1509 return GPG_ERR_NOT_IMPLEMENTED
;
1511 return do_pwmd_open(pwm
, filename
, 0, 1);
1515 gpg_error_t
pwmd_open(pwm_t
*pwm
, const char *filename
)
1517 return do_pwmd_open(pwm
, filename
, 0, 0);
1520 gpg_error_t
pwmd_open_async2(pwm_t
*pwm
, const char *filename
)
1522 #ifndef WITH_PINENTRY
1523 return GPG_ERR_NOT_IMPLEMENTED
;
1525 if (!pwm
|| !filename
)
1526 return GPG_ERR_INV_ARG
;
1529 return GPG_ERR_INV_STATE
;
1531 if (pwm
->cmd
!= ASYNC_CMD_NONE
)
1532 return GPG_ERR_ASS_NESTED_COMMANDS
;
1534 /* Initialize a new command since this is not a pinentry retry. */
1535 if (pwm
->lastcmd
!= ASYNC_CMD_OPEN2
)
1538 pwm
->cmd
= ASYNC_CMD_OPEN2
;
1539 pwm
->state
= ASYNC_PROCESS
;
1540 gpg_error_t rc
= do_pwmd_open(pwm
, filename
, 1, 1);
1543 reset_async(pwm
, 0);
1549 struct open_inquire_s
{
1552 pwmd_inquire_cb_t func
;
1557 /* We need to send the filename argument here rather than confusing the app.
1558 * The app will only send the passphrase and nothing else.
1560 static gpg_error_t
open_inquire_cb(void *user
, const char *cmd
,
1561 gpg_error_t rc
, char **data
, size_t *len
)
1563 struct open_inquire_s
*o
= user
;
1569 char *line
= pwmd_strdup_printf("%s ", o
->filename
);
1570 rc
= assuan_send_data(o
->pwm
->ctx
, line
, strlen(line
));
1574 /* Give the user a chance to cleanup. */
1576 return o
->func(o
->user
, cmd
, rc
, data
, len
);
1581 return o
->func(o
->user
, cmd
, rc
, data
, len
);
1584 gpg_error_t
pwmd_open_inquire(pwm_t
*pwm
, const char *filename
,
1585 pwmd_inquire_cb_t func
, void *user
)
1587 if (!pwm
|| !filename
|| !func
)
1588 return GPG_ERR_INV_ARG
;
1591 return GPG_ERR_INV_STATE
;
1593 struct open_inquire_s
*inq
= pwmd_calloc(1, sizeof(struct open_inquire_s
));
1597 return GPG_ERR_ENOMEM
;
1600 inq
->filename
= pwmd_strdup(filename
);
1604 char *cmd
= pwmd_strdup_printf("OPEN --inquire %s%s",
1605 (pwm
->opts
& OPT_LOCK_ON_OPEN
) ? "--lock " : "",
1606 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "");
1608 rc
= pwmd_inquire(pwm
, cmd
, open_inquire_cb
, inq
);
1610 pwmd_free(inq
->filename
);
1615 pwmd_free(pwm
->filename
);
1617 pwm
->filename
= pwmd_strdup(filename
);
1619 if (!pwm
->filename
) {
1621 rc
= GPG_ERR_ENOMEM
;
1628 gpg_error_t
pwmd_save_inquire(pwm_t
*pwm
, pwmd_inquire_cb_t func
, void *user
)
1631 return GPG_ERR_INV_ARG
;
1634 return GPG_ERR_INV_STATE
;
1637 char *tmp
= pwmd_strdup_printf("%li", pwm
->iterations
);
1638 char *cmd
= pwmd_strdup_printf("SAVE %s --inquire --iterations=%s --cipher=%s",
1639 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
1640 pwm
->iterations
!= -1 ? tmp
: "",
1641 pwm
->cipher
? pwm
->cipher
: "");
1643 rc
= pwmd_inquire(pwm
, cmd
, func
, user
);
1648 static gpg_error_t
do_pwmd_save(pwm_t
*pwm
, int nb
, int local_pinentry
)
1650 char *result
= NULL
;
1651 char *password
= NULL
;
1655 return GPG_ERR_INV_ARG
;
1658 return GPG_ERR_INV_STATE
;
1660 rc
= pwmd_command(pwm
, &result
, "ISCACHED %s", pwm
->filename
);
1662 if (rc
== GPG_ERR_ENOENT
)
1663 rc
= GPG_ERR_NOT_FOUND
;
1665 if (rc
&& rc
!= GPG_ERR_NOT_FOUND
)
1668 if (rc
== GPG_ERR_NOT_FOUND
) {
1669 rc
= get_custom_passphrase(pwm
, &password
);
1671 if (rc
&& rc
!= GPG_ERR_NO_DATA
)
1673 else if (rc
== GPG_ERR_NO_DATA
)
1674 rc
= GPG_ERR_NOT_FOUND
;
1679 if (rc
== GPG_ERR_NOT_FOUND
&& local_pinentry
) {
1680 #ifdef WITH_PINENTRY
1681 /* Get the password using the LOCAL pinentry. */
1685 pwmd_nb_status_t pw
;
1688 return gpg_error_from_syserror();
1701 pw
.error
= _do_save_getpin(pwm
, &password
);
1704 snprintf(pw
.password
, sizeof(pw
.password
), "%s",
1706 pwmd_free(password
);
1709 pth_write(p
[1], &pw
, sizeof(pw
));
1711 write(p
[1], &pw
, sizeof(pw
));
1713 memset(&pw
, 0, sizeof(pw
));
1718 rc
= gpg_error_from_syserror();
1732 rc
= _do_save_getpin(pwm
, &password
);
1739 pwm
->state
= ASYNC_DONE
;
1742 reset_async(pwm
, 0);
1745 if (!local_pinentry
&& !pwm
->tcp_conn
) {
1747 if (!local_pinentry
) {
1749 rc
= send_pinentry_options(pwm
);
1755 char *tmp
= pwmd_strdup_printf("%li", pwm
->iterations
);
1758 rc
= pwmd_command(pwm
, NULL
, "SAVE %s%s--iterations=%s --cipher=%s %s",
1759 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
1760 local_pinentry
|| pwm
->tcp_conn
? "--pinentry=0 " : "",
1761 pwm
->iterations
!= -1 ? tmp
: "",
1762 pwm
->cipher
? pwm
->cipher
: "",
1763 password
? password
: "");
1765 rc
= pwmd_command(pwm
, NULL
, "SAVE %s--iterations=%s --cipher=%s %s",
1766 (pwm
->opts
& OPT_BASE64
) ? "--base64 " : "",
1767 pwm
->iterations
!= -1 ? tmp
: "",
1768 pwm
->cipher
? pwm
->cipher
: "",
1769 password
? password
: "");
1774 if (!pwm
->passfunc
&& password
&& password
!= pwm
->password
)
1775 pwmd_free(password
);
1780 gpg_error_t
pwmd_save_async2(pwm_t
*pwm
)
1782 #ifndef WITH_PINENTRY
1783 return GPG_ERR_NOT_IMPLEMENTED
;
1786 return GPG_ERR_INV_ARG
;
1789 return GPG_ERR_INV_STATE
;
1791 if (pwm
->cmd
!= ASYNC_CMD_NONE
)
1792 return GPG_ERR_ASS_NESTED_COMMANDS
;
1794 pwm
->cmd
= ASYNC_CMD_SAVE2
;
1795 pwm
->state
= ASYNC_PROCESS
;
1796 gpg_error_t rc
= do_pwmd_save(pwm
, 1, 1);
1799 reset_async(pwm
, 0);
1805 gpg_error_t
pwmd_save2(pwm_t
*pwm
)
1807 #ifndef WITH_PINENTRY
1808 return GPG_ERR_NOT_IMPLEMENTED
;
1810 return do_pwmd_save(pwm
, 0, 1);
1814 gpg_error_t
pwmd_save(pwm_t
*pwm
)
1816 return do_pwmd_save(pwm
, 0, 0);
1819 gpg_error_t
pwmd_setopt(pwm_t
*pwm
, pwmd_option_t opt
, ...)
1827 return GPG_ERR_INV_ARG
;
1832 case PWMD_OPTION_BASE64
:
1833 n
= va_arg(ap
, int);
1835 if (n
< 0 || n
> 1) {
1836 rc
= GPG_ERR_INV_VALUE
;
1841 pwm
->opts
|= OPT_BASE64
;
1843 pwm
->opts
&= ~OPT_BASE64
;
1846 case PWMD_OPTION_ITERATIONS
:
1847 pwm
->iterations
= va_arg(ap
, long);
1849 if (pwm
->iterations
< -1) {
1850 pwm
->iterations
= -1;
1851 rc
= GPG_ERR_INV_VALUE
;
1855 case PWMD_OPTION_CIPHER
:
1856 arg1
= va_arg(ap
, char *);
1859 pwmd_free(pwm
->cipher
);
1861 pwm
->cipher
= arg1
? pwmd_strdup(arg1
) : NULL
;
1863 case PWMD_OPTION_LOCK_ON_OPEN
:
1864 n
= va_arg(ap
, int);
1867 rc
= GPG_ERR_INV_VALUE
;
1870 pwm
->opts
|= OPT_LOCK_ON_OPEN
;
1872 pwm
->opts
&= ~OPT_LOCK_ON_OPEN
;
1875 case PWMD_OPTION_INQUIRE_TOTAL
:
1876 pwm
->inquire_total
= va_arg(ap
, size_t);
1878 case PWMD_OPTION_STATUS_CB
:
1879 pwm
->status_func
= va_arg(ap
, pwmd_status_cb_t
);
1881 case PWMD_OPTION_STATUS_DATA
:
1882 pwm
->status_data
= va_arg(ap
, void *);
1884 case PWMD_OPTION_PASSPHRASE_CB
:
1885 pwm
->passfunc
= va_arg(ap
, pwmd_passphrase_cb_t
);
1887 case PWMD_OPTION_PASSPHRASE_DATA
:
1888 pwm
->passdata
= va_arg(ap
, void *);
1890 case PWMD_OPTION_PASSPHRASE
:
1891 arg1
= va_arg(ap
, char *);
1894 pwmd_free(pwm
->password
);
1896 pwm
->password
= arg1
? pwmd_strdup(arg1
) : NULL
;
1898 case PWMD_OPTION_PINENTRY_TRIES
:
1899 n
= va_arg(ap
, int);
1902 rc
= GPG_ERR_INV_VALUE
;
1904 pwm
->pinentry_tries
= n
;
1907 case PWMD_OPTION_PINENTRY_TIMEOUT
:
1908 n
= va_arg(ap
, int);
1911 rc
= GPG_ERR_INV_VALUE
;
1913 pwm
->pinentry_timeout
= n
;
1916 case PWMD_OPTION_PINENTRY_PATH
:
1917 if (pwm
->pinentry_path
)
1918 pwmd_free(pwm
->pinentry_path
);
1920 pwm
->pinentry_path
= _expand_homedir(va_arg(ap
, char *), NULL
);
1922 case PWMD_OPTION_PINENTRY_TTY
:
1923 arg1
= va_arg(ap
, char *);
1925 if (pwm
->pinentry_tty
)
1926 pwmd_free(pwm
->pinentry_tty
);
1928 pwm
->pinentry_tty
= arg1
? pwmd_strdup(arg1
) : NULL
;
1930 case PWMD_OPTION_PINENTRY_DISPLAY
:
1931 if (pwm
->pinentry_display
)
1932 pwmd_free(pwm
->pinentry_display
);
1934 pwm
->pinentry_display
= pwmd_strdup(va_arg(ap
, char *));
1936 case PWMD_OPTION_PINENTRY_TERM
:
1937 arg1
= va_arg(ap
, char *);
1939 if (pwm
->pinentry_term
)
1940 pwmd_free(pwm
->pinentry_term
);
1942 pwm
->pinentry_term
= arg1
? pwmd_strdup(arg1
) : NULL
;
1944 case PWMD_OPTION_PINENTRY_TITLE
:
1946 pwmd_free(pwm
->title
);
1948 pwm
->title
= _percent_escape(va_arg(ap
, char *));
1950 case PWMD_OPTION_PINENTRY_PROMPT
:
1952 pwmd_free(pwm
->prompt
);
1954 pwm
->prompt
= _percent_escape(va_arg(ap
, char *));
1956 case PWMD_OPTION_PINENTRY_DESC
:
1958 pwmd_free(pwm
->desc
);
1960 pwm
->desc
= _percent_escape(va_arg(ap
, char *));
1962 case PWMD_OPTION_PINENTRY_LC_CTYPE
:
1963 arg1
= va_arg(ap
, char *);
1966 pwmd_free(pwm
->lcctype
);
1968 pwm
->lcctype
= arg1
? pwmd_strdup(arg1
) : NULL
;
1970 case PWMD_OPTION_PINENTRY_LC_MESSAGES
:
1971 arg1
= va_arg(ap
, char *);
1973 if (pwm
->lcmessages
)
1974 pwmd_free(pwm
->lcmessages
);
1976 pwm
->lcmessages
= arg1
? pwmd_strdup(arg1
) : NULL
;
1979 case PWMD_OPTION_IP_VERSION
:
1980 n
= va_arg(ap
, int);
1989 rc
= GPG_ERR_INV_VALUE
;
1993 case PWMD_OPTION_KNOWNHOST_CB
:
1994 pwm
->kh_cb
= va_arg(ap
, pwmd_knownhost_cb_t
);
1996 case PWMD_OPTION_KNOWNHOST_DATA
:
1997 pwm
->kh_data
= va_arg(ap
, void *);
1999 case PWMD_OPTION_SSH_AGENT
:
2000 pwm
->use_agent
= va_arg(ap
, int);
2002 if (pwm
->use_agent
< 0 || pwm
->use_agent
> 1) {
2004 rc
= GPG_ERR_INV_VALUE
;
2009 case PWMD_OPTION_IP_VERSION
:
2010 case PWMD_OPTION_KNOWNHOST_CB
:
2011 case PWMD_OPTION_KNOWNHOST_DATA
:
2012 case PWMD_OPTION_SSH_AGENT
:
2013 rc
= GPG_ERR_NOT_IMPLEMENTED
;
2017 rc
= GPG_ERR_UNKNOWN_OPTION
;
2025 gpg_error_t
pwmd_get_fds(pwm_t
*pwm
, pwmd_fd_t
*fds
, int *n_fds
)
2030 int afds
[ARES_GETSOCK_MAXNUM
];
2035 if (!pwm
|| !fds
|| !n_fds
|| *n_fds
<= 0)
2036 return GPG_ERR_INV_ARG
;
2040 memset(afds
, 0, sizeof(int)*ARES_GETSOCK_MAXNUM
);
2042 memset(fds
, 0, sizeof(pwmd_fd_t
)*in_total
);
2047 case ASYNC_CMD_NONE
:
2048 case ASYNC_CMD_OPEN
:
2049 case ASYNC_CMD_SAVE
:
2050 #ifdef WITH_PINENTRY
2054 return GPG_ERR_INV_STATE
;
2057 fds
[fd
].fd
= pwm
->fd
;
2058 fds
[fd
++].flags
= PWMD_FD_READABLE
;
2060 #ifdef WITH_PINENTRY
2061 case ASYNC_CMD_OPEN2
:
2062 case ASYNC_CMD_SAVE2
:
2063 /* The command has already completed (cached or new). */
2064 if (pwm
->state
== ASYNC_DONE
)
2067 if (pwm
->nb_fd
== -1)
2068 return GPG_ERR_INV_STATE
;
2071 fds
[fd
].fd
= pwm
->nb_fd
;
2072 fds
[fd
++].flags
= PWMD_FD_READABLE
;
2077 if (!pwm
->tcp_conn
|| !pwm
->tcp_conn
->chan
)
2078 return GPG_ERR_INV_STATE
;
2080 n
= ares_getsock(pwm
->tcp_conn
->chan
, afds
, ARES_GETSOCK_MAXNUM
);
2082 for (i
= 0; i
< ARES_GETSOCK_MAXNUM
; i
++) {
2085 if (fd
> in_total
) {
2087 return GPG_ERR_ERANGE
;
2090 if (ARES_GETSOCK_READABLE(n
, i
)) {
2092 fds
[fd
].flags
|= PWMD_FD_READABLE
;
2095 if (ARES_GETSOCK_WRITABLE(n
, i
)) {
2097 fds
[fd
].flags
|= PWMD_FD_WRITABLE
;
2101 fds
[fd
++].fd
= afds
[i
];
2106 case ASYNC_CMD_CONNECT
:
2107 case ASYNC_CMD_HOSTKEY
:
2108 if (!pwm
->tcp_conn
|| pwm
->tcp_conn
->fd
== -1)
2109 return GPG_ERR_INV_STATE
;
2112 fds
[fd
].fd
= pwm
->tcp_conn
->fd
;
2113 fds
[fd
++].flags
= PWMD_FD_READABLE
;
2118 return GPG_ERR_INV_STATE
;
2121 pwm_t
*pwmd_new(const char *name
)
2123 pwm_t
*h
= pwmd_calloc(1, sizeof(pwm_t
));
2129 h
->name
= pwmd_strdup(name
);
2138 h
->pinentry_timeout
= -30;
2139 h
->pinentry_tries
= 3;
2142 h
->prot
= PWMD_IP_ANY
;
2145 if (ttyname(STDOUT_FILENO
)) {
2148 ttyname_r(STDOUT_FILENO
, buf
, sizeof(buf
));
2149 h
->pinentry_tty
= pwmd_strdup(buf
);
2151 if (!h
->pinentry_tty
)
2155 if (getenv("TERM") && h
->pinentry_tty
) {
2156 h
->pinentry_term
= pwmd_strdup(getenv("TERM"));
2158 if (!h
->pinentry_term
)
2162 if (getenv("DISPLAY")) {
2163 h
->pinentry_display
= pwmd_strdup(getenv("DISPLAY"));
2165 if (!h
->pinentry_display
)
2176 void pwmd_free(void *ptr
)
2181 void *pwmd_malloc(size_t size
)
2183 return _xmalloc(size
);
2186 void *pwmd_calloc(size_t nmemb
, size_t size
)
2188 return _xcalloc(nmemb
, size
);
2191 void *pwmd_realloc(void *ptr
, size_t size
)
2193 return _xrealloc(ptr
, size
);
2196 char *pwmd_strdup(const char *str
)
2198 return _xstrdup(str
);
2201 char *pwmd_strdup_printf(const char *fmt
, ...)
2212 len
= vsnprintf(NULL
, 0, fmt
, ap
);
2214 buf
= pwmd_malloc(++len
);
2217 vsnprintf(buf
, len
, fmt
, ap2
);
2223 gpg_error_t
pwmd_getpin(pwm_t
*pwm
, const char *filename
, char **result
,
2224 pwmd_pinentry_t which
)
2226 #ifndef WITH_PINENTRY
2227 return GPG_ERR_NOT_IMPLEMENTED
;
2229 return _pwmd_getpin(pwm
, filename
, result
, which
);
2233 const char *pwmd_version()
2235 return LIBPWMD_VERSION_STR
;