Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2011 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include <talloc.h>
24 : #include <time.h>
25 :
26 : #include "db/sysdb.h"
27 : #include "db/sysdb_private.h"
28 : #include "db/sysdb_sudo.h"
29 :
30 : #define NULL_CHECK(val, rval, label) do { \
31 : if (!val) { \
32 : rval = ENOMEM; \
33 : goto label; \
34 : } \
35 : } while(0)
36 :
37 : /* ==================== Utility functions ==================== */
38 :
39 0 : static errno_t sysdb_sudo_convert_time(const char *str, time_t *unix_time)
40 : {
41 : struct tm tm;
42 0 : char *tret = NULL;
43 :
44 : /* SUDO requires times to be in generalized time format:
45 : * YYYYMMDDHHMMSS[.|,fraction][(+|-HHMM)|Z]
46 : *
47 : * We need to use more format strings to parse this with strptime().
48 : */
49 0 : const char **format = NULL;
50 0 : const char *formats[] = {"%Y%m%d%H%M%SZ", /* 201212121300Z */
51 : "%Y%m%d%H%M%S%z", /* 201212121300+-0200 */
52 : "%Y%m%d%H%M%S.0Z",
53 : "%Y%m%d%H%M%S.0%z",
54 : "%Y%m%d%H%M%S,0Z",
55 : "%Y%m%d%H%M%S,0%z",
56 : NULL};
57 :
58 0 : for (format = formats; *format != NULL; format++) {
59 : /* strptime() may leave some fields uninitialized */
60 0 : memset(&tm, 0, sizeof(struct tm));
61 0 : tret = strptime(str, *format, &tm);
62 0 : if (tret != NULL && *tret == '\0') {
63 0 : *unix_time = mktime(&tm);
64 0 : return EOK;
65 : }
66 : }
67 :
68 0 : return EINVAL;
69 : }
70 :
71 0 : static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule,
72 : time_t now,
73 : bool *result)
74 : {
75 0 : TALLOC_CTX *tmp_ctx = NULL;
76 0 : const char **values = NULL;
77 0 : const char *name = NULL;
78 0 : time_t notBefore = 0;
79 0 : time_t notAfter = 0;
80 : time_t converted;
81 : errno_t ret;
82 : int i;
83 :
84 0 : if (!result) return EINVAL;
85 0 : *result = false;
86 :
87 0 : tmp_ctx = talloc_new(NULL);
88 0 : NULL_CHECK(tmp_ctx, ret, done);
89 :
90 0 : ret = sysdb_attrs_get_string(rule, SYSDB_SUDO_CACHE_AT_CN, &name);
91 0 : if (ret == ENOENT) {
92 0 : name = "<missing>";
93 0 : } else if(ret != EOK) {
94 0 : goto done;
95 : }
96 :
97 : /*
98 : * From man sudoers.ldap:
99 : *
100 : * If multiple sudoNotBefore entries are present, the *earliest* is used.
101 : * If multiple sudoNotAfter entries are present, the *last one* is used.
102 : *
103 : * From sudo sources, ldap.c:
104 : * If either the sudoNotAfter or sudoNotBefore attributes are missing,
105 : * no time restriction shall be imposed.
106 : */
107 :
108 : /* check for sudoNotBefore */
109 0 : ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTBEFORE,
110 : tmp_ctx, &values);
111 0 : if (ret == EOK) {
112 0 : for (i=0; values[i] ; i++) {
113 0 : ret = sysdb_sudo_convert_time(values[i], &converted);
114 0 : if (ret != EOK) {
115 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Invalid time format in rule [%s]!\n",
116 : name);
117 0 : goto done;
118 : }
119 :
120 : /* Grab the earliest */
121 0 : if (!notBefore) {
122 0 : notBefore = converted;
123 0 : } else if (notBefore > converted) {
124 0 : notBefore = converted;
125 : }
126 : }
127 0 : } else if (ret != ENOENT) {
128 0 : goto done;
129 : }
130 :
131 : /* check for sudoNotAfter */
132 0 : ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTAFTER,
133 : tmp_ctx, &values);
134 0 : if (ret == EOK) {
135 0 : for (i=0; values[i] ; i++) {
136 0 : ret = sysdb_sudo_convert_time(values[i], &converted);
137 0 : if (ret != EOK) {
138 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Invalid time format in rule [%s]!\n",
139 : name);
140 0 : goto done;
141 : }
142 :
143 : /* Grab the latest */
144 0 : if (!notAfter) {
145 0 : notAfter = converted;
146 0 : } else if (notAfter < converted) {
147 0 : notAfter = converted;
148 : }
149 : }
150 0 : } else if (ret != ENOENT) {
151 0 : goto done;
152 : }
153 :
154 0 : if ((notBefore == 0 || now >= notBefore)
155 0 : && (notAfter == 0 || now <= notAfter)) {
156 0 : *result = true;
157 : }
158 :
159 0 : if (*result) {
160 0 : DEBUG(SSSDBG_TRACE_ALL, "Rule [%s] matches time restrictions\n",
161 : name);
162 : } else {
163 0 : DEBUG(SSSDBG_TRACE_ALL, "Rule [%s] does not match time "
164 : "restrictions\n", name);
165 : }
166 :
167 0 : ret = EOK;
168 : done:
169 0 : talloc_free(tmp_ctx);
170 0 : return ret;
171 : }
172 :
173 0 : errno_t sysdb_sudo_filter_rules_by_time(TALLOC_CTX *mem_ctx,
174 : uint32_t in_num_rules,
175 : struct sysdb_attrs **in_rules,
176 : time_t now,
177 : uint32_t *_num_rules,
178 : struct sysdb_attrs ***_rules)
179 : {
180 0 : uint32_t num_rules = 0;
181 0 : struct sysdb_attrs **rules = NULL;
182 0 : TALLOC_CTX *tmp_ctx = NULL;
183 0 : bool allowed = false;
184 : errno_t ret;
185 : int i;
186 :
187 0 : tmp_ctx = talloc_new(NULL);
188 0 : NULL_CHECK(tmp_ctx, ret, done);
189 :
190 0 : if (now == 0) {
191 0 : now = time(NULL);
192 : }
193 :
194 0 : for (i = 0; i < in_num_rules; i++) {
195 0 : ret = sysdb_sudo_check_time(in_rules[i], now, &allowed);
196 0 : if (ret == EOK && allowed) {
197 0 : num_rules++;
198 0 : rules = talloc_realloc(tmp_ctx, rules, struct sysdb_attrs *,
199 : num_rules);
200 0 : NULL_CHECK(rules, ret, done);
201 :
202 0 : rules[num_rules - 1] = in_rules[i];
203 : }
204 : }
205 :
206 0 : *_num_rules = num_rules;
207 0 : *_rules = talloc_steal(mem_ctx, rules);
208 :
209 0 : ret = EOK;
210 :
211 : done:
212 0 : talloc_free(tmp_ctx);
213 0 : return ret;
214 : }
215 :
216 : errno_t
217 0 : sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
218 : uid_t uid, char **groupnames, unsigned int flags,
219 : char **_filter)
220 : {
221 0 : TALLOC_CTX *tmp_ctx = NULL;
222 0 : char *filter = NULL;
223 0 : char *specific_filter = NULL;
224 0 : char *sanitized = NULL;
225 : time_t now;
226 : errno_t ret;
227 : int i;
228 :
229 0 : tmp_ctx = talloc_new(NULL);
230 0 : NULL_CHECK(tmp_ctx, ret, done);
231 :
232 : /* build specific filter */
233 :
234 0 : specific_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
235 0 : NULL_CHECK(specific_filter, ret, done);
236 :
237 0 : if (flags & SYSDB_SUDO_FILTER_INCLUDE_ALL) {
238 0 : specific_filter = talloc_asprintf_append(specific_filter, "(%s=ALL)",
239 : SYSDB_SUDO_CACHE_AT_USER);
240 0 : NULL_CHECK(specific_filter, ret, done);
241 : }
242 :
243 0 : if (flags & SYSDB_SUDO_FILTER_INCLUDE_DFL) {
244 0 : specific_filter = talloc_asprintf_append(specific_filter, "(%s=defaults)",
245 : SYSDB_NAME);
246 0 : NULL_CHECK(specific_filter, ret, done);
247 : }
248 :
249 0 : if ((flags & SYSDB_SUDO_FILTER_USERNAME) && (username != NULL)) {
250 0 : ret = sss_filter_sanitize(tmp_ctx, username, &sanitized);
251 0 : if (ret != EOK) {
252 0 : goto done;
253 : }
254 :
255 0 : specific_filter = talloc_asprintf_append(specific_filter, "(%s=%s)",
256 : SYSDB_SUDO_CACHE_AT_USER,
257 : sanitized);
258 0 : NULL_CHECK(specific_filter, ret, done);
259 : }
260 :
261 0 : if ((flags & SYSDB_SUDO_FILTER_UID) && (uid != 0)) {
262 0 : specific_filter = talloc_asprintf_append(specific_filter, "(%s=#%llu)",
263 : SYSDB_SUDO_CACHE_AT_USER,
264 : (unsigned long long) uid);
265 0 : NULL_CHECK(specific_filter, ret, done);
266 : }
267 :
268 0 : if ((flags & SYSDB_SUDO_FILTER_GROUPS) && (groupnames != NULL)) {
269 0 : for (i=0; groupnames[i] != NULL; i++) {
270 0 : ret = sss_filter_sanitize(tmp_ctx, groupnames[i], &sanitized);
271 0 : if (ret != EOK) {
272 0 : goto done;
273 : }
274 :
275 0 : specific_filter = talloc_asprintf_append(specific_filter, "(%s=%%%s)",
276 : SYSDB_SUDO_CACHE_AT_USER,
277 : sanitized);
278 0 : NULL_CHECK(specific_filter, ret, done);
279 : }
280 : }
281 :
282 0 : if (flags & SYSDB_SUDO_FILTER_NGRS) {
283 0 : specific_filter = talloc_asprintf_append(specific_filter, "(%s=+*)",
284 : SYSDB_SUDO_CACHE_AT_USER);
285 0 : NULL_CHECK(specific_filter, ret, done);
286 : }
287 :
288 : /* build global filter */
289 :
290 0 : filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)",
291 : SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
292 0 : NULL_CHECK(filter, ret, done);
293 :
294 0 : if (specific_filter[0] != '\0') {
295 0 : filter = talloc_asprintf_append(filter, "(|%s)", specific_filter);
296 0 : NULL_CHECK(filter, ret, done);
297 : }
298 :
299 0 : if (flags & SYSDB_SUDO_FILTER_ONLY_EXPIRED) {
300 0 : now = time(NULL);
301 0 : filter = talloc_asprintf_append(filter, "(&(%s<=%lld))",
302 : SYSDB_CACHE_EXPIRE, (long long)now);
303 0 : NULL_CHECK(filter, ret, done);
304 : }
305 :
306 0 : filter = talloc_strdup_append(filter, ")");
307 0 : NULL_CHECK(filter, ret, done);
308 :
309 0 : ret = EOK;
310 0 : *_filter = talloc_steal(mem_ctx, filter);
311 :
312 : done:
313 0 : talloc_free(tmp_ctx);
314 0 : return ret;
315 : }
316 :
317 : errno_t
318 0 : sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx,
319 : struct sss_domain_info *domain,
320 : const char *username, uid_t *_uid,
321 : char ***groupnames)
322 : {
323 : TALLOC_CTX *tmp_ctx;
324 : errno_t ret;
325 : struct ldb_message *msg;
326 0 : struct ldb_message *group_msg = NULL;
327 0 : char **sysdb_groupnames = NULL;
328 0 : const char *primary_group = NULL;
329 : struct ldb_message_element *groups;
330 0 : uid_t uid = 0;
331 0 : gid_t gid = 0;
332 0 : size_t num_groups = 0;
333 : int i;
334 0 : const char *attrs[] = { SYSDB_MEMBEROF,
335 : SYSDB_GIDNUM,
336 : SYSDB_UIDNUM,
337 : NULL };
338 0 : const char *group_attrs[] = { SYSDB_NAME,
339 : NULL };
340 :
341 0 : tmp_ctx = talloc_new(NULL);
342 0 : NULL_CHECK(tmp_ctx, ret, done);
343 :
344 0 : ret = sysdb_search_user_by_name(tmp_ctx, domain, username, attrs, &msg);
345 0 : if (ret != EOK) {
346 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up user %s\n", username);
347 0 : goto done;
348 : }
349 :
350 0 : if (_uid != NULL) {
351 0 : uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
352 0 : if (!uid) {
353 0 : DEBUG(SSSDBG_CRIT_FAILURE, "A user with no UID?\n");
354 0 : ret = EIO;
355 0 : goto done;
356 : }
357 : }
358 :
359 : /* resolve secondary groups */
360 0 : if (groupnames != NULL) {
361 0 : groups = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
362 0 : if (!groups || groups->num_values == 0) {
363 : /* No groups for this user in sysdb currently */
364 0 : sysdb_groupnames = NULL;
365 0 : num_groups = 0;
366 : } else {
367 0 : num_groups = groups->num_values;
368 0 : sysdb_groupnames = talloc_array(tmp_ctx, char *, num_groups + 1);
369 0 : NULL_CHECK(sysdb_groupnames, ret, done);
370 :
371 : /* Get a list of the groups by groupname only */
372 0 : for (i = 0; i < groups->num_values; i++) {
373 0 : ret = sysdb_group_dn_name(domain->sysdb,
374 : sysdb_groupnames,
375 0 : (const char *)groups->values[i].data,
376 0 : &sysdb_groupnames[i]);
377 0 : if (ret != EOK) {
378 0 : ret = ENOMEM;
379 0 : goto done;
380 : }
381 : }
382 0 : sysdb_groupnames[groups->num_values] = NULL;
383 : }
384 : }
385 :
386 : /* resolve primary group */
387 0 : gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
388 0 : if (gid != 0) {
389 0 : ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, group_attrs,
390 : &group_msg);
391 0 : if (ret == EOK) {
392 0 : primary_group = ldb_msg_find_attr_as_string(group_msg, SYSDB_NAME,
393 : NULL);
394 0 : if (primary_group == NULL) {
395 0 : ret = ENOMEM;
396 0 : goto done;
397 : }
398 :
399 0 : num_groups++;
400 0 : sysdb_groupnames = talloc_realloc(tmp_ctx, sysdb_groupnames,
401 : char *, num_groups + 1);
402 0 : NULL_CHECK(sysdb_groupnames, ret, done);
403 :
404 0 : sysdb_groupnames[num_groups - 1] = talloc_strdup(sysdb_groupnames,
405 : primary_group);
406 0 : NULL_CHECK(sysdb_groupnames[num_groups - 1], ret, done);
407 :
408 0 : sysdb_groupnames[num_groups] = NULL;
409 0 : } else if (ret != ENOENT) {
410 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up group [%d]: %s\n",
411 : ret, strerror(ret));
412 0 : goto done;
413 : }
414 : }
415 :
416 0 : ret = EOK;
417 :
418 0 : if (_uid != NULL) {
419 0 : *_uid = uid;
420 : }
421 :
422 0 : if (groupnames != NULL) {
423 0 : *groupnames = talloc_steal(mem_ctx, sysdb_groupnames);
424 : }
425 : done:
426 0 : talloc_free(tmp_ctx);
427 0 : return ret;
428 : }
429 :
430 : errno_t
431 0 : sysdb_save_sudorule(struct sss_domain_info *domain,
432 : const char *rule_name,
433 : struct sysdb_attrs *attrs)
434 : {
435 : errno_t ret;
436 :
437 0 : DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", rule_name);
438 :
439 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS,
440 : SYSDB_SUDO_CACHE_OC);
441 0 : if (ret != EOK) {
442 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set rule object class [%d]: %s\n",
443 : ret, strerror(ret));
444 0 : return ret;
445 : }
446 :
447 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, rule_name);
448 0 : if (ret != EOK) {
449 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set name attribute [%d]: %s\n",
450 : ret, strerror(ret));
451 0 : return ret;
452 : }
453 :
454 0 : ret = sysdb_store_custom(domain, rule_name,
455 : SUDORULE_SUBDIR, attrs);
456 0 : if (ret != EOK) {
457 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_custom failed [%d]: %s\n",
458 : ret, strerror(ret));
459 0 : return ret;
460 : }
461 :
462 0 : return EOK;
463 : }
464 :
465 0 : static errno_t sysdb_sudo_set_refresh_time(struct sss_domain_info *domain,
466 : const char *attr_name,
467 : time_t value)
468 : {
469 : TALLOC_CTX *tmp_ctx;
470 : struct ldb_dn *dn;
471 0 : struct ldb_message *msg = NULL;
472 0 : struct ldb_result *res = NULL;
473 : errno_t ret;
474 : int lret;
475 :
476 0 : tmp_ctx = talloc_new(NULL);
477 0 : if (!tmp_ctx) {
478 0 : ret = ENOMEM;
479 0 : goto done;
480 : }
481 :
482 0 : dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
483 : SYSDB_TMPL_CUSTOM_SUBTREE,
484 : SUDORULE_SUBDIR, domain->name);
485 0 : if (!dn) {
486 0 : ret = ENOMEM;
487 0 : goto done;
488 : }
489 :
490 0 : lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
491 : NULL, NULL);
492 0 : if (lret != LDB_SUCCESS) {
493 0 : ret = sysdb_error_to_errno(lret);
494 0 : goto done;
495 : }
496 :
497 0 : msg = ldb_msg_new(tmp_ctx);
498 0 : if (msg == NULL) {
499 0 : ret = ENOMEM;
500 0 : goto done;
501 : }
502 0 : msg->dn = dn;
503 :
504 0 : if (res->count == 0) {
505 0 : lret = ldb_msg_add_string(msg, "cn", SUDORULE_SUBDIR);
506 0 : if (lret != LDB_SUCCESS) {
507 0 : ret = sysdb_error_to_errno(lret);
508 0 : goto done;
509 : }
510 0 : } else if (res->count != 1) {
511 0 : DEBUG(SSSDBG_CRIT_FAILURE,
512 : "Got more than one reply for base search!\n");
513 0 : ret = EIO;
514 0 : goto done;
515 : } else {
516 0 : lret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
517 0 : if (lret != LDB_SUCCESS) {
518 0 : ret = sysdb_error_to_errno(lret);
519 0 : goto done;
520 : }
521 : }
522 :
523 0 : lret = ldb_msg_add_fmt(msg, attr_name, "%lld", (long long)value);
524 0 : if (lret != LDB_SUCCESS) {
525 0 : ret = sysdb_error_to_errno(lret);
526 0 : goto done;
527 : }
528 :
529 0 : if (res->count) {
530 0 : lret = ldb_modify(domain->sysdb->ldb, msg);
531 : } else {
532 0 : lret = ldb_add(domain->sysdb->ldb, msg);
533 : }
534 :
535 0 : if (lret != LDB_SUCCESS) {
536 0 : DEBUG(SSSDBG_MINOR_FAILURE,
537 : "ldb operation failed: [%s](%d)[%s]\n",
538 : ldb_strerror(lret), lret, ldb_errstring(domain->sysdb->ldb));
539 : }
540 0 : ret = sysdb_error_to_errno(lret);
541 :
542 : done:
543 0 : talloc_free(tmp_ctx);
544 0 : return ret;
545 : }
546 :
547 0 : static errno_t sysdb_sudo_get_refresh_time(struct sss_domain_info *domain,
548 : const char *attr_name,
549 : time_t *value)
550 : {
551 : TALLOC_CTX *tmp_ctx;
552 : struct ldb_dn *dn;
553 : struct ldb_result *res;
554 : errno_t ret;
555 : int lret;
556 0 : const char *attrs[2] = {attr_name, NULL};
557 :
558 0 : tmp_ctx = talloc_new(NULL);
559 0 : if (tmp_ctx == NULL) {
560 0 : return ENOMEM;
561 : }
562 :
563 0 : dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
564 : SUDORULE_SUBDIR, domain->name);
565 0 : if (!dn) {
566 0 : ret = ENOMEM;
567 0 : goto done;
568 : }
569 :
570 0 : lret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
571 : attrs, NULL);
572 0 : if (lret != LDB_SUCCESS) {
573 0 : ret = sysdb_error_to_errno(lret);
574 0 : goto done;
575 : }
576 :
577 0 : if (res->count == 0) {
578 : /* This entry has not been populated in LDB
579 : * This is a common case, as unlike LDAP,
580 : * LDB does not need to have all of its parent
581 : * objects actually exist.
582 : */
583 0 : *value = 0;
584 0 : ret = EOK;
585 0 : goto done;
586 0 : } else if (res->count != 1) {
587 0 : DEBUG(SSSDBG_CRIT_FAILURE,
588 : "Got more than one reply for base search!\n");
589 0 : ret = EIO;
590 0 : goto done;
591 : }
592 :
593 0 : *value = ldb_msg_find_attr_as_int(res->msgs[0], attr_name, 0);
594 :
595 0 : ret = EOK;
596 :
597 : done:
598 0 : talloc_free(tmp_ctx);
599 0 : return ret;
600 : }
601 :
602 0 : errno_t sysdb_sudo_set_last_full_refresh(struct sss_domain_info *domain,
603 : time_t value)
604 : {
605 0 : return sysdb_sudo_set_refresh_time(domain,
606 : SYSDB_SUDO_AT_LAST_FULL_REFRESH, value);
607 : }
608 :
609 0 : errno_t sysdb_sudo_get_last_full_refresh(struct sss_domain_info *domain,
610 : time_t *value)
611 : {
612 0 : return sysdb_sudo_get_refresh_time(domain,
613 : SYSDB_SUDO_AT_LAST_FULL_REFRESH, value);
614 : }
615 :
616 : /* ==================== Purge functions ==================== */
617 :
618 0 : static errno_t sysdb_sudo_purge_all(struct sss_domain_info *domain)
619 : {
620 0 : struct ldb_dn *base_dn = NULL;
621 0 : TALLOC_CTX *tmp_ctx = NULL;
622 : errno_t ret;
623 :
624 0 : tmp_ctx = talloc_new(NULL);
625 0 : NULL_CHECK(tmp_ctx, ret, done);
626 :
627 0 : base_dn = sysdb_custom_subtree_dn(tmp_ctx, domain, SUDORULE_SUBDIR);
628 0 : NULL_CHECK(base_dn, ret, done);
629 :
630 0 : ret = sysdb_delete_recursive(domain->sysdb, base_dn, true);
631 0 : if (ret != EOK) {
632 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
633 0 : goto done;
634 : }
635 :
636 0 : ret = EOK;
637 : done:
638 0 : talloc_free(tmp_ctx);
639 0 : return ret;
640 : }
641 :
642 0 : errno_t sysdb_sudo_purge_byname(struct sss_domain_info *domain,
643 : const char *name)
644 : {
645 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Deleting sudo rule %s\n", name);
646 0 : return sysdb_delete_custom(domain, name, SUDORULE_SUBDIR);
647 : }
648 :
649 0 : errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain,
650 : const char *filter)
651 : {
652 : TALLOC_CTX *tmp_ctx;
653 : size_t count;
654 : struct ldb_message **msgs;
655 : const char *name;
656 : int i;
657 : errno_t ret;
658 : errno_t sret;
659 0 : bool in_transaction = false;
660 0 : const char *attrs[] = { SYSDB_OBJECTCLASS,
661 : SYSDB_NAME,
662 : SYSDB_SUDO_CACHE_AT_CN,
663 : NULL };
664 :
665 : /* just purge all if there's no filter */
666 0 : if (!filter) {
667 0 : return sysdb_sudo_purge_all(domain);
668 : }
669 :
670 0 : tmp_ctx = talloc_new(NULL);
671 0 : NULL_CHECK(tmp_ctx, ret, done);
672 :
673 : /* match entries based on the filter and remove them one by one */
674 0 : ret = sysdb_search_custom(tmp_ctx, domain, filter,
675 : SUDORULE_SUBDIR, attrs,
676 : &count, &msgs);
677 0 : if (ret == ENOENT) {
678 0 : DEBUG(SSSDBG_TRACE_FUNC, "No rules matched\n");
679 0 : ret = EOK;
680 0 : goto done;
681 0 : } else if (ret != EOK) {
682 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
683 0 : goto done;
684 : }
685 :
686 0 : ret = sysdb_transaction_start(domain->sysdb);
687 0 : if (ret != EOK) {
688 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
689 0 : goto done;
690 : }
691 0 : in_transaction = true;
692 :
693 0 : for (i = 0; i < count; i++) {
694 0 : name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
695 0 : if (name == NULL) {
696 0 : DEBUG(SSSDBG_OP_FAILURE, "A rule without a name?\n");
697 : /* skip this one but still delete other entries */
698 0 : continue;
699 : }
700 :
701 0 : ret = sysdb_sudo_purge_byname(domain, name);
702 0 : if (ret != EOK) {
703 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not delete rule %s\n", name);
704 0 : goto done;
705 : }
706 : }
707 :
708 0 : ret = sysdb_transaction_commit(domain->sysdb);
709 0 : if (ret != EOK) {
710 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
711 0 : goto done;
712 : }
713 0 : in_transaction = false;
714 :
715 : done:
716 0 : if (in_transaction) {
717 0 : sret = sysdb_transaction_cancel(domain->sysdb);
718 0 : if (sret != EOK) {
719 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
720 : }
721 : }
722 :
723 0 : talloc_free(tmp_ctx);
724 0 : return ret;
725 : }
|