1*48652Sbostic /*- 2*48652Sbostic * Copyright (c) 1985 The Regents of the University of California. 3*48652Sbostic * All rights reserved. 4*48652Sbostic * 5*48652Sbostic * %sccs.include.proprietary.c% 6*48652Sbostic */ 7*48652Sbostic 813638Ssam #ifndef lint 9*48652Sbostic static char sccsid[] = "@(#)chkpth.c 5.6 (Berkeley) 04/24/91"; 10*48652Sbostic #endif /* not lint */ 1113638Ssam 1213638Ssam #include "uucp.h" 1313638Ssam #include <sys/stat.h> 1413638Ssam 1513638Ssam struct userpath { 1613638Ssam char *us_lname; 1713638Ssam char *us_mname; 1813638Ssam char us_callback; 1913638Ssam char **us_path; 2013638Ssam struct userpath *unext; 2113638Ssam }; 2233944Srick 2313638Ssam struct userpath *Uhead = NULL; 2413638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL; 2513638Ssam int Uptfirst = 1; 2613638Ssam 2723588Sbloom /*LINTLIBRARY*/ 2823588Sbloom 2923588Sbloom /* 3023588Sbloom * this routine will check the path table for the 3113638Ssam * machine or log name (non-null parameter) to see if the 3223588Sbloom * input path (path) starts with an acceptable prefix. 3313638Ssam * 3413638Ssam * return codes: 0 | FAIL 3513638Ssam */ 3613638Ssam 3713638Ssam chkpth(logname, mchname, path) 3813638Ssam char *path, *logname, *mchname; 3913638Ssam { 4013638Ssam register struct userpath *u; 4113638Ssam extern char *lastpart(); 4213638Ssam register char **p, *s; 4313638Ssam 4413638Ssam /* Allow only rooted pathnames. Security wish. rti!trt */ 4518616Sralph if (*path != '/') { 4618616Sralph DEBUG(4, "filename doesn't begin with /\n", CNULL); 4717767Sralph return FAIL; 4818616Sralph } 4913638Ssam 5013638Ssam if (Uptfirst) { 5113638Ssam rdpth(); 5233944Srick if (Uhead == NULL) { 5333944Srick syslog(LOG_ERR, "USERFILE empty!"); 5433944Srick cleanup(FAIL); 5533944Srick } 5613638Ssam Uptfirst = 0; 5713638Ssam } 5813638Ssam for (u = Uhead; u != NULL; ) { 5913638Ssam if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME) 6013638Ssam break; 6123588Sbloom if (*mchname != '\0' && strncmp(mchname, u->us_mname, MAXBASENAME) == SAME) 6213638Ssam break; 6313638Ssam u = u->unext; 6413638Ssam } 6513638Ssam if (u == NULL) { 6613638Ssam if (*logname == '\0') 6713638Ssam u = Mchdef; 6813638Ssam else 6913638Ssam u = Logdef; 7013638Ssam if (u == NULL) 7117767Sralph return FAIL; 7213638Ssam } 7313638Ssam 7413638Ssam /* check for /../ in path name */ 7513638Ssam for (s = path; *s != '\0'; s++) { 7618616Sralph if (prefix("/../",s)) { 7718616Sralph DEBUG(4, "filename has /../ in it\n", CNULL); 7817767Sralph return FAIL; 7918616Sralph } 8013638Ssam } 8113638Ssam 8213638Ssam /* Check for access permission */ 8313638Ssam for (p = u->us_path; *p != NULL; p++) 8413638Ssam if (prefix(*p, path)) 8517767Sralph return SUCCESS; 8618616Sralph DEBUG(4, "filename not in list\n", CNULL); 8713638Ssam 8813638Ssam /* path name not valid */ 8917767Sralph return FAIL; 9013638Ssam } 9113638Ssam 9213638Ssam 9313638Ssam /*** 9413638Ssam * rdpth() 9513638Ssam * 9613638Ssam * rdpth - this routine will read the USERFILE and 9713638Ssam * construct the userpath structure pointed to by (u); 9813638Ssam * 9913638Ssam */ 10013638Ssam 10113638Ssam rdpth() 10213638Ssam { 10313638Ssam char buf[100 + 1], *pbuf[50 + 1]; 10413638Ssam register struct userpath *u; 10513638Ssam register char *pc, **cp; 10613638Ssam FILE *uf; 10713638Ssam 10813638Ssam if ((uf = fopen(USERFILE, "r")) == NULL) { 10913638Ssam /* can not open file */ 11013638Ssam return; 11113638Ssam } 11213638Ssam 11313638Ssam while (cfgets(buf, sizeof(buf), uf) != NULL) { 11413638Ssam int nargs, i; 11513638Ssam 11617767Sralph u = (struct userpath *)malloc(sizeof (struct userpath)); 11717767Sralph if (u == NULL) { 11813638Ssam DEBUG (1, "*** Userpath malloc failed\n", 0); 11913638Ssam fclose (uf); 12013638Ssam return; 12113638Ssam } 12213638Ssam if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char))) 12313638Ssam == NULL) { 12413638Ssam /* can not allocate space */ 12513638Ssam DEBUG (1, "Userpath calloc 1 failed\n", 0); 12613638Ssam fclose(uf); 12713638Ssam return; 12813638Ssam } 12913638Ssam 13013638Ssam strcpy(pc, buf); 13117767Sralph nargs = getargs(pc, pbuf, 50); 13213638Ssam u->us_lname = pbuf[0]; 13313638Ssam pc = index(u->us_lname, ','); 13413638Ssam if (pc != NULL) 13513638Ssam *pc++ = '\0'; 13613638Ssam else 13713638Ssam pc = u->us_lname + strlen(u->us_lname); 13813638Ssam u->us_mname = pc; 13923588Sbloom if (strlen(u->us_mname) > MAXBASENAME) 14023588Sbloom u->us_mname[MAXBASENAME] = '\0'; 14113638Ssam if (*u->us_lname == '\0' && Logdef == NULL) 14213638Ssam Logdef = u; 14317767Sralph if (*u->us_mname == '\0' && Mchdef == NULL) 14413638Ssam Mchdef = u; 14513638Ssam i = 1; 14613638Ssam if (strcmp(pbuf[1], "c") == SAME) { 14713638Ssam u->us_callback = 1; 14813638Ssam i++; 14913638Ssam } 15013638Ssam else 15113638Ssam u->us_callback = 0; 15217767Sralph cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *)); 15317767Sralph if (cp == NULL) { 15413638Ssam /* can not allocate space */ 15513638Ssam DEBUG (1, "Userpath calloc 2 failed!\n", 0); 15613638Ssam fclose(uf); 15713638Ssam return; 15813638Ssam } 15917767Sralph u->us_path = cp; 16013638Ssam 16113638Ssam while (i < nargs) 16213638Ssam *cp++ = pbuf[i++]; 16313638Ssam *cp = NULL; 16413638Ssam u->unext = Uhead; 16513638Ssam Uhead = u; 16613638Ssam } 16713638Ssam 16813638Ssam fclose(uf); 16913638Ssam return; 17013638Ssam } 17113638Ssam 17213638Ssam /*** 17313638Ssam * callback(name) check for callback 17413638Ssam * char *name; 17513638Ssam * 17613638Ssam * return codes: 17713638Ssam * 0 - no call back 17813638Ssam * 1 - call back 17913638Ssam */ 18013638Ssam 18113638Ssam callback(name) 18213638Ssam register char *name; 18313638Ssam { 18413638Ssam register struct userpath *u; 18513638Ssam 18613638Ssam if (Uptfirst) { 18713638Ssam rdpth(); 18833944Srick if (Uhead == NULL) { 18933944Srick syslog(LOG_ERR, "USERFILE empty!"); 19033944Srick cleanup(FAIL); 19133944Srick } 19213638Ssam Uptfirst = 0; 19313638Ssam } 19413638Ssam 19513638Ssam for (u = Uhead; u != NULL; ) { 19613638Ssam if (strcmp(u->us_lname, name) == SAME) 19713638Ssam /* found user name */ 19817767Sralph return u->us_callback; 19913638Ssam u = u->unext; 20013638Ssam } 20113638Ssam 20213638Ssam /* userid not found */ 20317767Sralph return 0; 20413638Ssam } 20513638Ssam 20613638Ssam 20713638Ssam /*** 20813638Ssam * chkperm(file, mopt) check write permission of file 20913638Ssam * char *mopt; none NULL - create directories 21013638Ssam * 21113638Ssam * if mopt != NULL and permissions are ok, 21213638Ssam * a side effect of this routine is to make 21313638Ssam * directories up to the last part of the 21413638Ssam * filename (if they do not exist). 21513638Ssam * 21617767Sralph * return SUCCESS | FAIL 21713638Ssam */ 21813638Ssam 21913638Ssam chkperm(file, mopt) 22013638Ssam char *file, *mopt; 22113638Ssam { 22213638Ssam struct stat s; 22313638Ssam int ret; 22413638Ssam char dir[MAXFULLNAME]; 22513638Ssam extern char *lastpart(); 22613638Ssam 22713638Ssam if (stat(subfile(file), &s) == 0) { 22818616Sralph if ((s.st_mode & ANYWRITE) == 0) { 22918616Sralph DEBUG(4,"file is not writable: mode %o\n", s.st_mode); 23017767Sralph return FAIL; 23118616Sralph } 23217767Sralph return SUCCESS; 23313638Ssam } 23413638Ssam 23513638Ssam strcpy(dir, file); 23613638Ssam *lastpart(dir) = '\0'; 23718616Sralph if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) { 23818616Sralph DEBUG(4, "can't stat directory %s\n", subfile(dir)); 23917767Sralph return FAIL; 24018616Sralph } 24113638Ssam 24213638Ssam if (ret != -1) { 24313638Ssam if ((s.st_mode & ANYWRITE) == 0) 24417767Sralph return FAIL; 24513638Ssam else 24617767Sralph return SUCCESS; 24713638Ssam } 24813638Ssam 24913638Ssam /* make directories */ 25017767Sralph return mkdirs(file); 25113638Ssam } 25213638Ssam 25313638Ssam /* 25413638Ssam * Check for sufficient privilege to request debugging. 25513638Ssam */ 25617767Sralph chkdebug() 25713638Ssam { 25817767Sralph if (access(SYSFILE, 04) < 0) { 25917767Sralph fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n"); 26013638Ssam cleanup(1); 26113638Ssam exit(1); /* Just in case */ 26213638Ssam } 26313638Ssam } 264