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