1 |
diff -up sudo-1.8.6p3/plugins/sudoers/alias.c.cycledetect sudo-1.8.6p3/plugins/sudoers/alias.c |
2 |
--- sudo-1.8.6p3/plugins/sudoers/alias.c.cycledetect 2012-09-18 15:56:29.000000000 +0200 |
3 |
+++ sudo-1.8.6p3/plugins/sudoers/alias.c 2013-08-09 10:52:04.785860905 +0200 |
4 |
@@ -1,5 +1,5 @@ |
5 |
/* |
6 |
- * Copyright (c) 2004-2005, 2007-2011 |
7 |
+ * Copyright (c) 2004-2005, 2007-2013 |
8 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
9 |
* |
10 |
* Permission to use, copy, modify, and distribute this software for any |
11 |
@@ -50,7 +50,6 @@ |
12 |
* Globals |
13 |
*/ |
14 |
struct rbtree *aliases; |
15 |
-unsigned int alias_seqno; |
16 |
|
17 |
/* |
18 |
* Comparison function for the red-black tree. |
19 |
@@ -76,29 +75,31 @@ alias_compare(const void *v1, const void |
20 |
/* |
21 |
* Search the tree for an alias with the specified name and type. |
22 |
* Returns a pointer to the alias structure or NULL if not found. |
23 |
+ * Caller is responsible for calling alias_put() on the returned |
24 |
+ * alias to mark it as unused. |
25 |
*/ |
26 |
struct alias * |
27 |
-alias_find(char *name, int type) |
28 |
+alias_get(char *name, int type) |
29 |
{ |
30 |
struct alias key; |
31 |
struct rbnode *node; |
32 |
struct alias *a = NULL; |
33 |
- debug_decl(alias_find, SUDO_DEBUG_ALIAS) |
34 |
+ debug_decl(alias_get, SUDO_DEBUG_ALIAS) |
35 |
|
36 |
key.name = name; |
37 |
key.type = type; |
38 |
if ((node = rbfind(aliases, &key)) != NULL) { |
39 |
/* |
40 |
- * Compare the global sequence number with the one stored |
41 |
- * in the alias. If they match then we've seen this alias |
42 |
- * before and found a loop. |
43 |
+ * Check whether this alias is already in use. |
44 |
+ * If so, we've detected a loop. If not, set the flag, |
45 |
+ * which the caller should clear with a call to alias_put(). |
46 |
*/ |
47 |
a = node->data; |
48 |
- if (a->seqno == alias_seqno) { |
49 |
+ if (a->used) { |
50 |
errno = ELOOP; |
51 |
debug_return_ptr(NULL); |
52 |
} |
53 |
- a->seqno = alias_seqno; |
54 |
+ a->used = true; |
55 |
} else { |
56 |
errno = ENOENT; |
57 |
} |
58 |
@@ -106,6 +107,17 @@ alias_find(char *name, int type) |
59 |
} |
60 |
|
61 |
/* |
62 |
+ * Clear the "used" flag in an alias once the caller is done with it. |
63 |
+ */ |
64 |
+void |
65 |
+alias_put(struct alias *a) |
66 |
+{ |
67 |
+ debug_decl(alias_put, SUDO_DEBUG_ALIAS) |
68 |
+ a->used = false; |
69 |
+ debug_return; |
70 |
+} |
71 |
+ |
72 |
+/* |
73 |
* Add an alias to the aliases redblack tree. |
74 |
* Returns NULL on success and an error string on failure. |
75 |
*/ |
76 |
@@ -119,7 +131,7 @@ alias_add(char *name, int type, struct m |
77 |
a = ecalloc(1, sizeof(*a)); |
78 |
a->name = name; |
79 |
a->type = type; |
80 |
- /* a->seqno = 0; */ |
81 |
+ /* a->used = false; */ |
82 |
list2tq(&a->members, members); |
83 |
if (rbinsert(aliases, a)) { |
84 |
snprintf(errbuf, sizeof(errbuf), _("Alias `%s' already defined"), name); |
85 |
diff -up sudo-1.8.6p3/plugins/sudoers/match.c.cycledetect sudo-1.8.6p3/plugins/sudoers/match.c |
86 |
--- sudo-1.8.6p3/plugins/sudoers/match.c.cycledetect 2013-08-09 10:52:04.783860895 +0200 |
87 |
+++ sudo-1.8.6p3/plugins/sudoers/match.c 2013-08-09 10:52:04.785860905 +0200 |
88 |
@@ -101,13 +101,13 @@ static bool command_matches_normal(char |
89 |
* Check for user described by pw in a list of members. |
90 |
* Returns ALLOW, DENY or UNSPEC. |
91 |
*/ |
92 |
-static int |
93 |
-_userlist_matches(struct passwd *pw, struct member_list *list) |
94 |
+int |
95 |
+userlist_matches(struct passwd *pw, struct member_list *list) |
96 |
{ |
97 |
struct member *m; |
98 |
struct alias *a; |
99 |
int rval, matched = UNSPEC; |
100 |
- debug_decl(_userlist_matches, SUDO_DEBUG_MATCH) |
101 |
+ debug_decl(userlist_matches, SUDO_DEBUG_MATCH) |
102 |
|
103 |
tq_foreach_rev(list, m) { |
104 |
switch (m->type) { |
105 |
@@ -123,10 +123,11 @@ _userlist_matches(struct passwd *pw, str |
106 |
matched = !m->negated; |
107 |
break; |
108 |
case ALIAS: |
109 |
- if ((a = alias_find(m->name, USERALIAS)) != NULL) { |
110 |
- rval = _userlist_matches(pw, &a->members); |
111 |
+ if ((a = alias_get(m->name, USERALIAS)) != NULL) { |
112 |
+ rval = userlist_matches(pw, &a->members); |
113 |
if (rval != UNSPEC) |
114 |
matched = m->negated ? !rval : rval; |
115 |
+ alias_put(a); |
116 |
break; |
117 |
} |
118 |
/* FALLTHROUGH */ |
119 |
@@ -141,20 +142,13 @@ _userlist_matches(struct passwd *pw, str |
120 |
debug_return_bool(matched); |
121 |
} |
122 |
|
123 |
-int |
124 |
-userlist_matches(struct passwd *pw, struct member_list *list) |
125 |
-{ |
126 |
- alias_seqno++; |
127 |
- return _userlist_matches(pw, list); |
128 |
-} |
129 |
- |
130 |
/* |
131 |
* Check for user described by pw in a list of members. |
132 |
* If both lists are empty compare against def_runas_default. |
133 |
* Returns ALLOW, DENY or UNSPEC. |
134 |
*/ |
135 |
-static int |
136 |
-_runaslist_matches(struct member_list *user_list, |
137 |
+int |
138 |
+runaslist_matches(struct member_list *user_list, |
139 |
struct member_list *group_list, struct member **matching_user, |
140 |
struct member **matching_group) |
141 |
{ |
142 |
@@ -163,7 +157,7 @@ _runaslist_matches(struct member_list *u |
143 |
int rval; |
144 |
int user_matched = UNSPEC; |
145 |
int group_matched = UNSPEC; |
146 |
- debug_decl(_runaslist_matches, SUDO_DEBUG_MATCH) |
147 |
+ debug_decl(runaslist_matches, SUDO_DEBUG_MATCH) |
148 |
|
149 |
if (runas_pw != NULL) { |
150 |
/* If no runas user or runas group listed in sudoers, use default. */ |
151 |
@@ -184,11 +178,12 @@ _runaslist_matches(struct member_list *u |
152 |
user_matched = !m->negated; |
153 |
break; |
154 |
case ALIAS: |
155 |
- if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { |
156 |
- rval = _runaslist_matches(&a->members, &empty, |
157 |
+ if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { |
158 |
+ rval = runaslist_matches(&a->members, &empty, |
159 |
matching_user, NULL); |
160 |
if (rval != UNSPEC) |
161 |
user_matched = m->negated ? !rval : rval; |
162 |
+ alias_put(a); |
163 |
break; |
164 |
} |
165 |
/* FALLTHROUGH */ |
166 |
@@ -221,11 +216,12 @@ _runaslist_matches(struct member_list *u |
167 |
group_matched = !m->negated; |
168 |
break; |
169 |
case ALIAS: |
170 |
- if ((a = alias_find(m->name, RUNASALIAS)) != NULL) { |
171 |
- rval = _runaslist_matches(&empty, &a->members, |
172 |
+ if ((a = alias_get(m->name, RUNASALIAS)) != NULL) { |
173 |
+ rval = runaslist_matches(&empty, &a->members, |
174 |
NULL, matching_group); |
175 |
if (rval != UNSPEC) |
176 |
group_matched = m->negated ? !rval : rval; |
177 |
+ alias_put(a); |
178 |
break; |
179 |
} |
180 |
/* FALLTHROUGH */ |
181 |
@@ -253,27 +249,17 @@ _runaslist_matches(struct member_list *u |
182 |
debug_return_int(UNSPEC); |
183 |
} |
184 |
|
185 |
-int |
186 |
-runaslist_matches(struct member_list *user_list, |
187 |
- struct member_list *group_list, struct member **matching_user, |
188 |
- struct member **matching_group) |
189 |
-{ |
190 |
- alias_seqno++; |
191 |
- return _runaslist_matches(user_list ? user_list : &empty, |
192 |
- group_list ? group_list : &empty, matching_user, matching_group); |
193 |
-} |
194 |
- |
195 |
/* |
196 |
* Check for host and shost in a list of members. |
197 |
* Returns ALLOW, DENY or UNSPEC. |
198 |
*/ |
199 |
-static int |
200 |
-_hostlist_matches(struct member_list *list) |
201 |
+int |
202 |
+hostlist_matches(struct member_list *list) |
203 |
{ |
204 |
struct member *m; |
205 |
struct alias *a; |
206 |
int rval, matched = UNSPEC; |
207 |
- debug_decl(_hostlist_matches, SUDO_DEBUG_MATCH) |
208 |
+ debug_decl(hostlist_matches, SUDO_DEBUG_MATCH) |
209 |
|
210 |
tq_foreach_rev(list, m) { |
211 |
switch (m->type) { |
212 |
@@ -289,10 +275,11 @@ _hostlist_matches(struct member_list *li |
213 |
matched = !m->negated; |
214 |
break; |
215 |
case ALIAS: |
216 |
- if ((a = alias_find(m->name, HOSTALIAS)) != NULL) { |
217 |
- rval = _hostlist_matches(&a->members); |
218 |
+ if ((a = alias_get(m->name, HOSTALIAS)) != NULL) { |
219 |
+ rval = hostlist_matches(&a->members); |
220 |
if (rval != UNSPEC) |
221 |
matched = m->negated ? !rval : rval; |
222 |
+ alias_put(a); |
223 |
break; |
224 |
} |
225 |
/* FALLTHROUGH */ |
226 |
@@ -307,23 +294,16 @@ _hostlist_matches(struct member_list *li |
227 |
debug_return_bool(matched); |
228 |
} |
229 |
|
230 |
-int |
231 |
-hostlist_matches(struct member_list *list) |
232 |
-{ |
233 |
- alias_seqno++; |
234 |
- return _hostlist_matches(list); |
235 |
-} |
236 |
- |
237 |
/* |
238 |
* Check for cmnd and args in a list of members. |
239 |
* Returns ALLOW, DENY or UNSPEC. |
240 |
*/ |
241 |
-static int |
242 |
-_cmndlist_matches(struct member_list *list) |
243 |
+int |
244 |
+cmndlist_matches(struct member_list *list) |
245 |
{ |
246 |
struct member *m; |
247 |
int matched = UNSPEC; |
248 |
- debug_decl(_cmndlist_matches, SUDO_DEBUG_MATCH) |
249 |
+ debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH) |
250 |
|
251 |
tq_foreach_rev(list, m) { |
252 |
matched = cmnd_matches(m); |
253 |
@@ -333,13 +313,6 @@ _cmndlist_matches(struct member_list *li |
254 |
debug_return_bool(matched); |
255 |
} |
256 |
|
257 |
-int |
258 |
-cmndlist_matches(struct member_list *list) |
259 |
-{ |
260 |
- alias_seqno++; |
261 |
- return _cmndlist_matches(list); |
262 |
-} |
263 |
- |
264 |
/* |
265 |
* Check cmnd and args. |
266 |
* Returns ALLOW, DENY or UNSPEC. |
267 |
@@ -357,11 +330,11 @@ cmnd_matches(struct member *m) |
268 |
matched = !m->negated; |
269 |
break; |
270 |
case ALIAS: |
271 |
- alias_seqno++; |
272 |
- if ((a = alias_find(m->name, CMNDALIAS)) != NULL) { |
273 |
- rval = _cmndlist_matches(&a->members); |
274 |
+ if ((a = alias_get(m->name, CMNDALIAS)) != NULL) { |
275 |
+ rval = cmndlist_matches(&a->members); |
276 |
if (rval != UNSPEC) |
277 |
matched = m->negated ? !rval : rval; |
278 |
+ alias_put(a); |
279 |
} |
280 |
break; |
281 |
case COMMAND: |
282 |
diff -up sudo-1.8.6p3/plugins/sudoers/parse.c.cycledetect sudo-1.8.6p3/plugins/sudoers/parse.c |
283 |
--- sudo-1.8.6p3/plugins/sudoers/parse.c.cycledetect 2012-09-18 15:57:43.000000000 +0200 |
284 |
+++ sudo-1.8.6p3/plugins/sudoers/parse.c 2013-08-09 10:52:04.785860905 +0200 |
285 |
@@ -676,13 +676,14 @@ _print_member(struct lbuf *lbuf, char *n |
286 |
} |
287 |
break; |
288 |
case ALIAS: |
289 |
- if ((a = alias_find(name, alias_type)) != NULL) { |
290 |
+ if ((a = alias_get(name, alias_type)) != NULL) { |
291 |
tq_foreach_fwd(&a->members, m) { |
292 |
if (m != tq_first(&a->members)) |
293 |
lbuf_append(lbuf, ", "); |
294 |
_print_member(lbuf, m->name, m->type, |
295 |
negated ? !m->negated : m->negated, alias_type); |
296 |
} |
297 |
+ alias_put(a); |
298 |
break; |
299 |
} |
300 |
/* FALLTHROUGH */ |
301 |
@@ -697,6 +698,5 @@ static void |
302 |
print_member(struct lbuf *lbuf, char *name, int type, int negated, |
303 |
int alias_type) |
304 |
{ |
305 |
- alias_seqno++; |
306 |
_print_member(lbuf, name, type, negated, alias_type); |
307 |
} |
308 |
diff -up sudo-1.8.6p3/plugins/sudoers/parse.h.cycledetect sudo-1.8.6p3/plugins/sudoers/parse.h |
309 |
--- sudo-1.8.6p3/plugins/sudoers/parse.h.cycledetect 2012-09-18 15:56:29.000000000 +0200 |
310 |
+++ sudo-1.8.6p3/plugins/sudoers/parse.h 2013-08-09 10:54:30.984565529 +0200 |
311 |
@@ -148,7 +148,7 @@ struct runascontainer { |
312 |
struct alias { |
313 |
char *name; /* alias name */ |
314 |
unsigned short type; /* {USER,HOST,RUNAS,CMND}ALIAS */ |
315 |
- unsigned short seqno; /* sequence number */ |
316 |
+ bool used; /* "used" flag for cycle detection */ |
317 |
struct member_list members; /* list of alias members */ |
318 |
}; |
319 |
|
320 |
@@ -170,35 +170,39 @@ struct defaults { |
321 |
extern struct userspec_list userspecs; |
322 |
extern struct defaults_list defaults; |
323 |
|
324 |
-/* |
325 |
- * Alias sequence number to avoid loops. |
326 |
- */ |
327 |
-extern unsigned int alias_seqno; |
328 |
- |
329 |
-/* |
330 |
- * Prototypes |
331 |
- */ |
332 |
-char *alias_add(char *, int, struct member *); |
333 |
-bool addr_matches(char *); |
334 |
-int cmnd_matches(struct member *); |
335 |
-int cmndlist_matches(struct member_list *); |
336 |
-bool command_matches(char *, char *); |
337 |
-int hostlist_matches(struct member_list *); |
338 |
-bool hostname_matches(char *, char *, char *); |
339 |
-bool netgr_matches(char *, char *, char *, char *); |
340 |
+/* alias.c */ |
341 |
bool no_aliases(void); |
342 |
-int runaslist_matches(struct member_list *, struct member_list *, struct member **, struct member **); |
343 |
-int userlist_matches(struct passwd *, struct member_list *); |
344 |
-bool usergr_matches(char *, char *, struct passwd *); |
345 |
-bool userpw_matches(char *, char *, struct passwd *); |
346 |
-bool group_matches(char *, struct group *); |
347 |
-struct alias *alias_find(char *, int); |
348 |
-struct alias *alias_remove(char *, int); |
349 |
-void alias_free(void *); |
350 |
-void alias_apply(int (*)(void *, void *), void *); |
351 |
+char *alias_add(char *name, int type, struct member *members); |
352 |
+int alias_compare(const void *a1, const void *a2); |
353 |
+struct alias *alias_get(char *name, int type); |
354 |
+struct alias *alias_remove(char *name, int type); |
355 |
+void alias_apply(int (*func)(void *, void *), void *cookie); |
356 |
+void alias_free(void *a); |
357 |
+void alias_put(struct alias *a); |
358 |
void init_aliases(void); |
359 |
-void init_lexer(void); |
360 |
+/* gram.c */ |
361 |
void init_parser(const char *, bool); |
362 |
-int alias_compare(const void *, const void *); |
363 |
+ |
364 |
+/* match_addr.c */ |
365 |
+bool addr_matches(char *n); |
366 |
+ |
367 |
+/* match.c */ |
368 |
+bool command_matches(char *sudoers_cmnd, char *sudoers_args); |
369 |
+bool group_matches(char *sudoers_group, struct group *gr); |
370 |
+bool hostname_matches(char *shost, char *lhost, char *pattern); |
371 |
+bool netgr_matches(char *netgr, char *lhost, char *shost, char *user); |
372 |
+bool usergr_matches(char *group, char *user, struct passwd *pw); |
373 |
+bool userpw_matches(char *sudoers_user, char *user, struct passwd *pw); |
374 |
+int cmnd_matches(struct member *m); |
375 |
+int cmndlist_matches(struct member_list *list); |
376 |
+int hostlist_matches(struct member_list *list); |
377 |
+int runaslist_matches(struct member_list *user_list, struct member_list *group_list, struct member **matching_user, struct member **matching_group); |
378 |
+int userlist_matches(struct passwd *pw, struct member_list *list); |
379 |
+ |
380 |
+/* toke.c */ |
381 |
+ void init_lexer(void); |
382 |
+ |
383 |
+/* base64.c */ |
384 |
+ size_t base64_decode(const char *str, unsigned char *dst, size_t dsize); |
385 |
|
386 |
#endif /* _SUDO_PARSE_H */ |
387 |
diff -up sudo-1.8.6p3/plugins/sudoers/visudo.c.cycledetect sudo-1.8.6p3/plugins/sudoers/visudo.c |
388 |
--- sudo-1.8.6p3/plugins/sudoers/visudo.c.cycledetect 2013-08-09 10:52:04.759860779 +0200 |
389 |
+++ sudo-1.8.6p3/plugins/sudoers/visudo.c 2013-08-09 10:52:04.786860910 +0200 |
390 |
@@ -1084,7 +1084,6 @@ alias_remove_recursive(char *name, int t |
391 |
} |
392 |
rbinsert(alias_freelist, a); |
393 |
} |
394 |
- alias_seqno++; |
395 |
debug_return_bool(rval); |
396 |
} |
397 |
|
398 |
@@ -1096,12 +1095,13 @@ check_alias(char *name, int type, int st |
399 |
int errors = 0; |
400 |
debug_decl(check_alias, SUDO_DEBUG_ALIAS) |
401 |
|
402 |
- if ((a = alias_find(name, type)) != NULL) { |
403 |
+ if ((a = alias_get(name, type)) != NULL) { |
404 |
/* check alias contents */ |
405 |
tq_foreach_fwd(&a->members, m) { |
406 |
if (m->type == ALIAS) |
407 |
errors += check_alias(m->name, type, strict, quiet); |
408 |
} |
409 |
+ alias_put(a); |
410 |
} else { |
411 |
if (!quiet) { |
412 |
char *fmt; |
413 |
@@ -1146,26 +1146,22 @@ check_aliases(bool strict, bool quiet) |
414 |
tq_foreach_fwd(&userspecs, us) { |
415 |
tq_foreach_fwd(&us->users, m) { |
416 |
if (m->type == ALIAS) { |
417 |
- alias_seqno++; |
418 |
errors += check_alias(m->name, USERALIAS, strict, quiet); |
419 |
} |
420 |
} |
421 |
tq_foreach_fwd(&us->privileges, priv) { |
422 |
tq_foreach_fwd(&priv->hostlist, m) { |
423 |
if (m->type == ALIAS) { |
424 |
- alias_seqno++; |
425 |
errors += check_alias(m->name, HOSTALIAS, strict, quiet); |
426 |
} |
427 |
} |
428 |
tq_foreach_fwd(&priv->cmndlist, cs) { |
429 |
tq_foreach_fwd(&cs->runasuserlist, m) { |
430 |
if (m->type == ALIAS) { |
431 |
- alias_seqno++; |
432 |
errors += check_alias(m->name, RUNASALIAS, strict, quiet); |
433 |
} |
434 |
} |
435 |
if ((m = cs->cmnd)->type == ALIAS) { |
436 |
- alias_seqno++; |
437 |
errors += check_alias(m->name, CMNDALIAS, strict, quiet); |
438 |
} |
439 |
} |
440 |
@@ -1176,7 +1172,6 @@ check_aliases(bool strict, bool quiet) |
441 |
tq_foreach_fwd(&userspecs, us) { |
442 |
tq_foreach_fwd(&us->users, m) { |
443 |
if (m->type == ALIAS) { |
444 |
- alias_seqno++; |
445 |
if (!alias_remove_recursive(m->name, USERALIAS)) |
446 |
errors++; |
447 |
} |
448 |
@@ -1184,7 +1179,6 @@ check_aliases(bool strict, bool quiet) |
449 |
tq_foreach_fwd(&us->privileges, priv) { |
450 |
tq_foreach_fwd(&priv->hostlist, m) { |
451 |
if (m->type == ALIAS) { |
452 |
- alias_seqno++; |
453 |
if (!alias_remove_recursive(m->name, HOSTALIAS)) |
454 |
errors++; |
455 |
} |
456 |
@@ -1192,13 +1186,11 @@ check_aliases(bool strict, bool quiet) |
457 |
tq_foreach_fwd(&priv->cmndlist, cs) { |
458 |
tq_foreach_fwd(&cs->runasuserlist, m) { |
459 |
if (m->type == ALIAS) { |
460 |
- alias_seqno++; |
461 |
if (!alias_remove_recursive(m->name, RUNASALIAS)) |
462 |
errors++; |
463 |
} |
464 |
} |
465 |
if ((m = cs->cmnd)->type == ALIAS) { |
466 |
- alias_seqno++; |
467 |
if (!alias_remove_recursive(m->name, CMNDALIAS)) |
468 |
errors++; |
469 |
} |
470 |
@@ -1225,7 +1217,6 @@ check_aliases(bool strict, bool quiet) |
471 |
tq_foreach_fwd(&d->binding, binding) { |
472 |
for (m = binding; m != NULL; m = m->next) { |
473 |
if (m->type == ALIAS) { |
474 |
- alias_seqno++; |
475 |
if (!alias_remove_recursive(m->name, atype)) |
476 |
errors++; |
477 |
} |