1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * apply file permission expression expr to perm 28 * 29 * each expression term must match 30 * 31 * [ugoa]*[-&+|^=]?[rwxst0-7]* 32 * 33 * terms may be combined using , 34 * 35 * if non-null, e points to the first unrecognized char in expr 36 */ 37 38 #include <ast.h> 39 #include <ls.h> 40 #include <modex.h> 41 42 int 43 strperm(const char* aexpr, char** e, register int perm) 44 { 45 register char* expr = (char*)aexpr; 46 register int c; 47 register int typ; 48 register int who; 49 int num; 50 int op; 51 int mask; 52 int masked; 53 54 if (perm == -1) 55 { 56 perm = 0; 57 masked = 1; 58 mask = ~0; 59 } 60 else 61 masked = 0; 62 for (;;) 63 { 64 op = num = who = typ = 0; 65 for (;;) 66 { 67 switch (c = *expr++) 68 { 69 case 'u': 70 who |= S_ISVTX|S_ISUID|S_IRWXU; 71 continue; 72 case 'g': 73 who |= S_ISVTX|S_ISGID|S_IRWXG; 74 continue; 75 case 'o': 76 who |= S_ISVTX|S_IRWXO; 77 continue; 78 case 'a': 79 who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 80 continue; 81 default: 82 if (c >= '0' && c <= '7') 83 { 84 if (!who) 85 who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 86 c = '='; 87 } 88 expr--; 89 /*FALLTHROUGH*/ 90 case '=': 91 if (who) 92 perm &= ~who; 93 else 94 perm = 0; 95 /*FALLTHROUGH*/ 96 case '+': 97 case '|': 98 case '-': 99 case '&': 100 case '^': 101 op = c; 102 for (;;) 103 { 104 switch (c = *expr++) 105 { 106 case 'r': 107 typ |= S_IRUSR|S_IRGRP|S_IROTH; 108 continue; 109 case 'w': 110 typ |= S_IWUSR|S_IWGRP|S_IWOTH; 111 continue; 112 case 'X': 113 if (!S_ISDIR(perm) && !(perm & (S_IXUSR|S_IXGRP|S_IXOTH))) 114 continue; 115 /*FALLTHROUGH*/ 116 case 'x': 117 typ |= S_IXUSR|S_IXGRP|S_IXOTH; 118 continue; 119 case 's': 120 typ |= S_ISUID|S_ISGID; 121 continue; 122 case 't': 123 typ |= S_ISVTX; 124 continue; 125 case 'l': 126 if (perm & S_IXGRP) 127 { 128 if (e) 129 *e = expr - 1; 130 return perm & S_IPERM; 131 } 132 typ |= S_ISGID; 133 continue; 134 case '=': 135 case '+': 136 case '|': 137 case '-': 138 case '&': 139 case '^': 140 case ',': 141 case 0: 142 if (who) 143 typ &= who; 144 else 145 switch (op) 146 { 147 case '=': 148 case '+': 149 case '|': 150 case '-': 151 case '&': 152 if (!masked) 153 { 154 masked = 1; 155 umask(mask = umask(0)); 156 mask = ~mask; 157 } 158 typ &= mask; 159 break; 160 } 161 switch (op) 162 { 163 default: 164 if (who) 165 perm &= ~who; 166 else 167 perm = 0; 168 /*FALLTHROUGH*/ 169 case '+': 170 case '|': 171 perm |= typ; 172 typ = 0; 173 break; 174 case '-': 175 perm &= ~typ; 176 typ = 0; 177 break; 178 case '&': 179 perm &= typ; 180 typ = 0; 181 break; 182 case '^': 183 if (typ &= perm) 184 { 185 /* 186 * propagate least restrictive to most restrictive 187 */ 188 189 if (typ & S_IXOTH) 190 perm |= who & (S_IXUSR|S_IXGRP); 191 if (typ & S_IWOTH) 192 perm |= who & (S_IWUSR|S_IWGRP); 193 if (typ & S_IROTH) 194 perm |= who & (S_IRUSR|S_IRGRP); 195 if (typ & S_IXGRP) 196 perm |= who & S_IXUSR; 197 if (typ & S_IWGRP) 198 perm |= who & S_IWUSR; 199 if (typ & S_IRGRP) 200 perm |= who & S_IRUSR; 201 202 /* 203 * if any execute then read => execute 204 */ 205 206 if ((typ |= perm) & (S_IXUSR|S_IXGRP|S_IXOTH)) 207 { 208 if (typ & S_IRUSR) 209 perm |= who & S_IXUSR; 210 if (typ & S_IRGRP) 211 perm |= who & S_IXGRP; 212 if (typ & S_IROTH) 213 perm |= who & S_IXOTH; 214 } 215 typ = 0; 216 } 217 break; 218 } 219 switch (c) 220 { 221 case '=': 222 case '+': 223 case '|': 224 case '-': 225 case '&': 226 case '^': 227 op = c; 228 typ = 0; 229 continue; 230 } 231 if (c) 232 break; 233 /*FALLTHROUGH*/ 234 default: 235 if (c < '0' || c > '7') 236 { 237 if (e) 238 *e = expr - 1; 239 if (typ) 240 { 241 if (who) 242 { 243 typ &= who; 244 perm &= ~who; 245 } 246 perm |= typ; 247 } 248 return perm & S_IPERM; 249 } 250 num = (num << 3) | (c - '0'); 251 if (!who && (op == '+' || op == '-')) 252 who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 253 if (*expr < '0' || *expr > '7') 254 { 255 typ |= modei(num); 256 num = 0; 257 } 258 continue; 259 } 260 break; 261 } 262 break; 263 } 264 break; 265 } 266 } 267 } 268