From ce666a02fa39a574f0f9cff8ee66de65351e7e4f Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Tue, 11 May 2021 15:12:30 +0100 Subject: [PATCH 1/3] Bring the PAM module up to date --- sesman/verify_user_pam.c | 154 +++++++++++++++++++++++++++++---------- 1 file changed, 116 insertions(+), 38 deletions(-) diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c index 3fbb9279..3c9f389e 100644 --- a/sesman/verify_user_pam.c +++ b/sesman/verify_user_pam.c @@ -30,6 +30,7 @@ #include "arch.h" #include "os_calls.h" +#include "log.h" #include "string_calls.h" #include @@ -53,43 +54,117 @@ struct t_auth_info pam_handle_t *ph; }; +/***************************************************************************//** + * Returns a string representing a pam_conv message style + * + * @param msg_style PAM msg_style (pam_conv(3)) + * @param buff Buffer for conversion of unrecognised values + * @param bufflen Total length of above + * + * The buffer described by buff is only written to if required. + */ +static const char * +msg_style_to_str(int msg_style, char *buff, unsigned int bufflen) +{ + const char *result; + switch (msg_style) + { + case PAM_PROMPT_ECHO_OFF: + result = "PAM_PROMPT_ECHO_OFF"; + break; + + case PAM_PROMPT_ECHO_ON: + result = "PAM_PROMPT_ECHO_ON"; + break; + + case PAM_ERROR_MSG: + result = "PAM_ERROR_MSG"; + break; + + case PAM_TEXT_INFO: + result = "PAM_TEXT_INFO"; + break; + + default: + snprintf(buff, bufflen, "UNKNOWN_0x%x", msg_style); + result = buff; + } + + return result; +} + /******************************************************************************/ static int verify_pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int i; - struct pam_response *reply; + struct pam_response *reply = NULL; struct t_user_pass *user_pass; + char sb[64]; + int rv = PAM_SUCCESS; - reply = g_new0(struct pam_response, num_msg); - - for (i = 0; i < num_msg; i++) + if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) { - switch (msg[i]->msg_style) + rv = PAM_CONV_ERR; + } + else if ((reply = g_new0(struct pam_response, num_msg)) == NULL) + { + rv = PAM_BUF_ERR; + } + else + { + for (i = 0; i < num_msg && rv == PAM_SUCCESS; i++) { - case PAM_PROMPT_ECHO_ON: /* username */ - user_pass = (struct t_user_pass *) appdata_ptr; - reply[i].resp = g_strdup(user_pass->user); - reply[i].resp_retcode = PAM_SUCCESS; - break; - case PAM_PROMPT_ECHO_OFF: /* password */ - user_pass = (struct t_user_pass *) appdata_ptr; - reply[i].resp = g_strdup(user_pass->pass); - reply[i].resp_retcode = PAM_SUCCESS; - break; - case PAM_TEXT_INFO: - g_memset(&reply[i], 0, sizeof(struct pam_response)); - break; - default: - g_printf("unknown in verify_pam_conv\r\n"); - g_free(reply); - return PAM_CONV_ERR; + LOG_DEVEL(LOG_LEVEL_INFO, "Handling struct pam_message" + " { style = %s, msg = \"%s\" }", + msg_style_to_str(msg[i]->msg_style, sb, sizeof (sb)), + msg[i]->msg == NULL ? "" : msg[i]->msg); + + switch (msg[i]->msg_style) + { + case PAM_PROMPT_ECHO_OFF: /* password */ + user_pass = (struct t_user_pass *) appdata_ptr; + reply[i].resp = g_strdup(user_pass->pass); + break; + + case PAM_ERROR_MSG: + LOG(LOG_LEVEL_ERROR, "PAM: %s", msg[i]->msg); + break; + + case PAM_TEXT_INFO: + LOG(LOG_LEVEL_INFO, "PAM: %s", msg[i]->msg); + break; + + default: + { + LOG(LOG_LEVEL_ERROR, "Unhandled message in verify_pam_conv" + " { style = %s, msg = \"%s\" }", + msg_style_to_str(msg[i]->msg_style, sb, sizeof (sb)), + msg[i]->msg == NULL ? "" : msg[i]->msg); + rv = PAM_CONV_ERR; + } + } } } - *resp = reply; - return PAM_SUCCESS; + if (rv == PAM_SUCCESS) + { + *resp = reply; + } + else if (reply != NULL) + { + for (i = 0; i < num_msg; i++) + { + if (reply[i].resp != NULL) + { + g_free(reply[i].resp); + } + } + g_free(reply); + } + + return rv; } /******************************************************************************/ @@ -126,7 +201,7 @@ auth_userpass(const char *user, const char *pass, int *errorcode) g_strncpy(auth_info->user_pass.pass, pass, MAX_BUF - 1); auth_info->pamc.conv = &verify_pam_conv; auth_info->pamc.appdata_ptr = &(auth_info->user_pass); - error = pam_start(service_name, 0, &(auth_info->pamc), &(auth_info->ph)); + error = pam_start(service_name, user, &(auth_info->pamc), &(auth_info->ph)); if (error != PAM_SUCCESS) { @@ -134,7 +209,8 @@ auth_userpass(const char *user, const char *pass, int *errorcode) { *errorcode = error; } - g_printf("pam_start failed: %s\r\n", pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_start failed: %s", + pam_strerror(auth_info->ph, error)); pam_end(auth_info->ph, error); g_free(auth_info); return 0; @@ -143,8 +219,8 @@ auth_userpass(const char *user, const char *pass, int *errorcode) error = pam_set_item(auth_info->ph, PAM_TTY, service_name); if (error != PAM_SUCCESS) { - g_printf("pam_set_item failed: %s\r\n", - pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_set_item failed: %s", + pam_strerror(auth_info->ph, error)); } error = pam_authenticate(auth_info->ph, 0); @@ -155,8 +231,8 @@ auth_userpass(const char *user, const char *pass, int *errorcode) { *errorcode = error; } - g_printf("pam_authenticate failed: %s\r\n", - pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_authenticate failed: %s", + pam_strerror(auth_info->ph, error)); pam_end(auth_info->ph, error); g_free(auth_info); return 0; @@ -175,8 +251,8 @@ auth_userpass(const char *user, const char *pass, int *errorcode) { *errorcode = error; } - g_printf("pam_acct_mgmt failed: %s\r\n", - pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_acct_mgmt failed: %s", + pam_strerror(auth_info->ph, error)); pam_end(auth_info->ph, error); g_free(auth_info); return 0; @@ -200,7 +276,8 @@ auth_start_session(long in_val, int in_display) if (error != PAM_SUCCESS) { - g_printf("pam_set_item failed: %s\r\n", pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_set_item failed: %s", + pam_strerror(auth_info->ph, error)); return 1; } @@ -208,7 +285,8 @@ auth_start_session(long in_val, int in_display) if (error != PAM_SUCCESS) { - g_printf("pam_setcred failed: %s\r\n", pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_setcred failed: %s", + pam_strerror(auth_info->ph, error)); return 1; } @@ -217,8 +295,8 @@ auth_start_session(long in_val, int in_display) if (error != PAM_SUCCESS) { - g_printf("pam_open_session failed: %s\r\n", - pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_open_session failed: %s", + pam_strerror(auth_info->ph, error)); return 1; } @@ -238,8 +316,8 @@ auth_stop_session(long in_val) error = pam_close_session(auth_info->ph, 0); if (error != PAM_SUCCESS) { - g_printf("pam_close_session failed: %s\r\n", - pam_strerror(auth_info->ph, error)); + LOG(LOG_LEVEL_ERROR, "pam_close_session failed: %s", + pam_strerror(auth_info->ph, error)); return 1; } auth_info->session_opened = 0; From 87701051d3655d39fb5c1d77c193cc0f0eff2191 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Thu, 10 Jun 2021 15:45:09 +0100 Subject: [PATCH 2/3] Update conversation header following review --- sesman/verify_user_pam.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c index 3c9f389e..6cad2a62 100644 --- a/sesman/verify_user_pam.c +++ b/sesman/verify_user_pam.c @@ -93,7 +93,30 @@ msg_style_to_str(int msg_style, char *buff, unsigned int bufflen) return result; } -/******************************************************************************/ +/***************************************************************************//** + * Provides the PAM conversation callback function + * + * At present, the main purpose of this function is to supply the + * user's password to the PAM stack, although some module logging is + * implemented here. + * + * @param[in] num_msg Count of messages in the msg array + * @param[in] msg Messages from the PAM stack to the application + * @param[out] resp Message replies from the application to the PAM stack + * @param[in] appdata_ptr Used to pass in a struct t_user_pass pointer + * + * @result PAM_SUCCESS if the messages were all processed successfully. + * + * @post If PAM_SUCCESS is returned, resp and its contents are allocated here + * and must be freed by the caller + * @post If PAM_SUCCESS is not returned, resp is not allocated and must not + * be not freed by the caller + * + * @note See pam_conv(3) for more information + * @note A basic example conversation function can be found in OSF RFC + 86.0 (1995) + */ + static int verify_pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) From a79f5c00b1727597bd9f01edc1b9100cd56f3618 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Thu, 17 Jun 2021 15:15:59 +0100 Subject: [PATCH 3/3] Replace snprintf() with g_snprintf() --- sesman/verify_user_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c index 6cad2a62..0d384eaf 100644 --- a/sesman/verify_user_pam.c +++ b/sesman/verify_user_pam.c @@ -86,7 +86,7 @@ msg_style_to_str(int msg_style, char *buff, unsigned int bufflen) break; default: - snprintf(buff, bufflen, "UNKNOWN_0x%x", msg_style); + g_snprintf(buff, bufflen, "UNKNOWN_0x%x", msg_style); result = buff; }