[sudo-workers] Supporting sudoUser:!foo in sudo.ldap

Simon Lees sflees at suse.de
Sun Jan 16 18:30:07 MST 2022


Hi All,

On 12/15/21 14:07, Simon Lees wrote:
> 
> 
> On 12/15/21 02:25, Todd C. Miller wrote:
>> I think this is worth pursuing.  The question I have is whether
>> supporting !username is sufficient.  If we are going to support
>> this kind of construct, it should probably mirror the existing query
>> that contains uid, groups, gids and netgroups.
>>
>> Does that make sense?
> 
> Yep, i'll go back and work on that, Thanks for the feedback.

Now I'm back from Summer Holidays here is round 2 that implements the
same Idea for everything.

Given the patch is larger i'm happy to upload it somewhere else if that
works better.


Again feedback is very much appreciated.

Thanks

Simon

Index: sudo-1.9.5p2/plugins/sudoers/ldap.c
===================================================================
--- sudo-1.9.5p2.orig/plugins/sudoers/ldap.c
+++ sudo-1.9.5p2/plugins/sudoers/ldap.c
@@ -923,7 +923,7 @@ done:
 static char *
 sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
 {
-    char *buf, timebuffer[TIMEFILTER_LENGTH + 1], idbuf[MAX_UID_T_LEN + 1];
+    char *buf, *notbuf, timebuffer[TIMEFILTER_LENGTH + 1],
idbuf[MAX_UID_T_LEN + 1];
     struct ldap_netgroup_list netgroups;
     struct ldap_netgroup *ng = NULL;
     struct gid_list *gidlist;
@@ -943,26 +943,29 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
     if (ldap_conf.search_filter)
 	sz += strlen(ldap_conf.search_filter);

-    /* Then add (|(sudoUser=USERNAME)(sudoUser=#uid)(sudoUser=ALL)) +
NUL */
-    sz += 29 + (12 + MAX_UID_T_LEN) + sudo_ldap_value_len(pw->pw_name);
+    /* Then add (| */
+    sz += 2;
+    /* For the following mult by 2 and add additional chars for ! */
+    /* (sudoUser=USERNAME)(sudoUser=#uid)(sudoUser=ALL)) + NUL */
+    sz += (27 + (12 + MAX_UID_T_LEN) +
sudo_ldap_value_len(pw->pw_name))*2+2;

     /* Add space for primary and supplementary groups and gids */
     if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
-	sz += 12 + sudo_ldap_value_len(grp->gr_name);
+	sz += (12 + sudo_ldap_value_len(grp->gr_name))*2+1;
     }
-    sz += 13 + MAX_UID_T_LEN;
+    sz += (13 + MAX_UID_T_LEN)*2+1;
     if ((grlist = sudo_get_grlist(pw)) != NULL) {
 	for (i = 0; i < grlist->ngroups; i++) {
 	    if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0)
 		continue;
-	    sz += 12 + sudo_ldap_value_len(grlist->groups[i]);
+	    sz += (12 + sudo_ldap_value_len(grlist->groups[i]))*2+1;
 	}
     }
     if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
 	for (i = 0; i < gidlist->ngids; i++) {
 	    if (pw->pw_gid == gidlist->gids[i])
 		continue;
-	    sz += 13 + MAX_UID_T_LEN;
+	    sz += (13 + MAX_UID_T_LEN)*2+1;
 	}
     }

@@ -971,7 +974,7 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
 	DPRINTF1("Looking up netgroups for %s", pw->pw_name);
 	if (sudo_netgroup_lookup(ld, pw, &netgroups)) {
 	    STAILQ_FOREACH(ng, &netgroups, entries) {
-		sz += 14 + strlen(ng->name);
+		sz += (14 + strlen(ng->name))*2+1;
 	    }
 	} else {
 	    /* sudo_netgroup_lookup() failed, clean up. */
@@ -986,9 +989,11 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
     /* If timed, add space for time limits. */
     if (ldap_conf.timed)
 	sz += TIMEFILTER_LENGTH;
-    if ((buf = malloc(sz)) == NULL)
+
+    if (((buf = malloc(sz)) == NULL) || ((notbuf = malloc(sz)) == NULL))
 	goto bad;
     *buf = '\0';
+    *notbuf = '\0';

     /*
      * If timed or using a search filter, start a global AND clause to
@@ -1004,23 +1009,35 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
     CHECK_STRLCAT(buf, "(|(sudoUser=", sz);
     CHECK_LDAP_VCAT(buf, pw->pw_name, sz);
     CHECK_STRLCAT(buf, ")", sz);
+    CHECK_STRLCAT(notbuf, "(sudoUser=!", sz);
+    CHECK_LDAP_VCAT(notbuf, pw->pw_name, sz);
+    CHECK_STRLCAT(notbuf, ")", sz);

     /* Append user-ID */
     (void) snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int)pw->pw_uid);
     CHECK_STRLCAT(buf, "(sudoUser=#", sz);
     CHECK_STRLCAT(buf, idbuf, sz);
     CHECK_STRLCAT(buf, ")", sz);
+    CHECK_STRLCAT(notbuf, "(sudoUser=!#", sz);
+    CHECK_STRLCAT(notbuf, idbuf, sz);
+    CHECK_STRLCAT(notbuf, ")", sz);

     /* Append primary group and group-ID */
     if (grp != NULL) {
 	CHECK_STRLCAT(buf, "(sudoUser=%", sz);
 	CHECK_LDAP_VCAT(buf, grp->gr_name, sz);
 	CHECK_STRLCAT(buf, ")", sz);
+	CHECK_STRLCAT(notbuf, "(sudoUser=!%", sz);
+	CHECK_LDAP_VCAT(notbuf, grp->gr_name, sz);
+	CHECK_STRLCAT(notbuf, ")", sz);
     }
     (void) snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int)pw->pw_gid);
     CHECK_STRLCAT(buf, "(sudoUser=%#", sz);
     CHECK_STRLCAT(buf, idbuf, sz);
     CHECK_STRLCAT(buf, ")", sz);
+    CHECK_STRLCAT(notbuf, "(sudoUser=!%#", sz);
+    CHECK_STRLCAT(notbuf, idbuf, sz);
+    CHECK_STRLCAT(notbuf, ")", sz);

     /* Append supplementary groups and group-IDs */
     if (grlist != NULL) {
@@ -1030,6 +1047,9 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
 	    CHECK_STRLCAT(buf, "(sudoUser=%", sz);
 	    CHECK_LDAP_VCAT(buf, grlist->groups[i], sz);
 	    CHECK_STRLCAT(buf, ")", sz);
+	    CHECK_STRLCAT(notbuf, "(sudoUser=!%", sz);
+	    CHECK_LDAP_VCAT(notbuf, grlist->groups[i], sz);
+	    CHECK_STRLCAT(notbuf, ")", sz);
 	}
     }
     if (gidlist != NULL) {
@@ -1041,6 +1061,9 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
 	    CHECK_STRLCAT(buf, "(sudoUser=%#", sz);
 	    CHECK_STRLCAT(buf, idbuf, sz);
 	    CHECK_STRLCAT(buf, ")", sz);
+	    CHECK_STRLCAT(notbuf, "(sudoUser=!%#", sz);
+	    CHECK_STRLCAT(notbuf, idbuf, sz);
+	    CHECK_STRLCAT(notbuf, ")", sz);
 	}
     }

@@ -1058,6 +1081,9 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
 	CHECK_STRLCAT(buf, "(sudoUser=+", sz);
 	CHECK_LDAP_VCAT(buf, ng->name, sz);
 	CHECK_STRLCAT(buf, ")", sz);
+	CHECK_STRLCAT(notbuf, "(sudoUser=!+", sz);
+	CHECK_LDAP_VCAT(notbuf, ng->name, sz);
+	CHECK_STRLCAT(notbuf, ")", sz);
 	free(ng->name);
 	free(ng);
     }
@@ -1074,8 +1100,15 @@ sudo_ldap_build_pass1(LDAP *ld, struct p
     } else if (ldap_conf.search_filter) {
 	CHECK_STRLCAT(buf, ")", sz); /* closes the global OR */
     }
+
+    /* Global ! filters */
+    CHECK_STRLCAT(buf, "(!", sz);
+    CHECK_LDAP_VCAT(buf, notbuf, sz);
+    CHECK_STRLCAT(buf, ")", sz);
+
     CHECK_STRLCAT(buf, ")", sz); /* closes the global OR or the global
AND */

+    free(notbuf);
     debug_return_str(buf);
 overflow:
     sudo_warnx(U_("internal error, %s overflow"), __func__);


-- 
Simon Lees (Simotek)                            http://simotek.net

Emergency Update Team                           keybase.io/simotek
SUSE Linux                           Adelaide Australia, UTC+10:30
GPG Fingerprint: 5B87 DB9D 88DC F606 E489 CEC5 0922 C246 02F0 014B
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 495 bytes
Desc: OpenPGP digital signature
URL: <http://www.sudo.ws/pipermail/sudo-workers/attachments/20220117/0da4649b/attachment.bin>


More information about the sudo-workers mailing list