diff options
author | Andrew Bartlett <abartlet@samba.org> | 2002-01-05 04:55:41 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2002-01-05 04:55:41 +0000 |
commit | 2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95 (patch) | |
tree | 257e7ba36de49aca7039b32a8611fc8b6dea9555 | |
parent | 5a9c2f74ab0285859a6942bbc06d9e726cc69d19 (diff) | |
download | samba-2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95.tar.gz samba-2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95.tar.bz2 samba-2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95.zip |
I've decided to move the auth code around a bit more...
The auth_authsupplied_info typedef is now just a plain struct - auth_context,
but it has been modified to contain the function pointers to the rest
of the auth subsystem's components.
(Who needs non-static functions anyway?)
In working all this mess out, I fixed a number of memory leaks and moved the
entire auth subsystem over to talloc().
Note that the TALLOC_CTX attached to the auth_context can be rather long-lived,
it is provided for things that are intended to live as long. (The
global_negprot_auth_context lasts the whole life of the smbd).
I've also adjusted a few things in auth_domain.c, mainly passing the domain as
a paramater to a few functions instead of looking up lp_workgroup(). I'm
hopign to make this entire thing a bit more trusted domains (as PDC) freindly
in the near future.
Other than that, I moved a bit of the code around, hence the rather messy diff.
Andrew Bartlett
(This used to be commit 12f5515f556cf39fea98134fe3e2ac4540501048)
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/auth/auth.c | 365 | ||||
-rw-r--r-- | source3/auth/auth_builtin.c | 19 | ||||
-rw-r--r-- | source3/auth/auth_compat.c | 111 | ||||
-rw-r--r-- | source3/auth/auth_domain.c | 51 | ||||
-rw-r--r-- | source3/auth/auth_info.c | 313 | ||||
-rw-r--r-- | source3/auth/auth_rhosts.c | 34 | ||||
-rw-r--r-- | source3/auth/auth_sam.c | 58 | ||||
-rw-r--r-- | source3/auth/auth_server.c | 22 | ||||
-rw-r--r-- | source3/auth/auth_unix.c | 10 | ||||
-rw-r--r-- | source3/auth/auth_util.c | 63 | ||||
-rw-r--r-- | source3/auth/auth_winbind.c | 21 | ||||
-rw-r--r-- | source3/include/auth.h | 34 | ||||
-rw-r--r-- | source3/rpc_server/srv_netlog_nt.c | 62 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 8 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 51 | ||||
-rw-r--r-- | source3/smbd/process.c | 12 | ||||
-rw-r--r-- | source3/smbd/server.c | 6 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 101 |
19 files changed, 690 insertions, 653 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index c0a35b75c7..dacc947d61 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -201,7 +201,7 @@ PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o AUTH_OBJ = auth/auth.o auth/auth_sam.o auth/auth_server.o auth/auth_domain.o \ auth/auth_rhosts.o auth/auth_unix.o auth/auth_util.o auth/auth_winbind.o \ - auth/auth_info.o auth/auth_builtin.o $(PLAINTEXT_AUTH_OBJ) + auth/auth_builtin.o auth/auth_compat.o $(PLAINTEXT_AUTH_OBJ) SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \ diff --git a/source3/auth/auth.c b/source3/auth/auth.c index bfd15dff34..6b68fa631a 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -1,10 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. + Version 3.0. Password and authentication handling - Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Andrew Bartlett 2001 + Copyright (C) Andrew Bartlett 2001-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 @@ -23,6 +21,95 @@ #include "includes.h" +/** List of various built-in authenticaion modules */ + +const struct auth_init_function builtin_auth_init_functions[] = { + { "guest", auth_init_guest }, + { "rhosts", auth_init_rhosts }, + { "hostsequiv", auth_init_hostsequiv }, + { "sam", auth_init_sam }, + { "samstrict", auth_init_samstrict }, + { "unix", auth_init_unix }, + { "smbserver", auth_init_smbserver }, + { "ntdomain", auth_init_ntdomain }, + { "winbind", auth_init_winbind }, +#ifdef DEVELOPER + { "name_to_ntstatus", auth_init_name_to_ntstatus }, +#endif + { NULL, NULL} +}; + +/**************************************************************************** + Try to get a challenge out of the various authenticaion modules. + Returns a const char of length 8 bytes. +****************************************************************************/ + +static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) +{ + DATA_BLOB challenge = data_blob(NULL, 0); + char *challenge_set_by = NULL; + auth_methods *auth_method; + TALLOC_CTX *mem_ctx; + + if (auth_context->challenge.length) { + DEBUG(5, ("get_ntlm_challange (auth subsystem): returning previous challenge (normal)\n")); + return auth_context->challenge.data; + } + + 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)); + 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: authenticaion method %s has already specified a challenge. Challenge by %s ignored.\n", + challenge_set_by, auth_method->name)); + continue; + } + + mem_ctx = talloc_init_named("auth_get_challange for module %s", auth_method->name); + if (!mem_ctx) { + smb_panic("talloc_init_named() failed!"); + } + + challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx); + if (!challenge.length) { + DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion 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) { + uchar chal[8]; + + generate_random_buffer(chal, sizeof(chal), False); + auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, + chal, sizeof(chal)); + + challenge_set_by = "random"; + } + + 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; + + return auth_context->challenge.data; +} + + /** * Check user is in correct domain (if required) * @@ -81,9 +168,9 @@ static BOOL check_domain_match(const char *user, const char *domain) * **/ -NTSTATUS check_password(const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; @@ -91,7 +178,7 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, auth_methods *auth_method; TALLOC_CTX *mem_ctx; - if (!user_info || !auth_info || !server_info) { + if (!user_info || !auth_context || !server_info) { return NT_STATUS_LOGON_FAILURE; } @@ -100,11 +187,11 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, DEBUG(3, ("check_password: mapped user is: [%s]\\[%s]@[%s]\n", user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str)); - if (auth_info->challenge_set_by) { - DEBUG(10, ("auth_info challenge created by %s\n", auth_info->challenge_set_by)); + if (auth_context->challenge_set_by) { + DEBUG(10, ("auth_context challenge created by %s\n", auth_context->challenge_set_by)); } DEBUG(10, ("challenge is: \n")); - dump_data(5, (auth_info)->challenge.data, (auth_info)->challenge.length); + dump_data(5, auth_context->challenge.data, auth_context->challenge.length); #ifdef DEBUG_PASSWORD DEBUG(100, ("user_info has passwords of length %d and %d\n", @@ -120,12 +207,12 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, return NT_STATUS_LOGON_FAILURE; } - for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next) + for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) { mem_ctx = talloc_init_named("%s authentication for user %s\\%s", auth_method->name, user_info->domain.str, user_info->smb_name.str); - nt_status = auth_method->auth(auth_method->private_data, mem_ctx, user_info, auth_info, server_info); + nt_status = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n", auth_method->name, user_info->smb_name.str)); @@ -182,124 +269,188 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, ZERO_STRUCTP(server_info); } return nt_status; - } -/** - * Squash an NT_STATUS in line with security requirements. - * In an attempt to avoid giving the whole game away when users - * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and - * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations - * (session setups in particular). - * - * @param nt_status NTSTATUS input for squashing. - * @return the 'squashed' nt_status - **/ +/*************************************************************************** + Clear out a auth_context, and destroy the attached TALLOC_CTX +***************************************************************************/ -NTSTATUS nt_status_squash(NTSTATUS nt_status) +static void free_auth_context(struct auth_context **auth_context) { - if NT_STATUS_IS_OK(nt_status) { - return nt_status; - } else 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; - } + if (*auth_context != NULL) { + talloc_destroy((*auth_context)->mem_ctx); + } + *auth_context = NULL; } +/*************************************************************************** + Make a auth_info struct +***************************************************************************/ +static NTSTATUS make_auth_context(struct auth_context **auth_context) +{ + TALLOC_CTX *mem_ctx; -/**************************************************************************** - COMPATABILITY INTERFACES: - ***************************************************************************/ + mem_ctx = talloc_init_named("authentication context"); + + *auth_context = talloc(mem_ctx, sizeof(**auth_context)); + if (!*auth_context) { + DEBUG(0,("make_auth_context: talloc failed!\n")); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + ZERO_STRUCTP(*auth_context); -/**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash -return True if the password is correct, False otherwise -****************************************************************************/ + (*auth_context)->mem_ctx = mem_ctx; + (*auth_context)->check_ntlm_password = check_ntlm_password; + (*auth_context)->get_ntlm_challenge = get_ntlm_challenge; + (*auth_context)->free = free_auth_context; + + return NT_STATUS_OK; +} -static NTSTATUS pass_check_smb(char *smb_name, - char *domain, - DATA_BLOB lm_pwd, - DATA_BLOB nt_pwd, - DATA_BLOB plaintext_password, - BOOL encrypted) +/*************************************************************************** + Make a auth_info struct for the auth subsystem +***************************************************************************/ +static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, char **text_list) { + auth_methods *list = NULL; + auth_methods *t = NULL; + auth_methods *tmp; + int i; NTSTATUS nt_status; - auth_usersupplied_info *user_info = NULL; - extern auth_authsupplied_info *negprot_global_auth_info; - auth_serversupplied_info *server_info = NULL; - if (encrypted) { - make_user_info_for_reply_enc(&user_info, smb_name, - domain, - lm_pwd, - nt_pwd, - plaintext_password); - nt_status = check_password(user_info, negprot_global_auth_info, &server_info); - } else { - auth_authsupplied_info *plaintext_auth_info = NULL; - DATA_BLOB chal; - if (!make_auth_info_subsystem(&plaintext_auth_info)) { - return NT_STATUS_NO_MEMORY; - } - - chal = auth_get_challenge(plaintext_auth_info); - if (!make_user_info_for_reply(&user_info, - smb_name, domain, chal.data, - plaintext_password)) { - return NT_STATUS_NO_MEMORY; + if (!text_list) { + DEBUG(2,("No auth method list!?\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context))) { + return nt_status; + } + + for (;*text_list; text_list++) + { + DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list)); + for (i = 0; builtin_auth_init_functions[i].name; i++) + { + if (strequal(builtin_auth_init_functions[i].name, *text_list)) + { + DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i)); + if (builtin_auth_init_functions[i].init(*auth_context, &t)) { + DEBUG(5,("auth method %s has a valid init\n", *text_list)); + t->name = builtin_auth_init_functions[i].name; + DLIST_ADD_END(list, t, tmp); + } else { + DEBUG(0,("auth method %s did not correctly init\n", *text_list)); + } + break; + } } - - nt_status = check_password(user_info, plaintext_auth_info, &server_info); - - data_blob_free(&chal); - free_auth_info(&plaintext_auth_info); - } - free_user_info(&user_info); - free_server_info(&server_info); + } + + (*auth_context)->auth_method_list = list; + return nt_status; } -/**************************************************************************** -check if a username/password pair is OK either via the system password -database or the encrypted SMB password database -return True if the password is correct, False otherwise -****************************************************************************/ -BOOL password_ok(char *smb_name, DATA_BLOB password_blob) +/*************************************************************************** + Make a auth_context struct for the auth subsystem +***************************************************************************/ + +NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) { + char **auth_method_list = NULL; + NTSTATUS nt_status; - DATA_BLOB null_password = data_blob(NULL, 0); - extern BOOL global_encrypted_passwords_negotiated; - BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24); - - if (encrypted) { - /* - * The password could be either NTLM or plain LM. Try NTLM first, - * but fall-through as required. - * NTLMv2 makes no sense here. - */ - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) { - return True; - } - - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) { - return True; + if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) { + return NT_STATUS_NO_MEMORY; + } + + if (auth_method_list == NULL) { + switch (lp_security()) + { + case SEC_DOMAIN: + DEBUG(5,("Making default auth method list for security=domain\n")); + auth_method_list = lp_list_make("guest samstrict ntdomain"); + break; + case SEC_SERVER: + DEBUG(5,("Making default auth method list for security=server\n")); + auth_method_list = lp_list_make("guest samstrict smbserver"); + break; + case SEC_USER: + if (lp_encrypted_passwords()) { + DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n")); + auth_method_list = lp_list_make("guest sam"); + } else { + DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n")); + auth_method_list = lp_list_make("guest unix"); + } + break; + case SEC_SHARE: + if (lp_encrypted_passwords()) { + DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n")); + auth_method_list = lp_list_make("guest sam"); + } else { + DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n")); + auth_method_list = lp_list_make("guest unix"); + } + break; + case SEC_ADS: + DEBUG(5,("Making default auth method list for security=ADS\n")); + auth_method_list = lp_list_make("guest samstrict ads ntdomain"); + break; + default: + DEBUG(5,("Unknown auth method!\n")); + return NT_STATUS_UNSUCCESSFUL; } } else { - if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { - return True; - } + DEBUG(5,("Using specified auth order\n")); + } + + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_text_list(auth_context, auth_method_list))) { + lp_list_free(&auth_method_list); + return nt_status; + } + + lp_list_free(&auth_method_list); + return nt_status; +} + +/*************************************************************************** + Make a auth_info struct with a random challenge +***************************************************************************/ + +NTSTATUS make_auth_context_random(struct auth_context **auth_context) +{ + uchar chal[8]; + NTSTATUS nt_status; + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) { + return nt_status; } + + generate_random_buffer(chal, sizeof(chal), False); + (*auth_context)->challenge = data_blob(chal, sizeof(chal)); + + (*auth_context)->challenge_set_by = "random"; + + return nt_status; +} + +/*************************************************************************** + Make a auth_info struct with a fixed challenge +***************************************************************************/ - return False; +NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[8]) +{ + NTSTATUS nt_status; + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) { + return nt_status; + } + + (*auth_context)->challenge = data_blob(chal, 8); + return nt_status; } diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c index f76987f685..f1c89689fa 100644 --- a/source3/auth/auth_builtin.c +++ b/source3/auth/auth_builtin.c @@ -29,10 +29,10 @@ * and pass onto the next module. **/ -static NTSTATUS check_guest_security(void *my_private_data, +static NTSTATUS check_guest_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; @@ -50,9 +50,9 @@ static NTSTATUS check_guest_security(void *my_private_data, } /* Guest modules initialisation */ -BOOL auth_init_guest(auth_methods **auth_method) +BOOL auth_init_guest(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } @@ -73,10 +73,10 @@ BOOL auth_init_guest(auth_methods **auth_method) * @return An NTSTATUS value based on the username **/ -static NTSTATUS check_name_to_ntstatus_security(void *my_private_data, +static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; @@ -100,9 +100,9 @@ static NTSTATUS check_name_to_ntstatus_security(void *my_private_data, } /** Module initailisation function */ -BOOL auth_init_name_to_ntstatus(auth_methods **auth_method) +BOOL auth_init_name_to_ntstatus(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } @@ -110,6 +110,3 @@ BOOL auth_init_name_to_ntstatus(auth_methods **auth_method) return True; } - - - diff --git a/source3/auth/auth_compat.c b/source3/auth/auth_compat.c new file mode 100644 index 0000000000..4039f0cc1e --- /dev/null +++ b/source3/auth/auth_compat.c @@ -0,0 +1,111 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0. + Password and authentication handling + Copyright (C) Andrew Bartlett 2001-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" + +/**************************************************************************** + COMPATABILITY INTERFACES: + ***************************************************************************/ + +/**************************************************************************** +check if a username/password is OK assuming the password is a 24 byte +SMB hash +return True if the password is correct, False otherwise +****************************************************************************/ + +static NTSTATUS pass_check_smb(char *smb_name, + char *domain, + DATA_BLOB lm_pwd, + DATA_BLOB nt_pwd, + DATA_BLOB plaintext_password, + BOOL encrypted) + +{ + NTSTATUS nt_status; + auth_usersupplied_info *user_info = NULL; + extern struct auth_context *negprot_global_auth_context; + auth_serversupplied_info *server_info = NULL; + if (encrypted) { + make_user_info_for_reply_enc(&user_info, smb_name, + domain, + lm_pwd, + nt_pwd); + nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, + user_info, &server_info); + } else { + struct auth_context *plaintext_auth_context = NULL; + const uint8 *chal; + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { + return nt_status; + } + + chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); + + if (!make_user_info_for_reply(&user_info, + smb_name, domain, chal, + plaintext_password)) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, + user_info, &server_info); + + plaintext_auth_context->free(&plaintext_auth_context); + } + free_user_info(&user_info); + free_server_info(&server_info); + return nt_status; +} + +/**************************************************************************** +check if a username/password pair is ok via the auth subsystem. +return True if the password is correct, False otherwise +****************************************************************************/ +BOOL password_ok(char *smb_name, DATA_BLOB password_blob) +{ + + DATA_BLOB null_password = data_blob(NULL, 0); + extern BOOL global_encrypted_passwords_negotiated; + BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24); + + if (encrypted) { + /* + * The password could be either NTLM or plain LM. Try NTLM first, + * but fall-through as required. + * NTLMv2 makes no sense here. + */ + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) { + return True; + } + + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) { + return True; + } + } else { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { + return True; + } + } + + return False; +} + + diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 6e3eb643d8..e836375406 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -125,8 +125,10 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); Utility function to attempt a connection to an IP address of a DC. ************************************************************************/ -static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, struct in_addr *ip, - unsigned char *trust_passwd) +static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, + const char *domain, + struct in_addr *ip, + unsigned char *trust_passwd) { fstring dc_name; @@ -137,7 +139,7 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, struct in_addr *ip if (is_zero_ip(*ip)) return NT_STATUS_UNSUCCESSFUL; - if (!lookup_dc_name(global_myname, lp_workgroup(), ip, dc_name)) + if (!lookup_dc_name(global_myname, domain, ip, dc_name)) return NT_STATUS_UNSUCCESSFUL; return connect_to_domain_password_server(cli, dc_name, trust_passwd); @@ -145,11 +147,12 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, struct in_addr *ip /*********************************************************************** We have been asked to dynamcially determine the IP addresses of - the PDC and BDC's for this DOMAIN, and query them in turn. + the PDC and BDC's for DOMAIN, and query them in turn. ************************************************************************/ static NTSTATUS find_connect_pdc(struct cli_state **cli, - unsigned char *trust_passwd, - time_t last_change_time) + const char *domain, + unsigned char *trust_passwd, + time_t last_change_time) { struct in_addr *ip_list = NULL; int count = 0; @@ -169,7 +172,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, if (time_now - last_change_time < 3600) use_pdc_only = True; - if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count)) + if (!get_dc_list(use_pdc_only, domain, &ip_list, &count)) return NT_STATUS_UNSUCCESSFUL; /* @@ -180,7 +183,9 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, if(!is_local_net(ip_list[i])) continue; - if(NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, &ip_list[i], trust_passwd))) + if(NT_STATUS_IS_OK(nt_status = + attempt_connect_to_dc(cli, domain, + &ip_list[i], trust_passwd))) break; zero_ip(&ip_list[i]); /* Tried and failed. */ @@ -192,7 +197,9 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, if(!NT_STATUS_IS_OK(nt_status)) { i = (sys_random() % count); - if (!NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, &ip_list[i], trust_passwd))) + if (!NT_STATUS_IS_OK(nt_status = + attempt_connect_to_dc(cli, domain, + &ip_list[i], trust_passwd))) zero_ip(&ip_list[i]); /* Tried and failed. */ } @@ -206,7 +213,9 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, * Note that from a WINS server the #1 IP address is the PDC. */ for(i = 0; i < count; i++) { - if (NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, &ip_list[i], trust_passwd))) + if (NT_STATUS_IS_OK(nt_status = + attempt_connect_to_dc(cli, domain, + &ip_list[i], trust_passwd))) break; } } @@ -224,6 +233,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, + const char *domain, uchar chal[8], auth_serversupplied_info **server_info, char *server, unsigned char *trust_passwd, @@ -246,7 +256,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, while (!NT_STATUS_IS_OK(nt_status) && next_token(&server,remote_machine,LIST_SEP,sizeof(remote_machine))) { if(strequal(remote_machine, "*")) { - nt_status = find_connect_pdc(&cli, trust_passwd, last_change_time); + nt_status = find_connect_pdc(&cli, domain, trust_passwd, last_change_time); } else { nt_status = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); } @@ -376,18 +386,19 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, Check for a valid username and password in security=domain mode. ****************************************************************************/ -static NTSTATUS check_ntdomain_security(void *my_private_data, +static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; char *p, *pserver; unsigned char trust_passwd[16]; time_t last_change_time; + char *domain = lp_workgroup(); - if (!user_info || !server_info || !auth_info) { + if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n")); return NT_STATUS_LOGON_FAILURE; } @@ -409,7 +420,7 @@ static NTSTATUS check_ntdomain_security(void *my_private_data, * Get the machine account password for our primary domain */ - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time)) + if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time)) { DEBUG(0, ("check_domain_security: could not fetch trust account password for domain %s\n", lp_workgroup())); unbecome_root(); @@ -433,18 +444,22 @@ static NTSTATUS check_ntdomain_security(void *my_private_data, if (! *pserver) pserver = "*"; p = pserver; - nt_status = domain_client_validate(mem_ctx, user_info, (uchar *)auth_info->challenge.data,server_info, + nt_status = domain_client_validate(mem_ctx, user_info, domain, + (uchar *)auth_context->challenge.data, + server_info, p, trust_passwd, last_change_time); return nt_status; } -BOOL auth_init_ntdomain(auth_methods **auth_method) +/* module initialisation */ +BOOL auth_init_ntdomain(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } (*auth_method)->auth = check_ntdomain_security; return True; } + diff --git a/source3/auth/auth_info.c b/source3/auth/auth_info.c deleted file mode 100644 index 9d399a88eb..0000000000 --- a/source3/auth/auth_info.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 3.0. - Authentication utility functions - Copyright (C) Andrew Bartlett 2001 - - 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" - -/** List of various built-in authenticaion modules */ - -const struct auth_init_function builtin_auth_init_functions[] = { - { "guest", auth_init_guest }, - { "rhosts", auth_init_rhosts }, - { "hostsequiv", auth_init_hostsequiv }, - { "sam", auth_init_sam }, - { "samstrict", auth_init_samstrict }, - { "unix", auth_init_unix }, - { "smbserver", auth_init_smbserver }, - { "ntdomain", auth_init_ntdomain }, - { "winbind", auth_init_winbind }, -#ifdef DEVELOPER - { "name_to_ntstatus", auth_init_name_to_ntstatus }, -#endif - { NULL, NULL} -}; - -/*************************************************************************** - Free a linked list of auth methods -***************************************************************************/ - -static void free_auth_methods_list(auth_methods **list) -{ - if (list != NULL) { - while (*list) { - auth_methods *old_head = *list; - if ((*list)->free_private_data) { - (*list)->free_private_data(&((*list)->private_data)); - } - DLIST_REMOVE(*list, *list); - SAFE_FREE(old_head); - } - - } -} - -/*************************************************************************** - Make a auth_info struct -***************************************************************************/ - -static BOOL make_auth_info(auth_authsupplied_info **auth_info) -{ - *auth_info = malloc(sizeof(**auth_info)); - if (!*auth_info) { - DEBUG(0,("make_auth_info: malloc failed!\n")); - return False; - } - ZERO_STRUCTP(*auth_info); - - return True; -} - -/*************************************************************************** - Make a auth_info struct with a specified list. -***************************************************************************/ - -BOOL make_auth_info_list(auth_authsupplied_info **auth_info, auth_methods *list) -{ - if (!make_auth_info(auth_info)) { - return False; - } - - (*auth_info)->auth_method_list = list; - - return True; -} - -/*************************************************************************** - Make a auth_info struct for the auth subsystem -***************************************************************************/ - -static BOOL make_auth_info_text_list(auth_authsupplied_info **auth_info, char **text_list) -{ - auth_methods *list = NULL; - auth_methods *t = NULL; - auth_methods *tmp; - int i; - - if (!text_list) { - DEBUG(2,("No auth method list!?\n")); - return False; - } - - for (;*text_list; text_list++) - { - DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list)); - for (i = 0; builtin_auth_init_functions[i].name; i++) - { - if (strequal(builtin_auth_init_functions[i].name, *text_list)) - { - DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i)); - if (builtin_auth_init_functions[i].init(&t)) { - DEBUG(5,("auth method %s has a valid init\n", *text_list)); - t->name = builtin_auth_init_functions[i].name; - DLIST_ADD_END(list, t, tmp); - } else { - DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list)); - } - break; - } - } - } - - if (!make_auth_info_list(auth_info, list)) { - free_auth_methods_list(&list); - return False; - } - - return True; -} - -/*************************************************************************** - Make a auth_info struct for the auth subsystem -***************************************************************************/ - -BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info) -{ - char **auth_method_list = NULL; - - if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) { - return False; - } - - if (auth_method_list == NULL) { - switch (lp_security()) - { - case SEC_DOMAIN: - DEBUG(5,("Making default auth method list for security=domain\n")); - auth_method_list = lp_list_make("guest samstrict ntdomain"); - break; - case SEC_SERVER: - DEBUG(5,("Making default auth method list for security=server\n")); - auth_method_list = lp_list_make("guest samstrict smbserver"); - break; - case SEC_USER: - if (lp_encrypted_passwords()) { - DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n")); - auth_method_list = lp_list_make("guest sam"); - } else { - DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n")); - auth_method_list = lp_list_make("guest unix"); - } - break; - case SEC_SHARE: - if (lp_encrypted_passwords()) { - DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n")); - auth_method_list = lp_list_make("guest sam"); - } else { - DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n")); - auth_method_list = lp_list_make("guest unix"); - } - break; - case SEC_ADS: - DEBUG(5,("Making default auth method list for security=ADS\n")); - auth_method_list = lp_list_make("guest samstrict ads ntdomain"); - break; - default: - DEBUG(5,("Unknown auth method!\n")); - return False; - } - } else { - DEBUG(5,("Using specified auth order\n")); - } - - if (!make_auth_info_text_list(auth_info, auth_method_list)) { - lp_list_free(&auth_method_list); - return False; - } - - lp_list_free(&auth_method_list); - return True; -} - -/*************************************************************************** - Make a auth_info struct with a random challenge -***************************************************************************/ - -BOOL make_auth_info_random(auth_authsupplied_info **auth_info) -{ - uchar chal[8]; - if (!make_auth_info_subsystem(auth_info)) { - return False; - } - - generate_random_buffer(chal, sizeof(chal), False); - (*auth_info)->challenge = data_blob(chal, sizeof(chal)); - - (*auth_info)->challenge_set_by = "random"; - - return True; -} - -/*************************************************************************** - Make a auth_info struct with a fixed challenge -***************************************************************************/ - -BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) -{ - if (!make_auth_info_subsystem(auth_info)) { - return False; - } - - (*auth_info)->challenge = data_blob(chal, 8); - return True; -} - -/*************************************************************************** - Clear out a auth_info struct that has been allocated -***************************************************************************/ - -void free_auth_info(auth_authsupplied_info **auth_info) -{ - if (*auth_info != NULL) { - free_auth_methods_list(&(*auth_info)->auth_method_list); - - data_blob_free(&(*auth_info)->challenge); - ZERO_STRUCT(**auth_info); - } - SAFE_FREE(*auth_info); -} - -/**************************************************************************** - Try to get a challenge out of the various authenticaion modules. - It is up to the caller to free it. -****************************************************************************/ - -DATA_BLOB auth_get_challenge(auth_authsupplied_info *auth_info) -{ - DATA_BLOB challenge = data_blob(NULL, 0); - char *challenge_set_by = NULL; - auth_methods *auth_method; - TALLOC_CTX *mem_ctx; - - if (auth_info->challenge.length) { - DEBUG(5, ("auth_get_challenge: returning previous challenge (normal)\n")); - return data_blob(auth_info->challenge.data, auth_info->challenge.length); - } - - for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next) - { - if (auth_method->get_chal) { - DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name)); - if (challenge_set_by) { - DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge. Challenge by %s ignored.\n", - challenge_set_by, auth_method->name)); - } else { - mem_ctx = talloc_init_named("auth_get_challange for module %s", auth_method->name); - if (!mem_ctx) { - smb_panic("talloc_init_named() failed!"); - } - - challenge = auth_method->get_chal(&auth_method->private_data, mem_ctx, auth_info); - if (challenge.length) { - DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name)); - auth_info->challenge = challenge; - challenge_set_by = auth_method->name; - auth_info->challenge_set_method = auth_method; - } else { - DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n", - auth_method->name)); - } - talloc_destroy(mem_ctx); - } - } else { - DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name)); - } - } - - if (!challenge_set_by) { - uchar chal[8]; - - generate_random_buffer(chal, sizeof(chal), False); - auth_info->challenge = data_blob(chal, sizeof(chal)); - - challenge_set_by = "random"; - } - - DEBUG(5, ("auth_info challenge created by %s\n", challenge_set_by)); - DEBUG(5, ("challenge is: \n")); - dump_data(5, auth_info->challenge.data, (auth_info)->challenge.length); - - SMB_ASSERT(auth_info->challenge.length == 8); - - auth_info->challenge_set_by=challenge_set_by; - - return data_blob(auth_info->challenge.data, auth_info->challenge.length); -} - - diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c index 1dd97872da..55ff7aa060 100644 --- a/source3/auth/auth_rhosts.c +++ b/source3/auth/auth_rhosts.c @@ -155,10 +155,10 @@ static BOOL check_hosts_equiv(struct passwd *pass) Check for a valid .rhosts/hosts.equiv entry for this user ****************************************************************************/ -static NTSTATUS check_hostsequiv_security(void *my_private_data, +static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; @@ -176,15 +176,26 @@ static NTSTATUS check_hostsequiv_security(void *my_private_data, return nt_status; } +/* module initialisation */ +BOOL auth_init_hostsequiv(struct auth_context *auth_context, auth_methods **auth_method) +{ + if (!make_auth_methods(auth_context, auth_method)) { + return False; + } + + (*auth_method)->auth = check_hostsequiv_security; + return True; +} + /**************************************************************************** Check for a valid .rhosts/hosts.equiv entry for this user ****************************************************************************/ -static NTSTATUS check_rhosts_security(void *my_private_data, +static NTSTATUS check_rhosts_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; @@ -209,22 +220,13 @@ static NTSTATUS check_rhosts_security(void *my_private_data, return nt_status; } -BOOL auth_init_hostsequiv(auth_methods **auth_method) +/* module initialisation */ +BOOL auth_init_rhosts(struct auth_context *auth_context, auth_methods **auth_method) { - - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } - (*auth_method)->auth = check_hostsequiv_security; - return True; -} -BOOL auth_init_rhosts(auth_methods **auth_method) -{ - - if (!make_auth_methods(auth_method)) { - return False; - } (*auth_method)->auth = check_rhosts_security; return True; } diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index c8b5386f7a..f1bcae461e 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -27,9 +27,9 @@ core of smb password checking routine. ****************************************************************************/ static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, - const uchar *part_passwd, - DATA_BLOB sec_blob, - uint8 user_sess_key[16]) + const uchar *part_passwd, + DATA_BLOB sec_blob, + uint8 user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar p24[24]; @@ -75,10 +75,10 @@ static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, core of smb password checking routine. ****************************************************************************/ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, - const uchar *part_passwd, - const DATA_BLOB sec_blob, - const char *user, const char *domain, - uint8 user_sess_key[16]) + const uchar *part_passwd, + const DATA_BLOB sec_blob, + const char *user, const char *domain, + uint8 user_sess_key[16]) { /* Finish the encryption of part_passwd. */ uchar kr[16]; @@ -132,10 +132,10 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, 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(TALLOC_CTX *mem_ctx, +static NTSTATUS sam_password_ok(const struct auth_context *auth_context, + TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, uint8 user_sess_key[16]) { uint16 acct_ctrl; @@ -175,7 +175,7 @@ static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx, */ DEBUG(4,("sam_password_ok: Checking NTLMv2 password\n")); if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, auth_info->challenge, + nt_pw, auth_context->challenge, user_info->smb_name.str, user_info->client_domain.str, user_sess_key)) @@ -192,7 +192,7 @@ static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx, */ DEBUG(4,("sam_password_ok: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, auth_info->challenge, + nt_pw, auth_context->challenge, user_sess_key)) { return NT_STATUS_OK; @@ -225,7 +225,7 @@ static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx, DEBUG(4,("sam_password_ok: Checking LM password\n")); if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, auth_info->challenge, + lm_pw, auth_context->challenge, user_sess_key)) { return NT_STATUS_OK; @@ -337,10 +337,10 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -static NTSTATUS check_sam_security(void *my_private_data, +static NTSTATUS check_sam_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; @@ -349,8 +349,8 @@ static NTSTATUS check_sam_security(void *my_private_data, uint8 user_sess_key[16]; const uint8* lm_hash; - if (!user_info || !auth_info) { - return NT_STATUS_LOGON_FAILURE; + if (!user_info || !auth_context) { + return NT_STATUS_UNSUCCESSFUL; } if (!pdb_init_sam(&sampass)) { @@ -370,7 +370,7 @@ static NTSTATUS check_sam_security(void *my_private_data, return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(mem_ctx, sampass, user_info, auth_info, user_sess_key); + nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); @@ -399,9 +399,10 @@ static NTSTATUS check_sam_security(void *my_private_data, return nt_status; } -BOOL auth_init_sam(auth_methods **auth_method) +/* module initialisation */ +BOOL auth_init_sam(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } @@ -409,20 +410,19 @@ BOOL auth_init_sam(auth_methods **auth_method) return True; } + /**************************************************************************** -check if a username/password is OK assuming the password is a 24 byte -SMB hash supplied in the user_info structure -return an NT_STATUS constant. +Check SAM security (above) but with a few extra checks. ****************************************************************************/ -static NTSTATUS check_samstrict_security(void *my_private_data, +static NTSTATUS check_samstrict_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { - if (!user_info || !auth_info) { + if (!user_info || !auth_context) { return NT_STATUS_LOGON_FAILURE; } @@ -434,12 +434,13 @@ static NTSTATUS check_samstrict_security(void *my_private_data, return NT_STATUS_NO_SUCH_USER; } - return check_sam_security(my_private_data, mem_ctx, user_info, auth_info, server_info); + return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info); } -BOOL auth_init_samstrict(auth_methods **auth_method) +/* module initialisation */ +BOOL auth_init_samstrict(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } @@ -447,3 +448,4 @@ BOOL auth_init_samstrict(auth_methods **auth_method) return True; } + diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index 7178e3147c..c83230b716 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -134,9 +134,9 @@ static void send_server_keepalive(void **private_data_pointer) Get the challenge out of a password server. ****************************************************************************/ -static DATA_BLOB auth_get_challenge_server(void **my_private_data, - TALLOC_CTX *mem_ctx, - const struct authsupplied_info *auth_info) +static DATA_BLOB auth_get_challenge_server(const struct auth_context *auth_context, + void **my_private_data, + TALLOC_CTX *mem_ctx) { struct cli_state *cli = server_cryptkey(mem_ctx); @@ -161,8 +161,10 @@ static DATA_BLOB auth_get_challenge_server(void **my_private_data, } *my_private_data = (void *)cli; - - return data_blob(cli->secblob.data,8); + + /* The return must be allocated on the caller's mem_ctx, as our own will be + destoyed just after the call. */ + return data_blob_talloc(auth_context->mem_ctx, cli->secblob.data,8); } else { return data_blob(NULL, 0); } @@ -174,10 +176,10 @@ static DATA_BLOB auth_get_challenge_server(void **my_private_data, - Validate a password with the password server. ****************************************************************************/ -static NTSTATUS check_smbserver_security(void *my_private_data, +static NTSTATUS check_smbserver_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { struct cli_state *cli; @@ -218,7 +220,7 @@ static NTSTATUS check_smbserver_security(void *my_private_data, return NT_STATUS_LOGON_FAILURE; } } else { - if (memcmp(cli->secblob.data, auth_info->challenge.data, 8) != 0) { + if (memcmp(cli->secblob.data, auth_context->challenge.data, 8) != 0) { DEBUG(1,("the challenge that the password server (%s) supplied us is not the one we gave our client. This just can't work :-(\n", cli->desthost)); return NT_STATUS_LOGON_FAILURE; } @@ -353,9 +355,9 @@ use this machine as the password server.\n")); return(nt_status); } -BOOL auth_init_smbserver(auth_methods **auth_method) +BOOL auth_init_smbserver(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } (*auth_method)->auth = check_smbserver_security; diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c index fa889af5f6..69c24b8213 100644 --- a/source3/auth/auth_unix.c +++ b/source3/auth/auth_unix.c @@ -83,10 +83,10 @@ static BOOL update_smbpassword_file(char *user, char *password) * unless the account has a null password. **/ -NTSTATUS check_unix_security(void *my_private_data, +static NTSTATUS check_unix_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; @@ -120,11 +120,13 @@ NTSTATUS check_unix_security(void *my_private_data, return nt_status; } -BOOL auth_init_unix(auth_methods **auth_method) +/* module initialisation */ +BOOL auth_init_unix(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } + (*auth_method)->auth = check_unix_security; return True; } diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index d9f3098e7c..a479f52ab2 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -276,13 +276,13 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - char *wksta_name, - uchar chal[8], - uchar lm_interactive_pwd[16], - uchar nt_interactive_pwd[16], - uchar *dc_sess_key) + const char *smb_name, + const char *client_domain, + const char *wksta_name, + const uchar chal[8], + const uchar lm_interactive_pwd[16], + const uchar nt_interactive_pwd[16], + const uchar *dc_sess_key) { char lm_pwd[16]; char nt_pwd[16]; @@ -360,7 +360,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - unsigned char chal[8], + const uint8 chal[8], DATA_BLOB plaintext_password) { @@ -383,7 +383,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, dump_data(100, plaintext_password.data, plaintext_password.length); #endif - SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); + SMBencrypt( (const uchar *)plaintext_password.data, (const uchar*)chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); /* We can't do an NT hash here, as the password needs to be @@ -415,8 +415,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, BOOL make_user_info_for_reply_enc(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - DATA_BLOB lm_resp, DATA_BLOB nt_resp, - DATA_BLOB plaintext_password) + DATA_BLOB lm_resp, DATA_BLOB nt_resp) { uint32 ntlmssp_flags = 0; @@ -572,9 +571,17 @@ BOOL make_server_info_guest(auth_serversupplied_info **server_info) Make an auth_methods struct ***************************************************************************/ -BOOL make_auth_methods(auth_methods **auth_method) +BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) { - *auth_method = malloc(sizeof(**auth_method)); + if (!auth_context) { + smb_panic("no auth_context supplied to make_auth_methods()!\n"); + } + + if (!auth_method) { + smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n"); + } + + *auth_method = talloc(auth_context->mem_ctx, sizeof(**auth_method)); if (!*auth_method) { DEBUG(0,("make_auth_method: malloc failed!\n")); return False; @@ -623,3 +630,33 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) return token; } + +/** + * Squash an NT_STATUS in line with security requirements. + * In an attempt to avoid giving the whole game away when users + * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and + * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations + * (session setups in particular). + * + * @param nt_status NTSTATUS input for squashing. + * @return the 'squashed' nt_status + **/ + +NTSTATUS 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) { + /* 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; + } +} + + + diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c index 74654f8bba..175e14a9d6 100644 --- a/source3/auth/auth_winbind.c +++ b/source3/auth/auth_winbind.c @@ -33,10 +33,10 @@ NSS_STATUS winbindd_request(int req_type, /* Authenticate a user with a challenge/response */ -static NTSTATUS check_winbind_security(void *my_private_data, +static NTSTATUS check_winbind_security(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, - const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { struct winbindd_request request; @@ -46,13 +46,13 @@ static NTSTATUS check_winbind_security(void *my_private_data, NTSTATUS nt_status; if (!user_info) { - return NT_STATUS_LOGON_FAILURE; + return NT_STATUS_UNSUCCESSFUL; } - if (!auth_info) { + 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_LOGON_FAILURE; + return NT_STATUS_UNSUCCESSFUL; } /* Send off request */ @@ -63,7 +63,7 @@ static NTSTATUS check_winbind_security(void *my_private_data, snprintf(request.data.auth_crap.user, sizeof(request.data.auth_crap.user), "%s\\%s", user_info->domain.str, user_info->smb_name.str); - memcpy(request.data.auth_crap.chal, auth_info->challenge.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)); @@ -97,16 +97,13 @@ static NTSTATUS check_winbind_security(void *my_private_data, return nt_status; } -BOOL auth_init_winbind(auth_methods **auth_method) +/* module initialisation */ +BOOL auth_init_winbind(struct auth_context *auth_context, auth_methods **auth_method) { - if (!make_auth_methods(auth_method)) { + if (!make_auth_methods(auth_context, auth_method)) { return False; } (*auth_method)->auth = check_winbind_security; return True; } - - - - diff --git a/source3/include/auth.h b/source3/include/auth.h index b823e7bf4b..fb48616273 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -41,7 +41,7 @@ typedef struct interactive_password OWF_INFO nt_owf; /* NT OWF Password */ } auth_interactive_password; -typedef struct usersupplied_info +typedef struct auth_usersupplied_info { DATA_BLOB lm_resp; @@ -67,7 +67,7 @@ typedef struct usersupplied_info #define SAM_FILL_UNIX 0x08 #define SAM_FILL_ALL (SAM_FILL_NAME | SAM_FILL_INFO3 | SAM_FILL_SAM | SAM_FILL_UNIX) -typedef struct serversupplied_info +typedef struct auth_serversupplied_info { BOOL guest; @@ -91,7 +91,7 @@ typedef struct serversupplied_info } auth_serversupplied_info; -typedef struct authsupplied_info { +struct auth_context { DATA_BLOB challenge; /* Who set this up in the first place? */ @@ -100,22 +100,30 @@ typedef struct authsupplied_info { struct auth_methods *challenge_set_method; /* What order are the various methods in? Try to stop it changing under us */ struct auth_methods *auth_method_list; -} auth_authsupplied_info; + + TALLOC_CTX *mem_ctx; + const uint8 *(*get_ntlm_challenge)(struct auth_context *auth_context); + NTSTATUS (*check_ntlm_password)(const struct auth_context *auth_context, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info); + NTSTATUS (*nt_status_squash)(NTSTATUS nt_status); + void (*free)(struct auth_context **auth_context); +}; typedef struct auth_methods { struct auth_methods *prev, *next; char *name; /* What name got this module */ - NTSTATUS (*auth)(void *my_private_data, + NTSTATUS (*auth)(const struct auth_context *auth_context, + void *my_private_data, TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - const struct authsupplied_info *auth_info, + const struct auth_usersupplied_info *user_info, auth_serversupplied_info **server_info); - DATA_BLOB (*get_chal)(void **my_private_data, - TALLOC_CTX *mem_ctx, - const struct authsupplied_info *auth_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 */ void *private_data; @@ -128,11 +136,11 @@ typedef struct auth_methods } auth_methods; -typedef struct auth_init_function { +struct auth_init_function { char *name; /* Function to create a member of the authmethods list */ - BOOL (*init)(struct auth_methods **auth_method); -} auth_init_function; + BOOL (*init)(struct auth_context *auth_context, struct auth_methods **auth_method); +}; #endif /* _SMBAUTH_H_ */ diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 634e2540fa..fbab46022c 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -568,19 +568,24 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * switch (ctr->switch_value) { case NET_LOGON_TYPE: { - auth_authsupplied_info *auth_info = NULL; - make_auth_info_fixed(&auth_info, ctr->auth.id2.lm_chal); + struct auth_context *auth_context = NULL; + if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) { + return status; + } + /* Standard challenge/response authenticaion */ - make_user_info_netlogon_network(&user_info, - nt_username, nt_domain, - nt_workstation, - ctr->auth.id2.lm_chal_resp.buffer, - ctr->auth.id2.lm_chal_resp.str_str_len, - ctr->auth.id2.nt_chal_resp.buffer, - ctr->auth.id2.nt_chal_resp.str_str_len); - - status = check_password(user_info, auth_info, &server_info); - free_auth_info(&auth_info); + if (!make_user_info_netlogon_network(&user_info, + nt_username, nt_domain, + nt_workstation, + ctr->auth.id2.lm_chal_resp.buffer, + ctr->auth.id2.lm_chal_resp.str_str_len, + ctr->auth.id2.nt_chal_resp.buffer, + ctr->auth.id2.nt_chal_resp.str_str_len)) { + status = NT_STATUS_NO_MEMORY; + } else { + status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); + } + auth_context->free(&auth_context); break; } @@ -590,23 +595,26 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * convert this to chellange/responce for the auth subsystem to chew on */ { - auth_authsupplied_info *auth_info = NULL; - DATA_BLOB chal; - if (!make_auth_info_subsystem(&auth_info)) { - return NT_STATUS_NO_MEMORY; + struct auth_context *auth_context = NULL; + const uint8 *chal; + if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) { + return status; } - chal = auth_get_challenge(auth_info); - - make_user_info_netlogon_interactive(&user_info, - nt_username, nt_domain, - nt_workstation, chal.data, - ctr->auth.id1.lm_owf.data, - ctr->auth.id1.nt_owf.data, - p->dc.sess_key); - status = check_password(user_info, auth_info, &server_info); - data_blob_free(&chal); - free_auth_info(&auth_info); + chal = auth_context->get_ntlm_challenge(auth_context); + + if (!make_user_info_netlogon_interactive(&user_info, + nt_username, nt_domain, + nt_workstation, chal, + ctr->auth.id1.lm_owf.data, + ctr->auth.id1.nt_owf.data, + p->dc.sess_key)) { + status = NT_STATUS_NO_MEMORY; + } else { + status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); + } + + auth_context->free(&auth_context); break; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index c97619c4b6..36ca7e0686 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -270,8 +270,8 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm NTSTATUS nt_status; + struct auth_context *auth_context = NULL; auth_usersupplied_info *user_info = NULL; - auth_authsupplied_info *auth_info = NULL; auth_serversupplied_info *server_info = NULL; uid_t uid; @@ -345,7 +345,7 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm } - make_auth_info_fixed(&auth_info, (uchar*)p->challenge); + make_auth_context_fixed(&auth_context, (uchar*)p->challenge); if (!make_user_info_netlogon_network(&user_info, user_name, domain, wks, @@ -355,9 +355,9 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm return False; } - nt_status = check_password(user_info, auth_info, &server_info); + nt_status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); - free_auth_info(&auth_info); + auth_context->free(&auth_context); free_user_info(&user_info); p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index d3afa19d00..52ba5e9789 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,7 +27,28 @@ extern fstring global_myworkgroup; extern fstring remote_machine; BOOL global_encrypted_passwords_negotiated = False; BOOL global_spnego_negotiated = False; -auth_authsupplied_info *negprot_global_auth_info = NULL; +struct auth_context *negprot_global_auth_context = NULL; + +static void get_challange(char buff[8]) +{ + NTSTATUS nt_status; + const uint8 *cryptkey; + + /* We might be called more than once, muliple negprots are premitted */ + if (negprot_global_auth_context) { + DEBUG(3, ("get challange: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n")); + negprot_global_auth_context->free(&negprot_global_auth_context); + } + + DEBUG(10, ("get challange: creating negprot_global_auth_context\n")); + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) { + DEBUG(0, ("make_auth_context_subsystem returned %s", get_nt_error_msg(nt_status))); + smb_panic("cannot make_negprot_global_auth_context!\n"); + } + DEBUG(10, ("get challange: getting challange\n")); + cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context); + memcpy(buff, cryptkey, 8); +} /**************************************************************************** reply for the core protocol @@ -69,7 +90,6 @@ static int reply_lanman1(char *inbuf, char *outbuf) int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; time_t t = time(NULL); - DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -80,12 +100,7 @@ static int reply_lanman1(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - if (!make_auth_info_subsystem(&negprot_global_auth_info)) { - smb_panic("cannot make_negprot_global_auth_info!\n"); - } - cryptkey = auth_get_challenge(negprot_global_auth_info); - memcpy(smb_buf(outbuf), cryptkey.data, 8); - data_blob_free(&cryptkey); + get_challange(smb_buf(outbuf)); } Protocol = PROTOCOL_LANMAN1; @@ -114,7 +129,6 @@ static int reply_lanman2(char *inbuf, char *outbuf) int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); int secword=0; time_t t = time(NULL); - DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); @@ -125,13 +139,9 @@ static int reply_lanman2(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1,secword); SIVAL(outbuf,smb_vwv6,sys_getpid()); + /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - if (!make_auth_info_subsystem(&negprot_global_auth_info)) { - smb_panic("cannot make_negprot_global_auth_info!\n"); - } - cryptkey = auth_get_challenge(negprot_global_auth_info); - memcpy(smb_buf(outbuf), cryptkey.data, 8); - data_blob_free(&cryptkey); + get_challange(smb_buf(outbuf)); } Protocol = PROTOCOL_LANMAN2; @@ -216,7 +226,6 @@ static int reply_nt1(char *inbuf, char *outbuf) int secword=0; time_t t = time(NULL); - DATA_BLOB cryptkey; char *p, *q; BOOL negotiate_spnego = False; @@ -275,13 +284,9 @@ static int reply_nt1(char *inbuf, char *outbuf) p = q = smb_buf(outbuf); if (!negotiate_spnego) { - if (global_encrypted_passwords_negotiated) { - if (!make_auth_info_subsystem(&negprot_global_auth_info)) { - smb_panic("cannot make_negprot_global_auth_info!\n"); - } - cryptkey = auth_get_challenge(negprot_global_auth_info); - memcpy(p, cryptkey.data, 8); - data_blob_free(&cryptkey); + /* Create a token value and add it to the outgoing packet. */ + if (global_encrypted_passwords_negotiated) { + get_challange(p); } SSVALS(outbuf,smb_vwv16+1,8); p += 8; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index af081d5059..2b31a24ced 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1112,7 +1112,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - extern auth_authsupplied_info *negprot_global_auth_info; + extern struct auth_context *negprot_global_auth_context; if (!send_keepalive(smbd_server_fd())) { DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); return False; @@ -1121,11 +1121,11 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t /* send a keepalive for a password server or the like. This is attached to the auth_info created in the negprot */ - if (negprot_global_auth_info - && negprot_global_auth_info->challenge_set_method - && negprot_global_auth_info->challenge_set_method->send_keepalive) { - negprot_global_auth_info->challenge_set_method->send_keepalive - (&negprot_global_auth_info->challenge_set_method->private_data); + if (negprot_global_auth_context + && negprot_global_auth_context->challenge_set_method + && negprot_global_auth_context->challenge_set_method->send_keepalive) { + negprot_global_auth_context->challenge_set_method->send_keepalive + (&negprot_global_auth_context->challenge_set_method->private_data); } last_keepalive_sent_time = t; diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 900f5b4846..1fab45048d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -475,7 +475,7 @@ void exit_server(char *reason) { static int firsttime=1; extern char *last_inbuf; - extern auth_authsupplied_info *negprot_global_auth_info; + extern struct auth_context *negprot_global_auth_context; if (!firsttime) exit(0); @@ -484,7 +484,9 @@ void exit_server(char *reason) change_to_root_user(); DEBUG(2,("Closing connections\n")); - free_auth_info(&negprot_global_auth_info); + if (negprot_global_auth_context) { + negprot_global_auth_context->free(&negprot_global_auth_context); + } conn_close_all(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 41a7a657e2..737ecade7d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,7 +23,7 @@ #include "includes.h" uint32 global_client_caps = 0; -static auth_authsupplied_info *ntlmssp_auth_info; +static struct auth_context *ntlmssp_auth_context; /* on a logon error possibly map the error to success if "map to guest" @@ -72,8 +72,7 @@ static void add_signature(char *outbuf) ****************************************************************************/ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) { - - auth_authsupplied_info *auth_info; + struct auth_context *auth_context; auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; @@ -83,11 +82,17 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) DEBUG(3,("Got anonymous request\n")); - make_user_info_guest(&user_info); - make_auth_info_fixed(&auth_info, chal); + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) { + return nt_status; + } + + if (!make_user_info_guest(&user_info)) { + auth_context->free(&auth_context); + return NT_STATUS_NO_MEMORY; + } - nt_status = check_password(user_info, auth_info, server_info); - free_auth_info(&auth_info); + nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info); + auth_context->free(&auth_context); free_user_info(&user_info); return nt_status; } @@ -233,8 +238,9 @@ static int reply_spnego_negotiate(connection_struct *conn, int i; uint32 ntlmssp_command, neg_flags; DATA_BLOB sess_key, chal, spnego_chal; - DATA_BLOB cryptkey; + const uint8 *cryptkey; BOOL got_kerberos = False; + NTSTATUS nt_status; /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { @@ -282,11 +288,15 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); - if (!make_auth_info_subsystem(&ntlmssp_auth_info)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + if (!ntlmssp_auth_context) { + ntlmssp_auth_context->free(&ntlmssp_auth_context); + } + + if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&ntlmssp_auth_context))) { + return ERROR_NT(nt_status); } - cryptkey = auth_get_challenge(ntlmssp_auth_info); + cryptkey = ntlmssp_auth_context->get_ntlm_challenge(ntlmssp_auth_context); /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ @@ -301,7 +311,7 @@ static int reply_spnego_negotiate(connection_struct *conn, 0, 0x30, /* ?? */ neg_flags, - cryptkey.data, cryptkey.length, + cryptkey, sizeof(cryptkey), 0, 0, 0, 0x3000); /* ?? */ @@ -314,7 +324,6 @@ static int reply_spnego_negotiate(connection_struct *conn, reply_sesssetup_blob(conn, outbuf, spnego_chal); data_blob_free(&chal); - data_blob_free(&cryptkey); data_blob_free(&spnego_chal); /* and tell smbd that we have already replied to this packet */ @@ -382,7 +391,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return ERROR_NT(NT_STATUS_NO_MEMORY); } - nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); + nt_status = ntlmssp_auth_context->check_ntlm_password(ntlmssp_auth_context, user_info, &server_info); if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest(nt_status, &server_info, user, workgroup); @@ -391,7 +400,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, SAFE_FREE(workgroup); SAFE_FREE(machine); - free_auth_info(&ntlmssp_auth_info); + ntlmssp_auth_context->free(&ntlmssp_auth_context); free_user_info(&user_info); @@ -544,7 +553,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, extern int max_send; auth_usersupplied_info *user_info = NULL; - extern auth_authsupplied_info *negprot_global_auth_info; + extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; @@ -672,13 +681,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine)); if (*user) { - if (global_spnego_negotiated) { - DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); - return ERROR_NT(NT_STATUS_UNSUCCESSFUL); - } - } - - if (*user) { pstrcpy(sub_user, user); } else { pstrcpy(sub_user, lp_guestaccount()); @@ -702,37 +704,46 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } if (!*user) { + if (global_spnego_negotiated) { + + /* This has to be here, becouse this is a perfectly valid behaviour for guest logons :-( */ + + DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } nt_status = check_guest_password(&server_info); } else if (doencrypt) { if (!make_user_info_for_reply_enc(&user_info, user, domain, - lm_resp, nt_resp, - plaintext_password)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + lm_resp, nt_resp)) { + nt_status = NT_STATUS_NO_MEMORY; + } else { + nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, + user_info, + &server_info); } - - nt_status = check_password(user_info, negprot_global_auth_info, &server_info); } else { - auth_authsupplied_info *plaintext_auth_info = NULL; - DATA_BLOB chal; - if (!make_auth_info_subsystem(&plaintext_auth_info)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - chal = auth_get_challenge(plaintext_auth_info); - - if (!make_user_info_for_reply(&user_info, - user, domain, chal.data, - plaintext_password)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - - nt_status = check_password(user_info, plaintext_auth_info, &server_info); + struct auth_context *plaintext_auth_context = NULL; + const uint8 *chal; + if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) { + chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); + + if (!make_user_info_for_reply(&user_info, + user, domain, chal, + plaintext_password)) { + nt_status = NT_STATUS_NO_MEMORY; + } - data_blob_free(&chal); - free_auth_info(&plaintext_auth_info); + if (NT_STATUS_IS_OK(nt_status)) { + nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, + user_info, + &server_info); + + plaintext_auth_context->free(&plaintext_auth_context); + } + } } free_user_info(&user_info); |