1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

r743: Start on a NETLOGON server in Samba4.

Currently this only authentiates the machine, not real users.

As a consequence of running the Samba4 NETLOGON test against Samba4, I
found a number of issues in the SAMR server, which I have addressed.
There are more templates in the provison.ldif for this reason.

I also added some debug to our credentials code, and fixed some bugs
in the auth_sam module.

The static buffer in generate_random_string() bit me badly, so I
removed it in favor of a talloc based system.

Andrew Bartlett
(This used to be commit 94624e519b)
This commit is contained in:
Andrew Bartlett 2004-05-15 07:51:38 +00:00 committed by Gerald (Jerry) Carter
parent 31b9470996
commit 064e7447be
13 changed files with 819 additions and 221 deletions

View File

@ -187,16 +187,12 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
NTSTATUS nt_status;
DATA_BLOB user_sess_key = data_blob(NULL, 0);
DATA_BLOB lm_sess_key = data_blob(NULL, 0);
const uint8 *lm_pwd, *nt_pwd;
const char *unicodePwd;
struct samr_Hash lmPwdHash_u, ntPwdHash_u;
struct samr_Hash *lmPwdHash, *ntPwdHash;
uint_t num_lm, num_nt;
uint8 *lm_pwd, *nt_pwd;
struct dom_sid *domain_sid;
const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
"sAMAcctFlags",
"userAccountControl",
"pwdLastSet",
"accountExpires",
"objectSid",
@ -204,7 +200,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
NULL,
};
const char *domain_attrs[] = {NULL};
const char *domain_attrs[] = {"name"};
if (!user_info || !auth_context) {
return NT_STATUS_UNSUCCESSFUL;
@ -270,40 +266,9 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
return NT_STATUS_ACCOUNT_LOCKED_OUT;
}
unicodePwd = samdb_result_string(msgs[0], "unicodePwd", NULL);
if (unicodePwd) {
BOOL lm_hash_ok;
/* compute the new nt and lm hashes */
lm_hash_ok = E_deshash(unicodePwd, lmPwdHash_u.hash);
E_md4hash(unicodePwd, ntPwdHash_u.hash);
if (lm_hash_ok) {
lm_pwd = lmPwdHash_u.hash;
} else {
lm_pwd = NULL;
}
nt_pwd = ntPwdHash_u.hash;
} else {
num_lm = samdb_result_hashes(mem_ctx, msgs[0], "lmPwdHash", &lmPwdHash);
if (num_lm == 0) {
lm_pwd = NULL;
} else if (num_lm > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
lm_pwd = lmPwdHash[0].hash;
}
num_nt = samdb_result_hashes(mem_ctx, msgs[0], "ntPwdHash", &ntPwdHash);
if (num_nt == 0) {
nt_pwd = NULL;
} else if (num_nt > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
nt_pwd = ntPwdHash[0].hash;
}
if (!NT_STATUS_IS_OK(nt_status = samdb_result_passwords(mem_ctx, msgs[0],
&lm_pwd, &nt_pwd))) {
return nt_status;
}
nt_status = sam_password_ok(auth_context, mem_ctx,

View File

@ -269,15 +269,14 @@ BOOL check_password_quality(const char *s)
static char c_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,";
char *generate_random_str(size_t len)
char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len)
{
static unsigned char retstr[256];
size_t i;
memset(retstr, '\0', sizeof(retstr));
char *retstr = talloc(mem_ctx, len + 1);
if (len > sizeof(retstr)-1)
len = sizeof(retstr) -1;
if (!retstr)
return NULL;
again:
generate_random_buffer(retstr, len, False);
@ -292,5 +291,5 @@ again:
goto again;
}
return (char *)retstr;
return retstr;
}

View File

@ -4,6 +4,7 @@
code to manipulate domain credentials
Copyright (C) Andrew Tridgell 1997-2003
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
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
@ -36,6 +37,10 @@ static void creds_init(struct creds_CredentialState *creds,
uint32 sum[2];
uint8 sum2[8];
dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data));
dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data));
dump_data_pw("Machine Pass", machine_password, 16);
sum[0] = IVAL(client_challenge->data, 0) + IVAL(server_challenge->data, 0);
sum[1] = IVAL(client_challenge->data, 4) + IVAL(server_challenge->data, 4);
@ -44,8 +49,6 @@ static void creds_init(struct creds_CredentialState *creds,
cred_hash1(creds->session_key, sum2, machine_password);
creds->sequence = time(NULL);
SIVAL(time_cred.data, 0, IVAL(client_challenge->data, 0));
SIVAL(time_cred.data, 4, IVAL(client_challenge->data, 4));
cred_hash2(creds->client.data, time_cred.data, creds->session_key, 1);
@ -136,6 +139,7 @@ void creds_client_init(struct creds_CredentialState *creds,
struct netr_Credential *initial_credential)
{
creds_init(creds, client_challenge, server_challenge, machine_password);
creds->sequence = time(NULL);
*initial_credential = creds->client;
}
@ -146,7 +150,8 @@ void creds_client_init(struct creds_CredentialState *creds,
BOOL creds_client_check(struct creds_CredentialState *creds,
const struct netr_Credential *received_credentials)
{
if (memcmp(received_credentials->data, creds->server.data, 8) != 0) {
if (!received_credentials ||
memcmp(received_credentials->data, creds->server.data, 8) != 0) {
DEBUG(2,("credentials check failed\n"));
return False;
}
@ -167,3 +172,38 @@ void creds_client_authenticator(struct creds_CredentialState *creds,
}
/*****************************************************************
The above functions are common to the client and server interface
next comes the server specific functions
******************************************************************/
/*
initialise the credentials chain and return the first server
credentials
*/
void creds_server_init(struct creds_CredentialState *creds,
const struct netr_Credential *client_challenge,
const struct netr_Credential *server_challenge,
const uint8 machine_password[16],
struct netr_Credential *initial_credential)
{
creds_init(creds, client_challenge, server_challenge, machine_password);
*initial_credential = creds->server;
}
/*
check that a credentials reply from a server is correct
*/
BOOL creds_server_check(const struct creds_CredentialState *creds,
const struct netr_Credential *received_credentials)
{
if (memcmp(received_credentials->data, creds->client.data, 8) != 0) {
DEBUG(2,("credentials check failed\n"));
dump_data_pw("client creds", creds->client.data, 8);
dump_data_pw("calc creds", received_credentials->data, 8);
return False;
}
return True;
}

View File

@ -27,3 +27,12 @@ struct creds_CredentialState {
struct netr_Credential client;
struct netr_Credential server;
};
/* for the timebeing, use the same neg flags as Samba3. */
/* The 7 here seems to be required to get Win2k not to downgrade us
to NT4. Actually, anything other than 1ff would seem to do... */
#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff
#define NETLOGON_NEG_SCHANNEL 0x40000000

View File

@ -932,7 +932,7 @@ static void init_globals(void)
string_set(&sDefault.fstype, FSTYPE_STRING);
string_set(&sDefault.ntvfs_handler, "default");
Globals.dcerpc_ep_servers = str_list_make("epmapper srvsvc wkssvc rpcecho samr", NULL);
Globals.dcerpc_ep_servers = str_list_make("epmapper srvsvc wkssvc rpcecho samr netlogon", NULL);
Globals.AuthMethods = str_list_make("guest sam_ignoredomain", NULL);

View File

@ -763,7 +763,7 @@ objectClass: userTemplate
cn: TemplateUser
name: TemplateUser
instanceType: 4
userAccountControl: 0x222
userAccountControl: 0x202
badPwdCount: 0
codePage: 0
countryCode: 0
@ -776,6 +776,48 @@ accountExpires: -1
logonCount: 0
sAMAccountType: 0x30000000
dn: CN=TemplateMemberServer,CN=Templates,${BASEDN}
objectClass: top
objectClass: computer
objectClass: Template
objectClass: userTemplate
cn: TemplateMemberServer
name: TemplateMemberServer
instanceType: 4
userAccountControl: 0x1002
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 0
primaryGroupID: 513
accountExpires: -1
logonCount: 0
sAMAccountType: 0x30000001
dn: CN=TemplateDomainController,CN=Templates,${BASEDN}
objectClass: top
objectClass: computer
objectClass: Template
objectClass: userTemplate
cn: TemplateDomainController
name: TemplateDomainController
instanceType: 4
userAccountControl: 0x2002
badPwdCount: 0
codePage: 0
countryCode: 0
badPasswordTime: 0
lastLogoff: 0
lastLogon: 0
pwdLastSet: 0
primaryGroupID: 513
accountExpires: -1
logonCount: 0
sAMAccountType: 0x30000001
dn: CN=TemplateGroup,CN=Templates,${BASEDN}
objectClass: top
objectClass: Template

View File

@ -4,7 +4,7 @@ SMB_SUBSYSTEM(DCERPC_COMMON,[],
[rpc_server/common/server_info.o
rpc_server/common/share_info.o])
SMB_SUBSYSTEM(SAMDB,[rpc_server/samr/samdb.o],[],[],[LIBLDB])
SMB_SUBSYSTEM(SAMDB,[rpc_server/samr/samdb.o rpc_server/samr/samr_utils.o],[],[],[LIBLDB])
SMB_MODULE(dcerpc_rpcecho,DCERPC,STATIC,[rpc_server/echo/rpc_echo.o])
SMB_MODULE(dcerpc_epmapper,DCERPC,STATIC,[rpc_server/epmapper/rpc_epmapper.o])
@ -13,6 +13,7 @@ SMB_MODULE(dcerpc_srvsvc,DCERPC,STATIC,[rpc_server/srvsvc/dcesrv_srvsvc.o],[],[]
SMB_MODULE(dcerpc_wkssvc,DCERPC,STATIC,[rpc_server/wkssvc/dcesrv_wkssvc.o],[],[],[DCERPC_COMMON])
SMB_MODULE(dcerpc_samr,DCERPC,STATIC,[rpc_server/samr/dcesrv_samr.o],[],[],[SAMDB DCERPC_COMMON])
SMB_MODULE(dcerpc_winreg,DCERPC,STATIC,[rpc_server/winreg/rpc_winreg.o],[],[],[REGISTRY])
SMB_MODULE(dcerpc_netlogon,DCERPC,STATIC,[rpc_server/netlogon/dcerpc_netlogon.o],[],[],[SAMDB DCERPC_COMMON])
SMB_SUBSYSTEM(DCERPC,rpc_server/dcerpc_server.o,
[rpc_server/dcerpc_tcp.o

View File

@ -0,0 +1,467 @@
/*
Unix SMB/CIFS implementation.
endpoint server for the netlogon pipe
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
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"
#include "rpc_server/common/common.h"
struct server_pipe_state {
TALLOC_CTX *mem_ctx;
struct netr_Credential client_challenge;
struct netr_Credential server_challenge;
BOOL authenticated;
char *account_name;
char *computer_name; /* for logging only */
uint32 acct_flags;
uint16 sec_chan_type;
struct creds_CredentialState *creds;
};
static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di)
{
dce_call->conn->private = NULL;
return NT_STATUS_OK;
}
/* this function is called when the client disconnects the endpoint */
static void netlogon_unbind(struct dcesrv_connection *conn, const struct dcesrv_interface *di)
{
struct server_pipe_state *pipe_state = conn->private;
if (pipe_state)
talloc_destroy(pipe_state->mem_ctx);
conn->private = NULL;
}
#define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
#define DCESRV_INTERFACE_NETLOGON_UNBIND netlogon_unbind
/*
netr_ServerReqChallenge
NTSTATUS netr_ServerReqChallenge(
[in] unistr *server_name,
[in] unistr computer_name,
[in][out] netr_Credential credentials
);
*/
static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerReqChallenge *r)
{
struct server_pipe_state *pipe_state = dce_call->conn->private;
TALLOC_CTX *pipe_mem_ctx;
ZERO_STRUCT(r->out.credentials);
/* destroyed on pipe shutdown */
if (pipe_state) {
talloc_destroy(pipe_state->mem_ctx);
dce_call->conn->private = NULL;
}
pipe_mem_ctx = talloc_init("internal netlogon pipe state for %s",
r->in.computer_name);
if (!pipe_mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
pipe_state = talloc_p(pipe_mem_ctx, struct server_pipe_state);
if (!pipe_state) {
talloc_destroy(pipe_mem_ctx);
return NT_STATUS_NO_MEMORY;
}
pipe_state->mem_ctx = pipe_mem_ctx;
pipe_state->authenticated = False;
pipe_state->creds = NULL;
pipe_state->account_name = NULL;
pipe_state->computer_name = NULL;
pipe_state->client_challenge = r->in.credentials;
generate_random_buffer(pipe_state->server_challenge.data,
sizeof(pipe_state->server_challenge.data),
False);
r->out.credentials = pipe_state->server_challenge;
dce_call->conn->private = pipe_state;
return NT_STATUS_OK;
}
/*
netr_ServerAuthenticate
secure channel types:
const int SEC_CHAN_WKSTA = 2;
const int SEC_CHAN_DOMAIN = 4;
const int SEC_CHAN_BDC = 6;
NTSTATUS netr_ServerAuthenticate(
[in] unistr *server_name,
[in] unistr username,
[in] uint16 secure_channel_type,
[in] unistr computer_name,
[in,out] netr_Credential credentials
);
*/
static NTSTATUS netr_ServerAuthenticateInternals(struct server_pipe_state *pipe_state,
TALLOC_CTX *mem_ctx,
const char *account_name,
const char *computer_name,
uint16 secure_channel_type,
uint32 in_flags,
const struct netr_Credential *client_credentials,
struct netr_Credential *server_credentials,
uint32 *out_flags)
{
void *sam_ctx;
uint8 *mach_pwd;
uint16 acct_flags;
int num_records;
struct ldb_message **msgs;
NTSTATUS nt_status;
const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
"userAccountControl", NULL
};
ZERO_STRUCTP(server_credentials);
if (out_flags) {
*out_flags = 0;
}
if (!pipe_state) {
DEBUG(1, ("No challange requested by client, cannot authenticate\n"));
return NT_STATUS_ACCESS_DENIED;
}
sam_ctx = samdb_connect();
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
/* pull the user attributes */
num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
"(&(sAMAccountName=%s)(objectclass=user))",
account_name);
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in passdb file.\n",
account_name));
samdb_close(sam_ctx);
return NT_STATUS_NO_SUCH_USER;
}
if (num_records > 1) {
DEBUG(1,("Found %d records matching user [%s]\n", num_records, account_name));
samdb_close(sam_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
acct_flags = samdb_result_acct_flags(msgs[0],
"userAccountControl");
if (acct_flags & ACB_DISABLED) {
DEBUG(1, ("Account [%s] is disabled\n", account_name));
return NT_STATUS_ACCESS_DENIED;
}
if (secure_channel_type == SEC_CHAN_WKSTA) {
if (!(acct_flags & ACB_WSTRUST)) {
DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", acct_flags));
return NT_STATUS_ACCESS_DENIED;
}
} else if (secure_channel_type == SEC_CHAN_DOMAIN) {
if (!(acct_flags & ACB_DOMTRUST)) {
DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", acct_flags));
return NT_STATUS_ACCESS_DENIED;
}
} else if (secure_channel_type == SEC_CHAN_BDC) {
if (!(acct_flags & ACB_SVRTRUST)) {
DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", acct_flags));
return NT_STATUS_ACCESS_DENIED;
}
} else {
DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", secure_channel_type));
return NT_STATUS_ACCESS_DENIED;
}
pipe_state->acct_flags = acct_flags;
pipe_state->sec_chan_type = secure_channel_type;
if (!NT_STATUS_IS_OK(nt_status = samdb_result_passwords(mem_ctx, msgs[0],
NULL, &mach_pwd))) {
samdb_close(sam_ctx);
return NT_STATUS_ACCESS_DENIED;
}
samdb_close(sam_ctx);
if (!pipe_state->creds) {
pipe_state->creds = talloc_p(mem_ctx, struct creds_CredentialState);
if (!pipe_state->creds) {
return NT_STATUS_NO_MEMORY;
}
}
creds_server_init(pipe_state->creds, &pipe_state->client_challenge,
&pipe_state->server_challenge, mach_pwd,
server_credentials);
if (!creds_server_check(pipe_state->creds, client_credentials)) {
return NT_STATUS_ACCESS_DENIED;
}
pipe_state->authenticated = True;
if (pipe_state->account_name) {
/* We don't want a memory leak on this long-lived talloc context */
talloc_free(pipe_state->mem_ctx, pipe_state->account_name);
}
pipe_state->account_name = talloc_strdup(pipe_state->mem_ctx, account_name);
if (pipe_state->computer_name) {
/* We don't want a memory leak on this long-lived talloc context */
talloc_free(pipe_state->mem_ctx, pipe_state->account_name);
}
pipe_state->computer_name = talloc_strdup(pipe_state->mem_ctx, computer_name);
if (out_flags) {
*out_flags = NETLOGON_NEG_AUTH2_FLAGS;
}
return NT_STATUS_OK;
}
static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerAuthenticate *r)
{
struct server_pipe_state *pipe_state = dce_call->conn->private;
return netr_ServerAuthenticateInternals(pipe_state,
mem_ctx,
r->in.username,
r->in.computer_name,
r->in.secure_channel_type,
0,
&r->in.credentials,
&r->out.credentials,
NULL);
}
static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerAuthenticate2 *r)
{
struct server_pipe_state *pipe_state = dce_call->conn->private;
return netr_ServerAuthenticateInternals(pipe_state,
mem_ctx,
r->in.username,
r->in.computer_name,
r->in.secure_channel_type,
*r->in.negotiate_flags,
&r->in.credentials,
&r->out.credentials,
r->out.negotiate_flags);
}
/*
netr_LogonUasLogon
*/
static WERROR netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonUasLogon *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_LogonUasLogoff
*/
static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonUasLogoff *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_LogonSamLogon
*/
static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonSamLogon *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_LogonSamLogoff
*/
static NTSTATUS netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonSamLogoff *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_ServerPasswordSet
*/
static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerPasswordSet *r)
{
}
/*
netr_DatabaseDeltas
*/
static NTSTATUS netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_DatabaseDeltas *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_DatabaseSync
*/
static NTSTATUS netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_DatabaseSync *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_AccountDeltas
*/
static NTSTATUS netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_AccountDeltas *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_AccountSync
*/
static NTSTATUS netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_AccountSync *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_GetDcName
*/
static NTSTATUS netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_GetDcName *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_LogonControl
*/
static WERROR netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonControl *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_GetAnyDCName
*/
static WERROR netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_GetAnyDCName *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_LogonControl2
*/
static WERROR netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonControl2 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_DatabaseSync2
*/
static NTSTATUS netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_DatabaseSync2 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_DatabaseRedo
*/
static NTSTATUS netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_DatabaseRedo *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
netr_LogonControl2Ex
*/
static WERROR netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonControl2Ex *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/* include the generated boilerplate */
#include "librpc/gen_ndr/ndr_netlogon_s.c"

View File

@ -603,6 +603,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
struct dcesrv_handle *u_handle;
int ret;
NTSTATUS status;
const char *container;
ZERO_STRUCTP(r->out.acct_handle);
*r->out.access_granted = 0;
@ -628,14 +629,55 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
ZERO_STRUCT(msg);
/* pull in all the template attributes */
ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
"(&(name=TemplateUser)(objectclass=userTemplate))");
if (ret != 0) {
DEBUG(1,("Failed to load TemplateUser from samdb\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
/* This must be one of these values *only* */
if (r->in.acct_flags == ACB_NORMAL) {
/* pull in all the template attributes */
ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
"(&(name=TemplateUser)(objectclass=userTemplate))");
if (ret != 0) {
DEBUG(1,("Failed to load TemplateUser from samdb\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
container = "Users";
} else if (r->in.acct_flags == ACB_WSTRUST) {
/* pull in all the template attributes */
ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
"(&(name=TemplateMemberServer)(objectclass=userTemplate))");
if (ret != 0) {
DEBUG(1,("Failed to load TemplateMemberServer from samdb\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
container = "Computers";
} else if (r->in.acct_flags == ACB_SVRTRUST) {
/* pull in all the template attributes */
ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
"(&(name=TemplateDomainController)(objectclass=userTemplate))");
if (ret != 0) {
DEBUG(1,("Failed to load TemplateDomainController from samdb\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
container = "DomainControllers";
} else if (r->in.acct_flags == ACB_DOMTRUST) {
/* pull in all the template attributes */
ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
"(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
if (ret != 0) {
DEBUG(1,("Failed to load TemplateTrustingDomain from samdb\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
container = "ForeignDomains"; /* FIXME: Is this correct?*/
} else {
return NT_STATUS_INVALID_PARAMETER;
}
/* allocate a rid */
status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
d_state->domain_dn, "nextRid", &rid);
@ -650,7 +692,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
}
/* add core elements to the ldb_message for the user */
msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", username, d_state->domain_dn);
msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", username, container, d_state->domain_dn);
if (!msg.dn) {
return NT_STATUS_NO_MEMORY;
}
@ -723,7 +765,7 @@ static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *
/* a simple wrapper around samr_CreateUser2 works nicely */
r2.in.handle = r->in.handle;
r2.in.username = r->in.username;
r2.in.acct_flags = 1234;
r2.in.acct_flags = ACB_NORMAL;
r2.in.access_mask = r->in.access_mask;
r2.out.acct_handle = r->out.acct_handle;
r2.out.access_granted = &access_granted;
@ -914,18 +956,9 @@ static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX
continue;
}
switch (atype & 0xF0000000) {
case ATYPE_ACCOUNT:
rtype = SID_NAME_USER;
break;
case ATYPE_GLOBAL_GROUP:
rtype = SID_NAME_DOM_GRP;
break;
case ATYPE_LOCAL_GROUP:
rtype = SID_NAME_ALIAS;
break;
default:
DEBUG(1,("Unknown sAMAccountType 0x%08x\n", atype));
rtype = samdb_atype_map(atype);
if (rtype == SID_NAME_UNKNOWN) {
status = STATUS_SOME_UNMAPPED;
continue;
}
@ -1654,7 +1687,7 @@ static NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
so the domain password policy can be used */
return samdb_set_password(a_state->sam_ctx, mem_ctx,
a_state->account_dn, a_state->domain_state->domain_dn,
msg, new_pass);
msg, new_pass, False /* This is a password set, not change */);
}
/*

View File

@ -416,6 +416,68 @@ uint_t samdb_result_hashes(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
return count;
}
NTSTATUS samdb_result_passwords(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
uint8 **lm_pwd, uint8 **nt_pwd)
{
const char *unicodePwd = samdb_result_string(msg, "unicodePwd", NULL);
struct samr_Hash *lmPwdHash, *ntPwdHash;
if (unicodePwd) {
if (nt_pwd) {
ntPwdHash = talloc_p(mem_ctx, struct samr_Hash);
if (!ntPwdHash) {
return NT_STATUS_NO_MEMORY;
}
E_md4hash(unicodePwd, ntPwdHash->hash);
*nt_pwd = ntPwdHash->hash;
}
if (lm_pwd) {
BOOL lm_hash_ok;
lmPwdHash = talloc_p(mem_ctx, struct samr_Hash);
if (!lmPwdHash) {
return NT_STATUS_NO_MEMORY;
}
/* compute the new nt and lm hashes */
lm_hash_ok = E_deshash(unicodePwd, lmPwdHash->hash);
if (lm_hash_ok) {
*lm_pwd = lmPwdHash->hash;
} else {
*lm_pwd = NULL;
}
}
} else {
if (nt_pwd) {
int num_nt;
num_nt = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
if (num_nt == 0) {
nt_pwd = NULL;
} else if (num_nt > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
*nt_pwd = ntPwdHash[0].hash;
}
}
if (lm_pwd) {
int num_lm;
num_lm = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
if (num_lm == 0) {
*lm_pwd = NULL;
} else if (num_lm > 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
} else {
*lm_pwd = lmPwdHash[0].hash;
}
}
}
return NT_STATUS_OK;
}
/*
pull a samr_LogonHours structutre from a result set.
@ -438,36 +500,13 @@ struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_
return hours;
}
/* mapping between ADS userAccountControl and SAMR acct_flags */
static const struct {
uint32 uf, acb;
} acct_flags_map[] = {
{ UF_ACCOUNTDISABLE, ACB_DISABLED },
{ UF_HOMEDIR_REQUIRED, ACB_HOMDIRREQ },
{ UF_PASSWD_NOTREQD, ACB_PWNOTREQ },
{ UF_TEMP_DUPLICATE_ACCOUNT, ACB_TEMPDUP },
{ UF_NORMAL_ACCOUNT, ACB_NORMAL },
{ UF_MNS_LOGON_ACCOUNT, ACB_MNS },
{ UF_INTERDOMAIN_TRUST_ACCOUNT, ACB_DOMTRUST },
{ UF_WORKSTATION_TRUST_ACCOUNT, ACB_WSTRUST },
{ UF_SERVER_TRUST_ACCOUNT, ACB_SVRTRUST },
{ UF_DONT_EXPIRE_PASSWD, ACB_PWNOEXP },
{ UF_LOCKOUT, ACB_AUTOLOCK }
};
/*
pull a set of account_flags from a result set.
*/
uint32 samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
uint16 samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
{
uint_t userAccountControl = ldb_msg_find_uint(msg, attr, 0);
uint32 i, ret = 0;
for (i=0;i<ARRAY_SIZE(acct_flags_map);i++) {
if (acct_flags_map[i].uf & userAccountControl) {
ret |= acct_flags_map[i].acb;
}
}
return ret;
return samdb_uf2acb(userAccountControl);
}
/*
@ -707,13 +746,7 @@ int samdb_msg_add_hashes(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg
int samdb_msg_add_acct_flags(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
const char *attr_name, uint32 v)
{
uint_t i, flags = 0;
for (i=0;i<ARRAY_SIZE(acct_flags_map);i++) {
if (acct_flags_map[i].acb & v) {
flags |= acct_flags_map[i].uf;
}
}
return samdb_msg_add_uint(ctx, mem_ctx, msg, attr_name, flags);
return samdb_msg_add_uint(ctx, mem_ctx, msg, attr_name, samdb_acb2uf(v));
}
/*
@ -808,7 +841,8 @@ static BOOL samdb_password_complexity_ok(const char *pass)
*/
NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
const char *user_dn, const char *domain_dn,
struct ldb_message *mod, const char *new_pass)
struct ldb_message *mod, const char *new_pass,
BOOL user_change)
{
const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory",
"ntPwdHistory", "unicodePwd",
@ -863,14 +897,62 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0);
minPwdAge = samdb_result_double(res[0], "minPwdAge", 0);
/* are all password changes disallowed? */
if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* compute the new nt and lm hashes */
lm_hash_ok = E_deshash(new_pass, lmNewHash.hash);
E_md4hash(new_pass, ntNewHash.hash);
/* can this user change password? */
if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
return NT_STATUS_PASSWORD_RESTRICTION;
if (user_change) {
/* are all password changes disallowed? */
if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* can this user change password? */
if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* yes, this is a minus. The ages are in negative 100nsec units! */
if (pwdLastSet - minPwdAge > now_double) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* check the immediately past password */
if (pwdHistoryLength > 0) {
if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
/* check the password history */
lmPwdHistory_len = MIN(lmPwdHistory_len, pwdHistoryLength);
ntPwdHistory_len = MIN(ntPwdHistory_len, pwdHistoryLength);
if (pwdHistoryLength > 0) {
if (unicodePwd && strcmp(unicodePwd, new_pass) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
for (i=0;lm_hash_ok && i<lmPwdHistory_len;i++) {
if (memcmp(lmNewHash.hash, lmPwdHistory[i].hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
for (i=0;i<ntPwdHistory_len;i++) {
if (memcmp(ntNewHash.hash, ntPwdHistory[i].hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
}
/* check the various password restrictions */
@ -878,58 +960,12 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* yes, this is a minus. The ages are in negative 100nsec units! */
if (pwdLastSet - minPwdAge > now_double) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* possibly check password complexity */
if (pwdProperties & DOMAIN_PASSWORD_COMPLEX &&
!samdb_password_complexity_ok(new_pass)) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* compute the new nt and lm hashes */
lm_hash_ok = E_deshash(new_pass, lmNewHash.hash);
E_md4hash(new_pass, ntNewHash.hash);
/* check the immediately past password */
if (pwdHistoryLength > 0) {
if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
/* check the password history */
lmPwdHistory_len = MIN(lmPwdHistory_len, pwdHistoryLength);
ntPwdHistory_len = MIN(ntPwdHistory_len, pwdHistoryLength);
if (pwdHistoryLength > 0) {
if (unicodePwd && strcmp(unicodePwd, new_pass) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
for (i=0;lm_hash_ok && i<lmPwdHistory_len;i++) {
if (memcmp(lmNewHash.hash, lmPwdHistory[i].hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
for (i=0;i<ntPwdHistory_len;i++) {
if (memcmp(ntNewHash.hash, ntPwdHistory[i].hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0)
/* the password is acceptable. Start forming the new fields */

View File

@ -1,9 +1,9 @@
/*
Unix SMB/CIFS implementation.
ads (active directory) utility library
helper mapping functions for the SAMDB server
Copyright (C) Stefan (metze) Metzmacher 2002
Copyright (C) Andrew Tridgell 2001
Copyright (C) Andrew Tridgell 2004
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
@ -25,57 +25,54 @@
/*
translated the ACB_CTRL Flags to UserFlags (userAccountControl)
*/
uint32 ads_acb2uf(uint16 acb)
{
uint32 uf = 0x00000000;
if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE;
if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED;
if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD;
if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT;
if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT;
if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT;
if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT;
if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT;
if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT;
if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD;
if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT;
/* mapping between ADS userAccountControl and SAMR acct_flags */
static const struct {
uint32 uf;
uint16 acb;
} acct_flags_map[] = {
{ UF_ACCOUNTDISABLE, ACB_DISABLED },
{ UF_HOMEDIR_REQUIRED, ACB_HOMDIRREQ },
{ UF_PASSWD_NOTREQD, ACB_PWNOTREQ },
{ UF_TEMP_DUPLICATE_ACCOUNT, ACB_TEMPDUP },
{ UF_NORMAL_ACCOUNT, ACB_NORMAL },
{ UF_MNS_LOGON_ACCOUNT, ACB_MNS },
{ UF_INTERDOMAIN_TRUST_ACCOUNT, ACB_DOMTRUST },
{ UF_WORKSTATION_TRUST_ACCOUNT, ACB_WSTRUST },
{ UF_SERVER_TRUST_ACCOUNT, ACB_SVRTRUST },
{ UF_DONT_EXPIRE_PASSWD, ACB_PWNOEXP },
{ UF_LOCKOUT, ACB_AUTOLOCK }
};
return uf;
uint32 samdb_acb2uf(uint16 acb)
{
uint32 i, ret = 0;
for (i=0;i<ARRAY_SIZE(acct_flags_map);i++) {
if (acct_flags_map[i].acb & acb) {
ret |= acct_flags_map[i].uf;
}
}
return ret;
}
/*
translated the UserFlags (userAccountControl) to ACB_CTRL Flags
*/
uint16 ads_uf2acb(uint32 uf)
uint16 samdb_uf2acb(uint32 uf)
{
uint16 acb = 0x0000;
if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED;
if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ;
if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ;
if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS;
if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP;
if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK;
switch (uf & UF_ACCOUNT_TYPE_MASK)
{
case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break;
case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break;
case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break;
case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break;
case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break;
/*Fix Me: what should we do here? */
default: acb |= ACB_NORMAL;break;
uint32 i;
uint16 ret = 0;
for (i=0;i<ARRAY_SIZE(acct_flags_map);i++) {
if (acct_flags_map[i].uf & uf) {
ret |= acct_flags_map[i].acb;
}
}
return acb;
return ret;
}
/*
get the accountType from the UserFlags
*/
uint32 ads_uf2atype(uint32 uf)
uint32 samdb_uf2atype(uint32 uf)
{
uint32 atype = 0x00000000;
@ -91,7 +88,7 @@ uint32 ads_uf2atype(uint32 uf)
/*
get the accountType from the groupType
*/
uint32 ads_gtype2atype(uint32 gtype)
uint32 samdb_gtype2atype(uint32 gtype)
{
uint32 atype = 0x00000000;
@ -121,7 +118,7 @@ uint32 ads_gtype2atype(uint32 gtype)
}
/* turn a sAMAccountType into a SID_NAME_USE */
enum SID_NAME_USE ads_atype_map(uint32 atype)
enum SID_NAME_USE samdb_atype_map(uint32 atype)
{
switch (atype & 0xF0000000) {
case ATYPE_GLOBAL_GROUP:

View File

@ -27,14 +27,6 @@
#define TEST_MACHINE_NAME "torturetest"
/* for the timebeing, use the same neg flags as Samba3. */
/* The 7 here seems to be required to get Win2k not to downgrade us
to NT4. Actually, anything other than 1ff would seem to do... */
#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff
#define NETLOGON_NEG_SCHANNEL 0x40000000
static struct {
struct dcerpc_pipe *p;
const char *machine_password;
@ -51,6 +43,7 @@ static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
struct samr_CreateUser2 r;
struct samr_OpenDomain o;
struct samr_LookupDomain l;
struct samr_GetUserPwInfo pwp;
struct samr_SetUserInfo s;
union samr_UserInfo u;
struct policy_handle handle;
@ -60,6 +53,7 @@ static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
BOOL ret = True;
DATA_BLOB session_key;
struct samr_Name name;
int policy_min_pw_len = 0;
printf("Connecting to SAMR\n");
@ -128,7 +122,14 @@ again:
return False;
}
join.machine_password = generate_random_str(8);
pwp.in.handle = &join.acct_handle;
status = dcerpc_samr_GetUserPwInfo(join.p, mem_ctx, &pwp);
if (NT_STATUS_IS_OK(status)) {
policy_min_pw_len = pwp.out.info.min_pwd_len;
}
join.machine_password = generate_random_str(mem_ctx, MAX(8, policy_min_pw_len));
printf("Setting machine account password '%s'\n", join.machine_password);
@ -179,6 +180,8 @@ static BOOL leave_domain_bdc(TALLOC_CTX *mem_ctx)
struct samr_DeleteUser d;
NTSTATUS status;
return True;
d.in.handle = &join.acct_handle;
d.out.handle = &join.acct_handle;
@ -432,15 +435,16 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
ZERO_STRUCT(samlogon_state->auth2);
creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
r->out.authenticator = NULL;
status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
if (!NT_STATUS_IS_OK(status)) {
if (error_string) {
*error_string = strdup(nt_errstr(status));
}
}
if (!creds_client_check(&samlogon_state->creds, &r->out.authenticator->cred)) {
if (!r->out.authenticator || !creds_client_check(&samlogon_state->creds, &r->out.authenticator->cred)) {
printf("Credential chaining failed\n");
}
@ -1020,12 +1024,13 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
r.in.secure_channel_type = SEC_CHAN_BDC;
r.in.computer_name = TEST_MACHINE_NAME;
password = generate_random_str(8);
password = generate_random_str(mem_ctx, 8);
E_md4hash(password, r.in.new_password.data);
creds_des_encrypt(&creds, &r.in.new_password);
printf("Testing ServerPasswordSet on machine account\n");
printf("Changing machine account password to '%s'\n", password);
creds_client_authenticator(&creds, &r.in.credential);
@ -1035,21 +1040,23 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
return False;
}
join.machine_password = password;
if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
printf("Credential chaining failed\n");
}
password = generate_random_str(mem_ctx, 8);
E_md4hash(password, r.in.new_password.data);
/* by changing the machine password twice we test the credentials
chaining fully */
printf("Testing a second ServerPasswordSet on machine account\n");
printf("Changing machine account password to '%s'\n", password);
creds_client_authenticator(&creds, &r.in.credential);
status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("ServerPasswordSet - %s\n", nt_errstr(status));
printf("ServerPasswordSet (2) - %s\n", nt_errstr(status));
return False;
}
@ -1057,6 +1064,8 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
printf("Credential chaining failed\n");
}
join.machine_password = password;
return True;
}

View File

@ -330,9 +330,9 @@ static BOOL test_SetUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
static char *samr_rand_pass(TALLOC_CTX *mem_ctx)
{
size_t len = 8 + (random() % 6);
char *s = generate_random_str(len);
char *s = generate_random_str(mem_ctx, len);
printf("Generated password '%s'\n", s);
return talloc_strdup(mem_ctx, s);
return s;
}
static BOOL test_SetUserPass(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,