]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/warning.c
sshfs: usage
[plan9front.git] / sys / src / cmd / auth / warning.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 #include <authsrv.h>
6 #include "authcmdlib.h"
7
8 /* working directory */
9 Dir     *dirbuf;
10 long    ndirbuf = 0;
11
12 int debug;
13
14 long    readdirect(int);
15 void    douser(Fs*, char*);
16 void    dodir(Fs*);
17 int     mail(Fs*, char*, char*, long);
18 int     mailin(Fs*, char*, long, char*, char*);
19 void    complain(char*, ...);
20 long    readnumfile(char*);
21 void    writenumfile(char*, long);
22
23 void
24 usage(void)
25 {
26         fprint(2, "usage: %s [-n] [-p]\n", argv0);
27         exits("usage");
28 }
29
30 void
31 main(int argc, char **argv)
32 {
33         int which;
34
35         which = 0;
36         ARGBEGIN{
37         case 'p':
38                 which |= Plan9;
39                 break;
40         case 'n':
41                 which |= Securenet;
42                 break;
43         case 'd':
44                 debug++;
45                 break;
46         default:
47                 usage();
48         }ARGEND
49         argv0 = "warning";
50
51         if(!which)
52                 which |= Plan9 | Securenet;
53         if(which & Plan9)
54                 dodir(&fs[Plan9]);
55         if(which & Securenet)
56                 dodir(&fs[Securenet]);
57 }
58
59 void
60 dodir(Fs *f)
61 {
62         int nfiles;
63         int i, fd;
64
65         if(chdir(f->keys) < 0){
66                 complain("can't chdir to %s: %r", f->keys);
67                 return;
68         }
69         fd = open(".", OREAD);
70         if(fd < 0){
71                 complain("can't open %s: %r\n", f->keys);
72                 return;
73         }
74         nfiles = dirreadall(fd, &dirbuf);
75         close(fd);
76         for(i = 0; i < nfiles; i++)
77                 douser(f, dirbuf[i].name);
78 }
79
80 /*
81  *  check for expiration
82  */
83 void
84 douser(Fs *f, char *user)
85 {
86         int n, nwarn;
87         char buf[128];
88         long rcvrs, et, now;
89         char *l;
90
91         sprint(buf, "%s/expire", user);
92         et = readnumfile(buf);
93         now = time(0);
94
95         /* start warning 2 weeks ahead of time */
96         if(et <= now || et > now+14*24*60*60)
97                 return;
98
99         sprint(buf, "%s/warnings", user);
100         nwarn = readnumfile(buf);
101         if(et <= now+14*24*60*60 && et > now+7*24*60*60){
102                 /* one warning 2 weeks before expiration */
103                 if(nwarn > 0)
104                         return;
105                 nwarn = 1;
106         } else {
107                 /* one warning 1 week before expiration */
108                 if(nwarn > 1)
109                         return;
110                 nwarn = 2;
111         }
112
113         /*
114          *  if we can't open the who file, just mail to the user and hope
115          *  for it makes it.
116          */
117         if(f->b){
118                 if(Bseek(f->b, 0, 0) < 0){
119                         Bterm(f->b);
120                         f->b = 0;
121                 }
122         }
123         if(f->b == 0){
124                 f->b = Bopen(f->who, OREAD);
125                 if(f->b == 0){
126                         if(mail(f, user, user, et) > 0)
127                                 writenumfile(buf, nwarn);
128                         return;
129                 }
130         }
131
132         /*
133          *  look for matches in the who file and mail to every address on
134          *  matching lines
135          */
136         rcvrs = 0;
137         while(l = Brdline(f->b, '\n')){
138                 n = strlen(user);
139                 if(strncmp(l, user, n) == 0 && (l[n] == ' ' || l[n] == '\t'))
140                         rcvrs += mailin(f, user, et, l, l+Blinelen(f->b));
141         }
142
143         /*
144          *  if no matches, try the user directly
145          */
146         if(rcvrs == 0)
147                 rcvrs = mail(f, user, user, et);
148         rcvrs += mail(f, "netkeys", user, et);
149         if(rcvrs)
150                 writenumfile(buf, nwarn);
151 }
152
153 /*
154  *  anything in <>'s is an address
155  */
156 int
157 mailin(Fs *f, char *user, long et, char *l, char *e)
158 {
159         int n;
160         int rcvrs;
161         char *p;
162         char addr[256];
163
164         p = 0;
165         rcvrs = 0;
166         while(l < e){
167                 switch(*l){
168                 case '<':
169                         p = l + 1;
170                         break;
171                 case '>':
172                         if(p == 0)
173                                 break;
174                         n = l - p;
175                         if(n > 0 && n <= sizeof(addr) - 2){
176                                 memmove(addr, p, n);
177                                 addr[n] = 0;
178                                 rcvrs += mail(f, addr, user, et);
179                         }
180                         p = 0;
181                         break;
182                 }
183                 l++;
184         }
185         return rcvrs;
186 }
187
188 /*
189  *  send mail
190  */
191 int
192 mail(Fs *f, char *rcvr, char *user, long et)
193 {
194         int pid, i, fd;
195         int pfd[2];
196         char *ct, *p;
197         Waitmsg *w;
198         char buf[128];
199
200         if(pipe(pfd) < 0){
201                 complain("out of pipes: %r");
202                 return 0;
203         }
204
205         switch(pid = fork()){
206         case -1:
207                 complain("can't fork: %r");
208                 return 0;
209         case 0:
210                 break;
211         default:
212                 if(debug)
213                         fprint(2, "started %d\n", pid);
214                 close(pfd[0]);
215                 ct = ctime(et);
216                 p = strchr(ct, '\n');
217                 *p = '.';
218                 fprint(pfd[1], "User '%s's %s expires on %s\n", user, f->msg, ct);
219                 if(f != fs)
220                         fprint(pfd[1], "If you wish to renew contact your local administrator.\n");
221                 p = strrchr(f->keys, '/');
222                 if(p)
223                         p++;
224                 else
225                         p = f->keys;
226                 sprint(buf, "/adm/warn.%s", p);
227                 fd = open(buf, OREAD);
228                 if(fd >= 0){
229                         while((i = read(fd, buf, sizeof(buf))) > 0)
230                                 write(pfd[1], buf, i);
231                         close(fd);
232                 }
233                 close(pfd[1]);
234
235                 /* wait for warning to be mailed */
236                 for(;;){
237                         w = wait();
238                         if(w == nil)
239                                 break;
240                         if(w->pid == pid){
241                                 if(debug)
242                                         fprint(2, "%d terminated: %s\n", pid, w->msg);
243                                 if(w->msg[0] == 0){
244                                         free(w);
245                                         break;
246                                 }else{
247                                         free(w);
248                                         return 0;
249                                 }
250                         }else
251                                 free(w);
252                 }
253                 return 1;
254         }
255
256         /* get out of the current namespace */
257         newns("none", 0);
258
259         dup(pfd[0], 0);
260         close(pfd[0]);
261         close(pfd[1]);
262         putenv("upasname", "netkeys");
263         if(debug){
264                 print("\nto %s\n", rcvr);
265                 execl("/bin/cat", "cat", nil);
266         }
267         execl("/bin/upas/send", "send", "-r", rcvr, nil);
268
269         /* just in case */
270         sysfatal("can't exec send: %r");
271
272         return 0;               /* for compiler */
273 }
274
275 void
276 complain(char *fmt, ...)
277 {
278         char buf[8192], *s;
279         va_list arg;
280
281         s = buf;
282         s += sprint(s, "%s: ", argv0);
283         va_start(arg, fmt);
284         s = vseprint(s, buf + sizeof(buf) / sizeof(*buf), fmt, arg);
285         va_end(arg);
286         *s++ = '\n';
287         write(2, buf, s - buf);
288 }
289
290 long
291 readnumfile(char *file)
292 {
293         int fd, n;
294         char buf[64];
295
296         fd = open(file, OREAD);
297         if(fd < 0){
298                 complain("can't open %s: %r", file);
299                 return 0;
300         }
301         n = read(fd, buf, sizeof(buf)-1);
302         close(fd);
303         if(n < 0){
304                 complain("can't read %s: %r", file);
305                 return 0;
306         }
307         buf[n] = 0;
308         return atol(buf);
309 }
310
311 void
312 writenumfile(char *file, long num)
313 {
314         int fd;
315
316         fd = open(file, OWRITE);
317         if(fd < 0){
318                 complain("can't open %s: %r", file);
319                 return;
320         }
321         fprint(fd, "%ld", num);
322         close(fd);
323 }