From 46a32687da249174a666d9166fccbe705c8beba0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 9 Jan 2005 12:55:25 +0000 Subject: r4620: - add interface functions to the auth subsystem so that callers doesn't need to use function pointers anymore - make the module init much easier - a lot of cleanups don't try to read the diff in auth/ better read the new files it passes test_echo.sh and test_rpc.sh abartlet: please fix spelling fixes metze (This used to be commit 3c0d16b8236451f2cfd38fc3db8ae2906106d847) --- source4/auth/auth.c | 403 +++++++++------------------- source4/auth/auth.h | 121 ++++----- source4/auth/auth_anonymous.c | 127 +++++++++ source4/auth/auth_builtin.c | 260 ------------------ source4/auth/auth_developer.c | 192 ++++++++++++++ source4/auth/auth_sam.c | 575 +++++++++++++++++++--------------------- source4/auth/auth_util.c | 595 +++++++++++++++++------------------------- source4/auth/auth_winbind.c | 101 +++---- source4/auth/config.mk | 25 +- 9 files changed, 1038 insertions(+), 1361 deletions(-) create mode 100644 source4/auth/auth_anonymous.c delete mode 100644 source4/auth/auth_builtin.c create mode 100644 source4/auth/auth_developer.c (limited to 'source4/auth') diff --git a/source4/auth/auth.c b/source4/auth/auth.c index 33f3020382..674e9a7f46 100644 --- a/source4/auth/auth.c +++ b/source4/auth/auth.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Password and authentication handling Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Stefan Metzmacher 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,111 +23,82 @@ #include "dlinklist.h" #include "auth/auth.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH +/*************************************************************************** + Set a fixed challenge +***************************************************************************/ +NTSTATUS auth_context_set_challenge(struct auth_context *auth_ctx, const uint8_t chal[8], const char *set_by) +{ + auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by); + NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by); + + auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8); + NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data); + + return NT_STATUS_OK; +} + +/*************************************************************************** + Set a fixed challenge +***************************************************************************/ +BOOL auth_challenge_may_be_modified(struct auth_context *auth_ctx) +{ + return auth_ctx->challenge.may_be_modified; +} /**************************************************************************** Try to get a challenge out of the various authentication modules. Returns a const char of length 8 bytes. ****************************************************************************/ - -static const uint8_t *get_ntlm_challenge(struct auth_context *auth_context) +NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, const uint8_t **_chal) { - DATA_BLOB challenge = data_blob(NULL, 0); - const char *challenge_set_by = NULL; - struct auth_methods *auth_method; - TALLOC_CTX *mem_ctx; - - if (auth_context->challenge.length) { - DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", - auth_context->challenge_set_by)); - return auth_context->challenge.data; + NTSTATUS nt_status; + struct auth_method_context *method; + + if (auth_ctx->challenge.data.length) { + DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n", + auth_ctx->challenge.set_by)); + *_chal = auth_ctx->challenge.data.data; + return NT_STATUS_OK; } - auth_context->challenge_may_be_modified = False; + for (method = auth_ctx->methods; method; method = method->next) { + DATA_BLOB challenge = data_blob(NULL,0); - for (auth_method = auth_context->auth_method_list; auth_method; auth_method = auth_method->next) { - if (auth_method->get_chal == NULL) { - DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name)); + nt_status = method->ops->get_challenge(method, auth_ctx, &challenge); + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) { continue; } - DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name)); - if (challenge_set_by != NULL) { - DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authentication method %s has already specified a challenge. Challenge by %s ignored.\n", - challenge_set_by, auth_method->name)); - continue; - } + NT_STATUS_NOT_OK_RETURN(nt_status); - mem_ctx = talloc_init("auth_get_challenge for module %s", auth_method->name); - if (!mem_ctx) { - smb_panic("talloc_init() failed!"); + if (challenge.length != 8) { + DEBUG(0, ("auth_get_challenge: invalid challenge (length %u) by mothod [%s]\n", + challenge.length, method->ops->name)); + return NT_STATUS_INTERNAL_ERROR; } - - challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx); - if (!challenge.length) { - DEBUG(3, ("auth_get_challenge: getting challenge from authentication method %s FAILED.\n", - auth_method->name)); - } else { - DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name)); - auth_context->challenge = challenge; - challenge_set_by = auth_method->name; - auth_context->challenge_set_method = auth_method; - } - talloc_destroy(mem_ctx); - } - - if (!challenge_set_by) { - uint8_t chal[8]; - - generate_random_buffer(chal, sizeof(chal)); - auth_context->challenge = data_blob_talloc(auth_context, - chal, sizeof(chal)); - - challenge_set_by = "random"; - auth_context->challenge_may_be_modified = True; - } - - DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by)); - DEBUG(5, ("challenge is: \n")); - dump_data(5, auth_context->challenge.data, auth_context->challenge.length); - - SMB_ASSERT(auth_context->challenge.length == 8); - auth_context->challenge_set_by=challenge_set_by; + auth_ctx->challenge.data = challenge; + auth_ctx->challenge.set_by = method->ops->name; - return auth_context->challenge.data; -} + break; + } + if (!auth_ctx->challenge.set_by) { + uint8_t chal[8]; + generate_random_buffer(chal, 8); -/** - * Check user is in correct domain (if required) - * - * @param user Only used to fill in the debug message - * - * @param domain The domain to be verified - * - * @return True if the user can connect with that domain, - * False otherwise. -**/ + auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8); + NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data); + auth_ctx->challenge.set_by = "random"; -static BOOL check_domain_match(const char *user, const char *domain) -{ - /* - * If we aren't serving to trusted domains, we must make sure that - * the validation request comes from an account in the same domain - * as the Samba server - */ - - if (!lp_allow_trusted_domains() && - !(strequal("", domain) || - strequal(lp_workgroup(), domain) || - is_myname(domain))) { - DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); - return False; - } else { - return True; + auth_ctx->challenge.may_be_modified = True; } + + DEBUG(10,("auth_get_challenge: challenge set by %s\n", + auth_ctx->challenge.set_by)); + + *_chal = auth_ctx->challenge.data.data; + return NT_STATUS_OK; } /** @@ -154,41 +126,38 @@ static BOOL check_domain_match(const char *user, const char *domain) * **/ -static NTSTATUS check_ntlm_password(struct auth_context *auth_context, - const struct auth_usersupplied_info *user_info, - TALLOC_CTX *out_mem_ctx, - struct auth_serversupplied_info **server_info) +NTSTATUS auth_check_password(struct auth_context *auth_ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { /* if all the modules say 'not for me' this is reasonable */ NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; - struct auth_methods *auth_method; - TALLOC_CTX *mem_ctx; + struct auth_method_context *method; + const char *method_name = "NO METHOD"; + const uint8_t *challenge; - if (!user_info || !auth_context || !server_info) - return NT_STATUS_LOGON_FAILURE; + DEBUG(3, ("auth_check_password: Checking password for unmapped user [%s]\\[%s]@[%s]\n", + user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name)); - DEBUG(3, ("check_ntlm_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", - user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str)); + DEBUGADD(3,("auth_check_password: mapped user is: [%s]\\[%s]@[%s]\n", + user_info->domain_name, user_info->account_name, user_info->workstation_name)); - DEBUG(3, ("check_ntlm_password: mapped user is: [%s]\\[%s]@[%s]\n", - user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str)); + nt_status = auth_get_challenge(auth_ctx, &challenge); - if (auth_context->challenge.length == 0) { - /* get a challenge, if we have not asked for one yet */ - get_ntlm_challenge(auth_context); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("auth_check_password: Invalid challenge (length %u) stored for this auth context set_by %s - cannot continue: %s\n", + auth_ctx->challenge.data.length, auth_ctx->challenge.set_by, nt_errstr(nt_status))); + return nt_status; } - if (auth_context->challenge.length != 8) { - DEBUG(0, ("check_ntlm_password: Invalid challenge stored for this auth context - cannot continue\n")); - return NT_STATUS_LOGON_FAILURE; + if (auth_ctx->challenge.set_by) { + DEBUG(10, ("auth_check_password: auth_context challenge created by %s\n", + auth_ctx->challenge.set_by)); } - if (auth_context->challenge_set_by) - DEBUG(10, ("check_ntlm_password: auth_context challenge created by %s\n", - auth_context->challenge_set_by)); - DEBUG(10, ("challenge is: \n")); - dump_data(5, auth_context->challenge.data, auth_context->challenge.length); + dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length); #ifdef DEBUG_PASSWORD DEBUG(100, ("user_info has passwords of length %d and %d\n", @@ -199,204 +168,78 @@ static NTSTATUS check_ntlm_password(struct auth_context *auth_context, dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length); #endif - /* This needs to be sorted: If it doesn't match, what should we do? */ - if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) - return NT_STATUS_LOGON_FAILURE; - - for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) { + for (method = auth_ctx->methods; method; method = method->next) { NTSTATUS result; - - mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name, - user_info->domain.str, user_info->smb_name.str); - result = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); + result = method->ops->check_password(method, mem_ctx, user_info, server_info); /* check if the module did anything */ - if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ) { - DEBUG(10,("check_ntlm_password: %s had nothing to say\n", auth_method->name)); - talloc_destroy(mem_ctx); - continue; - } - - nt_status = result; - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n", - auth_method->name, user_info->smb_name.str)); - - /* Give the server info to the client to hold onto */ - talloc_reference(out_mem_ctx, *server_info); - } else { - DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n", - auth_method->name, user_info->smb_name.str, nt_errstr(nt_status))); - } - - talloc_destroy(mem_ctx); - - if ( NT_STATUS_IS_OK(nt_status)) - { - break; + if (!NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { + method_name = method->ops->name; + nt_status = result; + break; } - } - if (NT_STATUS_IS_OK(nt_status)) { - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG((*server_info)->guest ? 5 : 2, - ("check_ntlm_password: %sauthentication for user [%s] -> [%s] succeeded\n", - (*server_info)->guest ? "guest " : "", - user_info->smb_name.str, - user_info->internal_username.str)); - } + DEBUG(11,("auth_check_password: %s had nothing to say\n", method->ops->name)); } if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(2, ("check_ntlm_password: Authentication for user [%s] -> [%s] FAILED with error %s\n", - user_info->smb_name.str, user_info->internal_username.str, - nt_errstr(nt_status))); - ZERO_STRUCTP(server_info); - } - return nt_status; -} - -/*************************************************************************** - Clear out a auth_context, and destroy the attached TALLOC_CTX -***************************************************************************/ - -void free_auth_context(struct auth_context **auth_context) -{ - struct auth_methods *auth_method; - - if (*auth_context) { - /* Free private data of context's authentication methods */ - for (auth_method = (*auth_context)->auth_method_list; auth_method; auth_method = auth_method->next) { - if (auth_method->free_private_data) { - auth_method->free_private_data (&auth_method->private_data); - auth_method->private_data = NULL; - } - } - - talloc_free(*auth_context); - *auth_context = NULL; + DEBUG(2,("auth_check_password: %s authentication for user [%s\\%s] FAILED with error %s\n", + method_name, user_info->domain_name, user_info->account_name, + nt_errstr(nt_status))); + return nt_status; } -} -/*************************************************************************** - Make a auth_info struct -***************************************************************************/ - -static NTSTATUS make_auth_context(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) -{ - *auth_context = talloc_p(mem_ctx, struct auth_context); - if (!*auth_context) { - DEBUG(0,("make_auth_context: talloc failed!\n")); - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(*auth_context); + DEBUG(5,("auth_check_password: %s authentication for user [%s\\%s] succeeded\n", + method_name, (*server_info)->domain_name, (*server_info)->account_name)); - (*auth_context)->check_ntlm_password = check_ntlm_password; - (*auth_context)->get_ntlm_challenge = get_ntlm_challenge; - - return NT_STATUS_OK; + return nt_status; } /*************************************************************************** Make a auth_info struct for the auth subsystem ***************************************************************************/ - -static NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx, - struct auth_context **auth_context, char **text_list) +NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, const char **methods, struct auth_context **auth_ctx) { - struct auth_methods *list = NULL; - struct auth_methods *t = NULL; - NTSTATUS nt_status; + int i; + struct auth_context *ctx; - if (!text_list) { - DEBUG(2,("make_auth_context_text_list: No auth method list!?\n")); - return NT_STATUS_UNSUCCESSFUL; + if (!methods) { + DEBUG(0,("auth_context_create: No auth method list!?\n")); + return NT_STATUS_INTERNAL_ERROR; } - - if (!NT_STATUS_IS_OK(nt_status = make_auth_context(mem_ctx, auth_context))) - return nt_status; - - for (;*text_list; text_list++) { - char *module_name = smb_xstrdup(*text_list); - char *module_params = NULL; - char *p; - const struct auth_operations *ops; - - DEBUG(5,("make_auth_context_text_list: Attempting to find an auth method to match %s\n", - *text_list)); - - p = strchr(module_name, ':'); - if (p) { - *p = 0; - module_params = p+1; - trim_string(module_params, " ", " "); - } - - trim_string(module_name, " ", " "); - - ops = auth_backend_byname(module_name); - if (!ops) { - DEBUG(5,("make_auth_context_text_list: Found auth method %s\n", *text_list)); - SAFE_FREE(module_name); - break; - } - if (NT_STATUS_IS_OK(ops->init(*auth_context, module_params, &t))) { - DEBUG(5,("make_auth_context_text_list: auth method %s has a valid init\n", - *text_list)); - DLIST_ADD_END(list, t, struct auth_methods *); - } else { - DEBUG(0,("make_auth_context_text_list: auth method %s did not correctly init\n", - *text_list)); - } - SAFE_FREE(module_name); - } - - (*auth_context)->auth_method_list = list; - - return nt_status; -} + ctx = talloc(mem_ctx, struct auth_context); + NT_STATUS_HAVE_NO_MEMORY(ctx); + ctx->challenge.set_by = NULL; + ctx->challenge.may_be_modified = False; + ctx->challenge.data = data_blob(NULL, 0); + ctx->methods = NULL; -/*************************************************************************** - Make a auth_context struct for the auth subsystem -***************************************************************************/ + for (i=0; methods[i] ; i++) { + struct auth_method_context *method; -NTSTATUS make_auth_context_subsystem(TALLOC_CTX *mem_ctx, struct auth_context **auth_context) -{ - char **auth_method_list = NULL; - NTSTATUS nt_status; + method = talloc(ctx, struct auth_method_context); + NT_STATUS_HAVE_NO_MEMORY(method); - if (lp_auth_methods() && !str_list_copy(&auth_method_list, lp_auth_methods())) { - return NT_STATUS_NO_MEMORY; + method->ops = auth_backend_byname(methods[i]); + if (!method->ops) { + DEBUG(1,("auth_context_create: failed to find method=%s\n", + methods[i])); + return NT_STATUS_INTERNAL_ERROR; + } + method->auth_ctx = ctx; + method->depth = i; + DLIST_ADD_END(ctx->methods, method, struct auth_method_context *); } - nt_status = make_auth_context_text_list(mem_ctx, auth_context, auth_method_list); - if (!NT_STATUS_IS_OK(nt_status)) { - str_list_free(&auth_method_list); - return nt_status; + if (!ctx->methods) { + return NT_STATUS_INTERNAL_ERROR; } - - str_list_free(&auth_method_list); - return nt_status; -} -/*************************************************************************** - Make a auth_info struct with a fixed challenge -***************************************************************************/ + *auth_ctx = ctx; -NTSTATUS make_auth_context_fixed(TALLOC_CTX *mem_ctx, - struct auth_context **auth_context, uint8_t chal[8]) -{ - NTSTATUS nt_status; - if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(mem_ctx, auth_context))) { - return nt_status; - } - - (*auth_context)->challenge = data_blob_talloc(*auth_context, chal, 8); - (*auth_context)->challenge_set_by = "fixed"; - return nt_status; + return NT_STATUS_OK; } /* the list of currently registered AUTH backends */ @@ -423,7 +266,6 @@ NTSTATUS auth_register(const void *_ops) return NT_STATUS_OBJECT_NAME_COLLISION; } - backends = realloc_p(backends, struct auth_backend, num_backends+1); if (!backends) { smb_panic("out of memory in auth_register"); @@ -468,11 +310,10 @@ const struct auth_critical_sizes *auth_interface_version(void) static const struct auth_critical_sizes critical_sizes = { AUTH_INTERFACE_VERSION, sizeof(struct auth_operations), - sizeof(struct auth_methods), + sizeof(struct auth_method_context), sizeof(struct auth_context), sizeof(struct auth_usersupplied_info), - sizeof(struct auth_serversupplied_info), - sizeof(struct auth_str), + sizeof(struct auth_serversupplied_info) }; return &critical_sizes; diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 3f1d11cb45..e78b21339f 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. Standardised Authentication types - Copyright (C) Andrew Bartlett 2001 + Copyright (C) Andrew Bartlett 2001 + Copyright (C) Stefan Metzmacher 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,50 +34,43 @@ /* version 1 - version from samba 3.0 - metze */ /* version 2 - initial samba4 version - metze */ /* version 3 - subsequent samba4 version - abartlet */ -#define AUTH_INTERFACE_VERSION 3 - -/* AUTH_STR - string */ -typedef struct auth_str -{ - int len; - char *str; -} AUTH_STR; +/* version 4 - subsequent samba4 version - metze */ +#define AUTH_INTERFACE_VERSION 4 struct auth_usersupplied_info { - + const char *account_name; + const char *domain_name; + const char *workstation_name; + + /* the values the client gives us */ + struct { + const char *account_name; + const char *domain_name; + } client; + + BOOL encrypted; + DATA_BLOB lm_resp; DATA_BLOB nt_resp; - DATA_BLOB lm_interactive_password; + DATA_BLOB lm_interactive_password; DATA_BLOB nt_interactive_password; DATA_BLOB plaintext_password; - - BOOL encrypted; - - AUTH_STR client_domain; /* domain name string */ - AUTH_STR domain; /* domain name after mapping */ - AUTH_STR internal_username; /* username after mapping */ - AUTH_STR smb_name; /* username before mapping */ - AUTH_STR wksta_name; /* workstation name (netbios calling name) unicode string */ - }; struct auth_serversupplied_info { - BOOL guest; - - struct dom_sid *user_sid; + struct dom_sid *account_sid; struct dom_sid *primary_group_sid; size_t n_domain_groups; struct dom_sid **domain_groups; - + DATA_BLOB user_session_key; DATA_BLOB lm_session_key; const char *account_name; - const char *domain; - const char *realm; + const char *domain_name; const char *full_name; const char *logon_script; @@ -90,76 +84,53 @@ struct auth_serversupplied_info NTTIME last_password_change; NTTIME allow_password_change; NTTIME force_password_change; - + uint16 logon_count; uint16 bad_password_count; - + uint32 acct_flags; + + BOOL authenticated; }; struct auth_session_info { - int refcount; struct security_token *security_token; struct auth_serversupplied_info *server_info; DATA_BLOB session_key; - - /* needed to key the schannel credentials */ - const char *workstation; }; -struct auth_context { - DATA_BLOB challenge; - - /* Who set this up in the first place? */ - const char *challenge_set_by; +struct auth_method_context; - BOOL challenge_may_be_modified; +struct auth_operations { + const char *name; - struct auth_methods *challenge_set_method; + NTSTATUS (*get_challenge)(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, DATA_BLOB *challenge); - /* methods, in the order they should be called */ - struct auth_methods *auth_method_list; - - const uint8_t *(*get_ntlm_challenge)(struct auth_context *auth_context); - NTSTATUS (*check_ntlm_password)(struct auth_context *auth_context, - const struct auth_usersupplied_info *user_info, - TALLOC_CTX *out_mem_ctx, - struct auth_serversupplied_info **server_info); - NTSTATUS (*nt_status_squash)(NTSTATUS nt_status); + NTSTATUS (*check_password)(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info); }; -struct auth_methods -{ - struct auth_methods *prev, *next; - const char *name; /* What name got this module */ - - NTSTATUS (*auth)(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info); - - DATA_BLOB (*get_chal)(const struct auth_context *auth_context, - void **my_private_data, - TALLOC_CTX *mem_ctx); - - /* Used to keep tabs on things like the cli for SMB server authentication */ +struct auth_method_context { + struct auth_method_context *prev, *next; + struct auth_context *auth_ctx; + const struct auth_operations *ops; + int depth; void *private_data; - - /* Function to clean up the above arbitary structure */ - void (*free_private_data)(void **private_data); +}; - /* Function to send a keepalive message on the above structure */ - void (*send_keepalive)(void **private_data); +struct auth_context { + struct { + /* Who set this up in the first place? */ + const char *set_by; -}; + BOOL may_be_modified; -struct auth_operations { - /* the name of the backend */ - const char *name; + DATA_BLOB data; + } challenge; - /* Function to create a member of the authmethods list */ - NTSTATUS (*init)(struct auth_context *, const char *, struct auth_methods **); + /* methods, in the order they should be called */ + struct auth_method_context *methods; }; /* this structure is used by backends to determine the size of some critical types */ diff --git a/source4/auth/auth_anonymous.c b/source4/auth/auth_anonymous.c new file mode 100644 index 0000000000..4e78e77cc3 --- /dev/null +++ b/source4/auth/auth_anonymous.c @@ -0,0 +1,127 @@ +/* + Unix SMB/CIFS implementation. + + Anonymous Authentification + + Copyright (C) Stefan Metzmacher 2004-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "auth/auth.h" +#include "librpc/gen_ndr/ndr_samr.h" +#include "librpc/gen_ndr/ndr_security.h" + +/** + * Return a anonymous logon for anonymous users (username = "") + * + * Typically used as the first module in the auth chain, this allows + * anonymou logons to be dealt with in one place. Non-anonymou logons 'fail' + * and pass onto the next module. + **/ +static NTSTATUS anonymous_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **_server_info) +{ + struct auth_serversupplied_info *server_info; + + if (user_info->account_name && *user_info->account_name) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + server_info = talloc(mem_ctx, struct auth_serversupplied_info); + NT_STATUS_HAVE_NO_MEMORY(server_info); + + server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid); + + /* is this correct? */ + server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS); + NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid); + + server_info->n_domain_groups = 0; + server_info->domain_groups = NULL; + + /* annoying, but the Anonymous really does have a session key, + and it is all zeros! */ + server_info->user_session_key = data_blob_talloc(server_info, NULL, 16); + NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data); + + server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16); + NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data); + + data_blob_clear(&server_info->user_session_key); + data_blob_clear(&server_info->lm_session_key); + + server_info->account_name = talloc_strdup(server_info, "ANONYMOUS LOGON"); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); + + server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY"); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); + + server_info->full_name = talloc_strdup(server_info, "Anonymous Logon"); + NT_STATUS_HAVE_NO_MEMORY(server_info->full_name); + + server_info->logon_script = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); + + server_info->profile_path = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); + + server_info->home_directory = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); + + server_info->home_drive = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); + + server_info->last_logon = 0; + server_info->last_logoff = 0; + server_info->acct_expiry = 0; + server_info->last_password_change = 0; + server_info->allow_password_change = 0; + server_info->force_password_change = 0; + + server_info->logon_count = 0; + server_info->bad_password_count = 0; + + server_info->acct_flags = ACB_NORMAL; + + server_info->authenticated = False; + + *_server_info = server_info; + + return NT_STATUS_OK; +} + +static struct auth_operations anonymous_auth_ops = { + .name = "anonymous", + .get_challenge = auth_get_challenge_not_implemented, + .check_password = anonymous_check_password +}; + +NTSTATUS auth_anonymous_init(void) +{ + NTSTATUS ret; + + ret = auth_register(&anonymous_auth_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register 'anonymous' auth backend!\n")); + return ret; + } + + return ret; +} diff --git a/source4/auth/auth_builtin.c b/source4/auth/auth_builtin.c deleted file mode 100644 index f3169231e8..0000000000 --- a/source4/auth/auth_builtin.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Generic authentication types - Copyright (C) Andrew Bartlett 2001-2002 - Copyright (C) Jelmer Vernooij 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "auth/auth.h" -#include "librpc/gen_ndr/ndr_samr.h" -#include "librpc/gen_ndr/ndr_security.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH - -/*************************************************************************** - Make (and fill) a user_info struct for a anonymous login. -***************************************************************************/ -static NTSTATUS make_server_info_anonymous(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **server_info) -{ - *server_info = talloc_p(mem_ctx, struct auth_serversupplied_info); - if (!*server_info) { - return NT_STATUS_NO_MEMORY; - } - - (*server_info)->guest = True; - - (*server_info)->user_sid = dom_sid_parse_talloc((*server_info), SID_NT_ANONYMOUS); - - /* is this correct? */ - (*server_info)->primary_group_sid = dom_sid_parse_talloc((*server_info), SID_BUILTIN_GUESTS); - - (*server_info)->n_domain_groups = 0; - (*server_info)->domain_groups = NULL; - - /* annoying, but the Guest really does have a session key, - and it is all zeros! */ - (*server_info)->user_session_key = data_blob_talloc(*server_info, NULL, 16); - (*server_info)->lm_session_key = data_blob_talloc(*server_info, NULL, 16); - - data_blob_clear(&(*server_info)->user_session_key); - data_blob_clear(&(*server_info)->lm_session_key); - - (*server_info)->account_name = talloc_strdup((*server_info), "ANONYMOUS LOGON"); - (*server_info)->domain = talloc_strdup((*server_info), "NT AUTHORITY"); - (*server_info)->full_name = talloc_strdup((*server_info), "Anonymous Logon"); - (*server_info)->logon_script = talloc_strdup((*server_info), ""); - (*server_info)->profile_path = talloc_strdup((*server_info), ""); - (*server_info)->home_directory = talloc_strdup((*server_info), ""); - (*server_info)->home_drive = talloc_strdup((*server_info), ""); - - (*server_info)->last_logon = 0; - (*server_info)->last_logoff = 0; - (*server_info)->acct_expiry = 0; - (*server_info)->last_password_change = 0; - (*server_info)->allow_password_change = 0; - (*server_info)->force_password_change = 0; - - (*server_info)->logon_count = 0; - (*server_info)->bad_password_count = 0; - - (*server_info)->acct_flags = ACB_NORMAL; - - return NT_STATUS_OK; -} - -/** - * Return a anonymous logon for anonymous users (username = "") - * - * Typically used as the first module in the auth chain, this allows - * guest logons to be dealt with in one place. Non-guest logons 'fail' - * and pass onto the next module. - **/ - -static NTSTATUS check_anonymous_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) -{ - /* mark this as 'not for me' */ - NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; - - if (!(user_info->internal_username.str - && *user_info->internal_username.str)) { - nt_status = make_server_info_anonymous(discard_const(auth_context), - server_info); - } - - return nt_status; -} - -/* Guest modules initialisation */ - -static NTSTATUS auth_init_anonymous(struct auth_context *auth_context, - const char *options, - struct auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) - return NT_STATUS_NO_MEMORY; - - (*auth_method)->auth = check_anonymous_security; - (*auth_method)->name = "anonymous"; - return NT_STATUS_OK; -} - -#ifdef DEVELOPER -/** - * Return an error based on username - * - * This function allows the testing of obsure errors, as well as the generation - * of NT_STATUS -> DOS error mapping tables. - * - * This module is of no value to end-users. - * - * The password is ignored. - * - * @return An NTSTATUS value based on the username - **/ - -static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status; - fstring user; - long error_num; - fstrcpy(user, user_info->smb_name.str); - - if (strncasecmp("NT_STATUS", user, strlen("NT_STATUS")) == 0) { - return nt_status_string_to_code(user); - } - - error_num = strtoul(user, NULL, 16); - - DEBUG(5,("check_name_to_ntstatus_security: Error for user %s was 0x%lx\n", user, error_num)); - - nt_status = NT_STATUS(error_num); - - return nt_status; -} - -/** Module initialisation function */ - -static NTSTATUS auth_init_name_to_ntstatus(struct auth_context *auth_context, - const char *param, - struct auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) - return NT_STATUS_NO_MEMORY; - - (*auth_method)->auth = check_name_to_ntstatus_security; - (*auth_method)->name = "name_to_ntstatus"; - return NT_STATUS_OK; -} - -/** - * Return a 'fixed' challenge instead of a variable one. - * - * The idea of this function is to make packet snifs consistant - * with a fixed challenge, so as to aid debugging. - * - * This module is of no value to end-users. - * - * This module does not actually authenticate the user, but - * just pretenteds to need a specified challenge. - * This module removes *all* security from the challenge-response system - * - * @return NT_STATUS_UNSUCCESSFUL - **/ - -static NTSTATUS check_fixed_challenge_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************************** - Get the challenge out of a password server. -****************************************************************************/ - -static DATA_BLOB auth_get_fixed_challenge(const struct auth_context *auth_context, - void **my_private_data, - TALLOC_CTX *mem_ctx) -{ - const char *challenge = "I am a teapot"; - return data_blob(challenge, 8); -} - - -/** Module initailisation function */ - -static NTSTATUS auth_init_fixed_challenge(struct auth_context *auth_context, - const char *param, - struct auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) - return NT_STATUS_NO_MEMORY; - - (*auth_method)->auth = check_fixed_challenge_security; - (*auth_method)->get_chal = auth_get_fixed_challenge; - (*auth_method)->name = "fixed_challenge"; - return NT_STATUS_OK; -} -#endif /* DEVELOPER */ - -NTSTATUS auth_builtin_init(void) -{ - NTSTATUS ret; - struct auth_operations ops; - - ops.name = "anonymous"; - ops.init = auth_init_anonymous; - ret = auth_register(&ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' auth backend!\n", - ops.name)); - return ret; - } - -#ifdef DEVELOPER - ops.name = "name_to_ntstatus"; - ops.init = auth_init_name_to_ntstatus; - ret = auth_register(&ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' auth backend!\n", - ops.name)); - return ret; - } - - ops.name = "fixed_challenge"; - ops.init = auth_init_fixed_challenge; - ret = auth_register(&ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' auth backend!\n", - ops.name)); - return ret; - } -#endif /* DEVELOPER */ - return ret; -} diff --git a/source4/auth/auth_developer.c b/source4/auth/auth_developer.c new file mode 100644 index 0000000000..6bb015ad35 --- /dev/null +++ b/source4/auth/auth_developer.c @@ -0,0 +1,192 @@ +/* + Unix SMB/CIFS implementation. + Generic authentication types + Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Stefan Metzmacher 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "auth/auth.h" +#include "librpc/gen_ndr/ndr_samr.h" +#include "librpc/gen_ndr/ndr_security.h" + +/** + * Return an error based on username + * + * This function allows the testing of obsure errors, as well as the generation + * of NT_STATUS -> DOS error mapping tables. + * + * This module is of no value to end-users. + * + * The password is ignored. + * + * @return An NTSTATUS value based on the username + **/ + +static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **_server_info) +{ + NTSTATUS nt_status; + struct auth_serversupplied_info *server_info; + fstring user; + uint32_t error_num; + fstrcpy(user, user_info->account_name); + + if (strncasecmp("NT_STATUS", user, strlen("NT_STATUS")) == 0) { + nt_status = nt_status_string_to_code(user); + } else { + error_num = strtoul(user, NULL, 16); + DEBUG(5,("name_to_ntstatus_check_password: Error for user %s was 0x%08X\n", user, error_num)); + nt_status = NT_STATUS(error_num); + } + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + server_info = talloc(mem_ctx, struct auth_serversupplied_info); + NT_STATUS_HAVE_NO_MEMORY(server_info); + + server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid); + + /* is this correct? */ + server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS); + NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid); + + server_info->n_domain_groups = 0; + server_info->domain_groups = NULL; + + /* annoying, but the Anonymous really does have a session key, + and it is all zeros! */ + server_info->user_session_key = data_blob_talloc(server_info, NULL, 16); + NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data); + + server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16); + NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data); + + data_blob_clear(&server_info->user_session_key); + data_blob_clear(&server_info->lm_session_key); + + server_info->account_name = talloc_asprintf(server_info, "NAME TO NTSTATUS %s ANONYMOUS LOGON", user); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); + + server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY"); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); + + server_info->full_name = talloc_asprintf(server_info, "NAME TO NTSTATUS %s Anonymous Logon", user); + NT_STATUS_HAVE_NO_MEMORY(server_info->full_name); + + server_info->logon_script = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); + + server_info->profile_path = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); + + server_info->home_directory = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); + + server_info->home_drive = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); + + server_info->last_logon = 0; + server_info->last_logoff = 0; + server_info->acct_expiry = 0; + server_info->last_password_change = 0; + server_info->allow_password_change = 0; + server_info->force_password_change = 0; + + server_info->logon_count = 0; + server_info->bad_password_count = 0; + + server_info->acct_flags = ACB_NORMAL; + + server_info->authenticated = False; + + *_server_info = server_info; + + return nt_status; +} + +static struct auth_operations name_to_ntstatus_auth_ops = { + .name = "name_to_ntstatus", + .get_challenge = auth_get_challenge_not_implemented, + .check_password = name_to_ntstatus_check_password +}; + +/** + * Return a 'fixed' challenge instead of a variable one. + * + * The idea of this function is to make packet snifs consistant + * with a fixed challenge, so as to aid debugging. + * + * This module is of no value to end-users. + * + * This module does not actually authenticate the user, but + * just pretenteds to need a specified challenge. + * This module removes *all* security from the challenge-response system + * + * @return NT_STATUS_UNSUCCESSFUL + **/ +static NTSTATUS fixed_challenge_get_challenge(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, DATA_BLOB *_blob) +{ + DATA_BLOB blob; + const char *challenge = "I am a teapot"; + + blob = data_blob_talloc(mem_ctx, challenge, 8); + NT_STATUS_HAVE_NO_MEMORY(blob.data); + + *_blob = blob; + return NT_STATUS_OK; +} + +static NTSTATUS fixed_challenge_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **_server_info) +{ + /* don't handle any users */ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static struct auth_operations fixed_challenge_auth_ops = { + .name = "fixed_challenge", + .get_challenge = fixed_challenge_get_challenge, + .check_password = fixed_challenge_check_password +}; + +NTSTATUS auth_developer_init(void) +{ + NTSTATUS ret; + + ret = auth_register(&name_to_ntstatus_auth_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register 'name_to_ntstatus' auth backend!\n")); + return ret; + } + + ret = auth_register(&fixed_challenge_auth_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register 'fixed_challenge' auth backend!\n")); + return ret; + } + + return ret; +} diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index a261fb223f..195cdeb06d 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -3,6 +3,7 @@ Password and authentication handling Copyright (C) Andrew Bartlett 2001-2004 Copyright (C) Gerald Carter 2003 + Copyright (C) Stefan Metzmacher 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,57 +26,52 @@ #include "auth/auth.h" #include "lib/ldb/include/ldb.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH - /**************************************************************************** Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ - -static NTSTATUS sam_password_ok(const struct auth_context *auth_context, - TALLOC_CTX *mem_ctx, - const char *username, - uint16_t acct_flags, - const struct samr_Password *lm_pwd, - const struct samr_Password *nt_pwd, - const struct auth_usersupplied_info *user_info, - DATA_BLOB *user_sess_key, - DATA_BLOB *lm_sess_key) +static NTSTATUS authsam_password_ok(const struct auth_context *auth_context, + TALLOC_CTX *mem_ctx, + uint16_t acct_flags, + const struct samr_Password *lm_pwd, + const struct samr_Password *nt_pwd, + const struct auth_usersupplied_info *user_info, + DATA_BLOB *user_sess_key, + DATA_BLOB *lm_sess_key) { NTSTATUS status; if (acct_flags & ACB_PWNOTREQ) { if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", - username)); + user_info->account_name)); return NT_STATUS_OK; } else { DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", - username)); + user_info->account_name)); return NT_STATUS_LOGON_FAILURE; } } - status = ntlm_password_check(mem_ctx, &auth_context->challenge, - &user_info->lm_resp, &user_info->nt_resp, - &user_info->lm_interactive_password, - &user_info->nt_interactive_password, - username, - user_info->smb_name.str, - user_info->client_domain.str, - lm_pwd->hash, nt_pwd->hash, user_sess_key, lm_sess_key); - - if (NT_STATUS_IS_OK(status)) { - if (user_sess_key && user_sess_key->data) { - talloc_steal(auth_context, user_sess_key->data); - } - if (lm_sess_key && lm_sess_key->data) { - talloc_steal(auth_context, lm_sess_key->data); - } + status = ntlm_password_check(mem_ctx, &auth_context->challenge.data, + &user_info->lm_resp, &user_info->nt_resp, + &user_info->lm_interactive_password, + &user_info->nt_interactive_password, + user_info->account_name, + user_info->client.account_name, + user_info->client.domain_name, + lm_pwd->hash, nt_pwd->hash, + user_sess_key, lm_sess_key); + NT_STATUS_NOT_OK_RETURN(status); + + if (user_sess_key && user_sess_key->data) { + talloc_steal(auth_context, user_sess_key->data); + } + if (lm_sess_key && lm_sess_key->data) { + talloc_steal(auth_context, lm_sess_key->data); } - return status; + return NT_STATUS_OK; } @@ -83,59 +79,55 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, Do a specific test for a SAM_ACCOUNT being vaild for this connection (ie not disabled, expired and the like). ****************************************************************************/ - -static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, - const char *username, - uint16_t acct_flags, - NTTIME *acct_expiry, - NTTIME *must_change_time, - NTTIME *last_set_time, - const char *workstation_list, - const struct auth_usersupplied_info *user_info) +static NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, + uint16_t acct_flags, + NTTIME acct_expiry, + NTTIME must_change_time, + NTTIME last_set_time, + const char *workstation_list, + const struct auth_usersupplied_info *user_info) { - DEBUG(4,("sam_account_ok: Checking SMB password for user %s\n", username)); + DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", user_info->account_name)); /* Quit if the account was disabled. */ if (acct_flags & ACB_DISABLED) { - DEBUG(1,("sam_account_ok: Account for user '%s' was disabled.\n", username)); + DEBUG(1,("authsam_account_ok: Account for user '%s' was disabled.\n", user_info->account_name)); return NT_STATUS_ACCOUNT_DISABLED; } /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { - DEBUG(1,("sam_account_ok: Account for user %s was locked out.\n", username)); + DEBUG(1,("authsam_account_ok: Account for user %s was locked out.\n", user_info->account_name)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } /* Test account expire time */ - if ((*acct_expiry) != -1 && time(NULL) > nt_time_to_unix(*acct_expiry)) { - DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", username)); - DEBUG(3,("sam_account_ok: Account expired at '%s'.\n", - nt_time_string(mem_ctx, *acct_expiry))); + if ((acct_expiry) != -1 && time(NULL) > nt_time_to_unix(acct_expiry)) { + DEBUG(1,("authsam_account_ok: Account for user '%s' has expired.\n", user_info->account_name)); + DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", + nt_time_string(mem_ctx, acct_expiry))); return NT_STATUS_ACCOUNT_EXPIRED; } if (!(acct_flags & ACB_PWNOEXP)) { - /* check for immediate expiry "must change at next logon" */ - if (*must_change_time == 0 && *last_set_time != 0) { + if (must_change_time == 0 && last_set_time != 0) { DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", - username)); + user_info->account_name)); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ - if ((*must_change_time) != 0 && nt_time_to_unix(*must_change_time) < time(NULL)) { + if ((must_change_time) != 0 && nt_time_to_unix(must_change_time) < time(NULL)) { DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", - username)); + user_info->account_name)); DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", - nt_time_string(mem_ctx, *must_change_time))); + nt_time_string(mem_ctx, must_change_time))); return NT_STATUS_PASSWORD_EXPIRED; } } /* Test workstation. Workstation list is comma separated. */ - if (workstation_list && *workstation_list) { BOOL invalid_ws = True; const char *s = workstation_list; @@ -143,35 +135,36 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, fstring tok; while (next_token(&s, tok, ",", sizeof(tok))) { - DEBUG(10,("sam_account_ok: checking for workstation match %s and %s (len=%d)\n", - tok, user_info->wksta_name.str, user_info->wksta_name.len)); - - if(strequal(tok, user_info->wksta_name.str)) { + DEBUG(10,("sam_account_ok: checking for workstation match '%s' and '%s'\n", + tok, user_info->workstation_name)); + + if (strequal(tok, user_info->workstation_name)) { invalid_ws = False; break; } } - - if (invalid_ws) + + if (invalid_ws) { return NT_STATUS_INVALID_WORKSTATION; + } } if (acct_flags & ACB_DOMTRUST) { - DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", username)); + DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", user_info->account_name)); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } - + if (acct_flags & ACB_SVRTRUST) { - DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", username)); + DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", user_info->account_name)); return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } - + if (acct_flags & ACB_WSTRUST) { - DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", username)); + DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", user_info->account_name)); return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } - + return NT_STATUS_OK; } @@ -179,21 +172,21 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, Look for the specified user in the sam, return ldb result structures ****************************************************************************/ -static NTSTATUS sam_search_user(const char *username, const char *domain, - TALLOC_CTX *mem_ctx, void *sam_ctx, - struct ldb_message ***ret_msgs, - struct ldb_message ***ret_msgs_domain) +static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, void *sam_ctx, + const char *account_name, + const char *domain_name, + struct ldb_message ***ret_msgs, + struct ldb_message ***ret_msgs_domain) { struct ldb_message **msgs; struct ldb_message **msgs_domain; - uint_t ret; - uint_t ret_domain; + int ret; + int ret_domain; const char *domain_dn = NULL; - const char *domain_sid; - const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash", + const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash", "userAccountControl", "pwdLastSet", "accountExpires", @@ -218,44 +211,52 @@ static NTSTATUS sam_search_user(const char *username, const char *domain, const char *domain_attrs[] = {"name", "objectSid"}; - if (domain) { + if (domain_name) { /* find the domain's DN */ ret_domain = samdb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs, "(&(|(realm=%s)(name=%s))(objectclass=domain))", - domain, domain); - + domain_name, domain_name); + if (ret_domain == -1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + if (ret_domain == 0) { - DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", - domain)); + DEBUG(3,("sam_search_user: Couldn't find domain [%s] in samdb.\n", + domain_name)); return NT_STATUS_NO_SUCH_USER; } - + if (ret_domain > 1) { DEBUG(0,("Found %d records matching domain [%s]\n", - ret_domain, domain)); + ret_domain, domain_name)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } domain_dn = msgs_domain[0]->dn; - } + /* pull the user attributes */ ret = samdb_search(sam_ctx, mem_ctx, domain_dn, &msgs, attrs, "(&(sAMAccountName=%s)(objectclass=user))", - username); + account_name); + if (ret == -1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } if (ret == 0) { - DEBUG(3,("check_sam_security: Couldn't find user [%s] in passdb file.\n", - username)); + DEBUG(3,("sam_search_user: Couldn't find user [%s] in samdb.\n", + account_name)); return NT_STATUS_NO_SUCH_USER; } if (ret > 1) { - DEBUG(0,("Found %d records matching user [%s]\n", ret, username)); + DEBUG(0,("Found %d records matching user [%s]\n", ret, account_name)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - - if (!domain) { + + if (!domain_name) { + const char *domain_sid; + domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid"); if (!domain_sid) { return NT_STATUS_INTERNAL_DB_CORRUPTION; @@ -265,9 +266,12 @@ static NTSTATUS sam_search_user(const char *username, const char *domain, ret_domain = samdb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs, "(&(objectSid=%s)(objectclass=domain))", domain_sid); + if (ret_domain == -1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } if (ret_domain == 0) { - DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", + DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", domain_sid)); return NT_STATUS_NO_SUCH_USER; } @@ -277,56 +281,46 @@ static NTSTATUS sam_search_user(const char *username, const char *domain, ret_domain, domain_sid)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - - domain_dn = msgs_domain[0]->dn; } + *ret_msgs = msgs; *ret_msgs_domain = msgs_domain; return NT_STATUS_OK; } -NTSTATUS sam_check_password(const struct auth_context *auth_context, - const char *username, - TALLOC_CTX *mem_ctx, void *sam_ctx, - struct ldb_message **msgs, - const char *domain_dn, - const struct auth_usersupplied_info *user_info, - DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) +static NTSTATUS authsam_authenticate(const struct auth_context *auth_context, + TALLOC_CTX *mem_ctx, void *sam_ctx, + struct ldb_message **msgs, + struct ldb_message **msgs_domain, + const struct auth_usersupplied_info *user_info, + DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { - uint16_t acct_flags; const char *workstation_list; NTTIME acct_expiry; NTTIME must_change_time; NTTIME last_set_time; struct samr_Password *lm_pwd, *nt_pwd; - NTSTATUS nt_status; - + const char *domain_dn = msgs_domain[0]->dn; acct_flags = samdb_result_acct_flags(msgs[0], "sAMAcctFlags"); /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", - username)); + user_info->account_name)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } - if (!NT_STATUS_IS_OK(nt_status = samdb_result_passwords(mem_ctx, msgs[0], - &lm_pwd, &nt_pwd))) { - return nt_status; - } + nt_status = samdb_result_passwords(mem_ctx, msgs[0], &lm_pwd, &nt_pwd); + NT_STATUS_NOT_OK_RETURN(nt_status); - nt_status = sam_password_ok(auth_context, mem_ctx, - username, acct_flags, - lm_pwd, nt_pwd, - user_info, user_sess_key, lm_sess_key); - - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = authsam_password_ok(auth_context, mem_ctx, + acct_flags, lm_pwd, nt_pwd, + user_info, user_sess_key, lm_sess_key); + NT_STATUS_NOT_OK_RETURN(nt_status); acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0); must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, @@ -336,40 +330,34 @@ NTSTATUS sam_check_password(const struct auth_context *auth_context, workstation_list = samdb_result_string(msgs[0], "userWorkstations", NULL); - nt_status = sam_account_ok(mem_ctx, username, acct_flags, - &acct_expiry, - &must_change_time, - &last_set_time, - workstation_list, - user_info); + nt_status = authsam_account_ok(mem_ctx, acct_flags, + acct_expiry, + must_change_time, + last_set_time, + workstation_list, + user_info); return nt_status; } -NTSTATUS sam_make_server_info(TALLOC_CTX *mem_ctx, void *sam_ctx, - struct ldb_message **msgs, struct ldb_message **msgs_domain, - struct auth_serversupplied_info **server_info) +static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, void *sam_ctx, + struct ldb_message **msgs, + struct ldb_message **msgs_domain, + DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key, + 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 }; /* find list of sids */ struct dom_sid **groupSIDs = NULL; - struct dom_sid *user_sid; + struct dom_sid *account_sid; struct dom_sid *primary_group_sid; - const char *sidstr; + const char *str; int i; uint_t rid; - - NTSTATUS nt_status; - if (!NT_STATUS_IS_OK(nt_status = make_server_info(mem_ctx, server_info, - samdb_result_string(msgs[0], "sAMAccountName", "")))) { - DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); - return nt_status; - } - group_ret = samdb_search(sam_ctx, mem_ctx, NULL, &group_msgs, group_attrs, "(&(member=%s)(sAMAccountType=*))", @@ -377,22 +365,29 @@ NTSTATUS sam_make_server_info(TALLOC_CTX *mem_ctx, void *sam_ctx, if (group_ret == -1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } + + server_info = talloc(mem_ctx, struct auth_serversupplied_info); + NT_STATUS_HAVE_NO_MEMORY(server_info); - if (group_ret > 0 && - !(groupSIDs = talloc_array(*server_info, struct dom_sid *, group_ret))) { - talloc_free(*server_info); - return NT_STATUS_NO_MEMORY; + if (group_ret > 0) { + groupSIDs = talloc_array(server_info, struct dom_sid *, group_ret); + NT_STATUS_HAVE_NO_MEMORY(groupSIDs); } - + /* Need to unroll some nested groups, but not aliases */ for (i = 0; i < group_ret; i++) { - sidstr = ldb_msg_find_string(group_msgs[i], "objectSid", NULL); - groupSIDs[i] = dom_sid_parse_talloc(*server_info, sidstr); + str = ldb_msg_find_string(group_msgs[i], "objectSid", NULL); + groupSIDs[i] = dom_sid_parse_talloc(groupSIDs, str); + NT_STATUS_HAVE_NO_MEMORY(groupSIDs[i]); } - - sidstr = ldb_msg_find_string(msgs[0], "objectSid", NULL); - user_sid = dom_sid_parse_talloc(*server_info, sidstr); - primary_group_sid = dom_sid_parse_talloc(*server_info, sidstr); + + str = ldb_msg_find_string(msgs[0], "objectSid", NULL); + account_sid = dom_sid_parse_talloc(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(account_sid); + + primary_group_sid = dom_sid_dup(server_info, account_sid); + NT_STATUS_HAVE_NO_MEMORY(primary_group_sid); + rid = samdb_result_uint(msgs[0], "primaryGroupID", ~0); if (rid == ~0) { if (group_ret > 0) { @@ -403,71 +398,68 @@ NTSTATUS sam_make_server_info(TALLOC_CTX *mem_ctx, void *sam_ctx, } else { primary_group_sid->sub_auths[primary_group_sid->num_auths-1] = rid; } + + server_info->account_sid = account_sid; + server_info->primary_group_sid = primary_group_sid; - (*server_info)->user_sid = user_sid; - (*server_info)->primary_group_sid = primary_group_sid; - - (*server_info)->n_domain_groups = group_ret; - (*server_info)->domain_groups = groupSIDs; - - (*server_info)->account_name - = talloc_strdup(*server_info, - samdb_result_string(msgs[0], "sAMAccountName", "")); - - (*server_info)->domain - = talloc_strdup(*server_info, - samdb_result_string(msgs_domain[0], "name", "")); - - (*server_info)->full_name - = talloc_strdup(*server_info, - samdb_result_string(msgs[0], "displayName", "")); - - (*server_info)->logon_script - = talloc_strdup(*server_info, - samdb_result_string(msgs[0], "scriptPath", "")); - (*server_info)->profile_path - = talloc_strdup(*server_info, - samdb_result_string(msgs[0], "profilePath", "")); - (*server_info)->home_directory - = talloc_strdup(*server_info, - samdb_result_string(msgs[0], "homeDirectory", "")); - - (*server_info)->home_drive - = talloc_strdup(*server_info, - samdb_result_string(msgs[0], "homeDrive", "")); - - (*server_info)->last_logon = samdb_result_nttime(msgs[0], "lastLogon", 0); - (*server_info)->last_logoff = samdb_result_nttime(msgs[0], "lastLogoff", 0); - (*server_info)->acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0); - (*server_info)->last_password_change = samdb_result_nttime(msgs[0], "pwdLastSet", 0); - (*server_info)->allow_password_change - = samdb_result_allow_password_change(sam_ctx, mem_ctx, - msgs_domain[0]->dn, msgs[0], "pwdLastSet"); - (*server_info)->force_password_change - = samdb_result_force_password_change(sam_ctx, mem_ctx, - msgs_domain[0]->dn, msgs[0], "pwdLastSet"); - - (*server_info)->logon_count = samdb_result_uint(msgs[0], "logonCount", 0); - (*server_info)->bad_password_count = samdb_result_uint(msgs[0], "badPwdCount", 0); - - (*server_info)->acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl"); - - (*server_info)->guest = False; - - if (!(*server_info)->account_name - || !(*server_info)->full_name - || !(*server_info)->logon_script - || !(*server_info)->profile_path - || !(*server_info)->home_directory - || !(*server_info)->home_drive) { - talloc_destroy(*server_info); - return NT_STATUS_NO_MEMORY; - } + server_info->n_domain_groups = group_ret; + server_info->domain_groups = groupSIDs; - return nt_status; + str = samdb_result_string(msgs[0], "sAMAccountName", ""); + server_info->account_name = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); + + str = samdb_result_string(msgs_domain[0], "name", ""); + server_info->domain_name = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); + + str = samdb_result_string(msgs[0], "displayName", ""); + server_info->full_name = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->full_name); + + str = samdb_result_string(msgs[0], "scriptPath", ""); + server_info->logon_script = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); + + str = samdb_result_string(msgs[0], "profilePath", ""); + server_info->profile_path = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); + + str = samdb_result_string(msgs[0], "homeDirectory", ""); + server_info->home_directory = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); + + str = samdb_result_string(msgs[0], "homeDrive", ""); + server_info->home_drive = talloc_strdup(server_info, str); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); + + server_info->last_logon = samdb_result_nttime(msgs[0], "lastLogon", 0); + server_info->last_logoff = samdb_result_nttime(msgs[0], "lastLogoff", 0); + server_info->acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0); + server_info->last_password_change = samdb_result_nttime(msgs[0], "pwdLastSet", 0); + + server_info->allow_password_change = samdb_result_allow_password_change(sam_ctx, mem_ctx, + msgs_domain[0]->dn, msgs[0], "pwdLastSet"); + server_info->force_password_change = samdb_result_force_password_change(sam_ctx, mem_ctx, + msgs_domain[0]->dn, msgs[0], "pwdLastSet"); + + server_info->logon_count = samdb_result_uint(msgs[0], "logonCount", 0); + server_info->bad_password_count = samdb_result_uint(msgs[0], "badPwdCount", 0); + + server_info->acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl"); + + server_info->user_session_key = user_sess_key; + server_info->lm_session_key = lm_sess_key; + + server_info->authenticated = True; + + *_server_info = server_info; + + return NT_STATUS_OK; } -NTSTATUS sam_get_server_info(const char *username, const char *domain, TALLOC_CTX *mem_ctx, +NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, const char *domain_name, + DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; @@ -481,35 +473,33 @@ NTSTATUS sam_get_server_info(const char *username, const char *domain, TALLOC_CT return NT_STATUS_INVALID_SYSTEM_SERVICE; } - nt_status = sam_search_user(username, domain, mem_ctx, sam_ctx, &msgs, &domain_msgs); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain_name, &msgs, &domain_msgs); + NT_STATUS_NOT_OK_RETURN(nt_status); - nt_status = sam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs, server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs, + user_sess_key, lm_sess_key, + server_info); + NT_STATUS_NOT_OK_RETURN(nt_status); return NT_STATUS_OK; } -static NTSTATUS check_sam_security_internals(const struct auth_context *auth_context, - const char *domain, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) +static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const char *domain, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { - /* mark this as 'not for me' */ - NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; - const char *username = user_info->internal_username.str; + NTSTATUS nt_status; + const char *account_name = user_info->account_name; struct ldb_message **msgs; struct ldb_message **domain_msgs; void *sam_ctx; DATA_BLOB user_sess_key, lm_sess_key; - if (!username || !*username) { - return nt_status; + if (!account_name || !*account_name) { + /* 'not for me' */ + return NT_STATUS_NOT_IMPLEMENTED; } sam_ctx = samdb_connect(mem_ctx); @@ -517,82 +507,52 @@ static NTSTATUS check_sam_security_internals(const struct auth_context *auth_con return NT_STATUS_INVALID_SYSTEM_SERVICE; } - nt_status = sam_search_user(username, domain, mem_ctx, sam_ctx, &msgs, &domain_msgs); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain, &msgs, &domain_msgs); + NT_STATUS_NOT_OK_RETURN(nt_status); - nt_status = sam_check_password(auth_context, username, mem_ctx, sam_ctx, msgs, domain_msgs[0]->dn, user_info, - &user_sess_key, &lm_sess_key); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - nt_status = sam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs, server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = authsam_authenticate(ctx->auth_ctx, mem_ctx, sam_ctx, msgs, domain_msgs, user_info, + &user_sess_key, &lm_sess_key); + NT_STATUS_NOT_OK_RETURN(nt_status); - talloc_reference(auth_context, *server_info); + nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs, + user_sess_key, lm_sess_key, + server_info); + NT_STATUS_NOT_OK_RETURN(nt_status); - (*server_info)->user_session_key = user_sess_key; - (*server_info)->lm_session_key = lm_sess_key; return NT_STATUS_OK; } -static NTSTATUS check_sam_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) +static NTSTATUS authsam_ignoredomain_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { - return check_sam_security_internals(auth_context, NULL, - mem_ctx, user_info, server_info); + return authsam_check_password_internals(ctx, mem_ctx, NULL, user_info, server_info); } -/* module initialisation */ -static NTSTATUS auth_init_sam_ignoredomain(struct auth_context *auth_context, - const char *param, - struct auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) { - return NT_STATUS_NO_MEMORY; - } - - (*auth_method)->auth = check_sam_security; - (*auth_method)->name = "sam_ignoredomain"; - return NT_STATUS_OK; -} - - /**************************************************************************** Check SAM security (above) but with a few extra checks. ****************************************************************************/ - -static NTSTATUS check_samstrict_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) +static NTSTATUS authsam_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { const char *domain; BOOL is_local_name, is_my_domain; - if (!user_info || !auth_context) { - return NT_STATUS_LOGON_FAILURE; - } - - is_local_name = is_myname(user_info->domain.str); - is_my_domain = strequal(user_info->domain.str, lp_workgroup()); + is_local_name = is_myname(user_info->domain_name); + is_my_domain = strequal(user_info->domain_name, lp_workgroup()); /* check whether or not we service this domain/workgroup name */ - - switch ( lp_server_role() ) { + switch (lp_server_role()) { case ROLE_STANDALONE: + domain = lp_netbios_name(); + break; case ROLE_DOMAIN_MEMBER: - if ( !is_local_name ) { - DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n", - user_info->domain.str, (lp_server_role() == ROLE_DOMAIN_MEMBER + if (!is_local_name) { + DEBUG(6,("authsam_check_password: %s is not one of my local names (%s)\n", + user_info->domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") )); return NT_STATUS_NOT_IMPLEMENTED; } @@ -600,55 +560,46 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context break; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - if ( !is_local_name && !is_my_domain ) { - DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n", - user_info->domain.str)); + if (!is_local_name && !is_my_domain) { + DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n", + user_info->domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } domain = lp_workgroup(); break; - default: /* name is ok */ - domain = user_info->domain.str; - break; + default: + DEBUG(6,("authsam_check_password: lp_server_role() has an undefined value\n")); + return NT_STATUS_NOT_IMPLEMENTED; } - - return check_sam_security_internals(auth_context, domain, mem_ctx, user_info, server_info); + + return authsam_check_password_internals(ctx, mem_ctx, domain, user_info, server_info); } -/* module initialisation */ -static NTSTATUS auth_init_sam(struct auth_context *auth_context, - const char *param, - struct auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) { - return NT_STATUS_NO_MEMORY; - } +static const struct auth_operations sam_ignoredomain_ops = { + .name = "sam_ignoredomain", + .get_challenge = auth_get_challenge_not_implemented, + .check_password = authsam_ignoredomain_check_password +}; - (*auth_method)->auth = check_samstrict_security; - (*auth_method)->name = "sam"; - return NT_STATUS_OK; -} +static const struct auth_operations sam_ops = { + .name = "sam", + .get_challenge = auth_get_challenge_not_implemented, + .check_password = authsam_check_password +}; NTSTATUS auth_sam_init(void) { NTSTATUS ret; - struct auth_operations ops; - ops.name = "sam"; - ops.init = auth_init_sam; - ret = auth_register(&ops); + ret = auth_register(&sam_ops); if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' auth backend!\n", - ops.name)); + DEBUG(0,("Failed to register 'sam' auth backend!\n")); return ret; } - ops.name = "sam_ignoredomain"; - ops.init = auth_init_sam_ignoredomain; - ret = auth_register(&ops); + ret = auth_register(&sam_ignoredomain_ops); if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' auth backend!\n", - ops.name)); + DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n")); return ret; } diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c index 04c36143dd..34aa632c3a 100644 --- a/source4/auth/auth_util.c +++ b/source4/auth/auth_util.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Bartlett 2001 Copyright (C) Jeremy Allison 2000-2001 Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Stefan Metzmacher 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,106 +28,101 @@ #include "libcli/security/security.h" #include "auth/auth.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH +/* this default function can be used by mostly all backends + * which don't want to set a challlenge + */ +NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, DATA_BLOB *challenge) +{ + /* we don't want to set a challenge */ + return NT_STATUS_NOT_IMPLEMENTED; +} /**************************************************************************** Create an auth_usersupplied_data structure ****************************************************************************/ static NTSTATUS make_user_info(TALLOC_CTX *mem_ctx, - struct auth_usersupplied_info **user_info, - const char *smb_name, - const char *internal_username, - const char *client_domain, - const char *domain, - const char *wksta_name, + const char *c_account_name, + const char *account_name, + const char *c_domain_name, + const char *domain_name, + const char *workstation_name, DATA_BLOB *lm_password, DATA_BLOB *nt_password, DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password, - DATA_BLOB *plaintext, - BOOL encrypted) + DATA_BLOB *plaintext_password, BOOL encrypted, + struct auth_usersupplied_info **_user_info) { + struct auth_usersupplied_info *user_info; + DATA_BLOB blob; - DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name)); + DEBUG(5,("attempting to make a user_info for %s (%s)\n", account_name, c_account_name)); - *user_info = talloc_p(mem_ctx, struct auth_usersupplied_info); - if (!user_info) { - return NT_STATUS_NO_MEMORY; - } + user_info = talloc(mem_ctx, struct auth_usersupplied_info); + NT_STATUS_HAVE_NO_MEMORY(user_info); + + DEBUG(5,("making strings for %s's user_info struct\n", account_name)); + + user_info->client.account_name = talloc_strdup(user_info, c_account_name); + NT_STATUS_HAVE_NO_MEMORY(user_info->client.account_name); + + user_info->account_name = talloc_strdup(user_info, account_name); + NT_STATUS_HAVE_NO_MEMORY(user_info->account_name); + + user_info->client.domain_name = talloc_strdup(user_info, c_domain_name); + NT_STATUS_HAVE_NO_MEMORY(user_info->client.domain_name); + + user_info->domain_name = talloc_strdup(user_info, domain_name); + NT_STATUS_HAVE_NO_MEMORY(user_info->domain_name); - ZERO_STRUCTP(*user_info); + user_info->workstation_name = talloc_strdup(user_info, workstation_name); + NT_STATUS_HAVE_NO_MEMORY(user_info->workstation_name); - DEBUG(5,("making strings for %s's user_info struct\n", internal_username)); + DEBUG(5,("making blobs for %s's user_info struct\n", account_name)); - (*user_info)->smb_name.str = talloc_strdup(*user_info, smb_name); - if ((*user_info)->smb_name.str) { - (*user_info)->smb_name.len = strlen(smb_name); + if (lm_password) { + blob = data_blob_dup_talloc(user_info, lm_password); + NT_STATUS_HAVE_NO_MEMORY(blob.data); } else { - free_user_info(user_info); - return NT_STATUS_NO_MEMORY; + blob = data_blob(NULL, 0); } - - (*user_info)->internal_username.str = talloc_strdup(*user_info, internal_username); - if ((*user_info)->internal_username.str) { - (*user_info)->internal_username.len = strlen(internal_username); + user_info->lm_resp = blob; + + if (nt_password) { + blob = data_blob_dup_talloc(user_info, nt_password); + NT_STATUS_HAVE_NO_MEMORY(blob.data); } else { - free_user_info(user_info); - return NT_STATUS_NO_MEMORY; + blob = data_blob(NULL, 0); } + user_info->nt_resp = blob; - (*user_info)->domain.str = talloc_strdup(*user_info, domain); - if ((*user_info)->domain.str) { - (*user_info)->domain.len = strlen(domain); + if (lm_interactive_password) { + blob = data_blob_dup_talloc(user_info, lm_interactive_password); + NT_STATUS_HAVE_NO_MEMORY(blob.data); } else { - free_user_info(user_info); - return NT_STATUS_NO_MEMORY; + blob = data_blob(NULL, 0); } + user_info->lm_interactive_password = blob; - (*user_info)->client_domain.str = talloc_strdup(*user_info, client_domain); - if ((*user_info)->client_domain.str) { - (*user_info)->client_domain.len = strlen(client_domain); + if (nt_interactive_password) { + blob = data_blob_dup_talloc(user_info, nt_interactive_password); + NT_STATUS_HAVE_NO_MEMORY(blob.data); } else { - free_user_info(user_info); - return NT_STATUS_NO_MEMORY; + blob = data_blob(NULL, 0); } + user_info->nt_interactive_password = blob; - (*user_info)->wksta_name.str = talloc_strdup(*user_info, wksta_name); - if ((*user_info)->wksta_name.str) { - (*user_info)->wksta_name.len = strlen(wksta_name); + if (plaintext_password) { + blob = data_blob_dup_talloc(user_info, plaintext_password); + NT_STATUS_HAVE_NO_MEMORY(blob.data); } else { - free_user_info(user_info); - return NT_STATUS_NO_MEMORY; + blob = data_blob(NULL, 0); } + user_info->plaintext_password = blob; + + user_info->encrypted = encrypted; + + DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , account_name, c_account_name)); - DEBUG(5,("making blobs for %s's user_info struct\n", internal_username)); - - if (lm_password) - (*user_info)->lm_resp = data_blob_talloc(*user_info, - lm_password->data, - lm_password->length); - if (nt_password) - (*user_info)->nt_resp = data_blob_talloc(*user_info, - nt_password->data, - nt_password->length); - if (lm_interactive_password) - (*user_info)->lm_interactive_password = - data_blob_talloc(*user_info, - lm_interactive_password->data, - lm_interactive_password->length); - if (nt_interactive_password) - (*user_info)->nt_interactive_password = - data_blob_talloc(*user_info, - nt_interactive_password->data, - nt_interactive_password->length); - - if (plaintext) - (*user_info)->plaintext_password = - data_blob_talloc(*user_info, - plaintext->data, - plaintext->length); - - (*user_info)->encrypted = encrypted; - - DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name)); + *_user_info = user_info; return NT_STATUS_OK; } @@ -136,84 +132,75 @@ static NTSTATUS make_user_info(TALLOC_CTX *mem_ctx, ****************************************************************************/ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx, - struct auth_usersupplied_info **user_info, - const char *smb_name, - const char *client_domain, - const char *wksta_name, + const char *c_account_name, + const char *c_domain_name, + const char *workstation_name, DATA_BLOB *lm_password, DATA_BLOB *nt_password, DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password, - DATA_BLOB *plaintext, - BOOL encrypted) + DATA_BLOB *plaintext, BOOL encrypted, + struct auth_usersupplied_info **user_info) { const char *domain; - - DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n", - client_domain, smb_name, wksta_name)); - + + DEBUG(5,("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n", + c_domain_name, c_account_name, workstation_name)); + /* don't allow "" as a domain, fixes a Win9X bug where it doens't supply a domain for logon script 'net use' commands. */ - - if ( *client_domain ) - domain = client_domain; - else + if (*c_domain_name) { + domain = c_domain_name; + } else { domain = lp_workgroup(); + } - /* we know that it is a trusted domain (and we are allowing - them) or it is our domain */ - - return make_user_info(mem_ctx, - user_info, smb_name, smb_name, - client_domain, domain, wksta_name, + return make_user_info(mem_ctx, + c_account_name, c_account_name, + c_domain_name, domain, + workstation_name, lm_password, nt_password, lm_interactive_password, nt_interactive_password, - plaintext, encrypted); + plaintext, encrypted, + user_info); } /**************************************************************************** Create an auth_usersupplied_data, making the DATA_BLOBs here. Decrypt and encrypt the passwords. ****************************************************************************/ - NTSTATUS make_user_info_netlogon_network(TALLOC_CTX *mem_ctx, - struct auth_usersupplied_info **user_info, - const char *smb_name, - const char *client_domain, - const char *wksta_name, + const char *c_account_name, + const char *c_domain_name, + const char *workstation_name, const uint8_t *lm_network_password, int lm_password_len, - const uint8_t *nt_network_password, int nt_password_len) + const uint8_t *nt_network_password, int nt_password_len, + struct auth_usersupplied_info **user_info) { - NTSTATUS nt_status; - DATA_BLOB lm_blob = data_blob(lm_network_password, lm_password_len); - DATA_BLOB nt_blob = data_blob(nt_network_password, nt_password_len); + DATA_BLOB lm_blob = data_blob_const(lm_network_password, lm_password_len); + DATA_BLOB nt_blob = data_blob_const(nt_network_password, nt_password_len); - nt_status = make_user_info_map(mem_ctx, - user_info, - smb_name, client_domain, - wksta_name, - lm_password_len ? &lm_blob : NULL, - nt_password_len ? &nt_blob : NULL, - NULL, NULL, NULL, - True); - - data_blob_free(&lm_blob); - data_blob_free(&nt_blob); - return nt_status; + return make_user_info_map(mem_ctx, + c_account_name, + c_domain_name, + workstation_name, + lm_password_len ? &lm_blob : NULL, + nt_password_len ? &nt_blob : NULL, + NULL, NULL, NULL, True, + user_info); } /**************************************************************************** Create an auth_usersupplied_data, making the DATA_BLOBs here. Decrypt and encrypt the passwords. ****************************************************************************/ - NTSTATUS make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx, - struct auth_usersupplied_info **user_info, - const char *smb_name, - const char *client_domain, - const char *wksta_name, - const uint8_t chal[8], - const struct samr_Password *lm_interactive_password, - const struct samr_Password *nt_interactive_password) + const char *c_account_name, + const char *c_domain_name, + const char *workstation_name, + const uint8_t chal[8], + const struct samr_Password *lm_interactive_password, + const struct samr_Password *nt_interactive_password, + struct auth_usersupplied_info **user_info) { NTSTATUS nt_status; DATA_BLOB local_lm_blob; @@ -223,111 +210,77 @@ NTSTATUS make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx, DATA_BLOB nt_interactive_blob; uint8_t local_lm_response[24]; uint8_t local_nt_response[24]; - + SMBOWFencrypt(lm_interactive_password->hash, chal, local_lm_response); SMBOWFencrypt(nt_interactive_password->hash, chal, local_nt_response); - - local_lm_blob = data_blob(local_lm_response, - sizeof(local_lm_response)); - lm_interactive_blob = data_blob(lm_interactive_password->hash, - sizeof(lm_interactive_password->hash)); - - local_nt_blob = data_blob(local_nt_response, - sizeof(local_nt_response)); - nt_interactive_blob = data_blob(nt_interactive_password->hash, - sizeof(nt_interactive_password->hash)); + + local_lm_blob = data_blob_const(local_lm_response, sizeof(local_lm_response)); + lm_interactive_blob = data_blob_const(lm_interactive_password->hash, + sizeof(lm_interactive_password->hash)); + + local_nt_blob = data_blob_const(local_nt_response, sizeof(local_nt_response)); + nt_interactive_blob = data_blob_const(nt_interactive_password->hash, + sizeof(nt_interactive_password->hash)); nt_status = make_user_info_map(mem_ctx, - user_info, - smb_name, client_domain, - wksta_name, + c_account_name, + c_domain_name, + workstation_name, &local_lm_blob, &local_nt_blob, &lm_interactive_blob, &nt_interactive_blob, - NULL, - True); - - data_blob_free(&local_lm_blob); - data_blob_free(&local_nt_blob); - data_blob_free(&lm_interactive_blob); - data_blob_free(&nt_interactive_blob); + NULL, True, + user_info); return nt_status; } + /**************************************************************************** Create an auth_usersupplied_data structure ****************************************************************************/ - NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx, - struct auth_usersupplied_info **user_info, - const char *smb_name, - const char *client_domain, - const char *remote_machine, - DATA_BLOB lm_resp, DATA_BLOB nt_resp) + const char *c_account_name, + const char *c_domain_name, + const char *workstation_name, + DATA_BLOB lm_resp, DATA_BLOB nt_resp, + struct auth_usersupplied_info **user_info) { return make_user_info_map(mem_ctx, - user_info, smb_name, - client_domain, - remote_machine, - lm_resp.data ? &lm_resp : NULL, - nt_resp.data ? &nt_resp : NULL, - NULL, NULL, NULL, - True); + c_account_name, + c_domain_name, + workstation_name, + lm_resp.data ? &lm_resp : NULL, + nt_resp.data ? &nt_resp : NULL, + NULL, NULL, NULL, True, + user_info); } /**************************************************************************** - Create a guest user_info blob, for anonymous authenticaion. + Create a anonymous user_info blob, for anonymous authenticaion. ****************************************************************************/ - -BOOL make_user_info_guest(TALLOC_CTX *mem_ctx, - struct auth_usersupplied_info **user_info) +NTSTATUS make_user_info_anonymous(TALLOC_CTX *mem_ctx, struct auth_usersupplied_info **user_info) { - NTSTATUS nt_status; - - nt_status = make_user_info(mem_ctx, - user_info, - "","", - "","", - "", - NULL, NULL, - NULL, NULL, - NULL, - True); - - return NT_STATUS_IS_OK(nt_status) ? True : False; + return make_user_info(mem_ctx, + "", "", "", "", "", + NULL, NULL, NULL, NULL, + NULL, True, + user_info); } - -/*************************************************************************** - Make a user_info struct -***************************************************************************/ - -NTSTATUS make_server_info(const TALLOC_CTX *mem_ctx, - struct auth_serversupplied_info **server_info, - const char *username) -{ - *server_info = talloc_p(mem_ctx, struct auth_serversupplied_info); - if (!*server_info) { - return NT_STATUS_NO_MEMORY; - } - ZERO_STRUCTP(*server_info); - - return NT_STATUS_OK; -} - /*************************************************************************** Make a server_info struct from the info3 returned by a domain logon ***************************************************************************/ - -NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx, - const char *internal_username, - struct auth_serversupplied_info **server_info, - uint16 validation_level, - union netr_Validation *validation) +NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx, + const char *account_name, + uint16 validation_level, + union netr_Validation *validation, + struct auth_serversupplied_info **_server_info) { - NTSTATUS nt_status; + struct auth_serversupplied_info *server_info; struct netr_SamBaseInfo *base = NULL; + int i; + switch (validation_level) { case 2: if (!validation || !validation->sam2) { @@ -351,42 +304,32 @@ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx, return NT_STATUS_INVALID_LEVEL; } - nt_status = make_server_info(mem_ctx, server_info, internal_username); + server_info = talloc(mem_ctx, struct auth_serversupplied_info); + NT_STATUS_HAVE_NO_MEMORY(server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - (*server_info)->guest = False; - - /* + /* Here is where we should check the list of trusted domains, and verify that the SID matches. */ + server_info->account_sid = dom_sid_add_rid(server_info, base->domain_sid, base->rid); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid); + - (*server_info)->user_sid = dom_sid_add_rid(*server_info, dom_sid_dup(*server_info, base->domain_sid), base->rid); - (*server_info)->primary_group_sid = dom_sid_add_rid(*server_info, dom_sid_dup(*server_info, base->domain_sid), base->primary_gid); + server_info->primary_group_sid = dom_sid_add_rid(server_info, base->domain_sid, base->primary_gid); + NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid); - (*server_info)->domain_groups = talloc_array_p((*server_info), struct dom_sid*, base->group_count); - if (!(*server_info)->domain_groups) { - return NT_STATUS_NO_MEMORY; + server_info->n_domain_groups = base->group_count; + if (base->group_count) { + server_info->domain_groups = talloc_array(server_info, struct dom_sid*, base->group_count); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups); + } else { + server_info->domain_groups = NULL; } - - for ((*server_info)->n_domain_groups = 0; - (*server_info)->n_domain_groups < base->group_count; - (*server_info)->n_domain_groups++) { - struct dom_sid *sid; - sid = dom_sid_dup((*server_info)->domain_groups, base->domain_sid); - if (!sid) { - return NT_STATUS_NO_MEMORY; - } - (*server_info)->domain_groups[(*server_info)->n_domain_groups] - = dom_sid_add_rid(*server_info, sid, - base->groupids[(*server_info)->n_domain_groups].rid); - if (!(*server_info)->domain_groups[(*server_info)->n_domain_groups]) { - return NT_STATUS_NO_MEMORY; - } + + for (i = 0; i < base->group_count; i++) { + server_info->domain_groups[i] = dom_sid_add_rid(server_info, base->domain_sid, base->groupids[i].rid); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_groups[i]); } /* Copy 'other' sids. We need to do sid filtering here to @@ -396,156 +339,95 @@ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx, */ if (validation_level == 3) { - int i; - (*server_info)->domain_groups - = talloc_realloc_p((*server_info), - (*server_info)->domain_groups, - struct dom_sid*, - base->group_count + validation->sam3->sidcount); - - if (!(*server_info)->domain_groups) { - return NT_STATUS_NO_MEMORY; - } - + struct dom_sid **dgrps = server_info->domain_groups; + size_t sidcount = server_info->n_domain_groups + validation->sam3->sidcount; + size_t n_dgrps = server_info->n_domain_groups; + + dgrps = talloc_realloc(server_info, dgrps, struct dom_sid*, sidcount); + NT_STATUS_HAVE_NO_MEMORY(dgrps); + for (i = 0; i < validation->sam3->sidcount; i++) { - (*server_info)->domain_groups[(*server_info)->n_domain_groups + i] = - dom_sid_dup((*server_info)->domain_groups, - validation->sam3->sids[i].sid); + dgrps[n_dgrps + i] = talloc_reference(dgrps, validation->sam3->sids[i].sid); } + server_info->n_domain_groups = sidcount; + server_info->domain_groups = dgrps; + /* Where are the 'global' sids?... */ } if (base->account_name.string) { - (*server_info)->account_name = talloc_reference(*server_info, base->account_name.string); + server_info->account_name = talloc_reference(server_info, base->account_name.string); } else { - (*server_info)->account_name = talloc_strdup(*server_info, internal_username); + server_info->account_name = talloc_strdup(server_info, account_name); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); } - - (*server_info)->domain = talloc_reference(*server_info, base->domain.string); - (*server_info)->full_name = talloc_reference(*server_info, base->full_name.string); - (*server_info)->logon_script = talloc_reference(*server_info, base->logon_script.string); - (*server_info)->profile_path = talloc_reference(*server_info, base->profile_path.string); - (*server_info)->home_directory = talloc_reference(*server_info, base->home_directory.string); - (*server_info)->home_drive = talloc_reference(*server_info, base->home_drive.string); - (*server_info)->last_logon = base->last_logon; - (*server_info)->last_logoff = base->last_logoff; - (*server_info)->acct_expiry = base->acct_expiry; - (*server_info)->last_password_change = base->last_password_change; - (*server_info)->allow_password_change = base->allow_password_change; - (*server_info)->force_password_change = base->force_password_change; - - (*server_info)->logon_count = base->logon_count; - (*server_info)->bad_password_count = base->bad_password_count; - - (*server_info)->acct_flags = base->acct_flags; + + server_info->domain_name = talloc_reference(server_info, base->domain.string); + server_info->full_name = talloc_reference(server_info, base->full_name.string); + server_info->logon_script = talloc_reference(server_info, base->logon_script.string); + server_info->profile_path = talloc_reference(server_info, base->profile_path.string); + server_info->home_directory = talloc_reference(server_info, base->home_directory.string); + server_info->home_drive = talloc_reference(server_info, base->home_drive.string); + server_info->last_logon = base->last_logon; + server_info->last_logoff = base->last_logoff; + server_info->acct_expiry = base->acct_expiry; + server_info->last_password_change = base->last_password_change; + server_info->allow_password_change = base->allow_password_change; + server_info->force_password_change = base->force_password_change; + server_info->logon_count = base->logon_count; + server_info->bad_password_count = base->bad_password_count; + server_info->acct_flags = base->acct_flags; + + server_info->authenticated = True; /* ensure we are never given NULL session keys */ - + if (all_zero(base->key.key, sizeof(base->key.key))) { - (*server_info)->user_session_key = data_blob(NULL, 0); + server_info->user_session_key = data_blob(NULL, 0); } else { - (*server_info)->user_session_key = data_blob_talloc((*server_info), base->key.key, sizeof(base->key.key)); + server_info->user_session_key = data_blob_talloc(server_info, base->key.key, sizeof(base->key.key)); + NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data); } if (all_zero(base->LMSessKey.key, sizeof(base->LMSessKey.key))) { - (*server_info)->lm_session_key = data_blob(NULL, 0); + server_info->lm_session_key = data_blob(NULL, 0); } else { - (*server_info)->lm_session_key = data_blob_talloc((*server_info), base->LMSessKey.key, sizeof(base->LMSessKey.key)); - } - return NT_STATUS_OK; -} - -/*************************************************************************** - Free a user_info struct -***************************************************************************/ - -void free_user_info(struct auth_usersupplied_info **user_info) -{ - DEBUG(5,("attempting to free (and zero) a user_info structure\n")); - if (*user_info) { - data_blob_clear(&(*user_info)->plaintext_password); - } - - talloc_free(*user_info); - *user_info = NULL; -} - -/*************************************************************************** - Clear out a server_info struct that has been allocated -***************************************************************************/ - -void free_server_info(struct auth_serversupplied_info **server_info) -{ - DEBUG(5,("attempting to free a server_info structure\n")); - talloc_free(*server_info); - *server_info = NULL; -} - -/*************************************************************************** - Make an auth_methods struct -***************************************************************************/ - -BOOL make_auth_methods(struct auth_context *auth_context, struct auth_methods **auth_method) -{ - if (!auth_context) { - smb_panic("no auth_context supplied to make_auth_methods()!\n"); + server_info->lm_session_key = data_blob_talloc(server_info, base->LMSessKey.key, sizeof(base->LMSessKey.key)); + NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data); } - if (!auth_method) { - smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n"); - } - - *auth_method = talloc_p(auth_context, struct auth_methods); - if (!*auth_method) { - return False; - } - ZERO_STRUCTP(*auth_method); - - return True; + *_server_info = server_info; + return NT_STATUS_OK; } -NTSTATUS make_session_info(TALLOC_CTX *mem_ctx, - struct auth_serversupplied_info *server_info, - struct auth_session_info **session_info) +NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + struct auth_session_info **_session_info) { + struct auth_session_info *session_info; NTSTATUS nt_status; - *session_info = talloc_p(mem_ctx, struct auth_session_info); - if (!*session_info) { - return NT_STATUS_NO_MEMORY; - } - - (*session_info)->server_info = server_info; - talloc_reference(*session_info, (*session_info)->server_info); + session_info = talloc(mem_ctx, struct auth_session_info); + NT_STATUS_HAVE_NO_MEMORY(session_info); + + session_info->server_info = talloc_reference(session_info, server_info); /* unless set otherwise, the session key is the user session - * key from the auth subsystem */ - - (*session_info)->session_key = server_info->user_session_key; + * key from the auth subsystem */ + session_info->session_key = server_info->user_session_key; - /* we should search for local groups here */ - - nt_status = security_token_create((*session_info), - server_info->user_sid, - server_info->primary_group_sid, - server_info->n_domain_groups, + nt_status = security_token_create(session_info, + server_info->account_sid, + server_info->primary_group_sid, + server_info->n_domain_groups, server_info->domain_groups, - False, - &(*session_info)->security_token); - - return nt_status; -} - -/*************************************************************************** - Clear out a server_info struct that has been allocated -***************************************************************************/ + server_info->authenticated, + &session_info->security_token); + NT_STATUS_NOT_OK_RETURN(nt_status); -void free_session_info(struct auth_session_info **session_info) -{ - DEBUG(5,("attempting to free a session_info structure\n")); - talloc_free((*session_info)); - *session_info = NULL; + *_session_info = session_info; + return NT_STATUS_OK; } /**************************************************************************** @@ -572,22 +454,15 @@ void auth_session_info_debug(int dbg_lev, * @param nt_status NTSTATUS input for squashing. * @return the 'squashed' nt_status **/ - -NTSTATUS nt_status_squash(NTSTATUS nt_status) +NTSTATUS auth_nt_status_squash(NTSTATUS nt_status) { - if NT_STATUS_IS_OK(nt_status) { - return nt_status; - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { + if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) { /* Match WinXP and don't give the game away */ return NT_STATUS_LOGON_FAILURE; - } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) { /* Match WinXP and don't give the game away */ return NT_STATUS_LOGON_FAILURE; - } else { - return nt_status; - } -} - - + } + return nt_status; +} diff --git a/source4/auth/auth_winbind.c b/source4/auth/auth_winbind.c index 8305bd1644..2ded310ebc 100644 --- a/source4/auth/auth_winbind.c +++ b/source4/auth/auth_winbind.c @@ -5,6 +5,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Andrew Bartlett 2001 - 2002 + Copyright (C) Stefan Metzmacher 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,9 +26,6 @@ #include "librpc/gen_ndr/ndr_netlogon.h" #include "auth/auth.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH - static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, struct netr_SamInfo3 *info3) { size_t len = response->length - sizeof(struct winbindd_response); @@ -36,7 +34,7 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response DATA_BLOB blob; blob.length = len - 4; blob.data = (uint8_t *)(((char *)response->extra_data) + 4); - + status = ndr_pull_struct_blob(&blob, mem_ctx, info3, (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3); @@ -48,28 +46,16 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response } /* Authenticate a user with a challenge/response */ - -static NTSTATUS check_winbind_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) +static NTSTATUS winbind_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { struct winbindd_request request; struct winbindd_response response; NSS_STATUS result; NTSTATUS nt_status; - struct netr_SamInfo3 info3; - - if (!user_info) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (!auth_context) { - DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", - user_info->internal_username.str)); - return NT_STATUS_UNSUCCESSFUL; - } + struct netr_SamInfo3 info3; /* Send off request */ @@ -77,84 +63,71 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, ZERO_STRUCT(response); request.flags = WBFLAG_PAM_INFO3_NDR; fstrcpy(request.data.auth_crap.user, - user_info->smb_name.str); + user_info->account_name); fstrcpy(request.data.auth_crap.domain, - user_info->domain.str); + user_info->domain_name); fstrcpy(request.data.auth_crap.workstation, - user_info->wksta_name.str); + user_info->workstation_name); + + memcpy(request.data.auth_crap.chal, ctx->auth_ctx->challenge.data.data, sizeof(request.data.auth_crap.chal)); - memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal)); - request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length, sizeof(request.data.auth_crap.lm_resp)); request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length, sizeof(request.data.auth_crap.nt_resp)); - + memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data, request.data.auth_crap.lm_resp_len); memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, request.data.auth_crap.nt_resp_len); - + result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); nt_status = NT_STATUS(response.data.auth.nt_status); - - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + NT_STATUS_NOT_OK_RETURN(nt_status); if (result == NSS_STATUS_SUCCESS && response.extra_data) { + union netr_Validation validation; + nt_status = get_info3_from_ndr(mem_ctx, &response, &info3); - if (NT_STATUS_IS_OK(nt_status)) { - union netr_Validation validation; - validation.sam3 = &info3; - nt_status = - make_server_info_netlogon_validation(mem_ctx, - user_info->internal_username.str, - server_info, - 3, - &validation); - } SAFE_FREE(response.extra_data); + NT_STATUS_NOT_OK_RETURN(nt_status); + + validation.sam3 = &info3; + nt_status = make_server_info_netlogon_validation(mem_ctx, + user_info->account_name, + 3, &validation, + server_info); + return nt_status; } else if (result == NSS_STATUS_SUCCESS && !response.extra_data) { DEBUG(0, ("Winbindd authenticated the user [%s]\\[%s], " "but did not include the required info3 reply!\n", - user_info->smb_name.str, user_info->domain.str)); - nt_status = NT_STATUS_INSUFFICIENT_LOGON_INFO; + user_info->domain_name, user_info->account_name)); + return NT_STATUS_INSUFFICIENT_LOGON_INFO; } else if (NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("Winbindd authentication for [%s]\\[%s] failed, " "but no error code is available!\n", - user_info->smb_name.str, user_info->domain.str)); - nt_status = NT_STATUS_NO_LOGON_SERVERS; + user_info->domain_name, user_info->account_name)); + return NT_STATUS_NO_LOGON_SERVERS; } return nt_status; } -/* module initialisation */ -static NTSTATUS auth_init_winbind(struct auth_context *auth_context, - const char *param, - struct auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) - return NT_STATUS_NO_MEMORY; - - (*auth_method)->name = "winbind"; - (*auth_method)->auth = check_winbind_security; - return NT_STATUS_OK; -} +static const struct auth_operations winbind_ops = { + .name = "winbind", + .get_challenge = auth_get_challenge_not_implemented, + .check_password = winbind_check_password +}; NTSTATUS auth_winbind_init(void) { NTSTATUS ret; - struct auth_operations ops; - ops.name = "winbind"; - ops.init = auth_init_winbind; - ret = auth_register(&ops); + ret = auth_register(&winbind_ops); if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' auth backend!\n", - ops.name)); + DEBUG(0,("Failed to register 'winbind' auth backend!\n")); + return ret; } return ret; } diff --git a/source4/auth/config.mk b/source4/auth/config.mk index 131828ae63..43a1ef4347 100644 --- a/source4/auth/config.mk +++ b/source4/auth/config.mk @@ -13,14 +13,13 @@ REQUIRED_SUBSYSTEMS = \ ####################### ####################### -# Start MODULE auth_builtin -[MODULE::auth_builtin] -INIT_FUNCTION = auth_builtin_init +# Start MODULE auth_anonymous +[MODULE::auth_anonymous] +INIT_FUNCTION = auth_anonymous_init SUBSYSTEM = AUTH -REQUIRED_SUBSYSTEMS = LIBCLI_UTILS INIT_OBJ_FILES = \ - auth/auth_builtin.o -# End MODULE auth_builtin + auth/auth_anonymous.o +# End MODULE auth_anonymous ####################### ####################### @@ -33,7 +32,17 @@ INIT_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = \ LIB_WINBIND_CLIENT \ NDR_NETLOGON LIBNDR -# End MODULE auth_builtin +# End MODULE auth_winbind +####################### + +####################### +# Start MODULE auth_developer +[MODULE::auth_developer] +INIT_FUNCTION = auth_developer_init +SUBSYSTEM = AUTH +INIT_OBJ_FILES = \ + auth/auth_developer.o +# End MODULE auth_developer ####################### ####################### @@ -43,8 +52,6 @@ INIT_OBJ_FILES = \ auth/auth.o ADD_OBJ_FILES = \ auth/auth_util.o \ - auth/pampass.o \ - auth/pass_check.o \ auth/ntlm_check.o # End SUBSYSTEM AUTH ####################### -- cgit