xref: /onnv-gate/usr/src/lib/libast/common/string/strperm.c (revision 12068:08a39a083754)
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)434887Schin strperm(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