diff options
33 files changed, 1842 insertions, 743 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index d69941bed3..6b3b337a12 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -197,7 +197,8 @@ NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o PLAINTEXT_AUTH_OBJ = passdb/pampass.o passdb/pass_check.o AUTH_OBJ = smbd/auth.o smbd/auth_smbpasswd.o smbd/auth_server.o smbd/auth_domain.o \ - smbd/auth_rhosts.o smbd/auth_unix.o smbd/auth_util.o $(PLAINTEXT_AUTH_OBJ) \ + smbd/auth_rhosts.o smbd/auth_unix.o smbd/auth_util.o smbd/auth_winbind.o \ + smbd/auth_info.o smbd/auth_builtin.o $(PLAINTEXT_AUTH_OBJ) \ libsmb/domain_client_validate.o diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 95c97182b8..c62e2ed5a0 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -58,27 +58,50 @@ static BOOL check_domain_match(char *user, char *domain) ****************************************************************************/ NTSTATUS check_password(const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - BOOL done_pam = False; const char *pdb_username; + auth_methods *auth_method; + + if (!user_info || !auth_info || !server_info) { + return NT_STATUS_LOGON_FAILURE; + } DEBUG(3, ("check_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str)); 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 (!NT_STATUS_IS_OK(nt_status)) { - nt_status = check_guest_security(user_info, server_info); + DEBUG(10, ("auth_info challange created by %s\n", auth_info->challange_set_by)); + DEBUG(10, ("challange is: \n")); + dump_data(5, (auth_info)->challange.data, (auth_info)->challange.length); + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("user_info has passwords of length %d and %d\n", + user_info->lm_resp.length, user_info->nt_resp.length)); + DEBUG(100, ("lm:\n")); + dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length); + DEBUG(100, ("nt:\n")); + dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length); +#endif + + for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next) + { + nt_status = auth_method->auth(auth_method->private_data, user_info, auth_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: checking guest-account for user [%s] suceeded\n", user_info->smb_name.str)); + DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n", + auth_method->name, user_info->smb_name.str)); } else { - DEBUG(10, ("check_password: checking gusst-account for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } + DEBUG(5, ("check_password: %s authentication for user [%s] FAILED with error %s\n", + auth_method->name, user_info->smb_name.str, get_nt_error_msg(nt_status))); + } + + if (NT_STATUS_IS_OK(nt_status)) { + break; + } } /* This needs to be sorted: If it doesn't match, what should we do? */ @@ -86,83 +109,47 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, return NT_STATUS_LOGON_FAILURE; } - if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = check_rhosts_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: Password (rhosts) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(10, ("check_password: Password (rhosts) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - - if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { - nt_status = check_domain_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (domain) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (domain) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - - if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { - nt_status = check_server_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (server) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (server) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } + /* This is one of the few places the *relies* (rather than just sets defaults + on the value of lp_security(). This needs to change. A new paramater + perhaps? */ if (lp_security() >= SEC_SERVER) { smb_user_control(user_info, *server_info, nt_status); } - if (!NT_STATUS_IS_OK(nt_status)) { - if (user_info->encrypted || lp_plaintext_to_smbpasswd()) { - nt_status = check_smbpasswd_security(user_info, server_info); - } else { - nt_status = check_unix_security(user_info, server_info); - done_pam = True; - } - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (unix/smbpasswd) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (unix/smbpasswd) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - if (NT_STATUS_IS_OK(nt_status)) { pdb_username = pdb_get_username((*server_info)->sam_account); - if (!done_pam && !(*server_info)->guest) { + if (!(*server_info)->guest) { /* We might not be root if we are an RPC call */ become_root(); nt_status = smb_pam_accountcheck(pdb_username); unbecome_root(); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", pdb_username)); + DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", + pdb_username)); } else { - DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", pdb_username, get_nt_error_msg(nt_status))); + DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", + pdb_username, get_nt_error_msg(nt_status))); } } + + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG((*server_info)->guest ? 5 : 2, + ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", + (*server_info)->guest ? "guest " : "", + user_info->smb_name.str, + user_info->internal_username.str, + pdb_username)); + } } - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", - (*server_info)->guest ? "guest " : "", - user_info->smb_name.str, - user_info->internal_username.str, - pdb_username)); - } else { - DEBUG(3, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", user_info->smb_name.str, user_info->internal_username.str, get_nt_error_msg(nt_status))); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", + user_info->smb_name.str, user_info->internal_username.str, + get_nt_error_msg(nt_status))); ZERO_STRUCTP(server_info); - } - + } return nt_status; } @@ -210,16 +197,35 @@ static NTSTATUS pass_check_smb(char *smb_name, { 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; + } - make_user_info_for_reply(&user_info, smb_name, - domain, - lm_pwd, - nt_pwd, - plaintext_password, - encrypted); - - nt_status = check_password(user_info, &server_info); + chal = auth_get_challange(plaintext_auth_info); + + if (!make_user_info_for_reply(&user_info, + smb_name, domain, chal.data, + plaintext_password)) { + return NT_STATUS_NO_MEMORY; + } + + 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); return nt_status; @@ -235,22 +241,23 @@ BOOL password_ok(char *smb_name, DATA_BLOB password_blob) DATA_BLOB null_password = data_blob(NULL, 0); extern BOOL global_encrypted_passwords_negotiated; - - if (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, global_encrypted_passwords_negotiated))) { + 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, global_encrypted_passwords_negotiated))) { + 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, global_encrypted_passwords_negotiated))) { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { return True; } } diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c new file mode 100644 index 0000000000..6ea6d0bbe0 --- /dev/null +++ b/source3/auth/auth_builtin.c @@ -0,0 +1,87 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0. + Generic authenticaion types + 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" + +/**************************************************************************** + Check for a guest logon (username = "") and if so create the required + structure. +****************************************************************************/ + +static NTSTATUS check_guest_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (!(user_info->internal_username.str + && *user_info->internal_username.str)) { + if (make_server_info_guest(server_info)) { + nt_status = NT_STATUS_OK; + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + + return nt_status; +} + +BOOL auth_init_guest(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_guest_security; + return True; +} + +/**************************************************************************** + Check against either sam or unix, depending on encryption. +****************************************************************************/ + +static NTSTATUS check_local_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (user_info->encrypted) { + nt_status = check_sam_security(my_private_data, user_info, auth_info, server_info); + } else { + nt_status = check_unix_security(my_private_data, user_info, auth_info, server_info); + } + + return nt_status; +} + +BOOL auth_init_local(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_local_security; + return True; +} + diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 4ada7d4a56..ef0e5b2f10 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -28,8 +28,10 @@ BOOL global_machine_password_needs_changing = False; Check for a valid username and password in security=domain mode. ****************************************************************************/ -NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_ntdomain_security(void *my_private_data, + 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; @@ -66,8 +68,18 @@ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, if (! *pserver) pserver = "*"; p = pserver; - nt_status = domain_client_validate(user_info, server_info, + nt_status = domain_client_validate(user_info, (uchar *)auth_info->challange.data,server_info, p, trust_passwd, last_change_time); return nt_status; } + +BOOL auth_init_ntdomain(auth_methods **auth_method) +{ + if (!make_auth_methods(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 new file mode 100644 index 0000000000..12b843d781 --- /dev/null +++ b/source3/auth/auth_info.c @@ -0,0 +1,279 @@ +/* + 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" + +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 }, + { "unix", auth_init_unix }, + { "local", auth_init_local }, + { "smbserver", auth_init_smbserver }, + { "ntdomain", auth_init_ntdomain }, + { "winbind", auth_init_winbind }, + { NULL, NULL} +}; + +/*************************************************************************** + 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; + + 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)); + /* Malloc entry, fill it, link it */ + t = (auth_methods *)malloc(sizeof(*t)); + if (!t) { + DEBUG(0,("make_pw_chat: malloc failed!\n")); + return False; + } + + ZERO_STRUCTP(t); + + 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; + } + } + } + + make_auth_info_list(auth_info, list); + + 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 (!make_auth_info(auth_info)) { + return False; + } + + 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 ntdomain local"); + break; + case SEC_SERVER: + DEBUG(5,("Making default auth method list for security=server\n")); + auth_method_list = lp_list_make("guest smbserver local"); + break; + case SEC_USER: + DEBUG(5,("Making default auth method list for security=user\n")); + auth_method_list = lp_list_make("guest local"); + break; + case SEC_SHARE: + DEBUG(5,("Making default auth method list for security=share\n")); + auth_method_list = lp_list_make("guest local"); + break; + } + } 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 challange +***************************************************************************/ + +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)->challange = data_blob(chal, sizeof(chal)); + + (*auth_info)->challange_set_by = "random"; + + return True; +} + +/*************************************************************************** + Make a auth_info struct with a fixed challange +***************************************************************************/ + +BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) +{ + if (!make_auth_info_subsystem(auth_info)) { + return False; + } + + (*auth_info)->challange = 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) +{ + auth_methods *list; + if (*auth_info != NULL) { + list = (*auth_info)->auth_method_list; + 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); + } + + data_blob_free(&(*auth_info)->challange); + ZERO_STRUCT(**auth_info); + } + SAFE_FREE(*auth_info); +} + +/**************************************************************************** + Try to get a challange out of the various authenticaion modules. + It is up to the caller to free it. +****************************************************************************/ + +DATA_BLOB auth_get_challange(auth_authsupplied_info *auth_info) +{ + DATA_BLOB challange = data_blob(NULL, 0); + char *challange_set_by = NULL; + auth_methods *auth_method; + + if (auth_info->challange.length) { + DEBUG(5, ("auth_get_challange: returning previous challange (normal)\n")); + return data_blob(auth_info->challange.data, auth_info->challange.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_challange: getting challange from module %s\n", auth_method->name)); + if (challange_set_by) { + DEBUG(1, ("auth_get_challange: CONFIGURATION ERROR: authenticaion method %s has already specified a challange. Challange by %s ignored.\n", + challange_set_by, auth_method->name)); + } else { + challange = auth_method->get_chal(&auth_method->private_data, auth_info); + if (challange.length) { + DEBUG(5, ("auth_get_challange: sucessfully got challange from module %s\n", auth_method->name)); + auth_info->challange = challange; + challange_set_by = auth_method->name; + auth_info->challange_set_method = auth_method; + } else { + DEBUG(3, ("auth_get_challange: getting challange from authenticaion method %s FAILED.\n", + auth_method->name)); + } + } + } else { + DEBUG(5, ("auth_get_challange: module %s did not want to specify a challange\n", auth_method->name)); + } + } + + if (!challange_set_by) { + uchar chal[8]; + + generate_random_buffer(chal, sizeof(chal), False); + auth_info->challange = data_blob(chal, sizeof(chal)); + + challange_set_by = "random"; + } + + DEBUG(5, ("auth_info challange created by %s\n", challange_set_by)); + DEBUG(5, ("challange is: \n")); + dump_data(5, auth_info->challange.data, (auth_info)->challange.length); + + SMB_ASSERT(auth_info->challange.length == 8); + + auth_info->challange_set_by=challange_set_by; + + return data_blob(auth_info->challange.data, auth_info->challange.length); +} + + diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c index 9c07e48a9b..2605f0770a 100644 --- a/source3/auth/auth_rhosts.c +++ b/source3/auth/auth_rhosts.c @@ -135,7 +135,6 @@ check for a possible hosts equiv or rhosts entry for the user static BOOL check_hosts_equiv(struct passwd *pass) { char *fname = NULL; - pstring rhostsfile; if (!pass) return(False); @@ -148,39 +147,82 @@ static BOOL check_hosts_equiv(struct passwd *pass) return(True); } - if (lp_use_rhosts()) - { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) - return(True); - } - } - return(False); } + /**************************************************************************** Check for a valid .rhosts/hosts.equiv entry for this user ****************************************************************************/ -NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_hostsequiv_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; struct passwd *pass = Get_Pwnam(user_info->internal_username.str); if (pass) { - become_root(); if (check_hosts_equiv(pass)) { nt_status = NT_STATUS_OK; make_server_info_pw(server_info, pass); } - unbecome_root(); } else { nt_status = NT_STATUS_NO_SUCH_USER; } return nt_status; } + + +/**************************************************************************** + Check for a valid .rhosts/hosts.equiv entry for this user +****************************************************************************/ + +static NTSTATUS check_rhosts_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + pstring rhostsfile; + + if (pass) { + char *home = pass->pw_dir; + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + become_root(); + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) { + nt_status = NT_STATUS_OK; + make_server_info_pw(server_info, pass); + } + unbecome_root(); + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + + return nt_status; +} + +BOOL auth_init_hostsequiv(auth_methods **auth_method) +{ + + if (!make_auth_methods(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 70632fb5df..24a4d4e4e4 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -96,7 +96,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, if (ntv2_response.length < 16) { /* We MUST have more than 16 bytes, or the stuff below will go crazy... */ - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", + DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", ntv2_response.length)); return False; } @@ -132,15 +132,16 @@ 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. ****************************************************************************/ -NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16]) +static NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + uint8 user_sess_key[16]) { + uint16 acct_ctrl; const uint8 *nt_pw, *lm_pw; - uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); uint32 ntlmssp_flags; - if (!user_info || !sampass) - return NT_STATUS_LOGON_FAILURE; - + acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) @@ -173,8 +174,8 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use */ DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, - user_info->sec_blob, user_info->smb_name.str, + nt_pw, auth_info->challange, + user_info->smb_name.str, user_info->client_domain.str, user_sess_key)) { @@ -190,7 +191,7 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, user_info->sec_blob, + nt_pw, auth_info->challange, user_sess_key)) { return NT_STATUS_OK; @@ -223,7 +224,7 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use DEBUG(4,("smb_password_ok: Checking LM password\n")); if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, user_info->sec_blob, + lm_pw, auth_info->challange, user_sess_key)) { return NT_STATUS_OK; @@ -265,6 +266,24 @@ static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_inf return NT_STATUS_ACCOUNT_EXPIRED; } + if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { + time_t must_change_time = pdb_get_pass_must_change_time(sampass); + time_t last_set_time = pdb_get_pass_last_set_time(sampass); + + /* check for immediate expiry "must change at next logon" */ + if (must_change_time == 0 && last_set_time != 0) { + DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); + return NT_STATUS_PASSWORD_MUST_CHANGE; + } + + /* check for expired password */ + if (must_change_time < time(NULL) && must_change_time != 0) { + DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); + DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); + return NT_STATUS_PASSWORD_EXPIRED; + } + } + /* Test workstation. Workstation list is comma separated. */ workstation_list = strdup(pdb_get_workstations(sampass)); @@ -293,24 +312,6 @@ static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_inf SAFE_FREE(workstation_list); } - if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { - time_t must_change_time = pdb_get_pass_must_change_time(sampass); - time_t last_set_time = pdb_get_pass_last_set_time(sampass); - - /* check for immediate expiry "must change at next logon" */ - if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); - return NT_STATUS_PASSWORD_MUST_CHANGE; - } - - /* check for expired password */ - if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); - return NT_STATUS_PASSWORD_EXPIRED; - } - } - if (acct_ctrl & ACB_DOMTRUST) { DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; @@ -336,7 +337,10 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +NTSTATUS check_sam_security(void *my_private_dat, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; @@ -344,7 +348,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ uint8 user_sess_key[16]; const uint8* lm_hash; - if (!user_info) { + if (!user_info || !auth_info) { return NT_STATUS_LOGON_FAILURE; } @@ -365,7 +369,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, user_sess_key); + nt_status = sam_password_ok(sampass, user_info, auth_info, user_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); @@ -394,6 +398,15 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return nt_status; } +BOOL auth_init_sam(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_sam_security; + return True; +} diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index ddbc284d50..067b5b2997 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -25,30 +25,18 @@ extern pstring global_myname; /**************************************************************************** - Return the client state structure. -****************************************************************************/ - -struct cli_state *server_client(void) -{ - static struct cli_state pw_cli; - return &pw_cli; -} - -/**************************************************************************** Support for server level security. ****************************************************************************/ -struct cli_state *server_cryptkey(void) +static struct cli_state *server_cryptkey(void) { - struct cli_state *cli; + struct cli_state *cli = NULL; fstring desthost; struct in_addr dest_ip; char *p, *pserver; BOOL connected_ok = False; - cli = server_client(); - - if (!cli_initialise(cli)) + if (!(cli = cli_initialise(cli))) return NULL; /* security = server just can't function with spnego */ @@ -88,7 +76,11 @@ struct cli_state *server_cryptkey(void) if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) return NULL; - + + if (strequal(desthost,myhostname())) { + exit_server("Password server loop!"); + } + DEBUG(3,("got session\n")); if (!cli_negprot(cli)) { @@ -109,13 +101,82 @@ struct cli_state *server_cryptkey(void) return cli; } +/**************************************************************************** + Clean up our allocated cli. +****************************************************************************/ + +static void free_server_private_data(void **private_data_pointer) +{ + struct cli_state **cli = (struct cli_state **)private_data_pointer; + if (*cli && (*cli)->initialised) { + cli_shutdown(*cli); + + SAFE_FREE(*cli); + } +} + +/**************************************************************************** + Send a 'keepalive' packet down the cli pipe. +****************************************************************************/ + +static void send_server_keepalive(void **private_data_pointer) +{ + struct cli_state **cli = (struct cli_state **)private_data_pointer; + + /* also send a keepalive to the password server if its still + connected */ + if (cli && *cli && (*cli)->initialised) { + if (!send_keepalive((*cli)->fd)) { + DEBUG( 2, ( "password server keepalive failed.\n")); + cli_shutdown(*cli); + SAFE_FREE(*cli); + } + } +} + +/**************************************************************************** + Get the challange out of a password server. +****************************************************************************/ + +static DATA_BLOB auth_get_challange_server(void **my_private_data, const struct authsupplied_info *auth_info) +{ + struct cli_state *cli = server_cryptkey(); + + if (cli) { + DEBUG(3,("using password server validation\n")); + if ((cli->sec_mode & 2) == 0) { + /* We can't work with unencrypted password servers + unless 'encrypt passwords = no' */ + DEBUG(5,("make_auth_info_server: Server is unencrypted, no challange available..\n")); + + *my_private_data = (void *)cli; + return data_blob(NULL, 0); + + } else if (cli->secblob.length < 8) { + /* We can't do much if we don't get a full challange */ + DEBUG(2,("make_auth_info_server: Didn't receive a full challange from server\n")); + cli_shutdown(cli); + return data_blob(NULL, 0); + } + + *my_private_data = (void *)cli; + + return data_blob(cli->secblob.data,8); + } else { + return data_blob(NULL, 0); + } +} + /**************************************************************************** Check for a valid username and password in security=server mode. - Validate a password with the password server. ****************************************************************************/ -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +static NTSTATUS check_smbserver_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -123,13 +184,32 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser static BOOL tested_password_server = False; static BOOL bad_password_server = False; NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + BOOL locally_made_cli = False; - cli = server_client(); + cli = my_private_data; + + if (cli) { + } else { + cli = server_cryptkey(); + locally_made_cli = True; + } - if (!cli->initialised) { + if (!cli || !cli->initialised) { DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(NT_STATUS_LOGON_FAILURE); + return NT_STATUS_LOGON_FAILURE; } + + if ((cli->sec_mode & 2) == 0) { + if (user_info->encrypted) { + DEBUG(1,("password server %s is plaintext, but we are encrypted. This just can't work :-(\n", cli->desthost)); + return NT_STATUS_LOGON_FAILURE; + } + } else { + if (memcmp(cli->secblob.data, auth_info->challange.data, 8) != 0) { + DEBUG(1,("the challange 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; + } + } if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); @@ -206,17 +286,32 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user_info->smb_name.str, - (char *)user_info->lm_resp.data, - user_info->lm_resp.length, - (char *)user_info->nt_resp.data, - user_info->nt_resp.length, - user_info->domain.str)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - /* Make this cli_nt_error() when the conversion is in */ - nt_status = cli_nt_error(cli); + if (!user_info->encrypted) { + /* Plaintext available */ + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->plaintext_password.data, + user_info->plaintext_password.length, + NULL, 0, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ + nt_status = cli_nt_error(cli); + } else { + nt_status = NT_STATUS_OK; + } } else { - nt_status = NT_STATUS_OK; + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->lm_resp.data, + user_info->lm_resp.length, + (char *)user_info->nt_resp.data, + user_info->nt_resp.length, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ + nt_status = cli_nt_error(cli); + } else { + nt_status = NT_STATUS_OK; + } } /* if logged in as guest then reject */ @@ -238,5 +333,22 @@ use this machine as the password server.\n")); } } + if (locally_made_cli) { + cli_shutdown(cli); + SAFE_FREE(cli); + } + return(nt_status); } + +BOOL auth_init_smbserver(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_smbserver_security; + (*auth_method)->get_chal = auth_get_challange_server; + (*auth_method)->send_keepalive = send_server_keepalive; + (*auth_method)->free_private_data = free_server_private_data; + return True; +} diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c index 8c4a520350..d134ce6909 100644 --- a/source3/auth/auth_unix.c +++ b/source3/auth/auth_unix.c @@ -82,7 +82,10 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +NTSTATUS check_unix_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; @@ -104,9 +107,19 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve if (pass) { make_server_info_pw(server_info, pass); } else { + /* we need to do somthing more useful here */ nt_status = NT_STATUS_NO_SUCH_USER; } } return nt_status; } + +BOOL auth_init_unix(auth_methods **auth_method) +{ + if (!make_auth_methods(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 25e0830fc7..d1b2cc92e5 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -23,49 +23,9 @@ #include "includes.h" -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; extern fstring remote_machine; extern pstring global_myname; -/******************************************************************* - Get the next challenge value - no repeats. -********************************************************************/ - -void generate_next_challenge(char *challenge) -{ - unsigned char buf[8]; - - generate_random_buffer(buf,8,False); - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; -} - -/******************************************************************* - Set the last challenge sent, usually from a password server. -********************************************************************/ - -BOOL set_challenge(unsigned char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* - Get the last challenge sent. -********************************************************************/ - -BOOL last_challenge(unsigned char *challenge) -{ - if (!challenge_sent) - return(False); - memcpy(challenge,saved_challenge,8); - return(True); -} - /**************************************************************************** Create a UNIX user on demand. ****************************************************************************/ @@ -166,7 +126,6 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, const char *client_domain, const char *domain, const char *wksta_name, - DATA_BLOB sec_blob, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) @@ -226,7 +185,6 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); - (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length); (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); @@ -246,7 +204,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, BOOL make_user_info_map(auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, - const char *wksta_name, DATA_BLOB sec_blob, + const char *wksta_name, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) @@ -265,7 +223,7 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, return make_user_info(user_info, smb_name, internal_username, client_domain, domain, - wksta_name, sec_blob, + wksta_name, lm_pwd, nt_pwd, plaintext, ntlmssp_flags, encrypted); @@ -280,12 +238,11 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - char *wksta_name, uchar chal[8], + char *wksta_name, uchar *lm_network_pwd, int lm_pwd_len, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -301,8 +258,8 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, - wksta_name, sec_blob, - nt_blob, lm_blob, + wksta_name, + lm_blob, nt_blob, plaintext_blob, ntlmssp_flags, True); @@ -320,6 +277,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, char *wksta_name, + char chal[8], uchar lm_interactive_pwd[16], uchar nt_interactive_pwd[16], uchar *dc_sess_key) @@ -329,11 +287,8 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; unsigned char key[16]; - uint8 chal[8]; uint32 ntlmssp_flags = 0; - generate_random_buffer(chal, 8, False); - ZERO_STRUCT(key); memcpy(key, dc_sess_key, 8); @@ -362,7 +317,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - generate_random_buffer(chal, 8, False); SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); @@ -373,7 +327,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -385,7 +338,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, - wksta_name, sec_blob, + wksta_name, local_lm_blob, local_nt_blob, plaintext_blob, @@ -402,13 +355,14 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, - char *username, - char *domain, - char *password) + const char *username, + const char *domain, + const char *password, + char chal[8] /* Give winbind back the challange we used */ + ) { unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; - char chal[8]; DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; DATA_BLOB plaintext_blob; @@ -453,16 +407,11 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); - - if (!sec_blob.data) { - return False; - } ret = make_user_info(user_info, username, username, domain, domain, - global_myname, sec_blob, + global_myname, local_nt_blob, local_lm_blob, plaintext_blob, @@ -483,12 +432,10 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - uchar chal[8], uchar *lm_network_pwd, int lm_pwd_len, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, 8); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -502,7 +449,7 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, ret = make_user_info(user_info, smb_name, smb_name, client_domain, client_domain, - global_myname, sec_blob, + global_myname, nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); @@ -517,59 +464,30 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - DATA_BLOB lm_resp, DATA_BLOB nt_resp, - DATA_BLOB plaintext_password, - BOOL encrypted) + char *smb_name, + char *client_domain, + char chal[8], + DATA_BLOB plaintext_password) { - uchar chal[8]; DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; - DATA_BLOB sec_blob; BOOL ret = False; uint32 ntlmssp_flags = 0; - if (encrypted) { - DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); - if (!last_challenge(chal)) { - DEBUG(0,("Encrypted login but no challange set!\n")); - return False; - } - sec_blob = data_blob(chal, 8); - - if (lm_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - } - if (nt_resp.length == 0) { - } else if (nt_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - } else { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; - } - - return make_user_info_map(user_info, smb_name, - client_domain, - remote_machine, sec_blob, - lm_resp, - nt_resp, - no_plaintext_blob, - ntlmssp_flags, encrypted); - } - - generate_random_buffer(chal, 8, False); - - sec_blob = data_blob(chal, 8); - /* * Not encrypted - do so. */ - DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n")); if (plaintext_password.data) { unsigned char local_lm_response[24]; + +#ifdef DEBUG_PASSWORD + DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length)); + dump_data(100, plaintext_password.data, plaintext_password.length); +#endif SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); @@ -587,23 +505,54 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, remote_machine, - sec_blob, local_lm_blob, local_nt_blob, plaintext_password, - ntlmssp_flags, encrypted); + ntlmssp_flags, False); data_blob_free(&local_lm_blob); return ret; } /**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +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) +{ + uint32 ntlmssp_flags = 0; + + DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); + + if (lm_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + } + if (nt_resp.length == 0) { + } else if (nt_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + } else { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + + return make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, + lm_resp, + nt_resp, + no_plaintext_blob, + ntlmssp_flags, True); +} + +/**************************************************************************** Create a guest user_info blob, for anonymous authenticaion. ****************************************************************************/ BOOL make_user_info_guest(auth_usersupplied_info **user_info) { - DATA_BLOB sec_blob = data_blob(NULL, 0); DATA_BLOB lm_blob = data_blob(NULL, 0); DATA_BLOB nt_blob = data_blob(NULL, 0); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -612,7 +561,7 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info) return make_user_info(user_info, "","", "","", - "", sec_blob, + "", nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); @@ -680,7 +629,6 @@ void free_user_info(auth_usersupplied_info **user_info) SAFE_FREE((*user_info)->internal_username.str); SAFE_FREE((*user_info)->client_domain.str); SAFE_FREE((*user_info)->domain.str); - data_blob_free(&(*user_info)->sec_blob); data_blob_free(&(*user_info)->lm_resp); data_blob_free(&(*user_info)->nt_resp); SAFE_FREE((*user_info)->interactive_password); @@ -725,6 +673,22 @@ BOOL make_server_info_guest(auth_serversupplied_info **server_info) return False; } +/*************************************************************************** + Make an auth_methods struct +***************************************************************************/ + +BOOL make_auth_methods(auth_methods **auth_method) +{ + *auth_method = malloc(sizeof(**auth_method)); + if (!*auth_method) { + DEBUG(0,("make_auth_method: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*auth_method); + + return True; +} + /**************************************************************************** Delete a SID token. ****************************************************************************/ @@ -764,25 +728,3 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) return token; } - -/**************************************************************************** - Check for a guest logon (username = "") and if so create the required - structure. -****************************************************************************/ - -NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - if (!(user_info->internal_username.str - && *user_info->internal_username.str)) { - if (make_server_info_guest(server_info)) { - nt_status = NT_STATUS_OK; - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - } - - return nt_status; -} diff --git a/source3/include/auth.h b/source3/include/auth.h index 04c5aa55e5..e33ccc2e24 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -53,8 +53,6 @@ typedef struct usersupplied_info uint32 ntlmssp_flags; - DATA_BLOB sec_blob; - AUTH_STR client_domain; /* domain name string */ AUTH_STR domain; /* domain name after mapping */ AUTH_STR internal_username; /* username after mapping */ @@ -69,16 +67,16 @@ 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 serversupplied_info { BOOL guest; /* This groups info is needed for when we become_user() for this uid */ int n_groups; gid_t *groups; - + /* NT group information taken from the info3 structure */ - + NT_USER_TOKEN *ptok; uchar session_key[16]; @@ -86,8 +84,52 @@ typedef struct serversupplied_info uint8 first_8_lm_hash[8]; uint32 sam_fill_level; /* How far is this structure filled? */ - + SAM_ACCOUNT *sam_account; + + void *pam_handle; + } auth_serversupplied_info; +typedef struct authsupplied_info { + DATA_BLOB challange; + + /* Who set this up in the first place? */ + char *challange_set_by; \ + + struct auth_methods *challange_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; + +typedef struct auth_methods +{ + struct auth_methods *prev, *next; + char *name; /* What name got this module */ + + NTSTATUS (*auth)(void *my_private_data, + const auth_usersupplied_info *user_info, + const struct authsupplied_info *auth_info, + auth_serversupplied_info **server_info); + + DATA_BLOB (*get_chal)(void **my_private_data, const struct authsupplied_info *auth_info); + + /* Used to keep tabs on things like the cli for SMB server authentication */ + void *private_data; + + /* Function to clean up the above arbitary structure */ + void (*free_private_data)(void **private_data); + + /* Function to send a keepalive message on the above structure */ + void (*send_keepalive)(void **private_data); + +} auth_methods; + +typedef 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; + + #endif /* _SMBAUTH_H_ */ diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index f5d6c5a7f4..4ea19db9ec 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -197,7 +197,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user, int passlen; char *p; - passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE); + passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_ASCII); set_message(cli->outbuf,13,0,True); CVAL(cli->outbuf,smb_com) = SMBsesssetupX; diff --git a/source3/libsmb/domain_client_validate.c b/source3/libsmb/domain_client_validate.c index 2fd17e1fa4..df263e7ae9 100644 --- a/source3/libsmb/domain_client_validate.c +++ b/source3/libsmb/domain_client_validate.c @@ -271,9 +271,10 @@ static BOOL find_connect_pdc(struct cli_state *pcli, ************************************************************************/ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info, - char *server, unsigned char *trust_passwd, - time_t last_change_time) + uchar chal[8], + auth_serversupplied_info **server_info, + char *server, unsigned char *trust_passwd, + time_t last_change_time) { fstring remote_machine; NET_ID_INFO_CTR ctr; @@ -330,7 +331,7 @@ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info, * in the info3 structure. */ - status = cli_nt_login_network(&cli, user_info, smb_uid_low, + status = cli_nt_login_network(&cli, user_info, chal, smb_uid_low, &ctr, &info3); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 9138583096..2ea0692fe9 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -40,6 +40,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) NET_USER_INFO_3 info3; NET_ID_INFO_CTR ctr; struct cli_state *cli; + uchar chal[8]; DEBUG(3, ("[%5d]: pam auth %s\n", state->pid, state->request.data.auth.user)); @@ -59,7 +60,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) if (state->request.data.auth.pass[0]) make_user_info_winbind(&user_info, name_user, name_domain, - state->request.data.auth.pass); + state->request.data.auth.pass, + chal); else return WINBINDD_ERROR; @@ -87,7 +89,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) goto done; } - result = cli_nt_login_network(cli, user_info, smb_uid_low, + result = cli_nt_login_network(cli, user_info, chal, smb_uid_low, &ctr, &info3); free_user_info(&user_info); @@ -123,7 +125,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) make_user_info_winbind_crap( &user_info, name_user, - name_domain, state->request.data.auth_crap.chal, + name_domain, (uchar *)state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len, (uchar *)state->request.data.auth_crap.nt_resp, @@ -153,8 +155,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) goto done; } - result = cli_nt_login_network(cli, user_info, smb_uid_low, - &ctr, &info3); + result = cli_nt_login_network(cli, user_info, state->request.data.auth_crap.chal, + smb_uid_low, &ctr, &info3); free_user_info(&user_info); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 3f781be67f..ab17f90a6e 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -179,6 +179,7 @@ typedef struct int maxprotocol; int minprotocol; int security; + char **AuthMethods; BOOL paranoid_server_security; int maxdisksize; int lpqcachetime; @@ -238,7 +239,6 @@ typedef struct BOOL bNullPasswords; BOOL bObeyPamRestrictions; BOOL bLoadPrinters; - BOOL bUseRhosts; BOOL bLargeReadwrite; BOOL bReadRaw; BOOL bWriteRaw; @@ -261,7 +261,6 @@ typedef struct BOOL bRestrictAnonymous; BOOL bLanmanAuth; BOOL bNTLMAuth; - BOOL bPlaintextToSmbpasswd; BOOL bDebugHiresTimestamp; BOOL bDebugPid; BOOL bDebugUid; @@ -661,6 +660,7 @@ static struct parm_struct parm_table[] = { {"Security Options", P_SEP, P_SEPARATOR}, {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC}, + {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC}, {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC}, {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_BASIC}, {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, 0}, @@ -691,8 +691,6 @@ static struct parm_struct parm_table[] = { {"restrict anonymous", P_BOOL, P_GLOBAL, &Globals.bRestrictAnonymous, NULL, NULL, 0}, {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, 0}, {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, 0}, - {"plaintext to smbpasswd", P_BOOL, P_GLOBAL, &Globals.bPlaintextToSmbpasswd, NULL, NULL, 0}, - {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL, NULL, 0}, {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, 0}, @@ -1191,7 +1189,7 @@ static void init_globals(void) string_set(&Globals.szPassdbModulePath, ""); string_set(&Globals.szGuestaccount, GUEST_ACCOUNT); - + /* * Allow the default PASSWD_CHAT to be overridden in local.h. */ @@ -1218,7 +1216,6 @@ static void init_globals(void) string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast"); Globals.bLoadPrinters = True; - Globals.bUseRhosts = False; Globals.max_packet = 65535; Globals.mangled_stack = 50; Globals.max_xmit = 65535; @@ -1281,7 +1278,6 @@ static void init_globals(void) Globals.bRestrictAnonymous = False; Globals.bLanmanAuth = True; /* Do use the LanMan hash if it is available */ Globals.bNTLMAuth = True; /* Do use NTLMv1 if it is available (otherwise NTLMv2) */ - Globals.bPlaintextToSmbpasswd = False; /* Check the passwords with smbpasswd, even if in plaintext */ Globals.map_to_guest = 0; /* By Default, "Never" */ Globals.min_passwd_length = MINPASSWDLENGTH; /* By Default, 5. */ Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */ @@ -1543,7 +1539,6 @@ FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy) FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster) FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons) FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters) -FN_GLOBAL_BOOL(lp_use_rhosts, &Globals.bUseRhosts) FN_GLOBAL_BOOL(lp_readprediction, &Globals.bReadPrediction) FN_GLOBAL_BOOL(lp_readbmpx, &Globals.bReadbmpx) FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw) @@ -1573,7 +1568,6 @@ FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains) FN_GLOBAL_BOOL(lp_restrict_anonymous, &Globals.bRestrictAnonymous) FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth) FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth) -FN_GLOBAL_BOOL(lp_plaintext_to_smbpasswd, &Globals.bPlaintextToSmbpasswd) FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs) FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks) FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing) @@ -1594,6 +1588,7 @@ FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime) FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol) FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol) FN_GLOBAL_INTEGER(lp_security, &Globals.security) +FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods) FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security) FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize) FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime) diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index e190be99a5..ce79be1666 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1408,7 +1408,7 @@ BOOL pdb_getsampwuid (SAM_ACCOUNT *sam_acct, uid_t uid) struct smb_passwd *smb_pw; void *fp = NULL; - DEBUG(10, ("pdb_getsampwuid: search by uid: %d\n", uid)); + DEBUG(10, ("pdb_getsampwuid: search by uid: %d\n", (int)uid)); /* Open the sam password file - not for update. */ fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth); diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c index eaedb1613a..e5c221690d 100644 --- a/source3/rpc_client/cli_login.c +++ b/source3/rpc_client/cli_login.c @@ -159,9 +159,10 @@ password equivalents over the network. JRA. ****************************************************************************/ NTSTATUS cli_nt_login_network(struct cli_state *cli, - const auth_usersupplied_info *user_info, - uint32 smb_userid_low, NET_ID_INFO_CTR *ctr, - NET_USER_INFO_3 *user_info3) + const auth_usersupplied_info *user_info, + uchar chal[8], + uint32 smb_userid_low, NET_ID_INFO_CTR *ctr, + NET_USER_INFO_3 *user_info3) { DEBUG(5,("cli_nt_login_network: %d\n", __LINE__)); /* indicate a "network" login */ @@ -174,7 +175,7 @@ NTSTATUS cli_nt_login_network(struct cli_state *cli, ((user_info->wksta_name.len > 0) ? user_info->wksta_name.str : cli->clnt_name_slash), - user_info->sec_blob.data, + chal, user_info->lm_resp.data, user_info->lm_resp.length, user_info->nt_resp.data, user_info->nt_resp.length); diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 1aa58f5274..6f0d2384d5 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -566,26 +566,46 @@ 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); /* Standard challange/response authenticaion */ make_user_info_netlogon_network(&user_info, nt_username, nt_domain, - nt_workstation, ctr->auth.id2.lm_chal, + 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); + break; + } case INTERACTIVE_LOGON_TYPE: /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted with the session key. We will convert this to challange/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; + } + + chal = auth_get_challange(auth_info); + make_user_info_netlogon_interactive(&user_info, nt_username, nt_domain, - nt_workstation, + 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); + break; } default: @@ -593,8 +613,6 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * return NT_STATUS_INVALID_INFO_CLASS; } /* end switch */ - status = check_password(user_info, &server_info); - free_user_info(&user_info); DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index b9c40e719b..4b3140b350 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -271,6 +271,7 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm NTSTATUS nt_status; auth_usersupplied_info *user_info = NULL; + auth_authsupplied_info *auth_info = NULL; auth_serversupplied_info *server_info = NULL; uid_t *puid; @@ -343,17 +344,20 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm return False; } + + make_auth_info_fixed(&auth_info, (uchar*)p->challenge); if (!make_user_info_netlogon_network(&user_info, - user_name, domain, wks, (uchar*)p->challenge, + user_name, domain, wks, lm_owf, lm_pw_len, nt_owf, nt_pw_len)) { DEBUG(0,("make_user_info_netlogon_network failed! Failing authenticaion.\n")); return False; } - nt_status = check_password(user_info, &server_info); + nt_status = check_password(user_info, auth_info, &server_info); + free_auth_info(&auth_info); free_user_info(&user_info); p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status); diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 95c97182b8..c62e2ed5a0 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -58,27 +58,50 @@ static BOOL check_domain_match(char *user, char *domain) ****************************************************************************/ NTSTATUS check_password(const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - BOOL done_pam = False; const char *pdb_username; + auth_methods *auth_method; + + if (!user_info || !auth_info || !server_info) { + return NT_STATUS_LOGON_FAILURE; + } DEBUG(3, ("check_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str)); 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 (!NT_STATUS_IS_OK(nt_status)) { - nt_status = check_guest_security(user_info, server_info); + DEBUG(10, ("auth_info challange created by %s\n", auth_info->challange_set_by)); + DEBUG(10, ("challange is: \n")); + dump_data(5, (auth_info)->challange.data, (auth_info)->challange.length); + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("user_info has passwords of length %d and %d\n", + user_info->lm_resp.length, user_info->nt_resp.length)); + DEBUG(100, ("lm:\n")); + dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length); + DEBUG(100, ("nt:\n")); + dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length); +#endif + + for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next) + { + nt_status = auth_method->auth(auth_method->private_data, user_info, auth_info, server_info); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: checking guest-account for user [%s] suceeded\n", user_info->smb_name.str)); + DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n", + auth_method->name, user_info->smb_name.str)); } else { - DEBUG(10, ("check_password: checking gusst-account for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } + DEBUG(5, ("check_password: %s authentication for user [%s] FAILED with error %s\n", + auth_method->name, user_info->smb_name.str, get_nt_error_msg(nt_status))); + } + + if (NT_STATUS_IS_OK(nt_status)) { + break; + } } /* This needs to be sorted: If it doesn't match, what should we do? */ @@ -86,83 +109,47 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, return NT_STATUS_LOGON_FAILURE; } - if (!NT_STATUS_IS_OK(nt_status)) { - nt_status = check_rhosts_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: Password (rhosts) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(10, ("check_password: Password (rhosts) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - - if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) { - nt_status = check_domain_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (domain) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (domain) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - - if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) { - nt_status = check_server_security(user_info, server_info); - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (server) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (server) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } + /* This is one of the few places the *relies* (rather than just sets defaults + on the value of lp_security(). This needs to change. A new paramater + perhaps? */ if (lp_security() >= SEC_SERVER) { smb_user_control(user_info, *server_info, nt_status); } - if (!NT_STATUS_IS_OK(nt_status)) { - if (user_info->encrypted || lp_plaintext_to_smbpasswd()) { - nt_status = check_smbpasswd_security(user_info, server_info); - } else { - nt_status = check_unix_security(user_info, server_info); - done_pam = True; - } - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(7, ("check_password: Password (unix/smbpasswd) for user [%s] suceeded\n", user_info->smb_name.str)); - } else { - DEBUG(5, ("check_password: Password (unix/smbpasswd) for user [%s] FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status))); - - } - } - if (NT_STATUS_IS_OK(nt_status)) { pdb_username = pdb_get_username((*server_info)->sam_account); - if (!done_pam && !(*server_info)->guest) { + if (!(*server_info)->guest) { /* We might not be root if we are an RPC call */ become_root(); nt_status = smb_pam_accountcheck(pdb_username); unbecome_root(); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", pdb_username)); + DEBUG(5, ("check_password: PAM Account for user [%s] suceeded\n", + pdb_username)); } else { - DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", pdb_username, get_nt_error_msg(nt_status))); + DEBUG(3, ("check_password: PAM Account for user [%s] FAILED with error %s\n", + pdb_username, get_nt_error_msg(nt_status))); } } + + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG((*server_info)->guest ? 5 : 2, + ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", + (*server_info)->guest ? "guest " : "", + user_info->smb_name.str, + user_info->internal_username.str, + pdb_username)); + } } - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_password: %sauthenticaion for user [%s] -> [%s] -> [%s] suceeded\n", - (*server_info)->guest ? "guest " : "", - user_info->smb_name.str, - user_info->internal_username.str, - pdb_username)); - } else { - DEBUG(3, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", user_info->smb_name.str, user_info->internal_username.str, get_nt_error_msg(nt_status))); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2, ("check_password: Authenticaion for user [%s] -> [%s] FAILED with error %s\n", + user_info->smb_name.str, user_info->internal_username.str, + get_nt_error_msg(nt_status))); ZERO_STRUCTP(server_info); - } - + } return nt_status; } @@ -210,16 +197,35 @@ static NTSTATUS pass_check_smb(char *smb_name, { 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; + } - make_user_info_for_reply(&user_info, smb_name, - domain, - lm_pwd, - nt_pwd, - plaintext_password, - encrypted); - - nt_status = check_password(user_info, &server_info); + chal = auth_get_challange(plaintext_auth_info); + + if (!make_user_info_for_reply(&user_info, + smb_name, domain, chal.data, + plaintext_password)) { + return NT_STATUS_NO_MEMORY; + } + + 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); return nt_status; @@ -235,22 +241,23 @@ BOOL password_ok(char *smb_name, DATA_BLOB password_blob) DATA_BLOB null_password = data_blob(NULL, 0); extern BOOL global_encrypted_passwords_negotiated; - - if (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, global_encrypted_passwords_negotiated))) { + 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, global_encrypted_passwords_negotiated))) { + 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, global_encrypted_passwords_negotiated))) { + if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) { return True; } } diff --git a/source3/smbd/auth_builtin.c b/source3/smbd/auth_builtin.c new file mode 100644 index 0000000000..6ea6d0bbe0 --- /dev/null +++ b/source3/smbd/auth_builtin.c @@ -0,0 +1,87 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0. + Generic authenticaion types + 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" + +/**************************************************************************** + Check for a guest logon (username = "") and if so create the required + structure. +****************************************************************************/ + +static NTSTATUS check_guest_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (!(user_info->internal_username.str + && *user_info->internal_username.str)) { + if (make_server_info_guest(server_info)) { + nt_status = NT_STATUS_OK; + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + } + + return nt_status; +} + +BOOL auth_init_guest(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_guest_security; + return True; +} + +/**************************************************************************** + Check against either sam or unix, depending on encryption. +****************************************************************************/ + +static NTSTATUS check_local_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + + if (user_info->encrypted) { + nt_status = check_sam_security(my_private_data, user_info, auth_info, server_info); + } else { + nt_status = check_unix_security(my_private_data, user_info, auth_info, server_info); + } + + return nt_status; +} + +BOOL auth_init_local(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_local_security; + return True; +} + diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c index 4ada7d4a56..ef0e5b2f10 100644 --- a/source3/smbd/auth_domain.c +++ b/source3/smbd/auth_domain.c @@ -28,8 +28,10 @@ BOOL global_machine_password_needs_changing = False; Check for a valid username and password in security=domain mode. ****************************************************************************/ -NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_ntdomain_security(void *my_private_data, + 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; @@ -66,8 +68,18 @@ NTSTATUS check_domain_security(const auth_usersupplied_info *user_info, if (! *pserver) pserver = "*"; p = pserver; - nt_status = domain_client_validate(user_info, server_info, + nt_status = domain_client_validate(user_info, (uchar *)auth_info->challange.data,server_info, p, trust_passwd, last_change_time); return nt_status; } + +BOOL auth_init_ntdomain(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_ntdomain_security; + return True; +} diff --git a/source3/smbd/auth_info.c b/source3/smbd/auth_info.c new file mode 100644 index 0000000000..12b843d781 --- /dev/null +++ b/source3/smbd/auth_info.c @@ -0,0 +1,279 @@ +/* + 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" + +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 }, + { "unix", auth_init_unix }, + { "local", auth_init_local }, + { "smbserver", auth_init_smbserver }, + { "ntdomain", auth_init_ntdomain }, + { "winbind", auth_init_winbind }, + { NULL, NULL} +}; + +/*************************************************************************** + 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; + + 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)); + /* Malloc entry, fill it, link it */ + t = (auth_methods *)malloc(sizeof(*t)); + if (!t) { + DEBUG(0,("make_pw_chat: malloc failed!\n")); + return False; + } + + ZERO_STRUCTP(t); + + 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; + } + } + } + + make_auth_info_list(auth_info, list); + + 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 (!make_auth_info(auth_info)) { + return False; + } + + 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 ntdomain local"); + break; + case SEC_SERVER: + DEBUG(5,("Making default auth method list for security=server\n")); + auth_method_list = lp_list_make("guest smbserver local"); + break; + case SEC_USER: + DEBUG(5,("Making default auth method list for security=user\n")); + auth_method_list = lp_list_make("guest local"); + break; + case SEC_SHARE: + DEBUG(5,("Making default auth method list for security=share\n")); + auth_method_list = lp_list_make("guest local"); + break; + } + } 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 challange +***************************************************************************/ + +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)->challange = data_blob(chal, sizeof(chal)); + + (*auth_info)->challange_set_by = "random"; + + return True; +} + +/*************************************************************************** + Make a auth_info struct with a fixed challange +***************************************************************************/ + +BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8]) +{ + if (!make_auth_info_subsystem(auth_info)) { + return False; + } + + (*auth_info)->challange = 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) +{ + auth_methods *list; + if (*auth_info != NULL) { + list = (*auth_info)->auth_method_list; + 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); + } + + data_blob_free(&(*auth_info)->challange); + ZERO_STRUCT(**auth_info); + } + SAFE_FREE(*auth_info); +} + +/**************************************************************************** + Try to get a challange out of the various authenticaion modules. + It is up to the caller to free it. +****************************************************************************/ + +DATA_BLOB auth_get_challange(auth_authsupplied_info *auth_info) +{ + DATA_BLOB challange = data_blob(NULL, 0); + char *challange_set_by = NULL; + auth_methods *auth_method; + + if (auth_info->challange.length) { + DEBUG(5, ("auth_get_challange: returning previous challange (normal)\n")); + return data_blob(auth_info->challange.data, auth_info->challange.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_challange: getting challange from module %s\n", auth_method->name)); + if (challange_set_by) { + DEBUG(1, ("auth_get_challange: CONFIGURATION ERROR: authenticaion method %s has already specified a challange. Challange by %s ignored.\n", + challange_set_by, auth_method->name)); + } else { + challange = auth_method->get_chal(&auth_method->private_data, auth_info); + if (challange.length) { + DEBUG(5, ("auth_get_challange: sucessfully got challange from module %s\n", auth_method->name)); + auth_info->challange = challange; + challange_set_by = auth_method->name; + auth_info->challange_set_method = auth_method; + } else { + DEBUG(3, ("auth_get_challange: getting challange from authenticaion method %s FAILED.\n", + auth_method->name)); + } + } + } else { + DEBUG(5, ("auth_get_challange: module %s did not want to specify a challange\n", auth_method->name)); + } + } + + if (!challange_set_by) { + uchar chal[8]; + + generate_random_buffer(chal, sizeof(chal), False); + auth_info->challange = data_blob(chal, sizeof(chal)); + + challange_set_by = "random"; + } + + DEBUG(5, ("auth_info challange created by %s\n", challange_set_by)); + DEBUG(5, ("challange is: \n")); + dump_data(5, auth_info->challange.data, (auth_info)->challange.length); + + SMB_ASSERT(auth_info->challange.length == 8); + + auth_info->challange_set_by=challange_set_by; + + return data_blob(auth_info->challange.data, auth_info->challange.length); +} + + diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c index 9c07e48a9b..2605f0770a 100644 --- a/source3/smbd/auth_rhosts.c +++ b/source3/smbd/auth_rhosts.c @@ -135,7 +135,6 @@ check for a possible hosts equiv or rhosts entry for the user static BOOL check_hosts_equiv(struct passwd *pass) { char *fname = NULL; - pstring rhostsfile; if (!pass) return(False); @@ -148,39 +147,82 @@ static BOOL check_hosts_equiv(struct passwd *pass) return(True); } - if (lp_use_rhosts()) - { - char *home = pass->pw_dir; - if (home) { - slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); - if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) - return(True); - } - } - return(False); } + /**************************************************************************** Check for a valid .rhosts/hosts.equiv entry for this user ****************************************************************************/ -NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) +static NTSTATUS check_hostsequiv_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; struct passwd *pass = Get_Pwnam(user_info->internal_username.str); if (pass) { - become_root(); if (check_hosts_equiv(pass)) { nt_status = NT_STATUS_OK; make_server_info_pw(server_info, pass); } - unbecome_root(); } else { nt_status = NT_STATUS_NO_SUCH_USER; } return nt_status; } + + +/**************************************************************************** + Check for a valid .rhosts/hosts.equiv entry for this user +****************************************************************************/ + +static NTSTATUS check_rhosts_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) +{ + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + struct passwd *pass = Get_Pwnam(user_info->internal_username.str); + pstring rhostsfile; + + if (pass) { + char *home = pass->pw_dir; + if (home) { + slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home); + become_root(); + if (check_user_equiv(pass->pw_name,client_name(),rhostsfile)) { + nt_status = NT_STATUS_OK; + make_server_info_pw(server_info, pass); + } + unbecome_root(); + } + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } + + return nt_status; +} + +BOOL auth_init_hostsequiv(auth_methods **auth_method) +{ + + if (!make_auth_methods(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/smbd/auth_server.c b/source3/smbd/auth_server.c index ddbc284d50..067b5b2997 100644 --- a/source3/smbd/auth_server.c +++ b/source3/smbd/auth_server.c @@ -25,30 +25,18 @@ extern pstring global_myname; /**************************************************************************** - Return the client state structure. -****************************************************************************/ - -struct cli_state *server_client(void) -{ - static struct cli_state pw_cli; - return &pw_cli; -} - -/**************************************************************************** Support for server level security. ****************************************************************************/ -struct cli_state *server_cryptkey(void) +static struct cli_state *server_cryptkey(void) { - struct cli_state *cli; + struct cli_state *cli = NULL; fstring desthost; struct in_addr dest_ip; char *p, *pserver; BOOL connected_ok = False; - cli = server_client(); - - if (!cli_initialise(cli)) + if (!(cli = cli_initialise(cli))) return NULL; /* security = server just can't function with spnego */ @@ -88,7 +76,11 @@ struct cli_state *server_cryptkey(void) if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip)) return NULL; - + + if (strequal(desthost,myhostname())) { + exit_server("Password server loop!"); + } + DEBUG(3,("got session\n")); if (!cli_negprot(cli)) { @@ -109,13 +101,82 @@ struct cli_state *server_cryptkey(void) return cli; } +/**************************************************************************** + Clean up our allocated cli. +****************************************************************************/ + +static void free_server_private_data(void **private_data_pointer) +{ + struct cli_state **cli = (struct cli_state **)private_data_pointer; + if (*cli && (*cli)->initialised) { + cli_shutdown(*cli); + + SAFE_FREE(*cli); + } +} + +/**************************************************************************** + Send a 'keepalive' packet down the cli pipe. +****************************************************************************/ + +static void send_server_keepalive(void **private_data_pointer) +{ + struct cli_state **cli = (struct cli_state **)private_data_pointer; + + /* also send a keepalive to the password server if its still + connected */ + if (cli && *cli && (*cli)->initialised) { + if (!send_keepalive((*cli)->fd)) { + DEBUG( 2, ( "password server keepalive failed.\n")); + cli_shutdown(*cli); + SAFE_FREE(*cli); + } + } +} + +/**************************************************************************** + Get the challange out of a password server. +****************************************************************************/ + +static DATA_BLOB auth_get_challange_server(void **my_private_data, const struct authsupplied_info *auth_info) +{ + struct cli_state *cli = server_cryptkey(); + + if (cli) { + DEBUG(3,("using password server validation\n")); + if ((cli->sec_mode & 2) == 0) { + /* We can't work with unencrypted password servers + unless 'encrypt passwords = no' */ + DEBUG(5,("make_auth_info_server: Server is unencrypted, no challange available..\n")); + + *my_private_data = (void *)cli; + return data_blob(NULL, 0); + + } else if (cli->secblob.length < 8) { + /* We can't do much if we don't get a full challange */ + DEBUG(2,("make_auth_info_server: Didn't receive a full challange from server\n")); + cli_shutdown(cli); + return data_blob(NULL, 0); + } + + *my_private_data = (void *)cli; + + return data_blob(cli->secblob.data,8); + } else { + return data_blob(NULL, 0); + } +} + /**************************************************************************** Check for a valid username and password in security=server mode. - Validate a password with the password server. ****************************************************************************/ -NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +static NTSTATUS check_smbserver_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; @@ -123,13 +184,32 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser static BOOL tested_password_server = False; static BOOL bad_password_server = False; NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + BOOL locally_made_cli = False; - cli = server_client(); + cli = my_private_data; + + if (cli) { + } else { + cli = server_cryptkey(); + locally_made_cli = True; + } - if (!cli->initialised) { + if (!cli || !cli->initialised) { DEBUG(1,("password server %s is not connected\n", cli->desthost)); - return(NT_STATUS_LOGON_FAILURE); + return NT_STATUS_LOGON_FAILURE; } + + if ((cli->sec_mode & 2) == 0) { + if (user_info->encrypted) { + DEBUG(1,("password server %s is plaintext, but we are encrypted. This just can't work :-(\n", cli->desthost)); + return NT_STATUS_LOGON_FAILURE; + } + } else { + if (memcmp(cli->secblob.data, auth_info->challange.data, 8) != 0) { + DEBUG(1,("the challange 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; + } + } if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); @@ -206,17 +286,32 @@ use this machine as the password server.\n")); * not guest enabled, we can try with the real password. */ - if (!cli_session_setup(cli, user_info->smb_name.str, - (char *)user_info->lm_resp.data, - user_info->lm_resp.length, - (char *)user_info->nt_resp.data, - user_info->nt_resp.length, - user_info->domain.str)) { - DEBUG(1,("password server %s rejected the password\n", cli->desthost)); - /* Make this cli_nt_error() when the conversion is in */ - nt_status = cli_nt_error(cli); + if (!user_info->encrypted) { + /* Plaintext available */ + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->plaintext_password.data, + user_info->plaintext_password.length, + NULL, 0, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ + nt_status = cli_nt_error(cli); + } else { + nt_status = NT_STATUS_OK; + } } else { - nt_status = NT_STATUS_OK; + if (!cli_session_setup(cli, user_info->smb_name.str, + (char *)user_info->lm_resp.data, + user_info->lm_resp.length, + (char *)user_info->nt_resp.data, + user_info->nt_resp.length, + user_info->domain.str)) { + DEBUG(1,("password server %s rejected the password\n", cli->desthost)); + /* Make this cli_nt_error() when the conversion is in */ + nt_status = cli_nt_error(cli); + } else { + nt_status = NT_STATUS_OK; + } } /* if logged in as guest then reject */ @@ -238,5 +333,22 @@ use this machine as the password server.\n")); } } + if (locally_made_cli) { + cli_shutdown(cli); + SAFE_FREE(cli); + } + return(nt_status); } + +BOOL auth_init_smbserver(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_smbserver_security; + (*auth_method)->get_chal = auth_get_challange_server; + (*auth_method)->send_keepalive = send_server_keepalive; + (*auth_method)->free_private_data = free_server_private_data; + return True; +} diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 70632fb5df..24a4d4e4e4 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -96,7 +96,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, if (ntv2_response.length < 16) { /* We MUST have more than 16 bytes, or the stuff below will go crazy... */ - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", + DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", ntv2_response.length)); return False; } @@ -132,15 +132,16 @@ 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. ****************************************************************************/ -NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16]) +static NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + uint8 user_sess_key[16]) { + uint16 acct_ctrl; const uint8 *nt_pw, *lm_pw; - uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); uint32 ntlmssp_flags; - if (!user_info || !sampass) - return NT_STATUS_LOGON_FAILURE; - + acct_ctrl = pdb_get_acct_ctrl(sampass); if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) @@ -173,8 +174,8 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use */ DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n")); if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, - user_info->sec_blob, user_info->smb_name.str, + nt_pw, auth_info->challange, + user_info->smb_name.str, user_info->client_domain.str, user_sess_key)) { @@ -190,7 +191,7 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use */ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, user_info->sec_blob, + nt_pw, auth_info->challange, user_sess_key)) { return NT_STATUS_OK; @@ -223,7 +224,7 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use DEBUG(4,("smb_password_ok: Checking LM password\n")); if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, user_info->sec_blob, + lm_pw, auth_info->challange, user_sess_key)) { return NT_STATUS_OK; @@ -265,6 +266,24 @@ static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_inf return NT_STATUS_ACCOUNT_EXPIRED; } + if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { + time_t must_change_time = pdb_get_pass_must_change_time(sampass); + time_t last_set_time = pdb_get_pass_last_set_time(sampass); + + /* check for immediate expiry "must change at next logon" */ + if (must_change_time == 0 && last_set_time != 0) { + DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); + return NT_STATUS_PASSWORD_MUST_CHANGE; + } + + /* check for expired password */ + if (must_change_time < time(NULL) && must_change_time != 0) { + DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); + DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); + return NT_STATUS_PASSWORD_EXPIRED; + } + } + /* Test workstation. Workstation list is comma separated. */ workstation_list = strdup(pdb_get_workstations(sampass)); @@ -293,24 +312,6 @@ static NTSTATUS sam_account_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_inf SAFE_FREE(workstation_list); } - if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP)) { - time_t must_change_time = pdb_get_pass_must_change_time(sampass); - time_t last_set_time = pdb_get_pass_last_set_time(sampass); - - /* check for immediate expiry "must change at next logon" */ - if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); - return NT_STATUS_PASSWORD_MUST_CHANGE; - } - - /* check for expired password */ - if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); - return NT_STATUS_PASSWORD_EXPIRED; - } - } - if (acct_ctrl & ACB_DOMTRUST) { DEBUG(2,("session_trust_account: Domain trust account %s denied by server\n", pdb_get_username(sampass))); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; @@ -336,7 +337,10 @@ SMB hash supplied in the user_info structure return an NT_STATUS constant. ****************************************************************************/ -NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +NTSTATUS check_sam_security(void *my_private_dat, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { SAM_ACCOUNT *sampass=NULL; BOOL ret; @@ -344,7 +348,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ uint8 user_sess_key[16]; const uint8* lm_hash; - if (!user_info) { + if (!user_info || !auth_info) { return NT_STATUS_LOGON_FAILURE; } @@ -365,7 +369,7 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_password_ok(sampass, user_info, user_sess_key); + nt_status = sam_password_ok(sampass, user_info, auth_info, user_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); @@ -394,6 +398,15 @@ NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_ return nt_status; } +BOOL auth_init_sam(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + + (*auth_method)->auth = check_sam_security; + return True; +} diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c index 8c4a520350..d134ce6909 100644 --- a/source3/smbd/auth_unix.c +++ b/source3/smbd/auth_unix.c @@ -82,7 +82,10 @@ check if a username/password is OK assuming the password in PLAIN TEXT ****************************************************************************/ -NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) +NTSTATUS check_unix_security(void *my_private_data, + const auth_usersupplied_info *user_info, + const auth_authsupplied_info *auth_info, + auth_serversupplied_info **server_info) { NTSTATUS nt_status; struct passwd *pass = NULL; @@ -104,9 +107,19 @@ NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serve if (pass) { make_server_info_pw(server_info, pass); } else { + /* we need to do somthing more useful here */ nt_status = NT_STATUS_NO_SUCH_USER; } } return nt_status; } + +BOOL auth_init_unix(auth_methods **auth_method) +{ + if (!make_auth_methods(auth_method)) { + return False; + } + (*auth_method)->auth = check_unix_security; + return True; +} diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c index 25e0830fc7..d1b2cc92e5 100644 --- a/source3/smbd/auth_util.c +++ b/source3/smbd/auth_util.c @@ -23,49 +23,9 @@ #include "includes.h" -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; extern fstring remote_machine; extern pstring global_myname; -/******************************************************************* - Get the next challenge value - no repeats. -********************************************************************/ - -void generate_next_challenge(char *challenge) -{ - unsigned char buf[8]; - - generate_random_buffer(buf,8,False); - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; -} - -/******************************************************************* - Set the last challenge sent, usually from a password server. -********************************************************************/ - -BOOL set_challenge(unsigned char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* - Get the last challenge sent. -********************************************************************/ - -BOOL last_challenge(unsigned char *challenge) -{ - if (!challenge_sent) - return(False); - memcpy(challenge,saved_challenge,8); - return(True); -} - /**************************************************************************** Create a UNIX user on demand. ****************************************************************************/ @@ -166,7 +126,6 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, const char *client_domain, const char *domain, const char *wksta_name, - DATA_BLOB sec_blob, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) @@ -226,7 +185,6 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username)); - (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length); (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length); (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length); (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length); @@ -246,7 +204,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info, BOOL make_user_info_map(auth_usersupplied_info **user_info, const char *smb_name, const char *client_domain, - const char *wksta_name, DATA_BLOB sec_blob, + const char *wksta_name, DATA_BLOB lm_pwd, DATA_BLOB nt_pwd, DATA_BLOB plaintext, uint32 ntlmssp_flags, BOOL encrypted) @@ -265,7 +223,7 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, return make_user_info(user_info, smb_name, internal_username, client_domain, domain, - wksta_name, sec_blob, + wksta_name, lm_pwd, nt_pwd, plaintext, ntlmssp_flags, encrypted); @@ -280,12 +238,11 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info, BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - char *wksta_name, uchar chal[8], + char *wksta_name, uchar *lm_network_pwd, int lm_pwd_len, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -301,8 +258,8 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, - wksta_name, sec_blob, - nt_blob, lm_blob, + wksta_name, + lm_blob, nt_blob, plaintext_blob, ntlmssp_flags, True); @@ -320,6 +277,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, char *wksta_name, + char chal[8], uchar lm_interactive_pwd[16], uchar nt_interactive_pwd[16], uchar *dc_sess_key) @@ -329,11 +287,8 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; unsigned char key[16]; - uint8 chal[8]; uint32 ntlmssp_flags = 0; - generate_random_buffer(chal, 8, False); - ZERO_STRUCT(key); memcpy(key, dc_sess_key, 8); @@ -362,7 +317,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, dump_data(100, nt_pwd, sizeof(nt_pwd)); #endif - generate_random_buffer(chal, 8, False); SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response); SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response); @@ -373,7 +327,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response)); DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response)); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -385,7 +338,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, - wksta_name, sec_blob, + wksta_name, local_lm_blob, local_nt_blob, plaintext_blob, @@ -402,13 +355,14 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, - char *username, - char *domain, - char *password) + const char *username, + const char *domain, + const char *password, + char chal[8] /* Give winbind back the challange we used */ + ) { unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; - char chal[8]; DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; DATA_BLOB plaintext_blob; @@ -453,16 +407,11 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, sizeof(chal)); - - if (!sec_blob.data) { - return False; - } ret = make_user_info(user_info, username, username, domain, domain, - global_myname, sec_blob, + global_myname, local_nt_blob, local_lm_blob, plaintext_blob, @@ -483,12 +432,10 @@ BOOL make_user_info_winbind(auth_usersupplied_info **user_info, BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, char *smb_name, char *client_domain, - uchar chal[8], uchar *lm_network_pwd, int lm_pwd_len, uchar *nt_network_pwd, int nt_pwd_len) { BOOL ret; - DATA_BLOB sec_blob = data_blob(chal, 8); DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len); DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -502,7 +449,7 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, ret = make_user_info(user_info, smb_name, smb_name, client_domain, client_domain, - global_myname, sec_blob, + global_myname, nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); @@ -517,59 +464,30 @@ BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info, ****************************************************************************/ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, - char *smb_name, - char *client_domain, - DATA_BLOB lm_resp, DATA_BLOB nt_resp, - DATA_BLOB plaintext_password, - BOOL encrypted) + char *smb_name, + char *client_domain, + char chal[8], + DATA_BLOB plaintext_password) { - uchar chal[8]; DATA_BLOB local_lm_blob; DATA_BLOB local_nt_blob; - DATA_BLOB sec_blob; BOOL ret = False; uint32 ntlmssp_flags = 0; - if (encrypted) { - DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); - if (!last_challenge(chal)) { - DEBUG(0,("Encrypted login but no challange set!\n")); - return False; - } - sec_blob = data_blob(chal, 8); - - if (lm_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; - } - if (nt_resp.length == 0) { - } else if (nt_resp.length == 24) { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; - } else { - ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; - } - - return make_user_info_map(user_info, smb_name, - client_domain, - remote_machine, sec_blob, - lm_resp, - nt_resp, - no_plaintext_blob, - ntlmssp_flags, encrypted); - } - - generate_random_buffer(chal, 8, False); - - sec_blob = data_blob(chal, 8); - /* * Not encrypted - do so. */ - DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n")); + DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n")); if (plaintext_password.data) { unsigned char local_lm_response[24]; + +#ifdef DEBUG_PASSWORD + DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length)); + dump_data(100, plaintext_password.data, plaintext_password.length); +#endif SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); @@ -587,23 +505,54 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, ret = make_user_info_map(user_info, smb_name, client_domain, remote_machine, - sec_blob, local_lm_blob, local_nt_blob, plaintext_password, - ntlmssp_flags, encrypted); + ntlmssp_flags, False); data_blob_free(&local_lm_blob); return ret; } /**************************************************************************** + Create an auth_usersupplied_data structure +****************************************************************************/ + +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) +{ + uint32 ntlmssp_flags = 0; + + DATA_BLOB no_plaintext_blob = data_blob(NULL, 0); + + if (lm_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM; + } + if (nt_resp.length == 0) { + } else if (nt_resp.length == 24) { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM; + } else { + ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + + return make_user_info_map(user_info, smb_name, + client_domain, + remote_machine, + lm_resp, + nt_resp, + no_plaintext_blob, + ntlmssp_flags, True); +} + +/**************************************************************************** Create a guest user_info blob, for anonymous authenticaion. ****************************************************************************/ BOOL make_user_info_guest(auth_usersupplied_info **user_info) { - DATA_BLOB sec_blob = data_blob(NULL, 0); DATA_BLOB lm_blob = data_blob(NULL, 0); DATA_BLOB nt_blob = data_blob(NULL, 0); DATA_BLOB plaintext_blob = data_blob(NULL, 0); @@ -612,7 +561,7 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info) return make_user_info(user_info, "","", "","", - "", sec_blob, + "", nt_blob, lm_blob, plaintext_blob, ntlmssp_flags, True); @@ -680,7 +629,6 @@ void free_user_info(auth_usersupplied_info **user_info) SAFE_FREE((*user_info)->internal_username.str); SAFE_FREE((*user_info)->client_domain.str); SAFE_FREE((*user_info)->domain.str); - data_blob_free(&(*user_info)->sec_blob); data_blob_free(&(*user_info)->lm_resp); data_blob_free(&(*user_info)->nt_resp); SAFE_FREE((*user_info)->interactive_password); @@ -725,6 +673,22 @@ BOOL make_server_info_guest(auth_serversupplied_info **server_info) return False; } +/*************************************************************************** + Make an auth_methods struct +***************************************************************************/ + +BOOL make_auth_methods(auth_methods **auth_method) +{ + *auth_method = malloc(sizeof(**auth_method)); + if (!*auth_method) { + DEBUG(0,("make_auth_method: malloc failed!\n")); + return False; + } + ZERO_STRUCTP(*auth_method); + + return True; +} + /**************************************************************************** Delete a SID token. ****************************************************************************/ @@ -764,25 +728,3 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) return token; } - -/**************************************************************************** - Check for a guest logon (username = "") and if so create the required - structure. -****************************************************************************/ - -NTSTATUS check_guest_security(const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) -{ - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - - if (!(user_info->internal_username.str - && *user_info->internal_username.str)) { - if (make_server_info_guest(server_info)) { - nt_status = NT_STATUS_OK; - } else { - nt_status = NT_STATUS_NO_SUCH_USER; - } - } - - return nt_status; -} diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 045e16a9bb..d080c23332 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -27,6 +27,7 @@ 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; /**************************************************************************** reply for the core protocol @@ -68,6 +69,7 @@ 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(); @@ -77,8 +79,14 @@ static int reply_lanman1(char *inbuf, char *outbuf) set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ - if (global_encrypted_passwords_negotiated) - generate_next_challenge(smb_buf(outbuf)); + 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_challange(negprot_global_auth_info); + memcpy(smb_buf(outbuf), cryptkey.data, 8); + data_blob_free(&cryptkey); + } Protocol = PROTOCOL_LANMAN1; @@ -106,40 +114,26 @@ 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); - struct cli_state *cli = NULL; - char cryptkey[8]; - char crypt_len = 0; + DATA_BLOB cryptkey; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); - - if (lp_security() == SEC_SERVER) { - cli = server_cryptkey(); - } - - if (cli) { - DEBUG(3,("using password server validation\n")); - global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); - } - + if (lp_security()>=SEC_USER) secword |= 1; if (global_encrypted_passwords_negotiated) secword |= 2; + set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True); + SSVAL(outbuf,smb_vwv1,secword); + SIVAL(outbuf,smb_vwv6,sys_getpid()); + if (global_encrypted_passwords_negotiated) { - crypt_len = 8; - if (!cli) { - generate_next_challenge(cryptkey); - } else { - memcpy(cryptkey, cli->secblob.data, 8); - set_challenge((unsigned char *)cryptkey); + if (!make_auth_info_subsystem(&negprot_global_auth_info)) { + smb_panic("cannot make_negprot_global_auth_info!\n"); } + cryptkey = auth_get_challange(negprot_global_auth_info); + memcpy(smb_buf(outbuf), cryptkey.data, 8); + data_blob_free(&cryptkey); } - set_message(outbuf,13,crypt_len,True); - SSVAL(outbuf,smb_vwv1,secword); - SIVAL(outbuf,smb_vwv6,sys_getpid()); - if (global_encrypted_passwords_negotiated) - memcpy(smb_buf(outbuf), cryptkey, 8); - Protocol = PROTOCOL_LANMAN2; /* Reply, SMBlockread, SMBwritelock supported. */ @@ -202,45 +196,22 @@ static int reply_nt1(char *inbuf, char *outbuf) int secword=0; time_t t = time(NULL); - struct cli_state *cli = NULL; - uint8 cryptkey[8]; + DATA_BLOB cryptkey; char *p, *q; BOOL negotiate_spnego = False; global_encrypted_passwords_negotiated = lp_encrypted_passwords(); - if (lp_security() == SEC_SERVER) { - DEBUG(5,("attempting password server validation\n")); - cli = server_cryptkey(); - } else { - DEBUG(5,("not attempting password server validation\n")); - /* do spnego in user level security if the client - supports it and we can do encrypted passwords */ - if (global_encrypted_passwords_negotiated && - (lp_security() == SEC_USER || - lp_security() == SEC_DOMAIN) && - (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { - negotiate_spnego = True; - capabilities |= CAP_EXTENDED_SECURITY; - } - } + /* do spnego in user level security if the client + supports it and we can do encrypted passwords */ - if (cli) { - DEBUG(3,("using password server validation\n")); - global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0); - } else { - DEBUG(3,("not using password server validation\n")); + if (global_encrypted_passwords_negotiated && + (lp_security() != SEC_SHARE) && + (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { + negotiate_spnego = True; + capabilities |= CAP_EXTENDED_SECURITY; } - if (global_encrypted_passwords_negotiated) { - if (!cli) { - generate_next_challenge((char *)cryptkey); - } else { - memcpy(cryptkey, cli->secblob.data, 8); - set_challenge(cryptkey); - } - } - capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) { @@ -283,7 +254,14 @@ static int reply_nt1(char *inbuf, char *outbuf) p = q = smb_buf(outbuf); if (!negotiate_spnego) { - if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8); + 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_challange(negprot_global_auth_info); + memcpy(p, cryptkey.data, 8); + data_blob_free(&cryptkey); + } SSVALS(outbuf,smb_vwv16+1,8); p += 8; DEBUG(3,("not using SPNEGO\n")); @@ -467,11 +445,6 @@ int reply_negprot(connection_struct *conn, /* possibly reload - change of architecture */ reload_services(True); - /* a special case to stop password server loops */ - if (Index == 1 && strequal(remote_machine,myhostname()) && - (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN)) - exit_server("Password server loop!"); - /* Check for protocols, most desirable first */ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) { @@ -508,3 +481,4 @@ int reply_negprot(connection_struct *conn, END_PROFILE(SMBnegprot); return(outsize); } + diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b020cdd5d7..d9322ae26c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1112,19 +1112,23 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - struct cli_state *cli = server_client(); - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - /* also send a keepalive to the password server if its still - connected */ - if (cli && cli->initialised) - if (!send_keepalive(cli->fd)) { - DEBUG( 2, ( "password server keepalive failed.\n")); - cli_shutdown(cli); - } - last_keepalive_sent_time = t; + extern auth_authsupplied_info *negprot_global_auth_info; + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + + /* 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->challange_set_method + && negprot_global_auth_info->challange_set_method->send_keepalive) { + negprot_global_auth_info->challange_set_method->send_keepalive + (&negprot_global_auth_info->challange_set_method->private_data); + } + + last_keepalive_sent_time = t; } /* check for connection timeouts */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index b08c8e8bda..2f374e48aa 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -476,7 +476,7 @@ void exit_server(char *reason) { static int firsttime=1; extern char *last_inbuf; - + extern auth_authsupplied_info *negprot_global_auth_info; if (!firsttime) exit(0); @@ -485,6 +485,8 @@ void exit_server(char *reason) change_to_root_user(); DEBUG(2,("Closing connections\n")); + free_auth_info(&negprot_global_auth_info); + conn_close_all(); invalidate_all_vuids(); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index b3e9b7be8f..c9db359569 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -23,6 +23,7 @@ #include "includes.h" uint32 global_client_caps = 0; +static auth_authsupplied_info *ntlmssp_auth_info; /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. @@ -37,6 +38,31 @@ static void add_signature(char *outbuf) set_message_end(outbuf,p); } +/**************************************************************************** + Do a 'guest' logon, getting back the +****************************************************************************/ +static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) +{ + + auth_authsupplied_info *auth_info; + auth_usersupplied_info *user_info = NULL; + + NTSTATUS nt_status; + char chal[8]; + + ZERO_STRUCT(chal); + + DEBUG(3,("Got anonymous request\n")); + + make_user_info_guest(&user_info); + make_auth_info_fixed(&auth_info, chal); + + nt_status = check_password(user_info, auth_info, server_info); + free_auth_info(&auth_info); + return nt_status; +} + + #if HAVE_KRB5 /**************************************************************************** reply to a session setup spnego negotiate packet for kerberos @@ -189,7 +215,7 @@ static int reply_spnego_negotiate(connection_struct *conn, int i; uint32 ntlmssp_command, neg_flags; DATA_BLOB sess_key, chal, spnego_chal; - uint8 cryptkey[8]; + DATA_BLOB cryptkey; BOOL got_kerberos = False; /* parse out the OIDs and the first sec blob */ @@ -238,10 +264,12 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got neg_flags=%08x\n", neg_flags)); - if (!last_challenge(cryptkey)) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); + if (!make_auth_info_subsystem(&ntlmssp_auth_info)) { + return ERROR_NT(NT_STATUS_NO_MEMORY); } + cryptkey = auth_get_challange(ntlmssp_auth_info); + /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ @@ -255,7 +283,7 @@ static int reply_spnego_negotiate(connection_struct *conn, 0, 0x30, /* ?? */ neg_flags, - cryptkey, 8, + cryptkey.data, cryptkey.length, 0, 0, 0, 0x3000); /* ?? */ @@ -268,6 +296,7 @@ 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 */ @@ -286,11 +315,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, char *workgroup, *user, *machine; DATA_BLOB lmhash, nthash, sess_key; DATA_BLOB plaintext_password = data_blob(NULL, 0); - DATA_BLOB sec_blob; uint32 ntlmssp_command, neg_flags; NTSTATUS nt_status; int sess_vuid; - char chal[8]; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; @@ -327,26 +354,19 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, file_save("lmhash1.dat", lmhash.data, lmhash.length); #endif - if (!last_challenge(chal)) { - DEBUG(0,("Encrypted login but no challange set!\n")); - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } - sec_blob = data_blob(chal, 8); - if (!sec_blob.data) { - return ERROR_NT(NT_STATUS_NO_MEMORY); - } - if (!make_user_info_map(&user_info, user, workgroup, - machine, sec_blob, + machine, lmhash, nthash, plaintext_password, neg_flags, True)) { return ERROR_NT(NT_STATUS_NO_MEMORY); } - nt_status = check_password(user_info, &server_info); + nt_status = check_password(user_info, ntlmssp_auth_info, &server_info); + free_auth_info(&ntlmssp_auth_info); + free_user_info(&user_info); data_blob_free(&lmhash); @@ -383,18 +403,17 @@ static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *ou int length, int bufsize) { int sess_vuid; - auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; - NTSTATUS nt_status; - DEBUG(3,("Got anonymous request\n")); - - make_user_info_guest(&user_info); + nt_status = check_guest_password(&server_info); - nt_status = check_password(user_info, &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + return ERROR_NT(nt_status_squash(nt_status)); + } sess_vuid = register_vuid(server_info, lp_guestaccount()); + free_server_info(&server_info); if (sess_vuid == -1) { @@ -490,6 +509,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; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; @@ -523,16 +543,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, lm_resp = data_blob(smb_buf(inbuf), passlen1); } else { plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); - if (!plaintext_password.data) { - DEBUG(0,("reply_sesssetup_and_X: malloc failed for plaintext_password!\n")); - return ERROR_NT(NT_STATUS_NO_MEMORY); - } else { - /* Ensure null termination */ - plaintext_password.data[passlen1] = 0; - } + /* Ensure null termination */ + plaintext_password.data[passlen1] = 0; } srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE); + *domain = 0; } else { uint16 passlen1 = SVAL(inbuf,smb_vwv7); @@ -645,15 +661,41 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, *user = 0; } - if (!make_user_info_for_reply(&user_info, - user, domain, - lm_resp, nt_resp, - plaintext_password, doencrypt)) { - return ERROR_NT(NT_STATUS_NO_MEMORY); + if (!*user) { + + 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); + } + + 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_challange(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); + + data_blob_free(&chal); + free_auth_info(&plaintext_auth_info); } - - nt_status = check_password(user_info, &server_info); - + free_user_info(&user_info); data_blob_free(&lm_resp); @@ -726,3 +768,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, END_PROFILE(SMBsesssetupX); return chain_reply(inbuf,outbuf,length,bufsize); } + + + + + diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index c1b8b10a84..97dc0c014a 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -92,12 +92,6 @@ to a valid password server.\n", sec_setting ); ret = 1; } - if(lp_use_rhosts() && !lp_hostname_lookups()) { - printf("ERROR: The setting 'use rhosts = yes' requires the 'hostname lookups = yes'.\n"); - ret = 1; - } - - /* * Password chat sanity checks. */ |