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