[...]
> >> 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);
}
}