summaryrefslogtreecommitdiff
path: root/source3/auth
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-01-05 04:55:41 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-01-05 04:55:41 +0000
commit2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95 (patch)
tree257e7ba36de49aca7039b32a8611fc8b6dea9555 /source3/auth
parent5a9c2f74ab0285859a6942bbc06d9e726cc69d19 (diff)
downloadsamba-2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95.tar.gz
samba-2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95.tar.bz2
samba-2e28f8ff0e3bb50ac5b2742c7678c39cb65bcd95.zip
I've decided to move the auth code around a bit more...
The auth_authsupplied_info typedef is now just a plain struct - auth_context, but it has been modified to contain the function pointers to the rest of the auth subsystem's components. (Who needs non-static functions anyway?) In working all this mess out, I fixed a number of memory leaks and moved the entire auth subsystem over to talloc(). Note that the TALLOC_CTX attached to the auth_context can be rather long-lived, it is provided for things that are intended to live as long. (The global_negprot_auth_context lasts the whole life of the smbd). I've also adjusted a few things in auth_domain.c, mainly passing the domain as a paramater to a few functions instead of looking up lp_workgroup(). I'm hopign to make this entire thing a bit more trusted domains (as PDC) freindly in the near future. Other than that, I moved a bit of the code around, hence the rather messy diff. Andrew Bartlett (This used to be commit 12f5515f556cf39fea98134fe3e2ac4540501048)
Diffstat (limited to 'source3/auth')
-rw-r--r--source3/auth/auth.c365
-rw-r--r--source3/auth/auth_builtin.c19
-rw-r--r--source3/auth/auth_compat.c111
-rw-r--r--source3/auth/auth_domain.c51
-rw-r--r--source3/auth/auth_info.c313
-rw-r--r--source3/auth/auth_rhosts.c34
-rw-r--r--source3/auth/auth_sam.c58
-rw-r--r--source3/auth/auth_server.c22
-rw-r--r--source3/auth/auth_unix.c10
-rw-r--r--source3/auth/auth_util.c63
-rw-r--r--source3/auth/auth_winbind.c21
11 files changed, 535 insertions, 532 deletions
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index bfd15dff34..6b68fa631a 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -1,10 +1,8 @@
/*
Unix SMB/Netbios implementation.
- Version 1.9.
+ Version 3.0.
Password and authentication handling
- Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Luke Kenneth Casson Leighton 1996-2000
- Copyright (C) Andrew Bartlett 2001
+ Copyright (C) Andrew Bartlett 2001-2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,6 +21,95 @@
#include "includes.h"
+/** List of various built-in authenticaion modules */
+
+const struct auth_init_function builtin_auth_init_functions[] = {
+ { "guest", auth_init_guest },
+ { "rhosts", auth_init_rhosts },
+ { "hostsequiv", auth_init_hostsequiv },
+ { "sam", auth_init_sam },
+ { "samstrict", auth_init_samstrict },
+ { "unix", auth_init_unix },
+ { "smbserver", auth_init_smbserver },
+ { "ntdomain", auth_init_ntdomain },
+ { "winbind", auth_init_winbind },
+#ifdef DEVELOPER
+ { "name_to_ntstatus", auth_init_name_to_ntstatus },
+#endif
+ { NULL, NULL}
+};
+
+/****************************************************************************
+ Try to get a challenge out of the various authenticaion modules.
+ Returns a const char of length 8 bytes.
+****************************************************************************/
+
+static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
+{
+ DATA_BLOB challenge = data_blob(NULL, 0);
+ char *challenge_set_by = NULL;
+ auth_methods *auth_method;
+ TALLOC_CTX *mem_ctx;
+
+ if (auth_context->challenge.length) {
+ DEBUG(5, ("get_ntlm_challange (auth subsystem): returning previous challenge (normal)\n"));
+ return auth_context->challenge.data;
+ }
+
+ for (auth_method = auth_context->auth_method_list; auth_method; auth_method = auth_method->next)
+ {
+ if (auth_method->get_chal == NULL) {
+ DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
+ continue;
+ }
+
+ DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
+ if (challenge_set_by != NULL) {
+ DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge. Challenge by %s ignored.\n",
+ challenge_set_by, auth_method->name));
+ continue;
+ }
+
+ mem_ctx = talloc_init_named("auth_get_challange for module %s", auth_method->name);
+ if (!mem_ctx) {
+ smb_panic("talloc_init_named() failed!");
+ }
+
+ challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx);
+ if (!challenge.length) {
+ DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n",
+ auth_method->name));
+ } else {
+ DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
+ auth_context->challenge = challenge;
+ challenge_set_by = auth_method->name;
+ auth_context->challenge_set_method = auth_method;
+ }
+ talloc_destroy(mem_ctx);
+ }
+
+ if (!challenge_set_by) {
+ uchar chal[8];
+
+ generate_random_buffer(chal, sizeof(chal), False);
+ auth_context->challenge = data_blob_talloc(auth_context->mem_ctx,
+ chal, sizeof(chal));
+
+ challenge_set_by = "random";
+ }
+
+ DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by));
+ DEBUG(5, ("challenge is: \n"));
+ dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
+
+ SMB_ASSERT(auth_context->challenge.length == 8);
+
+ auth_context->challenge_set_by=challenge_set_by;
+
+ return auth_context->challenge.data;
+}
+
+
/**
* Check user is in correct domain (if required)
*
@@ -81,9 +168,9 @@ static BOOL check_domain_match(const char *user, const char *domain)
*
**/
-NTSTATUS check_password(const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
- auth_serversupplied_info **server_info)
+static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
+ const struct auth_usersupplied_info *user_info,
+ struct auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
@@ -91,7 +178,7 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info,
auth_methods *auth_method;
TALLOC_CTX *mem_ctx;
- if (!user_info || !auth_info || !server_info) {
+ if (!user_info || !auth_context || !server_info) {
return NT_STATUS_LOGON_FAILURE;
}
@@ -100,11 +187,11 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info,
DEBUG(3, ("check_password: mapped user is: [%s]\\[%s]@[%s]\n",
user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str));
- if (auth_info->challenge_set_by) {
- DEBUG(10, ("auth_info challenge created by %s\n", auth_info->challenge_set_by));
+ if (auth_context->challenge_set_by) {
+ DEBUG(10, ("auth_context challenge created by %s\n", auth_context->challenge_set_by));
}
DEBUG(10, ("challenge is: \n"));
- dump_data(5, (auth_info)->challenge.data, (auth_info)->challenge.length);
+ dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("user_info has passwords of length %d and %d\n",
@@ -120,12 +207,12 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info,
return NT_STATUS_LOGON_FAILURE;
}
- for (auth_method = auth_info->auth_method_list;auth_method; auth_method = auth_method->next)
+ for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next)
{
mem_ctx = talloc_init_named("%s authentication for user %s\\%s", auth_method->name,
user_info->domain.str, user_info->smb_name.str);
- nt_status = auth_method->auth(auth_method->private_data, mem_ctx, user_info, auth_info, server_info);
+ nt_status = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3, ("check_password: %s authentication for user [%s] suceeded\n",
auth_method->name, user_info->smb_name.str));
@@ -182,124 +269,188 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info,
ZERO_STRUCTP(server_info);
}
return nt_status;
-
}
-/**
- * Squash an NT_STATUS in line with security requirements.
- * In an attempt to avoid giving the whole game away when users
- * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and
- * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations
- * (session setups in particular).
- *
- * @param nt_status NTSTATUS input for squashing.
- * @return the 'squashed' nt_status
- **/
+/***************************************************************************
+ Clear out a auth_context, and destroy the attached TALLOC_CTX
+***************************************************************************/
-NTSTATUS nt_status_squash(NTSTATUS nt_status)
+static void free_auth_context(struct auth_context **auth_context)
{
- if NT_STATUS_IS_OK(nt_status) {
- return nt_status;
- } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
- /* Match WinXP and don't give the game away */
- return NT_STATUS_LOGON_FAILURE;
-
- } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
- /* Match WinXP and don't give the game away */
- return NT_STATUS_LOGON_FAILURE;
- } else {
- return nt_status;
- }
+ if (*auth_context != NULL) {
+ talloc_destroy((*auth_context)->mem_ctx);
+ }
+ *auth_context = NULL;
}
+/***************************************************************************
+ Make a auth_info struct
+***************************************************************************/
+static NTSTATUS make_auth_context(struct auth_context **auth_context)
+{
+ TALLOC_CTX *mem_ctx;
-/****************************************************************************
- COMPATABILITY INTERFACES:
- ***************************************************************************/
+ mem_ctx = talloc_init_named("authentication context");
+
+ *auth_context = talloc(mem_ctx, sizeof(**auth_context));
+ if (!*auth_context) {
+ DEBUG(0,("make_auth_context: talloc failed!\n"));
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ZERO_STRUCTP(*auth_context);
-/****************************************************************************
-check if a username/password is OK assuming the password is a 24 byte
-SMB hash
-return True if the password is correct, False otherwise
-****************************************************************************/
+ (*auth_context)->mem_ctx = mem_ctx;
+ (*auth_context)->check_ntlm_password = check_ntlm_password;
+ (*auth_context)->get_ntlm_challenge = get_ntlm_challenge;
+ (*auth_context)->free = free_auth_context;
+
+ return NT_STATUS_OK;
+}
-static NTSTATUS pass_check_smb(char *smb_name,
- char *domain,
- DATA_BLOB lm_pwd,
- DATA_BLOB nt_pwd,
- DATA_BLOB plaintext_password,
- BOOL encrypted)
+/***************************************************************************
+ Make a auth_info struct for the auth subsystem
+***************************************************************************/
+static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context, char **text_list)
{
+ auth_methods *list = NULL;
+ auth_methods *t = NULL;
+ auth_methods *tmp;
+ int i;
NTSTATUS nt_status;
- auth_usersupplied_info *user_info = NULL;
- extern auth_authsupplied_info *negprot_global_auth_info;
- auth_serversupplied_info *server_info = NULL;
- if (encrypted) {
- make_user_info_for_reply_enc(&user_info, smb_name,
- domain,
- lm_pwd,
- nt_pwd,
- plaintext_password);
- nt_status = check_password(user_info, negprot_global_auth_info, &server_info);
- } else {
- auth_authsupplied_info *plaintext_auth_info = NULL;
- DATA_BLOB chal;
- if (!make_auth_info_subsystem(&plaintext_auth_info)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- chal = auth_get_challenge(plaintext_auth_info);
- if (!make_user_info_for_reply(&user_info,
- smb_name, domain, chal.data,
- plaintext_password)) {
- return NT_STATUS_NO_MEMORY;
+ if (!text_list) {
+ DEBUG(2,("No auth method list!?\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context))) {
+ return nt_status;
+ }
+
+ for (;*text_list; text_list++)
+ {
+ DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list));
+ for (i = 0; builtin_auth_init_functions[i].name; i++)
+ {
+ if (strequal(builtin_auth_init_functions[i].name, *text_list))
+ {
+ DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i));
+ if (builtin_auth_init_functions[i].init(*auth_context, &t)) {
+ DEBUG(5,("auth method %s has a valid init\n", *text_list));
+ t->name = builtin_auth_init_functions[i].name;
+ DLIST_ADD_END(list, t, tmp);
+ } else {
+ DEBUG(0,("auth method %s did not correctly init\n", *text_list));
+ }
+ break;
+ }
}
-
- nt_status = check_password(user_info, plaintext_auth_info, &server_info);
-
- data_blob_free(&chal);
- free_auth_info(&plaintext_auth_info);
- }
- free_user_info(&user_info);
- free_server_info(&server_info);
+ }
+
+ (*auth_context)->auth_method_list = list;
+
return nt_status;
}
-/****************************************************************************
-check if a username/password pair is OK either via the system password
-database or the encrypted SMB password database
-return True if the password is correct, False otherwise
-****************************************************************************/
-BOOL password_ok(char *smb_name, DATA_BLOB password_blob)
+/***************************************************************************
+ Make a auth_context struct for the auth subsystem
+***************************************************************************/
+
+NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context)
{
+ char **auth_method_list = NULL;
+ NTSTATUS nt_status;
- DATA_BLOB null_password = data_blob(NULL, 0);
- extern BOOL global_encrypted_passwords_negotiated;
- BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24);
-
- if (encrypted) {
- /*
- * The password could be either NTLM or plain LM. Try NTLM first,
- * but fall-through as required.
- * NTLMv2 makes no sense here.
- */
- if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) {
- return True;
- }
-
- if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) {
- return True;
+ if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (auth_method_list == NULL) {
+ switch (lp_security())
+ {
+ case SEC_DOMAIN:
+ DEBUG(5,("Making default auth method list for security=domain\n"));
+ auth_method_list = lp_list_make("guest samstrict ntdomain");
+ break;
+ case SEC_SERVER:
+ DEBUG(5,("Making default auth method list for security=server\n"));
+ auth_method_list = lp_list_make("guest samstrict smbserver");
+ break;
+ case SEC_USER:
+ if (lp_encrypted_passwords()) {
+ DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n"));
+ auth_method_list = lp_list_make("guest sam");
+ } else {
+ DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n"));
+ auth_method_list = lp_list_make("guest unix");
+ }
+ break;
+ case SEC_SHARE:
+ if (lp_encrypted_passwords()) {
+ DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n"));
+ auth_method_list = lp_list_make("guest sam");
+ } else {
+ DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n"));
+ auth_method_list = lp_list_make("guest unix");
+ }
+ break;
+ case SEC_ADS:
+ DEBUG(5,("Making default auth method list for security=ADS\n"));
+ auth_method_list = lp_list_make("guest samstrict ads ntdomain");
+ break;
+ default:
+ DEBUG(5,("Unknown auth method!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
}
} else {
- if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) {
- return True;
- }
+ DEBUG(5,("Using specified auth order\n"));
+ }
+
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_text_list(auth_context, auth_method_list))) {
+ lp_list_free(&auth_method_list);
+ return nt_status;
+ }
+
+ lp_list_free(&auth_method_list);
+ return nt_status;
+}
+
+/***************************************************************************
+ Make a auth_info struct with a random challenge
+***************************************************************************/
+
+NTSTATUS make_auth_context_random(struct auth_context **auth_context)
+{
+ uchar chal[8];
+ NTSTATUS nt_status;
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) {
+ return nt_status;
}
+
+ generate_random_buffer(chal, sizeof(chal), False);
+ (*auth_context)->challenge = data_blob(chal, sizeof(chal));
+
+ (*auth_context)->challenge_set_by = "random";
+
+ return nt_status;
+}
+
+/***************************************************************************
+ Make a auth_info struct with a fixed challenge
+***************************************************************************/
- return False;
+NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[8])
+{
+ NTSTATUS nt_status;
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) {
+ return nt_status;
+ }
+
+ (*auth_context)->challenge = data_blob(chal, 8);
+ return nt_status;
}
diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c
index f76987f685..f1c89689fa 100644
--- a/source3/auth/auth_builtin.c
+++ b/source3/auth/auth_builtin.c
@@ -29,10 +29,10 @@
* and pass onto the next module.
**/
-static NTSTATUS check_guest_security(void *my_private_data,
+static NTSTATUS check_guest_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
@@ -50,9 +50,9 @@ static NTSTATUS check_guest_security(void *my_private_data,
}
/* Guest modules initialisation */
-BOOL auth_init_guest(auth_methods **auth_method)
+BOOL auth_init_guest(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
@@ -73,10 +73,10 @@ BOOL auth_init_guest(auth_methods **auth_method)
* @return An NTSTATUS value based on the username
**/
-static NTSTATUS check_name_to_ntstatus_security(void *my_private_data,
+static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status;
@@ -100,9 +100,9 @@ static NTSTATUS check_name_to_ntstatus_security(void *my_private_data,
}
/** Module initailisation function */
-BOOL auth_init_name_to_ntstatus(auth_methods **auth_method)
+BOOL auth_init_name_to_ntstatus(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
@@ -110,6 +110,3 @@ BOOL auth_init_name_to_ntstatus(auth_methods **auth_method)
return True;
}
-
-
-
diff --git a/source3/auth/auth_compat.c b/source3/auth/auth_compat.c
new file mode 100644
index 0000000000..4039f0cc1e
--- /dev/null
+++ b/source3/auth/auth_compat.c
@@ -0,0 +1,111 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0.
+ Password and authentication handling
+ Copyright (C) Andrew Bartlett 2001-2002
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/****************************************************************************
+ COMPATABILITY INTERFACES:
+ ***************************************************************************/
+
+/****************************************************************************
+check if a username/password is OK assuming the password is a 24 byte
+SMB hash
+return True if the password is correct, False otherwise
+****************************************************************************/
+
+static NTSTATUS pass_check_smb(char *smb_name,
+ char *domain,
+ DATA_BLOB lm_pwd,
+ DATA_BLOB nt_pwd,
+ DATA_BLOB plaintext_password,
+ BOOL encrypted)
+
+{
+ NTSTATUS nt_status;
+ auth_usersupplied_info *user_info = NULL;
+ extern struct auth_context *negprot_global_auth_context;
+ auth_serversupplied_info *server_info = NULL;
+ if (encrypted) {
+ make_user_info_for_reply_enc(&user_info, smb_name,
+ domain,
+ lm_pwd,
+ nt_pwd);
+ nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
+ user_info, &server_info);
+ } else {
+ struct auth_context *plaintext_auth_context = NULL;
+ const uint8 *chal;
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
+ return nt_status;
+ }
+
+ chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
+
+ if (!make_user_info_for_reply(&user_info,
+ smb_name, domain, chal,
+ plaintext_password)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
+ user_info, &server_info);
+
+ plaintext_auth_context->free(&plaintext_auth_context);
+ }
+ free_user_info(&user_info);
+ free_server_info(&server_info);
+ return nt_status;
+}
+
+/****************************************************************************
+check if a username/password pair is ok via the auth subsystem.
+return True if the password is correct, False otherwise
+****************************************************************************/
+BOOL password_ok(char *smb_name, DATA_BLOB password_blob)
+{
+
+ DATA_BLOB null_password = data_blob(NULL, 0);
+ extern BOOL global_encrypted_passwords_negotiated;
+ BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24);
+
+ if (encrypted) {
+ /*
+ * The password could be either NTLM or plain LM. Try NTLM first,
+ * but fall-through as required.
+ * NTLMv2 makes no sense here.
+ */
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, encrypted))) {
+ return True;
+ }
+
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, encrypted))) {
+ return True;
+ }
+ } else {
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, encrypted))) {
+ return True;
+ }
+ }
+
+ return False;
+}
+
+
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index 6e3eb643d8..e836375406 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -125,8 +125,10 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli)));
Utility function to attempt a connection to an IP address of a DC.
************************************************************************/
-static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, struct in_addr *ip,
- unsigned char *trust_passwd)
+static NTSTATUS attempt_connect_to_dc(struct cli_state **cli,
+ const char *domain,
+ struct in_addr *ip,
+ unsigned char *trust_passwd)
{
fstring dc_name;
@@ -137,7 +139,7 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, struct in_addr *ip
if (is_zero_ip(*ip))
return NT_STATUS_UNSUCCESSFUL;
- if (!lookup_dc_name(global_myname, lp_workgroup(), ip, dc_name))
+ if (!lookup_dc_name(global_myname, domain, ip, dc_name))
return NT_STATUS_UNSUCCESSFUL;
return connect_to_domain_password_server(cli, dc_name, trust_passwd);
@@ -145,11 +147,12 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, struct in_addr *ip
/***********************************************************************
We have been asked to dynamcially determine the IP addresses of
- the PDC and BDC's for this DOMAIN, and query them in turn.
+ the PDC and BDC's for DOMAIN, and query them in turn.
************************************************************************/
static NTSTATUS find_connect_pdc(struct cli_state **cli,
- unsigned char *trust_passwd,
- time_t last_change_time)
+ const char *domain,
+ unsigned char *trust_passwd,
+ time_t last_change_time)
{
struct in_addr *ip_list = NULL;
int count = 0;
@@ -169,7 +172,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
if (time_now - last_change_time < 3600)
use_pdc_only = True;
- if (!get_dc_list(use_pdc_only, lp_workgroup(), &ip_list, &count))
+ if (!get_dc_list(use_pdc_only, domain, &ip_list, &count))
return NT_STATUS_UNSUCCESSFUL;
/*
@@ -180,7 +183,9 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
if(!is_local_net(ip_list[i]))
continue;
- if(NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, &ip_list[i], trust_passwd)))
+ if(NT_STATUS_IS_OK(nt_status =
+ attempt_connect_to_dc(cli, domain,
+ &ip_list[i], trust_passwd)))
break;
zero_ip(&ip_list[i]); /* Tried and failed. */
@@ -192,7 +197,9 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
if(!NT_STATUS_IS_OK(nt_status)) {
i = (sys_random() % count);
- if (!NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, &ip_list[i], trust_passwd)))
+ if (!NT_STATUS_IS_OK(nt_status =
+ attempt_connect_to_dc(cli, domain,
+ &ip_list[i], trust_passwd)))
zero_ip(&ip_list[i]); /* Tried and failed. */
}
@@ -206,7 +213,9 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
* Note that from a WINS server the #1 IP address is the PDC.
*/
for(i = 0; i < count; i++) {
- if (NT_STATUS_IS_OK(nt_status = attempt_connect_to_dc(cli, &ip_list[i], trust_passwd)))
+ if (NT_STATUS_IS_OK(nt_status =
+ attempt_connect_to_dc(cli, domain,
+ &ip_list[i], trust_passwd)))
break;
}
}
@@ -224,6 +233,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
+ const char *domain,
uchar chal[8],
auth_serversupplied_info **server_info,
char *server, unsigned char *trust_passwd,
@@ -246,7 +256,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
while (!NT_STATUS_IS_OK(nt_status) &&
next_token(&server,remote_machine,LIST_SEP,sizeof(remote_machine))) {
if(strequal(remote_machine, "*")) {
- nt_status = find_connect_pdc(&cli, trust_passwd, last_change_time);
+ nt_status = find_connect_pdc(&cli, domain, trust_passwd, last_change_time);
} else {
nt_status = connect_to_domain_password_server(&cli, remote_machine, trust_passwd);
}
@@ -376,18 +386,19 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
Check for a valid username and password in security=domain mode.
****************************************************************************/
-static NTSTATUS check_ntdomain_security(void *my_private_data,
+static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
char *p, *pserver;
unsigned char trust_passwd[16];
time_t last_change_time;
+ char *domain = lp_workgroup();
- if (!user_info || !server_info || !auth_info) {
+ if (!user_info || !server_info || !auth_context) {
DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n"));
return NT_STATUS_LOGON_FAILURE;
}
@@ -409,7 +420,7 @@ static NTSTATUS check_ntdomain_security(void *my_private_data,
* Get the machine account password for our primary domain
*/
- if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time))
+ if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time))
{
DEBUG(0, ("check_domain_security: could not fetch trust account password for domain %s\n", lp_workgroup()));
unbecome_root();
@@ -433,18 +444,22 @@ static NTSTATUS check_ntdomain_security(void *my_private_data,
if (! *pserver) pserver = "*";
p = pserver;
- nt_status = domain_client_validate(mem_ctx, user_info, (uchar *)auth_info->challenge.data,server_info,
+ nt_status = domain_client_validate(mem_ctx, user_info, domain,
+ (uchar *)auth_context->challenge.data,
+ server_info,
p, trust_passwd, last_change_time);
return nt_status;
}
-BOOL auth_init_ntdomain(auth_methods **auth_method)
+/* module initialisation */
+BOOL auth_init_ntdomain(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
(*auth_method)->auth = check_ntdomain_security;
return True;
}
+
diff --git a/source3/auth/auth_info.c b/source3/auth/auth_info.c
deleted file mode 100644
index 9d399a88eb..0000000000
--- a/source3/auth/auth_info.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 3.0.
- Authentication utility functions
- Copyright (C) Andrew Bartlett 2001
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-/** List of various built-in authenticaion modules */
-
-const struct auth_init_function builtin_auth_init_functions[] = {
- { "guest", auth_init_guest },
- { "rhosts", auth_init_rhosts },
- { "hostsequiv", auth_init_hostsequiv },
- { "sam", auth_init_sam },
- { "samstrict", auth_init_samstrict },
- { "unix", auth_init_unix },
- { "smbserver", auth_init_smbserver },
- { "ntdomain", auth_init_ntdomain },
- { "winbind", auth_init_winbind },
-#ifdef DEVELOPER
- { "name_to_ntstatus", auth_init_name_to_ntstatus },
-#endif
- { NULL, NULL}
-};
-
-/***************************************************************************
- Free a linked list of auth methods
-***************************************************************************/
-
-static void free_auth_methods_list(auth_methods **list)
-{
- if (list != NULL) {
- while (*list) {
- auth_methods *old_head = *list;
- if ((*list)->free_private_data) {
- (*list)->free_private_data(&((*list)->private_data));
- }
- DLIST_REMOVE(*list, *list);
- SAFE_FREE(old_head);
- }
-
- }
-}
-
-/***************************************************************************
- Make a auth_info struct
-***************************************************************************/
-
-static BOOL make_auth_info(auth_authsupplied_info **auth_info)
-{
- *auth_info = malloc(sizeof(**auth_info));
- if (!*auth_info) {
- DEBUG(0,("make_auth_info: malloc failed!\n"));
- return False;
- }
- ZERO_STRUCTP(*auth_info);
-
- return True;
-}
-
-/***************************************************************************
- Make a auth_info struct with a specified list.
-***************************************************************************/
-
-BOOL make_auth_info_list(auth_authsupplied_info **auth_info, auth_methods *list)
-{
- if (!make_auth_info(auth_info)) {
- return False;
- }
-
- (*auth_info)->auth_method_list = list;
-
- return True;
-}
-
-/***************************************************************************
- Make a auth_info struct for the auth subsystem
-***************************************************************************/
-
-static BOOL make_auth_info_text_list(auth_authsupplied_info **auth_info, char **text_list)
-{
- auth_methods *list = NULL;
- auth_methods *t = NULL;
- auth_methods *tmp;
- int i;
-
- if (!text_list) {
- DEBUG(2,("No auth method list!?\n"));
- return False;
- }
-
- for (;*text_list; text_list++)
- {
- DEBUG(5,("Attempting to find an auth method to match %s\n", *text_list));
- for (i = 0; builtin_auth_init_functions[i].name; i++)
- {
- if (strequal(builtin_auth_init_functions[i].name, *text_list))
- {
- DEBUG(5,("Found auth method %s (at pos %d)\n", *text_list, i));
- if (builtin_auth_init_functions[i].init(&t)) {
- DEBUG(5,("auth method %s has a valid init\n", *text_list));
- t->name = builtin_auth_init_functions[i].name;
- DLIST_ADD_END(list, t, tmp);
- } else {
- DEBUG(5,("auth method %s DOES NOT have a valid init\n", *text_list));
- }
- break;
- }
- }
- }
-
- if (!make_auth_info_list(auth_info, list)) {
- free_auth_methods_list(&list);
- return False;
- }
-
- return True;
-}
-
-/***************************************************************************
- Make a auth_info struct for the auth subsystem
-***************************************************************************/
-
-BOOL make_auth_info_subsystem(auth_authsupplied_info **auth_info)
-{
- char **auth_method_list = NULL;
-
- if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) {
- return False;
- }
-
- if (auth_method_list == NULL) {
- switch (lp_security())
- {
- case SEC_DOMAIN:
- DEBUG(5,("Making default auth method list for security=domain\n"));
- auth_method_list = lp_list_make("guest samstrict ntdomain");
- break;
- case SEC_SERVER:
- DEBUG(5,("Making default auth method list for security=server\n"));
- auth_method_list = lp_list_make("guest samstrict smbserver");
- break;
- case SEC_USER:
- if (lp_encrypted_passwords()) {
- DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n"));
- auth_method_list = lp_list_make("guest sam");
- } else {
- DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n"));
- auth_method_list = lp_list_make("guest unix");
- }
- break;
- case SEC_SHARE:
- if (lp_encrypted_passwords()) {
- DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n"));
- auth_method_list = lp_list_make("guest sam");
- } else {
- DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n"));
- auth_method_list = lp_list_make("guest unix");
- }
- break;
- case SEC_ADS:
- DEBUG(5,("Making default auth method list for security=ADS\n"));
- auth_method_list = lp_list_make("guest samstrict ads ntdomain");
- break;
- default:
- DEBUG(5,("Unknown auth method!\n"));
- return False;
- }
- } else {
- DEBUG(5,("Using specified auth order\n"));
- }
-
- if (!make_auth_info_text_list(auth_info, auth_method_list)) {
- lp_list_free(&auth_method_list);
- return False;
- }
-
- lp_list_free(&auth_method_list);
- return True;
-}
-
-/***************************************************************************
- Make a auth_info struct with a random challenge
-***************************************************************************/
-
-BOOL make_auth_info_random(auth_authsupplied_info **auth_info)
-{
- uchar chal[8];
- if (!make_auth_info_subsystem(auth_info)) {
- return False;
- }
-
- generate_random_buffer(chal, sizeof(chal), False);
- (*auth_info)->challenge = data_blob(chal, sizeof(chal));
-
- (*auth_info)->challenge_set_by = "random";
-
- return True;
-}
-
-/***************************************************************************
- Make a auth_info struct with a fixed challenge
-***************************************************************************/
-
-BOOL make_auth_info_fixed(auth_authsupplied_info **auth_info, uchar chal[8])
-{
- if (!make_auth_info_subsystem(auth_info)) {
- return False;
- }
-
- (*auth_info)->challenge = data_blob(chal, 8);
- return True;
-}
-
-/***************************************************************************
- Clear out a auth_info struct that has been allocated
-***************************************************************************/
-
-void free_auth_info(auth_authsupplied_info **auth_info)
-{
- if (*auth_info != NULL) {
- free_auth_methods_list(&(*auth_info)->auth_method_list);
-
- data_blob_free(&(*auth_info)->challenge);
- ZERO_STRUCT(**auth_info);
- }
- SAFE_FREE(*auth_info);
-}
-
-/****************************************************************************
- Try to get a challenge out of the various authenticaion modules.
- It is up to the caller to free it.
-****************************************************************************/
-
-DATA_BLOB auth_get_challenge(auth_authsupplied_info *auth_info)
-{
- DATA_BLOB challenge = data_blob(NULL, 0);
- char *challenge_set_by = NULL;
- auth_methods *auth_method;
- TALLOC_CTX *mem_ctx;
-
- if (auth_info->challenge.length) {
- DEBUG(5, ("auth_get_challenge: returning previous challenge (normal)\n"));
- return data_blob(auth_info->challenge.data, auth_info->challenge.length);
- }
-
- for (auth_method = auth_info->auth_method_list; auth_method; auth_method = auth_method->next)
- {
- if (auth_method->get_chal) {
- DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
- if (challenge_set_by) {
- DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authenticaion method %s has already specified a challenge. Challenge by %s ignored.\n",
- challenge_set_by, auth_method->name));
- } else {
- mem_ctx = talloc_init_named("auth_get_challange for module %s", auth_method->name);
- if (!mem_ctx) {
- smb_panic("talloc_init_named() failed!");
- }
-
- challenge = auth_method->get_chal(&auth_method->private_data, mem_ctx, auth_info);
- if (challenge.length) {
- DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
- auth_info->challenge = challenge;
- challenge_set_by = auth_method->name;
- auth_info->challenge_set_method = auth_method;
- } else {
- DEBUG(3, ("auth_get_challenge: getting challenge from authenticaion method %s FAILED.\n",
- auth_method->name));
- }
- talloc_destroy(mem_ctx);
- }
- } else {
- DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
- }
- }
-
- if (!challenge_set_by) {
- uchar chal[8];
-
- generate_random_buffer(chal, sizeof(chal), False);
- auth_info->challenge = data_blob(chal, sizeof(chal));
-
- challenge_set_by = "random";
- }
-
- DEBUG(5, ("auth_info challenge created by %s\n", challenge_set_by));
- DEBUG(5, ("challenge is: \n"));
- dump_data(5, auth_info->challenge.data, (auth_info)->challenge.length);
-
- SMB_ASSERT(auth_info->challenge.length == 8);
-
- auth_info->challenge_set_by=challenge_set_by;
-
- return data_blob(auth_info->challenge.data, auth_info->challenge.length);
-}
-
-
diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c
index 1dd97872da..55ff7aa060 100644
--- a/source3/auth/auth_rhosts.c
+++ b/source3/auth/auth_rhosts.c
@@ -155,10 +155,10 @@ static BOOL check_hosts_equiv(struct passwd *pass)
Check for a valid .rhosts/hosts.equiv entry for this user
****************************************************************************/
-static NTSTATUS check_hostsequiv_security(void *my_private_data,
+static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
@@ -176,15 +176,26 @@ static NTSTATUS check_hostsequiv_security(void *my_private_data,
return nt_status;
}
+/* module initialisation */
+BOOL auth_init_hostsequiv(struct auth_context *auth_context, auth_methods **auth_method)
+{
+ if (!make_auth_methods(auth_context, auth_method)) {
+ return False;
+ }
+
+ (*auth_method)->auth = check_hostsequiv_security;
+ return True;
+}
+
/****************************************************************************
Check for a valid .rhosts/hosts.equiv entry for this user
****************************************************************************/
-static NTSTATUS check_rhosts_security(void *my_private_data,
+static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
@@ -209,22 +220,13 @@ static NTSTATUS check_rhosts_security(void *my_private_data,
return nt_status;
}
-BOOL auth_init_hostsequiv(auth_methods **auth_method)
+/* module initialisation */
+BOOL auth_init_rhosts(struct auth_context *auth_context, auth_methods **auth_method)
{
-
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
- (*auth_method)->auth = check_hostsequiv_security;
- return True;
-}
-BOOL auth_init_rhosts(auth_methods **auth_method)
-{
-
- if (!make_auth_methods(auth_method)) {
- return False;
- }
(*auth_method)->auth = check_rhosts_security;
return True;
}
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index c8b5386f7a..f1bcae461e 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -27,9 +27,9 @@
core of smb password checking routine.
****************************************************************************/
static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response,
- const uchar *part_passwd,
- DATA_BLOB sec_blob,
- uint8 user_sess_key[16])
+ const uchar *part_passwd,
+ DATA_BLOB sec_blob,
+ uint8 user_sess_key[16])
{
/* Finish the encryption of part_passwd. */
uchar p24[24];
@@ -75,10 +75,10 @@ static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response,
core of smb password checking routine.
****************************************************************************/
static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response,
- const uchar *part_passwd,
- const DATA_BLOB sec_blob,
- const char *user, const char *domain,
- uint8 user_sess_key[16])
+ const uchar *part_passwd,
+ const DATA_BLOB sec_blob,
+ const char *user, const char *domain,
+ uint8 user_sess_key[16])
{
/* Finish the encryption of part_passwd. */
uchar kr[16];
@@ -132,10 +132,10 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response,
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
-static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx,
+static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
+ TALLOC_CTX *mem_ctx,
SAM_ACCOUNT *sampass,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
uint8 user_sess_key[16])
{
uint16 acct_ctrl;
@@ -175,7 +175,7 @@ static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx,
*/
DEBUG(4,("sam_password_ok: Checking NTLMv2 password\n"));
if (smb_pwd_check_ntlmv2( user_info->nt_resp,
- nt_pw, auth_info->challenge,
+ nt_pw, auth_context->challenge,
user_info->smb_name.str,
user_info->client_domain.str,
user_sess_key))
@@ -192,7 +192,7 @@ static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx,
*/
DEBUG(4,("sam_password_ok: Checking NT MD4 password\n"));
if (smb_pwd_check_ntlmv1(user_info->nt_resp,
- nt_pw, auth_info->challenge,
+ nt_pw, auth_context->challenge,
user_sess_key))
{
return NT_STATUS_OK;
@@ -225,7 +225,7 @@ static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx,
DEBUG(4,("sam_password_ok: Checking LM password\n"));
if (smb_pwd_check_ntlmv1(user_info->lm_resp,
- lm_pw, auth_info->challenge,
+ lm_pw, auth_context->challenge,
user_sess_key))
{
return NT_STATUS_OK;
@@ -337,10 +337,10 @@ SMB hash supplied in the user_info structure
return an NT_STATUS constant.
****************************************************************************/
-static NTSTATUS check_sam_security(void *my_private_data,
+static NTSTATUS check_sam_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
SAM_ACCOUNT *sampass=NULL;
@@ -349,8 +349,8 @@ static NTSTATUS check_sam_security(void *my_private_data,
uint8 user_sess_key[16];
const uint8* lm_hash;
- if (!user_info || !auth_info) {
- return NT_STATUS_LOGON_FAILURE;
+ if (!user_info || !auth_context) {
+ return NT_STATUS_UNSUCCESSFUL;
}
if (!pdb_init_sam(&sampass)) {
@@ -370,7 +370,7 @@ static NTSTATUS check_sam_security(void *my_private_data,
return NT_STATUS_NO_SUCH_USER;
}
- nt_status = sam_password_ok(mem_ctx, sampass, user_info, auth_info, user_sess_key);
+ nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key);
if (!NT_STATUS_IS_OK(nt_status)) {
pdb_free_sam(&sampass);
@@ -399,9 +399,10 @@ static NTSTATUS check_sam_security(void *my_private_data,
return nt_status;
}
-BOOL auth_init_sam(auth_methods **auth_method)
+/* module initialisation */
+BOOL auth_init_sam(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
@@ -409,20 +410,19 @@ BOOL auth_init_sam(auth_methods **auth_method)
return True;
}
+
/****************************************************************************
-check if a username/password is OK assuming the password is a 24 byte
-SMB hash supplied in the user_info structure
-return an NT_STATUS constant.
+Check SAM security (above) but with a few extra checks.
****************************************************************************/
-static NTSTATUS check_samstrict_security(void *my_private_data,
+static NTSTATUS check_samstrict_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
- if (!user_info || !auth_info) {
+ if (!user_info || !auth_context) {
return NT_STATUS_LOGON_FAILURE;
}
@@ -434,12 +434,13 @@ static NTSTATUS check_samstrict_security(void *my_private_data,
return NT_STATUS_NO_SUCH_USER;
}
- return check_sam_security(my_private_data, mem_ctx, user_info, auth_info, server_info);
+ return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info);
}
-BOOL auth_init_samstrict(auth_methods **auth_method)
+/* module initialisation */
+BOOL auth_init_samstrict(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
@@ -447,3 +448,4 @@ BOOL auth_init_samstrict(auth_methods **auth_method)
return True;
}
+
diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c
index 7178e3147c..c83230b716 100644
--- a/source3/auth/auth_server.c
+++ b/source3/auth/auth_server.c
@@ -134,9 +134,9 @@ static void send_server_keepalive(void **private_data_pointer)
Get the challenge out of a password server.
****************************************************************************/
-static DATA_BLOB auth_get_challenge_server(void **my_private_data,
- TALLOC_CTX *mem_ctx,
- const struct authsupplied_info *auth_info)
+static DATA_BLOB auth_get_challenge_server(const struct auth_context *auth_context,
+ void **my_private_data,
+ TALLOC_CTX *mem_ctx)
{
struct cli_state *cli = server_cryptkey(mem_ctx);
@@ -161,8 +161,10 @@ static DATA_BLOB auth_get_challenge_server(void **my_private_data,
}
*my_private_data = (void *)cli;
-
- return data_blob(cli->secblob.data,8);
+
+ /* The return must be allocated on the caller's mem_ctx, as our own will be
+ destoyed just after the call. */
+ return data_blob_talloc(auth_context->mem_ctx, cli->secblob.data,8);
} else {
return data_blob(NULL, 0);
}
@@ -174,10 +176,10 @@ static DATA_BLOB auth_get_challenge_server(void **my_private_data,
- Validate a password with the password server.
****************************************************************************/
-static NTSTATUS check_smbserver_security(void *my_private_data,
+static NTSTATUS check_smbserver_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
struct cli_state *cli;
@@ -218,7 +220,7 @@ static NTSTATUS check_smbserver_security(void *my_private_data,
return NT_STATUS_LOGON_FAILURE;
}
} else {
- if (memcmp(cli->secblob.data, auth_info->challenge.data, 8) != 0) {
+ if (memcmp(cli->secblob.data, auth_context->challenge.data, 8) != 0) {
DEBUG(1,("the challenge that the password server (%s) supplied us is not the one we gave our client. This just can't work :-(\n", cli->desthost));
return NT_STATUS_LOGON_FAILURE;
}
@@ -353,9 +355,9 @@ use this machine as the password server.\n"));
return(nt_status);
}
-BOOL auth_init_smbserver(auth_methods **auth_method)
+BOOL auth_init_smbserver(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
(*auth_method)->auth = check_smbserver_security;
diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c
index fa889af5f6..69c24b8213 100644
--- a/source3/auth/auth_unix.c
+++ b/source3/auth/auth_unix.c
@@ -83,10 +83,10 @@ static BOOL update_smbpassword_file(char *user, char *password)
* unless the account has a null password.
**/
-NTSTATUS check_unix_security(void *my_private_data,
+static NTSTATUS check_unix_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status;
@@ -120,11 +120,13 @@ NTSTATUS check_unix_security(void *my_private_data,
return nt_status;
}
-BOOL auth_init_unix(auth_methods **auth_method)
+/* module initialisation */
+BOOL auth_init_unix(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
+
(*auth_method)->auth = check_unix_security;
return True;
}
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index d9f3098e7c..a479f52ab2 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -276,13 +276,13 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
****************************************************************************/
BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
- char *smb_name,
- char *client_domain,
- char *wksta_name,
- uchar chal[8],
- uchar lm_interactive_pwd[16],
- uchar nt_interactive_pwd[16],
- uchar *dc_sess_key)
+ const char *smb_name,
+ const char *client_domain,
+ const char *wksta_name,
+ const uchar chal[8],
+ const uchar lm_interactive_pwd[16],
+ const uchar nt_interactive_pwd[16],
+ const uchar *dc_sess_key)
{
char lm_pwd[16];
char nt_pwd[16];
@@ -360,7 +360,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
char *smb_name,
char *client_domain,
- unsigned char chal[8],
+ const uint8 chal[8],
DATA_BLOB plaintext_password)
{
@@ -383,7 +383,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
dump_data(100, plaintext_password.data, plaintext_password.length);
#endif
- SMBencrypt( (const uchar *)plaintext_password.data, chal, local_lm_response);
+ SMBencrypt( (const uchar *)plaintext_password.data, (const uchar*)chal, local_lm_response);
local_lm_blob = data_blob(local_lm_response, 24);
/* We can't do an NT hash here, as the password needs to be
@@ -415,8 +415,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
BOOL make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
char *smb_name,
char *client_domain,
- DATA_BLOB lm_resp, DATA_BLOB nt_resp,
- DATA_BLOB plaintext_password)
+ DATA_BLOB lm_resp, DATA_BLOB nt_resp)
{
uint32 ntlmssp_flags = 0;
@@ -572,9 +571,17 @@ BOOL make_server_info_guest(auth_serversupplied_info **server_info)
Make an auth_methods struct
***************************************************************************/
-BOOL make_auth_methods(auth_methods **auth_method)
+BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method)
{
- *auth_method = malloc(sizeof(**auth_method));
+ if (!auth_context) {
+ smb_panic("no auth_context supplied to make_auth_methods()!\n");
+ }
+
+ if (!auth_method) {
+ smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
+ }
+
+ *auth_method = talloc(auth_context->mem_ctx, sizeof(**auth_method));
if (!*auth_method) {
DEBUG(0,("make_auth_method: malloc failed!\n"));
return False;
@@ -623,3 +630,33 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
return token;
}
+
+/**
+ * Squash an NT_STATUS in line with security requirements.
+ * In an attempt to avoid giving the whole game away when users
+ * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and
+ * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations
+ * (session setups in particular).
+ *
+ * @param nt_status NTSTATUS input for squashing.
+ * @return the 'squashed' nt_status
+ **/
+
+NTSTATUS nt_status_squash(NTSTATUS nt_status)
+{
+ if NT_STATUS_IS_OK(nt_status) {
+ return nt_status;
+ } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
+ /* Match WinXP and don't give the game away */
+ return NT_STATUS_LOGON_FAILURE;
+
+ } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
+ /* Match WinXP and don't give the game away */
+ return NT_STATUS_LOGON_FAILURE;
+ } else {
+ return nt_status;
+ }
+}
+
+
+
diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index 74654f8bba..175e14a9d6 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -33,10 +33,10 @@ NSS_STATUS winbindd_request(int req_type,
/* Authenticate a user with a challenge/response */
-static NTSTATUS check_winbind_security(void *my_private_data,
+static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
+ void *my_private_data,
TALLOC_CTX *mem_ctx,
const auth_usersupplied_info *user_info,
- const auth_authsupplied_info *auth_info,
auth_serversupplied_info **server_info)
{
struct winbindd_request request;
@@ -46,13 +46,13 @@ static NTSTATUS check_winbind_security(void *my_private_data,
NTSTATUS nt_status;
if (!user_info) {
- return NT_STATUS_LOGON_FAILURE;
+ return NT_STATUS_UNSUCCESSFUL;
}
- if (!auth_info) {
+ if (!auth_context) {
DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n",
user_info->internal_username.str));
- return NT_STATUS_LOGON_FAILURE;
+ return NT_STATUS_UNSUCCESSFUL;
}
/* Send off request */
@@ -63,7 +63,7 @@ static NTSTATUS check_winbind_security(void *my_private_data,
snprintf(request.data.auth_crap.user, sizeof(request.data.auth_crap.user),
"%s\\%s", user_info->domain.str, user_info->smb_name.str);
- memcpy(request.data.auth_crap.chal, auth_info->challenge.data, sizeof(request.data.auth_crap.chal));
+ memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal));
request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length,
sizeof(request.data.auth_crap.lm_resp));
@@ -97,16 +97,13 @@ static NTSTATUS check_winbind_security(void *my_private_data,
return nt_status;
}
-BOOL auth_init_winbind(auth_methods **auth_method)
+/* module initialisation */
+BOOL auth_init_winbind(struct auth_context *auth_context, auth_methods **auth_method)
{
- if (!make_auth_methods(auth_method)) {
+ if (!make_auth_methods(auth_context, auth_method)) {
return False;
}
(*auth_method)->auth = check_winbind_security;
return True;
}
-
-
-
-