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
32 #include <sys/types.h>
33 #include <sys/socket.h>
43 #include <sys/select.h>
67 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
68 #include <sys/types.h>
69 #include <sys/socket.h>
71 #include <netinet/in.h>
81 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
90 static gpg_error_t
status_cb (void *data
, const char *line
);
93 hook_read (assuan_context_t ctx
, assuan_fd_t fd
, void *data
, size_t len
)
95 pwm_t
*pwm
= assuan_get_pointer (ctx
);
98 return pwm
->read_cb (pwm
->read_cb_data
, fd
, data
, len
);
100 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
102 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->ssh
)
103 return read_hook_ssh (pwm
->tcp
->ssh
, fd
, data
, len
);
106 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->tls
)
107 return tls_read_hook (pwm
, fd
, data
, len
);
111 return read ((int) fd
, data
, len
);
115 hook_write (assuan_context_t ctx
, assuan_fd_t fd
, const void *data
,
118 pwm_t
*pwm
= assuan_get_pointer (ctx
);
122 return pwm
->write_cb (pwm
->write_cb_data
, fd
, data
, len
);
124 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
126 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->ssh
)
127 return write_hook_ssh (pwm
->tcp
->ssh
, fd
, data
, len
);
130 if (pwm
&& pwm
->tcp
&& pwm
->tcp
->tls
)
131 return tls_write_hook (pwm
, fd
, data
, len
);
135 /* libassuan cannot handle EAGAIN when doing writes. */
138 wrote
= write ((int) fd
, data
, len
);
139 if (wrote
== -1 && errno
== EAGAIN
)
142 while (wrote
== -1 && errno
== EAGAIN
);
148 hook_waitpid (assuan_context_t ctx
, pid_t pid
, int action
, int *status
,
153 return waitpid (pid
, status
, options
);
159 static int initialized
;
162 // May be called more than once.
163 gnutls_global_init ();
170 bindtextdomain ("libpwmd", LOCALEDIR
);
176 //gpgrt_set_alloc_func (_xrealloc_gpgrt);
190 gnutls_global_deinit ();
198 _connect_finalize (pwm_t
* pwm
)
203 int n
= assuan_get_active_fds (pwm
->ctx
, 0, active
, N_ARRAY (active
));
206 return GPG_ERR_EBADFD
;
210 pwm
->pinentry_pid
= -1;
213 rc
= pwmd_command (pwm
, &result
, NULL
, NULL
, NULL
, "GETINFO VERSION");
216 pwm
->version
= strtoul (result
, NULL
, 16);
220 if (!rc
&& pwm
->name
)
221 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION NAME=%s",
228 connect_uds (pwm_t
* pwm
, const char *path
)
230 char *socketpath
= NULL
;
236 return GPG_ERR_INV_ARG
;
238 pwbuf
= _getpwuid (&pw
);
240 return gpg_error_from_syserror ();
243 socketpath
= pwmd_strdup_printf ("%s/.pwmd/socket", pw
.pw_dir
);
245 socketpath
= _expand_homedir ((char *) path
, &pw
);
249 return GPG_ERR_ENOMEM
;
251 rc
= assuan_socket_connect (pwm
->ctx
, socketpath
, ASSUAN_INVALID_FD
, 0);
252 pwmd_free (socketpath
);
253 return rc
? rc
: _connect_finalize (pwm
);
257 init_handle (pwm_t
* pwm
)
260 static struct assuan_malloc_hooks mhooks
= {
261 pwmd_malloc
, pwmd_realloc
, pwmd_free
263 static struct assuan_system_hooks shooks
= {
264 ASSUAN_SYSTEM_HOOKS_VERSION
,
272 NULL
, //sendmsg both are used for FD passing
280 rc
= assuan_new_ext (&pwm
->ctx
, GPG_ERR_SOURCE_DEFAULT
, &mhooks
, NULL
,
285 assuan_set_pointer (pwm
->ctx
, pwm
);
286 assuan_ctx_set_system_hooks (pwm
->ctx
, &shooks
);
290 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
292 free_tcp (pwm_t
*pwm
)
294 struct tcp_s
*tcp
= pwm
->tcp
;
300 _free_ssh_conn (tcp
->ssh
);
306 pwmd_free (tcp
->host
);
309 freeaddrinfo (tcp
->addrs
);
313 pthread_cond_destroy (&tcp
->dns_cond
);
314 pthread_mutex_destroy (&tcp
->dns_mutex
);
320 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
322 resolve_host_thread (void *arg
)
325 struct addrinfo hints
= { 0 };
331 hints
.ai_family
= AF_UNSPEC
;
334 hints
.ai_family
= AF_INET
;
337 hints
.ai_family
= AF_INET6
;
341 hints
.ai_socktype
= SOCK_STREAM
;
342 snprintf (portstr
, sizeof (portstr
), "%i", pwm
->tcp
->port
);
343 int *n
= pwmd_malloc (sizeof (int));
344 pthread_cleanup_push (pwmd_free
, n
);
345 *n
= getaddrinfo (pwm
->tcp
->host
, portstr
, &hints
, &pwm
->tcp
->addrs
);
346 pthread_cleanup_pop (0);
347 pthread_cond_broadcast (&pwm
->tcp
->dns_cond
);
353 tcp_connect_common (pwm_t
* pwm
)
355 #define TS_TIMEOUT 50000000L
362 n
= pthread_create (&tid
, NULL
, resolve_host_thread
, pwm
);
364 return gpg_error_from_errno (n
);
366 pthread_mutex_lock (&pwm
->tcp
->dns_mutex
);
373 clock_gettime (CLOCK_REALTIME
, &ts
);
374 if (ts
.tv_nsec
+ TS_TIMEOUT
>= 1000000000LL) {
379 ts
.tv_nsec
+= TS_TIMEOUT
;
383 #ifdef HAVE_PTHREAD_CANCEL
384 pthread_cancel (tid
);
385 pthread_join (tid
, NULL
);
387 pthread_join (tid
, (void **)&result
);
390 return GPG_ERR_CANCELED
;
393 n
= pthread_cond_timedwait (&pwm
->tcp
->dns_cond
, &pwm
->tcp
->dns_mutex
,
397 if (pwm
->socket_timeout
&& ts
.tv_sec
- now
>= pwm
->socket_timeout
)
399 #ifdef HAVE_PTHREAD_CANCEL
400 pthread_cancel (tid
);
401 pthread_join (tid
, NULL
);
403 pthread_join (tid
, (void **)&result
);
406 return GPG_ERR_ETIMEDOUT
;
413 #ifdef HAVE_PTHREAD_CANCEL
414 pthread_cancel (tid
);
415 pthread_join (tid
, NULL
);
417 pthread_join (tid
, (void **)&result
);
420 return gpg_error_from_errno (n
);
423 pthread_join (tid
, (void **)&result
);
430 return GPG_ERR_UNKNOWN_HOST
; //FIXME
432 for (pwm
->tcp
->addr
= pwm
->tcp
->addrs
; pwm
->tcp
->addr
;
433 pwm
->tcp
->addr
= pwm
->tcp
->addrs
->ai_next
)
435 pwm
->fd
= socket (pwm
->tcp
->addr
->ai_family
, SOCK_STREAM
, 0);
438 rc
= gpg_error_from_syserror ();
439 if (pwm
->tcp
->addr
== pwm
->tcp
->addrs
->ai_next
)
444 if (fcntl (pwm
->fd
, F_SETFL
, O_NONBLOCK
) == -1)
446 rc
= gpg_error_from_syserror ();
450 if (connect (pwm
->fd
, pwm
->tcp
->addr
->ai_addr
,
451 pwm
->tcp
->addr
->ai_family
== AF_INET6
452 ? sizeof (struct sockaddr_in6
)
453 : sizeof (struct sockaddr
)) == -1)
457 unsigned elapsed
= 0;
459 rc
= gpg_error_from_syserror ();
460 if (gpg_err_code (rc
) != GPG_ERR_EINPROGRESS
)
464 if (pwm
->tcp
->addr
== pwm
->tcp
->addrs
->ai_next
)
473 FD_SET (pwm
->fd
, &wfds
);
474 n
= select (pwm
->fd
+1, NULL
, &wfds
, NULL
, &tv
);
476 if (!n
|| pwm
->cancel
)
479 rc
= gpg_error (GPG_ERR_CANCELED
);
480 else if (++elapsed
>= pwm
->socket_timeout
)
481 rc
= gpg_error (GPG_ERR_ETIMEDOUT
);
487 socklen_t len
= sizeof(int);
489 getsockopt (pwm
->fd
, SOL_SOCKET
, SO_ERROR
, &n
, &len
);
491 rc
= gpg_error_from_errno (n
);
494 rc
= gpg_error_from_syserror ();
500 if (pwm
->tcp
->addr
== pwm
->tcp
->addrs
->ai_next
501 || gpg_err_code (rc
) == GPG_ERR_ETIMEDOUT
513 if (fcntl (pwm
->fd
, F_SETFL
, 0) == -1)
514 rc
= gpg_error_from_syserror ();
521 command_start (pwm_t
*pwm
)
527 pwmd_connect_fd (pwm_t
* pwm
, int fd
)
532 return FINISH (GPG_ERR_INV_ARG
);
535 rc
= init_handle (pwm
);
539 else if (pwm
->fd
!= -1)
540 return FINISH (GPG_ERR_INV_STATE
);
544 if (!(pwm
->opts
& OPT_SIGPIPE
))
545 signal (SIGPIPE
, SIG_IGN
);
547 rc
= assuan_socket_connect_fd (pwm
->ctx
, fd
, 0);
551 pwm
->connected
= pwm
->user_fd
= 1;
552 rc
= _connect_finalize (pwm
);
556 pwmd_disconnect (pwm
);
562 pwmd_connect (pwm_t
* pwm
, const char *url
, ...)
568 return FINISH (GPG_ERR_INV_ARG
);
571 rc
= init_handle (pwm
);
573 return FINISH (GPG_ERR_INV_ARG
);
575 else if (pwm
->fd
!= -1)
576 return FINISH (GPG_ERR_INV_STATE
);
580 if (!(pwm
->opts
& OPT_SIGPIPE
))
581 signal (SIGPIPE
, SIG_IGN
);
586 rc
= GPG_ERR_UNSUPPORTED_PROTOCOL
;
588 if (p
&& (*p
== '/' || *p
== '~'))
589 rc
= connect_uds (pwm
, p
);
590 else if (!p
|| !strncmp (p
, "file://", 7))
594 #ifdef DEFAULT_PWMD_SOCKET
596 p
= DEFAULT_PWMD_SOCKET
;
598 rc
= connect_uds (pwm
, p
);
600 else if (!strncmp (p
, "ssh://", 6) || !strncmp (p
, "ssh6://", 7) ||
601 !strncmp (p
, "ssh4://", 7))
604 return FINISH (GPG_ERR_NOT_IMPLEMENTED
);
608 char *username
= NULL
;
610 if (!strncmp (p
, "ssh6://", 7))
612 pwm
->prot
= PWMD_IPV6
;
615 else if (!strncmp (p
, "ssh4://", 7))
617 pwm
->prot
= PWMD_IPV4
;
622 pwm
->prot
= PWMD_IP_ANY
;
626 rc
= _parse_ssh_url (p
, &host
, &port
, &username
);
630 char *identity
= NULL
;
631 char *knownhosts
= NULL
;
634 identity
= va_arg (ap
, char *);
636 if (!identity
&& !pwm
->use_agent
)
637 rc
= GPG_ERR_INV_ARG
;
639 knownhosts
= va_arg (ap
, char *);
644 rc
= _do_ssh_connect (pwm
, host
, port
, identity
, username
,
648 rc
= _connect_finalize (pwm
);
655 pwmd_free (username
);
656 pwm
->local_pinentry
= 1;
657 pwmd_free (pwm
->ssh_passphrase
);
658 pwm
->ssh_passphrase
= NULL
;
661 else if (!strncmp (p
, "tls://", 6) || !strncmp (p
, "tls6://", 7) ||
662 !strncmp (p
, "tls4://", 7))
665 return FINISH (GPG_ERR_NOT_IMPLEMENTED
);
670 if (!strncmp (p
, "tls6://", 7))
672 pwm
->prot
= PWMD_IPV6
;
675 else if (!strncmp (p
, "tls4://", 7))
677 pwm
->prot
= PWMD_IPV4
;
682 pwm
->prot
= PWMD_IP_ANY
;
686 rc
= tls_parse_url (p
, &host
, &port
);
690 char *clientcert
= NULL
;
691 char *clientkey
= NULL
;
693 char *server_fp
= NULL
;
696 clientcert
= va_arg (ap
, char *);
699 rc
= GPG_ERR_INV_ARG
;
702 clientkey
= va_arg (ap
, char *);
704 rc
= GPG_ERR_INV_ARG
;
707 cacert
= va_arg (ap
, char *);
709 rc
= GPG_ERR_INV_ARG
;
711 server_fp
= va_arg (ap
, char *);
718 rc
= tls_connect (pwm
, host
, port
, clientcert
, clientkey
, cacert
,
719 pwm
->tls_priority
, server_fp
, pwm
->tls_verify
);
722 rc
= _connect_finalize (pwm
);
729 pwm
->local_pinentry
= 1;
740 disconnect (pwm_t
* pwm
)
746 assuan_release (pwm
->ctx
);
748 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
753 pwm
->connected
= pwm
->user_fd
= 0;
757 pwmd_close (pwm_t
* pwm
)
763 pwmd_free (pwm
->pinentry_error
);
764 pwmd_free (pwm
->pinentry_desc
);
765 pwmd_free (pwm
->pinentry_prompt
);
766 pwmd_free (pwm
->pinentry_tty
);
767 pwmd_free (pwm
->pinentry_display
);
768 pwmd_free (pwm
->pinentry_term
);
769 pwmd_free (pwm
->pinentry_lcctype
);
770 pwmd_free (pwm
->pinentry_lcmessages
);
771 pwmd_free (pwm
->filename
);
772 pwmd_free (pwm
->name
);
773 pwmd_free (pwm
->passphrase_info
);
774 pwmd_free (pwm
->passphrase_hint
);
775 pwmd_free (pwm
->ssh_passphrase
);
776 pwmd_free (pwm
->tls_priority
);
780 _pinentry_disconnect (pwm
);
787 inquire_realloc_cb (void *data
, const void *buffer
, size_t len
)
789 membuf_t
*mem
= (membuf_t
*) data
;
795 if ((p
= pwmd_realloc (mem
->buf
, mem
->len
+ len
)) == NULL
)
796 return gpg_error (GPG_ERR_ENOMEM
);
799 memcpy ((char *) mem
->buf
+ mem
->len
, buffer
, len
);
805 get_password (pwm_t
* pwm
, char **result
, size_t * len
,
806 pwmd_pinentry_t w
, int echo
)
808 char buf
[ASSUAN_LINELENGTH
+1] = { 0 }, *p
;
809 struct termios told
, tnew
;
818 if (!isatty (STDIN_FILENO
))
820 fprintf (stderr
, N_("Input is not from a terminal! Failing.\n"));
821 return GPG_ERR_ENOTTY
;
826 if (tcgetattr (STDIN_FILENO
, &told
) == -1)
827 return gpg_error_from_syserror ();
829 memcpy (&tnew
, &told
, sizeof (struct termios
));
830 tnew
.c_lflag
&= ~(ECHO
);
831 tnew
.c_lflag
|= ICANON
| ECHONL
;
833 if (tcsetattr (STDIN_FILENO
, TCSANOW
, &tnew
) == -1)
837 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
838 return gpg_error_from_errno (n
);
842 if (pwm
->passphrase_hint
)
843 fprintf(stderr
, N_("Key info: %s\n"), pwm
->passphrase_hint
);
847 case PWMD_PINENTRY_OPEN
:
848 fprintf (stderr
, N_("Passphrase for %s: "), pwm
->filename
);
850 case PWMD_PINENTRY_OPEN_FAILED
:
851 fprintf (stderr
, N_("Invalid passphrase. Passphrase for %s: "),
854 case PWMD_PINENTRY_SAVE
:
855 fprintf (stderr
, N_("New passphrase for %s: "), pwm
->filename
);
857 case PWMD_PINENTRY_SAVE_CONFIRM
:
858 fprintf (stderr
, N_("Repeat passphrase: "));
860 case PWMD_PINENTRY_CONFIRM
:
861 if (pwm
->pinentry_desc
)
862 fprintf (stderr
, "%s", pwm
->pinentry_desc
);
864 if (pwm
->pinentry_prompt
)
865 fprintf (stderr
, "%s", pwm
->pinentry_prompt
);
867 fprintf(stderr
, N_("Confirm [y/N]:"));
872 p
= fgets (buf
, sizeof (buf
), stdin
);
875 tcsetattr (STDIN_FILENO
, TCSANOW
, &told
);
877 if (!p
|| feof (stdin
))
880 return GPG_ERR_CANCELED
;
883 /* Strip the newline character. */
884 p
[strlen (p
) - 1] = 0;
888 if (w
== PWMD_PINENTRY_CONFIRM
)
890 if (*p
!= 'y' && *p
!= 'Y')
891 return GPG_ERR_CANCELED
;
895 key
= pwmd_strdup_printf ("%s", p
);
896 wipememory (buf
, 0, sizeof (buf
));
898 return GPG_ERR_ENOMEM
;
908 if (w
== PWMD_PINENTRY_CONFIRM
)
909 return GPG_ERR_CANCELED
;
911 /* To satisfy inquire_cb(). */
913 *result
= pwmd_strdup ("");
923 pwmd_password (pwm_t
* pwm
, const char *keyword
, char **data
, size_t * size
)
926 int new_password
= 0;
927 char *password
= NULL
, *newpass
= NULL
;
938 if (!strcmp (keyword
, "NEW_PASSPHRASE"))
941 if (!new_password
&& pwm
->pinentry_try
)
945 if (pwm
->disable_pinentry
)
947 rc
= get_password (pwm
, &password
, size
,
948 new_password
? PWMD_PINENTRY_SAVE
:
949 error
? PWMD_PINENTRY_OPEN_FAILED
:
950 PWMD_PINENTRY_OPEN
, 0);
951 if (!rc
&& new_password
)
952 rc
= get_password (pwm
, &newpass
, size
, PWMD_PINENTRY_SAVE_CONFIRM
,
957 pwmd_pinentry_t which
;
961 ? PWMD_PINENTRY_SAVE_FAILED
: PWMD_PINENTRY_OPEN_FAILED
;
963 which
= new_password
? PWMD_PINENTRY_SAVE
: PWMD_PINENTRY_OPEN
;
965 rc
= pwmd_getpin (pwm
, pwm
->filename
, &password
, size
, which
);
966 if (!rc
&& new_password
)
967 rc
= pwmd_getpin (pwm
, pwm
->filename
, &newpass
, size
,
968 PWMD_PINENTRY_SAVE_CONFIRM
);
971 if (!rc
&& new_password
)
973 if ((!password
&& newpass
) || (!newpass
&& password
)
974 || (newpass
&& password
&& strcmp (newpass
, password
)))
976 if (pwm
->disable_pinentry
)
977 fprintf (stderr
, N_("Passphrases do not match.\n"));
979 pwmd_free (password
);
981 password
= newpass
= NULL
;
987 (void) pwmd_getpin (pwm
, pwm
->filename
, NULL
, NULL
, PWMD_PINENTRY_CLOSE
);
992 pwmd_free (password
);
998 inquire_cb (void *data
, const char *keyword
)
1000 pwm_t
*pwm
= (pwm_t
*) data
;
1002 int free_result
= 0;
1003 char *result
= NULL
;
1004 int is_password
= 0;
1005 int new_password
= 0;
1007 if (!strcmp (keyword
, "PASSPHRASE") || !strcmp (keyword
, "SIGN_PASSPHRASE"))
1009 else if (!strcmp (keyword
, "NEW_PASSPHRASE") || !strcmp (keyword
, "GENKEY"))
1012 /* Shouldn't get this far without a callback. */
1013 if (!pwm
->override_inquire
&& !pwm
->inquire_func
1014 && !is_password
&& !new_password
)
1015 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB
);
1024 if (!pwm
->override_inquire
&& (is_password
|| new_password
))
1027 rc
= pwmd_password (data
, keyword
, &result
, &len
);
1032 rc
= pwm
->inquire_func (pwm
->inquire_data
, keyword
, rc
, &result
,
1035 /* gpg will truncate a passphrase at the first nil byte which may be bad
1036 * for generated key files. */
1037 if ((!rc
|| gpg_err_code (rc
) == GPG_ERR_EOF
)
1038 && (is_password
|| new_password
))
1040 if (len
&& result
&& *result
)
1042 for (size_t n
= 0; n
< len
; n
++)
1044 if (result
[n
] == 0 && n
+1 != len
)
1045 rc
= GPG_ERR_INV_PASSPHRASE
;
1051 if (rc
&& gpg_err_code (rc
) != GPG_ERR_EOF
)
1053 #ifndef LIBASSUAN_2_1_0
1054 gpg_error_t trc
= rc
;
1056 /* Cancel this inquire. */
1057 rc
= assuan_send_data (pwm
->ctx
, NULL
, 1);
1063 /* There is a bug (or feature?) in assuan_send_data() that
1064 * when cancelling an inquire the next read from the server is
1065 * not done until the next command making the next command
1066 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
1068 rc
= assuan_read_line (pwm
->ctx
, &line
, &len
);
1070 /* Restore the original error. This differs from the error
1071 * returned from the pwmd command (GPG_ERR_CANCELED). This
1072 * error is returned to the calling function.
1081 if (gpg_err_code (rc
) == GPG_ERR_EOF
|| !rc
)
1083 if (len
<= 0 && !result
)
1088 else if ((len
<= 0 && result
) || (len
&& !result
))
1090 rc
= gpg_error (GPG_ERR_INV_ARG
);
1094 if (pwm
->inquire_maxlen
1095 && pwm
->inquire_sent
+ len
> pwm
->inquire_maxlen
)
1097 rc
= gpg_error (GPG_ERR_TOO_LARGE
);
1099 rc
= pwm
->inquire_func (pwm
->inquire_data
, keyword
, rc
,
1104 arc
= assuan_send_data (pwm
->ctx
, result
, len
);
1105 if (gpg_err_code (rc
) == GPG_ERR_EOF
)
1118 pwm
->inquire_sent
+= len
;
1120 if (pwm
->status_func
)
1122 char buf
[ASSUAN_LINELENGTH
];
1124 snprintf (buf
, sizeof (buf
), "XFER %zu %zu", pwm
->inquire_sent
,
1125 pwm
->inquire_total
);
1126 rc
= pwm
->status_func (pwm
->status_data
, buf
);
1136 pwm
->inquire_maxlen
= pwm
->inquire_sent
= 0;
1141 parse_assuan_line (pwm_t
* pwm
)
1147 rc
= assuan_read_line (pwm
->ctx
, &line
, &len
);
1150 if (line
[0] == 'O' && line
[1] == 'K' &&
1151 (line
[2] == 0 || line
[2] == ' '))
1154 else if (line
[0] == '#')
1157 else if (line
[0] == 'S' && (line
[1] == 0 || line
[1] == ' '))
1159 rc
= status_cb (pwm
, line
[1] == 0 ? line
+ 1 : line
+ 2);
1161 else if (line
[0] == 'E' && line
[1] == 'R' && line
[2] == 'R' &&
1162 (line
[3] == 0 || line
[3] == ' '))
1165 rc
= strtol (line
, NULL
, 10);
1173 reset_handle (pwm_t
*pwm
)
1178 pwm
->pinentry_disabled
= 0;
1179 #ifdef WITH_PINENTRY
1181 _pinentry_disconnect (pwm
);
1183 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1194 pwmd_disconnect (pwm_t
* pwm
)
1197 return FINISH (GPG_ERR_INV_ARG
);
1199 command_start (pwm
);
1202 return FINISH (GPG_ERR_INV_STATE
);
1209 /* Note that this should only be called when not in a command. */
1211 pwmd_process (pwm_t
* pwm
)
1215 struct timeval tv
= { 0, 0 };
1218 if (!pwm
|| pwm
->fd
== -1)
1219 return FINISH (GPG_ERR_INV_ARG
);
1221 return FINISH (GPG_ERR_INV_STATE
);
1224 FD_SET (pwm
->fd
, &fds
);
1225 n
= select (pwm
->fd
+ 1, &fds
, NULL
, NULL
, &tv
);
1228 return FINISH (gpg_error_from_syserror ());
1232 if (FD_ISSET (pwm
->fd
, &fds
))
1233 rc
= parse_assuan_line (pwm
);
1236 while (!rc
&& assuan_pending_line (pwm
->ctx
))
1237 rc
= parse_assuan_line (pwm
);
1239 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1240 if (gpg_err_code (rc
) == GPG_ERR_EOF
&& pwm
->tcp
)
1251 status_cb (void *data
, const char *line
)
1255 if (!strncmp (line
, "INQUIRE_MAXLEN ", 15))
1256 pwm
->inquire_maxlen
= strtol (line
+ 15, NULL
, 10);
1257 else if (!strncmp (line
, "PASSPHRASE_HINT ", 16))
1259 pwmd_free (pwm
->passphrase_hint
);
1260 pwm
->passphrase_hint
= pwmd_strdup (line
+16);
1262 else if (!strncmp (line
, "PASSPHRASE_INFO ", 16))
1264 pwmd_free (pwm
->passphrase_info
);
1265 pwm
->passphrase_info
= pwmd_strdup (line
+16);
1268 else if (!strcmp (line
, "REHANDSHAKE"))
1273 ret
= tls_read_hook (pwm
, pwm
->fd
, buf
, sizeof (buf
));
1276 pwm
->tls_error
= ret
;
1277 return GPG_ERR_GENERAL
;
1282 if (pwm
->status_func
)
1283 return pwm
->status_func (pwm
->status_data
, line
);
1289 _assuan_command (pwm_t
* pwm
, assuan_context_t ctx
,
1290 char **result
, size_t * len
, const char *cmd
)
1296 return FINISH (GPG_ERR_INV_ARG
);
1298 if (strlen (cmd
) >= ASSUAN_LINELENGTH
+ 1)
1299 return FINISH (GPG_ERR_LINE_TOO_LONG
);
1303 rc
= assuan_transact (ctx
, cmd
, inquire_realloc_cb
, &data
,
1304 #if WITH_QUALITY && WITH_PINENTRY
1305 pwm
->pctx
== ctx
? pwm
->_inquire_func
: inquire_cb
,
1306 pwm
->pctx
== ctx
? pwm
->_inquire_data
: pwm
,
1316 pwmd_free (data
.buf
);
1324 inquire_realloc_cb (&data
, "", 1);
1327 *result
= (char *) data
.buf
;
1329 pwmd_free (data
.buf
);
1336 pwm
->inquire_maxlen
= 0;
1341 pwmd_command_ap (pwm_t
* pwm
, char **result
, size_t * rlen
,
1342 pwmd_inquire_cb_t func
, void *user
, const char *cmd
,
1350 return GPG_ERR_INV_ARG
;
1352 command_start (pwm
);
1361 return FINISH (GPG_ERR_INV_ARG
);
1363 return FINISH (GPG_ERR_INV_STATE
);
1366 * C99 allows the dst pointer to be null which will calculate the length
1367 * of the would-be result and return it.
1370 len
= vsnprintf (NULL
, 0, cmd
, ap
);
1371 buf
= (char *) pwmd_malloc (len
+1);
1375 return FINISH (GPG_ERR_ENOMEM
);
1378 if (vsnprintf (buf
, len
+1, cmd
, ap2
) != len
)
1382 return FINISH (GPG_ERR_ENOMEM
);
1385 if (buf
[strlen (buf
) - 1] == '\n')
1386 buf
[strlen (buf
) - 1] = 0;
1387 if (buf
[strlen (buf
) - 1] == '\r')
1388 buf
[strlen (buf
) - 1] = 0;
1390 pwm
->inquire_func
= func
;
1391 pwm
->inquire_data
= user
;
1392 pwm
->inquire_sent
= 0;
1393 gpg_error_t rc
= _assuan_command (pwm
, pwm
->ctx
, result
, rlen
, buf
);
1399 pwmd_command (pwm_t
* pwm
, char **result
, size_t * len
,
1400 pwmd_inquire_cb_t func
, void *user
, const char *cmd
, ...)
1411 return FINISH (GPG_ERR_INV_ARG
);
1413 return FINISH (GPG_ERR_INV_STATE
);
1416 gpg_error_t rc
= pwmd_command_ap (pwm
, result
, len
, func
, user
, cmd
, ap
);
1422 send_pinentry_timeout (pwm_t
*pwm
)
1426 if ((pwm
->pinentry_timeout
>= 0
1427 && pwm
->pinentry_timeout
!= pwm
->current_pinentry_timeout
)
1428 || (pwm
->pinentry_timeout
== -1
1429 && pwm
->pinentry_timeout
!= pwm
->current_pinentry_timeout
))
1431 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1432 "OPTION pinentry-timeout=%i",
1433 pwm
->pinentry_timeout
);
1435 pwm
->current_pinentry_timeout
= pwm
->pinentry_timeout
;
1442 send_pinentry_options (pwm_t
* pwm
)
1446 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
,
1447 "OPTION disable-pinentry=0");
1448 if (!rc
&& pwm
->pinentry_tty
)
1449 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION TTYNAME=%s",
1452 if (!rc
&& pwm
->pinentry_term
)
1453 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION TTYTYPE=%s",
1454 pwm
->pinentry_term
);
1456 if (!rc
&& pwm
->pinentry_display
)
1457 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION DISPLAY=%s",
1458 pwm
->pinentry_display
);
1460 if (!rc
&& pwm
->pinentry_desc
)
1461 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION DESC=%s",
1462 pwm
->pinentry_desc
);
1464 if (!rc
&& pwm
->pinentry_lcctype
)
1465 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION LC_CTYPE=%s",
1466 pwm
->pinentry_lcctype
);
1468 if (!rc
&& pwm
->pinentry_lcmessages
)
1469 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION LC_MESSAGES=%s",
1470 pwm
->pinentry_lcmessages
);
1473 rc
= send_pinentry_timeout (pwm
);
1479 pwmd_socket_type (pwm_t
* pwm
, pwmd_socket_t
* result
)
1481 if (!pwm
|| !result
)
1482 return FINISH (GPG_ERR_INV_ARG
);
1484 *result
= PWMD_SOCKET_LOCAL
;
1487 return FINISH (GPG_ERR_INV_STATE
);
1491 *result
= PWMD_SOCKET_USER
;
1495 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1497 if (pwm
->tcp
&& pwm
->tcp
->ssh
)
1498 *result
= PWMD_SOCKET_SSH
;
1501 if (pwm
->tcp
&& pwm
->tcp
->tls
)
1502 *result
= PWMD_SOCKET_TLS
;
1509 disable_pinentry (pwm_t
*pwm
, int *disable
)
1512 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1513 int no_pinentry
= pwm
->disable_pinentry
|| pwm
->tcp
|| pwm
->local_pinentry
;
1515 int no_pinentry
= pwm
->disable_pinentry
|| pwm
->local_pinentry
;
1519 *disable
= no_pinentry
;
1521 if (pwm
->pinentry_disabled
&& no_pinentry
)
1523 else if (!pwm
->pinentry_disabled
&& !no_pinentry
)
1526 rc
= pwmd_command (pwm
, NULL
, NULL
, NULL
, NULL
, "OPTION disable-pinentry=%i",
1529 pwm
->pinentry_disabled
= no_pinentry
;
1535 pwmd_open (pwm_t
* pwm
, const char *filename
, pwmd_inquire_cb_t cb
,
1539 int no_pinentry
= 0;
1541 if (!pwm
|| !filename
|| !*filename
)
1542 return FINISH (GPG_ERR_INV_ARG
);
1545 return FINISH (GPG_ERR_INV_STATE
);
1547 command_start (pwm
);
1548 rc
= disable_pinentry (pwm
, &no_pinentry
);
1549 if (!rc
&& !no_pinentry
)
1550 rc
= send_pinentry_options (pwm
);
1554 pwm
->pinentry_try
= 0;
1555 pwmd_free (pwm
->filename
);
1556 pwm
->filename
= pwmd_strdup (filename
);
1560 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "OPEN %s%s",
1561 (pwm
->opts
& OPT_LOCK_ON_OPEN
) ? "--lock " : "",
1564 while (gpg_err_code (rc
) == GPG_ERR_BAD_PASSPHRASE
1565 && pwm
->pinentry_disabled
1566 && ++pwm
->pinentry_try
< pwm
->pinentry_tries
);
1568 pwm
->pinentry_try
= 0;
1572 pwmd_free (pwm
->filename
);
1573 pwm
->filename
= NULL
;
1577 pwmd_free (pwm
->passphrase_hint
);
1578 pwmd_free (pwm
->passphrase_info
);
1579 pwm
->passphrase_info
= pwm
->passphrase_hint
= NULL
;
1584 do_pwmd_save_passwd (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
,
1585 void *data
, int which
)
1588 int no_pinentry
= 0;
1591 return FINISH (GPG_ERR_INV_ARG
);
1593 return FINISH (GPG_ERR_INV_STATE
);
1595 command_start (pwm
);
1596 rc
= disable_pinentry (pwm
, &no_pinentry
);
1597 if (!rc
&& !no_pinentry
)
1598 rc
= send_pinentry_options (pwm
);
1602 if (which
== PWMD_WHICH_SAVE
)
1603 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "SAVE %s", args
? args
: "");
1604 else if (which
== PWMD_WHICH_PASSWD
)
1605 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "PASSWD %s", args
? args
: "");
1606 else if (which
== PWMD_WHICH_GENKEY
)
1607 rc
= pwmd_command (pwm
, NULL
, NULL
, cb
, data
, "GENKEY %s", args
? args
: "");
1610 pwmd_free (pwm
->passphrase_hint
);
1611 pwmd_free (pwm
->passphrase_info
);
1612 pwm
->passphrase_info
= pwm
->passphrase_hint
= NULL
;
1617 pwmd_passwd (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
, void *data
)
1619 return do_pwmd_save_passwd (pwm
, args
, cb
, data
, PWMD_WHICH_PASSWD
);
1623 pwmd_save (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
, void *data
)
1625 return do_pwmd_save_passwd (pwm
, args
, cb
, data
, PWMD_WHICH_SAVE
);
1629 pwmd_genkey (pwm_t
* pwm
, const char *args
, pwmd_inquire_cb_t cb
, void *data
)
1631 return do_pwmd_save_passwd (pwm
, args
, cb
, data
, PWMD_WHICH_GENKEY
);
1635 pwmd_get_set_opt (pwm_t
*pwm
, pwmd_option_t opt
, int get
, va_list ap
)
1639 char *arg1
, **charpp
;
1643 return GPG_ERR_INV_ARG
;
1645 command_start (pwm
);
1648 case PWMD_OPTION_SERVER_VERSION
:
1650 return GPG_ERR_NOT_SUPPORTED
;
1653 rc
= GPG_ERR_INV_STATE
;
1656 unsigned *u
= va_arg (ap
, unsigned *);
1661 case PWMD_OPTION_SIGPIPE
:
1664 intp
= va_arg (ap
, int *);
1665 *intp
= pwm
->opts
& OPT_SIGPIPE
? 1 : 0;
1669 n
= va_arg (ap
, int);
1672 rc
= GPG_ERR_INV_VALUE
;
1677 pwm
->opts
|= OPT_SIGPIPE
;
1679 pwm
->opts
&= ~OPT_SIGPIPE
;
1682 case PWMD_OPTION_LOCK_ON_OPEN
:
1685 intp
= va_arg (ap
, int *);
1686 *intp
= pwm
->opts
& OPT_LOCK_ON_OPEN
? 1 : 0;
1690 n
= va_arg (ap
, int);
1693 rc
= GPG_ERR_INV_VALUE
;
1698 pwm
->opts
|= OPT_LOCK_ON_OPEN
;
1700 pwm
->opts
&= ~OPT_LOCK_ON_OPEN
;
1703 case PWMD_OPTION_INQUIRE_TOTAL
:
1706 sizetp
= va_arg (ap
, size_t *);
1707 *sizetp
= pwm
->inquire_total
;
1711 pwm
->inquire_total
= va_arg (ap
, size_t);
1713 case PWMD_OPTION_STATUS_CB
:
1716 pwmd_status_cb_t
*cb
= va_arg (ap
, pwmd_status_cb_t
*);
1718 *cb
= pwm
->status_func
;
1722 pwm
->status_func
= va_arg (ap
, pwmd_status_cb_t
);
1724 case PWMD_OPTION_STATUS_DATA
:
1727 void **data
= va_arg (ap
, void **);
1729 *data
= pwm
->status_data
;
1733 pwm
->status_data
= va_arg (ap
, void *);
1735 case PWMD_OPTION_NO_PINENTRY
:
1738 intp
= va_arg (ap
, int *);
1739 *intp
= pwm
->disable_pinentry
;
1743 n
= va_arg (ap
, int);
1745 rc
= GPG_ERR_INV_VALUE
;
1747 pwm
->disable_pinentry
= n
;
1749 case PWMD_OPTION_LOCAL_PINENTRY
:
1752 intp
= va_arg (ap
, int *);
1753 *intp
= pwm
->local_pinentry
;
1757 n
= va_arg (ap
, int);
1759 rc
= GPG_ERR_INV_VALUE
;
1761 pwm
->local_pinentry
= n
;
1764 case PWMD_OPTION_PINENTRY_TIMEOUT
:
1767 intp
= va_arg (ap
, int *);
1768 *intp
= pwm
->pinentry_timeout
;
1772 n
= va_arg (ap
, int);
1774 rc
= GPG_ERR_INV_VALUE
;
1776 pwm
->pinentry_timeout
= n
;
1778 case PWMD_OPTION_PINENTRY_TRIES
:
1781 intp
= va_arg (ap
, int *);
1782 *intp
= pwm
->pinentry_tries
;
1786 n
= va_arg (ap
, int);
1788 rc
= GPG_ERR_INV_VALUE
;
1790 pwm
->pinentry_tries
= n
;
1792 case PWMD_OPTION_PINENTRY_PATH
:
1795 charpp
= va_arg (ap
, char **);
1796 *charpp
= pwm
->pinentry_path
;
1800 arg1
= va_arg (ap
, char *);
1801 pwmd_free (pwm
->pinentry_path
);
1802 pwm
->pinentry_path
= arg1
? _expand_homedir (arg1
, NULL
) : NULL
;
1804 case PWMD_OPTION_PINENTRY_TTY
:
1807 charpp
= va_arg (ap
, char **);
1808 *charpp
= pwm
->pinentry_tty
;
1812 arg1
= va_arg (ap
, char *);
1813 pwmd_free (pwm
->pinentry_tty
);
1814 pwm
->pinentry_tty
= arg1
? pwmd_strdup (arg1
) : NULL
;
1816 case PWMD_OPTION_PINENTRY_DISPLAY
:
1819 charpp
= va_arg (ap
, char **);
1820 *charpp
= pwm
->pinentry_display
;
1824 arg1
= va_arg (ap
, char *);
1825 pwmd_free (pwm
->pinentry_display
);
1826 pwm
->pinentry_display
= arg1
&& *arg1
? pwmd_strdup (arg1
) : NULL
;
1827 if (!pwm
->pinentry_display
)
1828 unsetenv ("DISPLAY");
1830 case PWMD_OPTION_PINENTRY_TERM
:
1833 charpp
= va_arg (ap
, char **);
1834 *charpp
= pwm
->pinentry_term
;
1838 arg1
= va_arg (ap
, char *);
1839 pwmd_free (pwm
->pinentry_term
);
1840 pwm
->pinentry_term
= arg1
&& *arg1
? pwmd_strdup (arg1
) : NULL
;
1841 if (pwm
->pinentry_term
)
1844 case PWMD_OPTION_PINENTRY_ERROR
:
1847 charpp
= va_arg (ap
, char **);
1848 *charpp
= pwm
->pinentry_error
;
1852 arg1
= va_arg (ap
, char *);
1853 pwmd_free (pwm
->pinentry_error
);
1854 if (pwm
->disable_pinentry
)
1855 pwm
->pinentry_error
= arg1
? pwmd_strdup (arg1
) : NULL
;
1857 pwm
->pinentry_error
= arg1
? _percent_escape (arg1
) : NULL
;
1859 case PWMD_OPTION_PINENTRY_PROMPT
:
1862 charpp
= va_arg (ap
, char **);
1863 *charpp
= pwm
->pinentry_prompt
;
1867 arg1
= va_arg (ap
, char *);
1868 pwmd_free (pwm
->pinentry_prompt
);
1869 if (pwm
->disable_pinentry
)
1870 pwm
->pinentry_prompt
= arg1
? pwmd_strdup (arg1
) : NULL
;
1872 pwm
->pinentry_prompt
= arg1
? _percent_escape (arg1
) : NULL
;
1874 case PWMD_OPTION_PINENTRY_DESC
:
1877 charpp
= va_arg (ap
, char **);
1878 *charpp
= pwm
->pinentry_desc
;
1882 arg1
= va_arg (ap
, char *);
1883 pwmd_free (pwm
->pinentry_desc
);
1884 if (pwm
->disable_pinentry
)
1885 pwm
->pinentry_desc
= arg1
? pwmd_strdup (arg1
) : NULL
;
1887 pwm
->pinentry_desc
= arg1
? _percent_escape (arg1
) : NULL
;
1889 case PWMD_OPTION_PINENTRY_LC_CTYPE
:
1892 charpp
= va_arg (ap
, char **);
1893 *charpp
= pwm
->pinentry_lcctype
;
1897 arg1
= va_arg (ap
, char *);
1898 pwmd_free (pwm
->pinentry_lcctype
);
1899 pwm
->pinentry_lcctype
= arg1
? pwmd_strdup (arg1
) : NULL
;
1901 case PWMD_OPTION_PINENTRY_LC_MESSAGES
:
1904 charpp
= va_arg (ap
, char **);
1905 *charpp
= pwm
->pinentry_lcmessages
;
1909 arg1
= va_arg (ap
, char *);
1910 pwmd_free (pwm
->pinentry_lcmessages
);
1911 pwm
->pinentry_lcmessages
= arg1
? pwmd_strdup (arg1
) : NULL
;
1913 case PWMD_OPTION_KNOWNHOST_CB
:
1916 pwmd_knownhost_cb_t
*cb
= va_arg (ap
, pwmd_knownhost_cb_t
*);
1922 pwm
->kh_cb
= va_arg (ap
, pwmd_knownhost_cb_t
);
1924 case PWMD_OPTION_KNOWNHOST_DATA
:
1927 void **data
= va_arg (ap
, void **);
1929 *data
= pwm
->kh_data
;
1933 pwm
->kh_data
= va_arg (ap
, void *);
1935 case PWMD_OPTION_SSH_AGENT
:
1938 intp
= va_arg (ap
, int *);
1939 *intp
= pwm
->use_agent
;
1943 n
= va_arg (ap
, int);
1945 rc
= GPG_ERR_INV_VALUE
;
1949 case PWMD_OPTION_SSH_PASSPHRASE
:
1951 return GPG_ERR_NOT_SUPPORTED
;
1953 pwmd_free (pwm
->ssh_passphrase
);
1954 pwm
->ssh_passphrase
= NULL
;
1955 arg1
= va_arg (ap
, char *);
1958 pwm
->ssh_passphrase
= pwmd_strdup (arg1
);
1959 if (!pwm
->ssh_passphrase
)
1960 return GPG_ERR_ENOMEM
;
1963 case PWMD_OPTION_SSH_NEEDS_PASSPHRASE
:
1966 intp
= va_arg (ap
, int *);
1967 *intp
= pwm
->needs_passphrase
;
1971 n
= va_arg (ap
, int);
1973 rc
= GPG_ERR_INV_VALUE
;
1975 pwm
->needs_passphrase
= n
;
1977 case PWMD_OPTION_TLS_VERIFY
:
1980 intp
= va_arg (ap
, int *);
1981 *intp
= pwm
->tls_verify
;
1985 n
= va_arg (ap
, int);
1987 rc
= GPG_ERR_INV_VALUE
;
1989 pwm
->tls_verify
= n
;
1991 case PWMD_OPTION_TLS_PRIORITY
:
1994 charpp
= va_arg (ap
, char **);
1995 *charpp
= pwm
->tls_priority
;
1999 pwmd_free (pwm
->tls_priority
);
2000 pwm
->tls_priority
= NULL
;
2001 arg1
= va_arg (ap
, char *);
2004 pwm
->tls_priority
= pwmd_strdup (arg1
);
2005 if (!pwm
->tls_priority
)
2006 rc
= GPG_ERR_ENOMEM
;
2009 case PWMD_OPTION_SOCKET_TIMEOUT
:
2012 intp
= va_arg (ap
, int *);
2013 *intp
= pwm
->socket_timeout
;
2017 n
= va_arg (ap
, int);
2020 rc
= GPG_ERR_INV_VALUE
;
2024 pwm
->socket_timeout
= n
;
2027 if (pwm
->tcp
&& pwm
->tcp
->ssh
&& pwm
->tcp
->ssh
->session
)
2029 pwm
->tcp
->ssh
->timeout
= pwm
->socket_timeout
;
2030 libssh2_session_set_timeout (pwm
->tcp
->ssh
->session
,
2031 pwm
->socket_timeout
* 1000);
2035 if (pwm
->tcp
&& pwm
->tcp
->tls
&& pwm
->tcp
->tls
->session
)
2036 pwm
->tcp
->tls
->timeout
= pwm
->socket_timeout
;
2039 case PWMD_OPTION_READ_CB
:
2042 pwmd_read_cb_t
*cb
= va_arg (ap
, pwmd_read_cb_t
*);
2047 pwm
->read_cb
= va_arg (ap
, pwmd_read_cb_t
);
2049 case PWMD_OPTION_READ_CB_DATA
:
2052 void **data
= va_arg (ap
, void **);
2054 *data
= pwm
->read_cb_data
;
2058 pwm
->read_cb_data
= va_arg (ap
, void *);
2060 case PWMD_OPTION_WRITE_CB
:
2063 pwmd_write_cb_t
*cb
= va_arg (ap
, pwmd_write_cb_t
*);
2065 *cb
= pwm
->write_cb
;
2068 pwm
->write_cb
= va_arg (ap
, pwmd_write_cb_t
);
2070 case PWMD_OPTION_WRITE_CB_DATA
:
2073 void **data
= va_arg (ap
, void **);
2075 *data
= pwm
->write_cb_data
;
2079 pwm
->write_cb_data
= va_arg (ap
, void *);
2081 case PWMD_OPTION_OVERRIDE_INQUIRE
:
2084 intp
= va_arg (ap
, int *);
2085 *intp
= pwm
->override_inquire
;
2089 n
= va_arg (ap
, int);
2091 rc
= GPG_ERR_INV_VALUE
;
2093 pwm
->override_inquire
= n
;
2096 rc
= GPG_ERR_UNKNOWN_OPTION
;
2104 pwmd_setopt (pwm_t
* pwm
, int opt
, ...)
2110 rc
= pwmd_get_set_opt (pwm
, opt
, 0, ap
);
2116 pwmd_getopt (pwm_t
*pwm
, int opt
, ...)
2122 rc
= pwmd_get_set_opt (pwm
, opt
, 1, ap
);
2128 set_rcdefaults (pwm_t
*pwm
, char *filename
)
2132 char *line
= NULL
, *p
;
2133 unsigned line_n
= 0;
2136 if (!filename
&& isatty (STDIN_FILENO
))
2139 int err
= ttyname_r (STDOUT_FILENO
, buf
, sizeof (buf
));
2143 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, buf
);
2147 if (getenv ("TERM"))
2149 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, getenv ("TERM"));
2156 if (!filename
&& getenv ("DISPLAY"))
2158 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, getenv ("DISPLAY"));
2163 f
= _expand_homedir (filename
? filename
: (char *)"~/.config/libpwmd.conf",
2167 line
= pwmd_malloc (LINE_MAX
);
2170 fp
= fopen (f
, "r");
2179 rc
= GPG_ERR_ENOMEM
;
2182 rc
= GPG_ERR_ENOMEM
;
2191 while ((p
= fgets (line
, LINE_MAX
, fp
)))
2193 char name
[32] = {0}, val
[512] = {0};
2200 while (isspace (*p
))
2203 if (!*p
|| *p
== '#')
2206 if (p
[strlen (p
)-1] == '\n')
2207 p
[strlen (p
)-1] = 0;
2209 t
= strchr (p
, '=');
2212 fprintf(stderr
, N_("%s(%u): malformed line\n"), f
, line_n
);
2216 for (np
= name
; p
!= t
; p
++)
2218 if (++len
== sizeof (name
))
2227 while (isspace (*t
))
2230 while (isspace (*t
))
2233 strncpy (val
, t
, sizeof (val
)-1);
2235 if (!strcasecmp (name
, "pinentry-path"))
2236 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_PATH
, val
);
2237 else if (!strcasecmp (name
, "pinentry-tries"))
2238 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TRIES
, atoi (val
));
2239 else if (!strcasecmp (name
, "pinentry-timeout"))
2240 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TIMEOUT
, atoi (val
));
2241 else if (!strcasecmp (name
, "no-pinentry"))
2242 rc
= pwmd_setopt (pwm
, PWMD_OPTION_NO_PINENTRY
, !!(atoi (val
)));
2243 else if (!strcasecmp (name
, "local-pinentry"))
2244 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCAL_PINENTRY
, !!(atoi (val
)));
2245 else if (!strcasecmp (name
, "pinentry-display"))
2246 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_DISPLAY
, val
);
2247 else if (!strcasecmp (name
, "pinentry-ttyname"))
2248 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TTY
, val
);
2249 else if (!strcasecmp (name
, "pinentry-ttytype"))
2250 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_TERM
, val
);
2251 else if (!strcasecmp (name
, "pinentry-lc-messages"))
2252 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_MESSAGES
, val
);
2253 else if (!strcasecmp (name
, "pinentry-lc-ctype"))
2254 rc
= pwmd_setopt (pwm
, PWMD_OPTION_PINENTRY_LC_CTYPE
, val
);
2255 else if (!strcasecmp (name
, "no-ssh-agent"))
2256 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SSH_AGENT
, !(atoi (val
)));
2257 else if (!strcasecmp (name
, "no-tls-verify"))
2258 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_VERIFY
, !(atoi (val
)));
2259 else if (!strcasecmp (name
, "tls-priority"))
2260 rc
= pwmd_setopt (pwm
, PWMD_OPTION_TLS_PRIORITY
, val
);
2261 else if (!strcasecmp (name
, "socket-timeout"))
2262 rc
= pwmd_setopt (pwm
, PWMD_OPTION_SOCKET_TIMEOUT
, atoi (val
));
2263 else if (!strcasecmp (name
, "no-lock"))
2264 rc
= pwmd_setopt (pwm
, PWMD_OPTION_LOCK_ON_OPEN
, !(atoi (val
)));
2265 else if (!strcasecmp (name
, "include"))
2266 rc
= set_rcdefaults (pwm
, val
);
2268 fprintf(stderr
, N_("%s(%u): invalid option '%s', ignored.\n"), f
,
2282 pwmd_new (const char *name
, pwm_t
** pwm
)
2284 pwm_t
*h
= pwmd_calloc (1, sizeof (pwm_t
));
2288 return FINISH (GPG_ERR_ENOMEM
);
2292 h
->name
= pwmd_strdup (name
);
2296 return FINISH (GPG_ERR_ENOMEM
);
2301 h
->pinentry_timeout
= -1;
2302 h
->current_pinentry_timeout
= -1;
2303 h
->pinentry_tries
= 3;
2304 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2305 h
->prot
= PWMD_IP_ANY
;
2306 h
->socket_timeout
= 120;
2309 h
->opts
|= OPT_LOCK_ON_OPEN
;
2311 rc
= set_rcdefaults (h
, NULL
);
2324 pwmd_free (void *ptr
)
2330 pwmd_malloc (size_t size
)
2332 return _xmalloc (size
);
2336 pwmd_calloc (size_t nmemb
, size_t size
)
2338 return _xcalloc (nmemb
, size
);
2342 pwmd_realloc (void *ptr
, size_t size
)
2344 return _xrealloc (ptr
, size
);
2348 pwmd_strdup (const char *str
)
2355 t
= _xmalloc ((len
+ 1) * sizeof (char));
2359 for (c
= 0; c
< len
; c
++)
2367 pwmd_strdup_printf (const char *fmt
, ...)
2378 len
= vsnprintf (NULL
, 0, fmt
, ap
);
2380 buf
= pwmd_malloc (++len
);
2382 vsnprintf (buf
, len
, fmt
, ap2
);
2389 pwmd_getpin (pwm_t
* pwm
, const char *filename
, char **result
,
2390 size_t * len
, pwmd_pinentry_t which
)
2392 #ifndef WITH_PINENTRY
2393 return FINISH (GPG_ERR_NOT_IMPLEMENTED
);
2397 command_start (pwm
);
2398 if (which
== PWMD_PINENTRY_CONFIRM
&& pwm
->disable_pinentry
)
2400 rc
= get_password (pwm
, NULL
, NULL
, which
, 1);
2404 rc
= _pwmd_getpin (pwm
, filename
, result
, len
, which
);
2412 return LIBPWMD_VERSION_STR
;
2420 #ifdef WITH_PINENTRY
2421 n
|= PWMD_FEATURE_PINENTRY
;
2424 n
|= PWMD_FEATURE_SSH
;
2427 n
|= PWMD_FEATURE_QUALITY
;
2430 n
|= PWMD_FEATURE_GNUTLS
;
2436 pwmd_fd (pwm_t
* pwm
, int *fd
)
2439 return FINISH (GPG_ERR_INV_ARG
);
2442 return FINISH (GPG_ERR_INV_STATE
);
2449 pwmd_set_pointer (pwm_t
*pwm
, void *data
)
2451 pwm
->user_data
= data
;
2455 pwmd_get_pointer (pwm_t
*pwm
)
2457 return pwm
->user_data
;
2461 pwmd_gnutls_error (pwm_t
*pwm
, const char **str
)
2468 if (str
&& pwm
&& pwm
->tls_error
)
2469 *str
= gnutls_strerror (pwm
->tls_error
);
2471 return pwm
? pwm
->tls_error
: 0;
2476 pwmd_cancel (pwm_t
*pwm
)
2479 return FINISH (GPG_ERR_INV_ARG
);
2481 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2482 if (pwm
->fd
== -1 && !pwm
->tcp
)
2486 return FINISH (GPG_ERR_INV_STATE
);
2488 /* Can only cancel the connection for the time being. */
2490 return FINISH (GPG_ERR_INV_STATE
);
2497 pwmd_test_quality (const char *str
, double *result
)
2499 #ifndef WITH_QUALITY
2502 return GPG_ERR_NOT_IMPLEMENTED
;
2505 return GPG_ERR_INV_ARG
;
2507 *result
= ZxcvbnMatch (str
, NULL
, NULL
);