From 9d432a9bd2c3a6b37aab42438e2854b52f052e5e Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Mon, 5 Feb 2007 08:04:51 -0500 Subject: [PATCH] Added PWMD_OPTION_PASSWORD_FUNC and PWMD_OPTION_PASSWORD_DATA to specify a custom password retrieval function. --- libpwmd/libpwmd.3.in | 10 ++++++++++ libpwmd/libpwmd.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ libpwmd/libpwmd.h | 22 +++++++++++++++++++++- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/libpwmd/libpwmd.3.in b/libpwmd/libpwmd.3.in index 00769cee..396a26b6 100644 --- a/libpwmd/libpwmd.3.in +++ b/libpwmd/libpwmd.3.in @@ -27,6 +27,8 @@ libpwmd \- pwmd client interface library .BI "int pwmd_command(pwm_t " *pwm ", char " **result ", int " **error ", pwmd_cmd " cmd ", " ... ");" .BI "void pwmd_close(pwm_t " *pwm ");" .BI "const char *pwmd_strerror(int " error ");" +.P +.BI "typedef char *(" pwmd_password_func ")(void *" data ");" .fi .SH DESCRIPTION .B libpwmd @@ -74,6 +76,14 @@ Sets library options and settings. The next argument is one of the following: .RS .TP +.B PWMD_OPTION_PASSWORD_FUNC +Specifies a function to use to get a password. The function should return an +allocated \fIchar *\fP string which is the password or NULL if there is an +error. +.TP +.B PWMD_OPTION_PASSWORD_DATA +A userdata pointer passed to the password function. +.TP .B PWMD_OPTION_USEAGENT Whether to use .BR gpg-agent (1) diff --git a/libpwmd/libpwmd.c b/libpwmd/libpwmd.c index aad22f23..8d44327d 100644 --- a/libpwmd/libpwmd.c +++ b/libpwmd/libpwmd.c @@ -590,6 +590,21 @@ int pwmd_command(pwm_t *pwm, char **result, int *error, pwmd_cmd cmd, ...) va_end(ap); return PWMD_ERROR; case PWMD_PERROR: + if (terror == EPWMD_CACHE_NOT_FOUND || + terror == EPWMD_FILE_NOT_FOUND) { + if (pwm->passfunc) { + password = (*pwm->passfunc)(pwm->passdata); + + if (!password) { + *error = EPWMD_KEY; + va_end(ap); + return PWMD_PERROR; + } + + goto gotpassword; + } + } + if (terror == EPWMD_CACHE_NOT_FOUND) { /* * Get the password from gpg-agent/pinentry. @@ -641,6 +656,7 @@ int pwmd_command(pwm_t *pwm, char **result, int *error, pwmd_cmd cmd, ...) break; } +gotpassword: if (send_to_daemon(pwm, "OPEN %s %s\n", filename, (password) ? password : "")) { if (password) secure_free(password, strlen(password)); @@ -656,6 +672,12 @@ int pwmd_command(pwm_t *pwm, char **result, int *error, pwmd_cmd cmd, ...) n = va_arg(ap, int); switch (n) { + case PWMD_OPTION_PASSWORD_FUNC: + pwm->passfunc = va_arg(ap, pwmd_password_func *); + break; + case PWMD_OPTION_PASSWORD_DATA: + pwm->passdata = va_arg(ap, void *); + break; case PWMD_OPTION_USEAGENT: n = va_arg(ap, int); @@ -700,7 +722,7 @@ int pwmd_command(pwm_t *pwm, char **result, int *error, pwmd_cmd cmd, ...) va_end(ap); return PWMD_OK; case PWMD_SAVE: - if (pwm->use_agent) { + if (pwm->use_agent || pwm->passfunc) { snprintf(buf, sizeof(buf), "CACHE ISCACHED %s\n", pwm->filename); n = pwmd_command(pwm, &tresult, &terror, PWMD_COMMAND, buf); @@ -712,10 +734,24 @@ int pwmd_command(pwm_t *pwm, char **result, int *error, pwmd_cmd cmd, ...) case PWMD_PERROR: if (terror == EPWMD_CACHE_NOT_FOUND || terror == EPWMD_FILE_NOT_FOUND) { - if (get_agent_password(pwm, &password)) { - *error = 0; - va_end(ap); - return PWMD_AGENT_ERROR; + + if (pwm->use_agent) { + if (get_agent_password(pwm, &password)) { + *error = 0; + va_end(ap); + return PWMD_AGENT_ERROR; + } + } + else { + if (pwm->passfunc) { + password = (*pwm->passfunc)(pwm->passdata); + + if (!password) { + *error = EPWMD_KEY; + va_end(ap); + return PWMD_PERROR; + } + } } if (!password || !*password) { @@ -731,7 +767,8 @@ int pwmd_command(pwm_t *pwm, char **result, int *error, pwmd_cmd cmd, ...) /* * We use pwmd's cache from now on. */ - clear_agent_password(pwm); + if (pwm->use_agent) + clear_agent_password(pwm); } else { *error = terror; diff --git a/libpwmd/libpwmd.h b/libpwmd/libpwmd.h index 2e7e7edf..9e772b45 100644 --- a/libpwmd/libpwmd.h +++ b/libpwmd/libpwmd.h @@ -30,13 +30,31 @@ typedef enum { PWMD_AGENT_ERROR, // gpg-agent error } pwmd_state; +typedef char *(pwmd_password_func)(void *data); + typedef enum { /* + * PWMD_OPTION_PASSWORD_FUNC + * + * Function to retrieve a password. This function should return an + * allocated string which is the password or NULL. + */ + PWMD_OPTION_PASSWORD_FUNC, + + /* + * PWMD_OPTION_PASSWORD_DATA + * + * Data passed to the password function. + */ + PWMD_OPTION_PASSWORD_DATA, + + /* * PWMD_OPTION_USEAGENT * * The following argument should be of type int and set to 1 to enable * the use of gpg-agent to retrieve passwords. Setting to 0 will disable - * using gpg-agent and the password must be set with PWMD_OPTION_PASSWORD. + * using gpg-agent and the password must be set with PWMD_OPTION_PASSWORD + * or gotten from PWMD_OPTION_PASSWORD_FUNC. */ PWMD_OPTION_USEAGENT, @@ -115,6 +133,8 @@ typedef struct { char *desc; char *password; char *filename; + pwmd_password_func *passfunc; + void *passdata; } pwm_t; /* -- 2.11.4.GIT