|
|
1.1 root 1: static char sccsid[] = "@(#)net.c 4.2 (Berkeley) 9/12/82";
2:
3: /* sccs id variable */
4: static char *net_sid = "@(#)net.c 1.8";
5:
6: # include "defs.h"
7: /* must be setuid root */
8: /*
9: net - -b -c cmd -f -i file -l name -mmach -n -o file -p passwd
10: -r file -s file -u uid -w -x -y -z command
11:
12: - take from standard input
13: -b never send anything back
14: -c cmd think of this as a "cmd" *
15: -f force prompting of user name and password
16: -i file remote stdin *
17: -l name remote login name
18: -m Mach remote machine
19: -n do not write back anything, always mail them back
20: -o file remote stdout & stderr *
21: -p pass remote password
22: -q quiet option, send back only if rcode !=0 or if there is stdout
23: -r file local response file
24: -s file local stdin file *
25:
26: (super users only, always skip login/passwd check:)
27: -u uid net queue files should be owned by uid (16 bits)
28: -w this is a write/mail response cmd *
29: -x this is being forwarded through us to another machine *
30: -y skip login/password check *
31: -z this is a response file being returned *
32:
33: * = not documented in net(NEW)
34:
35: */
36: /*
37: code option reason
38: q normal request
39: w -w message to be written back
40: -x being forwarded through us
41: y -y simply skips login check (used by netlpr)
42: s -z normal response
43: */
44: /* global variables */
45: struct userinfo status;
46:
47: /* local variables */
48: static char dfname[]= DFNAME;
49:
50: main(argc, argv)
51: char **argv; {
52: register int i;
53: int outerror(),uid;
54: char localin[FNS], skey[30];
55: char buf[BUFSIZ], suid[10];
56: char sin =0, zopt = 0, wopt = 0, yopt = 0, xopt = 0;
57: char *s,**sargv;
58: long cnt = 0L, maxfile = MAXFILELARGE;
59: FILE *file, *temp, *rfile;
60: struct utmp *putmp;
61: struct stat statbuf;
62: struct header hd;
63:
64: debugflg = DBV;
65: hd.hd_scmdact[0] = hd.hd_srespfile[0] = hd.hd_soutfile[0] = 0;
66: hd.hd_sinfile[0] = hd.hd_scmdvirt[0] = hd.hd_sttyname[0] = 0;
67: localin[0] = 0;
68: suid[0] = 0;
69: sargv = argv;
70:
71: if(isatty(0)) strcat(hd.hd_sttyname,ttyname(0));
72: else if(isatty(2)) strcat(hd.hd_sttyname,ttyname(2));
73: remote = 0;
74: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
75: signal(SIGHUP, outerror);
76: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
77: signal(SIGQUIT, outerror);
78: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
79: signal(SIGINT, outerror);
80: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
81: signal(SIGTERM, outerror);
82:
83: while(argc > 1 && argv[1][0] == '-'){
84: argc--; argv++;
85: switch(argv[0][1]){
86: case 0:
87: sin++;
88: break;
89: case 'b':
90: status.nonotify++;
91: break;
92: case 'c':
93: harg(hd.hd_scmdvirt);
94: break;
95: case 'f':
96: status.force++;
97: break;
98: case 'i':
99: harg(hd.hd_sinfile);
100: break;
101: case 'l':
102: harg(status.login);
103: break;
104: case 'm':
105: harg(buf);
106: remote = lookup(buf);
107: if(remote == 0){
108: fprintf(stderr,"Unknown machine %s\n",buf);
109: exit(EX_NOHOST);
110: }
111: break;
112: case 'n':
113: status.nowrite++;
114: break;
115: case 'o':
116: harg(hd.hd_soutfile);
117: break;
118: case 'p':
119: harg(status.mpasswd);
120: if(status.mpasswd[0] == 0)
121: strcpy(status.mpasswd,"\n\n");
122: break;
123: case 'q':
124: status.quiet++;
125: break;
126: case 'r':
127: harg(buf);
128: addir(hd.hd_srespfile,buf);
129: break;
130: case 's':
131: harg(localin);
132: break;
133: case 'u':
134: harg(suid);
135: break;
136: case 'w':
137: wopt++;
138: break;
139: case 'x':
140: xopt++;
141: break;
142: case 'y':
143: yopt++;
144: break;
145: case 'z':
146: zopt++;
147: break;
148: default:
149: fprintf(stderr,"Unknown option %s\n",argv[0]);
150: break;
151: }
152: }
153: while(argc > 1){
154: argc--; argv++;
155: strcat(hd.hd_scmdact,argv[0]);
156: strcat(hd.hd_scmdact," ");
157: }
158: sargv[1] = 0; /* so ps won't show passwd ??? */
159: hd.hd_uidfrom = uid = getuid();
160: hd.hd_gidfrom = getgid();
161: hd.hd_code = 'q';
162: if(zopt || wopt || yopt || xopt || suid[0] != 0){
163: /* check z or w or y or x option permission */
164: # ifndef TESTING
165: /* check effective user id ?? */
166: if (uid != SUPERUSER && uid != NUID) {
167: fprintf(stderr, "Error: Not super-user\n");
168: fprintf(stderr,"zopt %d wopt %d yopt %d xopt %d suid[0] %s\n", zopt, wopt, yopt, xopt, suid);
169: fprintf(stderr,"uid %d\n", uid);
170: debugflg = 1;
171: printhd(&hd);
172: outerror(EX_UNAVAILABLE);
173: }
174: # endif
175: hd.hd_code = zopt? 's': 'w';
176: hd.hd_code = yopt? 'y': hd.hd_code;
177: if (status.mpasswd[0] == 0) /* no passwd required */
178: strcpy(status.mpasswd, "\n");
179: debug("zopt %d wopt %d yopt %d xopt %d suid[0] %s\n", zopt, wopt, yopt, xopt, suid);
180: debug("uid %d\n", uid);
181: if(xopt)
182: setuid(SUPERUSER);
183: }
184: #ifdef CRN
185: strcpy( status.jobno, MAGICCRN ); /* default (invalid) crn */
186: #else
187: strcpy( status.jobno, "XYZZ"); /* default (invalid) crn */
188: #endif
189:
190: if(hd.hd_code == 'q' && !xopt){
191: /* read passwd file, get status.localname & crn */
192: passwdent();
193: }
194:
195: /* sets remote,status.login,status.force,status.mpasswd,
196: status.nonotify, status.nowrite */
197: /* may read passwd file if getenv(HOME) reads it */
198: commandfile();
199: if(status.force)status.login[0] = status.mpasswd[0] = 0;
200:
201: /* look up login name and passwd in the environment */
202: envloginpasswd(remote,status.login,status.mpasswd);
203:
204:
205: if(remote == 0)remote = getremote(local);
206: # ifndef TESTING
207: if(remote == local){
208: fprintf(stderr,"Request sent to local machine - doesn't make sense\n");
209: /* outerror(); */
210: }
211: # endif
212: strcat(status.defcmd," ");
213: if(strlen(hd.hd_scmdact) == 0)strcpy(hd.hd_scmdact,status.defcmd);
214: hd.hd_scmdact[strlen(hd.hd_scmdact)-1] = 0;
215: do {
216: mktemp(dfname); /* make until unique!! */
217: } while(stat(dfname,&statbuf) >= 0);
218: /* determine through machine */
219: i = gothru(local,remote);
220: if(i == 0){
221: s = longname(remote);
222: if(s != 0)fprintf(stderr,"No path to %s machine.\n",s);
223: else fprintf(stderr,"Unknown machine\n");
224: outerror(EX_NOHOST);
225: }
226: dfname[strlen(dfname)-11] = i; /* set directory */
227: dfname[strlen(dfname)-7] = i; /* set file (unused) */
228: /* check to see if data files are directories */
229: if(isdirectory(hd.hd_srespfile) || isdirectory(hd.hd_sinfile) || isdirectory(hd.hd_soutfile)){
230: fprintf(stderr,"%s is a directory, must be a file\n",
231: isdirectory(hd.hd_srespfile) ? hd.hd_srespfile :
232: isdirectory(hd.hd_sinfile) ? hd.hd_sinfile :
233: hd.hd_soutfile);
234: outerror(EX_USAGE);
235: }
236: if(suid[0] != 0)uid = atoi(suid);
237: if(hd.hd_srespfile[0]){
238: if(strcmp(hd.hd_srespfile,"/dev/tty") == 0){
239: fprintf(stderr,"Can't have /dev/tty as response file.\n");
240: outerror(EX_USAGE);
241: }
242: if(stat(hd.hd_srespfile,&statbuf) == -1){
243: strcpy(buf,hd.hd_srespfile);
244: s = &buf[0];
245: s = s + strlen(buf) - 1;
246: while(*s != '/' && s > &(buf[0]))s--;
247: *s = 0;
248: debug("chkdir %s",buf);
249: if(strlen(buf) == 0)strcpy(buf,".");
250: if(access(buf,2) == -1){
251: perror(buf);
252: outerror(EX_USAGE);
253: }
254: if((rfile=fopen(hd.hd_srespfile,"w")) == NULL){
255: perror(hd.hd_srespfile);
256: outerror(EX_USAGE);
257: }
258: chmod(hd.hd_srespfile,0600);
259: fclose(rfile);
260: mchown(hd.hd_srespfile,uid,hd.hd_gidfrom);
261: }
262: else if(access(hd.hd_srespfile,2) == -1){
263: perror(hd.hd_srespfile);
264: outerror(EX_USAGE);
265: }
266: else if(getsize(&statbuf) != 0L){
267: fprintf(stderr,"%s must have 0-length or not exist\n",
268: hd.hd_srespfile);
269: outerror(EX_USAGE);
270: }
271: }
272: /* go ahead and prompt for login name and passwd, if neccessary,
273: as long as the X option has not been specified */
274: if(hd.hd_code == 'q' && !xopt)promptlogin(remote);
275:
276: /* at this point, we create the dfa... file */
277: file = fopen(dfname,"w");
278: if(file == NULL){
279: perror(dfname);
280: outerror(EX_OSERR);
281: }
282: chmod(dfname,0600);
283: mchown(dfname,uid,getgid());
284: if(xopt)goto stickit;
285: if(status.mpasswd[0] == '\n')
286: status.mpasswd[0] = 0;
287: if(status.mpasswd[0] == 0 && hd.hd_code == 'q' &&
288: strcmp(status.login,"network") != 0){
289: fprintf(stderr,"Zero-length password not allowed\n");
290: outerror(EX_USAGE);
291: }
292: if(hd.hd_code == 'q' && (streql(status.login,"root") == 0 ||
293: streql(status.login,"ruut") == 0)){
294: fprintf(stderr,"Can't login as root through the network\n");
295: outerror(EX_USAGE);
296: }
297: makeuukey(skey,status.login,remote);
298: nbsencrypt(status.mpasswd,skey,hd.hd_sencpasswd);
299: enmask(status.mpasswd);
300: hd.hd_lttytime = 0;
301: if(hd.hd_sttyname[0] && status.nowrite == 0){
302: putmp = getutmp(hd.hd_sttyname);
303: if(putmp != NULL) hd.hd_lttytime = putmp->ut_time;
304: }
305: /*
306: debug("p:%s:\n",status.mpasswd);
307: */
308: /* write the header info onto 'file' */
309: hd.hd_mchto = remote;
310: hd.hd_mesgid.msg_mch = hd.hd_mchfrom = local;
311: hd.hd_vmajor = VMAJOR;
312: hd.hd_vminor = VMINOR;
313: strcpy(hd.hd_snto,status.login);
314: strcpy(hd.hd_snfrom,status.localname);
315: strcpy(hd.hd_spasswd,status.mpasswd);
316: strcpy(hd.hd_ijobno, status.jobno );
317: hd.hd_mesgid.msg_ltime = hd.hd_ltimesent = gettime();
318: hd.hd_fquiet = status.quiet;
319: hd.hd_fnonotify = status.nonotify;
320: hd.hd_mesgid.msg_pid = getpid();
321: hd.hd_fcompressed = 0;
322: /* handle account pairs, accounts which do not require
323: a passwd if you are logged in on the same one here */
324: hd.hd_facctpair = fisacctpair(&hd);
325:
326: writehdfd(&hd,file);
327: printhd(&hd);
328: stickit:
329: if(sin)
330: while((i = fread(buf,1,BUFSIZ,stdin)) > 0){
331: if(fwrite(buf,1,i,file) != i){
332: perror("net queue file");
333: outerror(EX_OSFILE);
334: }
335: if((cnt += i) > maxfile)goto toobig;
336: if(feof(stdin))break;
337: }
338: else if(localin[0]){
339: if(access(localin,4) == -1){
340: perror(localin);
341: outerror(EX_OSFILE);
342: }
343: temp = fopen(localin,"r");
344: if(temp == NULL){
345: perror(localin);
346: outerror(EX_OSFILE);
347: }
348: while((i = fread(buf,1,BUFSIZ,temp)) > 0){
349: if((cnt += i) > maxfile)goto toobig;
350: if(fwrite(buf,1,i,file) != i){
351: perror("net queue file");
352: outerror(EX_OSFILE);
353: }
354: }
355: fclose(temp);
356: }
357: fclose(file);
358: chmod(dfname,0400);
359: dfname[strlen(dfname)-9] = 'c';
360: file = fopen(dfname,"w");
361: chmod(dfname,0400);
362: fclose(file);
363: mchown(dfname,uid,getgid());
364: exit(EX_OK);
365: toobig:
366: fprintf(stderr,"No more than %ld bytes can be sent\n",maxfile);
367: outerror(EX_USAGE); /* no return */
368: }
369: /*
370: called if there is an error, makes sure that the files created
371: are deleted and the terminal is reset to echo
372: */
373: outerror(ret){
374: register int i;
375: struct sgttyb stt;
376: signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN);
377: signal(SIGQUIT,SIG_IGN); signal(SIGTERM,SIG_IGN);
378: unlink(dfname);
379: i = strlen(dfname) - 9;
380: dfname[i] = (dfname[i] == 'c' ? 'd' : 'c');
381: unlink(dfname);
382: if(gtty(0,&stt) >= 0){
383: stt.sg_flags |= ECHO;
384: stty(0,&stt);
385: }
386: exit(ret);
387: }
388: enmask(s)
389: register char *s; {
390: while(*s){
391: *s &= 0177; /* strip quote bites */
392: *s++ ^= 040; /* invert upper-lower */
393: }
394: }
395: addir(s,t)
396: register char *s, *t; {
397: if(t[0] == '/')strcpy(s,t);
398: else {
399: gwd(s);
400: strcat(s,t);
401: }
402: }
403:
404: /* returns true if phd is an account pair, false otherwise */
405: fisacctpair(phd)
406: register struct header *phd;
407: {
408: return(0);
409: }
410:
411:
412:
413: static struct stat x;
414: static struct direct y;
415: static int off = -1;
416:
417:
418: /* these three routines gwd, cat, ckroot and
419: data structures x, y, off, do a pwd to string name */
420: #ifdef V6
421: static FILE *file;
422:
423: gwd(name)
424: register char *name; {
425: *name = 0;
426: for(;;){
427: stat(".",&x);
428: if((file = fopen("..","r")) == NULL)break;
429: do {
430: if(fread(&y,1,sizeof y,file) != sizeof y)break;
431: } while(y.d_ino != x.st_ino);
432: fclose(file);
433: if(y.d_ino == ROOTINO){
434: ckroot(name);
435: break;
436: }
437: if(cat(name))break;
438: chdir("..");
439: }
440: chdir(name);
441: }
442: ckroot(name)
443: char *name; {
444: register int i;
445: if(stat(y.d_name,&x) < 0)return;
446: i = x.st_dev;
447: if(chdir("/") < 0)return;
448: if((file = fopen("/","r")) == NULL)return;
449: do {
450: if(fread(&y,1,sizeof y,file) != sizeof y)return;
451: if(y.d_ino == 0)continue;
452: if(stat(y.d_name,&x) < 0)return;
453: } while(x.st_dev!=i || (x.st_mode&S_IFMT)!=S_IFDIR);
454: if(strcmp(y.d_name,".") != 0 && strcmp(y.d_name,"..") != 0)
455: if(cat(name))return;
456: i = strlen(name);
457: name[i+1] = 0;
458: while(--i >= 0)name[i + 1] = name[i];
459: name[0] = '/';
460: return;
461: }
462: #else
463: static DIR *file;
464: static struct stat xx;
465:
466: gwd(name)
467: register char *name; {
468: int rdev, rino;
469: register int i;
470: register struct direct *dp;
471:
472: *name = 0;
473: stat("/", &x);
474: rdev = x.st_dev;
475: rino = x.st_ino;
476: for (;;) {
477: stat(".", &x);
478: if (x.st_ino == rino && x.st_dev == rdev)
479: break;
480: if ((file = opendir("..")) == NULL)
481: break;
482: fstat(file->dd_fd, &xx);
483: chdir("..");
484: if (x.st_dev == xx.st_dev) {
485: if (x.st_ino == xx.st_ino)
486: break;
487: do
488: if ((dp = readdir(file)) == NULL)
489: break;
490: while (dp->d_ino != x.st_ino);
491: }
492: else do {
493: if ((dp = readdir(file)) == NULL)
494: break;
495: stat(dp->d_name, &xx);
496: } while (xx.st_ino != x.st_ino || xx.st_dev != x.st_dev);
497: blkcpy(dp, &y, DIRSIZ(dp));
498: closedir(file);
499: if (cat(name))
500: break;
501: }
502: i = strlen(name);
503: name[i+1] = 0;
504: while (--i >= 0) name[i+1] = name[i];
505: name[0] = '/';
506: }
507: #endif
508:
509: cat(name)
510: register char *name; { /* return 1 to exit */
511: register int i,j;
512: i = -1;
513: while(y.d_name[++i] != 0);
514: if((off+i+2) > 511)return(1);
515: for(j = off +1; j >= 0; --j)name[j+i+1] = name[j];
516: off = i + off + 1;
517: name[i] = '/';
518: for(--i; i>= 0; --i)name[i] = y.d_name[i];
519: return(0);
520: }
521:
522:
523: /*
524: this function takes a file name and tells whether it is a
525: directory or on. Returns 1 if so, 0 otherwise.
526: null strings etc. return 0.
527: */
528: isdirectory(fn)
529: char *fn;
530: {
531: int i,ret=0;
532: if(fn == NULL || *fn == 0)return(0);
533: i = strlen(fn);
534: if(i == 1){
535: if(strcmp(fn,".") == 0)ret = 1;
536: if(strcmp(fn,"/") == 0)ret = 1;
537: }
538: else if(i == 2){
539: if(strcmp(fn,"..") == 0)ret = 1;
540: if(strcmp(fn,"/.") == 0)ret = 1;
541: }
542: else {
543: if(strcmp(fn+i-2,"/.") == 0)ret = 1;
544: if(strcmp(fn+i-3,"/..") == 0)ret = 1;
545: }
546: return(ret);
547: }
548:
549: blkcpy(from, to, size)
550: register *from, *to;
551: register int size;
552: {
553: while (size-- > 0)
554: *to++ = *from++;
555: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.