From e99082e05b9f0dd0e0f47fa1d2e1b9d922ea8c4c Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Thu, 15 Aug 2019 14:20:12 -0600
Subject: [PATCH] Fix special handling of ipa_hostname that was lost in sudo
 1.8.24. We now include the long and short hostname in sudo parser container.

---
 plugins/sudoers/file.c  |   2 +-
 plugins/sudoers/gram.c  | 215 ++++++++++++++++++++--------------------
 plugins/sudoers/gram.y  |   9 +-
 plugins/sudoers/ldap.c  |   2 +-
 plugins/sudoers/match.c |  23 +++--
 plugins/sudoers/parse.h |   3 +-
 plugins/sudoers/sssd.c  |   7 +-
 7 files changed, 140 insertions(+), 121 deletions(-)

Index: sudo-1.8.27/plugins/sudoers/file.c
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/file.c
+++ sudo-1.8.27/plugins/sudoers/file.c
@@ -83,7 +83,7 @@ sudo_file_open(struct sudo_nss *nss)
     if (handle != NULL) {
 	handle->fp = open_sudoers(sudoers_file, false, NULL);
 	if (handle->fp != NULL) {
-	    init_parse_tree(&handle->parse_tree);
+	    init_parse_tree(&handle->parse_tree, NULL, NULL);
 	} else {
 	    free(handle);
 	    handle = NULL;
Index: sudo-1.8.27/plugins/sudoers/gram.c
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/gram.c
+++ sudo-1.8.27/plugins/sudoers/gram.c
@@ -104,7 +104,9 @@ char *errorfile = NULL;
 struct sudoers_parse_tree parsed_policy = {
     TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
     TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
-    NULL /* aliases */
+    NULL, /* aliases */
+    NULL, /* lhost */
+    NULL /* shost */
 };
 
 /*
@@ -116,7 +118,7 @@ static bool add_userspec(struct member *
 static struct defaults *new_default(char *, char *, short);
 static struct member *new_member(char *, int);
 static struct command_digest *new_digest(int, char *);
-#line 78 "gram.y"
+#line 80 "gram.y"
 #ifndef YYSTYPE_DEFINED
 #define YYSTYPE_DEFINED
 typedef union {
@@ -133,7 +135,7 @@ typedef union {
     int tok;
 } YYSTYPE;
 #endif /* YYSTYPE_DEFINED */
-#line 131 "gram.c"
+#line 133 "gram.c"
 #define COMMAND 257
 #define ALIAS 258
 #define DEFVAR 259
@@ -673,7 +675,7 @@ short *yysslim;
 YYSTYPE *yyvs;
 unsigned int yystacksize;
 int yyparse(void);
-#line 904 "gram.y"
+#line 906 "gram.y"
 void
 sudoerserror(const char *s)
 {
@@ -1017,11 +1019,14 @@ free_userspec(struct userspec *us)
  * Initialized a sudoers parse tree.
  */
 void
-init_parse_tree(struct sudoers_parse_tree *parse_tree)
+init_parse_tree(struct sudoers_parse_tree *parse_tree, const char *lhost,
+    const char *shost)
 {
     TAILQ_INIT(&parse_tree->userspecs);
     TAILQ_INIT(&parse_tree->defaults);
     parse_tree->aliases = NULL;
+    parse_tree->shost = shost;
+    parse_tree->lhost = lhost;
 }
 
 /*
@@ -1098,7 +1103,7 @@ init_options(struct command_options *opt
     opts->limitprivs = NULL;
 #endif
 }
-#line 1044 "gram.c"
+#line 1049 "gram.c"
 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
 #if defined(__cplusplus) || defined(__STDC__)
 static int yygrowstack(void)
@@ -1307,23 +1312,23 @@ yyreduce:
     switch (yyn)
     {
 case 1:
-#line 176 "gram.y"
+#line 178 "gram.y"
 { ; }
 break;
 case 5:
-#line 184 "gram.y"
+#line 186 "gram.y"
 {
 			    ;
 			}
 break;
 case 6:
-#line 187 "gram.y"
+#line 189 "gram.y"
 {
 			    yyerrok;
 			}
 break;
 case 7:
-#line 190 "gram.y"
+#line 192 "gram.y"
 {
 			    if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) {
 				sudoerserror(N_("unable to allocate memory"));
@@ -1332,73 +1337,73 @@ case 7:
 			}
 break;
 case 8:
-#line 196 "gram.y"
+#line 198 "gram.y"
 {
 			    ;
 			}
 break;
 case 9:
-#line 199 "gram.y"
+#line 201 "gram.y"
 {
 			    ;
 			}
 break;
 case 10:
-#line 202 "gram.y"
+#line 204 "gram.y"
 {
 			    ;
 			}
 break;
 case 11:
-#line 205 "gram.y"
+#line 207 "gram.y"
 {
 			    ;
 			}
 break;
 case 12:
-#line 208 "gram.y"
+#line 210 "gram.y"
 {
 			    if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults))
 				YYERROR;
 			}
 break;
 case 13:
-#line 212 "gram.y"
+#line 214 "gram.y"
 {
 			    if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults))
 				YYERROR;
 			}
 break;
 case 14:
-#line 216 "gram.y"
+#line 218 "gram.y"
 {
 			    if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults))
 				YYERROR;
 			}
 break;
 case 15:
-#line 220 "gram.y"
+#line 222 "gram.y"
 {
 			    if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults))
 				YYERROR;
 			}
 break;
 case 16:
-#line 224 "gram.y"
+#line 226 "gram.y"
 {
 			    if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults))
 				YYERROR;
 			}
 break;
 case 18:
-#line 231 "gram.y"
+#line 233 "gram.y"
 {
 			    HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
 			    yyval.defaults = yyvsp[-2].defaults;
 			}
 break;
 case 19:
-#line 237 "gram.y"
+#line 239 "gram.y"
 {
 			    yyval.defaults = new_default(yyvsp[0].string, NULL, true);
 			    if (yyval.defaults == NULL) {
@@ -1408,7 +1413,7 @@ case 19:
 			}
 break;
 case 20:
-#line 244 "gram.y"
+#line 246 "gram.y"
 {
 			    yyval.defaults = new_default(yyvsp[0].string, NULL, false);
 			    if (yyval.defaults == NULL) {
@@ -1418,7 +1423,7 @@ case 20:
 			}
 break;
 case 21:
-#line 251 "gram.y"
+#line 253 "gram.y"
 {
 			    yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true);
 			    if (yyval.defaults == NULL) {
@@ -1428,7 +1433,7 @@ case 21:
 			}
 break;
 case 22:
-#line 258 "gram.y"
+#line 260 "gram.y"
 {
 			    yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
 			    if (yyval.defaults == NULL) {
@@ -1438,7 +1443,7 @@ case 22:
 			}
 break;
 case 23:
-#line 265 "gram.y"
+#line 267 "gram.y"
 {
 			    yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
 			    if (yyval.defaults == NULL) {
@@ -1448,14 +1453,14 @@ case 23:
 			}
 break;
 case 25:
-#line 275 "gram.y"
+#line 277 "gram.y"
 {
 			    HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
 			    yyval.privilege = yyvsp[-2].privilege;
 			}
 break;
 case 26:
-#line 281 "gram.y"
+#line 283 "gram.y"
 {
 			    struct privilege *p = calloc(1, sizeof(*p));
 			    if (p == NULL) {
@@ -1470,21 +1475,21 @@ case 26:
 			}
 break;
 case 27:
-#line 295 "gram.y"
+#line 297 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = false;
 			}
 break;
 case 28:
-#line 299 "gram.y"
+#line 301 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = true;
 			}
 break;
 case 29:
-#line 305 "gram.y"
+#line 307 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, ALIAS);
 			    if (yyval.member == NULL) {
@@ -1494,7 +1499,7 @@ case 29:
 			}
 break;
 case 30:
-#line 312 "gram.y"
+#line 314 "gram.y"
 {
 			    yyval.member = new_member(NULL, ALL);
 			    if (yyval.member == NULL) {
@@ -1504,7 +1509,7 @@ case 30:
 			}
 break;
 case 31:
-#line 319 "gram.y"
+#line 321 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, NETGROUP);
 			    if (yyval.member == NULL) {
@@ -1514,7 +1519,7 @@ case 31:
 			}
 break;
 case 32:
-#line 326 "gram.y"
+#line 328 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, NTWKADDR);
 			    if (yyval.member == NULL) {
@@ -1524,7 +1529,7 @@ case 32:
 			}
 break;
 case 33:
-#line 333 "gram.y"
+#line 335 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, WORD);
 			    if (yyval.member == NULL) {
@@ -1534,7 +1539,7 @@ case 33:
 			}
 break;
 case 35:
-#line 343 "gram.y"
+#line 345 "gram.y"
 {
 			    struct cmndspec *prev;
 			    prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
@@ -1588,7 +1593,7 @@ case 35:
 			}
 break;
 case 36:
-#line 396 "gram.y"
+#line 398 "gram.y"
 {
 			    struct cmndspec *cs = calloc(1, sizeof(*cs));
 			    if (cs == NULL) {
@@ -1640,7 +1645,7 @@ case 36:
 			}
 break;
 case 37:
-#line 447 "gram.y"
+#line 449 "gram.y"
 {
 			    yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
 			    if (yyval.digest == NULL) {
@@ -1650,7 +1655,7 @@ case 37:
 			}
 break;
 case 38:
-#line 454 "gram.y"
+#line 456 "gram.y"
 {
 			    yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
 			    if (yyval.digest == NULL) {
@@ -1660,7 +1665,7 @@ case 38:
 			}
 break;
 case 39:
-#line 461 "gram.y"
+#line 463 "gram.y"
 {
 			    yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
 			    if (yyval.digest == NULL) {
@@ -1670,7 +1675,7 @@ case 39:
 			}
 break;
 case 40:
-#line 468 "gram.y"
+#line 470 "gram.y"
 {
 			    yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
 			    if (yyval.digest == NULL) {
@@ -1680,13 +1685,13 @@ case 40:
 			}
 break;
 case 41:
-#line 477 "gram.y"
+#line 479 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			}
 break;
 case 42:
-#line 480 "gram.y"
+#line 482 "gram.y"
 {
 			    if (yyvsp[0].member->type != COMMAND) {
 				sudoerserror(N_("a digest requires a path name"));
@@ -1698,75 +1703,75 @@ case 42:
 			}
 break;
 case 43:
-#line 491 "gram.y"
+#line 493 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = false;
 			}
 break;
 case 44:
-#line 495 "gram.y"
+#line 497 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = true;
 			}
 break;
 case 45:
-#line 501 "gram.y"
+#line 503 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 46:
-#line 506 "gram.y"
+#line 508 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 47:
-#line 510 "gram.y"
+#line 512 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 48:
-#line 515 "gram.y"
+#line 517 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 49:
-#line 520 "gram.y"
+#line 522 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 50:
-#line 525 "gram.y"
+#line 527 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 51:
-#line 529 "gram.y"
+#line 531 "gram.y"
 {
 			    yyval.string = yyvsp[0].string;
 			}
 break;
 case 52:
-#line 534 "gram.y"
+#line 536 "gram.y"
 {
 			    yyval.runas = NULL;
 			}
 break;
 case 53:
-#line 537 "gram.y"
+#line 539 "gram.y"
 {
 			    yyval.runas = yyvsp[-1].runas;
 			}
 break;
 case 54:
-#line 542 "gram.y"
+#line 544 "gram.y"
 {
 			    yyval.runas = calloc(1, sizeof(struct runascontainer));
 			    if (yyval.runas != NULL) {
@@ -1784,7 +1789,7 @@ case 54:
 			}
 break;
 case 55:
-#line 557 "gram.y"
+#line 559 "gram.y"
 {
 			    yyval.runas = calloc(1, sizeof(struct runascontainer));
 			    if (yyval.runas == NULL) {
@@ -1796,7 +1801,7 @@ case 55:
 			}
 break;
 case 56:
-#line 566 "gram.y"
+#line 568 "gram.y"
 {
 			    yyval.runas = calloc(1, sizeof(struct runascontainer));
 			    if (yyval.runas == NULL) {
@@ -1808,7 +1813,7 @@ case 56:
 			}
 break;
 case 57:
-#line 575 "gram.y"
+#line 577 "gram.y"
 {
 			    yyval.runas = calloc(1, sizeof(struct runascontainer));
 			    if (yyval.runas == NULL) {
@@ -1820,7 +1825,7 @@ case 57:
 			}
 break;
 case 58:
-#line 584 "gram.y"
+#line 586 "gram.y"
 {
 			    yyval.runas = calloc(1, sizeof(struct runascontainer));
 			    if (yyval.runas != NULL) {
@@ -1838,13 +1843,13 @@ case 58:
 			}
 break;
 case 59:
-#line 601 "gram.y"
+#line 603 "gram.y"
 {
 			    init_options(&yyval.options);
 			}
 break;
 case 60:
-#line 604 "gram.y"
+#line 606 "gram.y"
 {
 			    yyval.options.notbefore = parse_gentime(yyvsp[0].string);
 			    free(yyvsp[0].string);
@@ -1855,7 +1860,7 @@ case 60:
 			}
 break;
 case 61:
-#line 612 "gram.y"
+#line 614 "gram.y"
 {
 			    yyval.options.notafter = parse_gentime(yyvsp[0].string);
 			    free(yyvsp[0].string);
@@ -1866,7 +1871,7 @@ case 61:
 			}
 break;
 case 62:
-#line 620 "gram.y"
+#line 622 "gram.y"
 {
 			    yyval.options.timeout = parse_timeout(yyvsp[0].string);
 			    free(yyvsp[0].string);
@@ -1880,7 +1885,7 @@ case 62:
 			}
 break;
 case 63:
-#line 631 "gram.y"
+#line 633 "gram.y"
 {
 #ifdef HAVE_SELINUX
 			    free(yyval.options.role);
@@ -1889,7 +1894,7 @@ case 63:
 			}
 break;
 case 64:
-#line 637 "gram.y"
+#line 639 "gram.y"
 {
 #ifdef HAVE_SELINUX
 			    free(yyval.options.type);
@@ -1898,7 +1903,7 @@ case 64:
 			}
 break;
 case 65:
-#line 643 "gram.y"
+#line 645 "gram.y"
 {
 #ifdef HAVE_PRIV_SET
 			    free(yyval.options.privs);
@@ -1907,7 +1912,7 @@ case 65:
 			}
 break;
 case 66:
-#line 649 "gram.y"
+#line 651 "gram.y"
 {
 #ifdef HAVE_PRIV_SET
 			    free(yyval.options.limitprivs);
@@ -1916,97 +1921,97 @@ case 66:
 			}
 break;
 case 67:
-#line 657 "gram.y"
+#line 659 "gram.y"
 {
 			    TAGS_INIT(yyval.tag);
 			}
 break;
 case 68:
-#line 660 "gram.y"
+#line 662 "gram.y"
 {
 			    yyval.tag.nopasswd = true;
 			}
 break;
 case 69:
-#line 663 "gram.y"
+#line 665 "gram.y"
 {
 			    yyval.tag.nopasswd = false;
 			}
 break;
 case 70:
-#line 666 "gram.y"
+#line 668 "gram.y"
 {
 			    yyval.tag.noexec = true;
 			}
 break;
 case 71:
-#line 669 "gram.y"
+#line 671 "gram.y"
 {
 			    yyval.tag.noexec = false;
 			}
 break;
 case 72:
-#line 672 "gram.y"
+#line 674 "gram.y"
 {
 			    yyval.tag.setenv = true;
 			}
 break;
 case 73:
-#line 675 "gram.y"
+#line 677 "gram.y"
 {
 			    yyval.tag.setenv = false;
 			}
 break;
 case 74:
-#line 678 "gram.y"
+#line 680 "gram.y"
 {
 			    yyval.tag.log_input = true;
 			}
 break;
 case 75:
-#line 681 "gram.y"
+#line 683 "gram.y"
 {
 			    yyval.tag.log_input = false;
 			}
 break;
 case 76:
-#line 684 "gram.y"
+#line 686 "gram.y"
 {
 			    yyval.tag.log_output = true;
 			}
 break;
 case 77:
-#line 687 "gram.y"
+#line 689 "gram.y"
 {
 			    yyval.tag.log_output = false;
 			}
 break;
 case 78:
-#line 690 "gram.y"
+#line 692 "gram.y"
 {
 			    yyval.tag.follow = true;
 			}
 break;
 case 79:
-#line 693 "gram.y"
+#line 695 "gram.y"
 {
 			    yyval.tag.follow = false;
 			}
 break;
 case 80:
-#line 696 "gram.y"
+#line 698 "gram.y"
 {
 			    yyval.tag.send_mail = true;
 			}
 break;
 case 81:
-#line 699 "gram.y"
+#line 701 "gram.y"
 {
 			    yyval.tag.send_mail = false;
 			}
 break;
 case 82:
-#line 704 "gram.y"
+#line 706 "gram.y"
 {
 			    yyval.member = new_member(NULL, ALL);
 			    if (yyval.member == NULL) {
@@ -2016,7 +2021,7 @@ case 82:
 			}
 break;
 case 83:
-#line 711 "gram.y"
+#line 713 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, ALIAS);
 			    if (yyval.member == NULL) {
@@ -2026,7 +2031,7 @@ case 83:
 			}
 break;
 case 84:
-#line 718 "gram.y"
+#line 720 "gram.y"
 {
 			    struct sudo_command *c = calloc(1, sizeof(*c));
 			    if (c == NULL) {
@@ -2044,7 +2049,7 @@ case 84:
 			}
 break;
 case 87:
-#line 739 "gram.y"
+#line 741 "gram.y"
 {
 			    const char *s;
 			    s = alias_add(&parsed_policy, yyvsp[-2].string, HOSTALIAS,
@@ -2056,14 +2061,14 @@ case 87:
 			}
 break;
 case 89:
-#line 751 "gram.y"
+#line 753 "gram.y"
 {
 			    HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
 			    yyval.member = yyvsp[-2].member;
 			}
 break;
 case 92:
-#line 761 "gram.y"
+#line 763 "gram.y"
 {
 			    const char *s;
 			    s = alias_add(&parsed_policy, yyvsp[-2].string, CMNDALIAS,
@@ -2075,14 +2080,14 @@ case 92:
 			}
 break;
 case 94:
-#line 773 "gram.y"
+#line 775 "gram.y"
 {
 			    HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
 			    yyval.member = yyvsp[-2].member;
 			}
 break;
 case 97:
-#line 783 "gram.y"
+#line 785 "gram.y"
 {
 			    const char *s;
 			    s = alias_add(&parsed_policy, yyvsp[-2].string, RUNASALIAS,
@@ -2094,7 +2099,7 @@ case 97:
 			}
 break;
 case 100:
-#line 798 "gram.y"
+#line 800 "gram.y"
 {
 			    const char *s;
 			    s = alias_add(&parsed_policy, yyvsp[-2].string, USERALIAS,
@@ -2106,28 +2111,28 @@ case 100:
 			}
 break;
 case 102:
-#line 810 "gram.y"
+#line 812 "gram.y"
 {
 			    HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
 			    yyval.member = yyvsp[-2].member;
 			}
 break;
 case 103:
-#line 816 "gram.y"
+#line 818 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = false;
 			}
 break;
 case 104:
-#line 820 "gram.y"
+#line 822 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = true;
 			}
 break;
 case 105:
-#line 826 "gram.y"
+#line 828 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, ALIAS);
 			    if (yyval.member == NULL) {
@@ -2137,7 +2142,7 @@ case 105:
 			}
 break;
 case 106:
-#line 833 "gram.y"
+#line 835 "gram.y"
 {
 			    yyval.member = new_member(NULL, ALL);
 			    if (yyval.member == NULL) {
@@ -2147,7 +2152,7 @@ case 106:
 			}
 break;
 case 107:
-#line 840 "gram.y"
+#line 842 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, NETGROUP);
 			    if (yyval.member == NULL) {
@@ -2157,7 +2162,7 @@ case 107:
 			}
 break;
 case 108:
-#line 847 "gram.y"
+#line 849 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, USERGROUP);
 			    if (yyval.member == NULL) {
@@ -2167,7 +2172,7 @@ case 108:
 			}
 break;
 case 109:
-#line 854 "gram.y"
+#line 856 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, WORD);
 			    if (yyval.member == NULL) {
@@ -2177,28 +2182,28 @@ case 109:
 			}
 break;
 case 111:
-#line 864 "gram.y"
+#line 866 "gram.y"
 {
 			    HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
 			    yyval.member = yyvsp[-2].member;
 			}
 break;
 case 112:
-#line 870 "gram.y"
+#line 872 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = false;
 			}
 break;
 case 113:
-#line 874 "gram.y"
+#line 876 "gram.y"
 {
 			    yyval.member = yyvsp[0].member;
 			    yyval.member->negated = true;
 			}
 break;
 case 114:
-#line 880 "gram.y"
+#line 882 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, ALIAS);
 			    if (yyval.member == NULL) {
@@ -2208,7 +2213,7 @@ case 114:
 			}
 break;
 case 115:
-#line 887 "gram.y"
+#line 889 "gram.y"
 {
 			    yyval.member = new_member(NULL, ALL);
 			    if (yyval.member == NULL) {
@@ -2218,7 +2223,7 @@ case 115:
 			}
 break;
 case 116:
-#line 894 "gram.y"
+#line 896 "gram.y"
 {
 			    yyval.member = new_member(yyvsp[0].string, WORD);
 			    if (yyval.member == NULL) {
@@ -2227,7 +2232,7 @@ case 116:
 			    }
 			}
 break;
-#line 2173 "gram.c"
+#line 2178 "gram.c"
     }
     yyssp -= yym;
     yystate = *yyssp;
Index: sudo-1.8.27/plugins/sudoers/gram.y
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/gram.y
+++ sudo-1.8.27/plugins/sudoers/gram.y
@@ -61,7 +61,9 @@ char *errorfile = NULL;
 struct sudoers_parse_tree parsed_policy = {
     TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
     TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
-    NULL /* aliases */
+    NULL, /* aliases */
+    NULL, /* lhost */
+    NULL /* shost */
 };
 
 /*
@@ -1244,11 +1246,14 @@ free_userspec(struct userspec *us)
  * Initialized a sudoers parse tree.
  */
 void
-init_parse_tree(struct sudoers_parse_tree *parse_tree)
+init_parse_tree(struct sudoers_parse_tree *parse_tree, const char *lhost,
+    const char *shost)
 {
     TAILQ_INIT(&parse_tree->userspecs);
     TAILQ_INIT(&parse_tree->defaults);
     parse_tree->aliases = NULL;
+    parse_tree->shost = shost;
+    parse_tree->lhost = lhost;
 }
 
 /*
Index: sudo-1.8.27/plugins/sudoers/ldap.c
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/ldap.c
+++ sudo-1.8.27/plugins/sudoers/ldap.c
@@ -1651,7 +1651,7 @@ sudo_ldap_open(struct sudo_nss *nss)
     }
     handle->ld = ld;
     /* handle->pw = NULL; */
-    init_parse_tree(&handle->parse_tree);
+    init_parse_tree(&handle->parse_tree, NULL, NULL);
     nss->handle = handle;
 
 done:
Index: sudo-1.8.27/plugins/sudoers/match.c
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/match.c
+++ sudo-1.8.27/plugins/sudoers/match.c
@@ -99,8 +99,10 @@ int
 user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
     const struct member *m)
 {
-    struct alias *a;
+    const char *lhost = parse_tree->lhost ? parse_tree->lhost : user_runhost;
+    const char *shost = parse_tree->shost ? parse_tree->shost : user_srunhost;
     int matched = UNSPEC;
+    struct alias *a;
     debug_decl(user_matches, SUDOERS_DEBUG_MATCH)
 
     switch (m->type) {
@@ -109,8 +111,8 @@ user_matches(struct sudoers_parse_tree *
 	    break;
 	case NETGROUP:
 	    if (netgr_matches(m->name,
-		def_netgroup_tuple ? user_runhost : NULL,
-		def_netgroup_tuple ? user_srunhost : NULL, pw->pw_name))
+		def_netgroup_tuple ? lhost : NULL,
+		def_netgroup_tuple ? shost : NULL, pw->pw_name))
 		matched = !m->negated;
 	    break;
 	case USERGROUP:
@@ -180,11 +182,13 @@ runaslist_matches(struct sudoers_parse_t
     const struct member_list *user_list, const struct member_list *group_list,
     struct member **matching_user, struct member **matching_group)
 {
+    const char *lhost = parse_tree->lhost ? parse_tree->lhost : user_runhost;
+    const char *shost = parse_tree->shost ? parse_tree->shost : user_srunhost;
+    int user_matched = UNSPEC;
+    int group_matched = UNSPEC;
     struct member *m;
     struct alias *a;
     int rc;
-    int user_matched = UNSPEC;
-    int group_matched = UNSPEC;
     debug_decl(runaslist_matches, SUDOERS_DEBUG_MATCH)
 
     if (ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) || !ISSET(sudo_user.flags, RUNAS_GROUP_SPECIFIED)) {
@@ -202,8 +206,8 @@ runaslist_matches(struct sudoers_parse_t
 			break;
 		    case NETGROUP:
 			if (netgr_matches(m->name,
-			    def_netgroup_tuple ? user_runhost : NULL,
-			    def_netgroup_tuple ? user_srunhost : NULL,
+			    def_netgroup_tuple ? lhost : NULL,
+			    def_netgroup_tuple ? shost : NULL,
 			    runas_pw->pw_name))
 			    user_matched = !m->negated;
 			break;
@@ -336,7 +340,10 @@ int
 hostlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
     const struct member_list *list)
 {
-    return hostlist_matches_int(parse_tree, pw, user_runhost, user_srunhost, list);
+    const char *lhost = parse_tree->lhost ? parse_tree->lhost : user_runhost;
+    const char *shost = parse_tree->shost ? parse_tree->shost : user_srunhost;
+
+    return hostlist_matches_int(parse_tree, pw, lhost, shost, list);
 }
 
 /*
Index: sudo-1.8.27/plugins/sudoers/parse.h
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/parse.h
+++ sudo-1.8.27/plugins/sudoers/parse.h
@@ -265,6 +265,7 @@ struct sudoers_parse_tree {
     struct userspec_list userspecs;
     struct defaults_list defaults;
     struct rbtree *aliases;
+    const char *shost, *lhost;
 };
 
 /* alias.c */
@@ -290,7 +291,7 @@ void free_userspec(struct userspec *us);
 void free_userspecs(struct userspec_list *usl);
 void free_default(struct defaults *def, struct member_list **binding);
 void free_defaults(struct defaults_list *defs);
-void init_parse_tree(struct sudoers_parse_tree *parse_tree);
+void init_parse_tree(struct sudoers_parse_tree *parse_tree, const char *shost, const char *lhost);
 void free_parse_tree(struct sudoers_parse_tree *parse_tree);
 void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
 
Index: sudo-1.8.27/plugins/sudoers/sssd.c
===================================================================
--- sudo-1.8.27.orig/plugins/sudoers/sssd.c
+++ sudo-1.8.27/plugins/sudoers/sssd.c
@@ -552,7 +552,6 @@ sudo_sss_open(struct sudo_nss *nss)
 	sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
 	debug_return_int(ENOMEM);
     }
-    init_parse_tree(&handle->parse_tree);
 
     /* Load symbols */
     handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
@@ -610,8 +609,6 @@ sudo_sss_open(struct sudo_nss *nss)
 	debug_return_int(EFAULT);
     }
 
-    nss->handle = handle;
-
     /*
      * If runhost is the same as the local host, check for ipa_hostname
      * in sssd.conf and use it in preference to user_runhost.
@@ -623,6 +620,10 @@ sudo_sss_open(struct sudo_nss *nss)
 	}
     }
 
+    /* The "parse tree" contains userspecs, defaults, aliases and hostnames. */
+    init_parse_tree(&handle->parse_tree, handle->ipa_host, handle->ipa_shost);
+    nss->handle = handle;
+
     sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
 
     debug_return_int(0);
