r743: Start on a NETLOGON server in Samba4.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 15 May 2004 07:51:38 +0000 (07:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:53:46 +0000 (12:53 -0500)
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)

13 files changed:
source4/auth/auth_sam.c
source4/lib/genrand.c
source4/libcli/auth/credentials.c
source4/libcli/auth/credentials.h
source4/param/loadparm.c
source4/provision.ldif
source4/rpc_server/config.m4
source4/rpc_server/netlogon/dcerpc_netlogon.c [new file with mode: 0644]
source4/rpc_server/samr/dcesrv_samr.c
source4/rpc_server/samr/samdb.c
source4/rpc_server/samr/samr_utils.c [moved from source4/libads/ads_utils.c with 59% similarity]
source4/torture/rpc/netlogon.c
source4/torture/rpc/samr.c

index d7e4e9782681debf917d54694c517ef0975be195..f57afba42563a63537092faed29054f616add4e8 100644 (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, 
index f891ac883a6d896c0c54ac2324bd495b6b0b8856..fdd4bb14fc52a2ff87e953f329405aa480c78843 100644 (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;
 }
index 638bff7e8ba7c79c726e5dfd3cffffd79c4c80df..7d56f26b11a85f0e20b0c939f0459f2d862f2bd4 100644 (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;
+}
+
index 7a7a34ced2cd41dd27e9a9f800941ff9f812dbc0..a7e81d43af139ab4afe0a93111c26823c69b91fd 100644 (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
+
index d36bd83e66230c14d54355d526b846cb75fbc203..3cd6b0b9ef285d20524b11255ea8b52e63064e34 100644 (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);
 
index 7ef007807d96ece70bd5a5a40fd653ff586872a5..35027fe7f8e2d0fc5f120d999245a04e92f78277 100644 (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
index 8c5f8baafc96367e151d096d33b28872abee6fa9..20b8e5e2b1fee7f4d317ecba41589d873c232cae 100644 (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
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
new file mode 100644 (file)
index 0000000..0c78ed1
--- /dev/null
@@ -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"
index d5a028ce096bca3ba955083232bcb98463d1b897..847b30e71c59d8ef2cb1224228f9a695d31dff03 100644 (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 */);
 }
 
 /* 
index 2fa17af8ea5b61fcacf6d3f990c57a4b2c2b1f77..2489dae6848aa181ad63576cea859debee042506 100644 (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,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)
similarity index 59%
rename from source4/libads/ads_utils.c
rename to source4/rpc_server/samr/samr_utils.c
index 1aad0bed547ed553ebc2541eae76e00c344e9ecc..247b2d47f453a1978ffe26b3bdc260ac82ab31c7 100644 (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
 /* 
 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:
index 0bdb63121c66cde5a3be1741f2c5a22ac59d477b..4ab88f08e1adf860b6d1054939ccafef090ddf29 100644 (file)
 
 #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;
 }
 
index 4e11cd3995147a0866032f1b56d24b7ae13793ee..14c124af788bf7ff928090efe54a3655853a36e5 100644 (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,