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: }

Defined functions

addir defined in line 395; used 1 times
blkcpy defined in line 549; used 1 times
cat defined in line 509; used 3 times
ckroot defined in line 442; used 1 times
enmask defined in line 388; used 1 times
fisacctpair defined in line 405; used 1 times
gwd defined in line 466; used 1 times
isdirectory defined in line 528; used 5 times
main defined in line 50; never used
outerror defined in line 373; used 21 times

Defined variables

dfname defined in line 48; used 21 times
net_sid defined in line 4; never used
off defined in line 415; used 4 times
sccsid defined in line 1; never used
status defined in line 45; used 35 times
x defined in line 413; used 18 times
xx defined in line 464; used 6 times
y defined in line 414; used 16 times
Last modified: 1982-10-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1692
Valid CSS Valid XHTML 1.0 Strict