summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-05-15 07:51:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:53:46 -0500
commit064e7447bebd715c8351d9a0ee31f648990f2336 (patch)
tree156925cd7c8d4616f0eca3a743b7323b3b0b23b7 /source4
parent31b9470996632d717c3c74482308e200906fdb8f (diff)
downloadsamba-064e7447bebd715c8351d9a0ee31f648990f2336.tar.gz
samba-064e7447bebd715c8351d9a0ee31f648990f2336.tar.bz2
samba-064e7447bebd715c8351d9a0ee31f648990f2336.zip
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 94624e519b66def97758b8a48a01ffe9029176f0)
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/auth_sam.c47
-rw-r--r--source4/lib/genrand.c11
-rw-r--r--source4/libcli/auth/credentials.c46
-rw-r--r--source4/libcli/auth/credentials.h9
-rw-r--r--source4/param/loadparm.c2
-rw-r--r--source4/provision.ldif44
-rw-r--r--source4/rpc_server/config.m43
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c467
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c77
-rw-r--r--source4/rpc_server/samr/samdb.c202
-rw-r--r--source4/rpc_server/samr/samr_utils.c (renamed from source4/libads/ads_utils.c)81
-rw-r--r--source4/torture/rpc/netlogon.c41
-rw-r--r--source4/torture/rpc/samr.c4
13 files changed, 816 insertions, 218 deletions
diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c
index d7e4e97826..f57afba425 100644
--- a/source4/auth/auth_sam.c
+++ b/source4/auth/auth_sam.c
@@ -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,
diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c
index f891ac883a..fdd4bb14fc 100644
--- a/source4/lib/genrand.c
+++ b/source4/lib/genrand.c
@@ -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;
}
diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c
index 638bff7e8b..7d56f26b11 100644
--- a/source4/libcli/auth/credentials.c
+++ b/source4/libcli/auth/credentials.c
@@ -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;
+}
+
diff --git a/source4/libcli/auth/credentials.h b/source4/libcli/auth/credentials.h
index 7a7a34ced2..a7e81d43af 100644
--- a/source4/libcli/auth/credentials.h
+++ b/source4/libcli/auth/credentials.h
@@ -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
+
diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
index d36bd83e66..3cd6b0b9ef 100644
--- a/source4/param/loadparm.c
+++ b/source4/param/loadparm.c
@@ -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);
diff --git a/source4/provision.ldif b/source4/provision.ldif
index 7ef007807d..35027fe7f8 100644
--- a/source4/provision.ldif
+++ b/source4/provision.ldif
@@ -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
diff --git a/source4/rpc_server/config.m4 b/source4/rpc_server/config.m4
index 8c5f8baafc..20b8e5e2b1 100644
--- a/source4/rpc_server/config.m4
+++ b/source4/rpc_server/config.m4
@@ -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
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
new file mode 100644
index 0000000000..0c78ed1864
--- /dev/null
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -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"
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index d5a028ce09..847b30e71c 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -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 */);
}
/*
diff --git a/source4/rpc_server/samr/samdb.c b/source4/rpc_server/samr/samdb.c
index 2fa17af8ea..2489dae684 100644
--- a/source4/rpc_server/samr/samdb.c
+++ b/source4/rpc_server/samr/samdb.c
@@ -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,71 +897,73 @@ 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;
- }
-
- /* can this user change password? */
- if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
-
- /* check the various password restrictions */
- if (minPwdLength > str_charnum(new_pass)) {
- 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) {
+ if (user_change) {
+ /* are all password changes disallowed? */
+ if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
- if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
+
+ /* can this user change password? */
+ if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
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) {
+
+ /* yes, this is a minus. The ages are in negative 100nsec units! */
+ if (pwdLastSet - minPwdAge > now_double) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
- if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
- 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;
+ }
}
- 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;
+ }
}
}
- for (i=0;lm_hash_ok && i<lmPwdHistory_len;i++) {
- if (memcmp(lmNewHash.hash, lmPwdHistory[i].hash, 16) == 0) {
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
+ /* check the various password restrictions */
+ if (minPwdLength > str_charnum(new_pass)) {
+ 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;
- }
+
+ /* possibly check password complexity */
+ if (pwdProperties & DOMAIN_PASSWORD_COMPLEX &&
+ !samdb_password_complexity_ok(new_pass)) {
+ return NT_STATUS_PASSWORD_RESTRICTION;
}
#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0)
diff --git a/source4/libads/ads_utils.c b/source4/rpc_server/samr/samr_utils.c
index 1aad0bed54..247b2d47f4 100644
--- a/source4/libads/ads_utils.c
+++ b/source4/rpc_server/samr/samr_utils.c
@@ -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:
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 0bdb63121c..4ab88f08e1 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -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;
}
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 4e11cd3995..14c124af78 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -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,