On Mon, Nov 17, 2003 at 10:23:32AM -0800, Keith wrote:
>
> Hello,
> After many unsuccessful hours, I have resorted to
> this list in the hope of finding an answer to this
> question:
>
> How to change the courier-imap MAILDIR env variable
> from the default $HOME/Maildir to
> '/var/spool/mail/$USERNAME/Maildir' (for example),
> when courier-imap is using the authpam authentication
> module?
I had to do this since my department uses nfs home directories extensively. I
didn't want someone's email deferred because there was a power failure or
their machine goes down. Anyway here's the code to do it. It's from
courier-0.37.3 source, so you may have to make a modification to it. It works
great, but I'm not entirely sure that the code is all done "properly." Just
two files you have to change. base/authlib/authpam.c and
base/authlib/preauthpam.c
I'll just include the source code as attachments. The prefix I made is
/var/spool/mail/courier/juser/Maildir and I have soft links in
/var/spool/mail/juser -> /var/spool/mail/courier/juser/Maildir so that
any user can use pine and mutt with maildir support and /var/spool/mail
is distributed on nfs.
>
> The manual [1] hints that a MAILDIR environment
> variable can be set: "3. Some additional environment
> variables may also be initialized: AUTHFULLNAME - the
> login ID's full name; MAILDIR - the login ID's default
> maildir mailbox; MAILDIRQUOTA - the requested maildir
> quota." However it is unclear (to me) how this can be
> accomplished when authenticating using authpam.
> Documentation examples I could find seem to centre on
> other authentication modules.
>
> The discussion here [2] suggests editing the imapd
> startup script, while here [3] the suggestions point
> to trying to set the MAILDIR environment variable
> using pam_env. As with the people in these posts, I
> have also not had much success using these
> suggestions.
>
> Symbolic linking $HOME/Maildir is not an option,
> and I cannot switch to use a different authentication
> module.
>
> Any suggestions or ideas on setting this MAILDIR
> environment variable for authpam authentication are
> very welcome!
>
> Cheers,
>
> Keith Nelson.
>
> [1] http://www.courier-mta.org/authlib.html
> [2]
> http://www.mail-archive.com/[EMAIL PROTECTED]/msg09986.html
> [3]
> http://www.mail-archive.com/[EMAIL PROTECTED]/msg14029.html
>
>
> __________________________________
> Do you Yahoo!?
> Protect your identity with Yahoo! Mail AddressGuard
> http://antispam.yahoo.com/whatsnewfree
>
>
> -------------------------------------------------------
> This SF. Net email is sponsored by: GoToMyPC
> GoToMyPC is the fast, easy and secure way to access your computer from
> any Web browser or wireless device. Click here to Try it Free!
> https://www.gotomypc.com/tr/OSDN/AW/Q4_2003/t/g22lp?Target=mm/g22lp.tmpl
> _______________________________________________
> courier-users mailing list
> [EMAIL PROTECTED]
> Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-users
--
EECS Systems Staff
-Michael Woods
/*
** Copyright 1998 - 2001 Double Precision, Inc. See COPYING for
** distribution information.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "auth.h"
#include "authmod.h"
#include "authwait.h"
#include "authstaticlist.h"
#if HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
#endif
#if HAVE_PAM_PAM_APPL_H
#include <Pam/pam_appl.h>
#endif
static const char rcsid[]="$Id: authpam.c,v 1.13 2001/06/16 22:16:25 mrsam Exp $";
static const char *pam_username, *pam_password, *pam_service;
static int pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int i = 0;
struct pam_response *repl = NULL;
repl = malloc(sizeof(struct pam_response) * num_msg);
if (!repl) return PAM_CONV_ERR;
for (i=0; i<num_msg; i++)
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_ON:
repl[i].resp_retcode = PAM_SUCCESS;
repl[i].resp = strdup(pam_username);
if (!repl[i].resp)
{
perror("strdup");
authexit(1);
}
break;
case PAM_PROMPT_ECHO_OFF:
repl[i].resp_retcode = PAM_SUCCESS;
repl[i].resp = strdup(pam_password);
if (!repl[i].resp)
{
perror("strdup");
authexit(1);
}
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
write(2, msg[i]->msg, strlen(msg[i]->msg));
write(2, "\n", 1);
repl[i].resp_retcode = PAM_SUCCESS;
repl[i].resp = NULL;
break;
default:
free (repl);
return PAM_CONV_ERR;
}
*resp=repl;
return PAM_SUCCESS;
}
static struct pam_conv conv = {
pam_conv,
NULL
};
static int dopam(pam_handle_t **pamh)
{
int retval;
retval=pam_start(pam_service, pam_username, &conv, pamh);
#if 0
if (retval == PAM_SUCCESS)
retval=pam_set_item(*pamh, PAM_AUTHTOK, pam_password);
#endif
if (retval == PAM_SUCCESS)
retval=pam_authenticate(*pamh, 0);
#if 0
#if HAVE_PAM_SETCRED
if (retval == PAM_SUCCESS)
retval=pam_setcred(*pamh, PAM_ESTABLISH_CRED);
#endif
if (retval == PAM_SUCCESS)
retval=pam_acct_mgmt(*pamh, 0);
#endif
return (retval);
}
struct callback_info {
char *username;
int issession;
void (*callback_func)(struct authinfo *, void *);
void *callback_arg;
} ;
static int callback_pam(struct authinfo *a, void *argptr)
{
struct callback_info *ci=(struct callback_info *)argptr;
pam_handle_t *pamh=NULL;
int pipefd[2];
int retval;
pid_t p;
int waitstat;
char *s;
// add these
char *alloc_buf;
char prepend[25];
s=strdup(a->sysusername);
if (!s)
{
perror("malloc");
return (1);
}
if (!ci->issession && /* Thankfully, no session voodoo needed this time */
ci->callback_func == 0)
{
retval=dopam(&pamh);
if (retval == PAM_SUCCESS)
{
if (pam_end(pamh, retval) != PAM_SUCCESS)
perror("Unable to release PAM tokens");
if (ci->callback_func == 0){
// changes made here
strcpy( prepend, "/var/spool/mail/courier/" );
alloc_buf=malloc(strlen(a->sysusername)+strlen(prepend)+2);
strcat(strcpy(alloc_buf, prepend), a->sysusername);
authsuccess(alloc_buf,
//
a->sysusername,
0,
&a->sysgroupid,
a->address,
a->fullname);
}
ci->username=s;
putenv("MAILDIR=");
return (0);
}
free(s);
free(alloc_buf);
if (pam_end(pamh, retval) != PAM_SUCCESS)
perror("Unable to release PAM tokens");
return (-1);
}
/*
** OK, in order to transparently support PAM sessions inside this
** authentication module, what we need to do is to fork(), and let
** the child run in its parent place. Once the child process exits,
** the parent calls pam_end_session, and clears the PAM library.
**
** This means that upon return from auth_pam(), your process ID
** might've changed!!!
**
** However, if the authentication fails, we can simply exit, without
** running as a child process.
**
** Additionally, the PAM library might allocate some resources that
** authenticated clients should not access. Therefore, we fork
** *before* we try to authenticate. If the authentication succeeds,
** the child process will run in the parent's place. The child
** process waits until the parent tells it whether the authentication
** worked. If it worked, the child keeps running. If not, the child
** exits, which the parent waits for.
**
** The authentication status is communicated to the child process via
** a pipe.
*/
if (pipe(pipefd) < 0)
{
perror("pipe");
free(s);
return (1);
}
if ((p=fork()) == -1)
{
perror("fork");
free(s);
return (1);
}
if (p == 0)
{
char dummy;
if (ci->callback_func) /* PAM memory leak */
{
close(pipefd[0]);
retval=dopam(&pamh);
if (retval == PAM_SUCCESS)
write(pipefd[1], "", 1);
close(pipefd[1]);
_exit(0);
}
close(pipefd[1]);
if (read(pipefd[0], &dummy, 1) != 1 || dummy)
authexit(1); /* Authentication failed by parent */
close(pipefd[0]);
putenv("MAILDIR=");
// here again
strcpy( prepend, "/var/spool/mail/courier/" );
alloc_buf=malloc(strlen(a->sysusername)+strlen(prepend)+2);
strcat(strcpy(alloc_buf, prepend), a->sysusername);
authsuccess(alloc_buf,
//
a->sysusername,
0,
&a->sysgroupid,
a->address,
a->fullname);
ci->username=s;
if (ci->callback_func)
{
a->address=s;
(*ci->callback_func)(a, ci->callback_arg);
}
return (0);
}
if (ci->callback_func)
{
char buf[1];
close(pipefd[1]);
while (wait(&waitstat) != p)
;
if (read(pipefd[0], buf, 1) > 0)
{
close(pipefd[0]);
a->address=s;
ci->username=s;
(*ci->callback_func)(a, ci->callback_arg);
return (0);
}
close(pipefd[0]);
free(s);
return (-1);
}
free(alloc_buf);
free(s);
close(pipefd[0]);
retval=dopam(&pamh);
if (retval == PAM_SUCCESS)
retval=pam_open_session(pamh, 0);
if (retval != PAM_SUCCESS)
{
if (pam_end(pamh, retval) != PAM_SUCCESS)
perror("Unable to release PAM tokens");
/* Wait for child to terminate */
close(pipefd[1]); /* Tell the child to shut down */
while (wait(&waitstat) != p)
;
return (-1);
}
/* Tell child process to run in authenticated state */
write(pipefd[1], "", 1);
close(pipefd[1]);
/* Wait for child process to finish */
while (wait(&waitstat) != p)
;
retval=pam_close_session(pamh, 0);
if (retval != PAM_SUCCESS)
perror("pam_close_session");
if (pam_end(pamh, retval) != PAM_SUCCESS)
perror("Unable to release PAM tokens");
if (WIFEXITED(waitstat))
authexit(WEXITSTATUS(waitstat));
authexit(255);
return (1);
}
extern int auth_pam_pre(const char *userid, const char *service,
int (*callback)(struct authinfo *, void *),
void *arg);
char *auth_pam(const char *service, const char *type, char *authdata,
int issession,
void (*callback_func)(struct authinfo *, void *), void *callback_arg)
{
struct callback_info ci;
int rc;
if (strcmp(type, AUTHTYPE_LOGIN) ||
(pam_username=strtok(authdata, "\n")) == 0 ||
(pam_password=strtok(0, "\n")) == 0)
{
errno=EPERM;
return (0);
}
pam_service=service;
ci.issession=issession;
ci.callback_func=callback_func;
ci.callback_arg=callback_arg;
rc=auth_pam_pre(pam_username, service, &callback_pam, &ci);
if (rc) return (0);
return (ci.username);
}
static void auth_pam_cleanup()
{
}
struct authstaticinfo authpam_info={
"authpam",
auth_pam,
auth_pam_pre,
auth_pam_cleanup,
auth_syspasswd};
/*
** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
** distribution information.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pwd.h>
#include "auth.h"
#if HAVE_SHADOW_H
#include <shadow.h>
#endif
static const char rcsid[]="$Id: preauthpam.c,v 1.8 2001/12/22 21:25:13 mrsam Exp $";
int auth_pam_pre(const char *userid, const char *service,
int (*callback)(struct authinfo *, void *),
void *arg)
{
struct authinfo auth;
struct passwd *pw;
// added these
char *alloc_buf;
char prepend[25];
#if HAVE_GETSPENT
struct spwd *spw;
#endif
memset(&auth, 0, sizeof(auth));
if ((pw=getpwnam(userid)) == 0)
{
if (errno == ENOMEM) return (1);
errno=EPERM;
return (-1);
}
// changes made here
strcpy( prepend, "/var/spool/mail/courier/" );
alloc_buf=malloc(strlen(userid)+strlen(prepend)+2);
strcat(strcpy(alloc_buf, prepend), userid);
auth.sysusername=userid;
auth.sysgroupid=pw->pw_gid;
auth.homedir=alloc_buf;
//
auth.address=userid;
auth.fullname=pw->pw_gecos;
auth.passwd=pw->pw_passwd;
#if HAVE_GETSPENT
if ((spw=getspnam(userid)) != 0)
auth.passwd=spw->sp_pwdp;
#endif
free(alloc_buf);
return ((*callback)(&auth, arg));
}