From 6dac91441f212c7a63e7d53e8d25b98825bc3b30 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Mon, 23 Mar 2009 22:02:07 -0400 Subject: [PATCH] API changes: removed: pwmd_pending_line(), pwmd_assuan_ctx(), pwmd_free_result(), pwmd_get_result(), pwmd_finalize() added: pwmd_new(), pwmd_get_fd(), pwmd_free(), pwmd_malloc(), pwmd_calloc(), pwmd_realloc(), pwmd_strdup() pwmd_new() returns a handle for use with all functions. Functions that retured a pwm_t now return a gpg_error_t. The 'name' argument when set, will send "OPTION CLIENT NAME=name" to the server after the connection is made. A 'result' argument is now passed to pwmd_process() which replaces pwmd_finalize() and pwmd_get_result() (needs work). pwmd_password_fn no longer uses a pwm_t parameter; only user data. Fixed _getpwuid(). pwmd_command() will only set 'result' to NULL if 'result' is not NULL. Another fix which should have been included in commit 9a7055d. --- src/Makefile.am | 3 +- src/libpwmd.c | 538 ++++++++++++++++++++++++++++--------------------------- src/libpwmd.h.in | 74 ++++---- src/pwmc.c | 148 ++++++--------- src/types.h | 6 +- 5 files changed, 367 insertions(+), 402 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0e7f0fb4..63c55956 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,7 +32,7 @@ endif endif bin_PROGRAMS = pwmc -pwmc_SOURCES = pwmc.c mem.h +pwmc_SOURCES = pwmc.c pwmc_CFLAGS = -DLOCALEDIR=\"${prefix}/share/locale\" pwmc_LDADD= -lpwmd @@ -40,7 +40,6 @@ if MEM_DEBUG CPPFLAGS += -DMEM_DEBUG else libpwmd_la_SOURCES += mem.c -pwmc_SOURCES += mem.c if WITH_LIBPTH libpwmd_pth_la_SOURCES += mem.c endif diff --git a/src/libpwmd.c b/src/libpwmd.c index d2e5ae50..edb1cadb 100644 --- a/src/libpwmd.c +++ b/src/libpwmd.c @@ -75,37 +75,36 @@ static gpg_error_t pinentry_command(pwm_t *pwm, char **result, const char *cmd); static gpg_error_t global_error; #endif -static struct passwd *_getpwuid(char **outbuf) +static char *_getpwuid(struct passwd *pwd) { size_t size = sysconf(_SC_GETPW_R_SIZE_MAX); - struct passwd pwd, *result; + struct passwd *result; char *buf; int n; if (size == -1) size = 16384; - buf = xmalloc(size); + buf = pwmd_malloc(size); if (!buf) return NULL; - n = getpwuid_r(getuid(), &pwd, buf, size, &result); + n = getpwuid_r(getuid(), pwd, buf, size, &result); if (n) { - xfree(buf); + pwmd_free(buf); errno = n; return NULL; } if (!result) { - xfree(buf); + pwmd_free(buf); return NULL; } errno = n; - *outbuf = buf; - return result; + return buf; } const char *_pwmd_strerror(gpg_error_t e) @@ -173,25 +172,28 @@ gpg_error_t pwmd_init() bindtextdomain("libpwmd", LOCALEDIR); #endif gpg_err_init(); - assuan_set_malloc_hooks(xmalloc, xrealloc, xfree); + assuan_set_malloc_hooks(pwmd_malloc, pwmd_realloc, pwmd_free); assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT); initialized = 1; return 0; } -static pwm_t *_socket_connect_finalize(pwm_t *pwm, assuan_context_t ctx) +static gpg_error_t _socket_connect_finalize(pwm_t *pwm) { int active[2]; - int n = assuan_get_active_fds(ctx, 0, active, sizeof(active)); + int n = assuan_get_active_fds(pwm->ctx, 0, active, sizeof(active)); pwm->fd = n <= 0 ? -1 : dup(active[0]); - pwm->ctx = ctx; #ifdef WITH_PINENTRY pwm->pid = -1; pwm->pinentry_tries = 3; #endif - assuan_set_pointer(ctx, pwm); - return pwm; + assuan_set_pointer(pwm->ctx, pwm); + + if (pwm->name) + return pwmd_command(pwm, NULL, "OPTION CLIENT NAME=%s", pwm->name); + + return 0; } #ifdef WITH_TCP @@ -242,32 +244,32 @@ static void free_tcp_conn(pwmd_tcp_conn_t *conn) return; if (conn->username) { - xfree(conn->username); + pwmd_free(conn->username); conn->username = NULL; } if (conn->known_hosts) { - xfree(conn->known_hosts); + pwmd_free(conn->known_hosts); conn->known_hosts = NULL; } if (conn->identity) { - xfree(conn->identity); + pwmd_free(conn->identity); conn->identity = NULL; } if (conn->identity_pub) { - xfree(conn->identity_pub); + pwmd_free(conn->identity_pub); conn->identity_pub = NULL; } if (conn->host) { - xfree(conn->host); + pwmd_free(conn->host); conn->host = NULL; } if (conn->hostkey) { - xfree(conn->hostkey); + pwmd_free(conn->hostkey); conn->hostkey = NULL; } @@ -289,7 +291,7 @@ static void free_tcp_conn(pwmd_tcp_conn_t *conn) if (conn->session) _ssh_deinit(conn); else - xfree(conn); + pwmd_free(conn); } static void _ssh_deinit(pwmd_tcp_conn_t *conn) @@ -338,13 +340,13 @@ static gpg_error_t init_tcp_conn(pwmd_tcp_conn_t **dst, const char *host, return GPG_ERR_INV_ARG; } - conn = xcalloc(1, sizeof(pwmd_tcp_conn_t)); + conn = pwmd_calloc(1, sizeof(pwmd_tcp_conn_t)); if (!conn) return gpg_error_from_errno(ENOMEM); conn->port = port == -1 ? 22 : port; - conn->host = xstrdup(host); + conn->host = pwmd_strdup(host); if (!conn->host) { rc = gpg_error_from_errno(ENOMEM); @@ -352,30 +354,30 @@ static gpg_error_t init_tcp_conn(pwmd_tcp_conn_t **dst, const char *host, } if (!get) { - char *pwbuf; - struct passwd *pw = _getpwuid(&pwbuf); + struct passwd pw; + char *pwbuf = _getpwuid(&pw); - if (!pw) { + if (!pwbuf) { rc = gpg_error_from_errno(errno); goto fail; } - conn->username = xstrdup(user ? user : pw->pw_name); - xfree(pwbuf); + conn->username = pwmd_strdup(user ? user : pw.pw_name); + pwmd_free(pwbuf); if (!conn->username) { rc = gpg_error_from_errno(ENOMEM); goto fail; } - conn->identity = xstrdup(identity); + conn->identity = pwmd_strdup(identity); if (!conn->identity) { rc = gpg_error_from_errno(ENOMEM); goto fail; } - conn->identity_pub = xmalloc(strlen(conn->identity)+5); + conn->identity_pub = pwmd_malloc(strlen(conn->identity)+5); if (!conn->identity_pub) { rc = gpg_error_from_errno(ENOMEM); @@ -383,7 +385,7 @@ static gpg_error_t init_tcp_conn(pwmd_tcp_conn_t **dst, const char *host, } sprintf(conn->identity_pub, "%s.pub", conn->identity); - conn->known_hosts = xstrdup(hosts); + conn->known_hosts = pwmd_strdup(hosts); if (!conn->known_hosts) { rc = gpg_error_from_errno(ENOMEM); @@ -492,24 +494,18 @@ static void dns_resolve_cb(void *arg, int status, int timeouts, pwm->tcp_conn->rc = do_connect(pwm, he->h_addrtype, he->h_addr); } -static pwm_t *_do_pwmd_tcp_connect_async(const char *host, int port, - const char *identity, const char *user, const char *known_hosts, - gpg_error_t *rc, pwmd_async_cmd_t which) +static gpg_error_t _do_pwmd_tcp_connect_async(pwm_t *pwm, const char *host, + int port, const char *identity, const char *user, + const char *known_hosts, pwmd_async_cmd_t which) { pwmd_tcp_conn_t *conn; - pwm_t *pwm; + gpg_error_t rc; - *rc = init_tcp_conn(&conn, host, port, identity, user, known_hosts, + rc = init_tcp_conn(&conn, host, port, identity, user, known_hosts, which == ASYNC_CMD_HOSTKEY ? 1 : 0); - if (*rc) - return NULL; - - if ((pwm = (pwm_t *)xcalloc(1, sizeof(pwm_t))) == NULL) { - *rc = gpg_error_from_syserror(); - free_tcp_conn(conn); - return NULL; - } + if (rc) + return rc; conn->async = 1; pwm->tcp_conn = conn; @@ -523,35 +519,35 @@ static pwm_t *_do_pwmd_tcp_connect_async(const char *host, int port, ares_init(&pwm->tcp_conn->chan); ares_query(pwm->tcp_conn->chan, pwm->tcp_conn->host, ns_c_any, ns_t_any, dns_resolve_cb, pwm); - return pwm; + return 0; } -pwm_t *pwmd_tcp_connect_async(const char *host, int port, const char *identity, - const char *user, const char *known_hosts, gpg_error_t *rc) +gpg_error_t pwmd_tcp_connect_async(pwm_t *pwm, const char *host, int port, + const char *identity, const char *user, const char *known_hosts) { - return _do_pwmd_tcp_connect_async(host, port, identity, user, known_hosts, - rc, ASYNC_CMD_CONNECT); + return _do_pwmd_tcp_connect_async(pwm, host, port, identity, user, + known_hosts, ASYNC_CMD_CONNECT); } static void *_ssh_malloc(size_t size, void **data) { - return xmalloc(size); + return pwmd_malloc(size); } static void _ssh_free(void *ptr, void **data) { - xfree(ptr); + pwmd_free(ptr); } static void *_ssh_realloc(void *ptr, size_t size, void **data) { - return xrealloc(ptr, size); + return pwmd_realloc(ptr, size); } static char *to_hex(const char *str, size_t slen) { int i; - char *buf = xmalloc(slen*2+1); + char *buf = pwmd_malloc(slen*2+1); if (!buf) return NULL; @@ -574,7 +570,7 @@ static int verify_host_key(pwm_t *pwm) if (!fp) return 1; - buf = xmalloc(LINE_MAX); + buf = pwmd_malloc(LINE_MAX); if (!buf) goto fail; @@ -592,13 +588,13 @@ static int verify_host_key(pwm_t *pwm) fail: if (buf) - xfree(buf); + pwmd_free(buf); fclose(fp); return 1; done: - xfree(buf); + pwmd_free(buf); fclose(fp); return 0; } @@ -634,85 +630,80 @@ static gpg_error_t authenticate_ssh(pwm_t *pwm) return 0; } -static pwm_t *setup_tcp_session(pwm_t *pwm, gpg_error_t *rc) +static gpg_error_t setup_tcp_session(pwm_t *pwm) { assuan_context_t ctx; struct assuan_io_hooks io_hooks = {read_hook, write_hook}; + gpg_error_t rc; pwm->tcp_conn->session = libssh2_session_init_ex(_ssh_malloc, _ssh_free, _ssh_realloc, NULL); if (!pwm->tcp_conn->session) { - *rc = gpg_error_from_errno(ENOMEM); + rc = gpg_error_from_errno(ENOMEM); goto fail; } if (libssh2_session_startup(pwm->tcp_conn->session, pwm->tcp_conn->fd)) { - *rc = GPG_ERR_ASSUAN_SERVER_FAULT; + rc = GPG_ERR_ASSUAN_SERVER_FAULT; goto fail; } - *rc = authenticate_ssh(pwm); + rc = authenticate_ssh(pwm); - if (*rc) + if (rc) goto fail; /* pwmd_get_hostkey(). */ if (pwm->tcp_conn->get_only) { - pwm->result = xstrdup(pwm->tcp_conn->hostkey); + pwm->result = pwmd_strdup(pwm->tcp_conn->hostkey); if (!pwm->result) { - *rc = gpg_error_from_errno(ENOMEM); + rc = gpg_error_from_errno(ENOMEM); goto fail; } - return pwm; + return 0; } pwm->tcp_conn->channel = libssh2_channel_open_session(pwm->tcp_conn->session); if (!pwm->tcp_conn->channel) { - *rc = GPG_ERR_ASSUAN_SERVER_FAULT; + rc = GPG_ERR_ASSUAN_SERVER_FAULT; goto fail; } if (libssh2_channel_shell(pwm->tcp_conn->channel)) { - *rc = GPG_ERR_ASSUAN_SERVER_FAULT; + rc = GPG_ERR_ASSUAN_SERVER_FAULT; goto fail; } assuan_set_io_hooks(&io_hooks); - *rc = assuan_socket_connect_fd(&ctx, pwm->tcp_conn->fd, 0, pwm); + rc = assuan_socket_connect_fd(&ctx, pwm->tcp_conn->fd, 0, pwm); - if (*rc) + if (rc) goto fail; assuan_set_finish_handler(ctx, _ssh_assuan_deinit); - return _socket_connect_finalize(pwm, ctx); + pwm->ctx = ctx; + return _socket_connect_finalize(pwm); fail: - if (!pwm->tcp_conn->async) - pwmd_close(pwm); - - return NULL; + free_tcp_conn(pwm->tcp_conn); + pwm->tcp_conn = NULL; + return rc; } -static pwm_t *_do_pwmd_tcp_connect(const char *host, int port, - const char *identity, const char *user, const char *known_hosts, - gpg_error_t *rc, int get) +static gpg_error_t _do_pwmd_tcp_connect(pwm_t *pwm, const char *host, int port, + const char *identity, const char *user, const char *known_hosts, int get) { - pwm_t *pwm = NULL; pwmd_tcp_conn_t *conn; + gpg_error_t rc; - *rc = init_tcp_conn(&conn, host, port, identity, user, known_hosts, get); - - if (*rc) - return NULL; + rc = init_tcp_conn(&conn, host, port, identity, user, known_hosts, get); - if ((pwm = (pwm_t *)xcalloc(1, sizeof(pwm_t))) == NULL) { - *rc = gpg_error_from_errno(ENOMEM); - goto fail; - } + if (rc) + return rc; pwm->tcp_conn = conn; pwm->tcp_conn->get_only = get; @@ -723,7 +714,7 @@ static pwm_t *_do_pwmd_tcp_connect(const char *host, int port, /* dns_resolve_cb() may have already been called. */ if (pwm->tcp_conn->rc) { - *rc = pwm->tcp_conn->rc; + rc = pwm->tcp_conn->rc; goto fail; } @@ -747,11 +738,11 @@ static pwm_t *_do_pwmd_tcp_connect(const char *host, int port, #endif if (n == -1) { - *rc = gpg_error_from_syserror(); + rc = gpg_error_from_syserror(); goto fail; } else if (n == 0) { - *rc = GPG_ERR_TIMEOUT; + rc = GPG_ERR_TIMEOUT; goto fail; } @@ -762,94 +753,83 @@ static pwm_t *_do_pwmd_tcp_connect(const char *host, int port, } while (pwm->cmd == ASYNC_CMD_DNS); if (pwm->tcp_conn->rc) { - *rc = pwm->tcp_conn->rc; + rc = pwm->tcp_conn->rc; goto fail; } - return setup_tcp_session(pwm, rc); + return setup_tcp_session(pwm); fail: - pwmd_close(pwm); - return NULL; + return rc; } -pwm_t *pwmd_tcp_connect(const char *host, int port, const char *identity, - const char *user, const char *known_hosts, gpg_error_t *rc) +gpg_error_t pwmd_tcp_connect(pwm_t *pwm, const char *host, int port, + const char *identity, const char *user, const char *known_hosts) { - return _do_pwmd_tcp_connect(host, port, identity, user, known_hosts, rc, 0); + return _do_pwmd_tcp_connect(pwm, host, port, identity, user, known_hosts, 0); } -/* Must free the result with pwmd_free_result(). */ -char *pwmd_get_hostkey(const char *host, int port, gpg_error_t *rc) +/* Must free the result with pwmd_free(). */ +gpg_error_t pwmd_get_hostkey(const char *host, int port, char **result) { char *hostkey; - pwm_t *pwm; - - pwm = _do_pwmd_tcp_connect(host, port, NULL, NULL, NULL, rc, 1); + pwm_t *pwm = pwmd_new(NULL); + gpg_error_t rc; if (!pwm) - return NULL; + return gpg_error_from_errno(ENOMEM); - hostkey = xstrdup(pwm->tcp_conn->hostkey); + rc = _do_pwmd_tcp_connect(pwm, host, port, NULL, NULL, NULL, 1); + + if (rc) { + pwmd_close(pwm); + return rc; + } + + hostkey = pwmd_strdup(pwm->tcp_conn->hostkey); if (!hostkey) - *rc = gpg_error_from_errno(ENOMEM); + rc = gpg_error_from_errno(ENOMEM); pwmd_close(pwm); - return hostkey; + *result = hostkey; + return rc; } -pwm_t *pwmd_get_hostkey_async(const char *host, int port, gpg_error_t *rc) +gpg_error_t pwmd_get_hostkey_async(pwm_t *pwm, const char *host, int port) { - return _do_pwmd_tcp_connect_async(host, port, NULL, NULL, NULL, rc, + return _do_pwmd_tcp_connect_async(pwm, host, port, NULL, NULL, NULL, ASYNC_CMD_HOSTKEY); } #endif -pwm_t *pwmd_connect(const char *path, gpg_error_t *rc) +gpg_error_t pwmd_connect(pwm_t *pwm, const char *path) { - pwm_t *pwm = NULL; char *socketpath = NULL; assuan_context_t ctx; - char *pwbuf; - struct passwd *pw = _getpwuid(&pwbuf); + struct passwd pw; + char *pwbuf = _getpwuid(&pw); + gpg_error_t rc; - if (!pw) { - *rc = gpg_error_from_errno(errno); - return NULL; - } + if (!pwbuf) + return gpg_error_from_errno(errno); if (!path) { - socketpath = (char *)xmalloc(strlen(pw->pw_dir) + strlen("/.pwmd/socket") + 1); - sprintf(socketpath, "%s/.pwmd/socket", pw->pw_dir); + socketpath = (char *)pwmd_malloc(strlen(pw.pw_dir) + strlen("/.pwmd/socket") + 1); + sprintf(socketpath, "%s/.pwmd/socket", pw.pw_dir); } else - socketpath = xstrdup(path); + socketpath = pwmd_strdup(path); - xfree(pwbuf); - *rc = assuan_socket_connect_ext(&ctx, socketpath, -1, 0); - xfree(socketpath); - - if (*rc) - return NULL; + pwmd_free(pwbuf); + rc = assuan_socket_connect_ext(&ctx, socketpath, -1, 0); + pwmd_free(socketpath); - if ((pwm = (pwm_t *)xcalloc(1, sizeof(pwm_t))) == NULL) { - *rc = gpg_error_from_syserror(); - return NULL; - } - - return _socket_connect_finalize(pwm, ctx); -} - -gpg_error_t pwmd_pending_line(pwm_t *pwm, char **line, size_t *len) -{ - if (!pwm) - return GPG_ERR_INV_ARG; - - if (assuan_pending_line(pwm->ctx)) - return assuan_read_line(pwm->ctx, line, len); + if (rc) + return rc; - return GPG_ERR_NO_DATA; + pwm->ctx = ctx; + return _socket_connect_finalize(pwm); } void pwmd_close(pwm_t *pwm) @@ -861,44 +841,44 @@ void pwmd_close(pwm_t *pwm) assuan_disconnect(pwm->ctx); if (pwm->password) - xfree(pwm->password); + pwmd_free(pwm->password); if (pwm->title) - xfree(pwm->title); + pwmd_free(pwm->title); if (pwm->desc) - xfree(pwm->desc); + pwmd_free(pwm->desc); if (pwm->prompt) - xfree(pwm->prompt); + pwmd_free(pwm->prompt); if (pwm->pinentry_tty) - xfree(pwm->pinentry_tty); + pwmd_free(pwm->pinentry_tty); if (pwm->pinentry_display) - xfree(pwm->pinentry_display); + pwmd_free(pwm->pinentry_display); if (pwm->pinentry_term) - xfree(pwm->pinentry_term); + pwmd_free(pwm->pinentry_term); if (pwm->lcctype) - xfree(pwm->lcctype); + pwmd_free(pwm->lcctype); if (pwm->lcmessages) - xfree(pwm->lcmessages); + pwmd_free(pwm->lcmessages); if (pwm->filename) - xfree(pwm->filename); + pwmd_free(pwm->filename); - if (pwm->result) - xfree(pwm->result); + if (pwm->name) + pwmd_free(pwm->name); #ifdef WITH_TCP if (pwm->tcp_conn) free_tcp_conn(pwm->tcp_conn); #endif - xfree(pwm); + pwmd_free(pwm); } static int mem_realloc_cb(void *data, const void *buffer, size_t len) @@ -909,7 +889,7 @@ static int mem_realloc_cb(void *data, const void *buffer, size_t len) if (!buffer) return 0; - if ((p = xrealloc(mem->buf, mem->len + len)) == NULL) + if ((p = pwmd_realloc(mem->buf, mem->len + len)) == NULL) return 1; mem->buf = p; @@ -918,11 +898,6 @@ static int mem_realloc_cb(void *data, const void *buffer, size_t len) return 0; } -void pwmd_free_result(void *data) -{ - xfree(data); -} - static int _inquire_cb(void *data, const char *keyword) { pwm_t *pwm = (pwm_t *)data; @@ -983,11 +958,6 @@ gpg_error_t pwmd_finalize(pwm_t *pwm) pwm->state = ASYNC_INIT; pwm->cmd = ASYNC_CMD_NONE; - if (pwm->result) - xfree(pwm->result); - - pwm->result = NULL; - #ifdef WITH_TCP if (pwm->cmd == ASYNC_CMD_CONNECT || pwm->cmd == ASYNC_CMD_DNS) { gpg_error_t rc = pwm->tcp_conn->rc; @@ -1021,7 +991,7 @@ static gpg_error_t do_nb_command(pwm_t *pwm, const char *cmd, const char *arg) if (pwm->state != ASYNC_INIT) return GPG_ERR_INV_STATE; - buf = (char *)xmalloc(len); + buf = (char *)pwmd_malloc(len); if (!buf) { rc = gpg_error_from_errno(ENOMEM); @@ -1030,7 +1000,7 @@ static gpg_error_t do_nb_command(pwm_t *pwm, const char *cmd, const char *arg) snprintf(buf, len, "%s %s", cmd, arg ? arg : ""); rc = assuan_write_line(pwm->ctx, buf); - xfree(buf); + pwmd_free(buf); if (!rc) pwm->state = ASYNC_PROCESS; @@ -1047,9 +1017,9 @@ gpg_error_t pwmd_open_async(pwm_t *pwm, const char *filename) /* For pinentry retries. */ if (!pwm->is_open_cmd) { if (pwm->filename) - xfree(pwm->filename); + pwmd_free(pwm->filename); - pwm->filename = xstrdup(filename); + pwm->filename = pwmd_strdup(filename); } pwm->is_open_cmd = 1; @@ -1098,24 +1068,7 @@ static gpg_error_t parse_assuan_line(pwm_t *pwm) return rc; } -gpg_error_t pwmd_get_result(pwm_t *pwm, const char **result) -{ - if (!pwm || !result) - return GPG_ERR_INV_ARG; - - if (pwm->state != ASYNC_DONE) - return GPG_ERR_INV_STATE; - - if (!pwm->result) - return GPG_ERR_NO_DATA; - - *result = pwm->result; - return 0; -} - -static gpg_error_t assuan_command(pwm_t *pwm, assuan_context_t ctx, - char **result, const char *cmd); -pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) +pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc, const char **result) { fd_set fds; int n; @@ -1128,6 +1081,18 @@ pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) return ASYNC_DONE; } + if (pwm->state == ASYNC_DONE) + return pwm->state; + + /* When not in a command, this will let libassuan process status messages + * by calling PWMD_OPTION_STATUS_FUNC. The client can poll the file + * descriptor returned by pwmd_get_fd() to determine when this should be + * called. */ + if (pwm->cmd == ASYNC_CMD_NONE) { + *rc = assuan_command(pwm, pwm->ctx, NULL, "NOP"); + return pwm->state; + } + #ifdef WITH_TCP if (pwm->cmd == ASYNC_CMD_DNS) { fd_set rfds, wfds; @@ -1135,6 +1100,7 @@ pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) if (pwm->tcp_conn->rc) { *rc = pwm->tcp_conn->rc; close(pwm->tcp_conn->fd); + pwm->tcp_conn->fd = -1; pwm->state = ASYNC_DONE; return pwm->state; } @@ -1176,14 +1142,17 @@ pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) else if (n == -1) { *rc = gpg_error_from_syserror(); close(pwm->tcp_conn->fd); + pwm->tcp_conn->fd = -1; pwm->state = ASYNC_DONE; return pwm->state; } ret = getsockopt(pwm->tcp_conn->fd, SOL_SOCKET, SO_ERROR, &n, &len); + if (ret || n) { *rc = ret ? gpg_error_from_syserror() : gpg_error_from_errno(n); close(pwm->tcp_conn->fd); + pwm->tcp_conn->fd = -1; pwm->state = ASYNC_DONE; return pwm->state; } @@ -1191,12 +1160,13 @@ pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) else if (pwm->tcp_conn->rc) { *rc = pwm->tcp_conn->rc; close(pwm->tcp_conn->fd); + pwm->tcp_conn->fd = -1; pwm->state = ASYNC_DONE; return pwm->state; } fcntl(pwm->tcp_conn->fd, F_SETFL, 0); - setup_tcp_session(pwm, rc); + *rc = setup_tcp_session(pwm); pwm->state = ASYNC_DONE; return pwm->state; } @@ -1207,16 +1177,6 @@ pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) return ASYNC_DONE; } - if (pwm->state == ASYNC_DONE) - return pwm->state; - - /* When not in a command, this will let libassuan process status messages - * by calling PWMD_OPTION_STATUS_FUNC. */ - if (pwm->cmd == ASYNC_CMD_NONE) { - *rc = assuan_command(pwm, pwm->ctx, NULL, "NOP"); - return pwm->state; - } - /* This is for the non-blocking OPEN and SAVE commands. */ FD_ZERO(&fds); FD_SET(pwm->fd, &fds); @@ -1258,7 +1218,7 @@ static gpg_error_t assuan_command(pwm_t *pwm, assuan_context_t ctx, if (rc) { if (data.buf) { - xfree(data.buf); + pwmd_free(data.buf); data.buf = NULL; } } @@ -1267,7 +1227,7 @@ static gpg_error_t assuan_command(pwm_t *pwm, assuan_context_t ctx, mem_realloc_cb(&data, "", 1); if (!result) { - xfree(data.buf); + pwmd_free(data.buf); rc = GPG_ERR_INV_ARG; } else @@ -1324,45 +1284,45 @@ static gpg_error_t set_pinentry_strings(pwm_t *pwm, int which) gpg_error_t error; if (!pwm->title) - pwm->title = xstrdup(N_("LibPWMD")); + pwm->title = pwmd_strdup(N_("LibPWMD")); if (!pwm->prompt) - pwm->prompt = xstrdup(N_("Passphrase:")); + pwm->prompt = pwmd_strdup(N_("Passphrase:")); if (!pwm->desc && !which) - pwm->desc = xstrdup(N_("Enter a passphrase.")); + pwm->desc = pwmd_strdup(N_("Enter a passphrase.")); if (which == 1) { snprintf(tmp, sizeof(tmp), "SETERROR %s", N_("Invalid passphrase, please try again.")); - buf = xstrdup(tmp); + buf = pwmd_strdup(tmp); } else if (which == 2) { snprintf(tmp, sizeof(tmp), "SETERROR %s", N_("Please type the passphrase again for confirmation.")); - buf = xstrdup(tmp); + buf = pwmd_strdup(tmp); } else { - buf = (char *)xmalloc(strlen("SETERROR ") + strlen(pwm->desc) + 1); + buf = (char *)pwmd_malloc(strlen("SETERROR ") + strlen(pwm->desc) + 1); sprintf(buf, "SETERROR %s", pwm->desc); } error = pinentry_command(pwm, NULL, buf); - xfree(buf); + pwmd_free(buf); if (error) return error; - buf = (char *)xmalloc(strlen("SETPROMPT ") + strlen(pwm->prompt) + 1); + buf = (char *)pwmd_malloc(strlen("SETPROMPT ") + strlen(pwm->prompt) + 1); sprintf(buf, "SETPROMPT %s", pwm->prompt); error = pinentry_command(pwm, NULL, buf); - xfree(buf); + pwmd_free(buf); if (error) return error; - buf = (char *)xmalloc(strlen("SETDESC ") + strlen(pwm->title) + 1); + buf = (char *)pwmd_malloc(strlen("SETDESC ") + strlen(pwm->title) + 1); sprintf(buf, "SETDESC %s", pwm->title); error = pinentry_command(pwm, NULL, buf); - xfree(buf); + pwmd_free(buf); return error; } @@ -1371,14 +1331,14 @@ static void update_pinentry_settings(pwm_t *pwm) FILE *fp; char buf[LINE_MAX]; char *p; - char *pwbuf; - struct passwd *pw = _getpwuid(&pwbuf); + struct passwd pw; + char *pwbuf = _getpwuid(&pw); - if (!pw) + if (!pwbuf) return; - snprintf(buf, sizeof(buf), "%s/.pwmd/pinentry.conf", pw->pw_dir); - xfree(pwbuf); + snprintf(buf, sizeof(buf), "%s/.pwmd/pinentry.conf", pw.pw_dir); + pwmd_free(pwbuf); if ((fp = fopen(buf, "r")) == NULL) return; @@ -1390,20 +1350,20 @@ static void update_pinentry_settings(pwm_t *pwm) continue; if (strcasecmp(name, "TTYNAME") == 0) { - xfree(pwm->pinentry_tty); - pwm->pinentry_tty = xstrdup(val); + pwmd_free(pwm->pinentry_tty); + pwm->pinentry_tty = pwmd_strdup(val); } else if (strcasecmp(name, "TTYTYPE") == 0) { - xfree(pwm->pinentry_term); - pwm->pinentry_term = xstrdup(val); + pwmd_free(pwm->pinentry_term); + pwm->pinentry_term = pwmd_strdup(val); } else if (strcasecmp(name, "DISPLAY") == 0) { - xfree(pwm->pinentry_display); - pwm->pinentry_display = xstrdup(val); + pwmd_free(pwm->pinentry_display); + pwm->pinentry_display = pwmd_strdup(val); } else if (strcasecmp(name, "PATH") == 0) { - xfree(pwm->pinentry_path); - pwm->pinentry_path = xstrdup(val); + pwmd_free(pwm->pinentry_path); + pwm->pinentry_path = pwmd_strdup(val); } } @@ -1428,7 +1388,7 @@ static gpg_error_t launch_pinentry(pwm_t *pwm) have_display = 1; else { if (!pwm->pinentry_tty) { - ttybuf = xmalloc(255); + ttybuf = pwmd_malloc(255); if (!ttybuf) return gpg_error_from_errno(ENOMEM); @@ -1436,7 +1396,7 @@ static gpg_error_t launch_pinentry(pwm_t *pwm) rc = ttyname_r(STDOUT_FILENO, ttybuf, 255); if (rc) { - xfree(ttybuf); + pwmd_free(ttybuf); return gpg_error_from_errno(rc); } @@ -1474,7 +1434,7 @@ static gpg_error_t launch_pinentry(pwm_t *pwm) rc = assuan_pipe_connect(&ctx, pwm->pinentry_path ? pwm->pinentry_path : PINENTRY_PATH, argv, child_list); if (ttybuf) - xfree(ttybuf); + pwmd_free(ttybuf); if (rc) return rc; @@ -1538,7 +1498,7 @@ static char *percent_escape(const char *atext) { const unsigned char *s; int len = strlen(atext) * 3 + 1; - char *buf = (char *)xmalloc(len), *p = buf; + char *buf = (char *)pwmd_malloc(len), *p = buf; if (!buf) return NULL; @@ -1579,10 +1539,10 @@ gpg_error_t pwmd_command_ap(pwm_t *pwm, char **result, const char *cmd, * of the would-be result and return it. */ len = vsnprintf(NULL, 0, cmd, ap)+1; - buf = (char *)xmalloc(len); + buf = (char *)pwmd_malloc(len); len = vsnprintf(buf, len, cmd, ap); error = send_command(pwm, result, buf); - xfree(buf); + pwmd_free(buf); return error; } @@ -1598,7 +1558,9 @@ gpg_error_t pwmd_command(pwm_t *pwm, char **result, const char *cmd, ...) if (!pwm || !cmd) return GPG_ERR_INV_ARG; - *result = NULL; + if (result) + *result = NULL; + va_start(ap, cmd); error = pwmd_command_ap(pwm, result, cmd, ap); va_end(ap); @@ -1688,9 +1650,9 @@ gpg_error_t pwmd_open_nb_finalize(pwm_t *pwm, pwmd_nb_status_t *pw) } if (pwm->filename) - xfree(pwm->filename); + pwmd_free(pwm->filename); - pwm->filename = xstrdup(pw->filename); + pwm->filename = pwmd_strdup(pw->filename); memset(pw, 0, sizeof(pwmd_nb_status_t)); return 0; @@ -1710,7 +1672,7 @@ static gpg_error_t do_open_command(pwm_t *pwm, const char *filename, char *passw memset(buf, 0, sizeof(buf)); if (error && result) - xfree(result); + pwmd_free(result); return error; } @@ -1744,7 +1706,7 @@ static int do_pwmd_open(pwm_t *pwm, gpg_error_t *error, const char *filename, return nb ? -1 : 1; snprintf(path, sizeof(path), "%s/%s", result, filename); - pwmd_free_result(result); + pwmd_free(result); if (access(path, R_OK) == -1) { if (errno == ENOENT) @@ -1755,7 +1717,7 @@ static int do_pwmd_open(pwm_t *pwm, gpg_error_t *error, const char *filename, if (*error == EPWMD_CACHE_NOT_FOUND) { if (pwm->passfunc) { - password = pwm->passfunc(pwm, pwm->passdata); + password = (char *)pwm->passfunc(pwm->passdata); goto gotpassword; } @@ -1881,7 +1843,7 @@ gotpassword: * be needed later (pwmd_save()) depending on the pwmd file cache settings. */ if (!pwm->passfunc && password && password != pwm->password) - xfree(password); + pwmd_free(password); #ifdef WITH_PINENTRY if (*error == EPWMD_BADKEY) { @@ -1904,9 +1866,9 @@ gotpassword: if (!*error) { if (pwm->filename) - xfree(pwm->filename); + pwmd_free(pwm->filename); - pwm->filename = xstrdup(filename); + pwm->filename = pwmd_strdup(filename); } /* @@ -1953,7 +1915,7 @@ again: pinentry_disconnect(pwm); if (*password) - xfree(*password); + pwmd_free(*password); return error; } @@ -1964,14 +1926,14 @@ again: } if (strcmp(*password, result)) { - xfree(*password); - xfree(result); + pwmd_free(*password); + pwmd_free(result); pinentry_disconnect(pwm); error = EPWMD_BADKEY; return error; } - xfree(result); + pwmd_free(result); pinentry_disconnect(pwm); return 0; } @@ -1988,7 +1950,7 @@ static gpg_error_t do_save_command(pwm_t *pwm, char *password) memset(&buf, 0, sizeof(buf)); if (error && result) - xfree(result); + pwmd_free(result); return error; } @@ -2025,7 +1987,7 @@ static int do_pwmd_save(pwm_t *pwm, gpg_error_t *error, int nb) if (*error == EPWMD_CACHE_NOT_FOUND) { if (pwm->passfunc) - password = (*pwm->passfunc)(pwm, pwm->passdata); + password = (char *)(*pwm->passfunc)(pwm->passdata); #ifdef WITH_PINENTRY else if (pwm->use_pinentry) { if (nb) { @@ -2113,7 +2075,7 @@ static int do_pwmd_save(pwm_t *pwm, gpg_error_t *error, int nb) *error = do_save_command(pwm, password); if (!pwm->passfunc && password && password != pwm->password) - xfree(password); + pwmd_free(password); if (nb) return *error ? -1 : -2; @@ -2169,9 +2131,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) arg1 = va_arg(ap, char *); if (pwm->password) - xfree(pwm->password); + pwmd_free(pwm->password); - pwm->password = xstrdup(arg1); + pwm->password = pwmd_strdup(arg1); break; case PWMD_OPTION_PINENTRY: n = va_arg(ap, int); @@ -2214,9 +2176,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_PATH: if (pwm->pinentry_path) - xfree(pwm->pinentry_path); + pwmd_free(pwm->pinentry_path); - pwm->pinentry_path = xstrdup(va_arg(ap, char *)); + pwm->pinentry_path = pwmd_strdup(va_arg(ap, char *)); if (!pwm->use_pinentry) error = pwmd_command(pwm, &result, "OPTION PATH=%s", @@ -2224,9 +2186,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_TTY: if (pwm->pinentry_tty) - xfree(pwm->pinentry_tty); + pwmd_free(pwm->pinentry_tty); - pwm->pinentry_tty = xstrdup(va_arg(ap, char *)); + pwm->pinentry_tty = pwmd_strdup(va_arg(ap, char *)); if (!pwm->use_pinentry) error = pwmd_command(pwm, &result, "OPTION TTY=%s", @@ -2234,9 +2196,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_DISPLAY: if (pwm->pinentry_display) - xfree(pwm->pinentry_display); + pwmd_free(pwm->pinentry_display); - pwm->pinentry_display = xstrdup(va_arg(ap, char *)); + pwm->pinentry_display = pwmd_strdup(va_arg(ap, char *)); if (!pwm->use_pinentry) error = pwmd_command(pwm, &result, "OPTION DISPLAY=%s", @@ -2244,9 +2206,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_TERM: if (pwm->pinentry_term) - xfree(pwm->pinentry_term); + pwmd_free(pwm->pinentry_term); - pwm->pinentry_term = xstrdup(va_arg(ap, char *)); + pwm->pinentry_term = pwmd_strdup(va_arg(ap, char *)); if (!pwm->use_pinentry) error = pwmd_command(pwm, &result, "OPTION TTYTYPE=%s", @@ -2254,7 +2216,7 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_TITLE: if (pwm->title) - xfree(pwm->title); + pwmd_free(pwm->title); pwm->title = percent_escape(va_arg(ap, char *)); @@ -2264,7 +2226,7 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_PROMPT: if (pwm->prompt) - xfree(pwm->prompt); + pwmd_free(pwm->prompt); pwm->prompt = percent_escape(va_arg(ap, char *)); @@ -2274,7 +2236,7 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_DESC: if (pwm->desc) - xfree(pwm->desc); + pwmd_free(pwm->desc); pwm->desc = percent_escape(va_arg(ap, char *)); @@ -2284,9 +2246,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_LC_CTYPE: if (pwm->lcctype) - xfree(pwm->lcctype); + pwmd_free(pwm->lcctype); - pwm->lcctype = xstrdup(va_arg(ap, char *)); + pwm->lcctype = pwmd_strdup(va_arg(ap, char *)); if (!pwm->use_pinentry) error = pwmd_command(pwm, &result, "OPTION LC_CTYPE=%s", @@ -2294,9 +2256,9 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) break; case PWMD_OPTION_PINENTRY_LC_MESSAGES: if (pwm->lcmessages) - xfree(pwm->lcmessages); + pwmd_free(pwm->lcmessages); - pwm->lcmessages = xstrdup(va_arg(ap, char *)); + pwm->lcmessages = pwmd_strdup(va_arg(ap, char *)); if (!pwm->use_pinentry) error = pwmd_command(pwm, &result, "OPTION LC_MESSAGES=%s", @@ -2311,16 +2273,58 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) return error; } -/* - * Prevent requiring assuan.h when setting ctx. The ctx is really an - * assuan_context_t *. - */ -gpg_error_t pwmd_assuan_ctx(pwm_t *pwm, void *ctx, int *fd) +gpg_error_t pwmd_get_fd(pwm_t *pwm, int *fd) { if (!pwm) return GPG_ERR_INV_ARG; - ctx = pwm->ctx; + if (pwm->fd == -1) + return GPG_ERR_INV_STATE; + *fd = pwm->fd; return 0; } + +pwm_t *pwmd_new(const char *name) +{ + pwm_t *h = pwmd_malloc(sizeof(pwm_t)); + + if (!h) + return NULL; + + if (name) { + h->name = pwmd_strdup(name); + + if (!h->name) { + pwmd_free(h); + return NULL; + } + } + + return h; +} + +void pwmd_free(void *ptr) +{ + xfree(ptr); +} + +void *pwmd_malloc(size_t size) +{ + return xmalloc(size); +} + +void *pwmd_calloc(size_t nmemb, size_t size) +{ + return xcalloc(nmemb, size); +} + +void *pwmd_realloc(void *ptr, size_t size) +{ + return xrealloc(ptr, size); +} + +char *pwmd_strdup(const char *str) +{ + return xstrdup(str); +} diff --git a/src/libpwmd.h.in b/src/libpwmd.h.in index 7f42a52c..52bcbeda 100644 --- a/src/libpwmd.h.in +++ b/src/libpwmd.h.in @@ -71,7 +71,7 @@ typedef enum { * A custom callback password retrieval function which is set with * pwmd_setopt(). This has priority over other retrieval methods if set. */ -typedef char *(*pwmd_password_fn)(pwm_t *pwm, void *data); +typedef const char *(*pwmd_password_fn)(void *data); /* * A callback to be set with pwmd_setopt() that processes Assuan protocol @@ -228,13 +228,20 @@ typedef enum { */ gpg_error_t pwmd_init(void); +/* Creates a new handle for use with the other library functions. The 'name' + * parameter specifies the name of the application using this library. + * + * Returns a new handle on success or NULL if there was not enough memory. + */ +pwm_t *pwmd_new(const char *name) __attribute__ ((warn_unused_result)); + /* * Connects to the socket specified by 'socket_path'. If socket_path is NULL, * then a default of ~/.pwmd/socket will be used. Returns a new handle for use * with the other functions or NULL if there was an error in which case * 'error' is set to an error code which may be described by pwmd_strerror(). */ -pwm_t *pwmd_connect(const char *socket_path, gpg_error_t *error) __attribute__ ((warn_unused_result)); +gpg_error_t pwmd_connect(pwm_t *pwm, const char *socket_path) __attribute__ ((warn_unused_result)); /* * Connects to the remote host "host". Both Ipv4 and IPv6 addresses are @@ -256,35 +263,27 @@ pwm_t *pwmd_connect(const char *socket_path, gpg_error_t *error) __attribute__ ( * an error in which case 'error' is set to an error code which may be * described by pwmd_strerror(). */ -pwm_t *pwmd_tcp_connect(const char *hostname, int port, const char *identity, const char *user, const char *known_hosts, gpg_error_t *error)__attribute__ ((warn_unused_result)); +gpg_error_t pwmd_tcp_connect(pwm_t *pwm, const char *hostname, int port, const char *identity, const char *user, const char *known_hosts) __attribute__ ((warn_unused_result)); /* Like pwmd_tcp_connect() but this function wont block while doing DNS * lookups and connecting. You should call pwmd_process() only when this * function succeeds (see pwmd_process() for more information). */ -pwm_t *pwmd_tcp_connect_async(const char *hostname, int port, const char *identity, const char *user, const char *known_hosts, gpg_error_t *error) __attribute__ ((warn_unused_result)); +gpg_error_t pwmd_tcp_connect_async(pwm_t *pwm, const char *hostname, int port, + const char *identity, const char *user, const char *known_hosts) __attribute__ ((warn_unused_result)); /* Retrieve the SSH server SHA1 host key. The result must be freed with - * pwmd_free_result(). - */ -char *pwmd_get_hostkey(const char *hostname, int port, gpg_error_t *rc) __attribute__ ((warn_unused_result)); -pwm_t *pwmd_get_hostkey_async(const char *hostname, int port, gpg_error_t *rc) __attribute__ ((warn_unused_result)); - -/* - * Sets 'ctx' to the assuan context associated with the handle 'pwm' and 'fd' - * to the socket file descriptor. Returns 0 on success or an error code. - * - * Note than ctx is really an assuan_context_t *. + * pwmd_free(). */ -gpg_error_t pwmd_assuan_ctx(pwm_t *pwm, void *ctx, int *fd) __attribute__ ((warn_unused_result)); +gpg_error_t pwmd_get_hostkey(const char *hostname, int port, char **result) __attribute__ ((warn_unused_result)); +gpg_error_t pwmd_get_hostkey_async(pwm_t *pwm, const char *hostname, int port) __attribute__ ((warn_unused_result)); /* - * A wrapper around assuan_pending_line() and assuan_read_line(). Returns 0 if - * there was a pending line and sets 'line' to the content and 'len' to the - * length. Returns GPG_ERR_NO_DATA if there was no pending line. Otherwise the - * error returned from assuan_read_line() is returned. + * Sets 'fd' to the file descriptor which is connected to the pwmd server. + * You can select() or poll() this fd to determine when to call + * pwmd_process(). Returns 0 on success or an error code. */ -gpg_error_t pwmd_pending_line(pwm_t *pwm, char **line, size_t *len) __attribute__ ((warn_unused_result)); +gpg_error_t pwmd_get_fd(pwm_t *pwm, int *fd) __attribute__ ((warn_unused_result)); /* * Sets a libpwmd option 'opt'. The next argument should be of the data type @@ -351,25 +350,11 @@ gpg_error_t pwmd_open_async(pwm_t *pwm, const char *filename) __attribute__ ((wa * that may have occurred is stored in 'rc'. If an error occurred or not, * pwmd_finalize() must be called to reset a control variable so the next * asynchronous command may be performed. - */ -pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc) __attribute__ ((warn_unused_result)); -gpg_error_t pwmd_get_result(pwm_t *pwm, const char **result) __attribute__ ((warn_unused_result)); -; - -/* - * Resets the control variable for the associated handle. Call this function - * after ASYNC_DONE is returned from pwmd_process(). The return value is not - * associated with the command that was being processed with pwmd_process(). - * This function returns 0 on success or an error if "pwm" is not a valid - * handle or in an inconsistant state. * - * NOTE: In the case that pwmd_tcp_connect_async() was used for the - * asynchronous command and an error occurred while connecting, this function - * will deallocate the resources used by the handle. You may then retry the - * connection. + * The result should not be modified by the client. It should be freed by + * calling pwmd_free() before the next asynchronous command. */ -//FIXME merge pwmd_get_result() into this function. -gpg_error_t pwmd_finalize(pwm_t *pwm) __attribute__ ((warn_unused_result)); +pwmd_async_t pwmd_process(pwm_t *pwm, gpg_error_t *rc, const char **result) __attribute__ ((warn_unused_result)); ; /* @@ -448,12 +433,6 @@ gpg_error_t pwmd_command_ap(pwm_t *pwm, char **result, const char *cmd, gpg_error_t pwmd_inquire(pwm_t *pwm, const char *cmd, pwmd_inquire_fn func, void *data) __attribute__ ((warn_unused_result)); -/* - * Free the memory used by the result of pwmd_command() if any. It is - * important to use this function because libpwmd keeps track of all memory - * de/allocations. - */ -void pwmd_free_result(void *); /* * Closes the connection to the socket and frees the resources of the handle. @@ -461,6 +440,15 @@ void pwmd_free_result(void *); */ void pwmd_close(pwm_t *pwm); + +/* Secure memory allocators. pwmd_free() should be called on all command + * results. */ +void pwmd_free(void *ptr); +void *pwmd_malloc(size_t size); +void *pwmd_calloc(size_t nmemb, size_t size); +void *pwmd_realloc(void *ptr, size_t size); +char *pwmd_strdup(const char *str); + /* * Protocol error codes. */ diff --git a/src/pwmc.c b/src/pwmc.c index 7137ffa8..f8d9fa6e 100644 --- a/src/pwmc.c +++ b/src/pwmc.c @@ -126,7 +126,7 @@ static gpg_error_t do_inquire(void *data, const char *keyword, gpg_error_t rc, if (inq->data) { snprintf(buf, sizeof(buf), "%s", inq->data); - xfree(inq->data); + pwmd_free(inq->data); inq->data = NULL; len = strlen(buf); p = buf + len; @@ -273,35 +273,35 @@ int main(int argc, char *argv[]) break; #ifdef WITH_TCP case 'H': - host = xstrdup(optarg); + host = pwmd_strdup(optarg); break; case 'R': port = atoi(optarg); break; case 'Y': - ident = xstrdup(optarg); + ident = pwmd_strdup(optarg); break; case 'U': - username = xstrdup(optarg); + username = pwmd_strdup(optarg); break; case 'K': - known_hosts = xstrdup(optarg); + known_hosts = pwmd_strdup(optarg); break; case 'G': get = 1; break; #endif case 'C': - lcctype = xstrdup(optarg); + lcctype = pwmd_strdup(optarg); break; case 'M': - lcmessages = xstrdup(optarg); + lcmessages = pwmd_strdup(optarg); break; case 't': timeout = atoi(optarg); break; case 'c': - clientname = xstrdup(optarg); + clientname = pwmd_strdup(optarg); break; case 'X': show_status = 0; @@ -320,7 +320,7 @@ int main(int argc, char *argv[]) inquirefp = fdopen(inquirefd, "r"); if (!inquirefp) { - xfree(password); + pwmd_free(password); err(EXIT_FAILURE, "%i", inquirefd); } break; @@ -329,7 +329,7 @@ int main(int argc, char *argv[]) outfp = fdopen(outfd, "w"); if (!outfp) { - xfree(password); + pwmd_free(password); err(EXIT_FAILURE, "%i", outfd); } break; @@ -341,38 +341,39 @@ int main(int argc, char *argv[]) have_iter = 1; break; case 's': - socketpath = xstrdup(optarg); + socketpath = pwmd_strdup(optarg); break; case 'p': - password = xstrdup(optarg); + password = pwmd_strdup(optarg); memset(optarg, 0, strlen(optarg)); break; case 'P': - pinentry_path = xstrdup(optarg); + pinentry_path = pwmd_strdup(optarg); break; case 'v': - xfree(password); + pwmd_free(password); printf("%s (pwmc)\n%s\n", PACKAGE_STRING, PACKAGE_BUGREPORT); exit(EXIT_SUCCESS); case 'h': default: - xfree(password); + pwmd_free(password); usage(argv[0]); } } if (host && !get && (!known_hosts || !ident)) { - xfree(password); + pwmd_free(password); usage(argv[0]); } if (get && !host) { - xfree(password); + pwmd_free(password); usage(argv[0]); } filename = argv[optind]; pwmd_init(); + pwm = pwmd_new("pwmc"); #ifdef WITH_TCP if (host) { @@ -381,108 +382,86 @@ int main(int argc, char *argv[]) if (get) { const char *hostkey; - xfree(password); - pwm = pwmd_get_hostkey_async(host, port, &error); + error = pwmd_get_hostkey_async(host, port); if (error) errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); do { - s = pwmd_process(pwm, &error); + s = pwmd_process(pwm, &error, &hostkey); fputc('.', stderr); usleep(50000); } while (s == ASYNC_PROCESS); - if (error) { - pwmd_close(pwm); - errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); - } - - error = pwmd_get_result(pwm, &hostkey); - - if (error) { - pwmd_close(pwm); - errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); - } + if (error) + goto done; printf("%s\n", hostkey); - pwmd_finalize(pwm); + pwmd_free(hostkey); + pwmd_free(password); pwmd_close(pwm); exit(EXIT_SUCCESS); } - if ((pwm = pwmd_tcp_connect_async(host, port, ident, username, known_hosts, &error)) == NULL) { - xfree(password); - errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); - } + error = pwmd_tcp_connect_async(pwm, host, port, ident, username, known_hosts); + + if (error) + goto done; do { - s = pwmd_process(pwm, &error); + s = pwmd_process(pwm, &error, &result); fputc('.', stderr); usleep(50000); } while (s == ASYNC_PROCESS); - if (error) { - pwmd_close(pwm); - xfree(password); - errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); - } - - pwmd_finalize(pwm); + if (error) + goto done; } else { #endif if (get) { - xfree(password); - char *hostkey = pwmd_get_hostkey(host, port, &error); + char *hostkey; + + error = pwmd_get_hostkey(host, port, &hostkey); if (error) - errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); + goto done; printf("%s\n", hostkey); - pwmd_free_result(hostkey); + pwmd_free(hostkey); + pwmd_free(password); exit(EXIT_SUCCESS); } - if ((pwm = pwmd_tcp_connect(host, port, ident, username, known_hosts, &error)) == NULL) { - xfree(password); - errx(EXIT_FAILURE, "%s: %s", host, pwmd_strerror(error)); - } + error = pwmd_tcp_connect(pwm, host, port, ident, username, known_hosts); + + if (error) + goto done; #ifdef DEBUG } #endif } else { #endif - if ((pwm = pwmd_connect(socketpath, &error)) == NULL) { - xfree(password); - errx(EXIT_FAILURE, "pwmd_connect(): %s", pwmd_strerror(error)); - } + error = pwmd_connect(pwm, socketpath); + + if (error) + goto done; #ifdef WITH_TCP } #endif - error = pwmd_command(pwm, &result, "OPTION CLIENT NAME=%s", clientname ? clientname : "pwmc"); - xfree(clientname); - - if (error) { - xfree(password); - goto done; - } - if (have_iter) { error = pwmd_command(pwm, &result, "VERSION"); - if (error && error != GPG_ERR_ASS_UNKNOWN_CMD) { - xfree(password); + if (error && error != GPG_ERR_ASS_UNKNOWN_CMD) goto done; - } - pwmd_free_result(result); + pwmd_free(result); if (error == GPG_ERR_ASS_UNKNOWN_CMD) { if (iter < -1) { - xfree(password); + pwmd_free(password); pwmd_close(pwm); usage(argv[0]); } @@ -490,7 +469,7 @@ int main(int argc, char *argv[]) else { /* pwmd version 2 or later. */ if (iter < 0) { - xfree(password); + pwmd_free(password); pwmd_close(pwm); usage(argv[0]); } @@ -500,21 +479,15 @@ int main(int argc, char *argv[]) if (timeout > 0) { error = pwmd_setopt(pwm, PWMD_OPTION_PINENTRY_TIMEOUT, timeout); - if (error) { - xfree(password); + if (error) goto done; - } } if (password) { error = pwmd_setopt(pwm, PWMD_OPTION_PASSWORD, password); - if (error) { - xfree(password); + if (error) goto done; - } - - xfree(password); } else { if (pinentry_path) { @@ -596,8 +569,6 @@ int main(int argc, char *argv[]) fputc('.', stderr); usleep(50000); } while (s == ASYNC_PROCESS); - - pwmd_finalize(pwm); } } else if (method == 2) { @@ -637,7 +608,7 @@ int main(int argc, char *argv[]) n = select(STDIN_FILENO+1, &rfds, NULL, NULL, &tv); if (n == 0) { - s = pwmd_process(pwm, &error); + s = pwmd_process(pwm, &error, &result); if (error) goto done; @@ -690,17 +661,17 @@ int main(int argc, char *argv[]) } if (inquire) { - struct inquire_s *inq = (struct inquire_s *)malloc(sizeof(struct inquire_s)); + struct inquire_s *inq = (struct inquire_s *)pwmd_malloc(sizeof(struct inquire_s)); if (!inq) { error = gpg_error_from_errno(ENOMEM); goto done; } - inq->data = xstrdup(p); + inq->data = pwmd_strdup(p); inq->fp = inquirefp; error = pwmd_inquire(pwm, inquire, do_inquire, inq); - free(inq); + pwmd_free(inq); goto done; } @@ -715,11 +686,12 @@ int main(int argc, char *argv[]) if (result) { fwrite(result, 1, strlen(result), outfp); - pwmd_free_result(result); + pwmd_free(result); } done: memset(command, 0, sizeof(command)); + pwmd_free(password); if (!error && save) { if (iter != -2) { @@ -735,12 +707,10 @@ done: if (!error) { do { - s = pwmd_process(pwm, &error); + s = pwmd_process(pwm, &error, &result); fputc('.', stderr); usleep(50000); } while (s == ASYNC_PROCESS); - - pwmd_finalize(pwm); } } else if (method == 3) { @@ -769,7 +739,7 @@ done: pwmd_close(pwm); if (socketpath) - xfree(socketpath); + pwmd_free(socketpath); exit(ret); } diff --git a/src/types.h b/src/types.h index 3e6e21e1..2b926a18 100644 --- a/src/types.h +++ b/src/types.h @@ -62,10 +62,10 @@ struct pwm_s { #ifdef WITH_TCP pwmd_tcp_conn_t *tcp_conn; #endif - char *result; int fd; pwmd_async_t state; pwmd_async_cmd_t cmd; + char *result; /* temporary: not related to anything the client can see. */ #ifdef WITH_PINENTRY pid_t pid; assuan_context_t pctx; @@ -93,6 +93,7 @@ struct pwm_s { void *status_data; pwmd_inquire_fn inquire_func; void *inquire_data; + char *name; }; typedef struct { @@ -100,4 +101,7 @@ typedef struct { void *buf; } membuf_t; +static gpg_error_t assuan_command(pwm_t *pwm, assuan_context_t ctx, + char **result, const char *cmd); + #endif -- 2.11.4.GIT