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 /source3/auth | |
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)
Diffstat (limited to 'source3/auth')
-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 |
11 files changed, 535 insertions, 532 deletions
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; } - - - - |