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