[Exim] passwd lookup and no getpwnam

Top Page
Delete this message
Reply to this message
Author: Josh Siegel
Date:  
To: exim-users
Subject: [Exim] passwd lookup and no getpwnam
[...]
> >> What I find strange is that exim has no built in getpwnam
> >> functionality. Isn't that a feasable way to access passwords on any
> >> Unix-like system or do PAM and other methods break it?
> >
> >Exim 4.12 provides a "passwd"-lookup.
> >
> >ciao

[...]

I created a stand alone suid program that verified usernames and passwords
that I just called out to.

--josh

==

/* Copyright (c) University of Cambridge 1995 - 2002 */
/* See the file NOTICE for conditions of use and distribution. */

// Modified by Josh Siegel  (joshs@???)
//
// This is a modified src/auths/call_pam.c that turns it into
// standalone functionality.  I compiled this and placed the
// resulting executable in /usr/exim/bin/authcheck.  I then set
// it to be suid to root so that the authentication would work
// consistantly.  I then added it as a authenticator
//
//   # gcc -o /usr/exim/bin/authcheck authcheck.cxx -lpam
//   # chown root /usr/exim/bin/authcheck
//   # chmod u+s /usr/exim/bin/authcheck
//
// begin authenticators
//
// login:
//     driver = plaintext
//     public_name = LOGIN
//     server_prompts = "Username:: : Password::"
//     server_condition = ${run{"/usr/exim/bin/authcheck" $1 $2}{yes}{no}}
// yes}{no}}
//     server_set_id = $1
//
// login2:
//     driver = plaintext
//     public_name = PLAIN
//     server_prompts = "Username:: : Password::"
//     server_condition = ${run{"/usr/exim/bin/authcheck" $1 $2}{yes}{no}}
// yes}{no}}
//     server_set_id = $1
//


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

static int pam_conv_had_error = 0;

char **g_argv;
int g_argc;
int g_arg;

static int
pam_converse (int num_msg, const struct pam_message **msg,
  struct pam_response **resp, void *appdata_ptr)
{
  int i;
  int sep = 0;
  struct pam_response *reply =
     (struct pam_response *) malloc(sizeof(struct pam_response) * num_msg);


if (reply == NULL)
return PAM_CONV_ERR;

  for (i = 0; i < num_msg; i++)
    {
    unsigned char *arg;
    switch (msg[i]->msg_style)
      {
      case PAM_PROMPT_ECHO_ON:
      case PAM_PROMPT_ECHO_OFF:
        reply[i].resp = strdup((g_arg >= g_argc) ?
"" : g_argv[g_arg++]); /* PAM frees resp */
        reply[i].resp_retcode = PAM_SUCCESS;
        break;


      case PAM_TEXT_INFO:    // Just acknowledge message
        reply[i].resp_retcode = PAM_SUCCESS;
        reply[i].resp = NULL;
        break;


      default:  /* Must be an error of some sort... */
        free (reply);
        pam_conv_had_error = 1;
        return PAM_CONV_ERR;
      }
    }


*resp = reply;
return PAM_SUCCESS;
}

void main(int argc, char **argv, char **argp) {

g_argc = argc;
g_argv = argv;
g_arg = 2;

pam_handle_t *pamh = NULL;
struct pam_conv pamc;

pamc.conv = pam_converse;
pamc.appdata_ptr = NULL;

int pam_error = pam_start("exim", argv[1], &pamc, &pamh);

  if (pam_error == PAM_SUCCESS)
  {
    pam_error = pam_authenticate (pamh, PAM_SILENT);
    if (pam_error == PAM_SUCCESS && !pam_conv_had_error)
      pam_error = pam_acct_mgmt (pamh, PAM_SILENT);
  }


pam_end(pamh, PAM_SUCCESS);

  if (pam_error == PAM_SUCCESS) {
    printf("yes\n");
    exit(0);
  } else {
    printf("no\n");
    exit(1);
  }
}