113638Ssam #ifndef lint 2*23588Sbloom static char sccsid[] = "@(#)chkpth.c 5.4 (Berkeley) 06/19/85"; 313638Ssam #endif 413638Ssam 513638Ssam #include "uucp.h" 613638Ssam #include <sys/stat.h> 713638Ssam 813638Ssam struct userpath { 913638Ssam char *us_lname; 1013638Ssam char *us_mname; 1113638Ssam char us_callback; 1213638Ssam char **us_path; 1313638Ssam struct userpath *unext; 1413638Ssam }; 1513638Ssam struct userpath *Uhead = NULL; 1613638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL; 1713638Ssam int Uptfirst = 1; 1813638Ssam 19*23588Sbloom /*LINTLIBRARY*/ 20*23588Sbloom 21*23588Sbloom /* 22*23588Sbloom * this routine will check the path table for the 2313638Ssam * machine or log name (non-null parameter) to see if the 24*23588Sbloom * input path (path) starts with an acceptable prefix. 2513638Ssam * 2613638Ssam * return codes: 0 | FAIL 2713638Ssam */ 2813638Ssam 2913638Ssam chkpth(logname, mchname, path) 3013638Ssam char *path, *logname, *mchname; 3113638Ssam { 3213638Ssam register struct userpath *u; 3313638Ssam extern char *lastpart(); 3413638Ssam register char **p, *s; 3513638Ssam 3613638Ssam /* Allow only rooted pathnames. Security wish. rti!trt */ 3718616Sralph if (*path != '/') { 3818616Sralph DEBUG(4, "filename doesn't begin with /\n", CNULL); 3917767Sralph return FAIL; 4018616Sralph } 4113638Ssam 4213638Ssam if (Uptfirst) { 4313638Ssam rdpth(); 4417767Sralph ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", CNULL, 0); 4513638Ssam Uptfirst = 0; 4613638Ssam } 4713638Ssam for (u = Uhead; u != NULL; ) { 4813638Ssam if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME) 4913638Ssam break; 50*23588Sbloom if (*mchname != '\0' && strncmp(mchname, u->us_mname, MAXBASENAME) == SAME) 5113638Ssam break; 5213638Ssam u = u->unext; 5313638Ssam } 5413638Ssam if (u == NULL) { 5513638Ssam if (*logname == '\0') 5613638Ssam u = Mchdef; 5713638Ssam else 5813638Ssam u = Logdef; 5913638Ssam if (u == NULL) 6017767Sralph return FAIL; 6113638Ssam } 6213638Ssam 6313638Ssam /* check for /../ in path name */ 6413638Ssam for (s = path; *s != '\0'; s++) { 6518616Sralph if (prefix("/../",s)) { 6618616Sralph DEBUG(4, "filename has /../ in it\n", CNULL); 6717767Sralph return FAIL; 6818616Sralph } 6913638Ssam } 7013638Ssam 7113638Ssam /* Check for access permission */ 7213638Ssam for (p = u->us_path; *p != NULL; p++) 7313638Ssam if (prefix(*p, path)) 7417767Sralph return SUCCESS; 7518616Sralph DEBUG(4, "filename not in list\n", CNULL); 7613638Ssam 7713638Ssam /* path name not valid */ 7817767Sralph return FAIL; 7913638Ssam } 8013638Ssam 8113638Ssam 8213638Ssam /*** 8313638Ssam * rdpth() 8413638Ssam * 8513638Ssam * rdpth - this routine will read the USERFILE and 8613638Ssam * construct the userpath structure pointed to by (u); 8713638Ssam * 8813638Ssam */ 8913638Ssam 9013638Ssam rdpth() 9113638Ssam { 9213638Ssam char buf[100 + 1], *pbuf[50 + 1]; 9313638Ssam register struct userpath *u; 9413638Ssam register char *pc, **cp; 9513638Ssam FILE *uf; 9613638Ssam 9713638Ssam if ((uf = fopen(USERFILE, "r")) == NULL) { 9813638Ssam /* can not open file */ 9913638Ssam return; 10013638Ssam } 10113638Ssam 10213638Ssam while (cfgets(buf, sizeof(buf), uf) != NULL) { 10313638Ssam int nargs, i; 10413638Ssam 10517767Sralph u = (struct userpath *)malloc(sizeof (struct userpath)); 10617767Sralph if (u == NULL) { 10713638Ssam DEBUG (1, "*** Userpath malloc failed\n", 0); 10813638Ssam fclose (uf); 10913638Ssam return; 11013638Ssam } 11113638Ssam if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char))) 11213638Ssam == NULL) { 11313638Ssam /* can not allocate space */ 11413638Ssam DEBUG (1, "Userpath calloc 1 failed\n", 0); 11513638Ssam fclose(uf); 11613638Ssam return; 11713638Ssam } 11813638Ssam 11913638Ssam strcpy(pc, buf); 12017767Sralph nargs = getargs(pc, pbuf, 50); 12113638Ssam u->us_lname = pbuf[0]; 12213638Ssam pc = index(u->us_lname, ','); 12313638Ssam if (pc != NULL) 12413638Ssam *pc++ = '\0'; 12513638Ssam else 12613638Ssam pc = u->us_lname + strlen(u->us_lname); 12713638Ssam u->us_mname = pc; 128*23588Sbloom if (strlen(u->us_mname) > MAXBASENAME) 129*23588Sbloom u->us_mname[MAXBASENAME] = '\0'; 13013638Ssam if (*u->us_lname == '\0' && Logdef == NULL) 13113638Ssam Logdef = u; 13217767Sralph if (*u->us_mname == '\0' && Mchdef == NULL) 13313638Ssam Mchdef = u; 13413638Ssam i = 1; 13513638Ssam if (strcmp(pbuf[1], "c") == SAME) { 13613638Ssam u->us_callback = 1; 13713638Ssam i++; 13813638Ssam } 13913638Ssam else 14013638Ssam u->us_callback = 0; 14117767Sralph cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *)); 14217767Sralph if (cp == NULL) { 14313638Ssam /* can not allocate space */ 14413638Ssam DEBUG (1, "Userpath calloc 2 failed!\n", 0); 14513638Ssam fclose(uf); 14613638Ssam return; 14713638Ssam } 14817767Sralph u->us_path = cp; 14913638Ssam 15013638Ssam while (i < nargs) 15113638Ssam *cp++ = pbuf[i++]; 15213638Ssam *cp = NULL; 15313638Ssam u->unext = Uhead; 15413638Ssam Uhead = u; 15513638Ssam } 15613638Ssam 15713638Ssam fclose(uf); 15813638Ssam return; 15913638Ssam } 16013638Ssam 16113638Ssam /*** 16213638Ssam * callback(name) check for callback 16313638Ssam * char *name; 16413638Ssam * 16513638Ssam * return codes: 16613638Ssam * 0 - no call back 16713638Ssam * 1 - call back 16813638Ssam */ 16913638Ssam 17013638Ssam callback(name) 17113638Ssam register char *name; 17213638Ssam { 17313638Ssam register struct userpath *u; 17413638Ssam 17513638Ssam if (Uptfirst) { 17613638Ssam rdpth(); 17717767Sralph ASSERT(Uhead != NULL, "INIT USERFILE, No Users!", CNULL, 0); 17813638Ssam Uptfirst = 0; 17913638Ssam } 18013638Ssam 18113638Ssam for (u = Uhead; u != NULL; ) { 18213638Ssam if (strcmp(u->us_lname, name) == SAME) 18313638Ssam /* found user name */ 18417767Sralph return u->us_callback; 18513638Ssam u = u->unext; 18613638Ssam } 18713638Ssam 18813638Ssam /* userid not found */ 18917767Sralph return 0; 19013638Ssam } 19113638Ssam 19213638Ssam 19313638Ssam /*** 19413638Ssam * chkperm(file, mopt) check write permission of file 19513638Ssam * char *mopt; none NULL - create directories 19613638Ssam * 19713638Ssam * if mopt != NULL and permissions are ok, 19813638Ssam * a side effect of this routine is to make 19913638Ssam * directories up to the last part of the 20013638Ssam * filename (if they do not exist). 20113638Ssam * 20217767Sralph * return SUCCESS | FAIL 20313638Ssam */ 20413638Ssam 20513638Ssam chkperm(file, mopt) 20613638Ssam char *file, *mopt; 20713638Ssam { 20813638Ssam struct stat s; 20913638Ssam int ret; 21013638Ssam char dir[MAXFULLNAME]; 21113638Ssam extern char *lastpart(); 21213638Ssam 21313638Ssam if (stat(subfile(file), &s) == 0) { 21418616Sralph if ((s.st_mode & ANYWRITE) == 0) { 21518616Sralph DEBUG(4,"file is not writable: mode %o\n", s.st_mode); 21617767Sralph return FAIL; 21718616Sralph } 21817767Sralph return SUCCESS; 21913638Ssam } 22013638Ssam 22113638Ssam strcpy(dir, file); 22213638Ssam *lastpart(dir) = '\0'; 22318616Sralph if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) { 22418616Sralph DEBUG(4, "can't stat directory %s\n", subfile(dir)); 22517767Sralph return FAIL; 22618616Sralph } 22713638Ssam 22813638Ssam if (ret != -1) { 22913638Ssam if ((s.st_mode & ANYWRITE) == 0) 23017767Sralph return FAIL; 23113638Ssam else 23217767Sralph return SUCCESS; 23313638Ssam } 23413638Ssam 23513638Ssam /* make directories */ 23617767Sralph return mkdirs(file); 23713638Ssam } 23813638Ssam 23913638Ssam /* 24013638Ssam * Check for sufficient privilege to request debugging. 24113638Ssam */ 24217767Sralph chkdebug() 24313638Ssam { 24417767Sralph if (access(SYSFILE, 04) < 0) { 24517767Sralph fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n"); 24613638Ssam cleanup(1); 24713638Ssam exit(1); /* Just in case */ 24813638Ssam } 24913638Ssam } 250