2 Copyright (C) 2006-2016, 2017 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
31 #include <sys/types.h>
41 #include <sys/socket.h>
45 #include <sys/select.h>
71 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
72 #include <sys/types.h>
74 #include <sys/socket.h>
76 #include <netinet/in.h>
87 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
96 static gpg_error_t
status_cb (void *data
, const char *line
);
99 hook_read (assuan_context_t ctx
, assuan_fd_t fd
, void *data
, size_t len
)
101 pwm_t
*pwm
= assuan_get_pointer (ctx
);
104 return pwm
->read_cb (pwm
->read_cb_data
, HANDLE2SOCKET (fd
), data
, len
);
106 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
108 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->ssh
)
110 ssize_t ret
= read_hook_ssh (pwm
->tcp
->ssh
, fd
, data
, len
);
116 __assuan_close (ctx
, pwm
->fd
);
117 pwm
->fd
= ASSUAN_INVALID_FD
;
125 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->tls
)
126 return tls_read_hook (pwm
, fd
, data
, len
);
130 return read (HANDLE2SOCKET (fd
), data
, len
);
134 hook_write (assuan_context_t ctx
, assuan_fd_t fd
, const void *data
,
137 pwm_t
*pwm
= assuan_get_pointer (ctx
);
141 return pwm
->write_cb (pwm
->write_cb_data
, HANDLE2SOCKET (fd
), data
, len
);
143 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
145 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->ssh
)
147 ssize_t ret
= write_hook_ssh (pwm
->tcp
->ssh
, fd
, data
, len
);
153 __assuan_close (ctx
, pwm
->fd
);
154 pwm
->fd
= ASSUAN_INVALID_FD
;
162 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->tls
)
163 return tls_write_hook (pwm
, fd
, data
, len
);
167 /* libassuan cannot handle EAGAIN when doing writes. */
170 wrote
= write (HANDLE2SOCKET (fd
), data
, len
);
171 if (wrote
== -1 && errno
== EAGAIN
)
172 __assuan_usleep (pwm
->ctx
, 50000);
174 while (wrote
== -1 && errno
== EAGAIN
);
181 hook_waitpid (assuan_context_t ctx
, pid_t pid
, int action
, int *status
,
186 return waitpid (pid
, status
, options
);
193 static int initialized
;
196 // May be called more than once.
197 gnutls_global_init ();
204 bindtextdomain ("libpwmd", LOCALEDIR
);
210 //gpgrt_set_alloc_func (_xrealloc_gpgrt);
224 gnutls_global_deinit ();
232 _connect_finalize (pwm_t
* pwm
)
236 assuan_fd_t active
[2];
237 int n
= assuan_get_active_fds (pwm
->ctx
, 0, active
, N_ARRAY (active
));
240 return GPG_ERR_EBADFD
;
244 pwm
->pinentry_pid
= -1;
247 rc
= pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
, "GETINFO VERSION");
250 pwm
->version
= strtoul (result
, NULL
, 16);
254 if (!rc
&& pwm
->name
)
255 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION NAME=%s",
262 connect_uds (pwm_t
* pwm
, const char *path
)
265 return GPG_ERR_UNSUPPORTED_PROTOCOL
;
268 return GPG_ERR_INV_ARG
;
270 char *socketpath
= NULL
;
275 pwbuf
= _getpwuid (&pw
);
277 return gpg_error_from_syserror ();
280 socketpath
= pwmd_strdup_printf ("%s/.pwmd/socket", pw
.pw_dir
);
282 socketpath
= _expand_homedir ((char *) path
, &pw
);
286 return GPG_ERR_ENOMEM
;
288 rc
= assuan_socket_connect (pwm
->ctx
, socketpath
, ASSUAN_INVALID_FD
, 0);
289 pwmd_free (socketpath
);
290 return rc
? rc
: _connect_finalize (pwm
);
295 init_handle (pwm_t
* pwm
)
298 static struct assuan_malloc_hooks mhooks
= {
299 pwmd_malloc
, pwmd_realloc
, pwmd_free
301 static struct assuan_system_hooks shooks
= {
302 ASSUAN_SYSTEM_HOOKS_VERSION
,
310 NULL
, //sendmsg both are used for FD passing
322 rc
= assuan_new_ext (&pwm
->ctx
, GPG_ERR_SOURCE_DEFAULT
, &mhooks
, NULL
,
327 assuan_set_pointer (pwm
->ctx
, pwm
);
328 assuan_ctx_set_system_hooks (pwm
->ctx
, &shooks
);
332 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
334 free_tcp (pwm_t
*pwm
)
336 struct tcp_s
*tcp
= pwm
->tcp
;
342 _free_ssh_conn (tcp
->ssh
);
348 pwmd_free (tcp
->host
);
351 freeaddrinfo (tcp
->addrs
);
355 pthread_cond_destroy (&tcp
->dns_cond
);
356 pthread_mutex_destroy (&tcp
->dns_mutex
);
362 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
364 resolve_host_thread (void *arg
)
367 struct addrinfo hints
= { 0 };
373 hints
.ai_family
= AF_UNSPEC
;
376 hints
.ai_family
= AF_INET
;
379 hints
.ai_family
= AF_INET6
;
383 hints
.ai_socktype
= SOCK_STREAM
;
384 snprintf (portstr
, sizeof (portstr
), "%i", pwm
->tcp
->port
);
385 int *n
= pwmd_malloc (sizeof (int));
386 pthread_cleanup_push (pwmd_free
, n
);
387 *n
= getaddrinfo (pwm
->tcp
->host
, portstr
, &hints
, &pwm
->tcp
->addrs
);
388 pthread_cleanup_pop (0);
389 pthread_cond_broadcast (&pwm
->tcp
->dns_cond
);
395 tcp_connect_common (pwm_t
* pwm
)
397 #define TS_TIMEOUT 50000000L
404 n
= pthread_create (&tid
, NULL
, resolve_host_thread
, pwm
);
406 return gpg_error_from_errno (n
);
408 pthread_mutex_lock (&pwm
->tcp
->dns_mutex
);
415 clock_gettime (CLOCK_REALTIME
, &ts
);
416 if (ts
.tv_nsec
+ TS_TIMEOUT
>= 1000000000LL) {
421 ts
.tv_nsec
+= TS_TIMEOUT
;
425 #ifdef HAVE_PTHREAD_CANCEL
426 pthread_cancel (tid
);
427 pthread_join (tid
, NULL
);
429 pthread_join (tid
, (void **)&result
);
432 return GPG_ERR_CANCELED
;
435 n
= pthread_cond_timedwait (&pwm
->tcp
->dns_cond
, &pwm
->tcp
->dns_mutex
,
439 if (pwm
->socket_timeout
&& ts
.tv_sec
- now
>= pwm
->socket_timeout
)
441 #ifdef HAVE_PTHREAD_CANCEL
442 pthread_cancel (tid
);
443 pthread_join (tid
, NULL
);
445 pthread_join (tid
, (void **)&result
);
448 return GPG_ERR_ETIMEDOUT
;
455 #ifdef HAVE_PTHREAD_CANCEL
456 pthread_cancel (tid
);
457 pthread_join (tid
, NULL
);
459 pthread_join (tid
, (void **)&result
);
462 return gpg_error_from_errno (n
);
465 pthread_join (tid
, (void **)&result
);
472 return GPG_ERR_UNKNOWN_HOST
; //FIXME
474 for (pwm
->tcp
->addr
= pwm
->tcp
->addrs
; pwm
->tcp
->addr
;
475 pwm
->tcp
->addr
= pwm
->tcp
->addrs
->ai_next
)
478 pwm
->fh
= _open_osfhandle (socket (pwm
->tcp
->addr
->ai_family
, SOCK_STREAM
, 0), 0);
479 pwm
->fd
= SOCKET2HANDLE (_get_osfhandle (pwm
->fh
));
481 pwm
->fd
= socket (pwm
->tcp
->addr
->ai_family
, SOCK_STREAM
, 0);
483 if (pwm
->fd
== ASSUAN_INVALID_FD
)
485 rc
= gpg_error_from_syserror ();
486 if (pwm
->tcp
->addr
== pwm
->tcp
->addrs
->ai_next
)
491 rc
= set_non_blocking (pwm
->fd
, 1);
494 __assuan_close (pwm
->ctx
, pwm
->fd
);
495 pwm
->fd
= ASSUAN_INVALID_FD
;
499 if (connect (HANDLE2SOCKET (pwm
->fd
), pwm
->tcp
->addr
->ai_addr
,
500 pwm
->tcp
->addr
->ai_family
== AF_INET6
501 ? sizeof (struct sockaddr_in6
)
502 : sizeof (struct sockaddr
)) == -1)
506 unsigned elapsed
= 0;
508 rc
= gpg_error_from_syserror ();
510 int w
= WSAGetLastError ();
515 rc
= GPG_ERR_EINPROGRESS
;
522 if (gpg_err_code (rc
) != GPG_ERR_EINPROGRESS
)
524 __assuan_close (pwm
->ctx
, pwm
->fd
);
525 pwm
->fd
= ASSUAN_INVALID_FD
;
526 if (pwm
->tcp
->addr
== pwm
->tcp
->addrs
->ai_next
)
535 FD_SET (HANDLE2SOCKET (pwm
->fd
), &wfds
);
536 n
= select (HANDLE2SOCKET (pwm
->fd
)+1, NULL
, &wfds
, NULL
, &tv
);
538 if (!n
|| pwm
->cancel
)
541 rc
= gpg_error (GPG_ERR_CANCELED
);
542 else if (++elapsed
>= pwm
->socket_timeout
)
543 rc
= gpg_error (GPG_ERR_ETIMEDOUT
);
549 socklen_t len
= sizeof (int);
554 getsockopt (HANDLE2SOCKET (pwm
->fd
), SOL_SOCKET
, SO_ERROR
, &ret
, &len
);
556 rc
= gpg_error_from_errno (ret
);
558 getsockopt (pwm
->fd
, SOL_SOCKET
, SO_ERROR
, &n
, &len
);
560 rc
= gpg_error_from_errno (n
);
564 rc
= gpg_error_from_syserror ();
568 __assuan_close (pwm
->ctx
, pwm
->fd
);
569 pwm
->fd
= ASSUAN_INVALID_FD
;
570 if (pwm
->tcp
->addr
== pwm
->tcp
->addrs
->ai_next
571 || gpg_err_code (rc
) == GPG_ERR_ETIMEDOUT
584 rc
= set_non_blocking (pwm
->fd
, 0);
587 __assuan_close (pwm
->ctx
, pwm
->fd
);
588 pwm
->fd
= ASSUAN_INVALID_FD
;
597 command_start (pwm_t
*pwm
)
603 pwmd_connect_fd (pwm_t
* pwm
, int fd
)
608 return FINISH (GPG_ERR_INV_ARG
);
611 rc
= init_handle (pwm
);
615 else if (pwm
->fd
!= ASSUAN_INVALID_FD
)
616 return FINISH (GPG_ERR_INV_STATE
);
621 if (!(pwm
->opts
& OPT_SIGPIPE
))
622 signal (SIGPIPE
, SIG_IGN
);
625 rc
= assuan_socket_connect_fd (pwm
->ctx
, fd
, 0);
628 pwm
->fd
= SOCKET2HANDLE (fd
);
629 pwm
->connected
= pwm
->user_fd
= 1;
630 rc
= _connect_finalize (pwm
);
634 pwmd_disconnect (pwm
);
640 pwmd_connect (pwm_t
* pwm
, const char *url
, ...)
646 return FINISH (GPG_ERR_INV_ARG
);
649 rc
= init_handle (pwm
);
651 return FINISH (GPG_ERR_INV_ARG
);
653 else if (pwm
->fd
!= ASSUAN_INVALID_FD
)
654 return FINISH (GPG_ERR_INV_STATE
);
659 if (!(pwm
->opts
& OPT_SIGPIPE
))
660 signal (SIGPIPE
, SIG_IGN
);
666 rc
= GPG_ERR_UNSUPPORTED_PROTOCOL
;
668 if (p
&& (*p
== '/' || *p
== '~'))
669 rc
= connect_uds (pwm
, p
);
670 else if (!p
|| !strncmp (p
, "file://", 7))
674 #ifdef DEFAULT_PWMD_SOCKET
676 p
= DEFAULT_PWMD_SOCKET
;
678 rc
= connect_uds (pwm
, p
);
680 else if (!strncmp (p
, "ssh://", 6) || !strncmp (p
, "ssh6://", 7) ||
681 !strncmp (p
, "ssh4://", 7))
684 return FINISH (GPG_ERR_NOT_IMPLEMENTED
);
688 char *username
= NULL
;
690 if (!strncmp (p
, "ssh6://", 7))
692 pwm
->prot
= PWMD_IPV6
;
695 else if (!strncmp (p
, "ssh4://", 7))
697 pwm
->prot
= PWMD_IPV4
;
702 pwm
->prot
= PWMD_IP_ANY
;
706 rc
= _parse_ssh_url (p
, &host
, &port
, &username
);
710 char *identity
= NULL
;
711 char *knownhosts
= NULL
;
714 identity
= va_arg (ap
, char *);
716 if (!identity
&& !pwm
->use_agent
)
717 rc
= GPG_ERR_INV_ARG
;
719 knownhosts
= va_arg (ap
, char *);
724 rc
= _do_ssh_connect (pwm
, host
, port
, identity
, username
,
728 rc
= _connect_finalize (pwm
);
735 pwmd_free (username
);
736 pwm
->local_pinentry
= 1;
737 pwmd_free (pwm
->ssh_passphrase
);
738 pwm
->ssh_passphrase
= NULL
;
741 else if (!strncmp (p
, "tls://", 6) || !strncmp (p
, "tls6://", 7) ||
742 !strncmp (p
, "tls4://", 7))
745 return FINISH (GPG_ERR_NOT_IMPLEMENTED
);
750 if (!strncmp (p
, "tls6://", 7))
752 pwm
->prot
= PWMD_IPV6
;
755 else if (!strncmp (p
, "tls4://", 7))
757 pwm
->prot
= PWMD_IPV4
;
762 pwm
->prot
= PWMD_IP_ANY
;
766 rc
= tls_parse_url (p
, &host
, &port
);
770 char *clientcert
= NULL
;
771 char *clientkey
= NULL
;
773 char *server_fp
= NULL
;
776 clientcert
= va_arg (ap
, char *);
779 rc
= GPG_ERR_INV_ARG
;
782 clientkey
= va_arg (ap
, char *);
784 rc
= GPG_ERR_INV_ARG
;
787 cacert
= va_arg (ap
, char *);
789 rc
= GPG_ERR_INV_ARG
;
791 server_fp
= va_arg (ap
, char *);
798 rc
= tls_connect (pwm
, host
, port
, clientcert
, clientkey
, cacert
,
799 pwm
->tls_priority
, server_fp
, pwm
->tls_verify
);
802 rc
= _connect_finalize (pwm
);
809 pwm
->local_pinentry
= 1;
820 disconnect (pwm_t
* pwm
)
826 assuan_release (pwm
->ctx
);
828 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
832 pwm
->fd
= ASSUAN_INVALID_FD
;
838 pwmd_close (pwm_t
* pwm
)
844 pwmd_free (pwm
->pinentry_error
);
845 pwmd_free (pwm
->pinentry_desc
);
846 pwmd_free (pwm
->pinentry_prompt
);
847 pwmd_free (pwm
->pinentry_tty
);
848 pwmd_free (pwm
->pinentry_display
);
849 pwmd_free (pwm
->pinentry_term
);
850 pwmd_free (pwm
->pinentry_lcctype
);
851 pwmd_free (pwm
->pinentry_lcmessages
);
852 pwmd_free (pwm
->filename
);
853 pwmd_free (pwm
->name
);
854 pwmd_free (pwm
->passphrase_info
);
855 pwmd_free (pwm
->passphrase_hint
);
856 pwmd_free (pwm
->ssh_passphrase
);
857 pwmd_free (pwm
->tls_priority
);
861 _pinentry_disconnect (pwm
);
868 inquire_realloc_cb (void *data
, const void *buffer
, size_t len
)
870 membuf_t
*mem
= (membuf_t
*) data
;
876 if ((p
= pwmd_realloc (mem
->buf
, mem
->len
+ len
)) == NULL
)
877 return gpg_error (GPG_ERR_ENOMEM
);
880 memcpy ((char *) mem
->buf
+ mem
->len
, buffer
, len
);
886 get_password (pwm_t
* pwm
, char **result
, size_t * len
,
887 pwmd_pinentry_t w
, int echo
)
889 char buf
[ASSUAN_LINELENGTH
+1] = { 0 }, *p
;
891 struct termios told
, tnew
;
901 if (!isatty (STDIN_FILENO
))
903 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
904 return GPG_ERR_ENOTTY
;
910 if (tcgetattr (STDIN_FILENO
, &told
) == -1)
911 return gpg_error_from_syserror ();
913 memcpy (&tnew
, &told
, sizeof (struct termios
));
914 tnew
.c_lflag
&= ~(ECHO
);
915 tnew
.c_lflag
|= ICANON
| ECHONL
;
917 if (tcsetattr (STDIN_FILENO
, TCSANOW
, &tnew
) == -1)
921 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
922 return gpg_error_from_errno (n
);
927 if (pwm
->passphrase_hint
)
928 fprintf(stderr
, N_("Key info: %s\n"), pwm
->passphrase_hint
);
932 case PWMD_PINENTRY_OPEN
:
933 fprintf (stderr
, N_("Passphrase for %s: "), pwm
->filename
);
935 case PWMD_PINENTRY_OPEN_FAILED
:
936 fprintf (stderr
, N_("Invalid passphrase. Passphrase for %s: "),
939 case PWMD_PINENTRY_SAVE
:
940 fprintf (stderr
, N_("New passphrase for %s: "), pwm
->filename
);
942 case PWMD_PINENTRY_SAVE_CONFIRM
:
943 fprintf (stderr
, N_("Repeat passphrase: "));
945 case PWMD_PINENTRY_CONFIRM
:
946 if (pwm
->pinentry_desc
)
947 fprintf (stderr
, "%s", pwm
->pinentry_desc
);
949 if (pwm
->pinentry_prompt
)
950 fprintf (stderr
, "%s", pwm
->pinentry_prompt
);
952 fprintf(stderr
, N_("Confirm [y/N]:"));
957 p
= fgets (buf
, sizeof (buf
), stdin
);
961 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
964 if (!p
|| feof (stdin
))
967 return GPG_ERR_CANCELED
;
970 /* Strip the newline character. */
971 p
[strlen (p
) - 1] = 0;
975 if (w
== PWMD_PINENTRY_CONFIRM
)
977 if (*p
!= 'y' && *p
!= 'Y')
978 return GPG_ERR_CANCELED
;
982 key
= pwmd_strdup_printf ("%s", p
);
983 wipememory (buf
, 0, sizeof (buf
));
985 return GPG_ERR_ENOMEM
;
995 if (w
== PWMD_PINENTRY_CONFIRM
)
996 return GPG_ERR_CANCELED
;
998 /* To satisfy inquire_cb(). */
1000 *result
= pwmd_strdup ("");
1010 pwmd_password (pwm_t
* pwm
, const char *keyword
, char **data
, size_t * size
)
1013 int new_password
= 0;
1014 char *password
= NULL
, *newpass
= NULL
;
1017 command_start (pwm
);
1025 if (!strcmp (keyword
, "NEW_PASSPHRASE"))
1028 if (!new_password
&& pwm
->pinentry_try
)
1032 if (pwm
->disable_pinentry
)
1034 rc
= get_password (pwm
, &password
, size
,
1035 new_password
? PWMD_PINENTRY_SAVE
:
1036 error
? PWMD_PINENTRY_OPEN_FAILED
:
1037 PWMD_PINENTRY_OPEN
, 0);
1038 if (!rc
&& new_password
)
1039 rc
= get_password (pwm
, &newpass
, size
, PWMD_PINENTRY_SAVE_CONFIRM
,
1044 pwmd_pinentry_t which
;
1047 which
= new_password
1048 ? PWMD_PINENTRY_SAVE_FAILED
: PWMD_PINENTRY_OPEN_FAILED
;
1050 which
= new_password
? PWMD_PINENTRY_SAVE
: PWMD_PINENTRY_OPEN
;
1052 rc
= pwmd_getpin (pwm
, pwm
->filename
, &password
, size
, which
);
1053 if (!rc
&& new_password
)
1054 rc
= pwmd_getpin (pwm
, pwm
->filename
, &newpass
, size
,
1055 PWMD_PINENTRY_SAVE_CONFIRM
);
1058 if (!rc
&& new_password
)
1060 if ((!password
&& newpass
) || (!newpass
&& password
)
1061 || (newpass
&& password
&& strcmp (newpass
, password
)))
1063 if (pwm
->disable_pinentry
)
1064 fprintf (stderr
, N_("Passphrases do not match.\n"));
1066 pwmd_free (password
);
1067 pwmd_free (newpass
);
1068 password
= newpass
= NULL
;
1074 (void) pwmd_getpin (pwm
, pwm
->filename
, NULL
, NULL
, PWMD_PINENTRY_CLOSE
);
1075 pwmd_free (newpass
);
1079 pwmd_free (password
);
1085 inquire_cb (void *data
, const char *keyword
)
1087 pwm_t
*pwm
= (pwm_t
*) data
;
1089 int free_result
= 0;
1090 char *result
= NULL
;
1091 int is_password
= 0;
1092 int new_password
= 0;
1094 if (!strcmp (keyword
, "PASSPHRASE") || !strcmp (keyword
, "SIGN_PASSPHRASE"))
1096 else if (!strcmp (keyword
, "NEW_PASSPHRASE") || !strcmp (keyword
, "GENKEY"))
1099 /* Shouldn't get this far without a callback. */
1100 if (!pwm
->override_inquire
&& !pwm
->inquire_func
1101 && !is_password
&& !new_password
)
1102 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB
);
1111 if (!pwm
->override_inquire
&& (is_password
|| new_password
))
1114 rc
= pwmd_password (data
, keyword
, &result
, &len
);
1119 rc
= pwm
->inquire_func (pwm
->inquire_data
, keyword
, rc
, &result
,
1122 /* gpg will truncate a passphrase at the first nil byte which may be bad
1123 * for generated key files. */
1124 if ((!rc
|| gpg_err_code (rc
) == GPG_ERR_EOF
)
1125 && (is_password
|| new_password
))
1127 if (len
&& result
&& *result
)
1129 for (size_t n
= 0; n
< len
; n
++)
1131 if (result
[n
] == 0 && n
+1 != len
)
1132 rc
= GPG_ERR_INV_PASSPHRASE
;
1138 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
1140 #ifndef LIBASSUAN_2_1_0
1141 gpg_error_t trc
= rc
;
1143 /* Cancel this inquire. */
1144 rc
= assuan_send_data (pwm
->ctx
, NULL
, 1);
1150 /* There is a bug (or feature?) in assuan_send_data() that
1151 * when cancelling an inquire the next read from the server is
1152 * not done until the next command making the next command
1153 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
1155 rc
= assuan_read_line (pwm
->ctx
, &line
, &len
);
1157 /* Restore the original error. This differs from the error
1158 * returned from the pwmd command (GPG_ERR_CANCELED). This
1159 * error is returned to the calling function.
1168 if (gpg_err_code (rc
) == GPG_ERR_EOF
|| !rc
)
1170 if (len
<= 0 && !result
)
1175 else if ((len
<= 0 && result
) || (len
&& !result
))
1177 rc
= gpg_error (GPG_ERR_INV_ARG
);
1181 if (pwm
->inquire_maxlen
1182 && pwm
->inquire_sent
+ len
> pwm
->inquire_maxlen
)
1184 rc
= gpg_error (GPG_ERR_TOO_LARGE
);
1186 rc
= pwm
->inquire_func (pwm
->inquire_data
, keyword
, rc
,
1191 arc
= assuan_send_data (pwm
->ctx
, result
, len
);
1192 if (gpg_err_code (rc
) == GPG_ERR_EOF
)
1205 pwm
->inquire_sent
+= len
;
1207 if (pwm
->status_func
)
1209 char buf
[ASSUAN_LINELENGTH
];
1211 snprintf (buf
, sizeof (buf
), "XFER %zu %zu", pwm
->inquire_sent
,
1212 pwm
->inquire_total
);
1213 rc
= pwm
->status_func (pwm
->status_data
, buf
);
1223 pwm
->inquire_maxlen
= pwm
->inquire_sent
= 0;
1228 parse_assuan_line (pwm_t
* pwm
)
1234 rc
= assuan_read_line (pwm
->ctx
, &line
, &len
);
1237 if (line
[0] == 'O' && line
[1] == 'K' &&
1238 (line
[2] == 0 || line
[2] == ' '))
1241 else if (line
[0] == '#')
1244 else if (line
[0] == 'S' && (line
[1] == 0 || line
[1] == ' '))
1246 rc
= status_cb (pwm
, line
[1] == 0 ? line
+ 1 : line
+ 2);
1248 else if (line
[0] == 'E' && line
[1] == 'R' && line
[2] == 'R' &&
1249 (line
[3] == 0 || line
[3] == ' '))
1252 rc
= strtol (line
, NULL
, 10);
1260 reset_handle (pwm_t
*pwm
)
1262 pwm
->fd
= ASSUAN_INVALID_FD
;
1265 pwm
->pinentry_disabled
= 0;
1266 #ifdef WITH_PINENTRY
1268 _pinentry_disconnect (pwm
);
1270 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1283 pwmd_disconnect (pwm_t
* pwm
)
1286 return FINISH (GPG_ERR_INV_ARG
);
1288 command_start (pwm
);
1290 if (pwm
->fd
== ASSUAN_INVALID_FD
)
1291 return FINISH (GPG_ERR_INV_STATE
);
1298 /* Note that this should only be called when not in a command. */
1300 pwmd_process (pwm_t
* pwm
)
1304 struct timeval tv
= { 0, 0 };
1307 if (!pwm
|| pwm
->fd
== ASSUAN_INVALID_FD
)
1308 return FINISH (GPG_ERR_INV_ARG
);
1310 return FINISH (GPG_ERR_INV_STATE
);
1313 FD_SET (HANDLE2SOCKET (pwm
->fd
), &fds
);
1314 n
= select (HANDLE2SOCKET (pwm
->fd
) + 1, &fds
, NULL
, NULL
, &tv
);
1317 return FINISH (gpg_error_from_syserror ());
1321 if (FD_ISSET (HANDLE2SOCKET (pwm
->fd
), &fds
))
1322 rc
= parse_assuan_line (pwm
);
1325 while (!rc
&& assuan_pending_line (pwm
->ctx
))
1326 rc
= parse_assuan_line (pwm
);
1328 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1329 if (gpg_err_code (rc
) == GPG_ERR_EOF
&& pwm
->tcp
)
1331 __assuan_close (pwm
->ctx
, pwm
->fd
);
1332 pwm
->fd
= ASSUAN_INVALID_FD
;
1340 status_cb (void *data
, const char *line
)
1344 if (!strncmp (line
, "INQUIRE_MAXLEN ", 15))
1345 pwm
->inquire_maxlen
= strtol (line
+ 15, NULL
, 10);
1346 else if (!strncmp (line
, "PASSPHRASE_HINT ", 16))
1348 pwmd_free (pwm
->passphrase_hint
);
1349 pwm
->passphrase_hint
= pwmd_strdup (line
+16);
1351 else if (!strncmp (line
, "PASSPHRASE_INFO ", 16))
1353 pwmd_free (pwm
->passphrase_info
);
1354 pwm
->passphrase_info
= pwmd_strdup (line
+16);
1357 else if (!strcmp (line
, "REHANDSHAKE"))
1362 ret
= tls_read_hook (pwm
, pwm
->fd
, buf
, sizeof (buf
));
1365 pwm
->tls_error
= ret
;
1366 return GPG_ERR_GENERAL
;
1371 if (pwm
->status_func
)
1372 return pwm
->status_func (pwm
->status_data
, line
);
1378 _assuan_command (pwm_t
* pwm
, assuan_context_t ctx
,
1379 char **result
, size_t * len
, const char *cmd
)
1385 return FINISH (GPG_ERR_INV_ARG
);
1387 if (strlen (cmd
) >= ASSUAN_LINELENGTH
+ 1)
1388 return FINISH (GPG_ERR_LINE_TOO_LONG
);
1392 rc
= assuan_transact (ctx
, cmd
, inquire_realloc_cb
, &data
,
1393 #if WITH_QUALITY && WITH_PINENTRY
1394 pwm
->pctx
== ctx
? pwm
->_inquire_func
: inquire_cb
,
1395 pwm
->pctx
== ctx
? pwm
->_inquire_data
: pwm
,
1405 pwmd_free (data
.buf
);
1413 inquire_realloc_cb (&data
, "", 1);
1416 *result
= (char *) data
.buf
;
1418 pwmd_free (data
.buf
);
1425 pwm
->inquire_maxlen
= 0;
1430 pwmd_command_ap (pwm_t
* pwm
, char **result
, size_t * rlen
,
1431 pwmd_inquire_cb_t func
, void *user
, const char *cmd
,
1439 return GPG_ERR_INV_ARG
;
1441 command_start (pwm
);
1450 return FINISH (GPG_ERR_INV_ARG
);
1452 return FINISH (GPG_ERR_INV_STATE
);
1455 * C99 allows the dst pointer to be null which will calculate the length
1456 * of the would-be result and return it.
1459 len
= vsnprintf (NULL
, 0, cmd
, ap
);
1460 buf
= (char *) pwmd_malloc (len
+1);
1464 return FINISH (GPG_ERR_ENOMEM
);
1467 if (vsnprintf (buf
, len
+1, cmd
, ap2
) != len
)
1471 return FINISH (GPG_ERR_ENOMEM
);
1474 if (buf
[strlen (buf
) - 1] == '\n')
1475 buf
[strlen (buf
) - 1] = 0;
1476 if (buf
[strlen (buf
) - 1] == '\r')
1477 buf
[strlen (buf
) - 1] = 0;
1479 pwm
->inquire_func
= func
;
1480 pwm
->inquire_data
= user
;
1481 pwm
->inquire_sent
= 0;
1482 gpg_error_t rc
= _assuan_command (pwm
, pwm
->ctx
, result
, rlen
, buf
);
1488 pwmd_command (pwm_t
* pwm
, char **result
, size_t * len
,
1489 pwmd_inquire_cb_t func
, void *user
, const char *cmd
, ...)
1500 return FINISH (GPG_ERR_INV_ARG
);
1502 return FINISH (GPG_ERR_INV_STATE
);
1505 gpg_error_t rc
= pwmd_command_ap (pwm
, result
, len
, func
, user
, cmd
, ap
);
1511 send_pinentry_timeout (pwm_t
*pwm
)
1515 if ((pwm
->pinentry_timeout
>= 0
1516 && pwm
->pinentry_timeout
!= pwm
->current_pinentry_timeout
)
1517 || (pwm
->pinentry_timeout
== -1
1518 && pwm
->pinentry_timeout
!= pwm
->current_pinentry_timeout
))
1520 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1521 "OPTION pinentry-timeout=%i",
1522 pwm
->pinentry_timeout
);
1524 pwm
->current_pinentry_timeout
= pwm
->pinentry_timeout
;
1531 send_pinentry_options (pwm_t
* pwm
)
1535 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1536 "OPTION disable-pinentry=0");
1537 if (!rc
&& pwm
->pinentry_tty
)
1538 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION TTYNAME=%s",
1541 if (!rc
&& pwm
->pinentry_term
)
1542 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION TTYTYPE=%s",
1543 pwm
->pinentry_term
);
1545 if (!rc
&& pwm
->pinentry_display
)
1546 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION DISPLAY=%s",
1547 pwm
->pinentry_display
);
1549 if (!rc
&& pwm
->pinentry_desc
)
1550 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION DESC=%s",
1551 pwm
->pinentry_desc
);
1553 if (!rc
&& pwm
->pinentry_lcctype
)
1554 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION LC_CTYPE=%s",
1555 pwm
->pinentry_lcctype
);
1557 if (!rc
&& pwm
->pinentry_lcmessages
)
1558 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION LC_MESSAGES=%s",
1559 pwm
->pinentry_lcmessages
);
1562 rc
= send_pinentry_timeout (pwm
);
1568 pwmd_socket_type (pwm_t
* pwm
, pwmd_socket_t
* result
)
1570 if (!pwm
|| !result
)
1571 return FINISH (GPG_ERR_INV_ARG
);
1573 *result
= PWMD_SOCKET_LOCAL
;
1575 if (pwm
->fd
== ASSUAN_INVALID_FD
)
1576 return FINISH (GPG_ERR_INV_STATE
);
1578 if (pwm
->user_fd
!= -1)
1580 *result
= PWMD_SOCKET_USER
;
1584 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1586 if (pwm
->tcp
&& pwm
->tcp
->ssh
)
1587 *result
= PWMD_SOCKET_SSH
;
1590 if (pwm
->tcp
&& pwm
->tcp
->tls
)
1591 *result
= PWMD_SOCKET_TLS
;
1598 disable_pinentry (pwm_t
*pwm
, int *disable
)
1601 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1602 int no_pinentry
= pwm
->disable_pinentry
|| pwm
->tcp
|| pwm
->local_pinentry
;
1604 int no_pinentry
= pwm
->disable_pinentry
|| pwm
->local_pinentry
;
1608 *disable
= no_pinentry
;
1610 if (pwm
->pinentry_disabled
&& no_pinentry
)
1612 else if (!pwm
->pinentry_disabled
&& !no_pinentry
)
1615 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION disable-pinentry=%i",
1618 pwm
->pinentry_disabled
= no_pinentry
;
1624 pwmd_open (pwm_t
* pwm
, const char *filename
, pwmd_inquire_cb_t cb
,
1628 int no_pinentry
= 0;
1630 if (!pwm
|| !filename
|| !*filename
)
1631 return FINISH (GPG_ERR_INV_ARG
);
1634 return FINISH (GPG_ERR_INV_STATE
);
1636 command_start (pwm
);
1637 rc
= disable_pinentry (pwm
, &no_pinentry
);
1638 if (!rc
&& !no_pinentry
)
1639 rc
= send_pinentry_options (pwm
);
1643 pwm
->pinentry_try
= 0;
1644 pwmd_free (pwm
->filename
);
1645 pwm
->filename
= pwmd_strdup (filename
);
1649 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "OPEN %s%s",
1650 (pwm
->opts
& OPT_LOCK_ON_OPEN
) ? "--lock " : "",
1653 while (gpg_err_code (rc
) == GPG_ERR_BAD_PASSPHRASE
1654 && pwm
->pinentry_disabled
1655 && ++pwm
->pinentry_try
< pwm
->pinentry_tries
);
1657 pwm
->pinentry_try
= 0;
1661 pwmd_free (pwm
->filename
);
1662 pwm
->filename
= NULL
;
1666 pwmd_free (pwm
->passphrase_hint
);
1667 pwmd_free (pwm
->passphrase_info
);
1668 pwm
->passphrase_info
= pwm
->passphrase_hint
= NULL
;
1673 do_pwmd_save_passwd (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
,
1674 void *data
, int which
)
1677 int no_pinentry
= 0;
1680 return FINISH (GPG_ERR_INV_ARG
);
1682 return FINISH (GPG_ERR_INV_STATE
);
1684 command_start (pwm
);
1685 rc
= disable_pinentry (pwm
, &no_pinentry
);
1686 if (!rc
&& !no_pinentry
)
1687 rc
= send_pinentry_options (pwm
);
1691 if (which
== PWMD_WHICH_SAVE
)
1692 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "SAVE %s", args
? args
: "");
1693 else if (which
== PWMD_WHICH_PASSWD
)
1694 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "PASSWD %s", args
? args
: "");
1695 else if (which
== PWMD_WHICH_GENKEY
)
1696 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "GENKEY %s", args
? args
: "");
1699 pwmd_free (pwm
->passphrase_hint
);
1700 pwmd_free (pwm
->passphrase_info
);
1701 pwm
->passphrase_info
= pwm
->passphrase_hint
= NULL
;
1706 pwmd_passwd (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
, void *data
)
1708 return do_pwmd_save_passwd (pwm
, args
, cb
, data
, PWMD_WHICH_PASSWD
);
1712 pwmd_save (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
, void *data
)
1714 return do_pwmd_save_passwd (pwm
, args
, cb
, data
, PWMD_WHICH_SAVE
);
1718 pwmd_genkey (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
, void *data
)
1720 return do_pwmd_save_passwd (pwm
, args
, cb
, data
, PWMD_WHICH_GENKEY
);
1724 pwmd_get_set_opt (pwm_t
*pwm
, pwmd_option_t opt
, int get
, va_list ap
)
1728 char *arg1
, **charpp
;
1732 return GPG_ERR_INV_ARG
;
1734 command_start (pwm
);
1737 case PWMD_OPTION_SERVER_VERSION
:
1739 return GPG_ERR_NOT_SUPPORTED
;
1742 rc
= GPG_ERR_INV_STATE
;
1745 unsigned *u
= va_arg (ap
, unsigned *);
1750 case PWMD_OPTION_SIGPIPE
:
1753 intp
= va_arg (ap
, int *);
1754 *intp
= pwm
->opts
& OPT_SIGPIPE
? 1 : 0;
1758 n
= va_arg (ap
, int);
1761 rc
= GPG_ERR_INV_VALUE
;
1766 pwm
->opts
|= OPT_SIGPIPE
;
1768 pwm
->opts
&= ~OPT_SIGPIPE
;
1771 case PWMD_OPTION_LOCK_ON_OPEN
:
1774 intp
= va_arg (ap
, int *);
1775 *intp
= pwm
->opts
& OPT_LOCK_ON_OPEN
? 1 : 0;
1779 n
= va_arg (ap
, int);
1782 rc
= GPG_ERR_INV_VALUE
;
1787 pwm
->opts
|= OPT_LOCK_ON_OPEN
;
1789 pwm
->opts
&= ~OPT_LOCK_ON_OPEN
;
1792 case PWMD_OPTION_INQUIRE_TOTAL
:
1795 sizetp
= va_arg (ap
, size_t *);
1796 *sizetp
= pwm
->inquire_total
;
1800 pwm
->inquire_total
= va_arg (ap
, size_t);
1802 case PWMD_OPTION_STATUS_CB
:
1805 pwmd_status_cb_t
*cb
= va_arg (ap
, pwmd_status_cb_t
*);
1807 *cb
= pwm
->status_func
;
1811 pwm
->status_func
= va_arg (ap
, pwmd_status_cb_t
);
1813 case PWMD_OPTION_STATUS_DATA
:
1816 void **data
= va_arg (ap
, void **);
1818 *data
= pwm
->status_data
;
1822 pwm
->status_data
= va_arg (ap
, void *);
1824 case PWMD_OPTION_NO_PINENTRY
:
1827 intp
= va_arg (ap
, int *);
1828 *intp
= pwm
->disable_pinentry
;
1832 n
= va_arg (ap
, int);
1834 rc
= GPG_ERR_INV_VALUE
;
1836 pwm
->disable_pinentry
= n
;
1838 case PWMD_OPTION_LOCAL_PINENTRY
:
1841 intp
= va_arg (ap
, int *);
1842 *intp
= pwm
->local_pinentry
;
1846 n
= va_arg (ap
, int);
1848 rc
= GPG_ERR_INV_VALUE
;
1850 pwm
->local_pinentry
= n
;
1853 case PWMD_OPTION_PINENTRY_TIMEOUT
:
1856 intp
= va_arg (ap
, int *);
1857 *intp
= pwm
->pinentry_timeout
;
1861 n
= va_arg (ap
, int);
1863 rc
= GPG_ERR_INV_VALUE
;
1865 pwm
->pinentry_timeout
= n
;
1867 case PWMD_OPTION_PINENTRY_TRIES
:
1870 intp
= va_arg (ap
, int *);
1871 *intp
= pwm
->pinentry_tries
;
1875 n
= va_arg (ap
, int);
1877 rc
= GPG_ERR_INV_VALUE
;
1879 pwm
->pinentry_tries
= n
;
1881 case PWMD_OPTION_PINENTRY_PATH
:
1884 charpp
= va_arg (ap
, char **);
1885 *charpp
= pwm
->pinentry_path
;
1889 arg1
= va_arg (ap
, char *);
1890 pwmd_free (pwm
->pinentry_path
);
1892 pwm
->pinentry_path
= arg1
? pwmd_strdup (arg1
) : NULL
;
1894 pwm
->pinentry_path
= arg1
? _expand_homedir (arg1
, NULL
) : NULL
;
1897 case PWMD_OPTION_PINENTRY_TTY
:
1900 charpp
= va_arg (ap
, char **);
1901 *charpp
= pwm
->pinentry_tty
;
1905 arg1
= va_arg (ap
, char *);
1906 pwmd_free (pwm
->pinentry_tty
);
1907 pwm
->pinentry_tty
= arg1
? pwmd_strdup (arg1
) : NULL
;
1909 case PWMD_OPTION_PINENTRY_DISPLAY
:
1912 charpp
= va_arg (ap
, char **);
1913 *charpp
= pwm
->pinentry_display
;
1917 arg1
= va_arg (ap
, char *);
1918 pwmd_free (pwm
->pinentry_display
);
1919 pwm
->pinentry_display
= arg1
&& *arg1
? pwmd_strdup (arg1
) : NULL
;
1921 if (!pwm
->pinentry_display
)
1922 unsetenv ("DISPLAY");
1925 case PWMD_OPTION_PINENTRY_TERM
:
1928 charpp
= va_arg (ap
, char **);
1929 *charpp
= pwm
->pinentry_term
;
1933 arg1
= va_arg (ap
, char *);
1934 pwmd_free (pwm
->pinentry_term
);
1935 pwm
->pinentry_term
= arg1
&& *arg1
? pwmd_strdup (arg1
) : NULL
;
1937 if (pwm
->pinentry_term
)
1941 case PWMD_OPTION_PINENTRY_ERROR
:
1944 charpp
= va_arg (ap
, char **);
1945 *charpp
= pwm
->pinentry_error
;
1949 arg1
= va_arg (ap
, char *);
1950 pwmd_free (pwm
->pinentry_error
);
1951 if (pwm
->disable_pinentry
)
1952 pwm
->pinentry_error
= arg1
? pwmd_strdup (arg1
) : NULL
;
1954 pwm
->pinentry_error
= arg1
? _percent_escape (arg1
) : NULL
;
1956 case PWMD_OPTION_PINENTRY_PROMPT
:
1959 charpp
= va_arg (ap
, char **);
1960 *charpp
= pwm
->pinentry_prompt
;
1964 arg1
= va_arg (ap
, char *);
1965 pwmd_free (pwm
->pinentry_prompt
);
1966 if (pwm
->disable_pinentry
)
1967 pwm
->pinentry_prompt
= arg1
? pwmd_strdup (arg1
) : NULL
;
1969 pwm
->pinentry_prompt
= arg1
? _percent_escape (arg1
) : NULL
;
1971 case PWMD_OPTION_PINENTRY_DESC
:
1974 charpp
= va_arg (ap
, char **);
1975 *charpp
= pwm
->pinentry_desc
;
1979 arg1
= va_arg (ap
, char *);
1980 pwmd_free (pwm
->pinentry_desc
);
1981 if (pwm
->disable_pinentry
)
1982 pwm
->pinentry_desc
= arg1
? pwmd_strdup (arg1
) : NULL
;
1984 pwm
->pinentry_desc
= arg1
? _percent_escape (arg1
) : NULL
;
1986 case PWMD_OPTION_PINENTRY_LC_CTYPE
:
1989 charpp
= va_arg (ap
, char **);
1990 *charpp
= pwm
->pinentry_lcctype
;
1994 arg1
= va_arg (ap
, char *);
1995 pwmd_free (pwm
->pinentry_lcctype
);
1996 pwm
->pinentry_lcctype
= arg1
? pwmd_strdup (arg1
) : NULL
;
1998 case PWMD_OPTION_PINENTRY_LC_MESSAGES
:
2001 charpp
= va_arg (ap
, char **);
2002 *charpp
= pwm
->pinentry_lcmessages
;
2006 arg1
= va_arg (ap
, char *);
2007 pwmd_free (pwm
->pinentry_lcmessages
);
2008 pwm
->pinentry_lcmessages
= arg1
? pwmd_strdup (arg1
) : NULL
;
2010 case PWMD_OPTION_KNOWNHOST_CB
:
2013 pwmd_knownhost_cb_t
*cb
= va_arg (ap
, pwmd_knownhost_cb_t
*);
2019 pwm
->kh_cb
= va_arg (ap
, pwmd_knownhost_cb_t
);
2021 case PWMD_OPTION_KNOWNHOST_DATA
:
2024 void **data
= va_arg (ap
, void **);
2026 *data
= pwm
->kh_data
;
2030 pwm
->kh_data
= va_arg (ap
, void *);
2032 case PWMD_OPTION_SSH_AGENT
:
2035 intp
= va_arg (ap
, int *);
2036 *intp
= pwm
->use_agent
;
2040 n
= va_arg (ap
, int);
2042 rc
= GPG_ERR_INV_VALUE
;
2046 case PWMD_OPTION_SSH_PASSPHRASE
:
2048 return GPG_ERR_NOT_SUPPORTED
;
2050 pwmd_free (pwm
->ssh_passphrase
);
2051 pwm
->ssh_passphrase
= NULL
;
2052 arg1
= va_arg (ap
, char *);
2055 pwm
->ssh_passphrase
= pwmd_strdup (arg1
);
2056 if (!pwm
->ssh_passphrase
)
2057 return GPG_ERR_ENOMEM
;
2060 case PWMD_OPTION_SSH_NEEDS_PASSPHRASE
:
2063 intp
= va_arg (ap
, int *);
2064 *intp
= pwm
->needs_passphrase
;
2068 n
= va_arg (ap
, int);
2070 rc
= GPG_ERR_INV_VALUE
;
2072 pwm
->needs_passphrase
= n
;
2074 case PWMD_OPTION_TLS_VERIFY
:
2077 intp
= va_arg (ap
, int *);
2078 *intp
= pwm
->tls_verify
;
2082 n
= va_arg (ap
, int);
2084 rc
= GPG_ERR_INV_VALUE
;
2086 pwm
->tls_verify
= n
;
2088 case PWMD_OPTION_TLS_PRIORITY
:
2091 charpp
= va_arg (ap
, char **);
2092 *charpp
= pwm
->tls_priority
;
2096 pwmd_free (pwm
->tls_priority
);
2097 pwm
->tls_priority
= NULL
;
2098 arg1
= va_arg (ap
, char *);
2101 pwm
->tls_priority
= pwmd_strdup (arg1
);
2102 if (!pwm
->tls_priority
)
2103 rc
= GPG_ERR_ENOMEM
;
2106 case PWMD_OPTION_SOCKET_TIMEOUT
:
2109 intp
= va_arg (ap
, int *);
2110 *intp
= pwm
->socket_timeout
;
2114 n
= va_arg (ap
, int);
2117 rc
= GPG_ERR_INV_VALUE
;
2121 pwm
->socket_timeout
= n
;
2124 if (pwm
->tcp
&& pwm
->tcp
->ssh
&& pwm
->tcp
->ssh
->session
)
2126 pwm
->tcp
->ssh
->timeout
= pwm
->socket_timeout
;
2127 libssh2_session_set_timeout (pwm
->tcp
->ssh
->session
,
2128 pwm
->socket_timeout
* 1000);
2132 if (pwm
->tcp
&& pwm
->tcp
->tls
&& pwm
->tcp
->tls
->session
)
2133 pwm
->tcp
->tls
->timeout
= pwm
->socket_timeout
;
2136 case PWMD_OPTION_READ_CB
:
2139 pwmd_read_cb_t
*cb
= va_arg (ap
, pwmd_read_cb_t
*);
2144 pwm
->read_cb
= va_arg (ap
, pwmd_read_cb_t
);
2146 case PWMD_OPTION_READ_CB_DATA
:
2149 void **data
= va_arg (ap
, void **);
2151 *data
= pwm
->read_cb_data
;
2155 pwm
->read_cb_data
= va_arg (ap
, void *);
2157 case PWMD_OPTION_WRITE_CB
:
2160 pwmd_write_cb_t
*cb
= va_arg (ap
, pwmd_write_cb_t
*);
2162 *cb
= pwm
->write_cb
;
2165 pwm
->write_cb
= va_arg (ap
, pwmd_write_cb_t
);
2167 case PWMD_OPTION_WRITE_CB_DATA
:
2170 void **data
= va_arg (ap
, void **);
2172 *data
= pwm
->write_cb_data
;
2176 pwm
->write_cb_data
= va_arg (ap
, void *);
2178 case PWMD_OPTION_OVERRIDE_INQUIRE
:
2181 intp
= va_arg (ap
, int *);
2182 *intp
= pwm
->override_inquire
;
2186 n
= va_arg (ap
, int);
2188 rc
= GPG_ERR_INV_VALUE
;
2190 pwm
->override_inquire
= n
;
2193 rc
= GPG_ERR_UNKNOWN_OPTION
;
2201 pwmd_setopt (pwm_t
* pwm
, int opt
, ...)
2207 rc
= pwmd_get_set_opt (pwm
, opt
, 0, ap
);
2213 pwmd_getopt (pwm_t
*pwm
, int opt
, ...)
2219 rc
= pwmd_get_set_opt (pwm
, opt
, 1, ap
);
2225 set_rcdefaults (pwm_t
*pwm
, char *filename
)
2229 char *line
= NULL
, *p
;
2230 unsigned line_n
= 0;
2234 if (!filename
&& isatty (STDIN_FILENO
))
2237 int err
= ttyname_r (STDOUT_FILENO
, buf
, sizeof (buf
));
2241 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, buf
);
2245 if (getenv ("TERM"))
2247 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, getenv ("TERM"));
2254 if (!filename
&& getenv ("DISPLAY"))
2256 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, getenv ("DISPLAY"));
2263 f
= pwmd_strdup ("libpwmd.conf");
2265 f
= _expand_homedir (filename
? filename
: (char *)"~/.config/libpwmd.conf",
2270 line
= pwmd_malloc (LINE_MAX
);
2273 fp
= fopen (f
, "r");
2282 rc
= GPG_ERR_ENOMEM
;
2285 rc
= GPG_ERR_ENOMEM
;
2294 while ((p
= fgets (line
, LINE_MAX
, fp
)))
2296 char name
[32] = {0}, val
[512] = {0};
2303 while (isspace (*p
))
2306 if (!*p
|| *p
== '#')
2309 if (p
[strlen (p
)-1] == '\n')
2310 p
[strlen (p
)-1] = 0;
2312 t
= strchr (p
, '=');
2315 fprintf(stderr
, N_("%s(%u): malformed line\n"), f
, line_n
);
2319 for (np
= name
; p
!= t
; p
++)
2321 if (++len
== sizeof (name
))
2330 while (isspace (*t
))
2333 while (isspace (*t
))
2336 strncpy (val
, t
, sizeof (val
)-1);
2338 if (!strcasecmp (name
, "pinentry-path"))
2339 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, val
);
2340 else if (!strcasecmp (name
, "pinentry-tries"))
2341 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, atoi (val
));
2342 else if (!strcasecmp (name
, "pinentry-timeout"))
2343 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, atoi (val
));
2344 else if (!strcasecmp (name
, "no-pinentry"))
2345 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, !!(atoi (val
)));
2346 else if (!strcasecmp (name
, "local-pinentry"))
2347 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, !!(atoi (val
)));
2348 else if (!strcasecmp (name
, "pinentry-display"))
2349 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, val
);
2350 else if (!strcasecmp (name
, "pinentry-ttyname"))
2351 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, val
);
2352 else if (!strcasecmp (name
, "pinentry-ttytype"))
2353 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, val
);
2354 else if (!strcasecmp (name
, "pinentry-lc-messages"))
2355 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, val
);
2356 else if (!strcasecmp (name
, "pinentry-lc-ctype"))
2357 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, val
);
2358 else if (!strcasecmp (name
, "no-ssh-agent"))
2359 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, !(atoi (val
)));
2360 else if (!strcasecmp (name
, "no-tls-verify"))
2361 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, !(atoi (val
)));
2362 else if (!strcasecmp (name
, "tls-priority"))
2363 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_PRIORITY
, val
);
2364 else if (!strcasecmp (name
, "socket-timeout"))
2365 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, atoi (val
));
2366 else if (!strcasecmp (name
, "no-lock"))
2367 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, !(atoi (val
)));
2368 else if (!strcasecmp (name
, "include"))
2369 rc
= set_rcdefaults (pwm
, val
);
2371 fprintf(stderr
, N_("%s(%u): invalid option '%s', ignored.\n"), f
,
2385 pwmd_new (const char *name
, pwm_t
** pwm
)
2387 pwm_t
*h
= pwmd_calloc (1, sizeof (pwm_t
));
2391 return FINISH (GPG_ERR_ENOMEM
);
2395 h
->name
= pwmd_strdup (name
);
2399 return FINISH (GPG_ERR_ENOMEM
);
2404 h
->pinentry_timeout
= -1;
2405 h
->current_pinentry_timeout
= -1;
2406 h
->pinentry_tries
= 3;
2407 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2408 h
->prot
= PWMD_IP_ANY
;
2409 h
->socket_timeout
= 120;
2414 WSAStartup (0x202, &wsdata
);
2418 h
->opts
|= OPT_LOCK_ON_OPEN
;
2420 rc
= set_rcdefaults (h
, NULL
);
2433 pwmd_free (void *ptr
)
2439 pwmd_malloc (size_t size
)
2441 return _xmalloc (size
);
2445 pwmd_calloc (size_t nmemb
, size_t size
)
2447 return _xcalloc (nmemb
, size
);
2451 pwmd_realloc (void *ptr
, size_t size
)
2453 return _xrealloc (ptr
, size
);
2457 pwmd_strdup (const char *str
)
2464 t
= _xmalloc ((len
+ 1) * sizeof (char));
2468 for (c
= 0; c
< len
; c
++)
2476 pwmd_strdup_printf (const char *fmt
, ...)
2487 len
= vsnprintf (NULL
, 0, fmt
, ap
);
2489 buf
= pwmd_malloc (++len
);
2491 vsnprintf (buf
, len
, fmt
, ap2
);
2498 pwmd_getpin (pwm_t
* pwm
, const char *filename
, char **result
,
2499 size_t * len
, pwmd_pinentry_t which
)
2501 #ifndef WITH_PINENTRY
2502 return FINISH (GPG_ERR_NOT_IMPLEMENTED
);
2506 command_start (pwm
);
2507 if (which
== PWMD_PINENTRY_CONFIRM
&& pwm
->disable_pinentry
)
2509 rc
= get_password (pwm
, NULL
, NULL
, which
, 1);
2513 rc
= _pwmd_getpin (pwm
, filename
, result
, len
, which
);
2521 return LIBPWMD_VERSION_STR
;
2529 #ifdef WITH_PINENTRY
2530 n
|= PWMD_FEATURE_PINENTRY
;
2533 n
|= PWMD_FEATURE_SSH
;
2536 n
|= PWMD_FEATURE_QUALITY
;
2539 n
|= PWMD_FEATURE_GNUTLS
;
2545 pwmd_fd (pwm_t
* pwm
, int *fd
)
2548 return FINISH (GPG_ERR_INV_ARG
);
2550 if (pwm
->fd
== ASSUAN_INVALID_FD
)
2551 return FINISH (GPG_ERR_INV_STATE
);
2553 *fd
= HANDLE2SOCKET (pwm
->fd
);
2558 pwmd_set_pointer (pwm_t
*pwm
, void *data
)
2560 pwm
->user_data
= data
;
2564 pwmd_get_pointer (pwm_t
*pwm
)
2566 return pwm
->user_data
;
2570 pwmd_gnutls_error (pwm_t
*pwm
, const char **str
)
2577 if (str
&& pwm
&& pwm
->tls_error
)
2578 *str
= gnutls_strerror (pwm
->tls_error
);
2580 return pwm
? pwm
->tls_error
: 0;
2585 pwmd_cancel (pwm_t
*pwm
)
2588 return FINISH (GPG_ERR_INV_ARG
);
2590 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2591 if (pwm
->fd
== ASSUAN_INVALID_FD
&& !pwm
->tcp
)
2593 if (pwm
->fd
== ASSUAN_INVALID_FD
)
2595 return FINISH (GPG_ERR_INV_STATE
);
2597 /* Can only cancel the connection for the time being. */
2599 return FINISH (GPG_ERR_INV_STATE
);
2606 pwmd_test_quality (const char *str
, double *result
)
2608 #ifndef WITH_QUALITY
2611 return GPG_ERR_NOT_IMPLEMENTED
;
2614 return GPG_ERR_INV_ARG
;
2616 *result
= ZxcvbnMatch (str
, NULL
, NULL
);