YYSTYPE *yyvs;
unsigned int yystacksize;
int yyparse(void);
-#line 898 "gram.y"
+#line 899 "gram.y"
void
sudoerserror(const char *s)
{
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 */
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) {
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);
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)
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);
}
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) {
}
break;
case 30:
-#line 310 "gram.y"
+#line 311 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 31:
-#line 317 "gram.y"
+#line 318 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) {
}
break;
case 32:
-#line 324 "gram.y"
+#line 325 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
if (yyval.member == NULL) {
}
break;
case 33:
-#line 331 "gram.y"
+#line 332 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
}
break;
case 35:
-#line 341 "gram.y"
+#line 342 "gram.y"
{
struct cmndspec *prev;
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
}
break;
case 36:
-#line 394 "gram.y"
+#line 395 "gram.y"
{
struct cmndspec *cs = calloc(1, sizeof(*cs));
if (cs == NULL) {
}
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) {
}
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) {
}
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) {
}
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) {
}
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"));
}
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) {
}
break;
case 55:
-#line 555 "gram.y"
+#line 556 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
}
break;
case 56:
-#line 564 "gram.y"
+#line 565 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
}
break;
case 57:
-#line 573 "gram.y"
+#line 574 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
}
break;
case 58:
-#line 582 "gram.y"
+#line 583 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) {
}
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);
}
break;
case 61:
-#line 610 "gram.y"
+#line 611 "gram.y"
{
yyval.options.notafter = parse_gentime(yyvsp[0].string);
free(yyvsp[0].string);
}
break;
case 62:
-#line 618 "gram.y"
+#line 619 "gram.y"
{
yyval.options.timeout = parse_timeout(yyvsp[0].string);
free(yyvsp[0].string);
}
break;
case 63:
-#line 629 "gram.y"
+#line 630 "gram.y"
{
#ifdef HAVE_SELINUX
free(yyval.options.role);
}
break;
case 64:
-#line 635 "gram.y"
+#line 636 "gram.y"
{
#ifdef HAVE_SELINUX
free(yyval.options.type);
}
break;
case 65:
-#line 641 "gram.y"
+#line 642 "gram.y"
{
#ifdef HAVE_PRIV_SET
free(yyval.options.privs);
}
break;
case 66:
-#line 647 "gram.y"
+#line 648 "gram.y"
{
#ifdef HAVE_PRIV_SET
free(yyval.options.limitprivs);
}
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) {
}
break;
case 83:
-#line 709 "gram.y"
+#line 710 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
}
break;
case 84:
-#line 716 "gram.y"
+#line 717 "gram.y"
{
struct sudo_command *c = calloc(1, sizeof(*c));
if (c == NULL) {
}
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);
}
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);
}
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);
}
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);
}
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) {
}
break;
case 106:
-#line 827 "gram.y"
+#line 828 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 107:
-#line 834 "gram.y"
+#line 835 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) {
}
break;
case 108:
-#line 841 "gram.y"
+#line 842 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, USERGROUP);
if (yyval.member == NULL) {
}
break;
case 109:
-#line 848 "gram.y"
+#line 849 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
}
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) {
}
break;
case 115:
-#line 881 "gram.y"
+#line 882 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 116:
-#line 888 "gram.y"
+#line 889 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
}
}
break;
-#line 2075 "gram.c"
+#line 2086 "gram.c"
}
yyssp -= yym;
yystate = *yyssp;
#include "sudoers.h"
#include "parse.h"
+#include "gram.h"
#include "sudo_lbuf.h"
#include "sudo_dso.h"
}
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 == '!')
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;
}
/*
}
/*
- * 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);
}
/*
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)
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
{
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);
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)
/* 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;
#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;
}
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)
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) {
}
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))
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;
}
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.
*/
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++;
}
}
} 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))