Convert ldap results into a sudoers userspec so we can use the "sudo

-l" output functions in parse.c.
This commit is contained in:
Todd C. Miller
2018-02-09 18:21:01 -07:00
parent 787717755b
commit 4e2402a8e4
5 changed files with 489 additions and 358 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)
struct member_list *members;
struct berval **p;
struct member *m;
debug_decl(bv_to_member_list, SUDOERS_DEBUG_LDAP)
sudo_lbuf_append(lbuf, " (");
if ((members = calloc(1, sizeof(*members))) == NULL)
return NULL;
TAILQ_INIT(members);
/* 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;
}
for (p = bv; *p != NULL; p++) {
if ((m = calloc(1, sizeof(*m))) == NULL)
goto bad;
/* 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, ") ");
/* 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, " ");
}
ldap_value_free_len(bv);
}
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);
}
/* 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);
}
/* 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)
*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);
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;
}
count++;
/* 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);
}
sudo_lbuf_append(lbuf, "\n");
debug_return_int(count);
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);
}
/*
* 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)
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;
bool no_runas_user = true;
char *rdn;
int count = 0;
debug_decl(sudo_ldap_display_entry_long, SUDOERS_DEBUG_LDAP)
struct berval **cmnd_bv, **cmnd; /* XXX - naming */
char *cn;
unsigned int i;
debug_decl(ldap2sudoers, 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);
if ((ldap_userspecs = calloc(1, sizeof(*ldap_userspecs))) == NULL)
goto oom;
TAILQ_INIT(ldap_userspecs);
/* 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);
/* 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 ((c->args = strdup(args)) == NULL) {
free(c);
free(m);
goto oom;
}
}
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;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* So we can inherit previous values. */
prev_cmndspec = cmndspec;
}
}
ldap_value_free_len(bv);
no_runas_user = false;
ldap_value_free_len(cmnd_bv);
cmnd_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");
}
debug_return_ptr(ldap_userspecs);
/* 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);
}
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);
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);
if (ldap_userspecs != NULL) {
while ((us = TAILQ_FIRST(ldap_userspecs)) != NULL) {
TAILQ_REMOVE(ldap_userspecs, us, entries);
free_userspec(us);
}
ldap_value_free_len(bv);
sudo_lbuf_append(lbuf, "\n");
free(ldap_userspecs);
}
/* 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);
}
ldap_value_free_len(bv);
sudo_lbuf_append(lbuf, "\n");
}
/*
* 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);
}
/* 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++;
}
ldap_value_free_len(bv);
}
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

View File

@@ -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))

View File

@@ -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 */