|
|
1.1 root 1: #include "authmgr.h"
2:
3: char admins[128];
4: int max_failures = MAX_FAILURES;
5: struct disallow* badlist;
6: int pushed_ld;
7: int gnotflg = 0; /* set if we shouldn't ask for a new number */
8: int dconflg = 0; /* set if real dest is dcon/mesgdcon */
9: int usepasswd = 0; /* set if we should ignore the key file */
10:
11: char dialbuf[128];
12: char* dialstring; /* dialstring from CSOURCE params */
13: char physource[128]; /* the switch.mod.chan stuff from CSOURCE */
14: char srcid[128]=""; /* the first field in CSOURCE */
15: char username[16]=""; /* the user's login name from CSOURCE */
16: char eusername[30]=""; /* effective login name */
17: char nettype[16]; /* shouldn't get bigger than this */
18: char options[16] ;
19: char redialbuf[128] ;
20: char defsvc[16]=""; /* default service */
21: FILE *log=0; /* log file */
22:
23: struct secmap *secidlist; /* list of security ID mappings */
24:
25: #define MLIST_SIZE 10
26: regsubexp mlist[MLIST_SIZE]; /* a match list for regexec */
27:
28: char* SYNTAX = "authmgr: Syntax error at line %d of control file\n";
29: #define DCON_CHALLENGE "CH" /* the dcon challenge response */
30:
31: int init(); /*forward*/
32: extern struct keyinfo* getkeyinfo();
33: char *makesourceid(); /*forward*/
34: char *getenv();
35: char *getpass();
36:
37: /*
38: * security - an authentication server
39: *
40: * For a given user, this locates that user's key in the
41: * key database, challenges the user to encrypt some data,
42: * and compares that user's result with the result of
43: * encrypting the data with the user's real key. If the
44: * results are the same, the user is authenticated, otherwise,
45: * no.
46: */
47: main(argc, argv)
48: int argc;
49: char* argv[];
50: {
51: int i, rc;
52: char buf[128];
53: char logname[30], logtries[128];
54: char *bp, *dp;
55: struct keyinfo *kp;
56: unsigned data, l, r;
57: ipcinfo info;
58: struct tm *tm = localtime(time((long *) 0));
59: long now = tm->tm_mday + 100*(tm->tm_mon) + 10000*(tm->tm_yday);
60:
61: if(rc=init(argc, argv) != 0) {
62: puts("REFUSED");
63: exit(rc);
64: }
65:
66:
67: /* main protocol section */
68: for(i=0; i<max_failures; i++) {
69: if(dconflg || gnotflg) {
70: printf("%s", DCON_CHALLENGE);
71: if(safegets(buf, sizeof(buf)) == NULL)
72: exit(0);
73: logname[8] = '\0';
74: strncpy(logname, buf, 8);
75: kp = getkeyinfo(logname, usepasswd);
76: bp = (*kp->kt->chal)(kp);
77: if(bp)
78: printf("%s\n", bp); /* send the challenge */
79: else
80: putchar('\n');
81: if(safegets(buf, sizeof(buf)) == NULL)
82: exit(0);
83: } else {
84: if(*eusername != '\0') {
85: strcpy(logname, eusername);
86: *eusername = '\0';
87: printf("login: %s\n", logname);
88: } else {
89: printf("login: ");
90: if(safegets(logname, sizeof(logname)) == NULL || *logname == '\0')
91: exit(0);
92: }
93: kp = getkeyinfo(logname, usepasswd);
94: bp = (*kp->kt->chal)(kp);
95: if(bp) {
96: printf("Enter response code for %s: ", bp);
97: if(safegets(buf, sizeof(buf)) == NULL || buf[0] == '\0')
98: exit(0);
99: } else {
100: printf("Password: ");
101: readnoecho(buf, sizeof buf);
102: }
103: }
104: (void) strcat(logtries, logname);
105: (void) strcat(logtries, " ");
106: strcpy(eusername, logname);
107:
108: if((kp->expire >= now) && (*kp->kt->comp)(kp, buf) == 0) {
109: goto success;
110: }
111: }
112:
113: doadmin(logtries);
114: puts("REFUSED");
115: exit(1);
116: success:
117: /* if no dialstring, ask for one */
118: /* if dconflg is set, dialstring isn't 0 */
119: if(dialstring == 0 || *dialstring == 0) {
120: i = 0;
121: while(i < max_failures) {
122: printf("\nDestination please: ");
123: fflush(stdout);
124: if(safegets(dialbuf, sizeof dialbuf) == NULL)
125: exit(0);
126: dialstring = dialbuf;
127: while(*dialstring == ' ' || *dialstring == '\t')
128: *dialstring++;
129: for(dp = dialstring;
130: *dp != '\0' && *dp != ' ' && *dp != '\t'; dp++)
131: ;
132: *dp = '\0';
133: if(*dialstring != '\0')
134: break;
135: i++ ;
136: }
137: if(i == max_failures) {
138: puts("\nNo new dialstring. Goodbye.\n");
139: exit(1);
140: }
141: }
142:
143: if (gnotflg)
144: options[0] = 'U' ;
145: else
146: options[0] = '-' ;
147: options[1] = 0 ;
148:
149: /* using "dialstring", send a redial msg to mgr */
150: strcpy(redialbuf, options) ;
151: strcat(redialbuf, ">") ;
152: strcat(redialbuf, dialstring) ;
153:
154: info.rfd = -1;
155: info.cfd = 0; /* pass back fd 0 */
156: info.myname = NULL;
157: info.user = logname;
158: info.machine = "";
159: info.uid = info.gid = -1;
160: info.name = ipcpath(redialbuf, nettype, defsvc);
161: info.param = "light"; /* bogus */
162: info.flags = 0;
163: if (log != 0) {
164: lognow();
165: fprintf(log, "%s %s (%s) redialing to %s\n",
166: srcid, username, eusername, info.name);
167: fclose(log);
168: }
169: if(pushed_ld)
170: ioctl(0, FIOPOPLD, (void *)0);
171: if(ipcredial(&info) != 0)
172: ; /* should complain somehow! */
173: exit(0);
174: }
175:
176: int
177: init(ac, av)
178: int ac;
179: char* av[];
180: {
181: FILE* cf;
182: char line[128] ;
183: #define NFLDS 10
184: char *fld[NFLDS];
185: int l, i, j, errflg = 0;
186: struct disallow *d = 0, *dp;
187: struct secmap *sp, *slp = 0;
188: regexp *prog;
189: char *c, *c2 = 0;
190: char *cntlfile = CONTROL_FILE;
191: int seen_defmap = 0;
192: char *malloc();
193: extern char *optarg;
194: extern int optind;
195:
196: while((i = getopt(ac, av, "nf:")) != -1)
197: switch(i) {
198: case 'n':
199: gnotflg++;
200: break;
201: case 'f':
202: cntlfile = optarg;
203: break;
204: case '?':
205: errflg++;
206: break;
207: }
208: if(errflg) {
209: fprintf(stderr, "authmgr: bad arglist\n");
210: return 1;
211: }
212: strcpy(physource, "auth1.1.1.F");
213: chdir("/tmp"); /* in case of core dumps; I wanna find them */
214: c = getenv("CSOURCE");
215: if(c) {
216: /* this "knows" the format of a CSOURCE */
217: if(strncmp(c, "source=", 7) == 0) {
218: c += 7;
219: c2 = nettype;
220: while(*c != '!')
221: *c2++ = *c++;
222: *c2 = '\0';
223:
224: c++;
225: c2 = srcid;
226: while(*c != ' ')
227: *c2++ = *c++;
228: *c2 = '\0';
229: } else
230: strcpy(nettype, "dk"); /* XXX */
231:
232: while(c = strchr(c, ' ')) {
233: c++;
234: if(strncmp(c, "user=", 5) == 0) {
235: c += 5;
236: c2 = username;
237: i = 0;
238: while(*c != ' ') {
239: if(*c >= '0' && *c <= '9')
240: i++;
241: *c2++ = *c++;
242: }
243: *c2 = '\0';
244: c++;
245: /*
246: * ignore the user name if it's numeric or
247: * if it's the magic unknown user
248: */
249: if(i == strlen(username) || strcmp(username, "_unknown_") == 0)
250: username[0] = '\0';
251: }
252: if(strncmp(c, "line=", 5) == 0) {
253: strcpy(physource, c+5);
254: break;
255: }
256: }
257: }
258: strcpy(eusername, username);
259: c = getenv("CDEST");
260: if(c) {
261: strcpy(line, c);
262: c = line;
263: setfields("!");
264: i = getfields(c, fld, NFLDS);
265: if(i >= 4) {
266: /* check if it matches my service; if so, ignore it */
267: j = strlen(fld[2]);
268: if((i = strlen(fld[3])) <= j ||
269: strcmp(&fld[3][i-j], fld[2]) != 0) {
270: strcpy(dialbuf, fld[3]);
271: dialstring = dialbuf;
272: }
273: }
274: }
275:
276: if(dialstring != NULL) {
277: if((i = strlen(dialstring)) > 4 &&
278: strcmp(&dialstring[i-4], "dcon") == 0)
279: dconflg++;
280: }
281: if(!dconflg && !gnotflg)
282: printf("Security Authentication check\n\n");
283:
284: if((cf = fopen(cntlfile, "r")) == NULL) {
285: fprintf(stderr, "authmgr: No control file\n");
286: return 2;
287: }
288:
289: setfields(" \t");
290: l = 0;
291: while(fgets(line, 128, cf) != NULL) {
292: l++;
293: for(i=0; line[i] == ' ' || line[i] == '\t'; i++)
294: ;
295: if(line[i] == '#') /* ignore comments */
296: continue;
297: if((c = strchr(&line[i], '\n')) != NULL) /* strip newline */
298: *c = '\0';
299:
300: i = getmfields(&line[i], fld, NFLDS);
301: if(i == 0) /* blank line */
302: continue;
303:
304: if(strcmp(fld[0], "admin") == 0) {
305: if(i < 2) {
306: fprintf(stderr, SYNTAX, l);
307: return 3;
308: }
309: (void) strcpy(admins, fld[1]);
310: for(j=2; j<i; j++) {
311: strcat(admins, " ");
312: strcat(admins, fld[j]);
313: }
314: } else if(strcmp(fld[0], "failures") == 0) {
315: if(i != 2 || (max_failures = atoi(fld[1])) < 3) {
316: fprintf(stderr, SYNTAX, l);
317: return 4;
318: }
319: } else if(strcmp(fld[0], "disallow") == 0) {
320: if(i != 2) {
321: fprintf(stderr, SYNTAX, l);
322: return 5;
323: }
324: dp = (struct disallow*) malloc(sizeof(struct disallow));
325: if(dp == 0) {
326: fprintf(stderr, "authmgr: out of memory\n");
327: return 6;
328: }
329: (void) strncpy(dp->logname, fld[1], 8);
330: dp->logname[8] = '\0';
331: dp->next = NULL;
332: if(d == 0) {
333: badlist = d = dp;
334: } else {
335: d->next = dp;
336: d = dp;
337: }
338: } else if(strcmp(fld[0], "usepasswd") == 0) {
339: if(i != 2) {
340: fprintf(stderr, SYNTAX, l);
341: return 7;
342: }
343: if((prog = regcomp(fld[1])) == NULL) {
344: fprintf(stderr, SYNTAX, l);
345: free((char*)prog);
346: return 8;
347: }
348: if(regexec(prog, srcid, mlist, MLIST_SIZE) != 0) {
349: usepasswd++;
350: }
351: } else if(strcmp(fld[0], "setuser") == 0) {
352: if((i < 2) | (i > 3)) {
353: fprintf(stderr, SYNTAX, l);
354: return 9;
355: }
356: if((prog = regcomp(fld[1])) == NULL) {
357: fprintf(stderr, SYNTAX, l);
358: free((char*)prog);
359: return 10;
360: }
361: if(regexec(prog, srcid, mlist, MLIST_SIZE) != 0) {
362: if (i == 2)
363: eusername[0] = '\0';
364: else {
365: strncpy(eusername, fld[2], 8);
366: eusername[8] = '\0';
367: }
368: }
369: } else if(strcmp(fld[0], "setsvc") == 0) {
370: if(i != 3) {
371: fprintf(stderr, SYNTAX, l);
372: return 11;
373: }
374: if((prog = regcomp(fld[1])) == NULL) {
375: fprintf(stderr, SYNTAX, l);
376: free((char*)prog);
377: return 12;
378: }
379: if(regexec(prog, srcid, mlist, MLIST_SIZE) == 0)
380: continue;
381: strncpy(defsvc, fld[2], 16);
382: defsvc[16]='\0';
383: } else if(strcmp(fld[0], "setlog") == 0) {
384: if(i != 3) {
385: fprintf(stderr, SYNTAX, l);
386: return 13;
387: }
388: if((prog = regcomp(fld[1])) == NULL) {
389: fprintf(stderr, SYNTAX, l);
390: free((char*)prog);
391: return 13;
392: }
393: if(regexec(prog, srcid, mlist, MLIST_SIZE) == 0)
394: continue;
395: if((log = fopen(fld[2], "a")) == NULL) {
396: fprintf(stderr, "Can't open log file %s\n", fld[2]);
397: return 20;
398: }
399: } else if(strcmp(fld[0], "secidmap") == 0) {
400: if(i != 3) {
401: fprintf(stderr, SYNTAX, l);
402: return 14;
403: }
404: sp = (struct secmap*) malloc(sizeof(struct secmap));
405: if(strcmp(fld[1], ".*") == 0)
406: seen_defmap = 1;
407: else if(seen_defmap) {
408: fprintf(stderr, "authmgr: Warning; default secidmap is not last secidmap at line %d\n", l);
409: free((char *)sp);
410: continue;
411: }
412: if((sp->prog = regcomp(fld[1])) == NULL) {
413: fprintf(stderr, SYNTAX, l);
414: free((char *)sp);
415: return 15;
416: }
417: if(slp == 0)
418: slp = secidlist = sp;
419: else {
420: slp->next = sp;
421: slp = sp;
422: }
423: slp->secid = strdup(fld[2]);
424: slp->next = NULL;
425: } else {
426: fprintf(stderr, SYNTAX, l);
427: return 16;
428: }
429: }
430: if(!seen_defmap) {
431: fprintf(stderr, "authmgr: No default ID configured. Help!\n");
432: return 17;
433: }
434: if(!dconflg && !gnotflg) {
435: struct tchars tcbuf;
436: extern int tty_ld;
437: /* make sure interface is usable by humans */
438: if(ioctl(0, TIOCGETC, &tcbuf) < 0) {
439: /* no tty ld (of any type) present; push one */
440: if(ioctl(0, FIOPUSHLD, &tty_ld) < 0)
441: printf("No tty processing supported; sorry\n");
442: pushed_ld++;
443: }
444: }
445: return 0;
446: }
447:
448: char*
449: makesourceid()
450: {
451: static char sbuf[128];
452: struct secmap *sp = secidlist;
453:
454: while(sp != NULL) {
455: if(regexec(sp->prog, srcid, mlist, MLIST_SIZE) != 0) {
456: sprintf(sbuf, "%s.%s", sp->secid, physource);
457: return sbuf;
458: }
459: sp = sp->next;
460: }
461: }
462:
463: readnoecho(rbuf, n)
464: char *rbuf;
465: int n;
466: {
467: struct sgttyb sg, noecho;
468: int failed = 0;
469:
470: failed = ioctl(0, TIOCGETP, &sg);
471: if(failed >= 0) {
472: noecho = sg;
473: noecho.sg_flags &= ~ECHO;
474: ioctl(0, TIOCSETP, &noecho);
475: }
476: safegets(rbuf, n);
477: if(failed >= 0)
478: ioctl(0, TIOCSETP, &sg);
479: }
480:
481: void
482: regerror(msg)
483: char *msg;
484: {
485: fprintf(stderr, "authmgr: %s\n", msg);
486: return;
487: }
488:
489: #include <utsname.h>
490:
491: /*
492: * doadmin -
493: * do whatever administrative muck is necessary when a login
494: * fails to authenticate itself after max_failures tries.
495: */
496: doadmin(logname)
497: char* logname;
498: {
499: char buf[256];
500: FILE* f;
501: struct utsname un;
502:
503: if (log != NULL) {
504: lognow();
505: fprintf(log, "%s %s (%s) failed\n",
506: srcid, username, eusername);
507: fclose(log);
508: }
509:
510: (void) uname(&un);
511: sprintf(buf, "/bin/mail %s", admins);
512: if((f = popen(buf, "w")) == NULL)
513: return; /* XXX */
514:
515: fprintf(f, "\
516: Subject: security alert from server %s\n\
517: \n\
518: The login(s) ``%s'' failed to correctly authenticate\n\
519: itself after %d consecutive attempts.\n\
520: The source of the attempts was:\n\
521: %s\n\
522: Recommendation: disable and investigate the login(s).\n",
523: un.nodename, logname, max_failures, getenv("CSOURCE"));
524:
525: (void) pclose(f);
526: }
527:
528:
529: /*
530: * a safe version of gets
531: */
532: safegets(bp, n)
533: char *bp;
534: int n;
535: {
536: char *cp;
537:
538: if(fgets(bp, n, stdin)==NULL)
539: return NULL;
540: for(cp=bp; *cp; cp++)
541: if(*cp=='\r' || *cp =='\n'){
542: *cp = 0;
543: break;
544: }
545: return bp;
546: }
547:
548: lognow()
549: {
550: struct tm *now;
551: long seconds;
552:
553: (void) time(&seconds);
554: now = localtime(&seconds);
555: fprintf(log, "%02d/%02d %02d:%02d:%02d ",
556: now->tm_mon+1, now->tm_mday,
557: now->tm_hour, now->tm_min, now->tm_sec);
558: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.