1/************************************************************************ 2 * Modify to taste in order to comply with your authentication * 3 * (e.g. Radius or shadow passwd) and mailbox conventions * 4 * * 5 * You have the liberty to redefine the identity typedef in * 6 * any way you see fit, so that it can hold state information * 7 * you need to authenticate your users * 8 * * 9 * Copyright (c) 1996-1997, S.R. van den Berg, The Netherlands * 10 * Copyright (c) 1999-2001, Philip Guenther, The United States * 11 * of America * 12 * #include "../README" or "README" * 13 ************************************************************************/ 14#ifdef RCS 15static /*const*/char rcsid[]= 16 "$Id: authenticate.c,v 1.10 2001/06/27 17:07:19 guenther Exp $"; 17#endif 18 19#ifdef PROCMAIL 20#include "includes.h" 21#include "robust.h" 22#include "shell.h" 23#include "misc.h" 24#else 25#include "config.h" 26 27#include <sys/types.h> 28#include <unistd.h> 29#include <pwd.h> 30#include <string.h> 31#include <stdlib.h> 32#define bbzero(s,l) memset(s,'\0',l) 33 34#ifdef SHADOW_PASSWD 35#include <shadow.h> 36#endif 37#endif /* PROCMAIL */ 38 39#include "authenticate.h" 40 41#ifndef MAILSPOOLDIR 42#define MAILSPOOLDIR "/var/spool/mail/" /* watch the trailing / */ 43#endif 44#ifndef MAILSPOOLSUFFIX 45#define MAILSPOOLSUFFIX "" /* suffix to force maildir or MH style */ 46#endif 47#ifndef MAILSPOOLHASH 48#define MAILSPOOLHASH 0 /* 2 would deliver to /var/spool/mail/b/a/bar */ 49#endif 50/*#define MAILSPOOLHOME "/.mail" /* watch the leading / */ 51 /* delivers to $HOME/.mail */ 52#define STRLEN(x) (sizeof(x)-1) 53 54struct auth_identity 55{ const struct passwd*pw; 56 char*mbox; 57 int sock; 58}; 59 60static auth_identity authi; /* reuse copy, only one active */ 61 62static void castlower(str)register char*str; /* and I'll take the low road */ 63{ for(;*str;str++) 64 if((unsigned)*str-'A'<='Z'-'A') /* uppercase character? */ 65 *str+='a'-'A'; /* cast it to lowercase */ 66} 67 68static const struct passwd*cgetpwnam(user,sock)const char*const user; 69 const int sock; 70{ return getpwnam(user); /* this should be selfexplanatory :-) */ 71} 72 73static const struct passwd*cgetpwuid(uid,sock)const uid_t uid;const int sock; 74{ return getpwuid(uid); /* no comment */ 75} 76 77/*const*/auth_identity*auth_finduser(user,sock)char*const user;const int sock; 78{ if(!(authi.pw=cgetpwnam(user,sock))) /* /etc/passwd user lookup */ 79 { char*p; 80 if(p=strchr(user,'@')) /* does the username contain an @? */ 81 *p='\0'; /* clueless user using the mailaddress */ 82 castlower(user); /* make it all lowercase (luser problem no. 1) */ 83 if(!(authi.pw=cgetpwnam(user,sock))) /* ok, be nice and try again */ 84 return 0; /* sorry, no such user on this planet */ 85 } 86 authi.sock=sock; /* save the filedescriptor for virtual server separation */ 87 if(authi.mbox) /* any old mailbox reference left? */ 88 free(authi.mbox),authi.mbox=0; /* clear the reference */ 89 return &authi; /* user found */ 90} 91 92/*const*/auth_identity*auth_finduid(uid,sock)const uid_t uid;const int sock; 93{ if(!(authi.pw=cgetpwuid(uid,sock))) /* /etc/passwd user lookup */ 94 return 0; /* nada */ 95 authi.sock=sock; /* save filedescriptor for later perusal */ 96 if(authi.mbox) /* old mailbox reference? */ 97 free(authi.mbox),authi.mbox=0; /* nix old mailbox reference */ 98 return &authi; /* user found */ 99} 100 101#ifndef PROCMAIL 102int auth_checkpassword(pass,pw,allowemptypw)const auth_identity*const pass; 103 const char*const pw;const int allowemptypw; 104{ const char*rpw; 105 rpw=pass->pw->pw_passwd; /* get the regular (encrypted) password */ 106#ifdef SHADOW_PASSWD 107 ;{ struct spwd*spwd; 108 if(spwd=getspnam(pass->pw->pw_name)) /* any shadow password? */ 109 rpw=spwd->sp_pwdp; /* override the regular one */ 110 } 111#endif 112 if(!*rpw) /* empty password found */ 113 return allowemptypw; /* should we allow this? */ 114 return !strcmp(rpw,crypt(pw,rpw)); /* compare the passwords */ 115} 116 117const char*auth_getsecret(pass)const auth_identity*const pass; 118{ return 0; /* no standard way to get a secret, add function here */ 119} 120#else /* PROCMAIL */ 121auth_identity*auth_newid P((void)) 122{ auth_identity*pass; /* create a new auth_identity placeholder */ 123 (pass=malloc(sizeof*pass))->pw=0;pass->mbox=0;return pass; 124} 125 126void auth_copyid(newpass,oldpass)auth_identity*newpass; 127 const auth_identity*oldpass; 128{ struct passwd*np;const struct passwd*op; 129 if(newpass->mbox) 130 free(newpass->mbox),newpass->mbox=0; 131 newpass->sock=oldpass->sock; 132 if(!(np=(struct passwd*)newpass->pw)) 133 { np=(struct passwd*)(newpass->pw=malloc(sizeof*np)); 134 bbzero(np,sizeof*np); 135 } 136 np->pw_uid=(op=oldpass->pw)->pw_uid;np->pw_gid=op->pw_gid; 137 np->pw_name=cstr(np->pw_name,op->pw_name); 138 np->pw_dir=cstr(np->pw_dir,op->pw_dir); 139 np->pw_shell=cstr(np->pw_shell,op->pw_shell); 140#ifndef NOpw_passwd 141 if(op->pw_passwd) 142 bbzero(op->pw_passwd,strlen(op->pw_passwd)); 143#endif 144} 145 146static void auth_zeroout(pass)auth_identity*pass; 147{ struct passwd*p; 148 if(p=(struct passwd*)pass->pw) 149 { bbzero(p->pw_name,strlen(p->pw_name)); 150#ifndef NOpw_passwd 151 if(p->pw_passwd)bbzero(p->pw_passwd,strlen(p->pw_passwd)); 152#endif 153#ifndef NOpw_class 154 if(p->pw_class)bbzero(p->pw_class,strlen(p->pw_class)); 155#endif 156#ifndef NOpw_gecos 157 if(p->pw_gecos)bbzero(p->pw_gecos,strlen(p->pw_gecos)); 158#endif 159 bbzero(p->pw_dir,strlen(p->pw_dir)); 160 bbzero(p->pw_shell,strlen(p->pw_shell)); 161 bbzero(p,sizeof(*p)); 162 } 163 if(pass->mbox) 164 bbzero(pass->mbox,strlen(pass->mbox)); 165} 166 167void auth_freeid(pass)auth_identity*pass; 168{ struct passwd*p; 169 auth_zeroout(pass); 170 if(p=(struct passwd*)pass->pw) 171 free(p->pw_name),free(p->pw_dir),free(p->pw_shell),free(p); 172 if(pass->mbox) 173 free(pass->mbox); 174 free(pass); 175} 176 177int auth_filledid(pass)const auth_identity*pass; 178{ return !!pass->pw; 179} 180#endif /* PROCMAIL */ 181 182const char*auth_mailboxname(pass)auth_identity*const pass; 183{ if(!pass->mbox) 184#ifdef MAILSPOOLHOME 185 { static const char mailfile[]=MAILSPOOLHOME;size_t i; 186 if(!(pass->mbox=malloc((i=strlen(pass->pw->pw_dir))+STRLEN(mailfile)+1))) 187 return ""; 188 strcpy(pass->mbox,pass->pw->pw_dir); 189 strcpy(pass->mbox+i,mailfile); 190#else 191 { static const char mailspooldir[]=MAILSPOOLDIR; 192 if(!(pass->mbox=malloc(STRLEN(mailspooldir)+MAILSPOOLHASH*2+ 193 strlen(pass->pw->pw_name)+1+STRLEN(MAILSPOOLSUFFIX)))) 194 return ""; 195 strcpy(pass->mbox,mailspooldir); 196 ;{ char*p,*n;size_t i;int c; 197 for(p=pass->mbox+STRLEN(mailspooldir),n=pass->pw->pw_name, 198 i=MAILSPOOLHASH;i--;*p++='/') 199 { if(*n) 200 c= *n++; 201 *p++=c; 202 } 203 strcpy(p,pass->pw->pw_name); 204 if(STRLEN(MAILSPOOLSUFFIX)) 205 strcat(p,MAILSPOOLSUFFIX); 206 } 207#endif /* MAILSPOOLHOME */ 208 } 209 return pass->mbox; 210} 211 212uid_t auth_whatuid(pass)const auth_identity*const pass; 213{ return pass->pw->pw_uid; 214} 215 216uid_t auth_whatgid(pass)const auth_identity*const pass; 217{ return pass->pw->pw_gid; 218} 219 220const char*auth_homedir(pass)const auth_identity*const pass; 221{ return pass->pw->pw_dir; 222} 223 224const char*auth_shell(pass)const auth_identity*const pass; 225{ return pass->pw->pw_shell; 226} 227 228const char*auth_username(pass)const auth_identity*const pass; 229{ return pass->pw->pw_name; 230} 231 232void auth_end P((void)) 233{ auth_zeroout(&authi); 234 if(authi.mbox) 235 free(authi.mbox),authi.mbox=0; /* discard the mailbox reference */ 236 endpwent(); 237#ifdef SHADOW_PASSWD 238 endspent(); 239#endif 240} 241