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