Blame SOURCES/sudo-1.8.6p3-netgrfilterfix.patch

523624
diff -up sudo-1.8.6p3/plugins/sudoers/sssd.c.netgrfilterfix sudo-1.8.6p3/plugins/sudoers/sssd.c
523624
--- sudo-1.8.6p3/plugins/sudoers/sssd.c.netgrfilterfix	2014-07-30 13:29:47.713823996 +0200
523624
+++ sudo-1.8.6p3/plugins/sudoers/sssd.c	2014-07-30 13:30:08.917436088 +0200
523624
@@ -614,16 +615,13 @@ sudo_sss_check_host(struct sudo_sss_hand
523624
 }
523624
 
523624
 /*
523624
- * Look for netgroup specifcations in the sudoUser attribute and
523624
- * if found, filter according to netgroup membership.
523624
- *  returns:
523624
- *   true -> netgroup spec found && negroup member
523624
- *  false -> netgroup spec found && not a meber of netgroup
523624
- *   true -> netgroup spec not found (filtered by SSSD already, netgroups are an exception)
523624
+ * SSSD doesn't handle netgroups, we have to ensure they are correctly filtered
523624
+ * in sudo. The rules may contain mixed sudoUser specification so we have to check
523624
+ * not only for netgroup membership but also for user and group matches.
523624
  */
523624
-bool sudo_sss_filter_user_netgroup(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
523624
+bool sudo_sss_filter_sudoUser(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
523624
 {
523624
-	bool ret = false, netgroup_spec_found = false;
523624
+	bool ret = false;
523624
 	char **val_array, *val;
523624
 	int i;
523624
 	debug_decl(sudo_sss_check_user_netgroup, SUDO_DEBUG_SSSD);
523624
@@ -641,21 +639,48 @@ bool sudo_sss_filter_user_netgroup(struc
523624
 			sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoUser): != 0");
523624
 			debug_return_bool(ret);
523624
 	}
523624
-
523624
+	/*
523624
+	 * Scan sudoUser values and look for netgroup specs.
523624
+	 * Netgroup-only rule specification should be filtered
523624
+	 * out if the user isn't member of any specified netgroup.
523624
+	 */
523624
 	for (i = 0; val_array[i] != NULL && !ret; ++i) {
523624
 		val = val_array[i];
523624
-		if (*val == '+') {
523624
-			netgroup_spec_found = true;
523624
-		}
523624
 		sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
523624
-		if (strcmp(val, "ALL") == 0 || netgr_matches(val, NULL, NULL, user_name)) {
523624
-			ret = true;
523624
-			sudo_debug_printf(SUDO_DEBUG_DIAG,
523624
-			                  "sssd/ldap sudoUser '%s' ... MATCH! (%s)", val, user_name);
523624
+		if (*val == '+') {
523624
+			/* Netgroup spec found, check netgroup membership */
523624
+			if (netgr_matches(val, NULL, NULL, handle->pw->pw_name)) {
523624
+				ret = true;
523624
+				sudo_debug_printf(SUDO_DEBUG_DIAG,
523624
+						  "sssd/ldap sudoUser '%s' ... MATCH! (%s)", val, handle->pw->pw_name);
523624
+			}
523624
+		} else {
523624
+			/*
523624
+			 * Non-netgroup sudoUser value
523624
+			 */
523624
+			if (strcmp(val, "ALL") == 0) {
523624
+				ret = true;
523624
+			} else {
523624
+				const char *match_val = (*val == '!' ? val + 1 : val);
523624
+				const bool negated = (*val == '!' ? true : false);
523624
+				const bool group_spec = (*match_val == '%' ? true : false);
523624
+
523624
+				if (group_spec) {
523624
+					if (usergr_matches(match_val,
523624
+							   handle->pw->pw_name, handle->pw)) {
523624
+						ret = !negated;
523624
+					}
523624
+				} else {
523624
+					if (userpw_matches(match_val,
523624
+							   handle->pw->pw_name, handle->pw)) {
523624
+						ret = !negated;
523624
+					}
523624
+				}
523624
+			}
523624
 		}
523624
 	}
523624
 	handle->fn_free_values(val_array);
523624
-	debug_return_bool(netgroup_spec_found ? ret : true);
523624
+	debug_return_bool(ret);
523624
 }
523624
 
523624
 static int
523624
@@ -666,7 +691,7 @@ sudo_sss_result_filterp(struct sudo_sss_
523624
     debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD);
523624
 
523624
     if (sudo_sss_check_host(handle, rule) &&
523624
-        sudo_sss_filter_user_netgroup(handle, rule))
523624
+        sudo_sss_filter_sudoUser(handle, rule))
523624
 	debug_return_int(1);
523624
     else
523624
 	debug_return_int(0);