Re: (mod_auth_)pam crashes solaris 8 server

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

 



Hi Ingo

Thanks for your quick reply! I could trace the problem down to
pam_unix.so not liking a NULL pointer instead of a username.

> > I am not sure if this is a mod_auth_pam or a Solaris pam problem. If
> > the process goes crazy nothing is logged at all, neither by
> > mod_auth_pam nor by pam_unix.so.1.
>
> No username is a fairly normal condition, e.g., it can happen when the
> user terminates the browsers password dialog.  I get it during testing
> (on Linux) regularly and the web-server didn't crash so I would be
> surprised if its a mod_auth_pam problem.

You are right, it's not a mod_auth_pam problem.

> Looking at the trace from the crashed server, I can only make a few
> guesses" "pam.conf" is opened and "pam_unix.so.1" is opened
> afterwards, so that means that the basic PAM initialization worked.
> After that, "libcmd.so.1" is opened.  Do you know what that library
> does?  From the name, I would assume it has something to do with
> running commands.

I have no clue, but share your assumption.

>  Are you using /etc/shadow?  In that case,
> Solaris-PAM is probably running some helper application to check the
> passwords.  Maybe that helper has problems checking an 'empty'
> username?

Even worse, we are using NIS+ ;-)

> Could you trace some other application (preferably one not running as
> root) and compare the results?  I would really like to find out what
> kind of problem that is.  Did you check Suns erratas already?

Yes, but I could not find anything.

Now, let me explain what I did:
With the attached source (check_user.c) I can reproduce the behaviour
on my machine. Just define SOLARIS8_CRASH, call check_user without a
username, the binary hangs and you can see your memory melt.

I assume you cannot reproduce this on your linux box, can you? But
then it's not clear yet if it's because you are using linux-pam or
because you are (probably) not using NIS+.

> Anyway, an empty username is not really usefull (whereas an empty
> password could be) so I implemented a small change that checks wether
> the username is empty before proceeding and refuses the request
> completely in case it is.  Please try it to see wether it helps.

Yes, it helps. As you can see the conversion function I copied into my
little test app does a similar check. So it's not that uncommon in the
PAM world.

Thanks a lot again for your help and the patch!

Regards
Thomas

PS: I also noticed a Mozilla 1.0 bug: if you leave the username empty
once, you have no chance to reenter username/password later on. You
won't see the password dialog ever, not even after a reload of the
page. You have to close/reopen Mozilla. This does not happen with
other browsers.
/*
This code is a compilation of the check_user.c file from Linux-PAM
(http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/pam/Linux-PAM/examples/check_user.c)
and the conversation function is taken from the freebsd distro
(http://www.freebsd.org/doc/en_US.ISO8859-1/articles/pam/pam-sample-conv.html)

compile with:
gcc -lpam check_user.c -o check_user


You need to add the following (or equivalent) to the /etc/pam.conf file.
  # check authorization
  check   auth       required    /usr/lib/security/$ISA/pam_unix.so.1 
  check   account    required    /usr/lib/security/$ISA/pam_unix.so.1

  define SOLARIS8_CRASH (see below), and Solaris will crash if you do not supply a username

  Thomas Werschlein, 09/13/2002
*/
    
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <security/pam_appl.h>

/* if I define this and do not supply a username this will
   crash my solaris 8 host (look at top and see how the process is eating up all memory!)
*/
//#define SOLARIS8_CRASH 1

int
converse(int n, const struct pam_message **msg,
	 struct pam_response **resp, void *data)
{
  char buf[PAM_MAX_RESP_SIZE];
  int i;

  data = data;
  if (n <= 0 || n > PAM_MAX_NUM_MSG)
    return (PAM_CONV_ERR);
  if ((*resp = calloc(n, sizeof **resp)) == NULL)
    return (PAM_BUF_ERR);
  for (i = 0; i < n; ++i) {
    resp[i]->resp_retcode = 0;
    resp[i]->resp = NULL;
    switch (msg[i]->msg_style) {
    case PAM_PROMPT_ECHO_OFF:
      resp[i]->resp = strdup(getpass(msg[i]->msg));
      if (resp[i]->resp == NULL)
	goto fail;
      break;
    case PAM_PROMPT_ECHO_ON:
#ifdef SOLARIS8_CRASH
      resp[i]->resp = NULL;
#else
      fputs(msg[i]->msg, stderr);
      if (fgets(buf, sizeof buf, stdin) == NULL)
	goto fail;
      resp[i]->resp = strdup(buf);
      if (resp[i]->resp == NULL)
	goto fail;
#endif
      break;
    case PAM_ERROR_MSG:
      fputs(msg[i]->msg, stderr);
      if (strlen(msg[i]->msg) > 0 &&
	  msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
	fputc('\n', stderr);
      break;
    case PAM_TEXT_INFO:
      fputs(msg[i]->msg, stdout);
      if (strlen(msg[i]->msg) > 0 &&
	  msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
	fputc('\n', stdout);
      break;
    default:
      goto fail;
    }
  }
  return (PAM_SUCCESS);
 fail:
  while (i)
    free(resp[--i]);
  free(*resp);
  *resp = NULL;
  return (PAM_CONV_ERR);
}

static struct pam_conv conv = {
    converse,
    NULL
};


int main(int argc, char *argv[])
{
    pam_handle_t *pamh=NULL;
    int retval;
    const char *user="";

    if(argc == 2) {
	user = argv[1];
    }

    if(argc > 2) {
	fprintf(stderr, "Usage: check_user [username]\n");
	exit(1);
    }

    retval = pam_start("check", user, &conv, &pamh);
	
    if (retval == PAM_SUCCESS)
        retval = pam_authenticate(pamh, 0);    /* is user really user? */

    if (retval == PAM_SUCCESS)
        retval = pam_acct_mgmt(pamh, 0);       /* permitted access? */

    /* This is where we have been authorized or not. */

    if (retval == PAM_SUCCESS) {
	fprintf(stdout, "Authenticated\n");
    } else {
	fprintf(stdout, "Not Authenticated\n");
    }

    if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
	pamh = NULL;
	fprintf(stderr, "check_user: failed to release authenticator\n");
	exit(1);
    }

    return ( retval == PAM_SUCCESS ? 0:1 );       /* indicate success */
}



[Index of Archives]     [Fedora Users]     [Kernel]     [Red Hat Install]     [Linux for the blind]     [Gimp]

  Powered by Linux