From: Todd C. Miller Date: Sat, 10 Feb 2018 01:21:01 +0000 (-0700) Subject: Convert ldap results into a sudoers userspec so we can use the "sudo X-Git-Tag: SUDO_1_8_23^2~146 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e2402a8e4a5401b8551742074e2cb3e14803fd2;p=sudo Convert ldap results into a sudoers userspec so we can use the "sudo -l" output functions in parse.c. --- diff --git a/plugins/sudoers/gram.c b/plugins/sudoers/gram.c index 48cb692be..bb7c3ae45 100644 --- a/plugins/sudoers/gram.c +++ b/plugins/sudoers/gram.c @@ -667,7 +667,7 @@ short *yysslim; YYSTYPE *yyvs; unsigned int yystacksize; int yyparse(void); -#line 898 "gram.y" +#line 899 "gram.y" void sudoerserror(const char *s) { @@ -866,12 +866,13 @@ free_members(struct member_list *members) void free_userspec(struct userspec *us) { - struct privilege *priv, *next; + struct privilege *priv; free_members(&us->users); - TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, next) { + while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; - struct cmndspec *cs, *cs_next; + struct cmndspec *cs; + struct defaults *def; #ifdef HAVE_SELINUX char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ @@ -879,8 +880,11 @@ free_userspec(struct userspec *us) char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ + TAILQ_REMOVE(&us->privileges, priv, entries); + free(priv->ldap_role); free_members(&priv->hostlist); - TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, cs_next) { + while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { + TAILQ_REMOVE(&priv->cmndlist, cs, entries); #ifdef HAVE_SELINUX /* Only free the first instance of a role/type. */ if (cs->role != role) { @@ -917,6 +921,12 @@ free_userspec(struct userspec *us) free_member(cs->cmnd); free(cs); } + while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { + TAILQ_REMOVE(&priv->defaults, def, entries); + free(def->var); + free(def->val); + free(def); + } free(priv); } rcstr_delref(us->file); @@ -1000,7 +1010,7 @@ init_options(struct command_options *opts) opts->limitprivs = NULL; #endif } -#line 951 "gram.c" +#line 961 "gram.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -1364,6 +1374,7 @@ case 26: sudoerserror(N_("unable to allocate memory")); YYERROR; } + TAILQ_INIT(&p->defaults); HLTQ_TO_TAILQ(&p->hostlist, yyvsp[-2].member, entries); HLTQ_TO_TAILQ(&p->cmndlist, yyvsp[0].cmndspec, entries); HLTQ_INIT(p, entries); @@ -1371,21 +1382,21 @@ case 26: } break; case 27: -#line 293 "gram.y" +#line 294 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 28: -#line 297 "gram.y" +#line 298 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 29: -#line 303 "gram.y" +#line 304 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); if (yyval.member == NULL) { @@ -1395,7 +1406,7 @@ case 29: } break; case 30: -#line 310 "gram.y" +#line 311 "gram.y" { yyval.member = new_member(NULL, ALL); if (yyval.member == NULL) { @@ -1405,7 +1416,7 @@ case 30: } break; case 31: -#line 317 "gram.y" +#line 318 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); if (yyval.member == NULL) { @@ -1415,7 +1426,7 @@ case 31: } break; case 32: -#line 324 "gram.y" +#line 325 "gram.y" { yyval.member = new_member(yyvsp[0].string, NTWKADDR); if (yyval.member == NULL) { @@ -1425,7 +1436,7 @@ case 32: } break; case 33: -#line 331 "gram.y" +#line 332 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); if (yyval.member == NULL) { @@ -1435,7 +1446,7 @@ case 33: } break; case 35: -#line 341 "gram.y" +#line 342 "gram.y" { struct cmndspec *prev; prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries); @@ -1489,7 +1500,7 @@ case 35: } break; case 36: -#line 394 "gram.y" +#line 395 "gram.y" { struct cmndspec *cs = calloc(1, sizeof(*cs)); if (cs == NULL) { @@ -1541,7 +1552,7 @@ case 36: } break; case 37: -#line 445 "gram.y" +#line 446 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string); if (yyval.digest == NULL) { @@ -1551,7 +1562,7 @@ case 37: } break; case 38: -#line 452 "gram.y" +#line 453 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string); if (yyval.digest == NULL) { @@ -1561,7 +1572,7 @@ case 38: } break; case 39: -#line 459 "gram.y" +#line 460 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string); if (yyval.digest == NULL) { @@ -1571,7 +1582,7 @@ case 39: } break; case 40: -#line 466 "gram.y" +#line 467 "gram.y" { yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string); if (yyval.digest == NULL) { @@ -1581,13 +1592,13 @@ case 40: } break; case 41: -#line 475 "gram.y" +#line 476 "gram.y" { yyval.member = yyvsp[0].member; } break; case 42: -#line 478 "gram.y" +#line 479 "gram.y" { if (yyvsp[0].member->type != COMMAND) { sudoerserror(N_("a digest requires a path name")); @@ -1599,75 +1610,75 @@ case 42: } break; case 43: -#line 489 "gram.y" +#line 490 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 44: -#line 493 "gram.y" +#line 494 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 45: -#line 499 "gram.y" +#line 500 "gram.y" { yyval.string = yyvsp[0].string; } break; case 46: -#line 504 "gram.y" +#line 505 "gram.y" { yyval.string = yyvsp[0].string; } break; case 47: -#line 508 "gram.y" +#line 509 "gram.y" { yyval.string = yyvsp[0].string; } break; case 48: -#line 513 "gram.y" +#line 514 "gram.y" { yyval.string = yyvsp[0].string; } break; case 49: -#line 518 "gram.y" +#line 519 "gram.y" { yyval.string = yyvsp[0].string; } break; case 50: -#line 523 "gram.y" +#line 524 "gram.y" { yyval.string = yyvsp[0].string; } break; case 51: -#line 527 "gram.y" +#line 528 "gram.y" { yyval.string = yyvsp[0].string; } break; case 52: -#line 532 "gram.y" +#line 533 "gram.y" { yyval.runas = NULL; } break; case 53: -#line 535 "gram.y" +#line 536 "gram.y" { yyval.runas = yyvsp[-1].runas; } break; case 54: -#line 540 "gram.y" +#line 541 "gram.y" { yyval.runas = calloc(1, sizeof(struct runascontainer)); if (yyval.runas != NULL) { @@ -1685,7 +1696,7 @@ case 54: } break; case 55: -#line 555 "gram.y" +#line 556 "gram.y" { yyval.runas = calloc(1, sizeof(struct runascontainer)); if (yyval.runas == NULL) { @@ -1697,7 +1708,7 @@ case 55: } break; case 56: -#line 564 "gram.y" +#line 565 "gram.y" { yyval.runas = calloc(1, sizeof(struct runascontainer)); if (yyval.runas == NULL) { @@ -1709,7 +1720,7 @@ case 56: } break; case 57: -#line 573 "gram.y" +#line 574 "gram.y" { yyval.runas = calloc(1, sizeof(struct runascontainer)); if (yyval.runas == NULL) { @@ -1721,7 +1732,7 @@ case 57: } break; case 58: -#line 582 "gram.y" +#line 583 "gram.y" { yyval.runas = calloc(1, sizeof(struct runascontainer)); if (yyval.runas != NULL) { @@ -1739,13 +1750,13 @@ case 58: } break; case 59: -#line 599 "gram.y" +#line 600 "gram.y" { init_options(&yyval.options); } break; case 60: -#line 602 "gram.y" +#line 603 "gram.y" { yyval.options.notbefore = parse_gentime(yyvsp[0].string); free(yyvsp[0].string); @@ -1756,7 +1767,7 @@ case 60: } break; case 61: -#line 610 "gram.y" +#line 611 "gram.y" { yyval.options.notafter = parse_gentime(yyvsp[0].string); free(yyvsp[0].string); @@ -1767,7 +1778,7 @@ case 61: } break; case 62: -#line 618 "gram.y" +#line 619 "gram.y" { yyval.options.timeout = parse_timeout(yyvsp[0].string); free(yyvsp[0].string); @@ -1781,7 +1792,7 @@ case 62: } break; case 63: -#line 629 "gram.y" +#line 630 "gram.y" { #ifdef HAVE_SELINUX free(yyval.options.role); @@ -1790,7 +1801,7 @@ case 63: } break; case 64: -#line 635 "gram.y" +#line 636 "gram.y" { #ifdef HAVE_SELINUX free(yyval.options.type); @@ -1799,7 +1810,7 @@ case 64: } break; case 65: -#line 641 "gram.y" +#line 642 "gram.y" { #ifdef HAVE_PRIV_SET free(yyval.options.privs); @@ -1808,7 +1819,7 @@ case 65: } break; case 66: -#line 647 "gram.y" +#line 648 "gram.y" { #ifdef HAVE_PRIV_SET free(yyval.options.limitprivs); @@ -1817,97 +1828,97 @@ case 66: } break; case 67: -#line 655 "gram.y" +#line 656 "gram.y" { TAGS_INIT(yyval.tag); } break; case 68: -#line 658 "gram.y" +#line 659 "gram.y" { yyval.tag.nopasswd = true; } break; case 69: -#line 661 "gram.y" +#line 662 "gram.y" { yyval.tag.nopasswd = false; } break; case 70: -#line 664 "gram.y" +#line 665 "gram.y" { yyval.tag.noexec = true; } break; case 71: -#line 667 "gram.y" +#line 668 "gram.y" { yyval.tag.noexec = false; } break; case 72: -#line 670 "gram.y" +#line 671 "gram.y" { yyval.tag.setenv = true; } break; case 73: -#line 673 "gram.y" +#line 674 "gram.y" { yyval.tag.setenv = false; } break; case 74: -#line 676 "gram.y" +#line 677 "gram.y" { yyval.tag.log_input = true; } break; case 75: -#line 679 "gram.y" +#line 680 "gram.y" { yyval.tag.log_input = false; } break; case 76: -#line 682 "gram.y" +#line 683 "gram.y" { yyval.tag.log_output = true; } break; case 77: -#line 685 "gram.y" +#line 686 "gram.y" { yyval.tag.log_output = false; } break; case 78: -#line 688 "gram.y" +#line 689 "gram.y" { yyval.tag.follow = true; } break; case 79: -#line 691 "gram.y" +#line 692 "gram.y" { yyval.tag.follow = false; } break; case 80: -#line 694 "gram.y" +#line 695 "gram.y" { yyval.tag.send_mail = true; } break; case 81: -#line 697 "gram.y" +#line 698 "gram.y" { yyval.tag.send_mail = false; } break; case 82: -#line 702 "gram.y" +#line 703 "gram.y" { yyval.member = new_member(NULL, ALL); if (yyval.member == NULL) { @@ -1917,7 +1928,7 @@ case 82: } break; case 83: -#line 709 "gram.y" +#line 710 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); if (yyval.member == NULL) { @@ -1927,7 +1938,7 @@ case 83: } break; case 84: -#line 716 "gram.y" +#line 717 "gram.y" { struct sudo_command *c = calloc(1, sizeof(*c)); if (c == NULL) { @@ -1945,7 +1956,7 @@ case 84: } break; case 87: -#line 737 "gram.y" +#line 738 "gram.y" { const char *s; s = alias_add(yyvsp[-2].string, HOSTALIAS, sudoers, this_lineno, yyvsp[0].member); @@ -1956,14 +1967,14 @@ case 87: } break; case 89: -#line 748 "gram.y" +#line 749 "gram.y" { HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 92: -#line 758 "gram.y" +#line 759 "gram.y" { const char *s; s = alias_add(yyvsp[-2].string, CMNDALIAS, sudoers, this_lineno, yyvsp[0].member); @@ -1974,14 +1985,14 @@ case 92: } break; case 94: -#line 769 "gram.y" +#line 770 "gram.y" { HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 97: -#line 779 "gram.y" +#line 780 "gram.y" { const char *s; s = alias_add(yyvsp[-2].string, RUNASALIAS, sudoers, this_lineno, yyvsp[0].member); @@ -1992,7 +2003,7 @@ case 97: } break; case 100: -#line 793 "gram.y" +#line 794 "gram.y" { const char *s; s = alias_add(yyvsp[-2].string, USERALIAS, sudoers, this_lineno, yyvsp[0].member); @@ -2003,28 +2014,28 @@ case 100: } break; case 102: -#line 804 "gram.y" +#line 805 "gram.y" { HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 103: -#line 810 "gram.y" +#line 811 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 104: -#line 814 "gram.y" +#line 815 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 105: -#line 820 "gram.y" +#line 821 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); if (yyval.member == NULL) { @@ -2034,7 +2045,7 @@ case 105: } break; case 106: -#line 827 "gram.y" +#line 828 "gram.y" { yyval.member = new_member(NULL, ALL); if (yyval.member == NULL) { @@ -2044,7 +2055,7 @@ case 106: } break; case 107: -#line 834 "gram.y" +#line 835 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); if (yyval.member == NULL) { @@ -2054,7 +2065,7 @@ case 107: } break; case 108: -#line 841 "gram.y" +#line 842 "gram.y" { yyval.member = new_member(yyvsp[0].string, USERGROUP); if (yyval.member == NULL) { @@ -2064,7 +2075,7 @@ case 108: } break; case 109: -#line 848 "gram.y" +#line 849 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); if (yyval.member == NULL) { @@ -2074,28 +2085,28 @@ case 109: } break; case 111: -#line 858 "gram.y" +#line 859 "gram.y" { HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries); yyval.member = yyvsp[-2].member; } break; case 112: -#line 864 "gram.y" +#line 865 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = false; } break; case 113: -#line 868 "gram.y" +#line 869 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = true; } break; case 114: -#line 874 "gram.y" +#line 875 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); if (yyval.member == NULL) { @@ -2105,7 +2116,7 @@ case 114: } break; case 115: -#line 881 "gram.y" +#line 882 "gram.y" { yyval.member = new_member(NULL, ALL); if (yyval.member == NULL) { @@ -2115,7 +2126,7 @@ case 115: } break; case 116: -#line 888 "gram.y" +#line 889 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); if (yyval.member == NULL) { @@ -2124,7 +2135,7 @@ case 116: } } break; -#line 2075 "gram.c" +#line 2086 "gram.c" } yyssp -= yym; yystate = *yyssp; diff --git a/plugins/sudoers/gram.y b/plugins/sudoers/gram.y index ed20fac00..a85c3027b 100644 --- a/plugins/sudoers/gram.y +++ b/plugins/sudoers/gram.y @@ -283,6 +283,7 @@ privilege : hostlist '=' cmndspeclist { sudoerserror(N_("unable to allocate memory")); YYERROR; } + TAILQ_INIT(&p->defaults); HLTQ_TO_TAILQ(&p->hostlist, $1, entries); HLTQ_TO_TAILQ(&p->cmndlist, $3, entries); HLTQ_INIT(p, entries); @@ -1093,12 +1094,13 @@ free_members(struct member_list *members) void free_userspec(struct userspec *us) { - struct privilege *priv, *next; + struct privilege *priv; free_members(&us->users); - TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, next) { + while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) { struct member_list *runasuserlist = NULL, *runasgrouplist = NULL; - struct cmndspec *cs, *cs_next; + struct cmndspec *cs; + struct defaults *def; #ifdef HAVE_SELINUX char *role = NULL, *type = NULL; #endif /* HAVE_SELINUX */ @@ -1106,8 +1108,11 @@ free_userspec(struct userspec *us) char *privs = NULL, *limitprivs = NULL; #endif /* HAVE_PRIV_SET */ + TAILQ_REMOVE(&us->privileges, priv, entries); + free(priv->ldap_role); free_members(&priv->hostlist); - TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, cs_next) { + while ((cs = TAILQ_FIRST(&priv->cmndlist)) != NULL) { + TAILQ_REMOVE(&priv->cmndlist, cs, entries); #ifdef HAVE_SELINUX /* Only free the first instance of a role/type. */ if (cs->role != role) { @@ -1144,6 +1149,12 @@ free_userspec(struct userspec *us) free_member(cs->cmnd); free(cs); } + while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) { + TAILQ_REMOVE(&priv->defaults, def, entries); + free(def->var); + free(def->val); + free(def); + } free(priv); } rcstr_delref(us->file); diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index e1b58bbe2..65e3eb46f 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -59,6 +59,7 @@ #include "sudoers.h" #include "parse.h" +#include "gram.h" #include "sudo_lbuf.h" #include "sudo_dso.h" @@ -2370,13 +2371,10 @@ sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry) } static void -sudo_ldap_print_quoted3(struct sudo_lbuf *lbuf, const char *prefix, const char *str, const char *suffix) +sudo_ldap_print_quoted(struct sudo_lbuf *lbuf, const char *str) { const char *name = str; - - /* Prefix is not quoted. */ - if (prefix != NULL) - sudo_lbuf_append(lbuf, "%s", prefix); + debug_decl(sudo_ldap_print_quoted, SUDOERS_DEBUG_LDAP) /* Do not quote UID/GID, all others get quoted. */ while (*name == '!') @@ -2392,21 +2390,7 @@ sudo_ldap_print_quoted3(struct sudo_lbuf *lbuf, const char *prefix, const char * sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", str); } - /* Suffix is not quoted. */ - if (suffix != NULL) - sudo_lbuf_append(lbuf, "%s", suffix); -} - -static void -sudo_ldap_print_quoted2(struct sudo_lbuf *lbuf, const char *prefix, const char *str) -{ - return sudo_ldap_print_quoted3(lbuf, prefix, str, NULL); -} - -static void -sudo_ldap_print_quoted(struct sudo_lbuf *lbuf, const char *str) -{ - return sudo_ldap_print_quoted3(lbuf, NULL, str, NULL); + debug_return; } /* @@ -2484,237 +2468,311 @@ sudo_ldap_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw, } /* - * Print a record in the short form, ala file sudoers. + * Convert an array of struct berval to a member list. */ -static int -sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *entry, struct passwd *pw, - struct sudo_lbuf *lbuf) +static struct member_list * +bv_to_member_list(struct berval **bv) { - struct berval **bv, **p; - bool no_runas_user = true; - int count = 0; - debug_decl(sudo_ldap_display_entry_short, SUDOERS_DEBUG_LDAP) - - sudo_lbuf_append(lbuf, " ("); + struct member_list *members; + struct berval **p; + struct member *m; + debug_decl(bv_to_member_list, SUDOERS_DEBUG_LDAP) - /* get the RunAsUser Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); - if (bv == NULL) - bv = ldap_get_values_len(ld, entry, "sudoRunAs"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - sudo_ldap_print_quoted2(lbuf, p != bv ? ", " : "", - (*p)->bv_val[0] ? (*p)->bv_val : user_name); - } - ldap_value_free_len(bv); - no_runas_user = false; - } + if ((members = calloc(1, sizeof(*members))) == NULL) + return NULL; + TAILQ_INIT(members); - /* get the RunAsGroup Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); - if (bv != NULL) { - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_ldap_print_quoted(lbuf, pw->pw_name); - } - sudo_lbuf_append(lbuf, " : "); - for (p = bv; *p != NULL; p++) { - sudo_ldap_print_quoted2(lbuf, p != bv ? ", " : "", (*p)->bv_val); - } - ldap_value_free_len(bv); - } else { - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_ldap_print_quoted(lbuf, def_runas_default); - } - } - sudo_lbuf_append(lbuf, ") "); + for (p = bv; *p != NULL; p++) { + if ((m = calloc(1, sizeof(*m))) == NULL) + goto bad; - /* Get the sudoNotBefore and sudoNotAfter Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoNotBefore"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - sudo_ldap_print_quoted3(lbuf, "NOTBEFORE=", (*p)->bv_val, " "); + char *val = (*p)->bv_val; + switch (val[0]) { + case '\0': + /* Empty RunAsUser means run as the invoking user. */ + m->type = MYSELF; + break; + case 'A': + if (strcmp(val, "ALL") == 0) { + m->type = ALL; + break; + } + /* FALLTHROUGH */ + default: + m->type = WORD; + m->name = strdup(val); + if (m->name == NULL) { + free(m); + goto bad; + } + break; } - ldap_value_free_len(bv); + TAILQ_INSERT_TAIL(members, m, entries); } - bv = ldap_get_values_len(ld, entry, "sudoNotAfter"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - sudo_ldap_print_quoted3(lbuf, "NOTAFTER=", (*p)->bv_val, " "); - } - ldap_value_free_len(bv); + debug_return_ptr(members); +bad: + while ((m = TAILQ_FIRST(members)) != NULL) { + TAILQ_REMOVE(members, m, entries); + free(m->name); + free(m); } + free(members); + debug_return_ptr(NULL); +} - /* get the Option Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoOption"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - char *val = (*p)->bv_val; - bool negated = sudo_ldap_is_negated(&val); - if (strcmp(val, "authenticate") == 0) - sudo_lbuf_append(lbuf, negated ? "NOPASSWD: " : "PASSWD: "); - else if (strcmp(val, "sudoedit_follow") == 0) - sudo_lbuf_append(lbuf, negated ? "NOFOLLOW: " : "FOLLOW: "); - else if (strcmp(val, "noexec") == 0) - sudo_lbuf_append(lbuf, negated ? "EXEC: " : "NOEXEC: "); - else if (strcmp(val, "setenv") == 0) - sudo_lbuf_append(lbuf, negated ? "NOSETENV: " : "SETENV: "); - else if (strcmp(val, "mail_all_cmnds") == 0 || strcmp(val, "mail_always") == 0) - sudo_lbuf_append(lbuf, negated ? "NOMAIL: " : "MAIL: "); - else if (!negated && strncmp(val, "command_timeout=", 16) == 0) - sudo_ldap_print_quoted3(lbuf, "TIMEOUT=", val + 16, " "); -#ifdef HAVE_SELINUX - else if (!negated && strncmp(val, "role=", 5) == 0) - sudo_ldap_print_quoted3(lbuf, "ROLE=", val + 5, " "); - else if (!negated && strncmp(val, "type=", 5) == 0) - sudo_ldap_print_quoted3(lbuf, "TYPE=", val + 5, " "); -#endif /* HAVE_SELINUX */ -#ifdef HAVE_PRIV_SET - else if (!negated && strncmp(val, "privs=", 6) == 0) - sudo_ldap_print_quoted3(lbuf, "PRIVS=", val + 6, " "); - else if (!negated && strncmp(val, "limitprivs=", 11) == 0) - sudo_ldap_print_quoted3(lbuf, "LIMITPRIVS=", val + 11, " "); -#endif /* HAVE_PRIV_SET */ - } - ldap_value_free_len(bv); - } +static struct userspec_list * +ldap2sudoers(LDAP *ld, struct ldap_result *lres) +{ + struct userspec_list *ldap_userspecs; + struct cmndspec *cmndspec = NULL; + struct sudo_command *c; + struct privilege *priv; + struct userspec *us; + struct member *m; + struct berval **bv, **p; + struct berval **cmnd_bv, **cmnd; /* XXX - naming */ + char *cn; + unsigned int i; + debug_decl(ldap2sudoers, SUDOERS_DEBUG_LDAP) - /* get the Command Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoCommand"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - char *args = strpbrk((*p)->bv_val, " \t"); - if (args != NULL) + if ((ldap_userspecs = calloc(1, sizeof(*ldap_userspecs))) == NULL) + goto oom; + TAILQ_INIT(ldap_userspecs); + + /* We only have a single userspec */ + if ((us = calloc(1, sizeof(*us))) == NULL) + goto oom; + TAILQ_INIT(&us->users); + TAILQ_INIT(&us->privileges); + TAILQ_INSERT_TAIL(ldap_userspecs, us, entries); + + /* The user has already matched, use ALL as wildcard. */ + if ((m = calloc(1, sizeof(*m))) == NULL) + goto oom; + m->type = ALL; + TAILQ_INSERT_TAIL(&us->users, m, entries); + + /* Treat each sudoRole as a separate privilege. */ + for (i = 0; i < lres->nentries; i++) { + struct cmndspec *prev_cmndspec = NULL; + LDAPMessage *entry = lres->entries[i].entry; + + /* Ignore sudoRole without sudoCommand. */ + cmnd_bv = ldap_get_values_len(ld, entry, "sudoCommand"); + if (cmnd_bv == NULL) + continue; + + if ((priv = calloc(1, sizeof(*priv))) == NULL) + goto oom; + TAILQ_INIT(&priv->hostlist); + TAILQ_INIT(&priv->cmndlist); + TAILQ_INIT(&priv->defaults); + TAILQ_INSERT_TAIL(&us->privileges, priv, entries); + + /* Get the entry's dn for long format printing. */ + cn = sudo_ldap_get_first_rdn(ld, entry); + priv->ldap_role = strdup(cn ? cn : "UNKNOWN"); + if (cn != NULL) + ldap_memfree(cn); + if (priv->ldap_role == NULL) + goto oom; + + /* The host has already matched, use ALL as wildcard. */ + if ((m = calloc(1, sizeof(*m))) == NULL) + goto oom; + m->type = ALL; + TAILQ_INSERT_TAIL(&priv->hostlist, m, entries); + + /* Parse sudoCommands and add to cmndlist. */ + for (cmnd = cmnd_bv; *cmnd != NULL; cmnd++) { + char *args; + + /* Allocate storage upfront. */ + cmndspec = calloc(1, sizeof(*cmndspec)); + c = calloc(1, sizeof(*c)); + m = calloc(1, sizeof(*m)); + if (cmndspec == NULL || c == NULL || m == NULL) { + free(c); + free(m); + goto oom; + } + TAILQ_INSERT_TAIL(&priv->cmndlist, cmndspec, entries); + + /* Initialize cmndspec */ + TAGS_INIT(cmndspec->tags); + cmndspec->notbefore = UNSPEC; + cmndspec->notafter = UNSPEC; + cmndspec->timeout = UNSPEC; + + /* Fill in command. */ + if ((args = strpbrk((*cmnd)->bv_val, " \t")) != NULL) { *args++ = '\0'; - if (p != bv) - sudo_lbuf_append(lbuf, ", "); - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED" \t", "%s", - (*p)->bv_val); - if (args != NULL) { - sudo_lbuf_append(lbuf, " "); - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", args); + if ((c->args = strdup(args)) == NULL) { + free(c); + free(m); + goto oom; + } } - count++; - } - ldap_value_free_len(bv); - } - sudo_lbuf_append(lbuf, "\n"); + if ((c->cmnd = strdup((*cmnd)->bv_val)) == NULL) { + free(c->args); + free(c); + free(m); + goto oom; + } + m->type = COMMAND; + m->name = (char *)c; + cmndspec->cmnd = m; + + if (prev_cmndspec != NULL) { + /* Inherit values from prior cmndspec */ + cmndspec->runasuserlist = prev_cmndspec->runasuserlist; + cmndspec->runasgrouplist = prev_cmndspec->runasgrouplist; + cmndspec->notbefore = prev_cmndspec->notbefore; + cmndspec->notafter = prev_cmndspec->notafter; + cmndspec->tags = prev_cmndspec->tags; + } else { + /* Parse sudoRunAsUser / sudoRunAs */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); + if (bv == NULL) + bv = ldap_get_values_len(ld, entry, "sudoRunAs"); /* old style */ + if (bv != NULL) { + cmndspec->runasuserlist = bv_to_member_list(bv); + if (cmndspec->runasuserlist == NULL) + goto oom; + ldap_value_free_len(bv); + bv = NULL; + } - debug_return_int(count); -} + /* Parse sudoRunAsGroup */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); + if (bv != NULL) { + cmndspec->runasgrouplist = bv_to_member_list(bv); + if (cmndspec->runasgrouplist == NULL) + goto oom; + ldap_value_free_len(bv); + bv = NULL; + } -/* - * Print a record in the long form. - */ -static int -sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *entry, struct passwd *pw, - struct sudo_lbuf *lbuf) -{ - struct berval **bv, **p; - bool no_runas_user = true; - char *rdn; - int count = 0; - debug_decl(sudo_ldap_display_entry_long, SUDOERS_DEBUG_LDAP) - - /* extract the dn, only show the first rdn */ - rdn = sudo_ldap_get_first_rdn(ld, entry); - if (rdn != NULL) - sudo_lbuf_append(lbuf, _("\nLDAP Role: %s\n"), rdn); - else - sudo_lbuf_append(lbuf, _("\nLDAP Role: UNKNOWN\n")); - if (rdn) - ldap_memfree(rdn); - - /* get the RunAsUser Values from the entry */ - sudo_lbuf_append(lbuf, " RunAsUsers: "); - bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); - if (bv == NULL) - bv = ldap_get_values_len(ld, entry, "sudoRunAs"); - if (bv != NULL) { - for (p = bv; *p != NULL; p++) { - sudo_lbuf_append(lbuf, "%s%s", p != bv ? ", " : "", (*p)->bv_val); - } - ldap_value_free_len(bv); - no_runas_user = false; - } + /* Parse sudoNotBefore */ + bv = ldap_get_values_len(ld, entry, "sudoNotBefore"); + if (bv != NULL) { + /* Only takes the last entry. */ + for (p = bv; *p != NULL; p++) { + cmndspec->notbefore = parse_gentime((*p)->bv_val); + } + ldap_value_free_len(bv); + bv = NULL; + } - /* get the RunAsGroup Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); - if (bv != NULL) { - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_lbuf_append(lbuf, "%s", pw->pw_name); - } - sudo_lbuf_append(lbuf, "\n RunAsGroups: "); - for (p = bv; *p != NULL; p++) { - sudo_lbuf_append(lbuf, "%s%s", p != bv ? ", " : "", (*p)->bv_val); - } - ldap_value_free_len(bv); - sudo_lbuf_append(lbuf, "\n"); - } else { - if (no_runas_user) { - /* finish printing sudoRunAs */ - sudo_lbuf_append(lbuf, "%s", def_runas_default); - } - sudo_lbuf_append(lbuf, "\n"); - } + /* Parse sudoNotAfter */ + bv = ldap_get_values_len(ld, entry, "sudoNotAfter"); + if (bv != NULL) { + /* Only takes the last entry. */ + for (p = bv; *p != NULL; p++) { + cmndspec->notafter = parse_gentime((*p)->bv_val); + } + ldap_value_free_len(bv); + bv = NULL; + } - /* Get the sudoNotBefore and sudoNotAfter Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoNotBefore"); - if (bv != NULL) { - sudo_lbuf_append(lbuf, " NotBefore: "); - for (p = bv; *p != NULL; p++) { - sudo_lbuf_append(lbuf, "%s%s", p != bv ? ", " : "", (*p)->bv_val); - } - ldap_value_free_len(bv); - sudo_lbuf_append(lbuf, "\n"); - } - bv = ldap_get_values_len(ld, entry, "sudoNotAfter"); - if (bv != NULL) { - sudo_lbuf_append(lbuf, " NotAfter: "); - for (p = bv; *p != NULL; p++) { - sudo_lbuf_append(lbuf, "%s%s", p != bv ? ", " : "", (*p)->bv_val); - } - ldap_value_free_len(bv); - sudo_lbuf_append(lbuf, "\n"); - } + /* Parse sudoOptions. */ + bv = ldap_get_values_len(ld, entry, "sudoOption"); + if (bv != NULL) { + for (p = bv; *p != NULL; p++) { + char *var, *val; + int op; + + op = sudo_ldap_parse_option((*p)->bv_val, &var, &val); + if (strcmp(var, "command_timeout") == 0) { + if (op == '=') + cmndspec->timeout = parse_timeout(val); +#ifdef HAVE_SELINUX + } else if (strcmp(var, "role") == 0) { + if (op == '=') { + if ((cmndspec->role = strdup(val)) == NULL) + goto oom; + } + } else if (strcmp(var, "type") == 0) { + if (op == '=') { + if ((cmndspec->type = strdup(val)) == NULL) + goto oom; + } +#endif /* HAVE_SELINUX */ +#ifdef HAVE_PRIV_SET + } else if (strcmp(var, "privs") == 0) { + if (op == '=') { + if ((cmndspec->privs = strdup(val)) == NULL) + goto oom; + } + } else if (strcmp(val, "limitprivs") == 0) { + if (op == '=') { + if ((cmndspec->limitprivs = strdup(val)) == NULL) + goto oom; + } +#endif /* HAVE_PRIV_SET */ + } else if (long_list) { + struct defaults *def = calloc(1, sizeof(*def)); + if (def == NULL) + goto oom; + def->op = op; + if ((def->var = strdup(var)) == NULL) { + free(def); + goto oom; + } + if (val != NULL) { + if ((def->val = strdup(val)) == NULL) { + free(def->var); + free(def); + goto oom; + } + } + TAILQ_INSERT_TAIL(&priv->defaults, def, entries); + } else { + /* Convert to tags. */ + if (op != true && op != false) + continue; + if (strcmp(var, "authenticate") == 0) { + cmndspec->tags.nopasswd = op == false; + } else if (strcmp(var, "sudoedit_follow") == 0) { + cmndspec->tags.follow = op == true; + } else if (strcmp(var, "noexec") == 0) { + cmndspec->tags.noexec = op == true; + } else if (strcmp(var, "setenv") == 0) { + cmndspec->tags.setenv = op == true; + } else if (strcmp(var, "mail_all_cmnds") == 0 || + strcmp(var, "mail_always") == 0) { + cmndspec->tags.send_mail = op == true; + } + } + } + ldap_value_free_len(bv); + bv = NULL; + } - /* get the Option Values from the entry */ - bv = ldap_get_values_len(ld, entry, "sudoOption"); - if (bv != NULL) { - sudo_lbuf_append(lbuf, " Options: "); - for (p = bv; *p != NULL; p++) { - sudo_lbuf_append(lbuf, "%s%s", p != bv ? ", " : "", (*p)->bv_val); + /* So we can inherit previous values. */ + prev_cmndspec = cmndspec; + } } - ldap_value_free_len(bv); - sudo_lbuf_append(lbuf, "\n"); + ldap_value_free_len(cmnd_bv); + cmnd_bv = NULL; } - /* - * Display order attribute if present. This attribute is single valued, - * so there is no need for a loop. - */ - bv = ldap_get_values_len(ld, entry, "sudoOrder"); - if (bv != NULL) { - if (*bv != NULL) { - sudo_lbuf_append(lbuf, _(" Order: %s\n"), (*bv)->bv_val); - } - ldap_value_free_len(bv); - } + debug_return_ptr(ldap_userspecs); - /* Get the command values from the entry. */ - bv = ldap_get_values_len(ld, entry, "sudoCommand"); - if (bv != NULL) { - sudo_lbuf_append(lbuf, _(" Commands:\n")); - for (p = bv; *p != NULL; p++) { - sudo_lbuf_append(lbuf, "\t%s\n", (*p)->bv_val); - count++; - } +oom: + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + if (cmnd_bv != NULL) + ldap_value_free_len(cmnd_bv); + if (bv != NULL) ldap_value_free_len(bv); + if (ldap_userspecs != NULL) { + while ((us = TAILQ_FIRST(ldap_userspecs)) != NULL) { + TAILQ_REMOVE(ldap_userspecs, us, entries); + free_userspec(us); + } + free(ldap_userspecs); } - - debug_return_int(count); + debug_return_ptr(NULL); } /* @@ -2725,10 +2783,10 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw, struct sudo_lbuf *lbuf) { struct sudo_ldap_handle *handle = nss->handle; - LDAP *ld; + struct userspec_list *ldap_userspecs = NULL; struct ldap_result *lres; - LDAPMessage *entry; - unsigned int i, count = 0; + LDAP *ld; + int ret = 0; debug_decl(sudo_ldap_display_privs, SUDOERS_DEBUG_LDAP) if (handle == NULL || handle->ld == NULL) @@ -2740,19 +2798,27 @@ sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw, if (lres == NULL) goto done; - /* Display all matching entries. */ - for (i = 0; i < lres->nentries; i++) { - entry = lres->entries[i].entry; - if (long_list) - count += sudo_ldap_display_entry_long(ld, entry, pw, lbuf); - else - count += sudo_ldap_display_entry_short(ld, entry, pw, lbuf); + /* Convert to sudoers parse tree. */ + if ((ldap_userspecs = ldap2sudoers(ld, lres)) == NULL) { + ret = -1; + goto done; } + /* Call common display code. */ + ret = sudo_display_userspecs(ldap_userspecs, pw, lbuf); + done: + if (ldap_userspecs != NULL) { + struct userspec *us; + while ((us = TAILQ_FIRST(ldap_userspecs)) != NULL) { + TAILQ_REMOVE(ldap_userspecs, us, entries); + free_userspec(us); + } + free(ldap_userspecs); + } if (sudo_lbuf_error(lbuf)) debug_return_int(-1); - debug_return_int(count); + debug_return_int(ret); } static int diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c index b68022abe..63197838b 100644 --- a/plugins/sudoers/parse.c +++ b/plugins/sudoers/parse.c @@ -373,6 +373,8 @@ sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, { debug_decl(sudo_file_append_cmnd, SUDOERS_DEBUG_NSS) + /* XXX - should not print privs/limitprivs, role/type, timeout + or notbefore/after if unchanged from prior cs */ #ifdef HAVE_PRIV_SET if (cs->privs) sudo_lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs); @@ -438,6 +440,29 @@ sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, debug_return_bool(!sudo_lbuf_error(lbuf)); } +/* + * Format and append a defaults entry to the specified lbuf. + */ +static void +sudo_file_append_default(struct sudo_lbuf *lbuf, struct defaults *d) +{ + debug_decl(sudo_file_append_default, SUDOERS_DEBUG_NSS) + + if (d->val != NULL) { + sudo_lbuf_append(lbuf, "%s%s", d->var, + d->op == '+' ? "+=" : d->op == '-' ? "-=" : "="); + if (strpbrk(d->val, " \t") != NULL) { + sudo_lbuf_append(lbuf, "\""); + sudo_lbuf_append_quoted(lbuf, "\"", "%s", d->val); + sudo_lbuf_append(lbuf, "\""); + } else + sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val); + } else { + sudo_lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var); + } + debug_return; +} + static int sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, struct sudo_lbuf *lbuf) @@ -451,6 +476,9 @@ sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, /* gcc -Wuninitialized false positive */ TAGS_INIT(tags); + /* XXX - should init tags for each privilege */ + /* XXX - does runas change inheriting? */ + /* XXX - what about time and timeout inheriting? */ TAILQ_FOREACH(priv, &us->privileges, entries) { if (hostlist_matches(pw, &priv->hostlist) != ALLOW) continue; @@ -519,6 +547,10 @@ new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs) #endif /* HAVE_SELINUX */ if (cs->timeout != prev_cs->timeout) return true; + if (cs->notbefore != prev_cs->notbefore) + return true; + if (cs->notafter != prev_cs->notafter) + return true; return false; } @@ -527,8 +559,9 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, struct sudo_lbuf *lbuf) { struct cmndspec *cs, *prev_cs; - struct member *m; struct privilege *priv; + struct defaults *def; + struct member *m; int nfound = 0, olen; debug_decl(sudo_file_display_priv_long, SUDOERS_DEBUG_NSS) @@ -538,7 +571,12 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, prev_cs = NULL; TAILQ_FOREACH(cs, &priv->cmndlist, entries) { if (new_long_entry(cs, prev_cs)) { - sudo_lbuf_append(lbuf, _("\nSudoers entry:\n")); + if (priv->ldap_role != NULL) { + sudo_lbuf_append(lbuf, _("\nLDAP Role: %s\n"), + priv->ldap_role); + } else { + sudo_lbuf_append(lbuf, _("\nSudoers entry:\n")); + } sudo_lbuf_append(lbuf, _(" RunAsUsers: ")); if (cs->runasuserlist != NULL) { TAILQ_FOREACH(m, cs->runasuserlist, entries) { @@ -563,6 +601,10 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, } olen = lbuf->len; sudo_lbuf_append(lbuf, _(" Options: ")); + TAILQ_FOREACH(def, &priv->defaults, entries) { + sudo_file_append_default(lbuf, def); + sudo_lbuf_append(lbuf, ", "); + } if (TAG_SET(cs->tags.setenv)) sudo_lbuf_append(lbuf, "%ssetenv, ", cs->tags.setenv ? "" : "!"); if (TAG_SET(cs->tags.noexec)) @@ -624,21 +666,16 @@ sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, debug_return_int(nfound); } -/* - * Returns the number of matching privileges or -1 on error. - */ +/* XXX - better naming */ int -sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw, +sudo_display_userspecs(struct userspec_list *usl, struct passwd *pw, struct sudo_lbuf *lbuf) { struct userspec *us; int nfound = 0; - debug_decl(sudo_file_display_priv, SUDOERS_DEBUG_NSS) + debug_decl(sudo_display_userspecs, SUDOERS_DEBUG_NSS) - if (nss->handle == NULL) - goto done; - - TAILQ_FOREACH(us, &userspecs, entries) { + TAILQ_FOREACH(us, usl, entries) { if (userlist_matches(pw, &us->users) != ALLOW) continue; @@ -649,10 +686,24 @@ sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw, } if (sudo_lbuf_error(lbuf)) debug_return_int(-1); -done: debug_return_int(nfound); } +/* + * Returns the number of matching privileges or -1 on error. + */ +static int +sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw, + struct sudo_lbuf *lbuf) +{ + debug_decl(sudo_file_display_priv, SUDOERS_DEBUG_NSS) + + if (nss->handle == NULL) + debug_return_int(0); + + debug_return_int(sudo_display_userspecs(&userspecs, pw, lbuf)); +} + /* * Display matching Defaults entries for the given user on this host. */ @@ -687,18 +738,8 @@ sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw, case DEFAULTS_CMND: continue; } - if (d->val != NULL) { - sudo_lbuf_append(lbuf, "%s%s%s", prefix, d->var, - d->op == '+' ? "+=" : d->op == '-' ? "-=" : "="); - if (strpbrk(d->val, " \t") != NULL) { - sudo_lbuf_append(lbuf, "\""); - sudo_lbuf_append_quoted(lbuf, "\"", "%s", d->val); - sudo_lbuf_append(lbuf, "\""); - } else - sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val); - } else - sudo_lbuf_append(lbuf, "%s%s%s", prefix, - d->op == false ? "!" : "", d->var); + sudo_lbuf_append(lbuf, "%s", prefix); + sudo_file_append_default(lbuf, d); prefix = ", "; nfound++; } @@ -778,11 +819,7 @@ display_bound_defaults(int deftype, struct sudo_lbuf *lbuf) } } else sudo_lbuf_append(lbuf, ", "); - if (d->val != NULL) { - sudo_lbuf_append(lbuf, "%s%s%s", d->var, d->op == '+' ? "+=" : - d->op == '-' ? "-=" : "=", d->val); - } else - sudo_lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var); + sudo_file_append_default(lbuf, d); } if (sudo_lbuf_error(lbuf)) diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index a2701824b..275071eaa 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -167,8 +167,10 @@ struct userspec { */ struct privilege { TAILQ_ENTRY(privilege) entries; + char *ldap_role; /* LDAP sudoRole */ struct member_list hostlist; /* list of hosts */ struct cmndspec_list cmndlist; /* list of Cmnd_Specs */ + struct defaults_list defaults; /* list of sudoOptions */ }; /* @@ -302,4 +304,8 @@ unsigned char *sudo_filedigest(int fd, const char *file, int digest_type, size_t /* digestname.c */ const char *digest_type_to_name(int digest_type); +/* parse.c */ +struct sudo_lbuf; +int sudo_display_userspecs(struct userspec_list *usl, struct passwd *pw, struct sudo_lbuf *lbuf); + #endif /* SUDOERS_PARSE_H */