1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +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:
Andrew Bartlett 0001-01-01 00:00:00 +00:00
parent 207ee8aac4
commit 12f5515f55
19 changed files with 696 additions and 659 deletions

View File

@ -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 \

View File

@ -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;
if (*auth_context != NULL) {
talloc_destroy((*auth_context)->mem_ctx);
}
*auth_context = NULL;
}
} 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 {
/***************************************************************************
Make a auth_info struct
***************************************************************************/
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;
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;
}
}
}
(*auth_context)->auth_method_list = list;
return nt_status;
}
/***************************************************************************
Make a auth_context struct for the auth subsystem
***************************************************************************/
NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context)
{
char **auth_method_list = NULL;
NTSTATUS nt_status;
/****************************************************************************
COMPATABILITY INTERFACES:
***************************************************************************/
if (lp_auth_methods() && !lp_list_copy(&auth_method_list, lp_auth_methods())) {
return NT_STATUS_NO_MEMORY;
}
/****************************************************************************
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
****************************************************************************/
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"));
}
static NTSTATUS pass_check_smb(char *smb_name,
char *domain,
DATA_BLOB lm_pwd,
DATA_BLOB nt_pwd,
DATA_BLOB plaintext_password,
BOOL encrypted)
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;
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;
if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) {
return nt_status;
}
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;
}
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)->challenge = data_blob(chal, 8);
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)
{
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;
}

View File

@ -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
View 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;
}

View File

@ -125,7 +125,9 @@ 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,
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,9 +147,10 @@ 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,
const char *domain,
unsigned char *trust_passwd,
time_t last_change_time)
{
@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
@ -162,7 +162,9 @@ 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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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);
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;
}
/* Standard challenge/response authenticaion */
make_user_info_netlogon_network(&user_info,
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 = check_password(user_info, auth_info, &server_info);
free_auth_info(&auth_info);
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,
if (!make_user_info_netlogon_interactive(&user_info,
nt_username, nt_domain,
nt_workstation, chal.data,
nt_workstation, chal,
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);
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;
}

View File

@ -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);

View File

@ -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) {
/* 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(p, cryptkey.data, 8);
data_blob_free(&cryptkey);
get_challange(p);
}
SSVALS(outbuf,smb_vwv16+1,8);
p += 8;

View File

@ -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;

View File

@ -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();

View File

@ -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;
}
nt_status = check_password(user_info, auth_info, server_info);
free_auth_info(&auth_info);
if (!make_user_info_guest(&user_info)) {
auth_context->free(&auth_context);
return NT_STATUS_NO_MEMORY;
}
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);
}
nt_status = check_password(user_info, negprot_global_auth_info, &server_info);
lm_resp, nt_resp)) {
nt_status = NT_STATUS_NO_MEMORY;
} 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);
nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
user_info,
&server_info);
}
chal = auth_get_challenge(plaintext_auth_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))) {
chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
if (!make_user_info_for_reply(&user_info,
user, domain, chal.data,
user, domain, chal,
plaintext_password)) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
nt_status = NT_STATUS_NO_MEMORY;
}
nt_status = check_password(user_info, plaintext_auth_info, &server_info);
if (NT_STATUS_IS_OK(nt_status)) {
nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
user_info,
&server_info);
data_blob_free(&chal);
free_auth_info(&plaintext_auth_info);
plaintext_auth_context->free(&plaintext_auth_context);
}
}
}
free_user_info(&user_info);