#ifdef RCS
static char rcsid[]=
"$Id: authenticate.c,v 1.10 2001/06/27 17:07:19 guenther Exp $";
#endif
#ifdef PROCMAIL
#include "includes.h"
#include "robust.h"
#include "shell.h"
#include "misc.h"
#else
#include "config.h"
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <string.h>
#include <stdlib.h>
#define bbzero(s,l) memset(s,'\0',l)
#ifdef SHADOW_PASSWD
#include <shadow.h>
#endif
#endif
#include "authenticate.h"
#ifndef MAILSPOOLDIR
#define MAILSPOOLDIR "/var/spool/mail/"
#endif
#ifndef MAILSPOOLSUFFIX
#define MAILSPOOLSUFFIX ""
#endif
#ifndef MAILSPOOLHASH
#define MAILSPOOLHASH 0
#endif
#define STRLEN(x) (sizeof(x)-1)
struct auth_identity
{ const struct passwd*pw;
char*mbox;
int sock;
};
static auth_identity authi;
static void castlower(str)register char*str;
{ for(;*str;str++)
if((unsigned)*str-'A'<='Z'-'A')
*str+='a'-'A';
}
static const struct passwd*cgetpwnam(user,sock)const char*const user;
const int sock;
{ return getpwnam(user);
}
static const struct passwd*cgetpwuid(uid,sock)const uid_t uid;const int sock;
{ return getpwuid(uid);
}
auth_identity*auth_finduser(user,sock)char*const user;const int sock;
{ if(!(authi.pw=cgetpwnam(user,sock)))
{ char*p;
if(p=strchr(user,'@'))
*p='\0';
castlower(user);
if(!(authi.pw=cgetpwnam(user,sock)))
return 0;
}
authi.sock=sock;
if(authi.mbox)
free(authi.mbox),authi.mbox=0;
return &authi;
}
auth_identity*auth_finduid(uid,sock)const uid_t uid;const int sock;
{ if(!(authi.pw=cgetpwuid(uid,sock)))
return 0;
authi.sock=sock;
if(authi.mbox)
free(authi.mbox),authi.mbox=0;
return &authi;
}
#ifndef PROCMAIL
int auth_checkpassword(pass,pw,allowemptypw)const auth_identity*const pass;
const char*const pw;const int allowemptypw;
{ const char*rpw;
rpw=pass->pw->pw_passwd;
#ifdef SHADOW_PASSWD
;{ struct spwd*spwd;
if(spwd=getspnam(pass->pw->pw_name))
rpw=spwd->sp_pwdp;
}
#endif
if(!*rpw)
return allowemptypw;
return !strcmp(rpw,crypt(pw,rpw));
}
const char*auth_getsecret(pass)const auth_identity*const pass;
{ return 0;
}
#else
auth_identity*auth_newid P((void))
{ auth_identity*pass;
(pass=malloc(sizeof*pass))->pw=0;pass->mbox=0;return pass;
}
void auth_copyid(newpass,oldpass)auth_identity*newpass;
const auth_identity*oldpass;
{ struct passwd*np;const struct passwd*op;
if(newpass->mbox)
free(newpass->mbox),newpass->mbox=0;
newpass->sock=oldpass->sock;
if(!(np=(struct passwd*)newpass->pw))
{ np=(struct passwd*)(newpass->pw=malloc(sizeof*np));
bbzero(np,sizeof*np);
}
np->pw_uid=(op=oldpass->pw)->pw_uid;np->pw_gid=op->pw_gid;
np->pw_name=cstr(np->pw_name,op->pw_name);
np->pw_dir=cstr(np->pw_dir,op->pw_dir);
np->pw_shell=cstr(np->pw_shell,op->pw_shell);
#ifndef NOpw_passwd
if(op->pw_passwd)
bbzero(op->pw_passwd,strlen(op->pw_passwd));
#endif
}
static void auth_zeroout(pass)auth_identity*pass;
{ struct passwd*p;
if(p=(struct passwd*)pass->pw)
{ bbzero(p->pw_name,strlen(p->pw_name));
#ifndef NOpw_passwd
if(p->pw_passwd)bbzero(p->pw_passwd,strlen(p->pw_passwd));
#endif
#ifndef NOpw_class
if(p->pw_class)bbzero(p->pw_class,strlen(p->pw_class));
#endif
#ifndef NOpw_gecos
if(p->pw_gecos)bbzero(p->pw_gecos,strlen(p->pw_gecos));
#endif
bbzero(p->pw_dir,strlen(p->pw_dir));
bbzero(p->pw_shell,strlen(p->pw_shell));
bbzero(p,sizeof(*p));
}
if(pass->mbox)
bbzero(pass->mbox,strlen(pass->mbox));
}
void auth_freeid(pass)auth_identity*pass;
{ struct passwd*p;
auth_zeroout(pass);
if(p=(struct passwd*)pass->pw)
free(p->pw_name),free(p->pw_dir),free(p->pw_shell),free(p);
if(pass->mbox)
free(pass->mbox);
free(pass);
}
int auth_filledid(pass)const auth_identity*pass;
{ return !!pass->pw;
}
#endif
const char*auth_mailboxname(pass)auth_identity*const pass;
{ if(!pass->mbox)
#ifdef MAILSPOOLHOME
{ static const char mailfile[]=MAILSPOOLHOME;size_t i;
if(!(pass->mbox=malloc((i=strlen(pass->pw->pw_dir))+STRLEN(mailfile)+1)))
return "";
strcpy(pass->mbox,pass->pw->pw_dir);
strcpy(pass->mbox+i,mailfile);
#else
{ static const char mailspooldir[]=MAILSPOOLDIR;
if(!(pass->mbox=malloc(STRLEN(mailspooldir)+MAILSPOOLHASH*2+
strlen(pass->pw->pw_name)+1+STRLEN(MAILSPOOLSUFFIX))))
return "";
strcpy(pass->mbox,mailspooldir);
;{ char*p,*n;size_t i;int c;
for(p=pass->mbox+STRLEN(mailspooldir),n=pass->pw->pw_name,
i=MAILSPOOLHASH;i--;*p++='/')
{ if(*n)
c= *n++;
*p++=c;
}
strcpy(p,pass->pw->pw_name);
if(STRLEN(MAILSPOOLSUFFIX))
strcat(p,MAILSPOOLSUFFIX);
}
#endif
}
return pass->mbox;
}
uid_t auth_whatuid(pass)const auth_identity*const pass;
{ return pass->pw->pw_uid;
}
uid_t auth_whatgid(pass)const auth_identity*const pass;
{ return pass->pw->pw_gid;
}
const char*auth_homedir(pass)const auth_identity*const pass;
{ return pass->pw->pw_dir;
}
const char*auth_shell(pass)const auth_identity*const pass;
{ return pass->pw->pw_shell;
}
const char*auth_username(pass)const auth_identity*const pass;
{ return pass->pw->pw_name;
}
void auth_end P((void))
{ auth_zeroout(&authi);
if(authi.mbox)
free(authi.mbox),authi.mbox=0;
endpwent();
#ifdef SHADOW_PASSWD
endspent();
#endif
}