diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-05-15 07:51:38 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:53:46 -0500 |
commit | 064e7447bebd715c8351d9a0ee31f648990f2336 (patch) | |
tree | 156925cd7c8d4616f0eca3a743b7323b3b0b23b7 /source4 | |
parent | 31b9470996632d717c3c74482308e200906fdb8f (diff) | |
download | samba-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.c | 47 | ||||
-rw-r--r-- | source4/lib/genrand.c | 11 | ||||
-rw-r--r-- | source4/libcli/auth/credentials.c | 46 | ||||
-rw-r--r-- | source4/libcli/auth/credentials.h | 9 | ||||
-rw-r--r-- | source4/param/loadparm.c | 2 | ||||
-rw-r--r-- | source4/provision.ldif | 44 | ||||
-rw-r--r-- | source4/rpc_server/config.m4 | 3 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 467 | ||||
-rw-r--r-- | source4/rpc_server/samr/dcesrv_samr.c | 77 | ||||
-rw-r--r-- | source4/rpc_server/samr/samdb.c | 202 | ||||
-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.c | 41 | ||||
-rw-r--r-- | source4/torture/rpc/samr.c | 4 |
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, |