Add pwmd_passwd().
[libpwmd.git] / src / libpwmd.c
blob38178b500fd9037604a354ed23b99330d4cf278a
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
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->tcp->tls, 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->tcp->tls, 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 int active[2];
174 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
176 if (n <= 0)
177 return GPG_ERR_EBADFD;
179 pwm->fd = active[0];
180 #ifdef WITH_PINENTRY
181 pwm->pinentry_pid = -1;
182 #endif
184 if (pwm->name)
185 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
186 pwm->name);
188 return rc;
191 static gpg_error_t
192 connect_uds (pwm_t * pwm, const char *path)
194 char *socketpath = NULL;
195 struct passwd pw;
196 char *pwbuf;
197 gpg_error_t rc;
199 if (!pwm)
200 return GPG_ERR_INV_ARG;
202 pwbuf = _getpwuid (&pw);
203 if (!pwbuf)
204 return gpg_error_from_syserror ();
206 if (!path || !*path)
207 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
208 else
209 socketpath = _expand_homedir ((char *) path, &pw);
211 pwmd_free (pwbuf);
212 if (!socketpath)
213 return GPG_ERR_ENOMEM;
215 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
216 pwmd_free (socketpath);
217 return rc ? rc : _connect_finalize (pwm);
220 static gpg_error_t
221 init_handle (pwm_t * pwm)
223 gpg_error_t rc;
224 static struct assuan_malloc_hooks mhooks = {
225 pwmd_malloc, pwmd_realloc, pwmd_free
227 static struct assuan_system_hooks shooks = {
228 ASSUAN_SYSTEM_HOOKS_VERSION,
229 __assuan_usleep,
230 __assuan_pipe,
231 __assuan_close,
232 hook_read,
233 hook_write,
234 //FIXME
235 NULL, //recvmsg
236 NULL, //sendmsg both are used for FD passing
237 __assuan_spawn,
238 hook_waitpid,
239 __assuan_socketpair,
240 __assuan_socket,
241 __assuan_connect
244 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
245 NULL);
246 if (rc)
247 return rc;
249 assuan_set_pointer (pwm->ctx, pwm);
250 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
251 return 0;
254 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
255 void
256 free_tcp (struct tcp_s *tcp)
258 if (!tcp)
259 return;
261 #ifdef WITH_SSH
262 _free_ssh_conn (tcp->ssh);
263 #endif
264 #ifdef WITH_GNUTLS
265 tls_free (tcp->tls);
266 #endif
268 pwmd_free (tcp->host);
269 if (tcp->addrs)
271 freeaddrinfo (tcp->addrs);
272 tcp->addrs = NULL;
275 pwmd_free (tcp);
277 #endif
279 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
280 gpg_error_t
281 tcp_connect_common (pwm_t * pwm)
283 struct addrinfo hints = { 0 };
284 int n;
285 char portstr[6];
286 gpg_error_t rc = 0;
288 switch (pwm->prot)
290 case PWMD_IP_ANY:
291 hints.ai_family = AF_UNSPEC;
292 break;
293 case PWMD_IPV4:
294 hints.ai_family = AF_INET;
295 break;
296 case PWMD_IPV6:
297 hints.ai_family = AF_INET6;
298 break;
301 hints.ai_socktype = SOCK_STREAM;
302 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
303 n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
304 if (n)
306 fprintf (stderr, "%s\n", gai_strerror (n));
307 return GPG_ERR_UNKNOWN_HOST; //FIXME
310 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
311 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
313 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
314 if (pwm->fd == -1)
316 rc = gpg_error_from_syserror ();
317 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
318 break;
319 continue;
322 if (pwm->socket_timeout)
323 fcntl (pwm->fd, F_SETFL, O_NONBLOCK);
325 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
326 pwm->tcp->addr->ai_family == AF_INET6
327 ? sizeof (struct sockaddr_in6)
328 : sizeof (struct sockaddr)) == -1)
330 int n;
331 struct timeval tv = { pwm->socket_timeout, 0 };
332 fd_set wfds;
334 rc = gpg_error_from_syserror ();
335 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
337 close (pwm->fd);
338 pwm->fd = -1;
339 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
340 return rc;
343 FD_ZERO (&wfds);
344 FD_SET (pwm->fd, &wfds);
345 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
346 rc = 0;
347 if (!n)
348 rc = gpg_error (GPG_ERR_ETIMEDOUT);
349 else if (n != -1)
351 socklen_t len = sizeof(int);
353 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
354 if (n)
355 rc = gpg_error_from_errno (n);
357 else if (n == -1)
358 rc = gpg_error_from_syserror ();
360 if (rc)
362 close (pwm->fd);
363 pwm->fd = -1;
364 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
365 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT)
366 return rc;
368 else
369 break;
371 else
372 break;
375 if (!rc && pwm->socket_timeout)
376 fcntl (pwm->fd, F_SETFL, 0);
378 return rc;
380 #endif
382 gpg_error_t
383 pwmd_connect (pwm_t * pwm, const char *url, ...)
385 const char *p = url;
386 gpg_error_t rc;
388 if (!pwm)
389 return FINISH (GPG_ERR_INV_ARG);
390 else if (!pwm->ctx)
392 rc = init_handle (pwm);
393 if (rc)
394 return rc;
397 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
399 if (p && *p == '/')
400 rc = connect_uds (pwm, p);
401 else if (!p || !strncmp (p, "file://", 7))
403 if (p)
404 p += 7;
405 #ifdef DEFAULT_PWMD_SOCKET
406 else
407 p = DEFAULT_PWMD_SOCKET;
408 #endif
409 rc = connect_uds (pwm, p);
411 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
412 !strncmp (p, "ssh4://", 7))
414 #ifndef WITH_SSH
415 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
416 #else
417 char *host = NULL;
418 int port;
419 char *username = NULL;
421 if (!strncmp (p, "ssh6://", 7))
423 pwm->prot = PWMD_IPV6;
424 p += 7;
426 else if (!strncmp (p, "ssh4://", 7))
428 pwm->prot = PWMD_IPV4;
429 p += 7;
431 else
433 pwm->prot = PWMD_IP_ANY;
434 p += 6;
437 rc = _parse_ssh_url (p, &host, &port, &username);
438 if (!rc)
440 va_list ap;
441 char *identity = NULL;
442 char *knownhosts = NULL;
444 va_start (ap, url);
445 identity = va_arg (ap, char *);
447 if (!identity && !pwm->use_agent)
448 rc = GPG_ERR_INV_ARG;
449 else
450 knownhosts = va_arg (ap, char *);
452 va_end (ap);
454 if (!rc)
455 rc = _do_ssh_connect (pwm, host, port, identity, username,
456 knownhosts);
457 if (!rc)
459 rc = _connect_finalize (pwm);
460 if (rc)
462 free_tcp (pwm->tcp);
463 pwm->tcp = NULL;
468 pwmd_free (host);
469 pwmd_free (username);
470 return FINISH (rc);
471 #endif
473 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
474 !strncmp (p, "tls4://", 7))
476 #ifndef WITH_GNUTLS
477 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
478 #else
479 char *host = NULL;
480 int port;
482 if (!strncmp (p, "tls6://", 7))
484 pwm->prot = PWMD_IPV6;
485 p += 7;
487 else if (!strncmp (p, "tls4://", 7))
489 pwm->prot = PWMD_IPV4;
490 p += 7;
492 else
494 pwm->prot = PWMD_IP_ANY;
495 p += 6;
498 rc = _parse_tls_url (p, &host, &port);
499 if (!rc)
501 va_list ap;
502 char *clientcert = NULL;
503 char *clientkey = NULL;
504 char *cacert = NULL;
505 char *prio = NULL;
506 char *server_fp = NULL;
508 va_start (ap, url);
509 clientcert = va_arg (ap, char *);
511 if (!clientcert)
512 rc = GPG_ERR_INV_ARG;
513 else
515 clientkey = va_arg (ap, char *);
516 if (!clientkey)
517 rc = GPG_ERR_INV_ARG;
518 else
520 cacert = va_arg (ap, char *);
521 if (!cacert)
522 rc = GPG_ERR_INV_ARG;
523 else
525 prio = va_arg (ap, char *);
526 server_fp = va_arg (ap, char *);
531 va_end (ap);
533 if (!rc)
534 rc = _do_tls_connect (pwm, host, port, clientcert, clientkey,
535 cacert, prio, server_fp, pwm->tls_verify);
536 if (!rc)
538 rc = _connect_finalize (pwm);
539 if (rc)
541 free_tcp (pwm->tcp);
542 pwm->tcp = NULL;
547 pwmd_free (host);
548 return FINISH (rc);
549 #endif
552 return FINISH (rc);
555 static void
556 disconnect (pwm_t * pwm)
558 if (!pwm)
559 return;
561 if (pwm->ctx)
562 assuan_release (pwm->ctx);
564 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
565 free_tcp (pwm->tcp);
566 pwm->tcp = NULL;
567 #endif
568 pwm->ctx = NULL;
569 pwm->fd = -1;
572 void
573 pwmd_close (pwm_t * pwm)
575 if (!pwm)
576 return;
578 disconnect (pwm);
579 pwmd_free (pwm->pinentry_error);
580 pwmd_free (pwm->pinentry_desc);
581 pwmd_free (pwm->pinentry_prompt);
582 pwmd_free (pwm->pinentry_tty);
583 pwmd_free (pwm->pinentry_display);
584 pwmd_free (pwm->pinentry_term);
585 pwmd_free (pwm->pinentry_lcctype);
586 pwmd_free (pwm->pinentry_lcmessages);
587 pwmd_free (pwm->filename);
588 pwmd_free (pwm->name);
590 #ifdef WITH_PINENTRY
591 if (pwm->pctx)
592 _pinentry_disconnect (pwm);
593 #endif
595 pwmd_free (pwm);
598 static gpg_error_t
599 inquire_realloc_cb (void *data, const void *buffer, size_t len)
601 membuf_t *mem = (membuf_t *) data;
602 void *p;
604 if (!buffer)
605 return 0;
607 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
608 return gpg_error (GPG_ERR_ENOMEM);
610 mem->buf = p;
611 memcpy ((char *) mem->buf + mem->len, buffer, len);
612 mem->len += len;
613 return 0;
616 static gpg_error_t
617 get_password (pwm_t * pwm, char **result, size_t * len,
618 pwmd_pinentry_t w, int echo)
620 char buf[LINE_MAX] = { 0 }, *p;
621 struct termios told, tnew;
622 char *key = NULL;
624 if (result)
625 *result = NULL;
627 if (len)
628 *len = 0;
630 if (!isatty (STDIN_FILENO))
632 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
633 return GPG_ERR_ENOTTY;
636 if (!echo)
638 if (tcgetattr (STDIN_FILENO, &told) == -1)
639 return gpg_error_from_syserror ();
641 memcpy (&tnew, &told, sizeof (struct termios));
642 tnew.c_lflag &= ~(ECHO);
643 tnew.c_lflag |= ICANON | ECHONL;
645 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
647 int n = errno;
649 tcsetattr (STDIN_FILENO, TCSANOW, &told);
650 return gpg_error_from_errno (n);
654 switch (w)
656 case PWMD_PINENTRY_OPEN:
657 fprintf (stderr, N_("Password for %s: "), pwm->filename);
658 break;
659 case PWMD_PINENTRY_OPEN_FAILED:
660 fprintf (stderr, N_("Invalid password. Password for %s: "),
661 pwm->filename);
662 break;
663 case PWMD_PINENTRY_SAVE:
664 fprintf (stderr, N_("New password for %s: "), pwm->filename);
665 break;
666 case PWMD_PINENTRY_SAVE_CONFIRM:
667 fprintf (stderr, N_("Confirm password: "));
668 break;
669 default:
670 break;
673 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
675 tcsetattr (STDIN_FILENO, TCSANOW, &told);
676 return 0;
679 if (!echo)
680 tcsetattr (STDIN_FILENO, TCSANOW, &told);
682 if (feof (stdin))
684 clearerr (stdin);
685 return GPG_ERR_CANCELED;
688 /* Strip the newline character. */
689 p[strlen (p) - 1] = 0;
691 if (buf[0])
693 key = pwmd_strdup_printf ("%s", p);
694 memset (buf, 0, sizeof (buf));
695 if (!key)
696 return GPG_ERR_ENOMEM;
698 if (result)
699 *result = key;
701 if (len)
702 *len = strlen (key);
704 else
706 if (result)
707 *result = pwmd_strdup ("");
709 if (len)
710 *len = 1;
713 return 0;
716 gpg_error_t
717 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
719 gpg_error_t rc;
720 int new_password = 0;
721 char *password = NULL, *newpass = NULL;
722 int error = 0;
724 if (data)
725 *data = NULL;
727 if (size)
728 *size = 0;
730 if (!strcmp (keyword, "NEW_PASSPHRASE"))
731 new_password = 1;
733 if (!new_password && pwm->pinentry_try)
734 error = 1;
736 again:
737 if (pwm->disable_pinentry)
739 rc = get_password (pwm, &password, size,
740 new_password ? PWMD_PINENTRY_SAVE :
741 error ? PWMD_PINENTRY_OPEN_FAILED :
742 PWMD_PINENTRY_OPEN, 0);
743 if (!rc && new_password)
744 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
747 else
749 pwmd_pinentry_t which;
751 if (error)
752 which = new_password
753 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
754 else
755 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
757 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
758 if (!rc && new_password)
759 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
760 PWMD_PINENTRY_SAVE_CONFIRM);
763 if (!rc && new_password)
765 if ((!password && newpass) || (!newpass && password)
766 || (newpass && password && strcmp (newpass, password)))
768 if (pwm->disable_pinentry)
769 fprintf (stderr, N_("Passphrases do not match.\n"));
771 pwmd_free (password);
772 pwmd_free (newpass);
773 password = newpass = NULL;
774 error = 1;
775 goto again;
779 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
780 pwmd_free (newpass);
781 if (!rc && data)
782 *data = password;
784 return rc;
787 static gpg_error_t
788 inquire_cb (void *data, const char *keyword)
790 pwm_t *pwm = (pwm_t *) data;
791 gpg_error_t rc = 0;
792 int free_result = 0;
793 char *result = NULL;
794 int is_password = 0;
795 int new_password = 0;
797 if (!strcmp (keyword, "PASSPHRASE"))
798 is_password = 1;
799 else if (!strcmp (keyword, "NEW_PASSPHRASE"))
800 new_password = 1;
802 /* Shouldn't get this far without a callback. */
803 if (!pwm->override_inquire && !pwm->inquire_func
804 && !is_password && !new_password)
805 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
807 for (;;)
809 size_t len = 0;
810 gpg_error_t arc;
812 result = NULL;
814 if (!pwm->override_inquire && (is_password || new_password))
816 free_result = 1;
817 rc = pwmd_password (data, keyword, &result, &len);
818 if (!rc)
819 rc = GPG_ERR_EOF;
821 else
822 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
823 &len);
825 cancel:
826 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
828 #ifndef LIBASSUAN_2_1_0
829 gpg_error_t trc = rc;
831 /* Cancel this inquire. */
832 rc = assuan_send_data (pwm->ctx, NULL, 1);
833 if (!rc)
835 char *line;
836 size_t len;
838 /* There is a bug (or feature?) in assuan_send_data() that
839 * when cancelling an inquire the next read from the server is
840 * not done until the next command making the next command
841 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
843 rc = assuan_read_line (pwm->ctx, &line, &len);
845 /* Restore the original error. This differs from the error
846 * returned from the pwmd command (GPG_ERR_CANCELED). This
847 * error is returned to the calling function.
849 if (!rc)
850 rc = trc;
852 #endif
853 break;
856 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
858 if (len <= 0 && !result)
860 rc = 0;
861 break;
863 else if ((len <= 0 && result) || (len && !result))
865 rc = gpg_error (GPG_ERR_INV_ARG);
866 break;
869 if (pwm->inquire_maxlen
870 && pwm->inquire_sent + len > pwm->inquire_maxlen)
872 rc = gpg_error (GPG_ERR_TOO_LARGE);
873 if (!free_result)
874 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
875 &result, &len);
876 goto cancel;
879 arc = assuan_send_data (pwm->ctx, result, len);
880 if (gpg_err_code (rc) == GPG_ERR_EOF)
882 rc = arc;
883 break;
886 rc = arc;
888 else if (rc)
889 break;
891 if (!rc)
893 pwm->inquire_sent += len;
895 if (pwm->status_func)
897 char buf[ASSUAN_LINELENGTH];
899 snprintf (buf, sizeof (buf), "XFER %lu %lu", pwm->inquire_sent,
900 pwm->inquire_total);
901 rc = pwm->status_func (pwm->status_data, buf);
902 if (rc)
903 continue;
908 if (free_result)
909 pwmd_free (result);
911 return rc;
914 static gpg_error_t
915 parse_assuan_line (pwm_t * pwm)
917 gpg_error_t rc;
918 char *line;
919 size_t len;
921 rc = assuan_read_line (pwm->ctx, &line, &len);
922 if (!rc)
924 if (line[0] == 'O' && line[1] == 'K' &&
925 (line[2] == 0 || line[2] == ' '))
928 else if (line[0] == '#')
931 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
933 if (pwm->status_func)
935 rc = pwm->status_func (pwm->status_data,
936 line[1] == 0 ? line + 1 : line + 2);
939 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
940 (line[3] == 0 || line[3] == ' '))
942 line += 4;
943 rc = strtol (line, NULL, 10);
947 return rc;
950 static void
951 reset_handle_state (pwm_t * pwm, int done)
953 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
954 if (pwm->tcp)
955 pwm->tcp->rc = 0;
957 if (done)
959 free_tcp (pwm->tcp);
960 pwm->tcp = NULL;
962 #endif
965 static void
966 reset_handle (pwm_t * h)
968 h->fd = -1;
969 #ifdef WITH_PINENTRY
970 if (h->pctx)
971 _pinentry_disconnect (h);
972 #endif
973 reset_handle_state (h, 0);
976 gpg_error_t
977 pwmd_disconnect (pwm_t * pwm)
979 if (!pwm)
980 return FINISH (GPG_ERR_INV_ARG);
982 if (pwm->fd == -1)
983 return FINISH (GPG_ERR_INV_STATE);
985 disconnect (pwm);
986 reset_handle (pwm);
987 return 0;
990 /* Note that this should only be called when not in a command. */
991 gpg_error_t
992 pwmd_process (pwm_t * pwm)
994 gpg_error_t rc = 0;
995 fd_set fds;
996 struct timeval tv = { 0, 0 };
997 int n;
999 if (!pwm)
1000 return FINISH (GPG_ERR_INV_ARG);
1001 else if (!pwm->ctx)
1002 return FINISH (GPG_ERR_INV_STATE);
1004 FD_ZERO (&fds);
1005 FD_SET (pwm->fd, &fds);
1006 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1008 if (n == -1)
1009 return FINISH (gpg_error_from_syserror ());
1011 if (n > 0)
1013 if (FD_ISSET (pwm->fd, &fds))
1014 rc = parse_assuan_line (pwm);
1017 while (!rc && assuan_pending_line (pwm->ctx))
1018 rc = parse_assuan_line (pwm);
1020 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1021 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1023 close (pwm->fd);
1024 pwm->fd = -1;
1026 #endif
1028 return FINISH (rc);
1031 static gpg_error_t
1032 status_cb (void *data, const char *line)
1034 pwm_t *pwm = data;
1036 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1037 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1039 if (pwm->status_func)
1040 return pwm->status_func (pwm->status_data, line);
1042 return 0;
1045 gpg_error_t
1046 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1047 char **result, size_t * len, const char *cmd)
1049 membuf_t data;
1050 gpg_error_t rc;
1052 if (!cmd || !*cmd)
1053 return FINISH (GPG_ERR_INV_ARG);
1055 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1056 return FINISH (GPG_ERR_LINE_TOO_LONG);
1058 data.len = 0;
1059 data.buf = NULL;
1060 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1061 #ifdef WITH_QUALITY
1062 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1063 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1064 #else
1065 inquire_cb, pwm,
1066 #endif
1067 status_cb, pwm);
1069 if (rc)
1071 if (data.buf)
1073 pwmd_free (data.buf);
1074 data.buf = NULL;
1077 else
1079 if (data.buf)
1081 inquire_realloc_cb (&data, "", 1);
1083 if (result)
1084 *result = (char *) data.buf;
1085 else
1086 pwmd_free (data.buf);
1088 if (len)
1089 *len = data.len;
1093 pwm->inquire_maxlen = 0;
1094 return rc;
1097 gpg_error_t
1098 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1099 pwmd_inquire_cb_t func, void *user, const char *cmd,
1100 va_list ap)
1102 char *buf;
1103 size_t len;
1104 va_list ap2;
1106 if (!pwm || !cmd)
1107 return FINISH (GPG_ERR_INV_ARG);
1108 if (!pwm->ctx)
1109 return FINISH (GPG_ERR_INV_STATE);
1112 * C99 allows the dst pointer to be null which will calculate the length
1113 * of the would-be result and return it.
1115 va_copy (ap2, ap);
1116 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1117 buf = (char *) pwmd_malloc (len);
1118 if (!buf)
1120 va_end (ap2);
1121 return FINISH (GPG_ERR_ENOMEM);
1124 len = vsnprintf (buf, len, cmd, ap2);
1125 va_end (ap2);
1127 if (buf[strlen (buf) - 1] == '\n')
1128 buf[strlen (buf) - 1] = 0;
1129 if (buf[strlen (buf) - 1] == '\r')
1130 buf[strlen (buf) - 1] = 0;
1132 pwm->inquire_func = func;
1133 pwm->inquire_data = user;
1134 pwm->inquire_sent = 0;
1135 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1136 pwmd_free (buf);
1137 return rc;
1140 gpg_error_t
1141 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1142 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1144 va_list ap;
1146 if (!pwm || !cmd)
1147 return FINISH (GPG_ERR_INV_ARG);
1148 if (!pwm->ctx)
1149 return FINISH (GPG_ERR_INV_STATE);
1151 if (result)
1152 *result = NULL;
1154 va_start (ap, cmd);
1155 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1156 va_end (ap);
1157 return rc;
1160 static gpg_error_t
1161 send_pinentry_options (pwm_t * pwm)
1163 gpg_error_t rc;
1165 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1166 "OPTION disable-pinentry=0");
1167 if (!rc && pwm->pinentry_tty)
1168 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1169 pwm->pinentry_tty);
1171 if (!rc && pwm->pinentry_term)
1172 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1173 pwm->pinentry_term);
1175 if (!rc && pwm->pinentry_display)
1176 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1177 pwm->pinentry_display);
1179 if (!rc && pwm->pinentry_desc)
1180 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1181 pwm->pinentry_desc);
1183 if (!rc && pwm->pinentry_lcctype)
1184 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1185 pwm->pinentry_lcctype);
1187 if (!rc && pwm->pinentry_lcmessages)
1188 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1189 pwm->pinentry_lcmessages);
1191 if (!rc && pwm->pinentry_timeout > 0)
1192 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1193 "OPTION pinentry-timeout=%i", pwm->pinentry_timeout);
1195 return rc;
1198 gpg_error_t
1199 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1201 if (!pwm || !result)
1202 return FINISH (GPG_ERR_INV_ARG);
1204 *result = PWMD_SOCKET_LOCAL;
1206 if (pwm->fd == -1)
1207 return FINISH (GPG_ERR_INV_STATE);
1209 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1210 #ifdef WITH_SSH
1211 if (pwm->tcp && pwm->tcp->ssh)
1212 *result = PWMD_SOCKET_SSH;
1213 #endif
1214 #ifdef WITH_GNUTLS
1215 if (pwm->tcp && pwm->tcp->tls)
1216 *result = PWMD_SOCKET_TLS;
1217 #endif
1218 #endif
1219 return 0;
1222 gpg_error_t
1223 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1224 void *data)
1226 gpg_error_t rc = 0;
1227 int no_pinentry;
1229 if (!pwm || !filename || !*filename)
1230 return FINISH (GPG_ERR_INV_ARG);
1232 if (!pwm->ctx)
1233 return FINISH (GPG_ERR_INV_STATE);
1235 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1236 no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1237 #else
1238 no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1239 #endif
1241 if (!no_pinentry)
1242 rc = send_pinentry_options (pwm);
1243 else
1244 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1245 "OPTION disable-pinentry");
1247 if (!rc)
1249 pwm->pinentry_try = 0;
1250 pwmd_free (pwm->filename);
1251 pwm->filename = pwmd_strdup (filename);
1255 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1256 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1257 filename);
1259 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1260 && no_pinentry && ++pwm->pinentry_try < pwm->pinentry_tries);
1262 pwm->pinentry_try = 0;
1264 if (rc)
1266 pwmd_free (pwm->filename);
1267 pwm->filename = NULL;
1271 return FINISH (rc);
1274 static gpg_error_t
1275 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1276 void *data, int save)
1278 gpg_error_t rc = 0;
1280 if (!pwm)
1281 return FINISH (GPG_ERR_INV_ARG);
1282 if (!pwm->ctx)
1283 return FINISH (GPG_ERR_INV_STATE);
1285 if (pwm->disable_pinentry || pwm->local_pinentry)
1286 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry");
1288 if (!rc)
1289 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1290 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
1292 return FINISH (rc);
1295 gpg_error_t
1296 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1298 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1301 gpg_error_t
1302 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1304 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1307 static gpg_error_t
1308 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1310 int n, *intp;
1311 size_t *sizetp;
1312 char *arg1, **charpp;
1313 gpg_error_t rc = 0;
1315 if (!pwm)
1316 return GPG_ERR_INV_ARG;
1318 switch (opt)
1320 case PWMD_OPTION_LOCK_ON_OPEN:
1321 if (get)
1323 intp = va_arg (ap, int *);
1324 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1325 break;
1328 n = va_arg (ap, int);
1330 if (n < 0 || n > 1)
1331 rc = GPG_ERR_INV_VALUE;
1333 if (n)
1334 pwm->opts |= OPT_LOCK_ON_OPEN;
1335 else
1336 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1338 break;
1339 case PWMD_OPTION_INQUIRE_TOTAL:
1340 if (get)
1342 sizetp = va_arg (ap, size_t *);
1343 *sizetp = pwm->inquire_total;
1344 break;
1347 pwm->inquire_total = va_arg (ap, size_t);
1348 break;
1349 case PWMD_OPTION_STATUS_CB:
1350 if (get)
1352 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1354 *cb = pwm->status_func;
1355 break;
1358 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1359 break;
1360 case PWMD_OPTION_STATUS_DATA:
1361 if (get)
1363 void **data = va_arg (ap, void **);
1365 *data = pwm->status_data;
1366 break;
1369 pwm->status_data = va_arg (ap, void *);
1370 break;
1371 case PWMD_OPTION_NO_PINENTRY:
1372 if (get)
1374 intp = va_arg (ap, int *);
1375 *intp = pwm->disable_pinentry;
1376 break;
1379 n = va_arg (ap, int);
1381 if (n < 0 || n > 1)
1382 rc = GPG_ERR_INV_VALUE;
1383 else
1384 pwm->disable_pinentry = n;
1386 break;
1387 case PWMD_OPTION_LOCAL_PINENTRY:
1388 if (get)
1390 intp = va_arg (ap, int *);
1391 *intp = pwm->local_pinentry;
1392 break;
1395 n = va_arg (ap, int);
1397 if (n < 0 || n > 1)
1398 rc = GPG_ERR_INV_VALUE;
1399 else
1400 pwm->local_pinentry = n;
1402 break;
1403 case PWMD_OPTION_PINENTRY_TIMEOUT:
1404 if (get)
1406 intp = va_arg (ap, int *);
1407 *intp = pwm->pinentry_timeout;
1408 break;
1411 n = va_arg (ap, int);
1413 if (n < 0)
1414 rc = GPG_ERR_INV_VALUE;
1415 else
1416 pwm->pinentry_timeout = n;
1418 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1419 if (!rc && pwm->fd != -1 && !pwm->tcp)
1420 #else
1421 if (!rc && pwm->fd != -1)
1422 #endif
1423 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1424 "OPTION pinentry-timeout=%i", pwm->pinentry_timeout);
1425 break;
1426 case PWMD_OPTION_PINENTRY_TRIES:
1427 if (get)
1429 intp = va_arg (ap, int *);
1430 *intp = pwm->pinentry_tries;
1431 break;
1434 n = va_arg (ap, int);
1435 pwm->pinentry_tries = n;
1436 break;
1437 case PWMD_OPTION_PINENTRY_PATH:
1438 if (get)
1440 charpp = va_arg (ap, char **);
1441 *charpp = pwm->pinentry_path;
1442 break;
1445 arg1 = va_arg (ap, char *);
1446 pwmd_free (pwm->pinentry_path);
1447 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1448 break;
1449 case PWMD_OPTION_PINENTRY_TTY:
1450 if (get)
1452 charpp = va_arg (ap, char **);
1453 *charpp = pwm->pinentry_tty;
1454 break;
1457 arg1 = va_arg (ap, char *);
1458 pwmd_free (pwm->pinentry_tty);
1459 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1460 break;
1461 case PWMD_OPTION_PINENTRY_DISPLAY:
1462 if (get)
1464 charpp = va_arg (ap, char **);
1465 *charpp = pwm->pinentry_display;
1466 break;
1469 arg1 = va_arg (ap, char *);
1470 pwmd_free (pwm->pinentry_display);
1471 pwm->pinentry_display = arg1 ? pwmd_strdup (arg1) : NULL;
1472 break;
1473 case PWMD_OPTION_PINENTRY_TERM:
1474 if (get)
1476 charpp = va_arg (ap, char **);
1477 *charpp = pwm->pinentry_term;
1478 break;
1481 arg1 = va_arg (ap, char *);
1482 pwmd_free (pwm->pinentry_term);
1483 pwm->pinentry_term = arg1 ? pwmd_strdup (arg1) : NULL;
1484 break;
1485 case PWMD_OPTION_PINENTRY_ERROR:
1486 if (get)
1488 charpp = va_arg (ap, char **);
1489 *charpp = pwm->pinentry_error;
1490 break;
1493 arg1 = va_arg (ap, char *);
1494 pwmd_free (pwm->pinentry_error);
1495 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1496 break;
1497 case PWMD_OPTION_PINENTRY_PROMPT:
1498 if (get)
1500 charpp = va_arg (ap, char **);
1501 *charpp = pwm->pinentry_prompt;
1502 break;
1505 arg1 = va_arg (ap, char *);
1506 pwmd_free (pwm->pinentry_prompt);
1507 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1508 break;
1509 case PWMD_OPTION_PINENTRY_DESC:
1510 if (get)
1512 charpp = va_arg (ap, char **);
1513 *charpp = pwm->pinentry_desc;
1514 break;
1517 arg1 = va_arg (ap, char *);
1518 pwmd_free (pwm->pinentry_desc);
1519 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1520 break;
1521 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1522 if (get)
1524 charpp = va_arg (ap, char **);
1525 *charpp = pwm->pinentry_lcctype;
1526 break;
1529 arg1 = va_arg (ap, char *);
1530 pwmd_free (pwm->pinentry_lcctype);
1531 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1532 break;
1533 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1534 if (get)
1536 charpp = va_arg (ap, char **);
1537 *charpp = pwm->pinentry_lcmessages;
1538 break;
1541 arg1 = va_arg (ap, char *);
1542 pwmd_free (pwm->pinentry_lcmessages);
1543 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1544 break;
1545 case PWMD_OPTION_KNOWNHOST_CB:
1546 if (get)
1548 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1550 *cb = pwm->kh_cb;
1551 break;
1554 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1555 break;
1556 case PWMD_OPTION_KNOWNHOST_DATA:
1557 if (get)
1559 void **data = va_arg (ap, void **);
1561 *data = pwm->kh_data;
1562 break;
1565 pwm->kh_data = va_arg (ap, void *);
1566 break;
1567 case PWMD_OPTION_SSH_AGENT:
1568 if (get)
1570 intp = va_arg (ap, int *);
1571 *intp = pwm->use_agent;
1572 break;
1575 pwm->use_agent = va_arg (ap, int);
1577 if (pwm->use_agent < 0 || pwm->use_agent > 1)
1579 pwm->use_agent = 0;
1580 rc = GPG_ERR_INV_VALUE;
1582 break;
1583 case PWMD_OPTION_TLS_VERIFY:
1584 if (get)
1586 intp = va_arg (ap, int *);
1587 *intp = pwm->tls_verify;
1588 break;
1591 pwm->tls_verify = va_arg (ap, int);
1593 if (pwm->tls_verify < 0 || pwm->tls_verify > 1)
1595 pwm->tls_verify = 0;
1596 rc = GPG_ERR_INV_VALUE;
1598 break;
1599 case PWMD_OPTION_SOCKET_TIMEOUT:
1600 if (get)
1602 intp = va_arg (ap, int *);
1603 *intp = pwm->socket_timeout;
1604 break;
1607 pwm->socket_timeout = va_arg (ap, int);
1608 if (pwm->socket_timeout < 0)
1610 pwm->socket_timeout = 0;
1611 rc = GPG_ERR_INV_VALUE;
1614 #ifdef WITH_SSH
1615 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1617 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1618 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1619 pwm->socket_timeout * 1000);
1621 #endif
1622 #ifdef WITH_GNUTLS
1623 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1624 pwm->tcp->tls->timeout = pwm->socket_timeout;
1625 #endif
1626 break;
1627 case PWMD_OPTION_OVERRIDE_INQUIRE:
1628 if (get)
1630 intp = va_arg (ap, int *);
1631 *intp = pwm->override_inquire;
1632 break;
1635 pwm->override_inquire = va_arg (ap, int);
1637 if (pwm->override_inquire < 0 || pwm->override_inquire > 1)
1639 pwm->override_inquire = 0;
1640 rc = GPG_ERR_INV_VALUE;
1642 break;
1643 default:
1644 rc = GPG_ERR_UNKNOWN_OPTION;
1645 break;
1648 return FINISH (rc);
1651 gpg_error_t
1652 pwmd_setopt (pwm_t * pwm, pwmd_option_t opt, ...)
1654 va_list ap;
1655 gpg_error_t rc = 0;
1657 va_start (ap, opt);
1658 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
1659 va_end (ap);
1660 return FINISH (rc);
1663 gpg_error_t
1664 pwmd_getopt (pwm_t *pwm, pwmd_option_t opt, ...)
1666 va_list ap;
1667 gpg_error_t rc = 0;
1669 va_start (ap, opt);
1670 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
1671 va_end (ap);
1672 return FINISH (rc);
1675 gpg_error_t
1676 pwmd_new (const char *name, pwm_t ** pwm)
1678 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
1679 gpg_error_t rc;
1681 if (!h)
1682 return FINISH (GPG_ERR_ENOMEM);
1684 if (name)
1686 h->name = pwmd_strdup (name);
1687 if (!h->name)
1689 pwmd_free (h);
1690 return FINISH (GPG_ERR_ENOMEM);
1694 reset_handle (h);
1695 h->pinentry_timeout = -30;
1696 h->pinentry_tries = 3;
1697 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1698 h->prot = PWMD_IP_ANY;
1699 #endif
1701 if (ttyname (STDOUT_FILENO))
1703 char buf[256];
1705 ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
1706 h->pinentry_tty = pwmd_strdup (buf);
1707 if (!h->pinentry_tty)
1709 rc = GPG_ERR_ENOMEM;
1710 goto fail;
1714 if (getenv ("TERM") && h->pinentry_tty)
1716 h->pinentry_term = pwmd_strdup (getenv ("TERM"));
1717 if (!h->pinentry_term)
1719 rc = GPG_ERR_ENOMEM;
1720 goto fail;
1724 if (getenv ("DISPLAY"))
1726 h->pinentry_display = pwmd_strdup (getenv ("DISPLAY"));
1727 if (!h->pinentry_display)
1729 rc = GPG_ERR_ENOMEM;
1730 goto fail;
1734 update_pinentry_settings (h);
1735 *pwm = h;
1736 return 0;
1738 fail:
1739 pwmd_close (h);
1740 return FINISH (rc);
1743 void
1744 pwmd_free (void *ptr)
1746 _xfree (ptr);
1749 void *
1750 pwmd_malloc (size_t size)
1752 return _xmalloc (size);
1755 void *
1756 pwmd_calloc (size_t nmemb, size_t size)
1758 return _xcalloc (nmemb, size);
1761 void *
1762 pwmd_realloc (void *ptr, size_t size)
1764 return _xrealloc (ptr, size);
1767 char *
1768 pwmd_strdup (const char *str)
1770 char *t;
1771 size_t len;
1772 register size_t c;
1774 len = strlen (str);
1775 t = _xmalloc ((len + 1) * sizeof (char));
1776 if (!t)
1777 return NULL;
1779 for (c = 0; c < len; c++)
1780 t[c] = str[c];
1782 t[c] = 0;
1783 return t;
1786 char *
1787 pwmd_strdup_printf (const char *fmt, ...)
1789 va_list ap, ap2;
1790 int len;
1791 char *buf;
1793 if (!fmt)
1794 return NULL;
1796 va_start (ap, fmt);
1797 va_copy (ap2, ap);
1798 len = vsnprintf (NULL, 0, fmt, ap);
1799 va_end (ap);
1800 buf = pwmd_malloc (++len);
1801 if (buf)
1802 vsnprintf (buf, len, fmt, ap2);
1804 va_end (ap2);
1805 return buf;
1808 gpg_error_t
1809 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
1810 size_t * len, pwmd_pinentry_t which)
1812 #ifndef WITH_PINENTRY
1813 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
1814 #else
1815 gpg_error_t rc = _pwmd_getpin (pwm, filename, result, len, which);
1817 return FINISH (rc);
1818 #endif
1821 const char *
1822 pwmd_version ()
1824 return LIBPWMD_VERSION_STR;
1827 unsigned int
1828 pwmd_features ()
1830 unsigned int n = 0;
1832 #ifdef WITH_PINENTRY
1833 n |= PWMD_FEATURE_PINENTRY;
1834 #endif
1835 #ifdef WITH_SSH
1836 n |= PWMD_FEATURE_SSH;
1837 #endif
1838 #ifdef WITH_QUALITY
1839 n |= PWMD_FEATURE_CRACK;
1840 #endif
1841 #ifdef WITH_GNUTLS
1842 n |= PWMD_FEATURE_GNUTLS;
1843 #endif
1844 return n;
1847 gpg_error_t
1848 pwmd_fd (pwm_t * pwm, int *fd)
1850 if (!pwm || !fd)
1851 return FINISH (GPG_ERR_INV_ARG);
1853 if (pwm->fd == -1)
1854 return FINISH (GPG_ERR_INV_STATE);
1856 *fd = pwm->fd;
1857 return 0;
1860 void
1861 pwmd_set_pointer (pwm_t *pwm, void *data)
1863 pwm->user_data = data;
1866 void *
1867 pwmd_get_pointer (pwm_t *pwm)
1869 return pwm->user_data;