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

What is wrong with this program?



		Hello

	The program attached tries to authenticate a user, having the
username and the password as argv[1] and argv[2]. The problem is the
memory leak: the program is getting bigger and bigger, as a ps can show.
	I am using RedHat Linux 5.1 on a x86. My pam libs are ok.
	Can anyone give me a hint? I suspect the 'reply' struct in
PAM_conv is never freed. I am not sure. Andrew, is the conversion
structure supposed to be freed by pam_end?

TIA,

						Mihai

	Mihai Ibanescu			Dynamic Network Technologies 
http://sysadm.dntis.ro/~misa	      Moara de Foc 35, et. 7, 6600 Iasi
	misa@dntis.ro			    tel. +40-32-252936
#include <security/pam_appl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>

#define PAM_CONF_FILE "login"

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

/* Logging to syslog any error message */

void log_msg(int priority, const char *fmt, va_list args)
{
	char buffer[1024];

	openlog(PAM_CONF_FILE, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
	vsnprintf(buffer, 1024, fmt, args);
	syslog(priority, buffer);
	closelog();
	return;
}

void log_err(const char * fmt, ...)
{
	va_list args;
        
	va_start(args, fmt);
	log_msg(LOG_ERR, fmt, args);
	va_end(args);
}

/* 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,
                     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:
      	log_err(msg[replies]->msg);
      	fprintf(stderr, "%s\n\n", msg[replies]->msg);
        reply[replies].resp_retcode = PAM_SUCCESS;
	reply[replies].resp = NULL;
        break;
      default:
        /* Must be an error of some sort... */
        fprintf(stderr, "%s\n\n", msg[replies]->msg);
        free (reply);
        PAM_error = 1;
        return PAM_CONV_ERR;
    }
  }
  *resp = reply;
  return PAM_SUCCESS;
}

static int test_conv (int num_msg,
                     const struct pam_message **msg,
		     struct pam_response **resp,
		     void *appdata_ptr) 
{
	return PAM_SUCCESS;
}

static struct pam_conv PAM_conversation = {
    &PAM_conv,
    NULL
};

/* Server log in
 * Accepts: user name string
 *	    password string
 * Returns: T if password validated, NIL otherwise
 */

int checkpw(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 0;

  /* validate password */

  #define PAM_BAIL if (PAM_error || (pam_error != PAM_SUCCESS)) { \
     pam_end(pamh, 0); return 0; \
   }
  PAM_password = password;
  PAM_username = username;
  pam_error = pam_start(PAM_CONF_FILE, username, &PAM_conversation, &pamh);
  PAM_BAIL;
  pam_error = pam_authenticate(pamh, 0);
  PAM_BAIL;
  pam_error = pam_acct_mgmt(pamh, 0);
  PAM_BAIL;
  pam_error = pam_setcred(pamh, PAM_ESTABLISH_CRED);
  PAM_BAIL;
  pam_end(pamh, PAM_SUCCESS);
  /* If this point is reached, the user has been authenticated. */
  return 1;
}

int main(int argc, char *argv[])
{
    char *user;
    char *pass;
    
    if(argc != 3) {
        fprintf(stderr, "Usage: %s username passwd\n", argv[0]);
        exit(1);
    }
    
    user = argv[1];
    pass = argv[2];

while (1) {

    if ( checkpw(user, pass) == 0 ) 
        printf("Pasword error\n");
	printf("OK\n");
}

    return 0;
}


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