Pull out the code which searches the name_value_list for a matching prompt, and also substitutes keywords (USERNAME etc.) into a separate function, for clarity and to support forthcoming changes.
Signed-off-by: Tim Small <t...@seoss.co.uk> --- src/plugins/auth-pam/auth-pam.c | 96 +++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c index d6fcda9..722d0cf 100644 --- a/src/plugins/auth-pam/auth-pam.c +++ b/src/plugins/auth-pam/auth-pam.c @@ -538,6 +538,58 @@ openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle) } /* + * Key value pair list search with USERNAME/COMMONNAME/PASSWORD + * substitution. + * + * Returns 1 if match (with/without substitution) and the first + * match (substituted if necessary) in the list is returned in + * response. The callee must arrange to free() the response. + * + * Returns 0 if no match for search_term found in the user_pass + * name_value_list, in this case response is left unmodified. + */ + +int +get_value_with_subst (struct user_pass const *up, const char * const search_term, char **response) +{ + int ret = 0; + int j; + const struct name_value_list *list = up->name_value_list; + /* loop through name/value pairs */ + for (j = 0; j < list->len; ++j) + { + const char *item_key = list->data[j].name; + const char *item_value = list->data[j].value; + + if (name_value_match (search_term, item_key)) + { + /* found name/value match */ + *response = NULL; + + if (DEBUG (up->verb)) + fprintf (stderr, "AUTH-PAM: BACKGROUND: name match found, query/match-string ['%s', '%s'] = '%s'\n", + search_term, + item_key, + item_value); + + if (strstr(item_value, "USERNAME")) + *response = searchandreplace(item_value, "USERNAME", up->username); + else if (strstr(item_value, "PASSWORD")) + *response = searchandreplace(item_value, "PASSWORD", up->password); + else if (strstr(item_value, "COMMONNAME")) + *response = searchandreplace(item_value, "COMMONNAME", up->common_name); + else + *response = strdup (item_value); + + if (*response != NULL) + ret = 1; + break; + } + } + return ret; +} + +/* * PAM conversation function */ static int @@ -574,47 +626,17 @@ my_conv (int n, const struct pam_message **msg_array, if (up->name_value_list && up->name_value_list->len > 0) { /* use name/value list match method */ - const struct name_value_list *list = up->name_value_list; - int j; - - /* loop through name/value pairs */ - for (j = 0; j < list->len; ++j) - { - const char *match_name = list->data[j].name; - const char *match_value = list->data[j].value; - - if (name_value_match (msg->msg, match_name)) - { - /* found name/value match */ - aresp[i].resp = NULL; - - if (DEBUG (up->verb)) - fprintf (stderr, "AUTH-PAM: BACKGROUND: name match found, query/match-string ['%s', '%s'] = '%s'\n", - msg->msg, - match_name, - match_value); - - if (strstr(match_value, "USERNAME")) - aresp[i].resp = searchandreplace(match_value, "USERNAME", up->username); - else if (strstr(match_value, "PASSWORD")) - aresp[i].resp = searchandreplace(match_value, "PASSWORD", up->password); - else if (strstr(match_value, "COMMONNAME")) - aresp[i].resp = searchandreplace(match_value, "COMMONNAME", up->common_name); - else - aresp[i].resp = strdup (match_value); - - if (aresp[i].resp == NULL) - ret = PAM_CONV_ERR; - break; - } + if (!get_value_with_subst (up, msg->msg, &(aresp[i].resp))) + { + ret = PAM_CONV_ERR; + if (DEBUG (up->verb)) + fprintf (stderr, "AUTH-PAM: BACKGROUND: Didn't find a match for prompt " + "'%s' which was requested by pam module.\n", msg->msg); } - - if (j == list->len) - ret = PAM_CONV_ERR; } else { - /* use PAM_PROMPT_ECHO_x hints */ + /* no name/value list provided, rely on PAM_PROMPT_ECHO_x hints alone */ switch (msg->msg_style) { case PAM_PROMPT_ECHO_OFF: -- 2.1.4