Resend pinentry options during PASSWD and SAVE.
[libpwmd.git] / src / libpwmd.c
blobfcdb67de7e28a6c6e9f0a9ab8c75f22009a88068
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of libpwmd.
7 Libpwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Libpwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <err.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <sys/wait.h>
38 #include <fcntl.h>
39 #include <pwd.h>
40 #include <time.h>
41 #include <limits.h>
42 #include <sys/select.h>
43 #include <termios.h>
44 #include <libpwmd.h>
46 #ifdef HAVE_STRINGS_H
47 #include <strings.h>
48 #endif
50 #ifndef LINE_MAX
51 #define LINE_MAX 2048
52 #endif
54 #include "mem.h"
55 #include "misc.h"
56 #include "types.h"
58 #ifdef WITH_PINENTRY
59 #include "pinentry.h"
60 #endif
62 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <netdb.h>
66 #include <netinet/in.h>
67 #endif
69 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
70 ? gpg_error(rc) : rc
72 typedef struct
74 size_t len;
75 void *buf;
76 } membuf_t;
78 ssize_t
79 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
81 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
82 pwm_t *pwm = assuan_get_pointer (ctx);
84 #ifdef WITH_SSH
85 if (pwm && pwm->tcp && pwm->tcp->ssh)
86 return read_hook_ssh (pwm->tcp->ssh, fd, data, len);
87 #endif
88 #ifdef WITH_GNUTLS
89 if (pwm && pwm->tcp && pwm->tcp->tls)
90 return read_hook_tls (pwm, fd, data, len);
91 #endif
92 #endif
94 return read ((int) fd, data, len);
97 ssize_t
98 hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data,
99 size_t len)
101 ssize_t wrote;
102 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
103 pwm_t *pwm = assuan_get_pointer (ctx);
105 #ifdef WITH_SSH
106 if (pwm && pwm->tcp && pwm->tcp->ssh)
107 return write_hook_ssh (pwm->tcp->ssh, fd, data, len);
108 #endif
109 #ifdef WITH_GNUTLS
110 if (pwm && pwm->tcp && pwm->tcp->tls)
111 return write_hook_tls (pwm, fd, data, len);
112 #endif
113 #endif
115 /* libassuan cannot handle EAGAIN when doing writes. */
118 wrote = write ((int) fd, data, len);
119 if (wrote == -1 && errno == EAGAIN)
120 usleep (50000);
122 while (wrote == -1 && errno == EAGAIN);
124 return wrote;
127 pid_t
128 hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status,
129 int options)
131 return waitpid (pid, status, options);
134 gpg_error_t
135 pwmd_init ()
137 static int initialized;
139 #ifdef WITH_GNUTLS
140 // May be called more than once.
141 gnutls_global_init ();
142 #endif
144 if (initialized)
145 return 0;
147 #ifndef MEM_DEBUG
148 _xmem_init ();
149 #endif
150 #ifdef ENABLE_NLS
151 bindtextdomain ("libpwmd", LOCALEDIR);
152 #endif
153 #ifdef WITH_SSH
154 libssh2_init (0);
155 #endif
156 gpg_err_init ();
157 initialized = 1;
158 return 0;
161 void
162 pwmd_deinit ()
164 #ifdef WITH_GNUTLS
165 gnutls_global_deinit ();
166 #endif
169 gpg_error_t
170 _connect_finalize (pwm_t * pwm)
172 gpg_error_t rc = 0;
173 char *result = NULL;
174 int active[2];
175 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
177 if (n <= 0)
178 return GPG_ERR_EBADFD;
180 pwm->fd = active[0];
181 #ifdef WITH_PINENTRY
182 pwm->pinentry_pid = -1;
183 #endif
185 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, "GETINFO VERSION");
186 if (!rc)
188 pwm->version = strtoul (result, NULL, 16);
189 pwmd_free (result);
192 if (!rc && pwm->name)
193 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
194 pwm->name);
196 return rc;
199 static gpg_error_t
200 connect_uds (pwm_t * pwm, const char *path)
202 char *socketpath = NULL;
203 struct passwd pw;
204 char *pwbuf;
205 gpg_error_t rc;
207 if (!pwm)
208 return GPG_ERR_INV_ARG;
210 pwbuf = _getpwuid (&pw);
211 if (!pwbuf)
212 return gpg_error_from_syserror ();
214 if (!path || !*path)
215 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
216 else
217 socketpath = _expand_homedir ((char *) path, &pw);
219 pwmd_free (pwbuf);
220 if (!socketpath)
221 return GPG_ERR_ENOMEM;
223 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
224 pwmd_free (socketpath);
225 return rc ? rc : _connect_finalize (pwm);
228 static gpg_error_t
229 init_handle (pwm_t * pwm)
231 gpg_error_t rc;
232 static struct assuan_malloc_hooks mhooks = {
233 pwmd_malloc, pwmd_realloc, pwmd_free
235 static struct assuan_system_hooks shooks = {
236 ASSUAN_SYSTEM_HOOKS_VERSION,
237 __assuan_usleep,
238 __assuan_pipe,
239 __assuan_close,
240 hook_read,
241 hook_write,
242 //FIXME
243 NULL, //recvmsg
244 NULL, //sendmsg both are used for FD passing
245 __assuan_spawn,
246 hook_waitpid,
247 __assuan_socketpair,
248 __assuan_socket,
249 __assuan_connect
252 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
253 NULL);
254 if (rc)
255 return rc;
257 assuan_set_pointer (pwm->ctx, pwm);
258 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
259 return 0;
262 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
263 void
264 free_tcp (pwm_t *pwm)
266 struct tcp_s *tcp = pwm->tcp;
268 if (!tcp)
269 return;
271 #ifdef WITH_SSH
272 _free_ssh_conn (tcp->ssh);
273 #endif
274 #ifdef WITH_GNUTLS
275 tls_free (pwm);
276 #endif
278 pwmd_free (tcp->host);
279 if (tcp->addrs)
281 freeaddrinfo (tcp->addrs);
282 tcp->addrs = NULL;
285 pthread_cond_destroy (&tcp->dns_cond);
286 pthread_mutex_destroy (&tcp->dns_mutex);
287 pwmd_free (tcp);
288 pwm->tcp = NULL;
290 #endif
292 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
293 static void *
294 resolve_host_thread (void *arg)
296 pwm_t *pwm = arg;
297 struct addrinfo hints = { 0 };
298 char portstr[6];
300 switch (pwm->prot)
302 case PWMD_IP_ANY:
303 hints.ai_family = AF_UNSPEC;
304 break;
305 case PWMD_IPV4:
306 hints.ai_family = AF_INET;
307 break;
308 case PWMD_IPV6:
309 hints.ai_family = AF_INET6;
310 break;
313 hints.ai_socktype = SOCK_STREAM;
314 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
315 int *n = pwmd_malloc (sizeof (int));
316 pthread_cleanup_push (pwmd_free, n);
317 *n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
318 pthread_cleanup_pop (0);
319 pthread_cond_broadcast (&pwm->tcp->dns_cond);
320 pthread_exit (n);
321 return NULL;
324 gpg_error_t
325 tcp_connect_common (pwm_t * pwm)
327 #define TS_TIMEOUT 50000000L
328 int n;
329 gpg_error_t rc = 0;
330 pthread_t tid;
331 time_t now;
333 time (&now);
334 n = pthread_create (&tid, NULL, resolve_host_thread, pwm);
335 if (n)
336 return gpg_error_from_errno (n);
338 pthread_mutex_lock (&pwm->tcp->dns_mutex);
340 for (;;)
342 struct timespec ts;
343 int *result = NULL;
345 clock_gettime (CLOCK_REALTIME, &ts);
346 if (ts.tv_nsec + TS_TIMEOUT >= 1000000000LL) {
347 ts.tv_sec++;
348 ts.tv_nsec = 0;
350 else
351 ts.tv_nsec += TS_TIMEOUT;
353 if (pwm->cancel)
355 #ifdef HAVE_PTHREAD_CANCEL
356 pthread_cancel (tid);
357 pthread_join (tid, NULL);
358 #else
359 pthread_join (tid, (void **)&result);
360 pwmd_free (result);
361 #endif
362 return GPG_ERR_CANCELED;
365 n = pthread_cond_timedwait (&pwm->tcp->dns_cond, &pwm->tcp->dns_mutex,
366 &ts);
367 if (n == ETIMEDOUT)
369 if (pwm->socket_timeout && ts.tv_sec - now >= pwm->socket_timeout)
371 #ifdef HAVE_PTHREAD_CANCEL
372 pthread_cancel (tid);
373 pthread_join (tid, NULL);
374 #else
375 pthread_join (tid, (void **)&result);
376 pwmd_free (result);
377 #endif
378 return GPG_ERR_ETIMEDOUT;
381 continue;
383 else if (n)
385 #ifdef HAVE_PTHREAD_CANCEL
386 pthread_cancel (tid);
387 pthread_join (tid, NULL);
388 #else
389 pthread_join (tid, (void **)&result);
390 pwmd_free (result);
391 #endif
392 return gpg_error_from_errno (n);
395 pthread_join (tid, (void **)&result);
396 n = *result;
397 pwmd_free (result);
398 break;
401 if (n)
402 return GPG_ERR_UNKNOWN_HOST; //FIXME
404 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
405 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
407 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
408 if (pwm->fd == -1)
410 rc = gpg_error_from_syserror ();
411 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
412 break;
413 continue;
416 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
418 rc = gpg_error_from_syserror ();
419 break;
422 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
423 pwm->tcp->addr->ai_family == AF_INET6
424 ? sizeof (struct sockaddr_in6)
425 : sizeof (struct sockaddr)) == -1)
427 int n;
428 struct timeval tv;
429 fd_set wfds;
430 unsigned elapsed = 0;
432 rc = gpg_error_from_syserror ();
433 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
435 close (pwm->fd);
436 pwm->fd = -1;
437 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
438 return rc;
439 continue;
442 again:
443 tv.tv_sec = 1;
444 tv.tv_usec = 0;
445 FD_ZERO (&wfds);
446 FD_SET (pwm->fd, &wfds);
447 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
448 rc = 0;
449 if (!n || pwm->cancel)
451 if (pwm->cancel)
452 rc = gpg_error (GPG_ERR_CANCELED);
453 else if (++elapsed >= pwm->socket_timeout)
454 rc = gpg_error (GPG_ERR_ETIMEDOUT);
455 else
456 goto again;
458 else if (n != -1)
460 socklen_t len = sizeof(int);
462 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
463 if (n)
464 rc = gpg_error_from_errno (n);
466 else if (n == -1)
467 rc = gpg_error_from_syserror ();
469 if (rc)
471 close (pwm->fd);
472 pwm->fd = -1;
473 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
474 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT
475 || pwm->cancel)
476 return rc;
478 else
479 break;
481 else
482 break;
485 if (!rc)
486 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
487 rc = gpg_error_from_syserror ();
489 return rc;
491 #endif
493 static void
494 command_start (pwm_t *pwm)
496 pwm->cancel = 0;
499 gpg_error_t
500 pwmd_connect (pwm_t * pwm, const char *url, ...)
502 const char *p = url;
503 gpg_error_t rc;
505 if (!pwm)
506 return FINISH (GPG_ERR_INV_ARG);
507 else if (!pwm->ctx)
509 rc = init_handle (pwm);
510 if (rc)
511 return rc;
514 command_start (pwm);
516 if (!(pwm->opts & OPT_SIGPIPE))
517 signal (SIGPIPE, SIG_IGN);
519 #ifdef WITH_GNUTLS
520 pwm->tls_error = 0;
521 #endif
522 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
524 if (p && (*p == '/' || *p == '~'))
525 rc = connect_uds (pwm, p);
526 else if (!p || !strncmp (p, "file://", 7))
528 if (p)
529 p += 7;
530 #ifdef DEFAULT_PWMD_SOCKET
531 else
532 p = DEFAULT_PWMD_SOCKET;
533 #endif
534 rc = connect_uds (pwm, p);
536 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
537 !strncmp (p, "ssh4://", 7))
539 #ifndef WITH_SSH
540 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
541 #else
542 char *host = NULL;
543 int port;
544 char *username = NULL;
546 if (!strncmp (p, "ssh6://", 7))
548 pwm->prot = PWMD_IPV6;
549 p += 7;
551 else if (!strncmp (p, "ssh4://", 7))
553 pwm->prot = PWMD_IPV4;
554 p += 7;
556 else
558 pwm->prot = PWMD_IP_ANY;
559 p += 6;
562 rc = _parse_ssh_url (p, &host, &port, &username);
563 if (!rc)
565 va_list ap;
566 char *identity = NULL;
567 char *knownhosts = NULL;
569 va_start (ap, url);
570 identity = va_arg (ap, char *);
572 if (!identity && !pwm->use_agent)
573 rc = GPG_ERR_INV_ARG;
574 else
575 knownhosts = va_arg (ap, char *);
577 va_end (ap);
579 if (!rc)
580 rc = _do_ssh_connect (pwm, host, port, identity, username,
581 knownhosts);
582 if (!rc)
584 rc = _connect_finalize (pwm);
585 if (rc)
586 free_tcp (pwm);
590 pwmd_free (host);
591 pwmd_free (username);
592 pwm->local_pinentry = 1;
593 #endif
595 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
596 !strncmp (p, "tls4://", 7))
598 #ifndef WITH_GNUTLS
599 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
600 #else
601 char *host = NULL;
602 int port;
604 if (!strncmp (p, "tls6://", 7))
606 pwm->prot = PWMD_IPV6;
607 p += 7;
609 else if (!strncmp (p, "tls4://", 7))
611 pwm->prot = PWMD_IPV4;
612 p += 7;
614 else
616 pwm->prot = PWMD_IP_ANY;
617 p += 6;
620 rc = _parse_tls_url (p, &host, &port);
621 if (!rc)
623 va_list ap;
624 char *clientcert = NULL;
625 char *clientkey = NULL;
626 char *cacert = NULL;
627 char *prio = NULL;
628 char *server_fp = NULL;
630 va_start (ap, url);
631 clientcert = va_arg (ap, char *);
633 if (!clientcert)
634 rc = GPG_ERR_INV_ARG;
635 else
637 clientkey = va_arg (ap, char *);
638 if (!clientkey)
639 rc = GPG_ERR_INV_ARG;
640 else
642 cacert = va_arg (ap, char *);
643 if (!cacert)
644 rc = GPG_ERR_INV_ARG;
645 else
647 prio = va_arg (ap, char *);
648 server_fp = va_arg (ap, char *);
653 va_end (ap);
655 if (!rc)
656 rc = _do_tls_connect (pwm, host, port, clientcert, clientkey,
657 cacert, prio, server_fp, pwm->tls_verify);
658 if (!rc)
660 rc = _connect_finalize (pwm);
661 if (rc)
662 free_tcp (pwm);
666 pwmd_free (host);
667 pwm->local_pinentry = 1;
668 #endif
671 if (!rc)
672 pwm->connected = 1;
674 return FINISH (rc);
677 static void
678 disconnect (pwm_t * pwm)
680 if (!pwm)
681 return;
683 if (pwm->ctx)
684 assuan_release (pwm->ctx);
686 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
687 free_tcp (pwm);
688 #endif
689 pwm->ctx = NULL;
690 pwm->fd = -1;
691 pwm->connected = 0;
694 void
695 pwmd_close (pwm_t * pwm)
697 if (!pwm)
698 return;
700 disconnect (pwm);
701 pwmd_free (pwm->pinentry_error);
702 pwmd_free (pwm->pinentry_desc);
703 pwmd_free (pwm->pinentry_prompt);
704 pwmd_free (pwm->pinentry_tty);
705 pwmd_free (pwm->pinentry_display);
706 pwmd_free (pwm->pinentry_term);
707 pwmd_free (pwm->pinentry_lcctype);
708 pwmd_free (pwm->pinentry_lcmessages);
709 pwmd_free (pwm->filename);
710 pwmd_free (pwm->name);
711 pwmd_free (pwm->passphrase_info);
712 pwmd_free (pwm->passphrase_hint);
714 #ifdef WITH_PINENTRY
715 if (pwm->pctx)
716 _pinentry_disconnect (pwm);
717 #endif
719 pwmd_free (pwm);
722 static gpg_error_t
723 inquire_realloc_cb (void *data, const void *buffer, size_t len)
725 membuf_t *mem = (membuf_t *) data;
726 void *p;
728 if (!buffer)
729 return 0;
731 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
732 return gpg_error (GPG_ERR_ENOMEM);
734 mem->buf = p;
735 memcpy ((char *) mem->buf + mem->len, buffer, len);
736 mem->len += len;
737 return 0;
740 static gpg_error_t
741 get_password (pwm_t * pwm, char **result, size_t * len,
742 pwmd_pinentry_t w, int echo)
744 char buf[LINE_MAX] = { 0 }, *p;
745 struct termios told, tnew;
746 char *key = NULL;
748 if (result)
749 *result = NULL;
751 if (len)
752 *len = 0;
754 if (!isatty (STDIN_FILENO))
756 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
757 return GPG_ERR_ENOTTY;
760 if (!echo)
762 if (tcgetattr (STDIN_FILENO, &told) == -1)
763 return gpg_error_from_syserror ();
765 memcpy (&tnew, &told, sizeof (struct termios));
766 tnew.c_lflag &= ~(ECHO);
767 tnew.c_lflag |= ICANON | ECHONL;
769 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
771 int n = errno;
773 tcsetattr (STDIN_FILENO, TCSANOW, &told);
774 return gpg_error_from_errno (n);
778 if (pwm->passphrase_hint)
779 fprintf(stderr, N_("Key info: %s\n"), pwm->passphrase_hint);
781 switch (w)
783 case PWMD_PINENTRY_OPEN:
784 fprintf (stderr, N_("Password for %s: "), pwm->filename);
785 break;
786 case PWMD_PINENTRY_OPEN_FAILED:
787 fprintf (stderr, N_("Invalid password. Password for %s: "),
788 pwm->filename);
789 break;
790 case PWMD_PINENTRY_SAVE:
791 fprintf (stderr, N_("New password for %s: "), pwm->filename);
792 break;
793 case PWMD_PINENTRY_SAVE_CONFIRM:
794 fprintf (stderr, N_("Confirm password: "));
795 break;
796 default:
797 break;
800 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
802 if (!echo)
803 tcsetattr (STDIN_FILENO, TCSANOW, &told);
804 return 0;
807 if (!echo)
808 tcsetattr (STDIN_FILENO, TCSANOW, &told);
810 if (feof (stdin))
812 clearerr (stdin);
813 return GPG_ERR_CANCELED;
816 /* Strip the newline character. */
817 p[strlen (p) - 1] = 0;
819 if (buf[0])
821 key = pwmd_strdup_printf ("%s", p);
822 memset (buf, 0, sizeof (buf));
823 if (!key)
824 return GPG_ERR_ENOMEM;
826 if (result)
827 *result = key;
829 if (len)
830 *len = strlen (key);
832 else
834 if (result)
835 *result = pwmd_strdup ("");
837 if (len)
838 *len = 1;
841 return 0;
844 gpg_error_t
845 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
847 gpg_error_t rc;
848 int new_password = 0;
849 char *password = NULL, *newpass = NULL;
850 int error = 0;
852 command_start (pwm);
854 if (data)
855 *data = NULL;
857 if (size)
858 *size = 0;
860 if (!strcmp (keyword, "NEW_PASSPHRASE"))
861 new_password = 1;
863 if (!new_password && pwm->pinentry_try)
864 error = 1;
866 again:
867 if (pwm->disable_pinentry)
869 rc = get_password (pwm, &password, size,
870 new_password ? PWMD_PINENTRY_SAVE :
871 error ? PWMD_PINENTRY_OPEN_FAILED :
872 PWMD_PINENTRY_OPEN, 0);
873 if (!rc && new_password)
874 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
877 else
879 pwmd_pinentry_t which;
881 if (error)
882 which = new_password
883 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
884 else
885 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
887 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
888 if (!rc && new_password)
889 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
890 PWMD_PINENTRY_SAVE_CONFIRM);
893 if (!rc && new_password)
895 if ((!password && newpass) || (!newpass && password)
896 || (newpass && password && strcmp (newpass, password)))
898 if (pwm->disable_pinentry)
899 fprintf (stderr, N_("Passphrases do not match.\n"));
901 pwmd_free (password);
902 pwmd_free (newpass);
903 password = newpass = NULL;
904 error = 1;
905 goto again;
909 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
910 pwmd_free (newpass);
911 if (!rc && data)
912 *data = password;
914 return rc;
917 static gpg_error_t
918 inquire_cb (void *data, const char *keyword)
920 pwm_t *pwm = (pwm_t *) data;
921 gpg_error_t rc = 0;
922 int free_result = 0;
923 char *result = NULL;
924 int is_password = 0;
925 int new_password = 0;
927 if (!strcmp (keyword, "PASSPHRASE") || !strcmp (keyword, "SIGN_PASSPHRASE"))
928 is_password = 1;
929 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
930 new_password = 1;
932 /* Shouldn't get this far without a callback. */
933 if (!pwm->override_inquire && !pwm->inquire_func
934 && !is_password && !new_password)
935 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
937 for (;;)
939 size_t len = 0;
940 gpg_error_t arc;
942 result = NULL;
944 if (!pwm->override_inquire && (is_password || new_password))
946 free_result = 1;
947 rc = pwmd_password (data, keyword, &result, &len);
948 if (!rc)
949 rc = GPG_ERR_EOF;
951 else
952 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
953 &len);
955 /* gpg will truncate a passphrase at the first nil byte which may be bad
956 * for generated key files. */
957 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
958 && (is_password || new_password))
960 if (len && result && *result)
962 for (size_t n = 0; n < len; n++)
964 if (result[n] == 0 && n+1 != len)
965 rc = GPG_ERR_INV_PASSPHRASE;
970 cancel:
971 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
973 #ifndef LIBASSUAN_2_1_0
974 gpg_error_t trc = rc;
976 /* Cancel this inquire. */
977 rc = assuan_send_data (pwm->ctx, NULL, 1);
978 if (!rc)
980 char *line;
981 size_t len;
983 /* There is a bug (or feature?) in assuan_send_data() that
984 * when cancelling an inquire the next read from the server is
985 * not done until the next command making the next command
986 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
988 rc = assuan_read_line (pwm->ctx, &line, &len);
990 /* Restore the original error. This differs from the error
991 * returned from the pwmd command (GPG_ERR_CANCELED). This
992 * error is returned to the calling function.
994 if (!rc)
995 rc = trc;
997 #endif
998 break;
1001 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
1003 if (len <= 0 && !result)
1005 rc = 0;
1006 break;
1008 else if ((len <= 0 && result) || (len && !result))
1010 rc = gpg_error (GPG_ERR_INV_ARG);
1011 break;
1014 if (pwm->inquire_maxlen
1015 && pwm->inquire_sent + len > pwm->inquire_maxlen)
1017 rc = gpg_error (GPG_ERR_TOO_LARGE);
1018 if (!free_result)
1019 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
1020 &result, &len);
1021 goto cancel;
1024 arc = assuan_send_data (pwm->ctx, result, len);
1025 if (gpg_err_code (rc) == GPG_ERR_EOF)
1027 rc = arc;
1028 break;
1031 rc = arc;
1033 else if (rc)
1034 break;
1036 if (!rc)
1038 pwm->inquire_sent += len;
1040 if (pwm->status_func)
1042 char buf[ASSUAN_LINELENGTH];
1044 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
1045 pwm->inquire_total);
1046 rc = pwm->status_func (pwm->status_data, buf);
1047 if (rc)
1048 continue;
1053 if (free_result)
1054 pwmd_free (result);
1056 return rc;
1059 static gpg_error_t
1060 parse_assuan_line (pwm_t * pwm)
1062 gpg_error_t rc;
1063 char *line;
1064 size_t len;
1066 rc = assuan_read_line (pwm->ctx, &line, &len);
1067 if (!rc)
1069 if (line[0] == 'O' && line[1] == 'K' &&
1070 (line[2] == 0 || line[2] == ' '))
1073 else if (line[0] == '#')
1076 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
1078 if (pwm->status_func)
1080 rc = pwm->status_func (pwm->status_data,
1081 line[1] == 0 ? line + 1 : line + 2);
1084 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
1085 (line[3] == 0 || line[3] == ' '))
1087 line += 4;
1088 rc = strtol (line, NULL, 10);
1092 return rc;
1095 static void
1096 reset_handle (pwm_t *pwm)
1098 pwm->fd = -1;
1099 pwm->cancel = 0;
1100 pwm->pinentry_disabled = 0;
1101 #ifdef WITH_PINENTRY
1102 if (pwm->pctx)
1103 _pinentry_disconnect (pwm);
1104 #endif
1105 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1106 #ifdef WITH_GNUTLS
1107 pwm->tls_error = 0;
1108 #endif
1110 if (pwm->tcp)
1111 pwm->tcp->rc = 0;
1112 #endif
1115 gpg_error_t
1116 pwmd_disconnect (pwm_t * pwm)
1118 if (!pwm)
1119 return FINISH (GPG_ERR_INV_ARG);
1121 command_start (pwm);
1123 if (pwm->fd == -1)
1124 return FINISH (GPG_ERR_INV_STATE);
1126 disconnect (pwm);
1127 reset_handle (pwm);
1128 return 0;
1131 /* Note that this should only be called when not in a command. */
1132 gpg_error_t
1133 pwmd_process (pwm_t * pwm)
1135 gpg_error_t rc = 0;
1136 fd_set fds;
1137 struct timeval tv = { 0, 0 };
1138 int n;
1140 if (!pwm || pwm->fd == -1)
1141 return FINISH (GPG_ERR_INV_ARG);
1142 else if (!pwm->ctx)
1143 return FINISH (GPG_ERR_INV_STATE);
1145 FD_ZERO (&fds);
1146 FD_SET (pwm->fd, &fds);
1147 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1149 if (n == -1)
1150 return FINISH (gpg_error_from_syserror ());
1152 if (n > 0)
1154 if (FD_ISSET (pwm->fd, &fds))
1155 rc = parse_assuan_line (pwm);
1158 while (!rc && assuan_pending_line (pwm->ctx))
1159 rc = parse_assuan_line (pwm);
1161 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1162 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1164 close (pwm->fd);
1165 pwm->fd = -1;
1167 #endif
1169 return FINISH (rc);
1172 static gpg_error_t
1173 status_cb (void *data, const char *line)
1175 pwm_t *pwm = data;
1177 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1178 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1179 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1181 pwmd_free (pwm->passphrase_hint);
1182 pwm->passphrase_hint = pwmd_strdup (line+16);
1184 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1186 pwmd_free (pwm->passphrase_info);
1187 pwm->passphrase_info = pwmd_strdup (line+16);
1190 if (pwm->status_func)
1191 return pwm->status_func (pwm->status_data, line);
1193 return 0;
1196 gpg_error_t
1197 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1198 char **result, size_t * len, const char *cmd)
1200 membuf_t data;
1201 gpg_error_t rc;
1203 if (!cmd || !*cmd)
1204 return FINISH (GPG_ERR_INV_ARG);
1206 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1207 return FINISH (GPG_ERR_LINE_TOO_LONG);
1209 data.len = 0;
1210 data.buf = NULL;
1211 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1212 #ifdef WITH_QUALITY
1213 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1214 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1215 #else
1216 inquire_cb, pwm,
1217 #endif
1218 status_cb, pwm);
1220 if (rc)
1222 if (data.buf)
1224 pwmd_free (data.buf);
1225 data.buf = NULL;
1228 else
1230 if (data.buf)
1232 inquire_realloc_cb (&data, "", 1);
1234 if (result)
1235 *result = (char *) data.buf;
1236 else
1237 pwmd_free (data.buf);
1239 if (len)
1240 *len = data.len;
1244 pwm->inquire_maxlen = 0;
1245 return rc;
1248 gpg_error_t
1249 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1250 pwmd_inquire_cb_t func, void *user, const char *cmd,
1251 va_list ap)
1253 char *buf;
1254 size_t len;
1255 va_list ap2;
1257 command_start (pwm);
1259 if (result)
1260 *result = NULL;
1262 if (rlen)
1263 *rlen = 0;
1265 if (!pwm || !cmd)
1266 return FINISH (GPG_ERR_INV_ARG);
1267 if (!pwm->ctx)
1268 return FINISH (GPG_ERR_INV_STATE);
1271 * C99 allows the dst pointer to be null which will calculate the length
1272 * of the would-be result and return it.
1274 va_copy (ap2, ap);
1275 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1276 buf = (char *) pwmd_malloc (len);
1277 if (!buf)
1279 va_end (ap2);
1280 return FINISH (GPG_ERR_ENOMEM);
1283 len = vsnprintf (buf, len, cmd, ap2);
1284 va_end (ap2);
1286 if (buf[strlen (buf) - 1] == '\n')
1287 buf[strlen (buf) - 1] = 0;
1288 if (buf[strlen (buf) - 1] == '\r')
1289 buf[strlen (buf) - 1] = 0;
1291 pwm->inquire_func = func;
1292 pwm->inquire_data = user;
1293 pwm->inquire_sent = 0;
1294 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1295 pwmd_free (buf);
1296 return rc;
1299 gpg_error_t
1300 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1301 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1303 va_list ap;
1305 if (result)
1306 *result = NULL;
1308 if (len)
1309 *len = 0;
1311 if (!pwm || !cmd)
1312 return FINISH (GPG_ERR_INV_ARG);
1313 if (!pwm->ctx)
1314 return FINISH (GPG_ERR_INV_STATE);
1316 va_start (ap, cmd);
1317 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1318 va_end (ap);
1319 return rc;
1322 static gpg_error_t
1323 send_pinentry_timeout (pwm_t *pwm)
1325 gpg_error_t rc = 0;
1327 if ((pwm->pinentry_timeout >= 0
1328 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1329 || (pwm->pinentry_timeout == -1
1330 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1332 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1333 "OPTION pinentry-timeout=%i",
1334 pwm->pinentry_timeout);
1335 if (!rc)
1336 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1339 return rc;
1342 static gpg_error_t
1343 send_pinentry_options (pwm_t * pwm)
1345 gpg_error_t rc;
1347 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1348 "OPTION disable-pinentry=0");
1349 if (!rc && pwm->pinentry_tty)
1350 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1351 pwm->pinentry_tty);
1353 if (!rc && pwm->pinentry_term)
1354 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1355 pwm->pinentry_term);
1357 if (!rc && pwm->pinentry_display)
1358 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1359 pwm->pinentry_display);
1361 if (!rc && pwm->pinentry_desc)
1362 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1363 pwm->pinentry_desc);
1365 if (!rc && pwm->pinentry_lcctype)
1366 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1367 pwm->pinentry_lcctype);
1369 if (!rc && pwm->pinentry_lcmessages)
1370 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1371 pwm->pinentry_lcmessages);
1373 if (!rc)
1374 rc = send_pinentry_timeout (pwm);
1376 return rc;
1379 gpg_error_t
1380 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1382 if (!pwm || !result)
1383 return FINISH (GPG_ERR_INV_ARG);
1385 *result = PWMD_SOCKET_LOCAL;
1387 if (pwm->fd == -1)
1388 return FINISH (GPG_ERR_INV_STATE);
1390 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1391 #ifdef WITH_SSH
1392 if (pwm->tcp && pwm->tcp->ssh)
1393 *result = PWMD_SOCKET_SSH;
1394 #endif
1395 #ifdef WITH_GNUTLS
1396 if (pwm->tcp && pwm->tcp->tls)
1397 *result = PWMD_SOCKET_TLS;
1398 #endif
1399 #endif
1400 return 0;
1403 static gpg_error_t
1404 disable_pinentry (pwm_t *pwm, int *disable)
1406 gpg_error_t rc;
1407 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1408 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1409 #else
1410 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1411 #endif
1413 if (disable)
1414 *disable = no_pinentry;
1416 if (pwm->pinentry_disabled && no_pinentry)
1417 return 0;
1418 else if (!pwm->pinentry_disabled && !no_pinentry)
1419 return 0;
1421 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1422 no_pinentry);
1423 if (!rc)
1424 pwm->pinentry_disabled = no_pinentry;
1426 return rc;
1429 gpg_error_t
1430 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1431 void *data)
1433 gpg_error_t rc = 0;
1434 int no_pinentry = 0;
1436 if (!pwm || !filename || !*filename)
1437 return FINISH (GPG_ERR_INV_ARG);
1439 if (!pwm->ctx)
1440 return FINISH (GPG_ERR_INV_STATE);
1442 command_start (pwm);
1443 rc = disable_pinentry (pwm, &no_pinentry);
1444 if (!rc && !no_pinentry)
1445 rc = send_pinentry_options (pwm);
1447 if (!rc)
1449 pwm->pinentry_try = 0;
1450 pwmd_free (pwm->filename);
1451 pwm->filename = pwmd_strdup (filename);
1455 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1456 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1457 filename);
1459 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1460 && pwm->pinentry_disabled
1461 && ++pwm->pinentry_try < pwm->pinentry_tries);
1463 pwm->pinentry_try = 0;
1465 if (rc)
1467 pwmd_free (pwm->filename);
1468 pwm->filename = NULL;
1472 pwmd_free (pwm->passphrase_hint);
1473 pwmd_free (pwm->passphrase_info);
1474 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1475 return FINISH (rc);
1478 static gpg_error_t
1479 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1480 void *data, int save)
1482 gpg_error_t rc = 0;
1483 int no_pinentry = 0;
1485 if (!pwm)
1486 return FINISH (GPG_ERR_INV_ARG);
1487 if (!pwm->ctx)
1488 return FINISH (GPG_ERR_INV_STATE);
1490 command_start (pwm);
1491 rc = disable_pinentry (pwm, &no_pinentry);
1492 if (!rc && !no_pinentry)
1493 rc = send_pinentry_options (pwm);
1495 if (!rc)
1496 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1497 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
1499 pwmd_free (pwm->passphrase_hint);
1500 pwmd_free (pwm->passphrase_info);
1501 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1502 return FINISH (rc);
1505 gpg_error_t
1506 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1508 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1511 gpg_error_t
1512 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1514 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1517 static gpg_error_t
1518 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1520 int n, *intp;
1521 size_t *sizetp;
1522 char *arg1, **charpp;
1523 gpg_error_t rc = 0;
1525 if (!pwm)
1526 return GPG_ERR_INV_ARG;
1528 command_start (pwm);
1529 switch (opt)
1531 case PWMD_OPTION_SERVER_VERSION:
1532 if (!get)
1533 return GPG_ERR_NOT_SUPPORTED;
1535 if (!pwm)
1536 rc = GPG_ERR_INV_ARG;
1537 else if (!pwm->ctx)
1538 rc = GPG_ERR_INV_STATE;
1539 else
1541 unsigned *u = va_arg (ap, unsigned *);
1542 *u = pwm->version;
1545 break;
1546 case PWMD_OPTION_SIGPIPE:
1547 if (get)
1549 intp = va_arg (ap, int *);
1550 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1551 break;
1554 n = va_arg (ap, int);
1555 if (n < 0 || n > 1)
1556 rc = GPG_ERR_INV_VALUE;
1558 if (n)
1559 pwm->opts |= OPT_SIGPIPE;
1560 else
1561 pwm->opts &= ~OPT_SIGPIPE;
1563 break;
1564 case PWMD_OPTION_LOCK_ON_OPEN:
1565 if (get)
1567 intp = va_arg (ap, int *);
1568 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1569 break;
1572 n = va_arg (ap, int);
1574 if (n < 0 || n > 1)
1575 rc = GPG_ERR_INV_VALUE;
1577 if (n)
1578 pwm->opts |= OPT_LOCK_ON_OPEN;
1579 else
1580 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1582 break;
1583 case PWMD_OPTION_INQUIRE_TOTAL:
1584 if (get)
1586 sizetp = va_arg (ap, size_t *);
1587 *sizetp = pwm->inquire_total;
1588 break;
1591 pwm->inquire_total = va_arg (ap, size_t);
1592 break;
1593 case PWMD_OPTION_STATUS_CB:
1594 if (get)
1596 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1598 *cb = pwm->status_func;
1599 break;
1602 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1603 break;
1604 case PWMD_OPTION_STATUS_DATA:
1605 if (get)
1607 void **data = va_arg (ap, void **);
1609 *data = pwm->status_data;
1610 break;
1613 pwm->status_data = va_arg (ap, void *);
1614 break;
1615 case PWMD_OPTION_NO_PINENTRY:
1616 if (get)
1618 intp = va_arg (ap, int *);
1619 *intp = pwm->disable_pinentry;
1620 break;
1623 n = va_arg (ap, int);
1625 if (n < 0 || n > 1)
1626 rc = GPG_ERR_INV_VALUE;
1627 else
1628 pwm->disable_pinentry = n;
1629 break;
1630 case PWMD_OPTION_LOCAL_PINENTRY:
1631 if (get)
1633 intp = va_arg (ap, int *);
1634 *intp = pwm->local_pinentry;
1635 break;
1638 n = va_arg (ap, int);
1640 if (n < 0 || n > 1)
1641 rc = GPG_ERR_INV_VALUE;
1642 else
1643 pwm->local_pinentry = n;
1645 break;
1646 case PWMD_OPTION_PINENTRY_TIMEOUT:
1647 if (get)
1649 intp = va_arg (ap, int *);
1650 *intp = pwm->pinentry_timeout;
1651 break;
1654 n = va_arg (ap, int);
1656 if (n < 0)
1657 rc = GPG_ERR_INV_VALUE;
1658 else
1659 pwm->pinentry_timeout = n;
1660 break;
1661 case PWMD_OPTION_PINENTRY_TRIES:
1662 if (get)
1664 intp = va_arg (ap, int *);
1665 *intp = pwm->pinentry_tries;
1666 break;
1669 n = va_arg (ap, int);
1670 pwm->pinentry_tries = n;
1671 break;
1672 case PWMD_OPTION_PINENTRY_PATH:
1673 if (get)
1675 charpp = va_arg (ap, char **);
1676 *charpp = pwm->pinentry_path;
1677 break;
1680 arg1 = va_arg (ap, char *);
1681 pwmd_free (pwm->pinentry_path);
1682 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1683 break;
1684 case PWMD_OPTION_PINENTRY_TTY:
1685 if (get)
1687 charpp = va_arg (ap, char **);
1688 *charpp = pwm->pinentry_tty;
1689 break;
1692 arg1 = va_arg (ap, char *);
1693 pwmd_free (pwm->pinentry_tty);
1694 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1695 break;
1696 case PWMD_OPTION_PINENTRY_DISPLAY:
1697 if (get)
1699 charpp = va_arg (ap, char **);
1700 *charpp = pwm->pinentry_display;
1701 break;
1704 arg1 = va_arg (ap, char *);
1705 pwmd_free (pwm->pinentry_display);
1706 pwm->pinentry_display = arg1 ? pwmd_strdup (arg1) : NULL;
1707 break;
1708 case PWMD_OPTION_PINENTRY_TERM:
1709 if (get)
1711 charpp = va_arg (ap, char **);
1712 *charpp = pwm->pinentry_term;
1713 break;
1716 arg1 = va_arg (ap, char *);
1717 pwmd_free (pwm->pinentry_term);
1718 pwm->pinentry_term = arg1 ? pwmd_strdup (arg1) : NULL;
1719 break;
1720 case PWMD_OPTION_PINENTRY_ERROR:
1721 if (get)
1723 charpp = va_arg (ap, char **);
1724 *charpp = pwm->pinentry_error;
1725 break;
1728 arg1 = va_arg (ap, char *);
1729 pwmd_free (pwm->pinentry_error);
1730 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1731 break;
1732 case PWMD_OPTION_PINENTRY_PROMPT:
1733 if (get)
1735 charpp = va_arg (ap, char **);
1736 *charpp = pwm->pinentry_prompt;
1737 break;
1740 arg1 = va_arg (ap, char *);
1741 pwmd_free (pwm->pinentry_prompt);
1742 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1743 break;
1744 case PWMD_OPTION_PINENTRY_DESC:
1745 if (get)
1747 charpp = va_arg (ap, char **);
1748 *charpp = pwm->pinentry_desc;
1749 break;
1752 arg1 = va_arg (ap, char *);
1753 pwmd_free (pwm->pinentry_desc);
1754 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1755 break;
1756 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1757 if (get)
1759 charpp = va_arg (ap, char **);
1760 *charpp = pwm->pinentry_lcctype;
1761 break;
1764 arg1 = va_arg (ap, char *);
1765 pwmd_free (pwm->pinentry_lcctype);
1766 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1767 break;
1768 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1769 if (get)
1771 charpp = va_arg (ap, char **);
1772 *charpp = pwm->pinentry_lcmessages;
1773 break;
1776 arg1 = va_arg (ap, char *);
1777 pwmd_free (pwm->pinentry_lcmessages);
1778 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1779 break;
1780 case PWMD_OPTION_KNOWNHOST_CB:
1781 if (get)
1783 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1785 *cb = pwm->kh_cb;
1786 break;
1789 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1790 break;
1791 case PWMD_OPTION_KNOWNHOST_DATA:
1792 if (get)
1794 void **data = va_arg (ap, void **);
1796 *data = pwm->kh_data;
1797 break;
1800 pwm->kh_data = va_arg (ap, void *);
1801 break;
1802 case PWMD_OPTION_SSH_AGENT:
1803 if (get)
1805 intp = va_arg (ap, int *);
1806 *intp = pwm->use_agent;
1807 break;
1810 pwm->use_agent = va_arg (ap, int);
1812 if (pwm->use_agent < 0 || pwm->use_agent > 1)
1814 pwm->use_agent = 0;
1815 rc = GPG_ERR_INV_VALUE;
1817 break;
1818 case PWMD_OPTION_TLS_VERIFY:
1819 if (get)
1821 intp = va_arg (ap, int *);
1822 *intp = pwm->tls_verify;
1823 break;
1826 pwm->tls_verify = va_arg (ap, int);
1828 if (pwm->tls_verify < 0 || pwm->tls_verify > 1)
1830 pwm->tls_verify = 0;
1831 rc = GPG_ERR_INV_VALUE;
1833 break;
1834 case PWMD_OPTION_SOCKET_TIMEOUT:
1835 if (get)
1837 intp = va_arg (ap, int *);
1838 *intp = pwm->socket_timeout;
1839 break;
1842 pwm->socket_timeout = va_arg (ap, int);
1843 if (pwm->socket_timeout < 0)
1845 pwm->socket_timeout = 0;
1846 rc = GPG_ERR_INV_VALUE;
1849 #ifdef WITH_SSH
1850 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1852 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1853 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1854 pwm->socket_timeout * 1000);
1856 #endif
1857 #ifdef WITH_GNUTLS
1858 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1859 pwm->tcp->tls->timeout = pwm->socket_timeout;
1860 #endif
1861 break;
1862 case PWMD_OPTION_OVERRIDE_INQUIRE:
1863 if (get)
1865 intp = va_arg (ap, int *);
1866 *intp = pwm->override_inquire;
1867 break;
1870 pwm->override_inquire = va_arg (ap, int);
1872 if (pwm->override_inquire < 0 || pwm->override_inquire > 1)
1874 pwm->override_inquire = 0;
1875 rc = GPG_ERR_INV_VALUE;
1877 break;
1878 default:
1879 rc = GPG_ERR_UNKNOWN_OPTION;
1880 break;
1883 return FINISH (rc);
1886 gpg_error_t
1887 pwmd_setopt (pwm_t * pwm, pwmd_option_t opt, ...)
1889 va_list ap;
1890 gpg_error_t rc = 0;
1892 va_start (ap, opt);
1893 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
1894 va_end (ap);
1895 return FINISH (rc);
1898 gpg_error_t
1899 pwmd_getopt (pwm_t *pwm, pwmd_option_t opt, ...)
1901 va_list ap;
1902 gpg_error_t rc = 0;
1904 va_start (ap, opt);
1905 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
1906 va_end (ap);
1907 return FINISH (rc);
1910 gpg_error_t
1911 pwmd_new (const char *name, pwm_t ** pwm)
1913 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
1914 gpg_error_t rc;
1916 if (!h)
1917 return FINISH (GPG_ERR_ENOMEM);
1919 if (name)
1921 h->name = pwmd_strdup (name);
1922 if (!h->name)
1924 pwmd_free (h);
1925 return FINISH (GPG_ERR_ENOMEM);
1929 reset_handle (h);
1930 h->pinentry_timeout = -1;
1931 h->current_pinentry_timeout = -1;
1932 h->pinentry_tries = 3;
1933 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1934 h->prot = PWMD_IP_ANY;
1935 #endif
1937 if (isatty (STDOUT_FILENO))
1939 char buf[256];
1940 int err = ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
1942 if (!err)
1944 h->pinentry_tty = pwmd_strdup (buf);
1945 if (!h->pinentry_tty)
1947 rc = GPG_ERR_ENOMEM;
1948 goto fail;
1953 if (getenv ("TERM") && h->pinentry_tty)
1955 h->pinentry_term = pwmd_strdup (getenv ("TERM"));
1956 if (!h->pinentry_term)
1958 rc = GPG_ERR_ENOMEM;
1959 goto fail;
1963 if (getenv ("DISPLAY"))
1965 h->pinentry_display = pwmd_strdup (getenv ("DISPLAY"));
1966 if (!h->pinentry_display)
1968 rc = GPG_ERR_ENOMEM;
1969 goto fail;
1973 update_pinentry_settings (h);
1974 *pwm = h;
1975 return 0;
1977 fail:
1978 pwmd_close (h);
1979 return FINISH (rc);
1982 void
1983 pwmd_free (void *ptr)
1985 _xfree (ptr);
1988 void *
1989 pwmd_malloc (size_t size)
1991 return _xmalloc (size);
1994 void *
1995 pwmd_calloc (size_t nmemb, size_t size)
1997 return _xcalloc (nmemb, size);
2000 void *
2001 pwmd_realloc (void *ptr, size_t size)
2003 return _xrealloc (ptr, size);
2006 char *
2007 pwmd_strdup (const char *str)
2009 char *t;
2010 size_t len;
2011 register size_t c;
2013 len = strlen (str);
2014 t = _xmalloc ((len + 1) * sizeof (char));
2015 if (!t)
2016 return NULL;
2018 for (c = 0; c < len; c++)
2019 t[c] = str[c];
2021 t[c] = 0;
2022 return t;
2025 char *
2026 pwmd_strdup_printf (const char *fmt, ...)
2028 va_list ap, ap2;
2029 int len;
2030 char *buf;
2032 if (!fmt)
2033 return NULL;
2035 va_start (ap, fmt);
2036 va_copy (ap2, ap);
2037 len = vsnprintf (NULL, 0, fmt, ap);
2038 va_end (ap);
2039 buf = pwmd_malloc (++len);
2040 if (buf)
2041 vsnprintf (buf, len, fmt, ap2);
2043 va_end (ap2);
2044 return buf;
2047 gpg_error_t
2048 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
2049 size_t * len, pwmd_pinentry_t which)
2051 #ifndef WITH_PINENTRY
2052 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
2053 #else
2054 command_start (pwm);
2055 gpg_error_t rc = _pwmd_getpin (pwm, filename, result, len, which);
2057 return FINISH (rc);
2058 #endif
2061 const char *
2062 pwmd_version ()
2064 return LIBPWMD_VERSION_STR;
2067 unsigned int
2068 pwmd_features ()
2070 unsigned int n = 0;
2072 #ifdef WITH_PINENTRY
2073 n |= PWMD_FEATURE_PINENTRY;
2074 #endif
2075 #ifdef WITH_SSH
2076 n |= PWMD_FEATURE_SSH;
2077 #endif
2078 #ifdef WITH_QUALITY
2079 n |= PWMD_FEATURE_CRACK;
2080 #endif
2081 #ifdef WITH_GNUTLS
2082 n |= PWMD_FEATURE_GNUTLS;
2083 #endif
2084 return n;
2087 gpg_error_t
2088 pwmd_fd (pwm_t * pwm, int *fd)
2090 if (!pwm || !fd)
2091 return FINISH (GPG_ERR_INV_ARG);
2093 if (pwm->fd == -1)
2094 return FINISH (GPG_ERR_INV_STATE);
2096 *fd = pwm->fd;
2097 return 0;
2100 void
2101 pwmd_set_pointer (pwm_t *pwm, void *data)
2103 pwm->user_data = data;
2106 void *
2107 pwmd_get_pointer (pwm_t *pwm)
2109 return pwm->user_data;
2113 pwmd_tls_error (pwm_t *pwm)
2115 #ifndef WITH_GNUTLS
2116 return 0;
2117 #else
2118 return pwm ? pwm->tls_error : 0;
2119 #endif
2122 gpg_error_t
2123 pwmd_cancel (pwm_t *pwm)
2125 if (!pwm)
2126 return FINISH (GPG_ERR_INV_ARG);
2128 if (pwm->fd == -1 && !pwm->tcp)
2129 return FINISH (GPG_ERR_INV_STATE);
2131 /* Can only cancel the connection for the time being. */
2132 if (pwm->connected)
2133 return FINISH (GPG_ERR_INV_STATE);
2135 pwm->cancel = 1;
2136 return 0;