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