warning.c 5.6 KB

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