Merge pull request #1883 from matt335672/pam_fixes

PAM module minor improvements #1883
This commit is contained in:
matt335672
2021-06-18 10:37:33 +01:00
committed by GitHub
+140 -39
View File
@@ -30,6 +30,7 @@
#include "arch.h"
#include "os_calls.h"
#include "log.h"
#include "string_calls.h"
#include <stdio.h>
@@ -53,43 +54,140 @@ 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:
g_snprintf(buff, bufflen, "UNKNOWN_0x%x", msg_style);
result = buff;
}
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)
{
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 ? "<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 ? "<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 +224,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 +232,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 +242,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 +254,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 +274,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 +299,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 +308,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 +318,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 +339,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;