From 72ccbcacddd2c3fdc6bfb61b8efb78625368365d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 15 Apr 2010 11:58:05 +1000 Subject: s4:auth Allow the operational module to get a user's tokenGroups from auth This creates a new interface to the auth subsystem, to allow an auth_context to be created from the ldb, and then tokenGroups to be calculated in the same way that the auth subsystem would. Andrew Bartlett --- source4/auth/auth.h | 13 +++-- source4/auth/gensec/gensec_gssapi.c | 1 + source4/auth/gensec/gensec_krb5.c | 2 +- source4/auth/ntlm/auth.c | 96 ++++++++++++++++++++++++++++--------- source4/auth/ntlm/auth_sam.c | 60 +++++++++++++++++------ 5 files changed, 131 insertions(+), 41 deletions(-) (limited to 'source4/auth') diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 3984704928..2678d2ca66 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -127,6 +127,7 @@ struct auth_method_context; struct auth_check_password_request; struct auth_context; struct auth_session_info; +struct ldb_dn; struct auth_operations { const char *name; @@ -153,6 +154,7 @@ struct auth_operations { NTSTATUS (*get_server_info_principal)(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, const char *principal, + struct ldb_dn *user_dn, struct auth_serversupplied_info **server_info); }; @@ -201,9 +203,10 @@ struct auth_context { NTSTATUS (*set_challenge)(struct auth_context *auth_ctx, const uint8_t chal[8], const char *set_by); NTSTATUS (*get_server_info_principal)(TALLOC_CTX *mem_ctx, - struct auth_context *auth_context, - const char *principal, - struct auth_serversupplied_info **server_info); + struct auth_context *auth_ctx, + const char *principal, + struct ldb_dn *user_dn, + struct auth_serversupplied_info **server_info); NTSTATUS (*generate_session_info)(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, @@ -231,7 +234,6 @@ struct auth_critical_sizes { struct ldb_message; struct ldb_context; -struct ldb_dn; struct gensec_security; NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, uint8_t chal[8]); @@ -265,6 +267,7 @@ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **methods, struct tevent_context *ev, struct messaging_context *msg, struct loadparm_context *lp_ctx, + struct ldb_context *sam_ctx, struct auth_context **auth_ctx); NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, @@ -272,6 +275,7 @@ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, struct messaging_context *msg, struct loadparm_context *lp_ctx, struct auth_context **auth_ctx); +NTSTATUS auth_context_create_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct auth_context **auth_ctx); NTSTATUS auth_check_password(struct auth_context *auth_ctx, TALLOC_CTX *mem_ctx, @@ -302,6 +306,7 @@ NTSTATUS auth_context_set_challenge(struct auth_context *auth_ctx, const uint8_t NTSTATUS auth_get_server_info_principal(TALLOC_CTX *mem_ctx, struct auth_context *auth_ctx, const char *principal, + struct ldb_dn *user_dn, struct auth_serversupplied_info **server_info); NTSTATUS samba_server_gensec_start(TALLOC_CTX *mem_ctx, diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 73c12a20ff..4aaae6cdad 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -1308,6 +1308,7 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi nt_status = gensec_security->auth_context->get_server_info_principal(mem_ctx, gensec_security->auth_context, principal_string, + NULL, &server_info); if (!NT_STATUS_IS_OK(nt_status)) { diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index 77b50cb41c..a0d880f5b2 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -653,7 +653,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security nt_status = gensec_security->auth_context->get_server_info_principal(mem_ctx, gensec_security->auth_context, principal_string, - &server_info); + NULL, &server_info); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c index e9e72fa2a5..b5f3afc86d 100644 --- a/source4/auth/ntlm/auth.c +++ b/source4/auth/ntlm/auth.c @@ -98,13 +98,16 @@ _PUBLIC_ NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, uint8_t chal } /**************************************************************************** - Try to get a challenge out of the various authentication modules. - Returns a const char of length 8 bytes. +Used in the gensec_gssapi and gensec_krb5 server-side code, where the +PAC isn't available, and for tokenGroups in the DSDB stack. + + Supply either a principal or a DN ****************************************************************************/ _PUBLIC_ NTSTATUS auth_get_server_info_principal(TALLOC_CTX *mem_ctx, - struct auth_context *auth_ctx, - const char *principal, - struct auth_serversupplied_info **server_info) + struct auth_context *auth_ctx, + const char *principal, + struct ldb_dn *user_dn, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct auth_method_context *method; @@ -114,7 +117,7 @@ _PUBLIC_ NTSTATUS auth_get_server_info_principal(TALLOC_CTX *mem_ctx, continue; } - nt_status = method->ops->get_server_info_principal(mem_ctx, auth_ctx, principal, server_info); + nt_status = method->ops->get_server_info_principal(mem_ctx, auth_ctx, principal, user_dn, server_info); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) { continue; } @@ -399,13 +402,14 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req, /*************************************************************************** Make a auth_info struct for the auth subsystem - - Allow the caller to specify the methods to use + - Allow the caller to specify the methods to use, including optionally the SAM to use ***************************************************************************/ _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **methods, - struct tevent_context *ev, - struct messaging_context *msg, - struct loadparm_context *lp_ctx, - struct auth_context **auth_ctx) + struct tevent_context *ev, + struct messaging_context *msg, + struct loadparm_context *lp_ctx, + struct ldb_context *sam_ctx, + struct auth_context **auth_ctx) { int i; struct auth_context *ctx; @@ -437,7 +441,11 @@ _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char ** ctx->msg_ctx = msg; ctx->lp_ctx = lp_ctx; - ctx->sam_ctx = samdb_connect(ctx, ctx->event_ctx, ctx->lp_ctx, system_session(ctx->lp_ctx)); + if (sam_ctx) { + ctx->sam_ctx = sam_ctx; + } else { + ctx->sam_ctx = samdb_connect(ctx, ctx->event_ctx, ctx->lp_ctx, system_session(ctx->lp_ctx)); + } for (i=0; methods[i] ; i++) { struct auth_method_context *method; @@ -471,15 +479,8 @@ _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char ** return NT_STATUS_OK; } -/*************************************************************************** - Make a auth_info struct for the auth subsystem - - Uses default auth_methods, depending on server role and smb.conf settings -***************************************************************************/ -_PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct messaging_context *msg, - struct loadparm_context *lp_ctx, - struct auth_context **auth_ctx) + +static const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx) { const char **auth_methods = NULL; switch (lp_server_role(lp_ctx)) { @@ -493,9 +494,60 @@ _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, auth_methods = lp_parm_string_list(mem_ctx, lp_ctx, NULL, "auth methods", "domain controller", NULL); break; } - return auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, auth_ctx); + return auth_methods; } +/*************************************************************************** + Make a auth_info struct for the auth subsystem + - Uses default auth_methods, depending on server role and smb.conf settings +***************************************************************************/ +_PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct messaging_context *msg, + struct loadparm_context *lp_ctx, + struct auth_context **auth_ctx) +{ + NTSTATUS status; + const char **auth_methods; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NT_STATUS_NO_MEMORY; + } + + auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx); + if (!auth_methods) { + return NT_STATUS_INVALID_PARAMETER; + } + status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx); + talloc_free(tmp_ctx); + return status; +} + +/* Create an auth context from an open LDB. + + This allows us not to re-open the LDB when we need to do a some authentication logic (such as tokenGroups) + + */ +NTSTATUS auth_context_create_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct auth_context **auth_ctx) +{ + NTSTATUS status; + const char **auth_methods; + struct loadparm_context *lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"), struct loadparm_context); + struct tevent_context *ev = ldb_get_event_context(ldb); + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NT_STATUS_NO_MEMORY; + } + + auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx); + if (!auth_methods) { + return NT_STATUS_INVALID_PARAMETER; + } + status = auth_context_create_methods(mem_ctx, auth_methods, ev, NULL, lp_ctx, ldb, auth_ctx); + talloc_free(tmp_ctx); + return status; +} /* the list of currently registered AUTH backends */ static struct auth_backend { diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index e4e56e1219..6d1ed0ea10 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -23,6 +23,8 @@ #include "system/time.h" #include "lib/ldb/include/ldb.h" #include "../lib/util/util_ldb.h" +#include "libcli/ldap/ldap_ndr.h" +#include "libcli/security/security.h" #include "auth/auth.h" #include "../libcli/auth/ntlm_check.h" #include "auth/ntlm/auth_proto.h" @@ -300,10 +302,14 @@ static NTSTATUS authsam_want_check(struct auth_method_context *ctx, } -/* Used in the gensec_gssapi and gensec_krb5 server-side code, where the PAC isn't available */ +/* Used in the gensec_gssapi and gensec_krb5 server-side code, where the PAC isn't available, and for tokenGroups in the DSDB stack. + + Supply either a principal or a DN +*/ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, const char *principal, + struct ldb_dn *user_dn, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; @@ -311,7 +317,6 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, DATA_BLOB lm_sess_key = data_blob(NULL, 0); struct ldb_message *msg; - struct ldb_context *sam_ctx; struct ldb_dn *domain_dn; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); @@ -319,21 +324,48 @@ NTSTATUS authsam_get_server_info_principal(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - sam_ctx = samdb_connect(tmp_ctx, auth_context->event_ctx, auth_context->lp_ctx, - system_session(auth_context->lp_ctx)); - if (sam_ctx == NULL) { - talloc_free(tmp_ctx); - return NT_STATUS_INVALID_SYSTEM_SERVICE; - } + if (principal) { + nt_status = sam_get_results_principal(auth_context->sam_ctx, tmp_ctx, principal, + user_attrs, &domain_dn, &msg); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return nt_status; + } + } else if (user_dn) { + struct dom_sid *user_sid, *domain_sid; + int ret; + /* pull the user attributes */ + ret = dsdb_search_one(auth_context->sam_ctx, tmp_ctx, &msg, user_dn, + LDB_SCOPE_BASE, user_attrs, DSDB_SEARCH_SHOW_EXTENDED_DN, "(objectClass=*)"); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_SUCH_USER; + } else if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } - nt_status = sam_get_results_principal(sam_ctx, tmp_ctx, principal, - user_attrs, &domain_dn, &msg); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(tmp_ctx); - return nt_status; + user_sid = samdb_result_dom_sid(msg, msg, "objectSid"); + + nt_status = dom_sid_split_rid(tmp_ctx, user_sid, &domain_sid, NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + domain_dn = samdb_search_dn(auth_context->sam_ctx, mem_ctx, NULL, + "(&(objectSid=%s)(objectClass=domain))", + ldap_encode_ndr_dom_sid(tmp_ctx, domain_sid)); + if (!domain_dn) { + DEBUG(3, ("authsam_get_server_info_principal: Failed to find domain with: SID %s\n", + dom_sid_string(tmp_ctx, domain_sid))); + return NT_STATUS_NO_SUCH_USER; + } + + } else { + return NT_STATUS_INVALID_PARAMETER; } - nt_status = authsam_make_server_info(tmp_ctx, sam_ctx, + nt_status = authsam_make_server_info(tmp_ctx, auth_context->sam_ctx, lp_netbios_name(auth_context->lp_ctx), lp_workgroup(auth_context->lp_ctx), domain_dn, -- cgit