]> granicus.if.org Git - sudo/commitdiff
Convert ldap results into a sudoers userspec so we can use the "sudo
authorTodd C. Miller <Todd.Miller@sudo.ws>
Sat, 10 Feb 2018 01:21:01 +0000 (18:21 -0700)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Sat, 10 Feb 2018 01:21:01 +0000 (18:21 -0700)
-l" output functions in parse.c.

plugins/sudoers/gram.c
plugins/sudoers/gram.y
plugins/sudoers/ldap.c
plugins/sudoers/parse.c
plugins/sudoers/parse.h

index 48cb692be1058f9a738583811329849787ff69ab..bb7c3ae45cb437505b5443148af9d15111058944 100644 (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;
index ed20fac00cf793a53597eefafa191dcd8a95836d..a85c3027bfa4346566350327d95cbe4f384abee6 100644 (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);
index e1b58bbe2f4922caa50fbe1ac7250f369cd91834..65e3eb46fa1078bdd3d09dd59a8444367295f80a 100644 (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)
-
-    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
index b68022abe5dc12686137a2f33a642837c50569a1..63197838b0c9e1e186220aa86730f6d1423a84d7 100644 (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))
index a2701824b558f6a1b01ff7816d9aa1cd502b8f94..275071eaa1ec52dd4061304fc492c66bb1ca7f13 100644 (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 */