src/authinfo_pam.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. PAM_conv
  2. COPY_STRING
  3. pam_got_pass
  4. 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 */

/* [<][>][^][v][top][bottom][index][help] */