xref: /plan9/sys/src/cmd/auth/warning.c (revision f54edc786b9c49b2c7ab1c0695cdc8c698b11f4d)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include <auth.h>
59a747e4fSDavid du Colombier #include "authcmdlib.h"
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier /* working directory */
8219b2ee8SDavid du Colombier Dir	*dirbuf;
9219b2ee8SDavid du Colombier long	ndirbuf = 0;
10219b2ee8SDavid du Colombier 
11219b2ee8SDavid du Colombier int debug;
12219b2ee8SDavid du Colombier 
13219b2ee8SDavid du Colombier long	readdirect(int);
14219b2ee8SDavid du Colombier void	douser(Fs*, char*);
15219b2ee8SDavid du Colombier void	dodir(Fs*);
16219b2ee8SDavid du Colombier int	mail(Fs*, char*, char*, long);
17219b2ee8SDavid du Colombier int	mailin(Fs*, char*, long, char*, char*);
18219b2ee8SDavid du Colombier void	complain(char*, ...);
19219b2ee8SDavid du Colombier long	readnumfile(char*);
20219b2ee8SDavid du Colombier void	writenumfile(char*, long);
21219b2ee8SDavid du Colombier 
22219b2ee8SDavid du Colombier void
usage(void)23219b2ee8SDavid du Colombier usage(void)
24219b2ee8SDavid du Colombier {
257dd7cddfSDavid du Colombier 	fprint(2, "usage: %s [-n] [-p]\n", argv0);
26219b2ee8SDavid du Colombier 	exits("usage");
27219b2ee8SDavid du Colombier }
28219b2ee8SDavid du Colombier 
29219b2ee8SDavid du Colombier void
main(int argc,char ** argv)30219b2ee8SDavid du Colombier main(int argc, char **argv)
31219b2ee8SDavid du Colombier {
32219b2ee8SDavid du Colombier 	int which;
33219b2ee8SDavid du Colombier 
34219b2ee8SDavid du Colombier 	which = 0;
35219b2ee8SDavid du Colombier 	ARGBEGIN{
36219b2ee8SDavid du Colombier 	case 'p':
37219b2ee8SDavid du Colombier 		which |= Plan9;
38219b2ee8SDavid du Colombier 		break;
39219b2ee8SDavid du Colombier 	case 'n':
40219b2ee8SDavid du Colombier 		which |= Securenet;
41219b2ee8SDavid du Colombier 		break;
42219b2ee8SDavid du Colombier 	case 'd':
43219b2ee8SDavid du Colombier 		debug++;
44219b2ee8SDavid du Colombier 		break;
45219b2ee8SDavid du Colombier 	default:
46219b2ee8SDavid du Colombier 		usage();
47219b2ee8SDavid du Colombier 	}ARGEND
48219b2ee8SDavid du Colombier 	argv0 = "warning";
49219b2ee8SDavid du Colombier 
50219b2ee8SDavid du Colombier 	if(!which)
51219b2ee8SDavid du Colombier 		which |= Plan9 | Securenet;
52219b2ee8SDavid du Colombier 	if(which & Plan9)
53219b2ee8SDavid du Colombier 		dodir(&fs[Plan9]);
54219b2ee8SDavid du Colombier 	if(which & Securenet)
55219b2ee8SDavid du Colombier 		dodir(&fs[Securenet]);
56219b2ee8SDavid du Colombier }
57219b2ee8SDavid du Colombier 
58219b2ee8SDavid du Colombier void
dodir(Fs * f)59219b2ee8SDavid du Colombier dodir(Fs *f)
60219b2ee8SDavid du Colombier {
61219b2ee8SDavid du Colombier 	int nfiles;
62219b2ee8SDavid du Colombier 	int i, fd;
63219b2ee8SDavid du Colombier 
64219b2ee8SDavid du Colombier 	if(chdir(f->keys) < 0){
65219b2ee8SDavid du Colombier 		complain("can't chdir to %s: %r", f->keys);
66219b2ee8SDavid du Colombier 		return;
67219b2ee8SDavid du Colombier 	}
68219b2ee8SDavid du Colombier  	fd = open(".", OREAD);
69219b2ee8SDavid du Colombier 	if(fd < 0){
70219b2ee8SDavid du Colombier 		complain("can't open %s: %r\n", f->keys);
71219b2ee8SDavid du Colombier 		return;
72219b2ee8SDavid du Colombier 	}
739a747e4fSDavid du Colombier 	nfiles = dirreadall(fd, &dirbuf);
74219b2ee8SDavid du Colombier 	close(fd);
75219b2ee8SDavid du Colombier 	for(i = 0; i < nfiles; i++)
76219b2ee8SDavid du Colombier 		douser(f, dirbuf[i].name);
77219b2ee8SDavid du Colombier }
78219b2ee8SDavid du Colombier 
79219b2ee8SDavid du Colombier /*
80219b2ee8SDavid du Colombier  *  check for expiration
81219b2ee8SDavid du Colombier  */
82219b2ee8SDavid du Colombier void
douser(Fs * f,char * user)83219b2ee8SDavid du Colombier douser(Fs *f, char *user)
84219b2ee8SDavid du Colombier {
85219b2ee8SDavid du Colombier 	int n, nwarn;
869a747e4fSDavid du Colombier 	char buf[128];
87219b2ee8SDavid du Colombier 	long rcvrs, et, now;
88219b2ee8SDavid du Colombier 	char *l;
89219b2ee8SDavid du Colombier 
90*f54edc78SDavid du Colombier 	snprint(buf, sizeof buf, "%s/expire", user);
91219b2ee8SDavid du Colombier 	et = readnumfile(buf);
92219b2ee8SDavid du Colombier 	now = time(0);
93219b2ee8SDavid du Colombier 
94219b2ee8SDavid du Colombier 	/* start warning 2 weeks ahead of time */
95219b2ee8SDavid du Colombier 	if(et <= now || et > now+14*24*60*60)
96219b2ee8SDavid du Colombier 		return;
97219b2ee8SDavid du Colombier 
98*f54edc78SDavid du Colombier 	snprint(buf, sizeof buf, "%s/warnings", user);
99219b2ee8SDavid du Colombier 	nwarn = readnumfile(buf);
100219b2ee8SDavid du Colombier 	if(et <= now+14*24*60*60 && et > now+7*24*60*60){
101219b2ee8SDavid du Colombier 		/* one warning 2 weeks before expiration */
102219b2ee8SDavid du Colombier 		if(nwarn > 0)
103219b2ee8SDavid du Colombier 			return;
104219b2ee8SDavid du Colombier 		nwarn = 1;
105219b2ee8SDavid du Colombier 	} else {
106219b2ee8SDavid du Colombier 		/* one warning 1 week before expiration */
107219b2ee8SDavid du Colombier 		if(nwarn > 1)
108219b2ee8SDavid du Colombier 			return;
109219b2ee8SDavid du Colombier 		nwarn = 2;
110219b2ee8SDavid du Colombier 	}
111219b2ee8SDavid du Colombier 
112219b2ee8SDavid du Colombier 	/*
113219b2ee8SDavid du Colombier 	 *  if we can't open the who file, just mail to the user and hope
114219b2ee8SDavid du Colombier  	 *  for it makes it.
115219b2ee8SDavid du Colombier 	 */
116219b2ee8SDavid du Colombier 	if(f->b){
117219b2ee8SDavid du Colombier 		if(Bseek(f->b, 0, 0) < 0){
118219b2ee8SDavid du Colombier 			Bterm(f->b);
119219b2ee8SDavid du Colombier 			f->b = 0;
120219b2ee8SDavid du Colombier 		}
121219b2ee8SDavid du Colombier 	}
122219b2ee8SDavid du Colombier 	if(f->b == 0){
123219b2ee8SDavid du Colombier 		f->b = Bopen(f->who, OREAD);
124219b2ee8SDavid du Colombier 		if(f->b == 0){
125219b2ee8SDavid du Colombier 			if(mail(f, user, user, et) > 0)
126219b2ee8SDavid du Colombier 				writenumfile(buf, nwarn);
127219b2ee8SDavid du Colombier 			return;
128219b2ee8SDavid du Colombier 		}
129219b2ee8SDavid du Colombier 	}
130219b2ee8SDavid du Colombier 
131219b2ee8SDavid du Colombier 	/*
132219b2ee8SDavid du Colombier 	 *  look for matches in the who file and mail to every address on
133219b2ee8SDavid du Colombier 	 *  matching lines
134219b2ee8SDavid du Colombier 	 */
135219b2ee8SDavid du Colombier 	rcvrs = 0;
136219b2ee8SDavid du Colombier 	while(l = Brdline(f->b, '\n')){
137219b2ee8SDavid du Colombier 		n = strlen(user);
138219b2ee8SDavid du Colombier 		if(strncmp(l, user, n) == 0 && (l[n] == ' ' || l[n] == '\t'))
139219b2ee8SDavid du Colombier 			rcvrs += mailin(f, user, et, l, l+Blinelen(f->b));
140219b2ee8SDavid du Colombier 	}
141219b2ee8SDavid du Colombier 
142219b2ee8SDavid du Colombier 	/*
143219b2ee8SDavid du Colombier 	 *  if no matches, try the user directly
144219b2ee8SDavid du Colombier 	 */
145219b2ee8SDavid du Colombier 	if(rcvrs == 0)
146219b2ee8SDavid du Colombier 		rcvrs = mail(f, user, user, et);
147219b2ee8SDavid du Colombier 	rcvrs += mail(f, "netkeys", user, et);
148219b2ee8SDavid du Colombier 	if(rcvrs)
149219b2ee8SDavid du Colombier 		writenumfile(buf, nwarn);
150219b2ee8SDavid du Colombier }
151219b2ee8SDavid du Colombier 
152219b2ee8SDavid du Colombier /*
153219b2ee8SDavid du Colombier  *  anything in <>'s is an address
154219b2ee8SDavid du Colombier  */
155219b2ee8SDavid du Colombier int
mailin(Fs * f,char * user,long et,char * l,char * e)156219b2ee8SDavid du Colombier mailin(Fs *f, char *user, long et, char *l, char *e)
157219b2ee8SDavid du Colombier {
158219b2ee8SDavid du Colombier 	int n;
159219b2ee8SDavid du Colombier 	int rcvrs;
160219b2ee8SDavid du Colombier 	char *p;
161219b2ee8SDavid du Colombier 	char addr[256];
162219b2ee8SDavid du Colombier 
163219b2ee8SDavid du Colombier 	p = 0;
164219b2ee8SDavid du Colombier 	rcvrs = 0;
165219b2ee8SDavid du Colombier 	while(l < e){
166219b2ee8SDavid du Colombier 		switch(*l){
167219b2ee8SDavid du Colombier 		case '<':
168219b2ee8SDavid du Colombier 			p = l + 1;
169219b2ee8SDavid du Colombier 			break;
170219b2ee8SDavid du Colombier 		case '>':
171219b2ee8SDavid du Colombier 			if(p == 0)
172219b2ee8SDavid du Colombier 				break;
173219b2ee8SDavid du Colombier 			n = l - p;
174219b2ee8SDavid du Colombier 			if(n > 0 && n <= sizeof(addr) - 2){
175219b2ee8SDavid du Colombier 				memmove(addr, p, n);
176219b2ee8SDavid du Colombier 				addr[n] = 0;
177219b2ee8SDavid du Colombier 				rcvrs += mail(f, addr, user, et);
178219b2ee8SDavid du Colombier 			}
179219b2ee8SDavid du Colombier 			p = 0;
180219b2ee8SDavid du Colombier 			break;
181219b2ee8SDavid du Colombier 		}
182219b2ee8SDavid du Colombier 		l++;
183219b2ee8SDavid du Colombier 	}
184219b2ee8SDavid du Colombier 	return rcvrs;
185219b2ee8SDavid du Colombier }
186219b2ee8SDavid du Colombier 
187219b2ee8SDavid du Colombier /*
188219b2ee8SDavid du Colombier  *  send mail
189219b2ee8SDavid du Colombier  */
190219b2ee8SDavid du Colombier int
mail(Fs * f,char * rcvr,char * user,long et)191219b2ee8SDavid du Colombier mail(Fs *f, char *rcvr, char *user, long et)
192219b2ee8SDavid du Colombier {
1937dd7cddfSDavid du Colombier 	int pid, i, fd;
194219b2ee8SDavid du Colombier 	int pfd[2];
195219b2ee8SDavid du Colombier 	char *ct, *p;
1969a747e4fSDavid du Colombier 	Waitmsg *w;
1977dd7cddfSDavid du Colombier 	char buf[128];
198219b2ee8SDavid du Colombier 
199219b2ee8SDavid du Colombier 	if(pipe(pfd) < 0){
200219b2ee8SDavid du Colombier 		complain("out of pipes: %r");
201219b2ee8SDavid du Colombier 		return 0;
202219b2ee8SDavid du Colombier 	}
203219b2ee8SDavid du Colombier 
2047dd7cddfSDavid du Colombier 	switch(pid = fork()){
205219b2ee8SDavid du Colombier 	case -1:
206219b2ee8SDavid du Colombier 		complain("can't fork: %r");
207219b2ee8SDavid du Colombier 		return 0;
208219b2ee8SDavid du Colombier 	case 0:
209219b2ee8SDavid du Colombier 		break;
210219b2ee8SDavid du Colombier 	default:
2117dd7cddfSDavid du Colombier 		if(debug)
2127dd7cddfSDavid du Colombier 			fprint(2, "started %d\n", pid);
213219b2ee8SDavid du Colombier 		close(pfd[0]);
214219b2ee8SDavid du Colombier 		ct = ctime(et);
215219b2ee8SDavid du Colombier 		p = strchr(ct, '\n');
216219b2ee8SDavid du Colombier 		*p = '.';
217219b2ee8SDavid du Colombier 		fprint(pfd[1], "User '%s's %s expires on %s\n", user, f->msg, ct);
218219b2ee8SDavid du Colombier 		if(f != fs)
219219b2ee8SDavid du Colombier 			fprint(pfd[1], "If you wish to renew contact your local administrator.\n");
2207dd7cddfSDavid du Colombier 		p = strrchr(f->keys, '/');
2217dd7cddfSDavid du Colombier 		if(p)
2227dd7cddfSDavid du Colombier 			p++;
2237dd7cddfSDavid du Colombier 		else
2247dd7cddfSDavid du Colombier 			p = f->keys;
225*f54edc78SDavid du Colombier 		snprint(buf, sizeof buf, "/adm/warn.%s", p);
2267dd7cddfSDavid du Colombier 		fd = open(buf, OREAD);
2277dd7cddfSDavid du Colombier 		if(fd >= 0){
2287dd7cddfSDavid du Colombier 			while((i = read(fd, buf, sizeof(buf))) > 0)
2297dd7cddfSDavid du Colombier 				write(pfd[1], buf, i);
2307dd7cddfSDavid du Colombier 			close(fd);
2317dd7cddfSDavid du Colombier 		}
232219b2ee8SDavid du Colombier 		close(pfd[1]);
233219b2ee8SDavid du Colombier 
2347dd7cddfSDavid du Colombier 		/* wait for warning to be mailed */
235219b2ee8SDavid du Colombier 		for(;;){
2369a747e4fSDavid du Colombier 			w = wait();
2379a747e4fSDavid du Colombier 			if(w == nil)
238219b2ee8SDavid du Colombier 				break;
2399a747e4fSDavid du Colombier 			if(w->pid == pid){
2407dd7cddfSDavid du Colombier 				if(debug)
2419a747e4fSDavid du Colombier 					fprint(2, "%d terminated: %s\n", pid, w->msg);
2429a747e4fSDavid du Colombier 				if(w->msg[0] == 0){
2439a747e4fSDavid du Colombier 					free(w);
244219b2ee8SDavid du Colombier 					break;
2459a747e4fSDavid du Colombier 				}else{
2469a747e4fSDavid du Colombier 					free(w);
247219b2ee8SDavid du Colombier 					return 0;
248219b2ee8SDavid du Colombier 				}
2499a747e4fSDavid du Colombier 			}else
2509a747e4fSDavid du Colombier 				free(w);
251219b2ee8SDavid du Colombier 		}
252219b2ee8SDavid du Colombier 		return 1;
253219b2ee8SDavid du Colombier 	}
254219b2ee8SDavid du Colombier 
255219b2ee8SDavid du Colombier 	/* get out of the current namespace */
256219b2ee8SDavid du Colombier 	newns("none", 0);
257219b2ee8SDavid du Colombier 
258219b2ee8SDavid du Colombier 	dup(pfd[0], 0);
259219b2ee8SDavid du Colombier 	close(pfd[0]);
260219b2ee8SDavid du Colombier 	close(pfd[1]);
261219b2ee8SDavid du Colombier 	putenv("upasname", "netkeys");
262219b2ee8SDavid du Colombier 	if(debug){
263219b2ee8SDavid du Colombier 		print("\nto %s\n", rcvr);
264f19e7b74SDavid du Colombier 		execl("/bin/cat", "cat", nil);
265219b2ee8SDavid du Colombier 	}
266f19e7b74SDavid du Colombier 	execl("/bin/upas/send", "send", "-r", rcvr, nil);
267219b2ee8SDavid du Colombier 
268219b2ee8SDavid du Colombier 	/* just in case */
269d854de59SDavid du Colombier 	sysfatal("can't exec send: %r");
270219b2ee8SDavid du Colombier 
271219b2ee8SDavid du Colombier 	return 0;		/* for compiler */
272219b2ee8SDavid du Colombier }
273219b2ee8SDavid du Colombier 
274219b2ee8SDavid du Colombier void
complain(char * fmt,...)275219b2ee8SDavid du Colombier complain(char *fmt, ...)
276219b2ee8SDavid du Colombier {
277219b2ee8SDavid du Colombier 	char buf[8192], *s;
2787dd7cddfSDavid du Colombier 	va_list arg;
279219b2ee8SDavid du Colombier 
280219b2ee8SDavid du Colombier 	s = buf;
281*f54edc78SDavid du Colombier 	s += snprint(s, sizeof buf, "%s: ", argv0);
2827dd7cddfSDavid du Colombier 	va_start(arg, fmt);
2839a747e4fSDavid du Colombier 	s = vseprint(s, buf + sizeof(buf) / sizeof(*buf), fmt, arg);
2847dd7cddfSDavid du Colombier 	va_end(arg);
285219b2ee8SDavid du Colombier 	*s++ = '\n';
286219b2ee8SDavid du Colombier 	write(2, buf, s - buf);
287219b2ee8SDavid du Colombier }
288219b2ee8SDavid du Colombier 
289219b2ee8SDavid du Colombier long
readnumfile(char * file)290219b2ee8SDavid du Colombier readnumfile(char *file)
291219b2ee8SDavid du Colombier {
292219b2ee8SDavid du Colombier 	int fd, n;
293219b2ee8SDavid du Colombier 	char buf[64];
294219b2ee8SDavid du Colombier 
295219b2ee8SDavid du Colombier 	fd = open(file, OREAD);
296219b2ee8SDavid du Colombier 	if(fd < 0){
29772783476SDavid du Colombier 		complain("can't open %s: %r", file);
298219b2ee8SDavid du Colombier 		return 0;
299219b2ee8SDavid du Colombier 	}
300219b2ee8SDavid du Colombier 	n = read(fd, buf, sizeof(buf)-1);
301219b2ee8SDavid du Colombier 	close(fd);
302219b2ee8SDavid du Colombier 	if(n < 0){
30372783476SDavid du Colombier 		complain("can't read %s: %r", file);
304219b2ee8SDavid du Colombier 		return 0;
305219b2ee8SDavid du Colombier 	}
306219b2ee8SDavid du Colombier 	buf[n] = 0;
307219b2ee8SDavid du Colombier 	return atol(buf);
308219b2ee8SDavid du Colombier }
309219b2ee8SDavid du Colombier 
310219b2ee8SDavid du Colombier void
writenumfile(char * file,long num)311219b2ee8SDavid du Colombier writenumfile(char *file, long num)
312219b2ee8SDavid du Colombier {
313219b2ee8SDavid du Colombier 	int fd;
314219b2ee8SDavid du Colombier 
315219b2ee8SDavid du Colombier 	fd = open(file, OWRITE);
316219b2ee8SDavid du Colombier 	if(fd < 0){
31772783476SDavid du Colombier 		complain("can't open %s: %r", file);
318219b2ee8SDavid du Colombier 		return;
319219b2ee8SDavid du Colombier 	}
3207dd7cddfSDavid du Colombier 	fprint(fd, "%ld", num);
321219b2ee8SDavid du Colombier 	close(fd);
322219b2ee8SDavid du Colombier }
323