|
|
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.