java-topology/defects/samba-0002/patch/samba-0002.patch

195 lines
6.4 KiB
Diff

# UNDF: UNDF-2026-000001031
# UNDF: UNDF-2026-XXXXXXXXX
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -163,6 +163,35 @@ NTSTATUS samdb_set_global_schema(struct ldb_context *ldb)
return NULL;
}
+/*
+ * Binary insertion into a sorted struct dom_sid array.
+ *
+ * Returns count+1 if the SID was inserted (new, unique).
+ * Returns count unchanged if the SID was already present (duplicate).
+ *
+ * Used by security_token_create() to replace O(N) linear dedup scan with
+ * O(log N) bsearch + O(N) shift. Total token-build cost drops from O(N^2)
+ * to O(N log N).
+ */
+static uint32_t sid_sorted_insert_unique(struct dom_sid *scratch,
+ uint32_t count,
+ const struct dom_sid *sid)
+{
+ uint32_t lo = 0, hi = count;
+ while (lo < hi) {
+ uint32_t mid = lo + (hi - lo) / 2;
+ int cmp = dom_sid_compare(&scratch[mid], sid);
+ if (cmp == 0) return count; /* duplicate */
+ if (cmp < 0) lo = mid + 1;
+ else hi = mid;
+ }
+ /* lo is the sorted insertion point */
+ memmove(&scratch[lo + 1], &scratch[lo],
+ (count - lo) * sizeof(struct dom_sid));
+ scratch[lo] = *sid;
+ return count + 1;
+}
+
/****************************************************************************
Create the SID list for this user.
****************************************************************************/
@@ -187,6 +216,16 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
enum claims_evaluation_control evaluate_claims;
bool sids_are_valid = false;
bool device_sids_are_valid = false;
+ /*
+ * Sorted scratch arrays for O(N log N) dedup.
+ * The existing nested for-loop dedup is O(N^2): for each incoming SID
+ * it scans all already-accepted SIDs linearly. For a Kerberos PAC
+ * with ~500 group SIDs that is ~125,000 dom_sid_equal() calls at login.
+ * We replace it with binary-insertion-sort into a scratch array so each
+ * membership test costs O(log N) instead of O(N).
+ */
+ struct dom_sid *sorted_sids = NULL;
+ uint32_t sorted_count = 0;
+ struct dom_sid *sorted_device_sids = NULL;
+ uint32_t sorted_device_count = 0;
bool authentication_was_compounded = session_info_flags & AUTH_SESSION_INFO_FORCE_COMPOUNDED_AUTHENTICATION;
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
@@ -224,31 +263,42 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
ptoken->num_sids = 0;
+ sorted_sids = talloc_array(tmp_ctx, struct dom_sid,
+ num_sids > 0 ? num_sids : 1);
+ if (sorted_sids == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
for (i = 0; i < num_sids; i++) {
- uint32_t check_sid_idx;
- for (check_sid_idx = 0;
- check_sid_idx < ptoken->num_sids;
- check_sid_idx++) {
- if (dom_sid_equal(&ptoken->sids[check_sid_idx], &sids[i].sid)) {
- break;
- }
- }
-
- if (check_sid_idx == ptoken->num_sids) {
- const struct dom_sid *sid = &sids[i].sid;
-
- sids_are_valid = sids_are_valid || dom_sid_equal(
- sid, &global_sid_Claims_Valid);
- authentication_was_compounded = authentication_was_compounded || dom_sid_equal(
- sid, &global_sid_Compounded_Authentication);
-
- ptoken->sids = talloc_realloc(ptoken, ptoken->sids, struct dom_sid, ptoken->num_sids + 1);
- if (ptoken->sids == NULL) {
- talloc_free(ptoken);
- return NT_STATUS_NO_MEMORY;
- }
-
- ptoken->sids[ptoken->num_sids] = *sid;
- ptoken->num_sids++;
+ const struct dom_sid *sid = &sids[i].sid;
+ uint32_t new_count;
+
+ /* O(log sorted_count) membership test + O(sorted_count) shift */
+ new_count = sid_sorted_insert_unique(sorted_sids, sorted_count, sid);
+ if (new_count == sorted_count) {
+ continue; /* duplicate */
}
+ sorted_count = new_count;
+
+ sids_are_valid = sids_are_valid || dom_sid_equal(
+ sid, &global_sid_Claims_Valid);
+ authentication_was_compounded = authentication_was_compounded || dom_sid_equal(
+ sid, &global_sid_Compounded_Authentication);
+
+ ptoken->sids = talloc_realloc(ptoken, ptoken->sids,
+ struct dom_sid, ptoken->num_sids + 1);
+ if (ptoken->sids == NULL) {
+ talloc_free(tmp_ctx);
+ talloc_free(ptoken);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ptoken->sids[ptoken->num_sids] = *sid;
+ ptoken->num_sids++;
}
if (authentication_was_compounded && num_device_sids) {
@@ -258,31 +308,40 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
- for (i = 0; i < num_device_sids; i++) {
- uint32_t check_sid_idx;
- for (check_sid_idx = 0;
- check_sid_idx < ptoken->num_device_sids;
- check_sid_idx++) {
- if (dom_sid_equal(&ptoken->device_sids[check_sid_idx], &device_sids[i].sid)) {
- break;
- }
- }
-
- if (check_sid_idx == ptoken->num_device_sids) {
- const struct dom_sid *device_sid = &device_sids[i].sid;
-
- device_sids_are_valid = device_sids_are_valid || dom_sid_equal(
- device_sid, &global_sid_Claims_Valid);
-
- ptoken->device_sids = talloc_realloc(ptoken,
- ptoken->device_sids,
- struct dom_sid,
- ptoken->num_device_sids + 1);
- if (ptoken->device_sids == NULL) {
- talloc_free(ptoken);
- return NT_STATUS_NO_MEMORY;
- }
-
- ptoken->device_sids[ptoken->num_device_sids] = *device_sid;
- ptoken->num_device_sids++;
+ sorted_device_sids = talloc_array(tmp_ctx, struct dom_sid,
+ num_device_sids > 0 ? num_device_sids : 1);
+ if (sorted_device_sids == NULL) {
+ talloc_free(tmp_ctx);
+ talloc_free(ptoken);
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i = 0; i < num_device_sids; i++) {
+ const struct dom_sid *device_sid = &device_sids[i].sid;
+ uint32_t new_dev_count;
+
+ new_dev_count = sid_sorted_insert_unique(sorted_device_sids,
+ sorted_device_count,
+ device_sid);
+ if (new_dev_count == sorted_device_count) {
+ continue; /* duplicate */
}
+ sorted_device_count = new_dev_count;
+
+ device_sids_are_valid = device_sids_are_valid || dom_sid_equal(
+ device_sid, &global_sid_Claims_Valid);
+
+ ptoken->device_sids = talloc_realloc(ptoken,
+ ptoken->device_sids,
+ struct dom_sid,
+ ptoken->num_device_sids + 1);
+ if (ptoken->device_sids == NULL) {
+ talloc_free(tmp_ctx);
+ talloc_free(ptoken);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ptoken->device_sids[ptoken->num_device_sids] = *device_sid;
+ ptoken->num_device_sids++;
}
}
+ /*
+ * Sort ptoken->sids[REMAINING_SIDS_INDEX..] so security_token_has_sid
+ * can use bsearch for O(log S) access checks (samba-0001 companion fix).
+ */
+ security_token_sort_sids(ptoken);
+