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