1: #ifndef lint 2: static char sccsid[] = "@(#)chkpth.c 5.1 (Berkeley) 7/2/83"; 3: #endif 4: 5: /* 6: * Doug Kingston, 30 July 82 to fix handling of the "userpath" structures. 7: * (brl-bmd) 8: * rti!trt: the code here is bizarre. There must be a zillion holes. 9: * chkpth should not be called for implied Spool requests . 10: * But explicit requests (foo!/usr/spoo/uucp/*) should use chkpth. 11: */ 12: #include "uucp.h" 13: #include <sys/types.h> 14: #include <sys/stat.h> 15: 16: 17: struct userpath { 18: char *us_lname; 19: char *us_mname; 20: char us_callback; 21: char **us_path; 22: struct userpath *unext; 23: }; 24: struct userpath *Uhead = NULL; 25: struct userpath *Mchdef = NULL, *Logdef = NULL; 26: int Uptfirst = 1; 27: 28: 29: /******* 30: * chkpth(logname, mchname, path) 31: * char *path, *logname, *mchname; 32: * 33: * chkpth - this routine will check the path table for the 34: * machine or log name (non-null parameter) to see if the 35: * input path (path) 36: * starts with an acceptable prefix. 37: * 38: * return codes: 0 | FAIL 39: */ 40: 41: chkpth(logname, mchname, path) 42: char *path, *logname, *mchname; 43: { 44: register struct userpath *u; 45: extern char *lastpart(); 46: register char **p, *s; 47: 48: /* Allow only rooted pathnames. Security wish. rti!trt */ 49: if (*path != '/') 50: return(FAIL); 51: 52: if (Uptfirst) { 53: rdpth(); 54: ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", "", 0); 55: Uptfirst = 0; 56: } 57: for (u = Uhead; u != NULL; ) { 58: if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME) 59: break; 60: if (*mchname != '\0' && strncmp(mchname, u->us_mname, 7) == SAME) 61: break; 62: u = u->unext; 63: } 64: if (u == NULL) { 65: if (*logname == '\0') 66: u = Mchdef; 67: else 68: u = Logdef; 69: if (u == NULL) 70: return(FAIL); 71: } 72: /* found user name */ 73: p = u->us_path; 74: 75: /* check for /../ in path name */ 76: for (s = path; *s != '\0'; s++) { 77: if (prefix("/../",s)) 78: return(FAIL); 79: } 80: 81: /* Check for access permission */ 82: for (p = u->us_path; *p != NULL; p++) 83: if (prefix(*p, path)) 84: return(0); 85: 86: /* path name not valid */ 87: return(FAIL); 88: } 89: 90: 91: /*** 92: * rdpth() 93: * 94: * rdpth - this routine will read the USERFILE and 95: * construct the userpath structure pointed to by (u); 96: * 97: * return codes: 0 | FAIL 98: * 99: * 5/3/81 - changed to enforce the uucp-wide convention that system 100: * names be 7 chars or less in length 101: */ 102: 103: rdpth() 104: { 105: char buf[100 + 1], *pbuf[50 + 1]; 106: register struct userpath *u; 107: register char *pc, **cp; 108: FILE *uf; 109: 110: if ((uf = fopen(USERFILE, "r")) == NULL) { 111: /* can not open file */ 112: return; 113: } 114: 115: while (cfgets(buf, sizeof(buf), uf) != NULL) { 116: int nargs, i; 117: 118: if ((u = (struct userpath *)malloc(sizeof (struct userpath))) == NULL) { 119: DEBUG (1, "*** Userpath malloc failed\n", 0); 120: fclose (uf); 121: return; 122: } 123: if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char))) 124: == NULL) { 125: /* can not allocate space */ 126: DEBUG (1, "Userpath calloc 1 failed\n", 0); 127: fclose(uf); 128: return; 129: } 130: 131: strcpy(pc, buf); 132: nargs = getargs(pc, pbuf); 133: u->us_lname = pbuf[0]; 134: pc = index(u->us_lname, ','); 135: if (pc != NULL) 136: *pc++ = '\0'; 137: else 138: pc = u->us_lname + strlen(u->us_lname); 139: u->us_mname = pc; 140: if (strlen(u->us_mname) > 7) 141: u->us_mname[7] = '\0'; 142: if (*u->us_lname == '\0' && Logdef == NULL) 143: Logdef = u; 144: /* rti!trt: commented following else so 145: * chkpth("","",file) works okay. 146: * I don't understand this, though. 147: */ 148: /*else*/ if (*u->us_mname == '\0' && Mchdef == NULL) 149: Mchdef = u; 150: i = 1; 151: if (strcmp(pbuf[1], "c") == SAME) { 152: u->us_callback = 1; 153: i++; 154: } 155: else 156: u->us_callback = 0; 157: if ((cp = u->us_path = 158: (char **)calloc((unsigned)(nargs-i+1), sizeof(char *))) == NULL) { 159: /* can not allocate space */ 160: DEBUG (1, "Userpath calloc 2 failed!\n", 0); 161: fclose(uf); 162: return; 163: } 164: 165: while (i < nargs) 166: *cp++ = pbuf[i++]; 167: *cp = NULL; 168: u->unext = Uhead; 169: Uhead = u; 170: } 171: 172: fclose(uf); 173: return; 174: } 175: 176: /*** 177: * callback(name) check for callback 178: * char *name; 179: * 180: * return codes: 181: * 0 - no call back 182: * 1 - call back 183: */ 184: 185: callback(name) 186: register char *name; 187: { 188: register struct userpath *u; 189: 190: if (Uptfirst) { 191: rdpth(); 192: ASSERT(Uhead != NULL, "INIT USERFILE, No Users!", "", 0); 193: Uptfirst = 0; 194: } 195: 196: for (u = Uhead; u != NULL; ) { 197: if (strcmp(u->us_lname, name) == SAME) 198: /* found user name */ 199: return(u->us_callback); 200: u = u->unext; 201: } 202: 203: /* userid not found */ 204: return(0); 205: } 206: 207: 208: /*** 209: * chkperm(file, mopt) check write permission of file 210: * char *mopt; none NULL - create directories 211: * 212: * if mopt != NULL and permissions are ok, 213: * a side effect of this routine is to make 214: * directories up to the last part of the 215: * filename (if they do not exist). 216: * 217: * return 0 | FAIL 218: */ 219: 220: chkperm(file, mopt) 221: char *file, *mopt; 222: { 223: struct stat s; 224: int ret; 225: char dir[MAXFULLNAME]; 226: extern char *lastpart(); 227: 228: if (stat(subfile(file), &s) == 0) { 229: /* Forbid scribbling on a not-generally-writable file */ 230: /* rti!trt */ 231: if ((s.st_mode & ANYWRITE) == 0) 232: return(FAIL); 233: return(0); 234: } 235: 236: strcpy(dir, file); 237: *lastpart(dir) = '\0'; 238: if ((ret = stat(subfile(dir), &s)) == -1 239: && mopt == NULL) 240: return(FAIL); 241: 242: if (ret != -1) { 243: if ((s.st_mode & ANYWRITE) == 0) 244: return(FAIL); 245: else 246: return(0); 247: } 248: 249: /* make directories */ 250: return(mkdirs(file)); 251: } 252: 253: /* 254: * Check for sufficient privilege to request debugging. 255: * Suggested by seismo!stewart, John Stewart. 256: */ 257: chkdebug(uid) 258: int uid; 259: { 260: if (uid > PRIV_UIDS) { 261: fprintf(stderr, "Sorry, uid must be <= %d for debugging\n", 262: PRIV_UIDS); 263: cleanup(1); 264: exit(1); /* Just in case */ 265: } 266: }