14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin /* 244887Schin * Glenn Fowler 254887Schin * AT&T Research 264887Schin * 274887Schin * apply file permission expression expr to perm 284887Schin * 294887Schin * each expression term must match 304887Schin * 314887Schin * [ugoa]*[-&+|^=]?[rwxst0-7]* 324887Schin * 334887Schin * terms may be combined using , 344887Schin * 354887Schin * if non-null, e points to the first unrecognized char in expr 364887Schin */ 374887Schin 384887Schin #include <ast.h> 394887Schin #include <ls.h> 404887Schin #include <modex.h> 414887Schin 424887Schin int strperm(const char * aexpr,char ** e,register int perm)434887Schinstrperm(const char* aexpr, char** e, register int perm) 444887Schin { 454887Schin register char* expr = (char*)aexpr; 464887Schin register int c; 474887Schin register int typ; 484887Schin register int who; 494887Schin int num; 504887Schin int op; 514887Schin int mask; 524887Schin int masked; 534887Schin 544887Schin if (perm == -1) 554887Schin { 564887Schin perm = 0; 574887Schin masked = 1; 584887Schin mask = ~0; 594887Schin } 604887Schin else 614887Schin masked = 0; 624887Schin for (;;) 634887Schin { 644887Schin op = num = who = typ = 0; 654887Schin for (;;) 664887Schin { 674887Schin switch (c = *expr++) 684887Schin { 694887Schin case 'u': 704887Schin who |= S_ISVTX|S_ISUID|S_IRWXU; 714887Schin continue; 724887Schin case 'g': 734887Schin who |= S_ISVTX|S_ISGID|S_IRWXG; 744887Schin continue; 754887Schin case 'o': 764887Schin who |= S_ISVTX|S_IRWXO; 774887Schin continue; 784887Schin case 'a': 794887Schin who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 804887Schin continue; 814887Schin default: 824887Schin if (c >= '0' && c <= '7') 834887Schin { 844887Schin if (!who) 854887Schin who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 864887Schin c = '='; 874887Schin } 884887Schin expr--; 894887Schin /*FALLTHROUGH*/ 904887Schin case '=': 914887Schin if (who) 924887Schin perm &= ~who; 934887Schin else 944887Schin perm = 0; 954887Schin /*FALLTHROUGH*/ 964887Schin case '+': 974887Schin case '|': 984887Schin case '-': 994887Schin case '&': 1004887Schin case '^': 1014887Schin op = c; 1024887Schin for (;;) 1034887Schin { 1044887Schin switch (c = *expr++) 1054887Schin { 1064887Schin case 'r': 1074887Schin typ |= S_IRUSR|S_IRGRP|S_IROTH; 1084887Schin continue; 1094887Schin case 'w': 1104887Schin typ |= S_IWUSR|S_IWGRP|S_IWOTH; 1114887Schin continue; 1124887Schin case 'X': 1134887Schin if (!S_ISDIR(perm) && !(perm & (S_IXUSR|S_IXGRP|S_IXOTH))) 1144887Schin continue; 1154887Schin /*FALLTHROUGH*/ 1164887Schin case 'x': 1174887Schin typ |= S_IXUSR|S_IXGRP|S_IXOTH; 1184887Schin continue; 1194887Schin case 's': 1204887Schin typ |= S_ISUID|S_ISGID; 1214887Schin continue; 1224887Schin case 't': 1234887Schin typ |= S_ISVTX; 1244887Schin continue; 1254887Schin case 'l': 1264887Schin if (perm & S_IXGRP) 1274887Schin { 1284887Schin if (e) 1294887Schin *e = expr - 1; 1304887Schin return perm & S_IPERM; 1314887Schin } 1324887Schin typ |= S_ISGID; 1334887Schin continue; 1344887Schin case '=': 1354887Schin case '+': 1364887Schin case '|': 1374887Schin case '-': 1384887Schin case '&': 1394887Schin case '^': 1404887Schin case ',': 1414887Schin case 0: 1424887Schin if (who) 1434887Schin typ &= who; 1444887Schin else 1454887Schin switch (op) 1464887Schin { 1474887Schin case '=': 1484887Schin case '+': 1494887Schin case '|': 1504887Schin case '-': 1514887Schin case '&': 1524887Schin if (!masked) 1534887Schin { 1544887Schin masked = 1; 1554887Schin umask(mask = umask(0)); 1564887Schin mask = ~mask; 1574887Schin } 1584887Schin typ &= mask; 1594887Schin break; 1604887Schin } 1614887Schin switch (op) 1624887Schin { 1634887Schin default: 1644887Schin if (who) 1654887Schin perm &= ~who; 1664887Schin else 1674887Schin perm = 0; 1684887Schin /*FALLTHROUGH*/ 1694887Schin case '+': 1704887Schin case '|': 1714887Schin perm |= typ; 1724887Schin typ = 0; 1734887Schin break; 1744887Schin case '-': 1754887Schin perm &= ~typ; 1764887Schin typ = 0; 1774887Schin break; 1784887Schin case '&': 1794887Schin perm &= typ; 1804887Schin typ = 0; 1814887Schin break; 1824887Schin case '^': 1834887Schin if (typ &= perm) 1844887Schin { 1854887Schin /* 1864887Schin * propagate least restrictive to most restrictive 1874887Schin */ 1884887Schin 1894887Schin if (typ & S_IXOTH) 1904887Schin perm |= who & (S_IXUSR|S_IXGRP); 1914887Schin if (typ & S_IWOTH) 1924887Schin perm |= who & (S_IWUSR|S_IWGRP); 1934887Schin if (typ & S_IROTH) 1944887Schin perm |= who & (S_IRUSR|S_IRGRP); 1954887Schin if (typ & S_IXGRP) 1964887Schin perm |= who & S_IXUSR; 1974887Schin if (typ & S_IWGRP) 1984887Schin perm |= who & S_IWUSR; 1994887Schin if (typ & S_IRGRP) 2004887Schin perm |= who & S_IRUSR; 2014887Schin 2024887Schin /* 2034887Schin * if any execute then read => execute 2044887Schin */ 2054887Schin 2064887Schin if ((typ |= perm) & (S_IXUSR|S_IXGRP|S_IXOTH)) 2074887Schin { 2084887Schin if (typ & S_IRUSR) 2094887Schin perm |= who & S_IXUSR; 2104887Schin if (typ & S_IRGRP) 2114887Schin perm |= who & S_IXGRP; 2124887Schin if (typ & S_IROTH) 2134887Schin perm |= who & S_IXOTH; 2144887Schin } 2154887Schin typ = 0; 2164887Schin } 2174887Schin break; 2184887Schin } 2194887Schin switch (c) 2204887Schin { 2214887Schin case '=': 2224887Schin case '+': 2234887Schin case '|': 2244887Schin case '-': 2254887Schin case '&': 2264887Schin case '^': 2274887Schin op = c; 2284887Schin typ = 0; 2294887Schin continue; 2304887Schin } 2314887Schin if (c) 2324887Schin break; 2334887Schin /*FALLTHROUGH*/ 2344887Schin default: 2354887Schin if (c < '0' || c > '7') 2364887Schin { 2374887Schin if (e) 2384887Schin *e = expr - 1; 2394887Schin if (typ) 2404887Schin { 2414887Schin if (who) 2424887Schin { 2434887Schin typ &= who; 2444887Schin perm &= ~who; 2454887Schin } 2464887Schin perm |= typ; 2474887Schin } 2484887Schin return perm & S_IPERM; 2494887Schin } 2504887Schin num = (num << 3) | (c - '0'); 2514887Schin if (!who && (op == '+' || op == '-')) 2524887Schin who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; 2534887Schin if (*expr < '0' || *expr > '7') 2544887Schin { 2554887Schin typ |= modei(num); 2564887Schin num = 0; 2574887Schin } 2584887Schin continue; 2594887Schin } 2604887Schin break; 2614887Schin } 2624887Schin break; 2634887Schin } 2644887Schin break; 2654887Schin } 2664887Schin } 2674887Schin } 268