File: authenticate.c

package info (click to toggle)
procmail 3.22-24
  • links: PTS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,104 kB
  • sloc: ansic: 9,885; sh: 1,957; makefile: 132
file content (240 lines) | stat: -rw-r--r-- 7,459 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/************************************************************************
 *	Modify to taste in order to comply with your authentication	*
 *	(e.g. Radius or shadow passwd) and mailbox conventions		*
 *									*
 *	You have the liberty to redefine the identity typedef in	*
 *	any way you see fit, so that it can hold state information	*
 *	you need to authenticate your users				*
 *									*
 *	Copyright (c) 1996-1997, S.R. van den Berg, The Netherlands	*
 *	Copyright (c) 1999-2001, Philip Guenther, The United States	*
 *						of America		*
 *	#include "../README" or "README"				*
 ************************************************************************/
#ifdef RCS
static /*const*/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 /* PROCMAIL */

#include "authenticate.h"

#ifndef MAILSPOOLDIR
#define MAILSPOOLDIR	"/var/mail/"	     /* watch the trailing / */
#endif
#ifndef MAILSPOOLSUFFIX
#define MAILSPOOLSUFFIX ""	      /* suffix to force maildir or MH style */
#endif
#ifndef MAILSPOOLHASH
#define MAILSPOOLHASH	0      /* 2 would deliver to /var/mail/b/a/bar */
#endif
/*#define MAILSPOOLHOME "/.mail"		      /* watch the leading / */
						  /* delivers to $HOME/.mail */
#define STRLEN(x)	(sizeof(x)-1)

struct auth_identity
{ const struct passwd*pw;
  char*mbox;
  int sock;
};

static auth_identity authi;		      /* reuse copy, only one active */

static void castlower(str)register char*str;   /* and I'll take the low road */
{ for(;*str;str++)
     if((unsigned)*str-'A'<='Z'-'A')		     /* uppercase character? */
	*str+='a'-'A';				     /* cast it to lowercase */
}

static const struct passwd*cgetpwnam(user,sock)const char*const user;
 const int sock;
{ return getpwnam(user);	       /* this should be selfexplanatory :-) */
}

static const struct passwd*cgetpwuid(uid,sock)const uid_t uid;const int sock;
{ return getpwuid(uid);					       /* no comment */
}

/*const*/auth_identity*auth_finduser(user,sock)char*const user;const int sock;
{ if(!(authi.pw=cgetpwnam(user,sock)))		  /* /etc/passwd user lookup */
   { char*p;
     if(p=strchr(user,'@'))		  /* does the username contain an @? */
	*p='\0';		      /* clueless user using the mailaddress */
     castlower(user);	      /* make it all lowercase (luser problem no. 1) */
     if(!(authi.pw=cgetpwnam(user,sock)))	/* ok, be nice and try again */
	return 0;		       /* sorry, no such user on this planet */
   }
  authi.sock=sock;  /* save the filedescriptor for virtual server separation */
  if(authi.mbox)			  /* any old mailbox reference left? */
     free(authi.mbox),authi.mbox=0;		      /* clear the reference */
  return &authi;					       /* user found */
}

/*const*/auth_identity*auth_finduid(uid,sock)const uid_t uid;const int sock;
{ if(!(authi.pw=cgetpwuid(uid,sock)))		  /* /etc/passwd user lookup */
     return 0;							     /* nada */
  authi.sock=sock;		    /* save filedescriptor for later perusal */
  if(authi.mbox)				   /* old mailbox reference? */
     free(authi.mbox),authi.mbox=0;		/* nix old mailbox reference */
  return &authi;					       /* user found */
}

#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;	     /* get the regular (encrypted) password */
#ifdef SHADOW_PASSWD
  ;{ struct spwd*spwd;
     if(spwd=getspnam(pass->pw->pw_name))	     /* any shadow password? */
	rpw=spwd->sp_pwdp;			 /* override the regular one */
   }
#endif
  if(!*rpw)					     /* empty password found */
     return allowemptypw;			    /* should we allow this? */
  return !strcmp(rpw,crypt(pw,rpw));		    /* compare the passwords */
}

const char*auth_getsecret(pass)const auth_identity*const pass;
{ return 0;	       /* no standard way to get a secret, add function here */
}
#else /* PROCMAIL */
auth_identity*auth_newid P((void))
{ auth_identity*pass;		   /* create a new auth_identity placeholder */
  (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 /* PROCMAIL */

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 /* MAILSPOOLHOME */
   }
  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;	    /* discard the mailbox reference */
  endpwent();
#ifdef SHADOW_PASSWD
  endspent();
#endif
}