src/authinfo_pam.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- PAM_conv
- COPY_STRING
- pam_got_pass
- pam_got_sasl
/*
NNTPCACHE Linux PAM authentication code.
Conversation function source from unattributed source, the rest (c) Peter C. Tonoli <peter@metaverse.org> 1999,2000
*/
#include "nglobal.h"
#ifdef AUTHINFO_PAM
#include "acc.h"
#include "reg.h"
#include "authinfo.h"
#include "authinfo_pam.h"
#include <security/pam_appl.h>
#ifdef __Linux__
# include <security/pam_misc.h>
#endif
/* we use authinfo_got_user() */
char *authinfo_pass;
/* PAM conversation function
* Here we assume (for now, at least) that echo on means login name, and
* echo off means password.
*/
static int PAM_conv (int num_msg,
/* [<][>][^][v][top][bottom][index][help] */
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr) {
int replies = 0;
struct pam_response *reply = NULL;
# define COPY_STRING(s) (s) ? strdup(s) : NULL
/* [<][>][^][v][top][bottom][index][help] */
reply = malloc(sizeof(struct pam_response) * num_msg);
if (!reply) return PAM_CONV_ERR;
for (replies = 0; replies < num_msg; replies++) {
switch (msg[replies]->msg_style) {
case PAM_PROMPT_ECHO_ON:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = COPY_STRING(authinfo_user);
/* PAM frees resp */
break;
case PAM_PROMPT_ECHO_OFF:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = COPY_STRING(authinfo_pass);
/* PAM frees resp */
break;
case PAM_TEXT_INFO:
/* fall through */
case PAM_ERROR_MSG:
/* ignore it... */
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = NULL;
break;
default:
/* Must be an error of some sort... */
free (reply);
return PAM_CONV_ERR;
}
}
if (reply) *resp = reply;
return PAM_SUCCESS;
}
EXPORT int pam_got_pass(char *pass)
/* [<][>][^][v][top][bottom][index][help] */
{
int retval = TRUE;
int pamtest;
static struct pam_conv PAM_conversation = {
&PAM_conv,
NULL
};
pam_handle_t *pamhandle;
if (authinfo_user == NULL) {
emitf("%d USER required\r\n", NNTP_AUTH_REJECT_VAL);
return FALSE;
}
authinfo_pass = pass;
if (pass && *pass) {
pamtest = pam_start(con->pamModuleName, authinfo_user, &PAM_conversation, &pamhandle);
if (pamtest != PAM_SUCCESS) {
retval = FALSE;
logen(("PAM : initialisation error : %s\r\n", pam_strerror(pamhandle, pamtest)));
} else {
pamtest = pam_authenticate(pamhandle, 0);
if (pamtest != PAM_SUCCESS) {
retval = FALSE;
if ((pamtest != PAM_AUTH_ERR) && (pamtest != PAM_USER_UNKNOWN)) logen(("PAM : authentication error : %s\r\n", pam_strerror(pamhandle, pamtest)));
/* We don't *really* want to know if the user is a valid user..
Can never trust those reading log files */
} else {
pamtest = (pam_acct_mgmt(pamhandle, 0));
if (pamtest != PAM_SUCCESS) {
retval = FALSE;
if (pamtest != PAM_USER_UNKNOWN) logen(("PAM : account management error : %s\r\n", pam_strerror(pamhandle, pamtest)));
/* We don't *really* want to know if the user is a valid user..
Can never trust those reading log files */
}
}
}
} else retval = FALSE; /* Auth with NULL passwords? I think not! */
/* Perhaps in the future we can actually use these two calls below when the
NNRP session has actually ended, or something */
pam_close_session(pamhandle, 0);
pam_end(pamhandle, 0);
if (retval == TRUE) {
emitf("%d Authentication accepted\r\n", NNTP_AUTH_OK_VAL);
} else emitf("%d Authentication rejected\r\n", NNTP_AUTH_REJECT_VAL);
return retval;
}
/*
* pam authenticator.
*/
EXPORT authenticator pam_authenticator = {
authinfo_got_user,
pam_got_pass,
#ifdef notyet
pam_got_sasl,
#endif
};
#ifdef notyet
EXPORT int pam_got_sasl(char *val)
/* [<][>][^][v][top][bottom][index][help] */
{
}
#endif
#endif /* AUTHINFO_PAM */