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