113638Ssam #ifndef lint 2*18616Sralph static char sccsid[] = "@(#)chkpth.c 5.3 (Berkeley) 04/10/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 1913638Ssam /******* 2013638Ssam * chkpth(logname, mchname, path) 2113638Ssam * char *path, *logname, *mchname; 2213638Ssam * 2313638Ssam * chkpth - this routine will check the path table for the 2413638Ssam * machine or log name (non-null parameter) to see if the 2513638Ssam * input path (path) 2613638Ssam * starts with an acceptable prefix. 2713638Ssam * 2813638Ssam * return codes: 0 | FAIL 2913638Ssam */ 3013638Ssam 3113638Ssam chkpth(logname, mchname, path) 3213638Ssam char *path, *logname, *mchname; 3313638Ssam { 3413638Ssam register struct userpath *u; 3513638Ssam extern char *lastpart(); 3613638Ssam register char **p, *s; 3713638Ssam 3813638Ssam /* Allow only rooted pathnames. Security wish. rti!trt */ 39*18616Sralph if (*path != '/') { 40*18616Sralph DEBUG(4, "filename doesn't begin with /\n", CNULL); 4117767Sralph return FAIL; 42*18616Sralph } 4313638Ssam 4413638Ssam if (Uptfirst) { 4513638Ssam rdpth(); 4617767Sralph ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", CNULL, 0); 4713638Ssam Uptfirst = 0; 4813638Ssam } 4913638Ssam for (u = Uhead; u != NULL; ) { 5013638Ssam if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME) 5113638Ssam break; 5213638Ssam if (*mchname != '\0' && strncmp(mchname, u->us_mname, 7) == SAME) 5313638Ssam break; 5413638Ssam u = u->unext; 5513638Ssam } 5613638Ssam if (u == NULL) { 5713638Ssam if (*logname == '\0') 5813638Ssam u = Mchdef; 5913638Ssam else 6013638Ssam u = Logdef; 6113638Ssam if (u == NULL) 6217767Sralph return FAIL; 6313638Ssam } 6413638Ssam 6513638Ssam /* check for /../ in path name */ 6613638Ssam for (s = path; *s != '\0'; s++) { 67*18616Sralph if (prefix("/../",s)) { 68*18616Sralph DEBUG(4, "filename has /../ in it\n", CNULL); 6917767Sralph return FAIL; 70*18616Sralph } 7113638Ssam } 7213638Ssam 7313638Ssam /* Check for access permission */ 7413638Ssam for (p = u->us_path; *p != NULL; p++) 7513638Ssam if (prefix(*p, path)) 7617767Sralph return SUCCESS; 77*18616Sralph DEBUG(4, "filename not in list\n", CNULL); 7813638Ssam 7913638Ssam /* path name not valid */ 8017767Sralph return FAIL; 8113638Ssam } 8213638Ssam 8313638Ssam 8413638Ssam /*** 8513638Ssam * rdpth() 8613638Ssam * 8713638Ssam * rdpth - this routine will read the USERFILE and 8813638Ssam * construct the userpath structure pointed to by (u); 8913638Ssam * 9013638Ssam */ 9113638Ssam 9213638Ssam rdpth() 9313638Ssam { 9413638Ssam char buf[100 + 1], *pbuf[50 + 1]; 9513638Ssam register struct userpath *u; 9613638Ssam register char *pc, **cp; 9713638Ssam FILE *uf; 9813638Ssam 9913638Ssam if ((uf = fopen(USERFILE, "r")) == NULL) { 10013638Ssam /* can not open file */ 10113638Ssam return; 10213638Ssam } 10313638Ssam 10413638Ssam while (cfgets(buf, sizeof(buf), uf) != NULL) { 10513638Ssam int nargs, i; 10613638Ssam 10717767Sralph u = (struct userpath *)malloc(sizeof (struct userpath)); 10817767Sralph if (u == NULL) { 10913638Ssam DEBUG (1, "*** Userpath malloc failed\n", 0); 11013638Ssam fclose (uf); 11113638Ssam return; 11213638Ssam } 11313638Ssam if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char))) 11413638Ssam == NULL) { 11513638Ssam /* can not allocate space */ 11613638Ssam DEBUG (1, "Userpath calloc 1 failed\n", 0); 11713638Ssam fclose(uf); 11813638Ssam return; 11913638Ssam } 12013638Ssam 12113638Ssam strcpy(pc, buf); 12217767Sralph nargs = getargs(pc, pbuf, 50); 12313638Ssam u->us_lname = pbuf[0]; 12413638Ssam pc = index(u->us_lname, ','); 12513638Ssam if (pc != NULL) 12613638Ssam *pc++ = '\0'; 12713638Ssam else 12813638Ssam pc = u->us_lname + strlen(u->us_lname); 12913638Ssam u->us_mname = pc; 13013638Ssam if (strlen(u->us_mname) > 7) 13113638Ssam u->us_mname[7] = '\0'; 13213638Ssam if (*u->us_lname == '\0' && Logdef == NULL) 13313638Ssam Logdef = u; 13417767Sralph if (*u->us_mname == '\0' && Mchdef == NULL) 13513638Ssam Mchdef = u; 13613638Ssam i = 1; 13713638Ssam if (strcmp(pbuf[1], "c") == SAME) { 13813638Ssam u->us_callback = 1; 13913638Ssam i++; 14013638Ssam } 14113638Ssam else 14213638Ssam u->us_callback = 0; 14317767Sralph cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *)); 14417767Sralph if (cp == NULL) { 14513638Ssam /* can not allocate space */ 14613638Ssam DEBUG (1, "Userpath calloc 2 failed!\n", 0); 14713638Ssam fclose(uf); 14813638Ssam return; 14913638Ssam } 15017767Sralph u->us_path = cp; 15113638Ssam 15213638Ssam while (i < nargs) 15313638Ssam *cp++ = pbuf[i++]; 15413638Ssam *cp = NULL; 15513638Ssam u->unext = Uhead; 15613638Ssam Uhead = u; 15713638Ssam } 15813638Ssam 15913638Ssam fclose(uf); 16013638Ssam return; 16113638Ssam } 16213638Ssam 16313638Ssam /*** 16413638Ssam * callback(name) check for callback 16513638Ssam * char *name; 16613638Ssam * 16713638Ssam * return codes: 16813638Ssam * 0 - no call back 16913638Ssam * 1 - call back 17013638Ssam */ 17113638Ssam 17213638Ssam callback(name) 17313638Ssam register char *name; 17413638Ssam { 17513638Ssam register struct userpath *u; 17613638Ssam 17713638Ssam if (Uptfirst) { 17813638Ssam rdpth(); 17917767Sralph ASSERT(Uhead != NULL, "INIT USERFILE, No Users!", CNULL, 0); 18013638Ssam Uptfirst = 0; 18113638Ssam } 18213638Ssam 18313638Ssam for (u = Uhead; u != NULL; ) { 18413638Ssam if (strcmp(u->us_lname, name) == SAME) 18513638Ssam /* found user name */ 18617767Sralph return u->us_callback; 18713638Ssam u = u->unext; 18813638Ssam } 18913638Ssam 19013638Ssam /* userid not found */ 19117767Sralph return 0; 19213638Ssam } 19313638Ssam 19413638Ssam 19513638Ssam /*** 19613638Ssam * chkperm(file, mopt) check write permission of file 19713638Ssam * char *mopt; none NULL - create directories 19813638Ssam * 19913638Ssam * if mopt != NULL and permissions are ok, 20013638Ssam * a side effect of this routine is to make 20113638Ssam * directories up to the last part of the 20213638Ssam * filename (if they do not exist). 20313638Ssam * 20417767Sralph * return SUCCESS | FAIL 20513638Ssam */ 20613638Ssam 20713638Ssam chkperm(file, mopt) 20813638Ssam char *file, *mopt; 20913638Ssam { 21013638Ssam struct stat s; 21113638Ssam int ret; 21213638Ssam char dir[MAXFULLNAME]; 21313638Ssam extern char *lastpart(); 21413638Ssam 21513638Ssam if (stat(subfile(file), &s) == 0) { 216*18616Sralph if ((s.st_mode & ANYWRITE) == 0) { 217*18616Sralph DEBUG(4,"file is not writable: mode %o\n", s.st_mode); 21817767Sralph return FAIL; 219*18616Sralph } 22017767Sralph return SUCCESS; 22113638Ssam } 22213638Ssam 22313638Ssam strcpy(dir, file); 22413638Ssam *lastpart(dir) = '\0'; 225*18616Sralph if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) { 226*18616Sralph DEBUG(4, "can't stat directory %s\n", subfile(dir)); 22717767Sralph return FAIL; 228*18616Sralph } 22913638Ssam 23013638Ssam if (ret != -1) { 23113638Ssam if ((s.st_mode & ANYWRITE) == 0) 23217767Sralph return FAIL; 23313638Ssam else 23417767Sralph return SUCCESS; 23513638Ssam } 23613638Ssam 23713638Ssam /* make directories */ 23817767Sralph return mkdirs(file); 23913638Ssam } 24013638Ssam 24113638Ssam /* 24213638Ssam * Check for sufficient privilege to request debugging. 24313638Ssam */ 24417767Sralph chkdebug() 24513638Ssam { 24617767Sralph if (access(SYSFILE, 04) < 0) { 24717767Sralph fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n"); 24813638Ssam cleanup(1); 24913638Ssam exit(1); /* Just in case */ 25013638Ssam } 25113638Ssam } 252