diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-06-04 14:07:35 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-06-04 14:10:11 +1000 |
commit | dfd56dd29415b06b5ea137f8c333da42e8ff1aa6 (patch) | |
tree | 487d0e8f42b6f2c39b15fcea4a1ae52b60518a6b | |
parent | 0849c1ef77a0538d5d232016a51c002e2197e776 (diff) | |
download | samba-dfd56dd29415b06b5ea137f8c333da42e8ff1aa6.tar.gz samba-dfd56dd29415b06b5ea137f8c333da42e8ff1aa6.tar.bz2 samba-dfd56dd29415b06b5ea137f8c333da42e8ff1aa6.zip |
changed the auth path to use extended DN ops to avoid non-indexed searches
Logs showed that every SAM authentication was causing a non-indexed
ldb search for member=XXX. This was previously indexed in Samba4, but
since we switched to using the indexes from the full AD schema it now
isn't.
The fix is to use the extended DN operations to allow us to ask the
server for the memberOf attribute instead, with with the SIDs attached
to the result. This also means one less search on every
authentication.
The patch is made more complex by the fact that some common routines
use the result of these user searches, so we had to update all
searches that uses user_attrs and those common routines to make sure
they all returned a ldb_message with a memberOf filled in and the SIDs
attached.
-rw-r--r-- | source4/auth/ntlm/auth_sam.c | 47 | ||||
-rw-r--r-- | source4/auth/sam.c | 84 | ||||
-rw-r--r-- | source4/kdc/hdb-samba4.c | 52 |
3 files changed, 91 insertions, 92 deletions
diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index 75ed3243d4..0bb79e234c 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -43,32 +43,23 @@ extern const char *domain_ref_attrs[]; static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, const char *account_name, struct ldb_dn *domain_dn, - struct ldb_message ***ret_msgs) + struct ldb_message **ret_msg) { - struct ldb_message **msgs; - int ret; /* pull the user attributes */ - ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, user_attrs, - "(&(sAMAccountName=%s)(objectclass=user))", - ldb_binary_encode_string(mem_ctx, account_name)); - if (ret == -1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - if (ret == 0) { + ret = gendb_search_single_extended_dn(sam_ctx, mem_ctx, domain_dn, LDB_SCOPE_SUBTREE, + ret_msg, user_attrs, + "(&(sAMAccountName=%s)(objectclass=user))", + ldb_binary_encode_string(mem_ctx, account_name)); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { DEBUG(3,("sam_search_user: Couldn't find user [%s] in samdb, under %s\n", account_name, ldb_dn_get_linearized(domain_dn))); - return NT_STATUS_NO_SUCH_USER; + return NT_STATUS_NO_SUCH_USER; } - - if (ret > 1) { - DEBUG(0,("Found %d records matching user [%s]\n", ret, account_name)); + if (ret != LDB_SUCCESS) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - - *ret_msgs = msgs; return NT_STATUS_OK; } @@ -147,14 +138,14 @@ static NTSTATUS authsam_password_ok(struct auth_context *auth_context, static NTSTATUS authsam_authenticate(struct auth_context *auth_context, TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, struct ldb_dn *domain_dn, - struct ldb_message **msgs, + struct ldb_message *msg, const struct auth_usersupplied_info *user_info, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { struct samr_Password *lm_pwd, *nt_pwd; NTSTATUS nt_status; - uint16_t acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msgs[0], domain_dn); + uint16_t acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, domain_dn); /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { @@ -170,7 +161,7 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context, } } - nt_status = samdb_result_passwords(mem_ctx, auth_context->lp_ctx, msgs[0], &lm_pwd, &nt_pwd); + nt_status = samdb_result_passwords(mem_ctx, auth_context->lp_ctx, msg, &lm_pwd, &nt_pwd); NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = authsam_password_ok(auth_context, mem_ctx, @@ -181,7 +172,7 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context, nt_status = authsam_account_ok(mem_ctx, sam_ctx, user_info->logon_parameters, domain_dn, - msgs[0], + msg, user_info->workstation_name, user_info->mapped.account_name, false); @@ -198,7 +189,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx { NTSTATUS nt_status; const char *account_name = user_info->mapped.account_name; - struct ldb_message **msgs; + struct ldb_message *msg; struct ldb_context *sam_ctx; struct ldb_dn *domain_dn; DATA_BLOB user_sess_key, lm_sess_key; @@ -226,13 +217,13 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx return NT_STATUS_NO_SUCH_DOMAIN; } - nt_status = authsam_search_account(tmp_ctx, sam_ctx, account_name, domain_dn, &msgs); + nt_status = authsam_search_account(tmp_ctx, sam_ctx, account_name, domain_dn, &msg); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } - nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, sam_ctx, domain_dn, msgs, user_info, + nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, sam_ctx, domain_dn, msg, user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); @@ -242,7 +233,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx nt_status = authsam_make_server_info(tmp_ctx, sam_ctx, lp_netbios_name(ctx->auth_ctx->lp_ctx), lp_sam_name(ctx->auth_ctx->lp_ctx), domain_dn, - msgs[0], + msg, user_sess_key, lm_sess_key, server_info); if (!NT_STATUS_IS_OK(nt_status)) { @@ -322,7 +313,7 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, DATA_BLOB user_sess_key = data_blob(NULL, 0); DATA_BLOB lm_sess_key = data_blob(NULL, 0); - struct ldb_message **msgs; + struct ldb_message *msg; struct ldb_context *sam_ctx; struct ldb_dn *domain_dn; @@ -339,7 +330,7 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, } nt_status = sam_get_results_principal(sam_ctx, tmp_ctx, principal, - &domain_dn, &msgs); + &domain_dn, &msg); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -348,7 +339,7 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, lp_netbios_name(auth_context->lp_ctx), lp_workgroup(auth_context->lp_ctx), domain_dn, - msgs[0], + msg, user_sess_key, lm_sess_key, server_info); if (NT_STATUS_IS_OK(nt_status)) { diff --git a/source4/auth/sam.c b/source4/auth/sam.c index c70c02cb3c..68eaacf255 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -28,6 +28,7 @@ #include "libcli/security/security.h" #include "libcli/ldap/ldap.h" #include "librpc/gen_ndr/ndr_netlogon.h" +#include "librpc/gen_ndr/ndr_security.h" #include "param/param.h" #include "auth/auth_sam.h" @@ -66,6 +67,7 @@ const char *user_attrs[] = { "badPwdCount", "logonCount", "primaryGroupID", + "memberOf", NULL, }; @@ -261,9 +263,7 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte struct auth_serversupplied_info **_server_info) { struct auth_serversupplied_info *server_info; - struct ldb_message **group_msgs; - int group_ret; - const char *group_attrs[3] = { "sAMAccountType", "objectSid", NULL }; + int group_ret = 0; /* find list of sids */ struct dom_sid **groupSIDs = NULL; struct dom_sid *account_sid; @@ -271,39 +271,48 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte const char *str; int i; uint_t rid; - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - - group_ret = gendb_search(sam_ctx, - tmp_ctx, NULL, &group_msgs, group_attrs, - "(&(member=%s)(sAMAccountType=*))", - ldb_dn_get_linearized(msg->dn)); - if (group_ret == -1) { - talloc_free(tmp_ctx); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + struct ldb_message_element *el; - server_info = talloc(mem_ctx, struct auth_serversupplied_info); - NT_STATUS_HAVE_NO_MEMORY(server_info); + server_info = talloc(tmp_ctx, struct auth_serversupplied_info); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info, tmp_ctx); - if (group_ret > 0) { + el = ldb_msg_find_element(msg, "memberOf"); + if (el != NULL) { + group_ret = el->num_values; groupSIDs = talloc_array(server_info, struct dom_sid *, group_ret); - NT_STATUS_HAVE_NO_MEMORY(groupSIDs); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupSIDs, tmp_ctx); } - /* Need to unroll some nested groups, but not aliases */ + /* TODO Note: this is incomplete. We need to unroll some + * nested groups, but not aliases */ for (i = 0; i < group_ret; i++) { - groupSIDs[i] = samdb_result_dom_sid(groupSIDs, - group_msgs[i], "objectSid"); - NT_STATUS_HAVE_NO_MEMORY(groupSIDs[i]); + struct ldb_dn *dn; + const struct ldb_val *v; + enum ndr_err_code ndr_err; + + dn = ldb_dn_from_ldb_val(tmp_ctx, sam_ctx, &el->values[i]); + if (dn == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + v = ldb_dn_get_extended_component(dn, "SID"); + groupSIDs[i] = talloc(groupSIDs, struct dom_sid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupSIDs[i], tmp_ctx); + + ndr_err = ndr_pull_struct_blob(v, groupSIDs[i], NULL, groupSIDs[i], + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } } - talloc_free(tmp_ctx); - account_sid = samdb_result_dom_sid(server_info, msg, "objectSid"); - NT_STATUS_HAVE_NO_MEMORY(account_sid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid, tmp_ctx); primary_group_sid = dom_sid_dup(server_info, account_sid); - NT_STATUS_HAVE_NO_MEMORY(primary_group_sid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_sid, tmp_ctx); rid = samdb_result_uint(msg, "primaryGroupID", ~0); if (rid == ~0) { @@ -325,30 +334,30 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte server_info->account_name = talloc_steal(server_info, samdb_result_string(msg, "sAMAccountName", NULL)); server_info->domain_name = talloc_strdup(server_info, domain_name); - NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->domain_name, tmp_ctx); str = samdb_result_string(msg, "displayName", ""); server_info->full_name = talloc_strdup(server_info, str); - NT_STATUS_HAVE_NO_MEMORY(server_info->full_name); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->full_name, tmp_ctx); str = samdb_result_string(msg, "scriptPath", ""); server_info->logon_script = talloc_strdup(server_info, str); - NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->logon_script, tmp_ctx); str = samdb_result_string(msg, "profilePath", ""); server_info->profile_path = talloc_strdup(server_info, str); - NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->profile_path, tmp_ctx); str = samdb_result_string(msg, "homeDirectory", ""); server_info->home_directory = talloc_strdup(server_info, str); - NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->home_directory, tmp_ctx); str = samdb_result_string(msg, "homeDrive", ""); server_info->home_drive = talloc_strdup(server_info, str); - NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->home_drive, tmp_ctx); server_info->logon_server = talloc_strdup(server_info, netbios_name); - NT_STATUS_HAVE_NO_MEMORY(server_info->logon_server); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_info->logon_server, tmp_ctx); server_info->last_logon = samdb_result_nttime(msg, "lastLogon", 0); server_info->last_logoff = samdb_result_nttime(msg, "lastLogoff", 0); @@ -373,7 +382,7 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte server_info->authenticated = true; - *_server_info = server_info; + *_server_info = talloc_steal(mem_ctx, server_info); return NT_STATUS_OK; } @@ -381,7 +390,7 @@ _PUBLIC_ NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_conte NTSTATUS sam_get_results_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, const char *principal, struct ldb_dn **domain_dn, - struct ldb_message ***msgs) + struct ldb_message **msg) { struct ldb_dn *user_dn; NTSTATUS nt_status; @@ -399,12 +408,13 @@ NTSTATUS sam_get_results_principal(struct ldb_context *sam_ctx, } /* pull the user attributes */ - ret = gendb_search_dn(sam_ctx, tmp_ctx, user_dn, msgs, user_attrs); - if (ret != 1) { + ret = gendb_search_single_extended_dn(sam_ctx, tmp_ctx, user_dn, LDB_SCOPE_BASE, + msg, user_attrs, "(objectClass=*)"); + if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - talloc_steal(mem_ctx, *msgs); + talloc_steal(mem_ctx, *msg); talloc_steal(mem_ctx, *domain_dn); talloc_free(tmp_ctx); diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 585285795f..28a82bcf61 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -921,18 +921,15 @@ static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_con krb5_const_principal principal, enum hdb_ldb_ent_type ent_type, struct ldb_dn *realm_dn, - struct ldb_message ***pmsg) + struct ldb_message **pmsg) { krb5_error_code ret; int lret; char *filter = NULL; const char * const *princ_attrs = user_attrs; - char *short_princ; char *short_princ_talloc; - struct ldb_result *res = NULL; - ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &short_princ); if (ret != 0) { @@ -969,19 +966,18 @@ static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_con return ENOMEM; } - lret = ldb_search(ldb_ctx, mem_ctx, &res, realm_dn, - LDB_SCOPE_SUBTREE, princ_attrs, "%s", filter); - if (lret != LDB_SUCCESS) { - DEBUG(3, ("Failed to search for %s: %s\n", filter, ldb_errstring(ldb_ctx))); + lret = gendb_search_single_extended_dn(ldb_ctx, mem_ctx, + realm_dn, LDB_SCOPE_SUBTREE, + pmsg, princ_attrs, "%s", filter); + if (lret == LDB_ERR_NO_SUCH_OBJECT) { + DEBUG(3, ("Failed find a entry for %s\n", filter)); return HDB_ERR_NOENTRY; - } else if (res->count == 0 || res->count > 1) { - DEBUG(3, ("Failed find a single entry for %s: got %d\n", filter, res->count)); - talloc_free(res); + } + if (lret != LDB_SUCCESS) { + DEBUG(3, ("Failed single search for for %s - %s\n", + filter, ldb_errstring(ldb_ctx))); return HDB_ERR_NOENTRY; } - talloc_steal(mem_ctx, res->msgs); - *pmsg = res->msgs; - talloc_free(res); return 0; } @@ -989,7 +985,7 @@ static krb5_error_code LDB_lookup_trust(krb5_context context, struct ldb_context TALLOC_CTX *mem_ctx, const char *realm, struct ldb_dn *realm_dn, - struct ldb_message ***pmsg) + struct ldb_message **pmsg) { int lret; char *filter = NULL; @@ -1015,7 +1011,7 @@ static krb5_error_code LDB_lookup_trust(krb5_context context, struct ldb_context return HDB_ERR_NOENTRY; } talloc_steal(mem_ctx, res->msgs); - *pmsg = res->msgs; + *pmsg = res->msgs[0]; talloc_free(res); return 0; } @@ -1060,7 +1056,7 @@ static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db, char *principal_string; struct ldb_dn *realm_dn; krb5_error_code ret; - struct ldb_message **msg = NULL; + struct ldb_message *msg = NULL; ret = krb5_unparse_name(context, principal, &principal_string); @@ -1082,7 +1078,7 @@ static krb5_error_code LDB_fetch_client(krb5_context context, HDB *db, ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_CLIENT, - realm_dn, msg[0], entry_ex); + realm_dn, msg, entry_ex); return ret; } @@ -1093,7 +1089,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, hdb_entry_ex *entry_ex) { krb5_error_code ret; - struct ldb_message **msg = NULL; + struct ldb_message *msg = NULL; struct ldb_dn *realm_dn = ldb_get_default_basedn(db->hdb_db); const char *realm; struct loadparm_context *lp_ctx = talloc_get_type(ldb_get_opaque(db->hdb_db, "loadparm"), struct loadparm_context); @@ -1146,7 +1142,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_KRBTGT, - realm_dn, msg[0], entry_ex); + realm_dn, msg, entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: self krbtgt message2entry failed"); } @@ -1183,7 +1179,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, ret = LDB_trust_message2entry(context, db, lp_ctx, mem_ctx, principal, direction, - realm_dn, msg[0], entry_ex); + realm_dn, msg, entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: trust_message2entry failed"); } @@ -1204,7 +1200,7 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, { krb5_error_code ret; const char *realm; - struct ldb_message **msg = NULL; + struct ldb_message *msg = NULL; struct ldb_dn *realm_dn; if (principal->name.name_string.len >= 2) { /* 'normal server' case */ @@ -1232,10 +1228,12 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, return HDB_ERR_NOENTRY; } - ldb_ret = gendb_search_dn((struct ldb_context *)db->hdb_db, - mem_ctx, user_dn, &msg, user_attrs); - - if (ldb_ret != 1) { + ldb_ret = gendb_search_single_extended_dn((struct ldb_context *)db->hdb_db, + mem_ctx, + user_dn, LDB_SCOPE_BASE, + &msg, user_attrs, + "(objectClass=*)"); + if (ldb_ret != LDB_SUCCESS) { return HDB_ERR_NOENTRY; } @@ -1257,7 +1255,7 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, ret = LDB_message2entry(context, db, mem_ctx, principal, HDB_SAMBA4_ENT_TYPE_SERVER, - realm_dn, msg[0], entry_ex); + realm_dn, msg, entry_ex); if (ret != 0) { krb5_warnx(context, "LDB_fetch: message2entry failed"); } |