From ece6eae4d8862a564c581a3f3808c04edab6cb19 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Dec 2010 17:17:07 +1100 Subject: [PATCH] s4-auth Add function to obtain any user's session_info from a given LDB This will be a building block for a tokenGroups test, which can compare against a remote server (in particular the rootDSE) against what we would calculate the tokenGroups to be. (this meant moving some parts out of the auth_sam code into the containing library) Andrew Bartlett --- source4/auth/ntlm/auth_sam.c | 87 ++++-------------------------------- source4/auth/pyauth.c | 64 +++++++++++++++++++++++++- source4/auth/sam.c | 84 ++++++++++++++++++++++++++++++++++ source4/auth/session.c | 39 ++++++++++++++++ source4/auth/session.h | 14 ++++++ source4/auth/wscript_build | 2 +- 6 files changed, 209 insertions(+), 81 deletions(-) diff --git a/source4/auth/ntlm/auth_sam.c b/source4/auth/ntlm/auth_sam.c index 259efec8e5b..645713286d0 100644 --- a/source4/auth/ntlm/auth_sam.c +++ b/source4/auth/ntlm/auth_sam.c @@ -353,87 +353,16 @@ 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, 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) +/* Wrapper for the auth subsystem pointer */ +NTSTATUS authsam_get_server_info_principal_wrapper(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; - DATA_BLOB user_sess_key = data_blob(NULL, 0); - DATA_BLOB lm_sess_key = data_blob(NULL, 0); - - struct ldb_message *msg; - struct ldb_dn *domain_dn; - - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) { - return NT_STATUS_NO_MEMORY; - } - - 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; - } - - 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, auth_context->sam_ctx, - lpcfg_netbios_name(auth_context->lp_ctx), - lpcfg_workgroup(auth_context->lp_ctx), - domain_dn, - msg, - user_sess_key, lm_sess_key, - server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(tmp_ctx); - return nt_status; - } - - talloc_steal(mem_ctx, *server_info); - talloc_free(tmp_ctx); - - return NT_STATUS_OK; + return authsam_get_server_info_principal(mem_ctx, auth_context->lp_ctx, auth_context->sam_ctx, + principal, user_dn, server_info); } - static const struct auth_operations sam_ignoredomain_ops = { .name = "sam_ignoredomain", .get_challenge = auth_get_challenge_not_implemented, diff --git a/source4/auth/pyauth.c b/source4/auth/pyauth.c index 2ef5ebb8829..f8bf4d98629 100644 --- a/source4/auth/pyauth.c +++ b/source4/auth/pyauth.c @@ -18,13 +18,15 @@ #include #include "includes.h" +#include "libcli/util/pyerrors.h" #include "param/param.h" #include "pyauth.h" +#include "pyldb.h" #include "auth/system_session_proto.h" +#include "auth/session.h" #include "param/pyparam.h" #include "libcli/security/security.h" - static PyTypeObject PyAuthSession = { .tp_name = "AuthSession", .tp_basicsize = sizeof(py_talloc_Object), @@ -102,9 +104,69 @@ static PyObject *py_admin_session(PyObject *module, PyObject *args) return PyAuthSession_FromSession(session); } +static PyObject *py_user_session(PyObject *module, PyObject *args, PyObject *kwargs) +{ + NTSTATUS nt_status; + struct auth_session_info *session; + TALLOC_CTX *mem_ctx; + const char * const kwnames[] = { "ldb", "lp_ctx", "principal", "dn", "session_info_flags" }; + struct ldb_context *ldb_ctx; + PyObject *py_ldb = Py_None; + PyObject *py_dn = Py_None; + PyObject *py_lp_ctx = Py_None; + struct loadparm_context *lp_ctx = NULL; + struct ldb_dn *user_dn; + char *principal = NULL; + int session_info_flags; /* This is an int, because that's what + * we need for the python + * PyArg_ParseTupleAndKeywords */ + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OzOi", + discard_const_p(char *, kwnames), + &py_ldb, &py_lp_ctx, &principal, &py_dn, &session_info_flags)) { + return NULL; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + PyErr_NoMemory(); + return NULL; + } + + ldb_ctx = PyLdb_AsLdbContext(py_ldb); + + if (py_dn == Py_None) { + user_dn = NULL; + } else { + if (!PyObject_AsDn(ldb_ctx, py_dn, ldb_ctx, &user_dn)) { + talloc_free(mem_ctx); + return NULL; + } + } + + lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); + if (lp_ctx == NULL) { + talloc_free(mem_ctx); + return NULL; + } + + nt_status = authsam_get_session_info_principal(mem_ctx, lp_ctx, ldb_ctx, principal, user_dn, + session_info_flags, &session); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + PyErr_NTSTATUS_IS_ERR_RAISE(nt_status); + } + + talloc_steal(NULL, session); + talloc_free(mem_ctx); + + return PyAuthSession_FromSession(session); +} + static PyMethodDef py_auth_methods[] = { { "system_session", (PyCFunction)py_system_session, METH_VARARGS, NULL }, { "admin_session", (PyCFunction)py_admin_session, METH_VARARGS, NULL }, + { "user_session", (PyCFunction)py_user_session, METH_VARARGS, NULL }, { NULL }, }; diff --git a/source4/auth/sam.c b/source4/auth/sam.c index fcb125660b3..0a97d81b828 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -28,6 +28,8 @@ #include "libcli/security/security.h" #include "auth/auth_sam.h" #include "dsdb/common/util.h" +#include "libcli/ldap/ldap_ndr.h" +#include "param/param.h" #define KRBTGT_ATTRS \ /* required for the krb5 kdc */ \ @@ -503,3 +505,85 @@ NTSTATUS sam_get_results_principal(struct ldb_context *sam_ctx, return NT_STATUS_OK; } + +/* 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 loadparm_context *lp_ctx, + struct ldb_context *sam_ctx, + const char *principal, + struct ldb_dn *user_dn, + struct auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status; + DATA_BLOB user_sess_key = data_blob(NULL, 0); + DATA_BLOB lm_sess_key = data_blob(NULL, 0); + + struct ldb_message *msg; + struct ldb_dn *domain_dn; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NT_STATUS_NO_MEMORY; + } + + if (principal) { + 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; + } + } else if (user_dn) { + struct dom_sid *user_sid, *domain_sid; + int ret; + /* pull the user attributes */ + ret = dsdb_search_one(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; + } + + 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(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, + lpcfg_netbios_name(lp_ctx), + lpcfg_workgroup(lp_ctx), + domain_dn, + msg, + user_sess_key, lm_sess_key, + server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return nt_status; + } + + talloc_steal(mem_ctx, *server_info); + talloc_free(tmp_ctx); + + return NT_STATUS_OK; +} diff --git a/source4/auth/session.c b/source4/auth/session.c index c4bd351b0e5..124fdb989b8 100644 --- a/source4/auth/session.c +++ b/source4/auth/session.c @@ -23,6 +23,7 @@ #include "includes.h" #include "auth/auth.h" +#include "auth/auth_sam.h" #include "libcli/security/security.h" #include "libcli/auth/libcli_auth.h" #include "dsdb/samdb/samdb.h" @@ -195,6 +196,44 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/* Produce a session_info for an arbitary DN or principal in the local + * DB, assuming the local DB holds all the groups + * + * Supply either a principal or a DN + */ +NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx, + struct ldb_context *sam_ctx, + const char *principal, + struct ldb_dn *user_dn, + uint32_t session_info_flags, + struct auth_session_info **session_info) +{ + NTSTATUS nt_status; + struct auth_serversupplied_info *server_info; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NT_STATUS_NO_MEMORY; + } + nt_status = authsam_get_server_info_principal(tmp_ctx, lp_ctx, sam_ctx, + principal, user_dn, + &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return nt_status; + } + + nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx, + server_info, session_info_flags, + session_info); + + if (NT_STATUS_IS_OK(nt_status)) { + talloc_steal(mem_ctx, *session_info); + } + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + /** * prints a struct auth_session_info security token to debug output. */ diff --git a/source4/auth/session.h b/source4/auth/session.h index 39c818fbf23..caedbc80288 100644 --- a/source4/auth/session.h +++ b/source4/auth/session.h @@ -30,7 +30,9 @@ struct auth_session_info { #include "librpc/gen_ndr/netlogon.h" +struct tevent_context; struct ldb_context; +struct ldb_dn; /* Create a security token for a session SYSTEM (the most * trusted/prvilaged account), including the local machine account as * the off-host credentials */ @@ -48,6 +50,18 @@ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, struct loadparm_context *lp_ctx, struct auth_session_info **_session_info); +/* Produce a session_info for an arbitary DN or principal in the local + * DB, assuming the local DB holds all the groups + * + * Supply either a principal or a DN + */ +NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx, + struct loadparm_context *lp_ctx, + struct ldb_context *sam_ctx, + const char *principal, + struct ldb_dn *user_dn, + uint32_t session_info_flags, + struct auth_session_info **session_info); struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx); diff --git a/source4/auth/wscript_build b/source4/auth/wscript_build index 700a4a9ae4d..0111774d2e9 100644 --- a/source4/auth/wscript_build +++ b/source4/auth/wscript_build @@ -48,7 +48,7 @@ bld.SAMBA_SUBSYSTEM('auth_sam_reply', bld.SAMBA_PYTHON('pyauth', source='pyauth.c', public_deps='auth_system_session', - deps='samdb pytalloc-util pyparam_util', + deps='samdb pytalloc-util pyparam_util pyldb-util', realname='samba/auth.so' ) -- 2.34.1