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 +- source4/include/structs.h | 1 + source4/libcli/auth/gensec_krb5.c | 61 ++- source4/libcli/auth/gensec_ntlmssp.c | 154 +++---- source4/libcli/security/security_token.c | 45 +- source4/librpc/rpc/dcerpc_schannel.c | 17 +- source4/rpc_server/dcerpc_server.c | 3 +- source4/rpc_server/lsa/dcesrv_lsa.c | 4 +- source4/rpc_server/netlogon/dcerpc_netlogon.c | 89 ++-- source4/smb_server/negprot.c | 38 +- source4/smb_server/sesssetup.c | 87 ++-- source4/utils/ntlm_auth.c | 6 +- 20 files changed, 1267 insertions(+), 1637 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 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 ####################### diff --git a/source4/include/structs.h b/source4/include/structs.h index ccf6b5911e..9572bfe038 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -85,6 +85,7 @@ struct smbsrv_tcon; struct smb_signing_context; struct smbsrv_connection; struct auth_context; +struct auth_method_context; struct request_buffer; struct pvfs_dir; diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c index 0ab32318aa..aaf892e1e6 100644 --- a/source4/libcli/auth/gensec_krb5.c +++ b/source4/libcli/auth/gensec_krb5.c @@ -6,6 +6,7 @@ Copyright (C) Andrew Bartlett 2004 Copyright (C) Andrew Tridgell 2001 Copyright (C) Luke Howard 2002-2003 + 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 @@ -30,9 +31,6 @@ #include "librpc/gen_ndr/ndr_krb5pac.h" #include "auth/auth.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_AUTH - enum GENSEC_KRB5_STATE { GENSEC_KRB5_SERVER_START, GENSEC_KRB5_CLIENT_START, @@ -620,7 +618,7 @@ static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security, } static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security, - struct auth_session_info **session_info_out) + struct auth_session_info **_session_info) { NTSTATUS nt_status; struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data; @@ -629,20 +627,22 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security struct PAC_LOGON_INFO *logon_info; char *p; char *principal; - const char *username; + const char *account_name; const char *realm; - *session_info_out = NULL; - principal = talloc_strdup(gensec_krb5_state, gensec_krb5_state->peer_principal); + NT_STATUS_HAVE_NO_MEMORY(principal); + p = strchr(principal, '@'); if (p) { *p = '\0'; + p++; + realm = p; + } else { + realm = lp_realm(); } - p++; - username = principal; - realm = p; - + account_name = principal; + /* decode and verify the pac */ nt_status = gensec_krb5_decode_pac(gensec_krb5_state, &logon_info, gensec_krb5_state->pac, gensec_krb5_state); @@ -659,36 +659,33 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security union netr_Validation validation; validation.sam3 = &logon_info->info3; nt_status = make_server_info_netlogon_validation(gensec_krb5_state, - username, - &server_info, - 3, - &validation); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + account_name, + 3, &validation, + &server_info); + talloc_free(principal); + NT_STATUS_NOT_OK_RETURN(nt_status); } else { - nt_status = sam_get_server_info(username, realm, gensec_krb5_state, &server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + DATA_BLOB user_sess_key = data_blob(NULL, 0); + DATA_BLOB lm_sess_key = data_blob(NULL, 0); + /* TODO: should we pass the krb5 session key in here? */ + nt_status = sam_get_server_info(gensec_krb5_state, account_name, realm, + user_sess_key, lm_sess_key, + &server_info); + talloc_free(principal); + NT_STATUS_NOT_OK_RETURN(nt_status); } /* references the server_info into the session_info */ - nt_status = make_session_info(gensec_krb5_state, server_info, &session_info); + nt_status = auth_generate_session_info(gensec_krb5_state, server_info, &session_info); talloc_free(server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - talloc_free(principal); + NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = gensec_krb5_session_key(gensec_security, &session_info->session_key); + NT_STATUS_NOT_OK_RETURN(nt_status); - session_info->workstation = NULL; + *_session_info = session_info; - *session_info_out = session_info; - - return nt_status; + return NT_STATUS_OK; } static BOOL gensec_krb5_have_feature(struct gensec_security *gensec_security, diff --git a/source4/libcli/auth/gensec_ntlmssp.c b/source4/libcli/auth/gensec_ntlmssp.c index a91c2817af..ae97803ef7 100644 --- a/source4/libcli/auth/gensec_ntlmssp.c +++ b/source4/libcli/auth/gensec_ntlmssp.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2003 Copyright (C) Andrew Bartlett 2004 + 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 @@ -40,8 +41,15 @@ struct gensec_ntlmssp_state { static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state) { struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; + NTSTATUS status; + const uint8_t *chal; + + status = auth_get_challenge(gensec_ntlmssp_state->auth_context, &chal); + if (!NT_STATUS_IS_OK(status)) { + return NULL; + } - return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context); + return chal; } /** @@ -53,7 +61,7 @@ static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_s { struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; - return gensec_ntlmssp_state->auth_context->challenge_may_be_modified; + return auth_challenge_may_be_modified(gensec_ntlmssp_state->auth_context); } /** @@ -62,20 +70,20 @@ static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_s */ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) { + NTSTATUS nt_status; struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context; struct auth_context *auth_context = gensec_ntlmssp_state->auth_context; + const uint8_t *chal; - SMB_ASSERT(challenge->length == 8); + if (challenge->length != 8) { + return NT_STATUS_INVALID_PARAMETER; + } - auth_context->challenge = data_blob_talloc(auth_context, - challenge->data, challenge->length); + chal = challenge->data; - auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)"; + nt_status = auth_context_set_challenge(auth_context, chal, "NTLMSSP callback (NTLM2)"); - DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by)); - DEBUG(5, ("challenge is: \n")); - dump_data(5, auth_context->challenge.data, auth_context->challenge.length); - return NT_STATUS_OK; + return nt_status; } /** @@ -90,44 +98,21 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, struct auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; -#if 0 - /* the client has given us its machine name (which we otherwise would not get on port 445). - we need to possibly reload smb.conf if smb.conf includes depend on the machine name */ - - set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True); - - /* setup the string used by %U */ - /* sub_set_smb_name checks for weird internally */ - sub_set_smb_name(gensec_ntlmssp_state->ntlmssp_state->user); - - reload_services(True); - -#endif - nt_status = make_user_info_map(ntlmssp_state, - &user_info, + nt_status = make_user_info_map(ntlmssp_state, gensec_ntlmssp_state->ntlmssp_state->user, gensec_ntlmssp_state->ntlmssp_state->domain, gensec_ntlmssp_state->ntlmssp_state->workstation, gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL, gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL, - NULL, NULL, NULL, - True); - - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - nt_status = gensec_ntlmssp_state-> - auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context, - user_info, - gensec_ntlmssp_state, - &gensec_ntlmssp_state->server_info); + NULL, NULL, NULL, True, + &user_info); + NT_STATUS_NOT_OK_RETURN(nt_status); - free_user_info(&user_info); + nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, gensec_ntlmssp_state, + user_info, &gensec_ntlmssp_state->server_info); + talloc_free(user_info); + NT_STATUS_NOT_OK_RETURN(nt_status); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } if (gensec_ntlmssp_state->server_info->user_session_key.length) { DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length)); *user_session_key = data_blob_talloc(ntlmssp_state, @@ -151,12 +136,6 @@ static int gensec_ntlmssp_destroy(void *ptr) ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state); } - if (gensec_ntlmssp_state->auth_context) { - free_auth_context(&gensec_ntlmssp_state->auth_context); - } - if (gensec_ntlmssp_state->server_info) { - free_server_info(&gensec_ntlmssp_state->server_info); - } return 0; } @@ -183,21 +162,16 @@ static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security) static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) { NTSTATUS nt_status; - NTSTATUS status; struct ntlmssp_state *ntlmssp_state; struct gensec_ntlmssp_state *gensec_ntlmssp_state; - status = gensec_ntlmssp_start(gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + nt_status = gensec_ntlmssp_start(gensec_security); + NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp_state = gensec_security->private_data; - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_ntlmssp_state, - &gensec_ntlmssp_state->ntlmssp_state))) { - return nt_status; - } + nt_status = ntlmssp_server_start(gensec_ntlmssp_state, &gensec_ntlmssp_state->ntlmssp_state); + NT_STATUS_NOT_OK_RETURN(nt_status); if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; @@ -206,19 +180,17 @@ static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_secur gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } - ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; - nt_status = make_auth_context_subsystem(gensec_ntlmssp_state, &gensec_ntlmssp_state->auth_context); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = auth_context_create(gensec_ntlmssp_state, lp_auth_methods(), &gensec_ntlmssp_state->auth_context); + NT_STATUS_NOT_OK_RETURN(nt_status); + ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state; ntlmssp_state->auth_context = gensec_ntlmssp_state; ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; ntlmssp_state->check_password = auth_ntlmssp_check_password; ntlmssp_state->server_role = lp_server_role(); - + return NT_STATUS_OK; } @@ -226,19 +198,15 @@ static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_secur { struct gensec_ntlmssp_state *gensec_ntlmssp_state; char *password = NULL; - - NTSTATUS status; - status = gensec_ntlmssp_start(gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + NTSTATUS nt_status; + + nt_status = gensec_ntlmssp_start(gensec_security); + NT_STATUS_NOT_OK_RETURN(nt_status); gensec_ntlmssp_state = gensec_security->private_data; - status = ntlmssp_client_start(gensec_ntlmssp_state, - &gensec_ntlmssp_state->ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + nt_status = ntlmssp_client_start(gensec_ntlmssp_state, + &gensec_ntlmssp_state->ntlmssp_state); + NT_STATUS_NOT_OK_RETURN(nt_status); if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { /* @@ -259,36 +227,27 @@ static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_secur gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; } - status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, - gensec_security->user.domain); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + nt_status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, + gensec_security->user.domain); + NT_STATUS_NOT_OK_RETURN(nt_status); - status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, - gensec_security->user.name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + nt_status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, + gensec_security->user.name); + NT_STATUS_NOT_OK_RETURN(nt_status); if (gensec_security->user.name) { - status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + nt_status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password); + NT_STATUS_NOT_OK_RETURN(nt_status); } if (password) { - status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, - password); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + nt_status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, password); + NT_STATUS_NOT_OK_RETURN(nt_status); } gensec_security->private_data = gensec_ntlmssp_state; - return status; + return NT_STATUS_OK; } /* @@ -499,19 +458,14 @@ static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_secur { NTSTATUS nt_status; struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data; - nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info); + NT_STATUS_NOT_OK_RETURN(nt_status); (*session_info)->session_key = data_blob_talloc(*session_info, gensec_ntlmssp_state->ntlmssp_state->session_key.data, gensec_ntlmssp_state->ntlmssp_state->session_key.length); - (*session_info)->workstation = talloc_strdup(*session_info, - gensec_ntlmssp_state->ntlmssp_state->workstation); - return NT_STATUS_OK; } diff --git a/source4/libcli/security/security_token.c b/source4/libcli/security/security_token.c index 7bd533dbee..b9baf796df 100644 --- a/source4/libcli/security/security_token.c +++ b/source4/libcli/security/security_token.c @@ -4,6 +4,7 @@ security descriptror utility functions Copyright (C) Andrew Tridgell 2004 + 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 @@ -48,42 +49,46 @@ struct security_token *security_token_initialise(TALLOC_CTX *mem_ctx) Create the SID list for this user. ****************************************************************************/ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx, - struct dom_sid *user_sid, struct dom_sid *group_sid, - int n_groupSIDs, struct dom_sid **groupSIDs, - BOOL is_guest, struct security_token **token) + struct dom_sid *user_sid, + struct dom_sid *group_sid, + int n_groupSIDs, + struct dom_sid **groupSIDs, + BOOL is_authenticated, + struct security_token **token) { struct security_token *ptoken; int i; NTSTATUS status; ptoken = security_token_initialise(mem_ctx); - if (ptoken == NULL) { - return NT_STATUS_NO_MEMORY; - } + NT_STATUS_HAVE_NO_MEMORY(ptoken); ptoken->sids = talloc_array_p(ptoken, struct dom_sid *, n_groupSIDs + 5); - if (!ptoken->sids) { - return NT_STATUS_NO_MEMORY; - } + NT_STATUS_HAVE_NO_MEMORY(ptoken->sids); - ptoken->user_sid = user_sid; - ptoken->group_sid = group_sid; + ptoken->user_sid = talloc_reference(ptoken, user_sid); + ptoken->group_sid = talloc_reference(ptoken, group_sid); ptoken->privilege_mask = 0; - ptoken->sids[0] = user_sid; - ptoken->sids[1] = group_sid; + ptoken->sids[0] = ptoken->user_sid; + ptoken->sids[1] = ptoken->group_sid; /* * Finally add the "standard" SIDs. - * The only difference between guest and "anonymous" (which we - * don't really support) is the addition of Authenticated_Users. + * The only difference between guest and "anonymous" + * is the addition of Authenticated_Users. */ ptoken->sids[2] = dom_sid_parse_talloc(mem_ctx, SID_WORLD); + NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[2]); ptoken->sids[3] = dom_sid_parse_talloc(mem_ctx, SID_NT_NETWORK); - ptoken->sids[4] = dom_sid_parse_talloc(mem_ctx, - is_guest?SID_BUILTIN_GUESTS: - SID_NT_AUTHENTICATED_USERS); - ptoken->num_sids = 5; + NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[3]); + ptoken->num_sids = 4; + + if (is_authenticated) { + ptoken->sids[4] = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHENTICATED_USERS); + NT_STATUS_HAVE_NO_MEMORY(ptoken->sids[4]); + ptoken->num_sids++; + } for (i = 0; i < n_groupSIDs; i++) { size_t check_sid_idx; @@ -96,7 +101,7 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx, } if (check_sid_idx == ptoken->num_sids) { - ptoken->sids[ptoken->num_sids++] = groupSIDs[i]; + ptoken->sids[ptoken->num_sids++] = talloc_reference(ptoken, groupSIDs[i]); } } diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 92e8d0ca38..10852159a8 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -226,25 +226,14 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security, NTSTATUS dcerpc_schannel_session_info(struct gensec_security *gensec_security, struct auth_session_info **session_info) -{ - struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; - +{ (*session_info) = talloc_p(gensec_security, struct auth_session_info); - if (*session_info == NULL) { - return NT_STATUS_NO_MEMORY; - } + NT_STATUS_HAVE_NO_MEMORY(*session_info); ZERO_STRUCTP(*session_info); - (*session_info)->refcount = 1; - - (*session_info)->workstation = talloc_strdup(*session_info, dce_schan_state->account_name); - if ((*session_info)->workstation == NULL) { - talloc_free(*session_info); - return NT_STATUS_NO_MEMORY; - } + return NT_STATUS_OK; } - /** * Return the struct creds_CredentialState. diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index c86ffb2cd0..e4f5818826 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -330,8 +330,7 @@ NTSTATUS dcesrv_endpoint_search_connect(struct dcesrv_context *dce_ctx, return status; } - session_info->refcount++; - (*dce_conn_p)->auth_state.session_info = session_info; + (*dce_conn_p)->auth_state.session_info = talloc_reference((*dce_conn_p), session_info); (*dce_conn_p)->auth_state.session_key = dcesrv_inherited_session_key; /* TODO: check security descriptor of the endpoint here diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 9811c37ace..dd22834c01 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -1556,12 +1556,12 @@ static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX * if (!dce_call->conn->auth_state.session_info || !dce_call->conn->auth_state.session_info->server_info || !dce_call->conn->auth_state.session_info->server_info->account_name || - !dce_call->conn->auth_state.session_info->server_info->domain) { + !dce_call->conn->auth_state.session_info->server_info->domain_name) { return NT_STATUS_INTERNAL_ERROR; } account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name); - authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain); + authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name); _account_name = talloc_p(mem_ctx, struct lsa_String); NTSTATUS_TALLOC_CHECK(_account_name); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 167c4e8ceb..0733a467f7 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -4,6 +4,7 @@ endpoint server for the netlogon pipe Copyright (C) Andrew Bartlett 2004 + 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 @@ -496,90 +497,79 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ creds_des_decrypt(pipe_state->creds, &r->in.logon.password->ntpassword); } - nt_status = make_auth_context_subsystem(pipe_state, &auth_context); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + /* TODO: we need to deny anonymous access here */ + nt_status = auth_context_create(mem_ctx, lp_auth_methods(), &auth_context); + NT_STATUS_NOT_OK_RETURN(nt_status); + + nt_status = auth_get_challenge(auth_context, &chal); + NT_STATUS_NOT_OK_RETURN(nt_status); - chal = auth_context->get_ntlm_challenge(auth_context); - nt_status = make_user_info_netlogon_interactive(auth_context, - &user_info, + nt_status = make_user_info_netlogon_interactive(mem_ctx, r->in.logon.password->identity_info.account_name.string, r->in.logon.password->identity_info.domain_name.string, r->in.logon.password->identity_info.workstation.string, chal, &r->in.logon.password->lmpassword, - &r->in.logon.password->ntpassword); - break; - + &r->in.logon.password->ntpassword, + &user_info); + NT_STATUS_NOT_OK_RETURN(nt_status); + break; case 2: case 6: - nt_status = make_auth_context_fixed(pipe_state, - &auth_context, r->in.logon.network->challenge); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + /* TODO: we need to deny anonymous access here */ + nt_status = auth_context_create(mem_ctx, lp_auth_methods(), &auth_context); + NT_STATUS_NOT_OK_RETURN(nt_status); + + nt_status = auth_context_set_challenge(auth_context, r->in.logon.network->challenge, "netr_LogonSamLogonWithFlags"); + NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = make_user_info_netlogon_network(auth_context, - &user_info, r->in.logon.network->identity_info.account_name.string, r->in.logon.network->identity_info.domain_name.string, r->in.logon.network->identity_info.workstation.string, r->in.logon.network->lm.data, r->in.logon.network->lm.length, - r->in.logon.network->nt.data, r->in.logon.network->nt.length); + r->in.logon.network->nt.data, r->in.logon.network->nt.length, + &user_info); + NT_STATUS_NOT_OK_RETURN(nt_status); break; default: - free_auth_context(&auth_context); return NT_STATUS_INVALID_PARAMETER; } - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - nt_status = auth_context->check_ntlm_password(auth_context, - user_info, - mem_ctx, - &server_info); - - /* keep the auth_context for the life of this call */ - talloc_steal(dce_call, auth_context); - - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } + nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info); + NT_STATUS_NOT_OK_RETURN(nt_status); sam = talloc_p(mem_ctx, struct netr_SamBaseInfo); + NT_STATUS_HAVE_NO_MEMORY(sam); - ZERO_STRUCTP(sam); - sam->last_logon = server_info->last_logon; sam->last_logoff = server_info->last_logoff; sam->acct_expiry = server_info->acct_expiry; sam->last_password_change = server_info->last_password_change; sam->allow_password_change = server_info->allow_password_change; sam->force_password_change = server_info->force_password_change; - - sam->account_name.string = talloc_strdup(mem_ctx, server_info->account_name); - sam->full_name.string = talloc_strdup(mem_ctx, server_info->full_name); - sam->logon_script.string = talloc_strdup(mem_ctx, server_info->logon_script); - sam->profile_path.string = talloc_strdup(mem_ctx, server_info->profile_path); - sam->home_directory.string = talloc_strdup(mem_ctx, server_info->home_directory); - sam->home_drive.string = talloc_strdup(mem_ctx, server_info->home_drive); - + + sam->account_name.string = server_info->account_name; + sam->full_name.string = server_info->full_name; + sam->logon_script.string = server_info->logon_script; + sam->profile_path.string = server_info->profile_path; + sam->home_directory.string = server_info->home_directory; + sam->home_drive.string = server_info->home_drive; + sam->logon_count = server_info->logon_count; sam->bad_password_count = sam->bad_password_count; - sam->rid = server_info->user_sid->sub_auths[server_info->user_sid->num_auths-1]; + sam->rid = server_info->account_sid->sub_auths[server_info->account_sid->num_auths-1]; sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1]; sam->group_count = 0; sam->groupids = NULL; sam->user_flags = 0; /* TODO: w2k3 uses 0x120 - what is this? */ sam->acct_flags = server_info->acct_flags; sam->logon_server.string = lp_netbios_name(); - - sam->domain.string = talloc_strdup(mem_ctx, server_info->domain); - - sam->domain_sid = dom_sid_dup(mem_ctx, server_info->user_sid); + + sam->domain.string = server_info->domain_name; + + sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid); + NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid); sam->domain_sid->num_auths--; if (server_info->user_session_key.length == sizeof(sam->key.key)) { @@ -627,6 +617,7 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ switch (r->in.validation_level) { case 2: sam2 = talloc_p(mem_ctx, struct netr_SamInfo2); + NT_STATUS_HAVE_NO_MEMORY(sam2); ZERO_STRUCTP(sam2); sam2->base = *sam; r->out.validation.sam2 = sam2; @@ -634,6 +625,7 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ case 3: sam3 = talloc_p(mem_ctx, struct netr_SamInfo3); + NT_STATUS_HAVE_NO_MEMORY(sam3); ZERO_STRUCTP(sam3); sam3->base = *sam; r->out.validation.sam3 = sam3; @@ -641,6 +633,7 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ case 6: sam6 = talloc_p(mem_ctx, struct netr_SamInfo6); + NT_STATUS_HAVE_NO_MEMORY(sam6); ZERO_STRUCTP(sam6); sam6->base = *sam; sam6->forest.string = lp_realm(); diff --git a/source4/smb_server/negprot.c b/source4/smb_server/negprot.c index d5e55bf100..77df978a05 100644 --- a/source4/smb_server/negprot.c +++ b/source4/smb_server/negprot.c @@ -24,29 +24,40 @@ /* initialise the auth_context for this server and return the cryptkey */ -static void get_challenge(struct smbsrv_connection *smb_conn, uint8_t buff[8]) +static NTSTATUS get_challenge(struct smbsrv_connection *smb_conn, uint8_t buff[8]) { NTSTATUS nt_status; - const uint8_t *cryptkey; + const uint8_t *challenge; /* muliple negprots are not premitted */ if (smb_conn->negotiate.auth_context) { DEBUG(3,("get challenge: is this a secondary negprot? auth_context is non-NULL!\n")); - smb_panic("secondary negprot"); + return NT_STATUS_FOOBAR; } DEBUG(10, ("get challenge: creating negprot_global_auth_context\n")); - nt_status = make_auth_context_subsystem(smb_conn, &smb_conn->negotiate.auth_context); + nt_status = auth_context_create(smb_conn, lp_auth_methods(), &smb_conn->negotiate.auth_context); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("auth_context_create() returned %s", nt_errstr(nt_status))); + return nt_status; + } + + nt_status = auth_context_create(smb_conn, lp_auth_methods(), &smb_conn->negotiate.auth_context); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("auth_context_create() returned %s", nt_errstr(nt_status))); + return nt_status; + } + nt_status = auth_get_challenge(smb_conn->negotiate.auth_context, &challenge); if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status))); - smb_panic("cannot make_negprot_global_auth_context!\n"); + DEBUG(0, ("auth_get_challenge() returned %s", nt_errstr(nt_status))); + return nt_status; } - DEBUG(10, ("get challenge: getting challenge\n")); - cryptkey = smb_conn->negotiate.auth_context->get_ntlm_challenge(smb_conn->negotiate.auth_context); - memcpy(buff, cryptkey, 8); + memcpy(buff, challenge, 8); + + return NT_STATUS_OK; } /**************************************************************************** @@ -140,8 +151,15 @@ static void reply_lanman1(struct smbsrv_request *req, uint16_t choice) /* Create a token value and add it to the outgoing packet. */ if (req->smb_conn->negotiate.encrypted_passwords) { + NTSTATUS nt_status; + SSVAL(req->out.vwv, VWV(11), 8); - get_challenge(req->smb_conn, req->out.data); + + nt_status = get_challenge(req->smb_conn, req->out.data); + if (!NT_STATUS_IS_OK(nt_status)) { + smbsrv_terminate_connection(req->smb_conn, "LANMAN1 get_challenge failed\n"); + return; + } } if (req->smb_conn->signing.mandatory_signing) { diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index dcecc1327c..bab52e25fe 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -47,43 +47,40 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s struct auth_usersupplied_info *user_info = NULL; struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info; - - TALLOC_CTX *mem_ctx = talloc_named(req, 0, "NT1 session setup"); char *remote_machine; - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_named(req, 0, "OLD session setup"); + NT_STATUS_HAVE_NO_MEMORY(mem_ctx); + if (!req->smb_conn->negotiate.done_sesssetup) { req->smb_conn->negotiate.max_send = sess->old.in.bufsize; } remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); - status = make_user_info_for_reply_enc(req->smb_conn, - &user_info, + status = make_user_info_for_reply_enc(req->smb_conn, sess->old.in.user, sess->old.in.domain, remote_machine, sess->old.in.password, - data_blob(NULL, 0)); + data_blob(NULL, 0), + &user_info); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return NT_STATUS_ACCESS_DENIED; } - status = req->smb_conn->negotiate.auth_context->check_ntlm_password(req->smb_conn->negotiate.auth_context, - user_info, - mem_ctx, - &server_info); + status = auth_check_password(req->smb_conn->negotiate.auth_context, + mem_ctx, user_info, &server_info); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); - return nt_status_squash(status); + return auth_nt_status_squash(status); } /* This references server_info into session_info */ - status = make_session_info(req, server_info, &session_info); + status = auth_generate_session_info(req, server_info, &session_info); talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status)) { - return nt_status_squash(status); + return auth_nt_status_squash(status); } sess->old.out.action = 0; @@ -111,11 +108,10 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s struct auth_usersupplied_info *user_info = NULL; struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info; - TALLOC_CTX *mem_ctx = talloc_named(req, 0, "NT1 session setup"); + TALLOC_CTX *mem_ctx; - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } + mem_ctx = talloc_named(req, 0, "NT1 session setup"); + NT_STATUS_HAVE_NO_MEMORY(mem_ctx); if (!req->smb_conn->negotiate.done_sesssetup) { req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize; @@ -127,53 +123,53 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s if (sess->nt1.in.user && *sess->nt1.in.user) { return NT_STATUS_ACCESS_DENIED; - } else { - make_user_info_guest(req->smb_conn, &user_info); } - - status = make_auth_context_subsystem(req->smb_conn, &auth_context); + status = make_user_info_anonymous(req->smb_conn, &user_info); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return status; } - - status = auth_context->check_ntlm_password(auth_context, - user_info, - mem_ctx, - &server_info); + + /* TODO: should we use just "anonymous" here? */ + status = auth_context_create(req->smb_conn, lp_auth_methods(), &auth_context); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); + return status; + } + + status = auth_check_password(auth_context, mem_ctx, + user_info, &server_info); } else { char *remote_machine; + remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); - status = make_user_info_for_reply_enc(req->smb_conn, - &user_info, + + status = make_user_info_for_reply_enc(req->smb_conn, sess->nt1.in.user, sess->nt1.in.domain, remote_machine, sess->nt1.in.password1, - sess->nt1.in.password2); + sess->nt1.in.password2, + &user_info); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return NT_STATUS_ACCESS_DENIED; } - status = req->smb_conn->negotiate - .auth_context->check_ntlm_password(req->smb_conn->negotiate - .auth_context, - user_info, - req, - &server_info); + status = auth_check_password(req->smb_conn->negotiate.auth_context, + req, user_info, &server_info); } if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); - return nt_status_squash(status); + return auth_nt_status_squash(status); } /* This references server_info into session_info */ - status = make_session_info(mem_ctx, server_info, &session_info); + status = auth_generate_session_info(mem_ctx, server_info, &session_info); if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); - return nt_status_squash(status); + return auth_nt_status_squash(status); } sess->nt1.out.action = 0; @@ -188,14 +184,15 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s &sess->nt1.out.domain); req->session = smbsrv_session_find(req->smb_conn, sess->nt1.out.vuid); - if (session_info->server_info->guest) { + if (!session_info->server_info->authenticated) { return NT_STATUS_OK; } + if (!srv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) { /* Already signing, or disabled */ return NT_STATUS_OK; } - + /* Force check of the request packet, now we know the session key */ req_signing_check_incoming(req); @@ -275,7 +272,7 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup status = gensec_session_key(smb_sess->gensec_ctx, &session_key); if (NT_STATUS_IS_OK(status) - && !smb_sess->session_info->server_info->guest + && smb_sess->session_info->server_info->authenticated && srv_setup_signing(req->smb_conn, &session_key, NULL)) { /* Force check of the request packet, now we know the session key */ req_signing_check_incoming(req); @@ -284,7 +281,7 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup } } else { - status = nt_status_squash(status); + status = auth_nt_status_squash(status); if (smb_sess->gensec_ctx && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { talloc_free(smb_sess->gensec_ctx); diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index 569e1e7cb8..804c8d3c17 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -440,7 +440,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, } mux_printf(mux_id, "GL %s\n", grouplist); - free_session_info(&session_info); + talloc_free(session_info); data_blob_free(&in); return; } @@ -450,7 +450,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, nt_status = gensec_update(*gensec_state, NULL, in, &out); /* don't leak 'bad password'/'no such user' info to the network client */ - nt_status = nt_status_squash(nt_status); + nt_status = auth_nt_status_squash(nt_status); if (out.length) { out_base64 = base64_encode_data_blob(out); @@ -494,7 +494,7 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, reply_code = "AF"; reply_arg = talloc_asprintf(*gensec_state, - "%s%s%s", session_info->server_info->domain, + "%s%s%s", session_info->server_info->domain_name, lp_winbind_separator(), session_info->server_info->account_name); talloc_free(session_info); } -- cgit