summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in3
-rw-r--r--source3/auth/auth.c165
-rw-r--r--source3/auth/auth_builtin.c87
-rw-r--r--source3/auth/auth_domain.c18
-rw-r--r--source3/auth/auth_info.c279
-rw-r--r--source3/auth/auth_rhosts.c72
-rw-r--r--source3/auth/auth_sam.c75
-rw-r--r--source3/auth/auth_server.c172
-rw-r--r--source3/auth/auth_unix.c15
-rw-r--r--source3/auth/auth_util.c208
-rw-r--r--source3/include/auth.h54
-rw-r--r--source3/libsmb/cliconnect.c2
-rw-r--r--source3/libsmb/domain_client_validate.c9
-rw-r--r--source3/nsswitch/winbindd_pam.c12
-rw-r--r--source3/param/loadparm.c13
-rw-r--r--source3/passdb/pdb_smbpasswd.c2
-rw-r--r--source3/rpc_client/cli_login.c9
-rw-r--r--source3/rpc_server/srv_netlog_nt.c26
-rw-r--r--source3/rpc_server/srv_pipe.c8
-rw-r--r--source3/smbd/auth.c165
-rw-r--r--source3/smbd/auth_builtin.c87
-rw-r--r--source3/smbd/auth_domain.c18
-rw-r--r--source3/smbd/auth_info.c279
-rw-r--r--source3/smbd/auth_rhosts.c72
-rw-r--r--source3/smbd/auth_server.c172
-rw-r--r--source3/smbd/auth_smbpasswd.c75
-rw-r--r--source3/smbd/auth_unix.c15
-rw-r--r--source3/smbd/auth_util.c208
-rw-r--r--source3/smbd/negprot.c102
-rw-r--r--source3/smbd/process.c30
-rw-r--r--source3/smbd/server.c4
-rw-r--r--source3/smbd/sesssetup.c123
-rw-r--r--source3/utils/testparm.c6
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.
*/