113638Ssam #ifndef lint 2*33944Srick static char sccsid[] = "@(#)chkpth.c 5.5 (Berkeley) 04/05/88"; 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 }; 15*33944Srick 1613638Ssam struct userpath *Uhead = NULL; 1713638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL; 1813638Ssam int Uptfirst = 1; 1913638Ssam 2023588Sbloom /*LINTLIBRARY*/ 2123588Sbloom 2223588Sbloom /* 2323588Sbloom * this routine will check the path table for the 2413638Ssam * machine or log name (non-null parameter) to see if the 2523588Sbloom * input path (path) starts with an acceptable prefix. 2613638Ssam * 2713638Ssam * return codes: 0 | FAIL 2813638Ssam */ 2913638Ssam 3013638Ssam chkpth(logname, mchname, path) 3113638Ssam char *path, *logname, *mchname; 3213638Ssam { 3313638Ssam register struct userpath *u; 3413638Ssam extern char *lastpart(); 3513638Ssam register char **p, *s; 3613638Ssam 3713638Ssam /* Allow only rooted pathnames. Security wish. rti!trt */ 3818616Sralph if (*path != '/') { 3918616Sralph DEBUG(4, "filename doesn't begin with /\n", CNULL); 4017767Sralph return FAIL; 4118616Sralph } 4213638Ssam 4313638Ssam if (Uptfirst) { 4413638Ssam rdpth(); 45*33944Srick if (Uhead == NULL) { 46*33944Srick syslog(LOG_ERR, "USERFILE empty!"); 47*33944Srick cleanup(FAIL); 48*33944Srick } 4913638Ssam Uptfirst = 0; 5013638Ssam } 5113638Ssam for (u = Uhead; u != NULL; ) { 5213638Ssam if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME) 5313638Ssam break; 5423588Sbloom if (*mchname != '\0' && strncmp(mchname, u->us_mname, MAXBASENAME) == SAME) 5513638Ssam break; 5613638Ssam u = u->unext; 5713638Ssam } 5813638Ssam if (u == NULL) { 5913638Ssam if (*logname == '\0') 6013638Ssam u = Mchdef; 6113638Ssam else 6213638Ssam u = Logdef; 6313638Ssam if (u == NULL) 6417767Sralph return FAIL; 6513638Ssam } 6613638Ssam 6713638Ssam /* check for /../ in path name */ 6813638Ssam for (s = path; *s != '\0'; s++) { 6918616Sralph if (prefix("/../",s)) { 7018616Sralph DEBUG(4, "filename has /../ in it\n", CNULL); 7117767Sralph return FAIL; 7218616Sralph } 7313638Ssam } 7413638Ssam 7513638Ssam /* Check for access permission */ 7613638Ssam for (p = u->us_path; *p != NULL; p++) 7713638Ssam if (prefix(*p, path)) 7817767Sralph return SUCCESS; 7918616Sralph DEBUG(4, "filename not in list\n", CNULL); 8013638Ssam 8113638Ssam /* path name not valid */ 8217767Sralph return FAIL; 8313638Ssam } 8413638Ssam 8513638Ssam 8613638Ssam /*** 8713638Ssam * rdpth() 8813638Ssam * 8913638Ssam * rdpth - this routine will read the USERFILE and 9013638Ssam * construct the userpath structure pointed to by (u); 9113638Ssam * 9213638Ssam */ 9313638Ssam 9413638Ssam rdpth() 9513638Ssam { 9613638Ssam char buf[100 + 1], *pbuf[50 + 1]; 9713638Ssam register struct userpath *u; 9813638Ssam register char *pc, **cp; 9913638Ssam FILE *uf; 10013638Ssam 10113638Ssam if ((uf = fopen(USERFILE, "r")) == NULL) { 10213638Ssam /* can not open file */ 10313638Ssam return; 10413638Ssam } 10513638Ssam 10613638Ssam while (cfgets(buf, sizeof(buf), uf) != NULL) { 10713638Ssam int nargs, i; 10813638Ssam 10917767Sralph u = (struct userpath *)malloc(sizeof (struct userpath)); 11017767Sralph if (u == NULL) { 11113638Ssam DEBUG (1, "*** Userpath malloc failed\n", 0); 11213638Ssam fclose (uf); 11313638Ssam return; 11413638Ssam } 11513638Ssam if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char))) 11613638Ssam == NULL) { 11713638Ssam /* can not allocate space */ 11813638Ssam DEBUG (1, "Userpath calloc 1 failed\n", 0); 11913638Ssam fclose(uf); 12013638Ssam return; 12113638Ssam } 12213638Ssam 12313638Ssam strcpy(pc, buf); 12417767Sralph nargs = getargs(pc, pbuf, 50); 12513638Ssam u->us_lname = pbuf[0]; 12613638Ssam pc = index(u->us_lname, ','); 12713638Ssam if (pc != NULL) 12813638Ssam *pc++ = '\0'; 12913638Ssam else 13013638Ssam pc = u->us_lname + strlen(u->us_lname); 13113638Ssam u->us_mname = pc; 13223588Sbloom if (strlen(u->us_mname) > MAXBASENAME) 13323588Sbloom u->us_mname[MAXBASENAME] = '\0'; 13413638Ssam if (*u->us_lname == '\0' && Logdef == NULL) 13513638Ssam Logdef = u; 13617767Sralph if (*u->us_mname == '\0' && Mchdef == NULL) 13713638Ssam Mchdef = u; 13813638Ssam i = 1; 13913638Ssam if (strcmp(pbuf[1], "c") == SAME) { 14013638Ssam u->us_callback = 1; 14113638Ssam i++; 14213638Ssam } 14313638Ssam else 14413638Ssam u->us_callback = 0; 14517767Sralph cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *)); 14617767Sralph if (cp == NULL) { 14713638Ssam /* can not allocate space */ 14813638Ssam DEBUG (1, "Userpath calloc 2 failed!\n", 0); 14913638Ssam fclose(uf); 15013638Ssam return; 15113638Ssam } 15217767Sralph u->us_path = cp; 15313638Ssam 15413638Ssam while (i < nargs) 15513638Ssam *cp++ = pbuf[i++]; 15613638Ssam *cp = NULL; 15713638Ssam u->unext = Uhead; 15813638Ssam Uhead = u; 15913638Ssam } 16013638Ssam 16113638Ssam fclose(uf); 16213638Ssam return; 16313638Ssam } 16413638Ssam 16513638Ssam /*** 16613638Ssam * callback(name) check for callback 16713638Ssam * char *name; 16813638Ssam * 16913638Ssam * return codes: 17013638Ssam * 0 - no call back 17113638Ssam * 1 - call back 17213638Ssam */ 17313638Ssam 17413638Ssam callback(name) 17513638Ssam register char *name; 17613638Ssam { 17713638Ssam register struct userpath *u; 17813638Ssam 17913638Ssam if (Uptfirst) { 18013638Ssam rdpth(); 181*33944Srick if (Uhead == NULL) { 182*33944Srick syslog(LOG_ERR, "USERFILE empty!"); 183*33944Srick cleanup(FAIL); 184*33944Srick } 18513638Ssam Uptfirst = 0; 18613638Ssam } 18713638Ssam 18813638Ssam for (u = Uhead; u != NULL; ) { 18913638Ssam if (strcmp(u->us_lname, name) == SAME) 19013638Ssam /* found user name */ 19117767Sralph return u->us_callback; 19213638Ssam u = u->unext; 19313638Ssam } 19413638Ssam 19513638Ssam /* userid not found */ 19617767Sralph return 0; 19713638Ssam } 19813638Ssam 19913638Ssam 20013638Ssam /*** 20113638Ssam * chkperm(file, mopt) check write permission of file 20213638Ssam * char *mopt; none NULL - create directories 20313638Ssam * 20413638Ssam * if mopt != NULL and permissions are ok, 20513638Ssam * a side effect of this routine is to make 20613638Ssam * directories up to the last part of the 20713638Ssam * filename (if they do not exist). 20813638Ssam * 20917767Sralph * return SUCCESS | FAIL 21013638Ssam */ 21113638Ssam 21213638Ssam chkperm(file, mopt) 21313638Ssam char *file, *mopt; 21413638Ssam { 21513638Ssam struct stat s; 21613638Ssam int ret; 21713638Ssam char dir[MAXFULLNAME]; 21813638Ssam extern char *lastpart(); 21913638Ssam 22013638Ssam if (stat(subfile(file), &s) == 0) { 22118616Sralph if ((s.st_mode & ANYWRITE) == 0) { 22218616Sralph DEBUG(4,"file is not writable: mode %o\n", s.st_mode); 22317767Sralph return FAIL; 22418616Sralph } 22517767Sralph return SUCCESS; 22613638Ssam } 22713638Ssam 22813638Ssam strcpy(dir, file); 22913638Ssam *lastpart(dir) = '\0'; 23018616Sralph if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) { 23118616Sralph DEBUG(4, "can't stat directory %s\n", subfile(dir)); 23217767Sralph return FAIL; 23318616Sralph } 23413638Ssam 23513638Ssam if (ret != -1) { 23613638Ssam if ((s.st_mode & ANYWRITE) == 0) 23717767Sralph return FAIL; 23813638Ssam else 23917767Sralph return SUCCESS; 24013638Ssam } 24113638Ssam 24213638Ssam /* make directories */ 24317767Sralph return mkdirs(file); 24413638Ssam } 24513638Ssam 24613638Ssam /* 24713638Ssam * Check for sufficient privilege to request debugging. 24813638Ssam */ 24917767Sralph chkdebug() 25013638Ssam { 25117767Sralph if (access(SYSFILE, 04) < 0) { 25217767Sralph fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n"); 25313638Ssam cleanup(1); 25413638Ssam exit(1); /* Just in case */ 25513638Ssam } 25613638Ssam } 257