|
|
1.1 root 1: /*
2: The daemon program that runs the network.
3:
4: Usage:
5: netdaemon -m mach [-r readfd] [-w writefd] [-d] [-h]
6: [-os] [-or] [-ou num]
7:
8: Must be started by root.
9: Options:
10: -m mach remote machine is mach (required)
11: -d turn debugging on
12: -r num if simulute w/pipes, read from num
13: -w num if simulate w/pipes, write on num
14: -h use high-speed link (not implemented yet)
15: -os only send
16: -or only receive
17: -ou num only send things with uid = num
18: -p num length of packet
19: */
20:
21: # include "defs.h"
22: /* take a time, adjust to be in PST, and divide by no of secs in a day */
23: /* adjust by 10 mins, and day is considered to begin at 3AM */
24: /* 6*3600 = 21600 +17400 = 39000 */
25: /* number of seconds in a day, usually 86400L */
26: # define nsecday 86400L
27: /* number of days since time began */
28: # define numdays(S) ((S - 39000L)/nsecday)
29: /* set my priority to normal */
30: # define RENICE (nice(-40), nice(20), nice(0))
31:
32: /* global variables */
33: extern char **environ;
34: struct dumpstruc dump;
35: struct bstruct btable[];
36: struct daemonparms netd;
37: struct userinfo status;
38:
39: /* local variables */
40: static long length;
41: static FILE *dir;
42: /* static char sheader[] = "ABCDE"; */
43: static char tempfile[]= TEMPFILE;
44: static char publogfile[]= PUBLOGFILE;
45: static struct stat statbuf;
46: static struct direct dirbuf;
47: int handlekill();
48: static char frommach;
49: long linechars();
50:
51: main(argc,argv)
52: char **argv; {
53: register int i;
54: long ltime,t;
55: char buf[100];
56:
57: nice(-1);
58: signal(SIGTERM,handlekill);
59: debugflg = DBV;
60: setupdaemon(argc,argv);
61: /* now running alone as a daemon */
62: /*
63: for(i=0; i<15; i++)close(i);
64: signal(SIGHUP,SIG_IGN);
65: signal(SIGQUIT,SIG_IGN);
66: signal(SIGINT,SIG_IGN);
67: */
68: senddir[strlen(senddir)-1] = remote; /* choose dir */
69: if(chdir(senddir) < 0){
70: perror(senddir);
71: exit(EX_OSFILE);
72: }
73: dir = fopen(senddir,"r");
74: if(dir == NULL){
75: perror(senddir);
76: exit(EX_OSFILE);
77: }
78: mktemp(tempfile);
79: tempfile[strlen(tempfile) - 7] = remote;
80: ltime = gettime();
81: if(ltime == 0L)
82: fprintf(stderr,"The network says 'The clock is set wrong.'\n");
83: sprintf(buf,"net restarted to %s %d %s",longname(remote),
84: getpid(),ctime(<ime));
85: dump.longtime = ltime;
86: dump.lastndays = numdays(ltime);
87: addtolog(remote,buf);
88: addtopublic(buf);
89: fprintf(stderr,buf);
90: if(!debugflg)fclose(stderr);
91: sendpurge();
92: mainloop();
93: /* never returns */
94: }
95: /* the main loop of the daemon, alternatively rcv then send, if poss.*/
96: mainloop(){
97: register int i;
98:
99: for(;;){ /* begin reading file */
100: debug("daemon %c %d\n",remote,getpid());
101: /* first receive */
102: if(netd.dp_sndorcv >= 0){ /* if we can receive */
103: i = netrcv();
104: if(i == -1)dump.nabnormal++;
105: }
106: /* now look to send */
107: if(netd.dp_sndorcv <= 0) /* if we can send */
108: netsend();
109: /* print out statistics if the right time */
110: printstat();
111: dump.nloop++;
112: }
113: }
114: /* this code is a little strange because some machines
115: seem to have trouble having the date set, and time()
116: returns 0 until somebody remembers to set the date */
117: printstat(){
118: long thisndays, thistime;
119: thistime = gettime();
120: thisndays = numdays(thistime);
121: if(dump.longtime == 0L){
122: dump.longtime = thistime;
123: dump.lastndays = thisndays;
124: return;
125: }
126: if(thisndays == dump.lastndays + 1L) dumpit(thistime);
127: dump.lastndays = thisndays;
128: }
129: /* look for files to send */
130: netsend(){
131: static long lasttime = 0;
132: static char nleft = 1;
133: long lFileLen,diff;
134: double drate;
135: register int uid,uidBest;
136: char *sdate,*sn,*swait;
137: long ot,nt,filesize;
138: register int i;
139: char stemp[20];
140: static char jname[FNS];
141:
142: debug("ck send");
143: if(stat(senddir,&statbuf) < 0){
144: error("%s %s",senddir,sys_errlist[errno]);
145: return;
146: }
147: if(statbuf.st_mtime == lasttime && nleft == 0)return; /* no need to search */
148: lasttime = statbuf.st_mtime;
149: fseek(dir,0L,0);
150: lFileLen = 10000000L;
151: nleft = 0;
152: while(fread(&dirbuf,1,sizeof dirbuf,dir) == sizeof dirbuf){
153: if(dirbuf.d_ino == 0
154: || dirbuf.d_name[0] != 'c'
155: || dirbuf.d_name[1] != 'f'
156: || dirbuf.d_name[2] != remote
157: || stat(dirbuf.d_name,&statbuf) < 0
158: || statbuf.st_mode == 0)
159: continue;
160: dirbuf.d_name[0] = 'd';
161: if(stat(dirbuf.d_name,&statbuf) < 0 || statbuf.st_mode == 0)
162: continue;
163: uid = guid(statbuf.st_uid,statbuf.st_gid);
164: if(netd.dp_onlyuid != 0 && uid != netd.dp_onlyuid && uid != SUPERUSER
165: && uid != NUID)continue;
166: nleft++;
167: filesize = getsize(&statbuf);
168: if(lFileLen > filesize){
169: lFileLen = filesize;
170: for(i=0; i<DIRSIZ; i++)
171: jname[i] = dirbuf.d_name[i];
172: uidBest = uid;
173: }
174: # ifdef MAXSENDQ
175: if(nleft > MAXSENDQ)break;
176: # endif
177: }
178: if(lFileLen == 10000000L)return;
179: strcpy(stemp,jname);
180: stemp[0] = 'c';
181: sn = SnFromUid(uidBest);
182: if(sn == NULL){
183: addtolog(remote,"Unknown userid %d\n",uidBest);
184: return;
185: }
186: addtolog(remote,"^S %s %c: %s ",sn,remote,jname+2);
187: ot = gettime();
188: if(send(jname) == 0)return;
189: nt = gettime();
190: filesize = getsize(&statbuf);
191: unlink(jname);
192: unlink(stemp);
193: diff = nt - ot;
194: if(diff < 1)diff = 1; /* avoid dividing by zero */
195: sdate = ctime(&nt)+4;
196: sdate[strlen(sdate) -9] = 0;
197: swait = comptime(ot - statbuf.st_mtime);
198: jname[3] = jname[2];
199: # ifndef NOFP
200: drate = (double)filesize / (double)diff;
201: addtolog(remote,"^T%c(%s, %ldb, %ldsec, %4.1fb/sec, w %s)\n",
202: remote,sdate,filesize, diff,drate, swait);
203: # else
204: addtolog(remote,"^T%c(%s, %ldb, %ldsec, w %s)\n",
205: remote,sdate,filesize, diff,swait);
206: # endif
207: addtopublic("%s: sent %-8s to %s (%s, %ld b, wait %s)\n",
208: sdate,sn,longname(remote),jname+3,filesize,swait);
209: dump.nsend++;
210: dump.bytetot += filesize;
211: dump.elaptot += diff;
212: }
213: send(jname)
214: char *jname;
215: { /* push those bytes */
216: /* returns 0 if send fails, 1 otherwise */
217: register int n;
218: int i;
219: long lsize;
220: char mbuf[20], buf[MAXNBUF];
221: register char *p;
222: register FILE *jfile;
223:
224: debug("send %s",jname);
225: if(stat(jname,&statbuf) < 0)goto sfail;
226: lsize = getsize(&statbuf);
227: if(lsize < MINSIZE){ /* all files are at least this long */
228: unlink(jname);
229: jname[0] = 'c';
230: unlink(jname);
231: return(1);
232: }
233: jfile = fopen(jname,"r");
234: if(jfile == NULL)goto sfail;
235: /*
236: strcpy(mbuf,sheader);
237: i = strlen(sheader);
238: p = (char *)&lsize;
239: lsize = fixuplong(lsize);
240: mbuf[i] = *p++;
241: mbuf[i+1] = *p++;
242: mbuf[i+2] = *p++;
243: mbuf[i+3] = *p++;
244: i = i + 4;
245: sendreset();
246: */
247: initseqno();
248: sprintf(mbuf,"|%08ld|",lsize);
249: i = 10;
250: if(xwrite(mbuf,i) == WRITEFAIL)goto bwrite;
251: while((n=read(fileno(jfile),buf,MAXNBUF)) > 0)
252: if(xwrite(buf,n) == WRITEFAIL)goto bwrite;
253: fclose(jfile);
254: debug("end send");
255: return(1);
256: bwrite:
257: dump.nsendfail++;
258: fclose(jfile);
259: addtolog(remote,"^F%c\n",remote);
260: return(0);
261: sfail:
262: error("%s: %s",jname,sys_errlist[errno]);
263: dump.nsendfail++;
264: return(0);
265: }
266: netrcv(){
267: /* returns -2 in normal fail, -1 in abnormal fail, >= 0 otherwise */
268: char sin;
269: char mgetc(), *s;
270: register int n;
271: char c;
272: int i, dummy, pid;
273: unsigned rcode;
274: long otime,olength,diff,rcvfinish,nt;
275: double r;
276: char hbuf[20], buf[MAXNBUF];
277: register FILE *temp;
278: static struct header hd;
279:
280: initseqno();
281: /*
282: n = nread(hbuf,strlen(sheader));
283: if(n == BROKENREAD)return(-2);
284: if(n != strlen(sheader) || strcmp(sheader,hbuf) != 0){
285: error("wrong head %d %s",n,hbuf);
286: return(-1);
287: }
288: n = nread(&length,4);
289: length = fixuplong(length);
290: */
291: n = nread(hbuf,10);
292: if(n == BROKENREAD)return(-2);
293: if(n != 10){
294: error("bad length nread %d",n);
295: return(-1);
296: }
297: hbuf[10] = 0;
298: if(hbuf[0] != '|' || hbuf[9] != '|'){
299: error("poor format %s",hbuf);
300: return(-1);
301: }
302: hbuf[9] = 0;
303: length = atol(hbuf+1);
304: if(length < 0 || length > 100000000L){
305: error("bad length %ld",length);
306: return(-1);
307: }
308: dump.braw = 4;
309: olength = length;
310: otime = gettime();
311: debug("length = %ld\n",length);
312:
313: /*
314: begin parsing header
315:
316: from local to remote (requests)
317: code net option reason
318: q normal request
319: y -y simply skips login check (used by netlpr)
320:
321: from remote to local
322: code net option reason
323: w -w message to be written/mailed back
324: s -z normal response
325: */
326:
327: i = readhd(&hd);
328: if(i == -3)goto forw; /* being forwarded thru us */
329: if(i != 0)return(i);
330:
331: strcpy(status.login, hd.hd_snto);
332: strcpy(status.localname,hd.hd_snfrom);
333:
334: demask(hd.hd_spasswd);
335:
336: s = hd.hd_scmdvirt;
337: while(*s && *s != ' ')s++;
338: c = *s;
339: *s = 0;
340: if(strcmp(hd.hd_scmdvirt,"netlpr") == 0)dump.nnetlpr++;
341: else if(strcmp(hd.hd_scmdvirt,"netmail") == 0)dump.nnetmail++;
342: else if(strcmp(hd.hd_scmdvirt,"mail") == 0)dump.nsmail++;
343: else if(strcmp(hd.hd_scmdvirt,"netcp") == 0)dump.nnetcp++;
344: else if(strcmp(hd.hd_scmdvirt,"response") == 0)dump.nresp++;
345: else dump.nnet++;
346: *s = c;
347:
348: printhd(&hd);
349:
350: /* any chars left are data */
351: forw:
352: sin = 0;
353: if(length > 0){ /* make a temp input file */
354: increment(tempfile);
355: temp = fopen(tempfile,"w");
356: if(temp == NULL){
357: error("%s %s",tempfile,sys_errlist[errno]);
358: return(-1);
359: }
360: chmod(tempfile,0600);
361: if(hd.hd_mchto != local){
362: fprintf(temp,"%c :%c :",hd.hd_code,hd.hd_mchto);
363: fflush(temp);
364: }
365: /* this is the loop to read in all the data */
366: while((n = mread(buf,MAXNBUF)) > 0)
367: if(write(fileno(temp),buf,n) != n){
368: error("%s %s",tempfile,sys_errlist[errno]);
369: fclose(temp);
370: unlink(tempfile);
371: return(-1);
372: };
373: fclose(temp);
374: if(n == BROKENREAD || length > 0){
375: unlink(tempfile);
376: return(-2);
377: }
378: sin = 1;
379: if(hd.hd_mchto != local){
380: diff = gettime() - otime;
381: if(diff < 1)diff = 1; /* avoid dividing by 0 */
382: # ifndef NOFP
383: r = olength;
384: r = r/diff;
385: addtolog(remote,"^P(to %c, %ldb, %ldsec, %4.1fb/sec)\n",
386: hd.hd_mchto,olength,diff,r);
387: # else
388: addtolog(remote,"^P(to %c, %ldb, %ldsec)\n",
389: hd.hd_mchto,olength,diff);
390: # endif
391: dump.npass++;
392: dump.bytetot += olength;
393: dump.elaptot += diff;
394: while((pid = fork()) == -1)sleep(2);
395: if(pid == 0){
396: RENICE;
397: execl(netcmd,"net","-x","-m",longname(hd.hd_mchto),
398: "-s",tempfile,0);
399: error("%s: %s",netcmd,sys_errlist[errno]);
400: exit(EX_UNAVAILABLE);
401: }
402: wait(&rcode);
403: unlink(tempfile);
404: rcode >>= 8;
405: if(rcode != 0)
406: error("pass-thru rcode %d");
407: debug("passthru to %c code %c rcode %d",
408: hd.hd_mchto,hd.hd_code,rcode);
409: return(1);
410: }
411: }
412: if(length > 0){error("file too short"); return(-1); }
413: rcvfinish = gettime();
414:
415: while((pid = fork()) == -1)sleep(2);
416: if(pid > 0){
417: wait(&dummy);
418: return(1); /* normal return */
419: }
420: RENICE;
421: while((pid = fork()) == -1)sleep(2);
422: if(pid != 0)exit(EX_OK);
423:
424: /* child process which forks and waits */
425: mktemp(resfile);
426: while((pid = fork()) == -1)sleep(2);
427: if(pid == 0){
428: /* child */
429: strcpy(status.loginshell,Bsh);
430: frommach = hd.hd_mchfrom;
431: n = check(&hd,(hd.hd_code == 'q'));
432: if(!n)errormsg(TRUE,&hd,NULL,
433: "Bad remote login/password '%s'",hd.hd_snto);
434: temp = fopen(resfile,"w");
435: if(temp == NULL)
436: errormsg(TRUE,&hd,NULL,
437: "Create file %s: %s",resfile,sys_errlist[errno]);
438: fclose(temp);
439: chmod(resfile,0600);
440: mchown(resfile,status.muid,status.mgid);
441: if(sin)
442: mchown(tempfile,status.muid,status.mgid);
443: else tempfile[0] = 0;
444: setgid(status.mgid);
445: setuid(status.muid);
446: /* after this point our gid, uid is the target user's */
447: excmd(&hd,resfile,tempfile);
448: }
449: /* parent */
450: wait(&rcode);
451: rcode = (((rcode&077400) >>8) &0177);
452: /*
453: fclose(stdin);
454: fclose(stdout);
455: fclose(stderr);
456: */
457: if(sin)unlink(tempfile);
458: /*
459: now send something back to the sender
460: unless this was a response (file or message)
461: */
462: if((hd.hd_code == 'q' || hd.hd_code == 'y')
463: && (hd.hd_srespfile[0] || !hd.hd_fnonotify))
464: sndresponse(&hd,rcode);
465: unlink(resfile);
466: s = ctime(&rcvfinish);
467: s += 4;
468: s[strlen(s) -8] = 0;
469: diff = rcvfinish - otime;
470: if(diff < 1)diff = 1; /* avoid dividing by zero */
471: dump.bytetot += olength;
472: dump.elaptot += diff;
473: sprintf(buf,"%s rcv %c:%-8s (%s)",
474: s,hd.hd_mchfrom,hd.hd_snfrom,hd.hd_snto);
475: addtolog(remote,"%s C: %s\n",buf,hd.hd_scmdvirt);
476: addtopublic("%s R: %d C: %s\n",buf,rcode,hd.hd_scmdvirt);
477: nt = rcvfinish - hd.hd_ltimesent;
478: buf[0] = 0;
479: if(nt > 0L)sprintf(buf," took (%s)",comptime(nt));
480: # ifndef NOFP
481: r = olength;
482: r = r/diff;
483: addtolog(remote,"\t\tR: %d%s %ldb %ldsec %4.1fb/sec\n",
484: rcode,buf,olength,diff,r);
485: r = dump.braw;
486: r = r/diff;
487: addtolog(remote,"\t\t%4.1frb/sec %4.1f%% use\n",r,(r/linechars())*100L);
488: # else
489: addtolog(remote,"\t\tR: %d%s %ldb %ldsec\n",
490: rcode,buf,olength,diff);
491: # endif
492: exit(EX_OK);
493: /*UNREACHED*/
494: }
495: long linechars(){
496: if(netd.dp_inspeed == 13)return(960L);
497: else return(120L);
498: }
499: /*
500: execute the user's command
501: this procedure is executed with uid, gid of the user
502: */
503: excmd(phd,tempresfile,tempinfile)
504: register struct header *phd;
505: char *tempresfile, *tempinfile;
506: {
507: FILE *fd;
508: int i, uid;
509: register char *s, c;
510:
511: uid = getuid();
512: uid = uidmask(uid);
513: status.muid = uidmask(status.muid);
514: if(uid != status.muid)error("setuid fails");
515: debug("uid: %u, gid: %u\n",uid,status.mgid);
516: /* check for allowed root commands, for security reasons */
517: if(uid == SUPERUSER){
518: s = phd->hd_scmdact;
519: while(*s && *s != ' ')s++;
520: c = *s;
521: *s = 0;
522: /* these are the only commands root may execute */
523: if(strcmp(phd->hd_scmdact,"cat") != 0
524: && strcmp(phd->hd_scmdact,"/bin/cat") != 0
525: && strcmp(phd->hd_scmdact,MWRITECMD) != 0
526: && strcmp(phd->hd_scmdact,"netrm") != 0
527: && strcmp(phd->hd_scmdact,"/usr/lib/tq") != 0
528: && strcmp(phd->hd_scmdact,"/usr/lib/rtrrm") != 0
529: && strcmp(phd->hd_scmdact,"lpr") != 0)
530: errormsg(TRUE,phd,tempresfile,
531: "Not allowed to execute '%s' as root",
532: phd->hd_scmdact);
533: *s = c;
534: }
535: if(chdir(status.dir) < 0)
536: errormsg(TRUE,phd,tempresfile,
537: "chdir %s: %s",status.dir,sys_errlist[errno]);
538: setenv(status.dir); /* set up v7 environment */
539: if(tempinfile[0])mreopen(TRUE,phd,tempresfile,tempinfile,"r",stdin);
540: else if(phd->hd_sinfile[0])mreopen(TRUE,phd,tempresfile,phd->hd_sinfile,"r",stdin);
541: else mreopen(TRUE,phd,tempresfile,"/dev/null","r",stdin);
542: if(phd->hd_code == 's' && phd->hd_soutfile[0]){
543: if(stat(phd->hd_soutfile,&statbuf) < 0
544: || getsize(&statbuf) != 0)
545: errormsg(FALSE,phd,tempresfile,"Bad result file '%s'",phd->hd_soutfile);
546: mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout);
547: }
548: else if(phd->hd_soutfile[0]){
549: fd = fopen(phd->hd_soutfile,"w");
550: if(fd == NULL)
551: errormsg(TRUE,phd,tempresfile,"Open file %s: %s",
552: phd->hd_soutfile,sys_errlist[errno]);
553: fclose(fd);
554: mreopen(TRUE,phd,tempresfile,phd->hd_soutfile,"w",stdout);
555: }
556: else mreopen(TRUE,phd,tempresfile,tempresfile,"a",stdout);
557: debug("exec '%s'\n",phd->hd_scmdact);
558: if(debugflg == 0){
559: /* cheat */
560: close(2);
561: dup(1);
562: /*
563: mreopen(TRUE,phd,tempresfile,tempresfile,"a",stderr);
564: */
565: }
566: for(i=3;i<15;i++)close(i);
567: if(strcmp(phd->hd_scmdact,"cat") == 0
568: || strcmp(phd->hd_scmdact,"/bin/cat") == 0)excat();
569: do {
570: mexecl(status.loginshell,"sh","-c",phd->hd_scmdact,0);
571: sleep(2);
572: } while(errno == ETXTBSY);
573: perror(status.loginshell);
574: exit(EX_UNAVAILABLE);
575: }
576: /*
577: send back a response
578:
579: if errormsg was called the resfile should be unlinked,
580: to avoid two messages being sent there
581: */
582: sndresponse(phd,rcode)
583: unsigned rcode;
584: struct header *phd;
585: {
586: char cmdstr[BUFSIZ], buf[BUFSIZ];
587: int dummy;
588: long maxfile = MAXFILE;
589: /* send response back if a response file
590: was given or if mail/write is allowed */
591: if(stat(resfile,&statbuf) < 0){
592: error("%s %s",resfile,sys_errlist[errno]);
593: return;
594: }
595: /* allow larger files between the Ingres machines */
596: if(machtype[local - 'a'] == M_INGRES
597: && machtype[remote - 'a'] == M_INGRES)
598: maxfile = MAXFILELARGE;
599: if(getsize(&statbuf) >= maxfile){
600: errormsg(TRUE,phd,"Result file too large - not sent");
601: return;
602: }
603: if(getsize(&statbuf) == 0){
604: /* response file specified, no output generated */
605: if(phd->hd_srespfile[0] != 0)return;
606: /* quiet option - no output and a rcode of 0 */
607: if(rcode == 0 && phd->hd_fquiet)return;
608: }
609: /* use both old and new mwrite parm lists */
610:
611: if(phd->hd_srespfile[0])
612: sprintf(cmdstr,"-o %s cat",phd->hd_srespfile);
613: else sprintf(cmdstr,
614: "%s -t %s -f %s -x %ld -c \"'%s'\" -y %s -e %ld -r %d",
615: MWRITECMD, phd->hd_addrfrom, phd->hd_addrto, phd->hd_lttytime,
616: phd->hd_scmdvirt, phd->hd_sttyname, phd->hd_ltimesent-TIMEBASE, rcode);
617:
618: sprintf(buf,"%s -m%c -z -b -l %s -s %s -c response %s",
619: netcmd,phd->hd_mchfrom,phd->hd_snfrom,resfile,cmdstr);
620: dummy = system(buf); /* execute command buf */
621: }
622:
623: /*
624:
625: excat
626: does nothing more than copy standard input to standard
627: output, like the cat command, but reports write errors.
628: Uses getc and putc rather than fwrite and fread because
629: the latter call getc and putc.
630: */
631: excat(){
632: register int n;
633: char buf[BUFSIZ];
634:
635: errno = 0;
636: while((n = read(0,buf,BUFSIZ)) > 0){
637: if(write(1,buf,n) != n){
638: perror("filecat: stdout");
639: exit(EX_OSFILE);
640: }
641: }
642: if(errno){
643: perror("filecat: stdin");
644: exit(EX_OSFILE);
645: }
646: exit(EX_OK);
647: }
648: /* returns errors for netrcv() */
649: static readhd(phd)
650: register struct header *phd;
651: {
652: char cflag, sbuf[BUFSIZ], parmlist[PARMLIST];
653: int i = 0;
654: char code;
655: code = mgetc();
656: phd->hd_mchto = mgetc();
657: if(code != 'q' && code != 'y' && code != 'w' && code != 's'){
658: error("bad code");
659: return(-1);
660: }
661: phd->hd_code = code;
662: if(phd->hd_mchto < 'a' || 'z' < phd->hd_mchto){
663: error("bad phd->hd_mchto");
664: return(-1);
665: }
666: if(phd->hd_mchto != local)return(-3); /* being forwarded through us */
667: phd->hd_mchfrom = mgetc();
668: phd->hd_vmajor = mgetc();
669: phd->hd_vminor = mgetc();
670: i += mgets(phd->hd_snto,NS);
671: i += mgets(phd->hd_spasswd,20);
672: i += mgets(phd->hd_sinfile,FNS);
673: i += mgets(phd->hd_soutfile,FNS);
674: i += mgets(phd->hd_srespfile,FNS);
675: i += mgets(phd->hd_snfrom,NS);
676:
677: /* addrfrom is the person who sent this to us,
678: addrto is the person who received the command, i.e.
679: addrto is on this machine */
680: if(phd->hd_snfrom[0] == 0)strcpy(phd->hd_snfrom,"root");
681: sprintf(phd->hd_addrfrom, "%s:%s",longname(phd->hd_mchfrom),phd->hd_snfrom);
682: sprintf(phd->hd_addrto, "%s:%s",longname(phd->hd_mchto),phd->hd_snto);
683:
684: i += mgets(phd->hd_sttyname,20);
685: if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx");
686: cflag = mgetc();
687: if(!phd->hd_mchfrom || !phd->hd_code || !cflag || !phd->hd_vmajor || !phd->hd_vminor){
688: error("mgetc fails");
689: return(-1);
690: }
691:
692: cflag -= 'a';
693: phd->hd_fnonotify = (cflag & F_NONOTIFY);
694: phd->hd_fquiet = (cflag & F_QUIET);
695:
696: phd->hd_vmajor -= 'a';
697: phd->hd_vminor -= 'a';
698:
699: i += mgets(sbuf,BUFSIZ);
700: phd->hd_lttytime = 0;
701: sscanf(sbuf,"%lo",&phd->hd_lttytime);
702:
703: i += mgets(parmlist,PARMLIST);
704: phd->hd_ijobno = atoi(parmlist);
705: /* keep variable parameter list in jobno slot */
706: parseparmlist(parmlist);
707:
708: i += mgets(sbuf,BUFSIZ); /* time sent */
709: sscanf(sbuf,"%ld",&phd->hd_ltimesent);
710: phd->hd_ltimesent += TIMEBASE;
711: i += mgetcmd(phd->hd_scmdact);
712: i += mgetcmd(phd->hd_scmdvirt);
713: if(i != 0){error("mgets fails"); return(-1);}
714: if(phd->hd_scmdvirt[0] == 0)strcpy(phd->hd_scmdvirt,phd->hd_scmdact);
715: return(0);
716: }
717: /*
718: check() -- verify login name and password
719: phd = login,passwd
720: fverify = 1 if password must check
721: Returns 1 if password is ok, 0 if not.
722: */
723: check(phd,fverify) /* 1 if OK, 0 if not */
724: register struct header *phd;
725: int fverify;
726: {
727: char *sencpasswd, *u, *nullstr = "";
728: struct passwd *pwd;
729: if(phd->hd_snto[0] == 0)return(!fverify);
730: if(!goodacctname(phd->hd_snto))return(!fverify);
731: pwd = getpwnam(phd->hd_snto);
732: if(pwd == NULL)return(!fverify);
733:
734: if(machtype[local-'a'] == M_CC && machtype[frommach-'a'] == M_CC)
735: sencpasswd = phd->hd_spasswd;
736: else if(*phd->hd_spasswd)sencpasswd = crypt(phd->hd_spasswd,pwd->pw_passwd);
737: else sencpasswd = nullstr;
738:
739: status.muid = guid(pwd->pw_uid,pwd->pw_gid);
740: status.mgid = pwd->pw_gid;
741: if(isdigit(pwd->pw_gecos[0]))status.jobno = atoi(pwd->pw_gecos);
742: else status.jobno = 32767;
743: strcpy(status.dir,pwd->pw_dir);
744: strcpy(status.loginshell,pwd->pw_shell);
745: u = status.loginshell;
746: if(u[0] == 0 || strcmp("/bin/sbash",u) == 0)strcpy(u,Bsh);
747:
748: getpwdf(pwd);
749: /* ignore network passwd */
750: /* acct is not a pair, acct is not "network", passwd is incorrect,
751: and verification is requested => passwd not ok */
752: if(!facctpaircheck(phd) && strcmp(phd->hd_snto,"network") != 0
753: && strcmp(pwd->pw_passwd,sencpasswd) != 0 && fverify)
754: return(0);
755: return(1); /* otherwise passwd ok */
756: }
757: mread(b,n)
758: register int n; {
759: if(length <= 0)return(0);
760: if(length < n)n = length;
761: n = nread(b,n);
762: if(n != BROKENREAD)length -= n;
763: return(n);
764: }
765: char mgetc(){ /* returns 0 if fail */
766: register char c;
767: register int n;
768: char buf[3];
769: if((n=nread(buf,3)) == BROKENREAD)return(0);
770: if(n != 3){error("bad read %d",n); return(0); }
771: c = buf[0];
772: if(buf[1] != ' ' && buf[1] != ':'){error("Bad char %c",buf[1]); return(0); }
773: length -= 3;
774: if(length < 0){error("length wrong2 %ld",length); return(0); }
775: return(c);
776: }
777: /* read in string over the network wire */
778: /* put string in s, max length is maxlen */
779: mgets(s,maxlen) /* returns 0 if ok, 1 if not */
780: int maxlen;
781: register char *s; {
782: register char *q;
783: register int n;
784: char c;
785: q = s;
786: for(;;) {
787: if((n=nread(&c,1)) == BROKENREAD){
788: *s = 0;
789: error("mgets %s",s);
790: return(1);
791: }
792: if(n == 0)break;
793: if(c == '\\'){
794: if((n=nread(&c,1)) == BROKENREAD){
795: *s = 0;
796: error("mgets %s",s);
797: return(1);
798: }
799: if(n == 0)break;
800: }
801: if(c == ' ')break;
802: if(maxlen-- > 0) *s++ = c;
803: }
804: *s = 0;
805: if(nread(&c,1) == BROKENREAD){
806: error("mgets %s",s);
807: return(1);
808: }
809: length -= (s - q + 2);
810: if(length < 0){error("length wrong1 %ld %s",length,q); return(-1); }
811: if(maxlen < 0)
812: error("mgets - string too long");
813: return(0);
814: }
815: mgetcmd(s) /* returns 0 if succeed, 1 otherwise */
816: char *s; {
817: int i,n;
818: char c;
819: i = 0;
820: for(;;){
821: if((n=nread(&c,1)) == BROKENREAD){
822: s[i] = 0;
823: error("mgetcmd %s",s);
824: return(1);
825: }
826: if(n <= 0 || c == '\n')break;
827: if(c == '\\'){
828: if(nread(&c,1) == BROKENREAD){
829: s[i] = 0;
830: error("mgetcmd %s",s);
831: return(1);
832: }
833: length--;
834: }
835: s[i++] = c;
836: length--;
837: }
838: s[i] = 0;
839: length--;
840: return(0);
841: }
842: increment(s)
843: char *s; {
844: int i;
845: char *p;
846: i = strlen(s) - 1;
847: while(s[i] == '9')i--;
848: if(s[i] < '0' || s[i] > '9'){
849: p = s+i+1;
850: while(*p)*p++ = '0';
851: return;
852: }
853: (s[i])++;
854: i++;
855: while(s[i])s[i++] = '0';
856: return;
857: }
858: /* gather 24-hour stats and mail to STATADDR */
859: /* should also gather stats on # error msgs */
860: dumpit(currt)
861: long currt; {
862: register struct dumpstruc *p = &dump;
863: register int ntot;
864: long elapt;
865: double cputime,utime,stime,bs,rawbs;
866: char *sstartt;
867: FILE *fdm;
868: char froma[30];
869: struct tms tbf;
870:
871: /* if STATADDR is a file, the mail program this call will
872: ultimately execute must be able to deal with it,
873: and the remote mail program must be able to write on the
874: file, i.e. mode 666 */
875: sprintf(froma,"%s=>",longname(local));
876: strcat(froma,longname(remote));
877: fdm = mailopen(STATADDR,froma,1,0);
878: if(fdm == NULL)return;
879:
880: /* calculate times */
881: elapt = currt - dump.longtime;
882: ntot = p->nnetcp + p->nnetmail + p->nsmail + p->nnetlpr
883: + p->nresp + p->nnet;
884: sstartt = ctime(&dump.longtime) + 4;
885: sstartt[strlen(sstartt) - 9] = 0;
886:
887: times(&tbf);
888: # ifndef NOFP
889: utime = tbf.tms_utime + tbf.tms_cutime;
890: stime = tbf.tms_stime + tbf.tms_cstime;
891: cputime = utime + stime;
892:
893: if(elapt > 0)cputime = (cputime/elapt) * 100.0;
894: else cputime = 0.0;
895: utime = utime/60.0;
896: stime = stime/60.0;
897: cputime = cputime/60.0;
898: bs = p->bytetot;
899: if(p->elaptot > 0)bs = bs /p->elaptot;
900: else bs = 0.0;
901: # endif
902:
903: /* print out the statistics */
904: fprintf(fdm,"Subject: %s, %s, time %s\n",
905: froma,sstartt, comptime(elapt));
906: fprintf(fdm,"Command summary:\n");
907: fprintf(fdm,"\t# sent %d\t# pass_thru %d\t# rcv %d:\t# netcp %d\n",
908: p->nsend,p->npass,ntot,p->nnetcp);
909: fprintf(fdm,"\t# netlpr %d\t# netmail %d\t# sendbmail %d\t# resp %d\n",
910: p->nnetlpr,p->nnetmail,p->nsmail,p->nresp);
911: fprintf(fdm,"Protocol summary:\n");
912: fprintf(fdm,"\t# pk_sent %d\t# pk_rcv %d\t# b_sent %ld\t# b_rcv %ld\n",
913: p->npacksent,p->npackrcv,p->nbytesent, p->nbytercv);
914: fprintf(fdm,
915: "\t# send_fails %d\t# retrans %d\t# abn %d\t\t# cksum_errs %d\n",
916: p->nsendfail,p->nretrans, p->nabnormal,p->ncksum);
917: # ifndef NOFP
918: fprintf(fdm,"Load:\tuser %4.1f\tsys %4.1f\tpct %5.2f\trate %6.1f\n",
919: utime,stime,cputime,bs);
920: rawbs = p->brawtot*100L;
921: rawbs = rawbs / linechars();
922: fprintf(fdm,"\trawbytes %ld\tuse %4.1f\n", p->brawtot,rawbs);
923: # endif
924: mailclose(fdm);
925:
926: /* reset counters */
927: p->nbytesent = p->nbytercv = p->elaptot = p->bytetot = 0L;
928: p->nretrans = p->nloop = p->nabnormal = p->ncksum = 0;
929: p->npacksent = p->npackrcv = p->nnetcp = p->nnetmail = 0;
930: p->nsmail = p->nnetlpr = p->nnet = p->npass = 0;
931: p->nsend = p->nsendfail = 0;
932: dump.longtime = currt;
933: }
934: /* returns 1 if n is ok, 0 if not */
935: goodacctname(n)
936: char *n; {
937: int i;
938: i = -1;
939: while(btable[++i].bname)
940: if(strcmp(btable[i].bname,n) == 0 &&
941: local == btable[i].bmach)return(0);
942: return(1);
943: }
944: demask(s)
945: register char *s; {
946: /*
947: static char buf[20];
948: char skey[30];
949: makeuukey(skey,status.login,local);
950: strcpy(s,nbsdecrypt(s,skey,buf));
951: */
952: while(*s){
953: *s &= 0177; /* strip quote bites */
954: *s++ ^= 040; /* invert upper-lower */
955: }
956: }
957: /*VARARGS0*/
958: mreopen(fsendtofmach,phd,sfn,a,b,c){
959: /* simply handles errors by giving error msg */
960: if(freopen(a,b,c) == NULL)
961: errormsg(fsendtofmach,phd,sfn,"%s: %s",a,sys_errlist[errno]);
962: }
963: /*
964: addtopub(string, args)
965:
966: add a message to the public logfile /usr/net/logfile.
967: note that the file must be writeable by everyone
968: if error messages from the netrcv subroutine
969: such as chdir errors are to be noticed.
970: */
971: /*VARARGS0*/
972: addtopublic(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n)
973: char *s;
974: {
975: static FILE *log = NULL;
976: if(log == NULL){
977: if(stat(publogfile,&statbuf) < 0)return;
978: log = fopen(publogfile,"a");
979: if(log == NULL)return;
980: }
981: fseek(log,0L,2);
982: fprintf(log,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n);
983: fflush(log);
984: }
985: /* set up a dummy environment for v7 /bin/sh */
986: setenv(home)
987: char *home; {
988: static char *env[3],benv[2][50];
989: env[0] = benv[0];
990: env[1] = benv[1];
991: strcpy(env[0],"PATH=:/bin:/usr/bin");
992: sprintf(env[1],"HOME=%s",home);
993: env[2] = 0;
994: environ = env;
995: }
996: /*
997: errormsg(fsendtofmach,phd,sfn,"string",arg(s))
998:
999: Sends error message to user.
1000: If fsendtofmach=TRUE, send to phd->hd_mchfrom, otherwise
1001: send to phd->hd_mchto.
1002: Also, if error occured during return of a "response",
1003: send to local machine.
1004:
1005: Note that errormsg can be called by the netrcv subroutine
1006: after the setuid() call to the specific user, so the
1007: user must be able to get off an error msg back to him,
1008: and to write in the two log files.
1009: Can't use -w,-x,-y,-z for the net cmd because must be root for those.
1010:
1011: If sfn != NULL, then unlink sfn before exiting.
1012: */
1013: /*VARARGS0*/
1014: errormsg(fsendtofmach,phd,sfn,s,a,b,c,d,e,f,g,h)
1015: char fsendtofmach;
1016: struct header *phd;
1017: char *sfn,*s;
1018: {
1019: int rcode;
1020: char errstr[BUFSIZ], cmdstr[BUFSIZ], rcmd[BUFSIZ];
1021: char toadd[FNS], fromadd[FNS], mchto, mchfrom;
1022: char snto[FNS], snfrom[FNS];
1023:
1024: if(phd->hd_sttyname[0] == 0)strcpy(phd->hd_sttyname,"/dev/ttyx");
1025: /* will send to toadd, from fromadd */
1026: if(!fsendtofmach || strcmp(phd->hd_scmdvirt,"response") == 0){
1027: /* send to tomach mach, thus send to toaddr. */
1028: /* if this is an error during a response, send to local mach. */
1029: strcpy(toadd, phd->hd_addrto);
1030: strcpy(fromadd,phd->hd_addrfrom);
1031: }
1032: else { /* send to remote mach, thus send back to addrfrom*/
1033: strcpy(toadd, phd->hd_addrfrom);
1034: strcpy(fromadd,phd->hd_addrto);
1035: }
1036: sprintf(errstr,"Error: ");
1037: sprintf(cmdstr,s,a,b,c,d,e,f,g,h);
1038: strcat(errstr,cmdstr);
1039: strcat(errstr,"\n");
1040: addtolog(remote,errstr);
1041: addtopublic(errstr);
1042:
1043: mchto = MchSFromAddr(snto,toadd);
1044: mchfrom = MchSFromAddr(snfrom,fromadd);
1045:
1046: sprintf(rcmd,
1047: "%s %s %s %lo %c %s \"'%s'\" %ld -t %s -f %s -x %ld -y %s -c \"'%s'\" -e %ld",
1048: MWRITECMD, snto, phd->hd_sttyname, phd->hd_lttytime,
1049: local, snfrom,phd->hd_scmdvirt, phd->hd_ltimesent-TIMEBASE,
1050: toadd, fromadd, phd->hd_lttytime, phd->hd_sttyname, phd->hd_scmdvirt,
1051: phd->hd_ltimesent-TIMEBASE);
1052:
1053: if(mchto == local)
1054: sprintf(cmdstr, "echo \"%s\" | %s", errstr,rcmd);
1055: else
1056: sprintf(cmdstr,
1057: "echo \"%s\" | %s -m%c -b -c errormessage -l network - %s",
1058: errstr,netcmd,mchto,rcmd);
1059: rcode = system(cmdstr);
1060: if(sfn != NULL)unlink(sfn);
1061: exit(EX_USAGE);
1062: }
1063: handlekill(){ /* SIGTERM signal */
1064: long t;
1065: /*
1066: t = gettime();
1067: dumpit(t);
1068: */
1069: exit(EX_OK); /* kill myself */
1070: }
1071:
1072: /* check a request to see if it is an acct pair */
1073: /* returns 1 if it is, 0 if not */
1074: static facctpaircheck(phd)
1075: register struct header *phd;
1076: {
1077: return(0);
1078: }
1079:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.