|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)uuxqt.c 5.2 (Berkeley) 7/2/83";
3: #endif
4:
5: #include "uucp.h"
6: #include <sys/types.h>
7: #include <sys/stat.h>
8: #ifdef NDIR
9: #include "ndir.h"
10: #else
11: #include <sys/dir.h>
12: #endif
13:
14: #define APPCMD(d) {\
15: char *p;\
16: for (p = d; *p != '\0';) *cmdp++ = *p++;\
17: *cmdp++ = ' ';\
18: *cmdp = '\0';}
19:
20: /*
21: * uuxqt will execute commands set up by a uux command,
22: * usually from a remote machine - set by uucp.
23: */
24:
25: #define NCMDS 50
26: char *Cmds[NCMDS];
27:
28: int notiok = 1;
29: int nonzero = 0;
30:
31: char PATH[MAXFULLNAME] = "PATH=/bin:/usr/bin";
32: /* to remove restrictions from uuxqt
33: * define ALLOK 1
34: *
35: * to add allowable commands, add to the file CMDFILE
36: * A line of form "PATH=..." changes the search path
37: */
38:
39:
40: main(argc, argv)
41: char *argv[];
42: {
43: char xcmd[MAXFULLNAME];
44: int argnok;
45: char xfile[MAXFULLNAME], user[32], buf[BUFSIZ];
46: char lbuf[30];
47: char cfile[NAMESIZE], dfile[MAXFULLNAME];
48: char file[NAMESIZE];
49: char fin[MAXFULLNAME], sysout[NAMESIZE], fout[MAXFULLNAME];
50: register FILE *xfp, *fp;
51: FILE *dfp;
52: char path[MAXFULLNAME];
53: char cmd[BUFSIZ];
54: /* set size of prm to something large -- cmcl2!salkind */
55: char *cmdp, prm[1000], *ptr;
56: char *getprm(), *lastpart();
57: int uid, ret, badfiles;
58: register int i;
59: int stcico = 0;
60: char retstat[30];
61: int orig_uid = getuid();
62:
63: strcpy(Progname, "uuxqt");
64: uucpname(Myname);
65:
66: /* Try to run as uucp -- rti!trt */
67: setgid(getegid());
68: setuid(geteuid());
69:
70: umask(WFMASK);
71: Ofn = 1;
72: Ifn = 0;
73: while (argc>1 && argv[1][0] == '-') {
74: switch(argv[1][1]){
75: case 'x':
76: chkdebug(orig_uid);
77: Debug = atoi(&argv[1][2]);
78: if (Debug <= 0)
79: Debug = 1;
80: break;
81: default:
82: fprintf(stderr, "unknown flag %s\n", argv[1]);
83: break;
84: }
85: --argc; argv++;
86: }
87:
88: DEBUG(4, "\n\n** %s **\n", "START");
89: subchdir(Spool);
90: strcpy(Wrkdir, Spool);
91: uid = getuid();
92: guinfo(uid, User, path);
93: DEBUG(4, "User - %s\n", User);
94: if (ulockf(X_LOCK, (time_t) X_LOCKTIME) != 0)
95: exit(0);
96:
97: fp = fopen(CMDFILE, "r");
98: if (fp == NULL) {
99: /* Fall-back if CMDFILE missing. Sept 1982, rti!trt */
100: logent("CAN'T OPEN", CMDFILE);
101: Cmds[0] = "rmail";
102: Cmds[1] = "rnews";
103: Cmds[2] = "ruusend";
104: Cmds[3] = NULL;
105: goto doprocess;
106: }
107: DEBUG(5, "%s opened\n", CMDFILE);
108: for (i=0; i<NCMDS-1 && cfgets(xcmd, sizeof(xcmd), fp) != NULL; i++) {
109: xcmd[strlen(xcmd)-1] = '\0';
110: if (strncmp(xcmd, "PATH=", 5) == 0) {
111: strcpy(PATH, xcmd);
112: i--; /* kludge */
113: continue;
114: }
115: DEBUG(5, "xcmd = %s\n", xcmd);
116: Cmds[i] = malloc((unsigned)(strlen(xcmd)+1));
117: strcpy(Cmds[i], xcmd);
118: }
119: Cmds[i] = 0;
120: fclose(fp);
121:
122: doprocess:
123: DEBUG(4, "process %s\n", "");
124: while (gtxfile(xfile) > 0) {
125: ultouch(); /* rti!trt */
126: DEBUG(4, "xfile - %s\n", xfile);
127:
128: xfp = fopen(subfile(xfile), "r");
129: ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0);
130:
131: /* initialize to default */
132: strcpy(user, User);
133: strcpy(fin, "/dev/null");
134: strcpy(fout, "/dev/null");
135: sprintf(sysout, "%.7s", Myname);
136: badfiles = 0; /* this was missing -- rti!trt */
137: while (fgets(buf, BUFSIZ, xfp) != NULL) {
138: switch (buf[0]) {
139: case X_USER:
140: sscanf(&buf[1], "%s%s", user, Rmtname);
141: break;
142: case X_STDIN:
143: sscanf(&buf[1], "%s", fin);
144: i = expfile(fin);
145: /* rti!trt: do not check permissions of
146: * vanilla spool file */
147: if (i != 0
148: && (chkpth("", "", fin) || anyread(fin) != 0))
149: badfiles = 1;
150: break;
151: case X_STDOUT:
152: sscanf(&buf[1], "%s%s", fout, sysout);
153: sysout[7] = '\0';
154: /* rti!trt: do not check permissions of
155: * vanilla spool file. DO check permissions
156: * of writing on a non-vanilla file */
157: i = 1;
158: if (fout[0] != '~' || prefix(sysout, Myname))
159: i = expfile(fout);
160: if (i != 0
161: && (chkpth("", "", fout)
162: || chkperm(fout, (char *)1)))
163: badfiles = 1;
164: break;
165: case X_CMD:
166: strcpy(cmd, &buf[2]);
167: if (*(cmd + strlen(cmd) - 1) == '\n')
168: *(cmd + strlen(cmd) - 1) = '\0';
169: break;
170: case X_NONOTI:
171: notiok = 0;
172: break;
173: case X_NONZERO:
174: nonzero = 1;
175: break;
176: default:
177: break;
178: }
179: }
180:
181: fclose(xfp);
182: DEBUG(4, "fin - %s, ", fin);
183: DEBUG(4, "fout - %s, ", fout);
184: DEBUG(4, "sysout - %s, ", sysout);
185: DEBUG(4, "user - %s\n", user);
186: DEBUG(4, "cmd - %s\n", cmd);
187:
188: /* command execution */
189: if (strcmp(fout, "/dev/null") == SAME)
190: strcpy(dfile,"/dev/null");
191: else
192: gename(DATAPRE, sysout, 'O', dfile);
193:
194: /* expand file names where necessary */
195: expfile(dfile);
196: strcpy(buf, PATH);
197: strcat(buf, ";export PATH;");
198: cmdp = buf + strlen(buf);
199: ptr = cmd;
200: xcmd[0] = '\0';
201: argnok = 0;
202: while ((ptr = getprm(ptr, prm)) != NULL) {
203: if (prm[0] == ';' || prm[0] == '^'
204: || prm[0] == '&' || prm[0] == '|') {
205: xcmd[0] = '\0';
206: APPCMD(prm);
207: continue;
208: }
209:
210: if ((argnok = argok(xcmd, prm)) != 0)
211: /* command not valid */
212: break;
213:
214: if (prm[0] == '~')
215: expfile(prm);
216: APPCMD(prm);
217: }
218: if (argnok || badfiles) {
219: sprintf(lbuf, "%s XQT DENIED", user);
220: logent(cmd, lbuf);
221: DEBUG(4, "bad command %s\n", prm);
222: notify(user, Rmtname, cmd, "DENIED");
223: goto rmfiles;
224: }
225: sprintf(lbuf, "%s XQT", user);
226: logent(buf, lbuf);
227: DEBUG(4, "cmd %s\n", buf);
228:
229: mvxfiles(xfile);
230: subchdir(XQTDIR);
231: ret = shio(buf, fin, dfile, (char *)NULL);
232: /* watcgl.11, dmmartindale, signal and exit values were reversed */
233: sprintf(retstat, "signal %d, exit %d", ret & 0377,
234: (ret>>8) & 0377);
235: if (strcmp(xcmd, "rmail") == SAME)
236: notiok = 0;
237: if (strcmp(xcmd, "rnews") == SAME)
238: nonzero = 1;
239: if (notiok && (!nonzero || (nonzero && ret != 0)))
240: notify(user, Rmtname, cmd, retstat);
241: else if (ret != 0 && strcmp(xcmd, "rmail") == SAME) {
242: /* mail failed - return letter to sender */
243: retosndr(user, Rmtname, fin);
244: sprintf(buf, "ret (%o) from %s!%s", ret, Rmtname, user);
245: logent("MAIL FAIL", buf);
246: }
247: DEBUG(4, "exit cmd - %d\n", ret);
248: subchdir(Spool);
249: rmxfiles(xfile);
250: if (ret != 0) {
251: /* exit status not zero */
252: dfp = fopen(subfile(dfile), "a");
253: ASSERT(dfp != NULL, "CAN'T OPEN", dfile, 0);
254: fprintf(dfp, "exit status %d", ret);
255: fclose(dfp);
256: }
257: if (strcmp(fout, "/dev/null") != SAME) {
258: if (prefix(sysout, Myname)) {
259: xmv(dfile, fout);
260: chmod(fout, BASEMODE);
261: }
262: else {
263: gename(CMDPRE, sysout, 'O', cfile);
264: fp = fopen(subfile(cfile), "w");
265: ASSERT(fp != NULL, "OPEN", cfile, 0);
266: fprintf(fp, "S %s %s %s - %s 0666\n",
267: dfile, fout, user, lastpart(dfile));
268: fclose(fp);
269: }
270: }
271: rmfiles:
272: xfp = fopen(subfile(xfile), "r");
273: ASSERT(xfp != NULL, "CAN'T OPEN", xfile, 0);
274: while (fgets(buf, BUFSIZ, xfp) != NULL) {
275: if (buf[0] != X_RQDFILE)
276: continue;
277: sscanf(&buf[1], "%s", file);
278: unlink(subfile(file));
279: }
280: unlink(subfile(xfile));
281: fclose(xfp);
282: }
283:
284: if (stcico)
285: xuucico("");
286: cleanup(0);
287: }
288:
289:
290: cleanup(code)
291: int code;
292: {
293: logcls();
294: rmlock(CNULL);
295: exit(code);
296: }
297:
298:
299: /*******
300: * gtxfile(file) get a file to execute
301: * char *file;
302: *
303: * return codes: 0 - no file | 1 - file to execute
304: * Mod to recheck for X-able files. Sept 1982, rti!trt.
305: * Suggested by utzoo.2458 (utzoo!henry)
306: * Uses iswrk/gtwrkf to keep files in sequence, May 1983.
307: */
308:
309: gtxfile(file)
310: register char *file;
311: {
312: char pre[3];
313: register int rechecked;
314:
315: pre[0] = XQTPRE;
316: pre[1] = '.';
317: pre[2] = '\0';
318: rechecked = 0;
319: retry:
320: if (!gtwrkf(Spool, file)) {
321: if (rechecked)
322: return(0);
323: rechecked = 1;
324: DEBUG(4, "iswrk\n", "");
325: if (!iswrk(file, "get", Spool, pre))
326: return(0);
327: }
328: DEBUG(4, "file - %s\n", file);
329: #ifndef UUDIR
330: /* skip spurious subdirectories */
331: if (strcmp(pre, file) == SAME)
332: goto retry;
333: #endif
334: if (gotfiles(file))
335: return(1);
336: goto retry;
337: }
338:
339:
340: /***
341: * gotfiles(file) check for needed files
342: * char *file;
343: *
344: * return codes: 0 - not ready | 1 - all files ready
345: */
346:
347: gotfiles(file)
348: register char *file;
349: {
350: struct stat stbuf;
351: register FILE *fp;
352: char buf[BUFSIZ], rqfile[MAXFULLNAME];
353:
354: fp = fopen(subfile(file), "r");
355: if (fp == NULL)
356: return(0);
357:
358: while (fgets(buf, BUFSIZ, fp) != NULL) {
359: DEBUG(4, "%s\n", buf);
360: if (buf[0] != X_RQDFILE)
361: continue;
362: sscanf(&buf[1], "%s", rqfile);
363: expfile(rqfile);
364: if (stat(subfile(rqfile), &stbuf) == -1) {
365: fclose(fp);
366: return(0);
367: }
368: }
369:
370: fclose(fp);
371: return(1);
372: }
373:
374:
375: /***
376: * rmxfiles(xfile) remove execute files to x-directory
377: * char *xfile;
378: *
379: * return codes - none
380: */
381:
382: rmxfiles(xfile)
383: register char *xfile;
384: {
385: register FILE *fp;
386: char buf[BUFSIZ], file[NAMESIZE], tfile[NAMESIZE];
387: char tfull[MAXFULLNAME];
388:
389: if((fp = fopen(subfile(xfile), "r")) == NULL)
390: return;
391:
392: while (fgets(buf, BUFSIZ, fp) != NULL) {
393: if (buf[0] != X_RQDFILE)
394: continue;
395: if (sscanf(&buf[1], "%s%s", file, tfile) < 2)
396: continue;
397: sprintf(tfull, "%s/%s", XQTDIR, tfile);
398: unlink(subfile(tfull));
399: }
400: fclose(fp);
401: return;
402: }
403:
404:
405: /***
406: * mvxfiles(xfile) move execute files to x-directory
407: * char *xfile;
408: *
409: * return codes - none
410: */
411:
412: mvxfiles(xfile)
413: char *xfile;
414: {
415: register FILE *fp;
416: char buf[BUFSIZ], ffile[MAXFULLNAME], tfile[NAMESIZE];
417: char tfull[MAXFULLNAME];
418: int ret;
419:
420: if((fp = fopen(subfile(xfile), "r")) == NULL)
421: return;
422:
423: while (fgets(buf, BUFSIZ, fp) != NULL) {
424: if (buf[0] != X_RQDFILE)
425: continue;
426: if (sscanf(&buf[1], "%s%s", ffile, tfile) < 2)
427: continue;
428: expfile(ffile);
429: sprintf(tfull, "%s/%s", XQTDIR, tfile);
430: /* duke!rti, ncsu!mcm: use xmv, not link(II) */
431: unlink(subfile(tfull));
432: ret = xmv(ffile, tfull);
433: ASSERT(ret == 0, "XQTDIR ERROR", "", ret);
434: }
435: fclose(fp);
436: return;
437: }
438:
439:
440: /***
441: * argok(xc, cmd) check for valid command/argumanet
442: * *NOTE - side effect is to set xc to the
443: * command to be executed.
444: * char *xc, *cmd;
445: *
446: * return 0 - ok | 1 nok
447: */
448:
449: argok(xc, cmd)
450: register char *xc, *cmd;
451: {
452: register char **ptr;
453:
454: #ifndef ALLOK
455: /* don't allow sh command strings `....` */
456: /* don't allow redirection of standard in or out */
457: /* don't allow other funny stuff */
458: /* but there are probably total holes here */
459: /* post-script. ittvax!swatt has a uuxqt that solves this. */
460: /* This version of uuxqt will shortly disappear */
461: if (index(cmd, '`') != NULL
462: || index(cmd, '>') != NULL
463: || index(cmd, ';') != NULL
464: || index(cmd, '^') != NULL
465: || index(cmd, '&') != NULL
466: || index(cmd, '|') != NULL
467: || index(cmd, '<') != NULL)
468: return(1);
469: #endif
470:
471: if (xc[0] != '\0')
472: return(0);
473:
474: #ifndef ALLOK
475: ptr = Cmds;
476: while(*ptr != NULL) {
477: if (strcmp(cmd, *ptr) == SAME)
478: break;
479: ptr++;
480: }
481: if (*ptr == NULL)
482: return(1);
483: #endif
484: strcpy(xc, cmd);
485: return(0);
486: }
487:
488:
489: /***
490: * notify send mail to user giving execution results
491: * return code - none
492: * This program assumes new mail command - send remote mail
493: */
494:
495: notify(user, rmt, cmd, str)
496: char *user, *rmt, *cmd, *str;
497: {
498: char text[MAXFULLNAME];
499: char ruser[MAXFULLNAME];
500:
501: sprintf(text, "uuxqt cmd (%.50s) status (%s)", cmd, str);
502: if (prefix(rmt, Myname))
503: strcpy(ruser, user);
504: else
505: sprintf(ruser, "%s!%s", rmt, user);
506: mailst(ruser, text, "");
507: return;
508: }
509:
510: /***
511: * retosndr - return mail to sender
512: *
513: * return code - none
514: */
515:
516: retosndr(user, rmt, file)
517: char *user, *rmt, *file;
518: {
519: char ruser[100];
520:
521: if (strcmp(rmt, Myname) == SAME)
522: strcpy(ruser, user);
523: else
524: sprintf(ruser, "%s!%s", rmt, user);
525:
526: if (anyread(file) == 0)
527: mailst(ruser, "Mail failed. Letter returned to sender.\n", file);
528: else
529: mailst(ruser, "Mail failed. Letter returned to sender.\n", "");
530: return;
531: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.