[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Cyrus IMAPd pwcheck + PAM - possible solution...



Morning...

	Last week, one of the subscribers to the Cyrus IMAPd mailing list
sent in a patch for using PAM inside of pwcheck.  The patch, I think,
looks good, except that after running for a short period of time, it
'crashes' with a 'too many open files' error message.

	I cleaned up the pwcheck() function that calls the pam_start/etc
functions, but beyond that, I'm kinda lost...can someone tell me whether
there are any obvious errors in the PAM_conv code?  The person that wrote
this is running it, if I understand correctly, on a 'quiet' system, so I'm
sort of figuring that the bug only exhibits itself on my system as it
being hit multiple times per second :(

	I'm running Solaris 2.6...

Thanks...


---------- Forwarded message ----------
Date: Mon, 31 Aug 1998 11:28:12 -0300 (ADT)
From: Marc G. Fournier <marc.fournier@acadiau.ca>
To: scrappy@hub.org
Subject: PAM

#include <security/pam_appl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Static variables used to communicate between the conversation function
 * and the server_login function
 */
static char *PAM_username;
static char *PAM_password;

/* PAM conversation function
 */
static int PAM_conv (int num_msg,
                     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

  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(PAM_username);
          /* PAM frees resp */
        break;
      case PAM_PROMPT_ECHO_OFF:
        reply[replies].resp_retcode = PAM_SUCCESS;
	reply[replies].resp = COPY_STRING(PAM_password);
          /* PAM frees resp */
        break;
      case PAM_TEXT_INFO:
        /* fall through */
      case PAM_ERROR_MSG:
        /* ignore it, but pam still wants a NULL response... */
        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;
    }
  }
  *resp = reply;
  return PAM_SUCCESS;
}

static struct pam_conv PAM_conversation = {
    PAM_conv,
    NULL
};

/* Server log in
 * Accepts: user name string
 *	    password string
 * Returns: "OK" if password validated, error message otherwise
 */ 
 
char *pwcheck(char *username, char *password)
{
  pam_handle_t *pamh;
  int pam_error;

  /* PAM only handles authentication, not user information. */
  if ( !(username && password && strlen(username) && strlen(password)) )
      return "Incorrect username";

  /* validate password */

  PAM_password = password;
  PAM_username = username;
  fprintf(stderr, "checking %s\n", username);
  pam_error = pam_start("cyrus", username, &PAM_conversation, &pamh);
  if (pam_error == PAM_SUCCESS) 
    pam_error = pam_authenticate(pamh, 0);
    
  if (pam_error == PAM_SUCCESS) 
    pam_error = pam_acct_mgmt(pamh, 0);

  if ( pam_error == PAM_SUCCESS) 
    fprintf(stderr, "\tauthenticated %s\n", username);
  else
    fprintf(stderr, "\tfailed to authenticate %s\n", username);
  
  if(pam_end(pamh, pam_error) != PAM_SUCCESS) {
    pamh = NULL;
    fprintf(stderr, "pwcheck: failed to release authenticator\n");
    exit(1);
  }
  return ( pam_error == PAM_SUCCESS ? "OK" : "Incorrect passwd" );
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []