| 1 | #include "uucp.h" |
| 2 | #include <sys/types.h> |
| 3 | #include <sys/stat.h> |
| 4 | |
| 5 | |
| 6 | #define DFLTNAME "default" |
| 7 | #define MAXUSERS 20 |
| 8 | struct userpath { |
| 9 | char *us_lname; |
| 10 | char *us_mname; |
| 11 | char us_callback; |
| 12 | char **us_path; |
| 13 | }; |
| 14 | struct userpath Upt[15]; |
| 15 | struct userpath *Mchdef = NULL, *Logdef = NULL; |
| 16 | int Nbrusers = 0; |
| 17 | int Uptfirst = 1; |
| 18 | |
| 19 | /******* |
| 20 | * chkpth(logname, mchname, path) |
| 21 | * char *path, *logname, *mchname; |
| 22 | * |
| 23 | * chkpth - this routine will check the path table for the |
| 24 | * machine or log name (non-null parameter) to see if the |
| 25 | * input path (path) |
| 26 | * starts with an acceptable prefix. |
| 27 | * |
| 28 | * return codes: 0 | FAIL |
| 29 | */ |
| 30 | |
| 31 | chkpth(logname, mchname, path) |
| 32 | char *path, *logname, *mchname; |
| 33 | { |
| 34 | struct userpath *u; |
| 35 | extern char *lastpart(); |
| 36 | char **p, *s; |
| 37 | char c; |
| 38 | int ret, i; |
| 39 | |
| 40 | if (prefix(THISDIR, path)) |
| 41 | return(FAIL); |
| 42 | if (Uptfirst) { |
| 43 | ret = rdpth(Upt); |
| 44 | ASSERT(ret == 0, "INIT USERFILE %d", Nbrusers); |
| 45 | Uptfirst = 0; |
| 46 | } |
| 47 | for (u = Upt, i = 0; i < Nbrusers; i++, u++) { |
| 48 | if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME) |
| 49 | break; |
| 50 | if (*mchname != '\0' && strcmp(mchname, u->us_mname) == SAME) |
| 51 | break; |
| 52 | |
| 53 | } |
| 54 | if (i >= Nbrusers) { |
| 55 | if (*logname == '\0') |
| 56 | u = Mchdef; |
| 57 | else |
| 58 | u = Logdef; |
| 59 | if (u == NULL) |
| 60 | return(FAIL); |
| 61 | } |
| 62 | /* found user name */ |
| 63 | p = u->us_path; |
| 64 | /* check for /../ in path name */ |
| 65 | for (s = path; *s != '\0'; s++) { |
| 66 | if (*s == '/' && prefix("../", (++s))) |
| 67 | return(FAIL); |
| 68 | } |
| 69 | |
| 70 | if (chklnk(path) > LINKLEVEL) |
| 71 | return(FAIL); |
| 72 | for (p = u->us_path; *p != NULL; p++) |
| 73 | if (prefix(*p, path)) |
| 74 | return(0); |
| 75 | |
| 76 | if (prefix(Spool, path)) { |
| 77 | if ((c = *lastpart(path)) == DATAPRE |
| 78 | || c == XQTPRE) |
| 79 | return(0); |
| 80 | } |
| 81 | /* path name not valid */ |
| 82 | return(FAIL); |
| 83 | } |
| 84 | |
| 85 | |
| 86 | /*** |
| 87 | * rdpth(u) |
| 88 | * struct userpath *u; |
| 89 | * |
| 90 | * rdpth - this routine will read the USFILE and |
| 91 | * construct the userpath structure pointed to by (u); |
| 92 | * |
| 93 | * return codes: 0 | FAIL |
| 94 | */ |
| 95 | |
| 96 | rdpth(u) |
| 97 | struct userpath *u; |
| 98 | { |
| 99 | char buf[BUFSIZ + 1], *pbuf[BUFSIZ + 1], *pc, **cp; |
| 100 | extern char *calloc(), *index(); |
| 101 | FILE *uf; |
| 102 | |
| 103 | if ((uf = fopen(USERFILE, "r")) == NULL) { |
| 104 | /* can not open file */ |
| 105 | return(FAIL); |
| 106 | } |
| 107 | |
| 108 | while (fgets(buf, BUFSIZ, uf) != NULL) { |
| 109 | int nargs, i; |
| 110 | if (++Nbrusers > MAXUSERS) { |
| 111 | fclose(uf); |
| 112 | return(FAIL); |
| 113 | } |
| 114 | if ((pc = calloc(strlen(buf) + 1, sizeof (char))) |
| 115 | == NULL) { |
| 116 | /* can not allocate space */ |
| 117 | fclose(uf); |
| 118 | return(FAIL); |
| 119 | } |
| 120 | |
| 121 | strcpy(pc, buf); |
| 122 | nargs = getargs(pc, pbuf); |
| 123 | u->us_lname = pbuf[0]; |
| 124 | pc = index(u->us_lname, ','); |
| 125 | if (pc != NULL) |
| 126 | *pc++ = '\0'; |
| 127 | else |
| 128 | pc = u + strlen(u->us_lname); |
| 129 | u->us_mname = pc; |
| 130 | if (*u->us_lname == '\0') |
| 131 | Logdef = u; |
| 132 | else if (*u->us_mname == '\0') |
| 133 | Mchdef = u; |
| 134 | i = 1; |
| 135 | if (strcmp(pbuf[1], "c") == SAME) { |
| 136 | u->us_callback = 1; |
| 137 | i++; |
| 138 | } |
| 139 | else |
| 140 | u->us_callback = 0; |
| 141 | if ((cp = u->us_path = |
| 142 | calloc(nargs - i + 1, sizeof (char *))) == NULL) { |
| 143 | /* can not allocate space */ |
| 144 | fclose(uf); |
| 145 | return(FAIL); |
| 146 | } |
| 147 | |
| 148 | while (i < nargs) |
| 149 | *cp++ = pbuf[i++]; |
| 150 | *cp = NULL; |
| 151 | u++; |
| 152 | } |
| 153 | |
| 154 | fclose(uf); |
| 155 | return(0); |
| 156 | } |
| 157 | |
| 158 | |
| 159 | /*** |
| 160 | * callback(name) check for callback |
| 161 | * char *name; |
| 162 | * |
| 163 | * return codes: |
| 164 | * 0 - no call back |
| 165 | * 1 - call back |
| 166 | */ |
| 167 | |
| 168 | callback(name) |
| 169 | char *name; |
| 170 | { |
| 171 | struct userpath *u; |
| 172 | int ret, i; |
| 173 | |
| 174 | if (Uptfirst) { |
| 175 | ret = rdpth(Upt); |
| 176 | ASSERT(ret == 0, "INIT USERFILE %d", Nbrusers); |
| 177 | Uptfirst = 0; |
| 178 | } |
| 179 | |
| 180 | for (u = Upt, i = 0; i < Nbrusers; u++, i++) { |
| 181 | if (strcmp(u->us_lname, name) != SAME) |
| 182 | continue; |
| 183 | |
| 184 | /* found user name */ |
| 185 | return(u->us_callback); |
| 186 | } |
| 187 | |
| 188 | /* userid not found */ |
| 189 | return(0); |
| 190 | } |
| 191 | |
| 192 | |
| 193 | /*** |
| 194 | * chklnk(name) get number of links |
| 195 | * char *name; |
| 196 | * |
| 197 | * return codes: 0 - stat failed or directory | number of links |
| 198 | */ |
| 199 | |
| 200 | chklnk(name) |
| 201 | char *name; |
| 202 | { |
| 203 | struct stat s; |
| 204 | |
| 205 | if (stat(name, &s) == -1) |
| 206 | return(0); |
| 207 | if ((s.st_mode & S_IFMT) == S_IFDIR) |
| 208 | return(0); |
| 209 | return(s.st_nlinks); |
| 210 | } |
| 211 | |
| 212 | |
| 213 | /*** |
| 214 | * chkperm(file, user, mopt) check write permission of file |
| 215 | * char *file, *user; |
| 216 | * char *mopt; none NULL - create directories |
| 217 | * |
| 218 | * if mopt != NULL and permissions are ok, |
| 219 | * a side effect of this routine is to make |
| 220 | * directories up to the last part of the |
| 221 | * filename (if they do not exist). |
| 222 | * |
| 223 | * return 0 | FAIL |
| 224 | */ |
| 225 | |
| 226 | chkperm(file, user, mopt) |
| 227 | char *file, *user, *mopt; |
| 228 | { |
| 229 | struct stat s; |
| 230 | int ret, bits; |
| 231 | char dir[MAXFULLNAME]; |
| 232 | extern char *lastpart(); |
| 233 | |
| 234 | if (stat(file, &s) != -1) |
| 235 | return(0); |
| 236 | |
| 237 | strcpy(dir, file); |
| 238 | *lastpart(dir) = '\0'; |
| 239 | if ((ret = stat(dir, &s)) == -1 |
| 240 | && mopt == NULL) |
| 241 | return(FAIL); |
| 242 | |
| 243 | bits = (geteuid() == 0) ? 02 : 0200; |
| 244 | if (ret != -1) { |
| 245 | if ((s.st_mode & bits) == 0) |
| 246 | return(FAIL); |
| 247 | else |
| 248 | return(0); |
| 249 | } |
| 250 | |
| 251 | /* make directories */ |
| 252 | return(mkdirs(file)); |
| 253 | } |