Annotation of 3BSD/cmd/net/net.c, revision 1.1

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: static char dfname[]=          DFNAME;
        !            40: 
        !            41: main(argc, argv)
        !            42:   char **argv; {
        !            43:        register int i;
        !            44:        int outerror(),uid;
        !            45:        char *genparmlist();
        !            46:        char resp[FNS], infile[FNS], outfile[FNS], localin[FNS];
        !            47:        char buf[BUFSIZ], suid[10];
        !            48:        char sin =0, code, zopt = 0, wopt = 0, yopt = 0, xopt = 0;
        !            49:        char *s,*sn;
        !            50:        char sTtyname[20], sCmdAct[BUFSIZ], sCmdVirt[BUFSIZ];
        !            51:        long cnt = 0L, maxfile = MAXFILE, lTtytime;
        !            52:        char cflag = 'a';
        !            53:        FILE *file, *temp, *rfile;
        !            54:        struct utmp utmpstr;
        !            55:        struct stat statbuf;
        !            56: 
        !            57:        debugflg = DBV;
        !            58:        argv[argc] = 0;
        !            59:        sCmdAct[0] = resp[0] = outfile[0] = infile[0] = 0;
        !            60:        sCmdVirt[0] = localin[0] = 0;
        !            61:        sTtyname[0] = 0;
        !            62:        suid[0] = 0;
        !            63: 
        !            64:        if(isatty(0)) strcat(sTtyname,ttyname(0));
        !            65:        else if(isatty(2)) strcat(sTtyname,ttyname(2));
        !            66:        remote = 0;
        !            67:        signal(SIGHUP,outerror);
        !            68:        signal(SIGQUIT,outerror);
        !            69:        signal(SIGINT,outerror);
        !            70:        signal(SIGTRM,outerror);
        !            71: 
        !            72:        while(argc > 1 && argv[1][0] == '-'){
        !            73:                argc--; argv++;
        !            74:                switch(argv[0][1]){
        !            75:                case 0:   sin++; break;
        !            76:                case 'b': status.nonotify++; break;
        !            77:                case 'c': harg(sCmdVirt,&argc,&argv); break;
        !            78:                case 'f': status.force++; break;
        !            79:                case 'i': harg(infile,&argc,&argv); break;
        !            80:                case 'l': harg(status.login,&argc,&argv); break;
        !            81:                case 'm': harg(buf,&argc,&argv); remote = lookup(buf); break;
        !            82:                case 'n': status.nowrite++; break;
        !            83:                case 'o': harg(outfile,&argc,&argv); break;
        !            84:                case 'p':
        !            85:                          harg(status.mpasswd,&argc,&argv);
        !            86:                          if(status.mpasswd[0] == 0)
        !            87:                                strcpy(status.mpasswd,"\n\n");
        !            88:                          break;
        !            89:                case 'q': status.quiet++; break;
        !            90:                case 'r': harg(buf,&argc,&argv); addir(resp,buf); break;
        !            91:                case 's': harg(localin,&argc,&argv); break;
        !            92:                case 'u': harg(suid,&argc,&argv); break;
        !            93:                case 'w': wopt++; break;
        !            94:                case 'x': xopt++; break;
        !            95:                case 'y': yopt++; break;
        !            96:                case 'z': zopt++; break;
        !            97:                default:
        !            98:                        fprintf(stderr,"Unknown option %s\n",argv[0]);
        !            99:                        break;
        !           100:                }
        !           101:                }
        !           102:        while(argc > 1){
        !           103:                argc--; argv++;
        !           104:                strcat(sCmdAct,argv[0]);
        !           105:                strcat(sCmdAct," ");
        !           106:                }
        !           107:        uid = getuid();
        !           108:        code = 'q';
        !           109:        if(zopt || wopt || yopt || xopt || suid[0] != 0){
        !           110:                /* check z or w or y or x option permission */
        !           111: # ifndef TESTING
        !           112:                if(uid != SUPERUSER){
        !           113:                        fprintf(stderr,"Error: Not super-user");
        !           114:                        outerror();
        !           115:                        }
        !           116: # endif
        !           117:                code = zopt ? 's' : 'w';
        !           118:                code = yopt ? 'y' : code;
        !           119:                if(status.mpasswd[0] == 0)      /* no passwd required */
        !           120:                        strcpy(status.mpasswd,"\n");
        !           121:                }
        !           122: 
        !           123:        status.jobno = 32767;           /* default (invalid) job number */
        !           124:        if(code == 'q' && !xopt){
        !           125:                if((sn = SnCurrent()) == NULL
        !           126:                /* || machtype[local-'a'] == M_CC */)
        !           127:                        /* turns out we never use jobno, except in netlpr */
        !           128:                        /* read passwd file, get status.localname & jobno */
        !           129:                        passwdent();
        !           130:                else
        !           131:                        /* don't bother reading passwd file, don't need jobno */
        !           132:                        strcpy(status.localname,sn);
        !           133:        }
        !           134: 
        !           135:        /* sets remote,status.login,status.force,status.mpasswd,
        !           136:                status.nonotify, status.nowrite */
        !           137:        /* may read passwd file if getenv(HOME) reads it */
        !           138:        commandfile();
        !           139: 
        !           140:        if(remote == 0)remote = getremote(local);
        !           141: # ifndef TESTING
        !           142:        if(remote == local){
        !           143:                fprintf(stderr,"Request sent to local machine - doesn't make sense\n");
        !           144:                /* outerror(); */
        !           145:                }
        !           146: # endif
        !           147:        strcat(status.defcmd," ");
        !           148:        if(strlen(sCmdAct) == 0)strcpy(sCmdAct,status.defcmd);
        !           149:        sCmdAct[strlen(sCmdAct)-1] = 0;
        !           150:        mktemp(dfname);
        !           151:        /* determine through machine */
        !           152:        i = gothru(local,remote);
        !           153:        if(i == 0){
        !           154:                s = longname(remote);
        !           155:                if(s != 0)fprintf(stderr,"No path to %s machine.\n",s);
        !           156:                else fprintf(stderr,"Unknown machine\n");
        !           157:                outerror();
        !           158:                }
        !           159:        dfname[strlen(dfname)-11] = i;          /* set directory */
        !           160:        dfname[strlen(dfname)-7] = i;           /* set file (unused) */
        !           161:        /* check to see if data files are directories */
        !           162:        if(isdirectory(resp) || isdirectory(infile) || isdirectory(outfile)){
        !           163:                fprintf(stderr,"%s is a directory, must be a file\n",
        !           164:                        isdirectory(resp)    ? resp :
        !           165:                        isdirectory(infile)  ? infile :
        !           166:                        outfile);
        !           167:                outerror();
        !           168:        }
        !           169:        if(suid[0] != 0)uid = atoi(suid);
        !           170:        if(resp[0]){
        !           171:                if(strcmp(resp,"/dev/tty") == 0){
        !           172:                fprintf(stderr,"Can't have /dev/tty as response file.\n");
        !           173:                        outerror();
        !           174:                        }
        !           175:                if(stat(resp,&statbuf) == -1){
        !           176:                        strcpy(buf,resp);
        !           177:                        s = &buf[0];
        !           178:                        s = s + strlen(buf) - 1;
        !           179:                        while(*s != '/' && s > &(buf[0]))s--;
        !           180:                        *s = 0;
        !           181:                        debug("chkdir %s",buf);
        !           182:                        if(strlen(buf) == 0)strcpy(buf,".");
        !           183:                        if(access(buf,2) == -1){
        !           184:                                perror(buf);
        !           185:                                outerror();
        !           186:                                }
        !           187:                        if((rfile=fopen(resp,"w")) == NULL){
        !           188:                                perror(resp);
        !           189:                                outerror();
        !           190:                                }
        !           191:                        chmod(resp,0600);
        !           192:                        fclose(rfile);
        !           193:                        mchown(resp,uid,getgid());
        !           194:                        }
        !           195:                else if(access(resp,2) == -1){
        !           196:                        perror(resp);
        !           197:                        outerror();
        !           198:                        }
        !           199:                }
        !           200:        /* go ahead and prompt for login name and passwd, if neccessary,
        !           201:           as long as the X option has not been specified */
        !           202:        if(code == 'q' && !xopt)promptlogin(remote);
        !           203: 
        !           204:        /* at this point, we create the dfa... file */
        !           205:        file = fopen(dfname,"w");
        !           206:        if(file == NULL){
        !           207:                perror(dfname);
        !           208:                outerror();
        !           209:                }
        !           210:        chmod(dfname,0600);
        !           211:        mchown(dfname,uid,getgid());
        !           212:        if(xopt)goto stickit;
        !           213:        if(status.mpasswd[0] == '\n')
        !           214:                status.mpasswd[0] = 0;
        !           215: # ifndef NEWPROT
        !           216:        if(machtype[local-'a'] == M_CC && machtype[remote-'a'] == M_CC
        !           217:                && status.mpasswd[0] != 0){
        !           218:                s = crypt(status.mpasswd);
        !           219:                strcpy(status.mpasswd,s);
        !           220:                }
        !           221: # endif
        !           222:        if(status.mpasswd[0] == 0 && code == 'q' &&
        !           223:                strcmp(status.login,"network") != 0){
        !           224:                fprintf(stderr,"Zero-length password not allowed\n");
        !           225:                outerror();
        !           226:                }
        !           227:        if(code == 'q' && (streql(status.login,"root") == 0 ||
        !           228:                streql(status.login,"ruut") == 0)){
        !           229:                fprintf(stderr,"Can't login as root through the network\n");
        !           230:                outerror();
        !           231:                }
        !           232: # ifdef SPACCT
        !           233:        /* handle special accounts */
        !           234:        /* give a value for mgid and muid */
        !           235:        strcpy(status.mpasswd,handlesp(status.login,status.mpasswd,
        !           236:                status.localname,status.muid,status.mgid));
        !           237: # endif
        !           238:        enmask(status.mpasswd);
        !           239:        lTtytime = 0;
        !           240:        if(sTtyname[0] && status.nowrite == 0){
        !           241:                temp = fopen("/etc/utmp","r");
        !           242:                if(temp == NULL){
        !           243:                        perror("/etc/utmp");
        !           244:                        outerror();
        !           245:                        }
        !           246:                while(fread(&utmpstr,1,sizeof utmpstr,temp) == sizeof utmpstr)
        !           247: # ifdef OLDTTY
        !           248:                        if(utmpstr.ut_tty == sTtyname[8]){
        !           249: # else
        !           250:                        if(strcmp(utmpstr.ut_line,sTtyname+5) == 0){
        !           251: # endif
        !           252:                                lTtytime = utmpstr.ut_time;
        !           253:                                break;
        !           254:                                }
        !           255:                }
        !           256: /*
        !           257:        debug("p:%s:\n",status.mpasswd);
        !           258: */
        !           259:        /* cflag is initially 'a'. Add the flags as needed. */
        !           260:        if(status.nonotify)cflag += F_NONOTIFY;
        !           261:        if(status.quiet)cflag += F_QUIET;
        !           262: /*
        !           263:        protocol:
        !           264:        code, remote mach, local mach, version stamp (2), remote login name,
        !           265:        password, -i, -o, -r files,
        !           266:        local login name, terminal, flag, utmp tty login time,
        !           267:        cc jobno(variable parameter list), current time,
        !           268:        command '\n' real command '\n'
        !           269:        any data
        !           270:        
        !           271:        changes:
        !           272:        1) remove header
        !           273:        3) use ascii length instead of 4 bytes
        !           274:        4) encrypt the login name, command, and part of data as well
        !           275: */
        !           276: 
        !           277:        fprintf(file,
        !           278:        "%c :%c :%c :%c :%c :%s :%s :%s :%s :%s :%s :%s :%c :%lo :%d%s :%ld :",
        !           279:                code,remote,local,VMAJOR+'a',VMINOR+'a',status.login,
        !           280:                status.mpasswd,infile,outfile,resp,
        !           281:                status.localname,sTtyname,cflag,lTtytime,
        !           282:                status.jobno,genparmlist(),gettime()-TIMEBASE);
        !           283:        fputs(sCmdAct,file);
        !           284:        putc('\n',file);
        !           285:        fputs(sCmdVirt,file);
        !           286:        putc('\n',file);
        !           287: stickit:
        !           288:        /* between ingres machines, allow long files */
        !           289:        /* this should be parametrized on a per machine pair basis */
        !           290:        if(machtype[local  - 'a'] == M_INGRES &&
        !           291:           machtype[remote - 'a'] == M_INGRES)
        !           292:                maxfile = MAXFILELARGE;
        !           293:        if(sin)
        !           294:                while((i = fread(buf,1,BUFSIZ,stdin)) > 0){
        !           295:                        if(fwrite(buf,1,i,file) != i){
        !           296:                                perror("net queue file");
        !           297:                                outerror();
        !           298:                                }
        !           299:                        if((cnt += i) > maxfile)goto toobig;
        !           300:                        if(feof(stdin))break;
        !           301:                        }
        !           302:        else if(localin[0]){
        !           303:                if(access(localin,4) == -1){
        !           304:                        perror(localin);
        !           305:                        outerror();
        !           306:                        }
        !           307:                temp = fopen(localin,"r");
        !           308:                if(temp == NULL){
        !           309:                        perror(localin);
        !           310:                        outerror();
        !           311:                        }
        !           312:                while((i = fread(buf,1,BUFSIZ,temp)) > 0){
        !           313:                        if((cnt += i) > maxfile)goto toobig;
        !           314:                        if(fwrite(buf,1,i,file) != i){
        !           315:                                perror("net queue file");
        !           316:                                outerror();
        !           317:                                }
        !           318:                        }
        !           319:                fclose(temp);
        !           320:                }
        !           321:        fclose(file);
        !           322:        chmod(dfname,0400);
        !           323:        dfname[strlen(dfname)-9] = 'c';
        !           324:        file = fopen(dfname,"w");
        !           325:        chmod(dfname,0400);
        !           326:        fclose(file);
        !           327:        mchown(dfname,uid,getgid());
        !           328:        exit(0);
        !           329: toobig:
        !           330:        fprintf(stderr,"No more than %ld bytes can be sent\n",maxfile);
        !           331:        outerror();             /* no return */
        !           332:        }
        !           333: /* 
        !           334:    called if there is an error, makes sure that the files created
        !           335:    are deleted and the terminal is reset to echo
        !           336: */
        !           337: outerror(){
        !           338:        register int i;
        !           339:        struct sgttyb stt;
        !           340:        signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN);
        !           341:        signal(SIGQUIT,SIG_IGN); signal(SIGTRM,SIG_IGN);
        !           342:        unlink(dfname);
        !           343:        i = strlen(dfname) - 9;
        !           344:        dfname[i] = (dfname[i] == 'c' ? 'd' : 'c');
        !           345:        unlink(dfname);
        !           346:        if(gtty(0,&stt) >= 0){
        !           347:                stt.sg_flags |= ECHO;
        !           348:                stty(0,&stt);
        !           349:                }
        !           350:        exit(1);
        !           351:        }
        !           352: enmask(s)
        !           353:   register char *s; {
        !           354: # ifdef NEWPROT
        !           355:        static char buf[20];
        !           356:        strcpy(s,nbsencrypt(s,THEKEY,buf));
        !           357: # else
        !           358:        while(*s){
        !           359:                *s &= 0177;             /* strip quote bites */
        !           360:                *s++ ^= 040;            /* invert upper-lower */
        !           361:                }
        !           362: # endif
        !           363:        }
        !           364: addir(s,t)
        !           365:   register char *s, *t; {
        !           366:        if(t[0] == '/')strcpy(s,t);
        !           367:        else {
        !           368:                gwd(s);
        !           369:                strcat(s,t);
        !           370:                }
        !           371:        }
        !           372: /* returns pass if not special, otherwise returns funny passwd */
        !           373: /* list of special accounts must be consistent - with netdaemon.c */
        !           374: char *handlesp(log,pass,localname,luid,lgid)
        !           375: char *log,*pass,*localname;{
        !           376:        /* experimental */
        !           377: # ifdef SPACCT
        !           378:        long lt;
        !           379:        char str[20];
        !           380:        if(strcmp(log,localname) == 0 && luid != 0 && lgid == 0 && (
        !           381:        strcmp(log,"source") == 0
        !           382:        || strcmp(log,"daemon") == 0
        !           383:        )) {
        !           384:                lt = lgid;
        !           385:                lt = (lt << 16) | luid;
        !           386:                sprintf(str,"%ld",lt);
        !           387:                return(str);
        !           388:                }
        !           389: # endif
        !           390:        return(pass);
        !           391:        }
        !           392: 
        !           393: 
        !           394: 
        !           395: static struct stat x;
        !           396: static struct direct y;
        !           397: static FILE *file;
        !           398: static int off = -1;
        !           399: 
        !           400: 
        !           401: /* these three routines gwd, cat, ckroot and 
        !           402:    data structures x, y, off, do a pwd to string name */
        !           403: gwd(name)
        !           404:   register char *name; {
        !           405:        *name = 0;
        !           406:        for(;;){
        !           407:                stat(".",&x);
        !           408:                if((file = fopen("..","r")) == NULL)break;
        !           409:                do {
        !           410:                        if(fread(&y,1,sizeof y,file) != sizeof y)break;
        !           411:                        } while(y.d_ino != x.st_ino);
        !           412:                fclose(file);
        !           413:                if(y.d_ino == ROOTINO){
        !           414:                        ckroot(name);
        !           415:                        break;
        !           416:                        }
        !           417:                if(cat(name))break;
        !           418:                chdir("..");
        !           419:                }
        !           420:        chdir(name);
        !           421:        }
        !           422: 
        !           423: cat(name)
        !           424:   register char *name; {               /* return 1 to exit */
        !           425:        register int i,j;
        !           426:        i = -1;
        !           427:        while(y.d_name[++i] != 0);
        !           428:        if((off+i+2) > 511)return(1);
        !           429:        for(j = off +1; j >= 0; --j)name[j+i+1] = name[j];
        !           430:        off = i + off + 1;
        !           431:        name[i] = '/';
        !           432:        for(--i; i>= 0; --i)name[i] = y.d_name[i];
        !           433:        return(0);
        !           434:        }
        !           435: 
        !           436: ckroot(name)
        !           437:   char *name; {
        !           438:        register int i;
        !           439:        if(stat(y.d_name,&x) < 0)return;
        !           440:        i = x.st_dev;
        !           441:        if(chdir("/") < 0)return;
        !           442:        if((file = fopen("/","r")) == NULL)return;
        !           443:        do {
        !           444:                if(fread(&y,1,sizeof y,file) != sizeof y)return;
        !           445:                if(y.d_ino == 0)continue;
        !           446:                if(stat(y.d_name,&x) < 0)return;
        !           447:                } while(x.st_dev!=i || (x.st_mode&S_IFMT)!=S_IFDIR);
        !           448:        if(strcmp(y.d_name,".") != 0 && strcmp(y.d_name,"..") != 0)
        !           449:                if(cat(name))return;
        !           450:        i = strlen(name);
        !           451:        name[i+1] = 0;
        !           452:        while(--i >= 0)name[i + 1] = name[i];
        !           453:        name[0] = '/';
        !           454:        return;
        !           455:        }
        !           456: /*
        !           457:        this function takes a file name and tells whether it is a 
        !           458:        directory or on. Returns 1 if so, 0 otherwise.
        !           459:        null strings etc. return 0.
        !           460: */
        !           461: isdirectory(fn)
        !           462:        char *fn;
        !           463: {
        !           464:        int i,ret=0;
        !           465:        if(fn == NULL || *fn == 0)return(0);
        !           466:        i = strlen(fn);
        !           467:        if(i == 1){
        !           468:                if(strcmp(fn,".")       == 0)ret = 1;
        !           469:                if(strcmp(fn,"/")       == 0)ret = 1;
        !           470:        }
        !           471:        else if(i == 2){
        !           472:                if(strcmp(fn,"..")      == 0)ret = 1;
        !           473:                if(strcmp(fn,"/.")      == 0)ret = 1;
        !           474:        }
        !           475:        else {
        !           476:                if(strcmp(fn+i-2,"/.")  == 0)ret = 1;
        !           477:                if(strcmp(fn+i-3,"/..") == 0)ret = 1;
        !           478:        }
        !           479:        return(ret);
        !           480: }
        !           481: /*
        !           482:        generate a variable parameter list
        !           483:        the format is:
        !           484:                (name value, name value, ..., name value)
        !           485:        where names are unquoted single words and values
        !           486:        are unquoted if a single alphanumeric word, and are
        !           487:        surrounded by {} otherwise. \ quotes { and }.
        !           488:        the values are escape-processed, e.g. \n becomes 012.
        !           489:        this function returns such a list.
        !           490:        Returns the null parm list if nothing to give, i.e. "()" 
        !           491: 
        !           492:        Should also default so single keywords can have on/off
        !           493:        states, and so do not require a value.
        !           494: 
        !           495:        Things this variable protocol should specify:
        !           496:                EPASSWD         encrypted passwd
        !           497:                FILEMODE        file mode
        !           498:                FROMUID         from users' uid
        !           499:                FROMGID         from users' gid
        !           500:                COMPRESS        use colin's compression
        !           501:                SPACCT          handle special accounts.
        !           502:                MESSAGEID       unique number identifying this request.
        !           503:                VTOUSERNAME     name netq should display as being "To:"
        !           504:                FILENAME        when omitted by netcp, will use FILENAME ext.
        !           505:                MACHINE2        a second machine (e.g. 3way netcp)
        !           506:                LOGIN2          a second login name
        !           507:                PASSWD2         a second passwd
        !           508:                REPLYTO         the person the response should be sent to
        !           509: 
        !           510: */
        !           511: char *genparmlist(){
        !           512:        static char returnstr[PARMLIST];
        !           513:        strcpy(returnstr,"()");
        !           514:        return(returnstr);
        !           515: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.