r1041: - pulled the domain join code out of the netlogon test and made it a separate...
authorAndrew Tridgell <tridge@samba.org>
Sun, 6 Jun 2004 07:14:10 +0000 (07:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:56:33 +0000 (12:56 -0500)
  multiple torture tests to temporarily join a domain

- fixed a session key size problem

- added a schannel test suite

- allow schannel to work with ncacn_ip_tcp
(This used to be commit 36f05e4d575099fcb957b8a55781c38dcd2e1177)

source4/libcli/auth/schannel.c
source4/librpc/rpc/dcerpc.h
source4/librpc/rpc/dcerpc_schannel.c
source4/librpc/rpc/dcerpc_util.c
source4/torture/config.mk
source4/torture/rpc/netlogon.c
source4/torture/rpc/schannel.c [new file with mode: 0644]
source4/torture/rpc/spoolss.c
source4/torture/rpc/testjoin.c [new file with mode: 0644]
source4/torture/torture.c

index 294873feffbd5248b6d7ad7390957ed0f2b7e47a..95e881d32af922e39f904521792395a4f2516891 100644 (file)
@@ -286,7 +286,7 @@ void schannel_end(struct schannel_state **state)
   create an schannel context state
 */
 NTSTATUS schannel_start(struct schannel_state **state,
-                       uint8_t session_key[16],
+                       const uint8_t session_key[16],
                        BOOL initiator)
 {
        TALLOC_CTX *mem_ctx;
index 74bdaf878e68a83956f279c45698af01e639bf85..d81f0ab9650d2ece650c98b4c180a5c33087e2ee 100644 (file)
@@ -71,21 +71,28 @@ struct dcerpc_pipe {
 };
 
 /* dcerpc pipe flags */
-#define DCERPC_DEBUG_PRINT_IN  (1<<0)
-#define DCERPC_DEBUG_PRINT_OUT (1<<1)
+#define DCERPC_DEBUG_PRINT_IN          (1<<0)
+#define DCERPC_DEBUG_PRINT_OUT         (1<<1)
 #define DCERPC_DEBUG_PRINT_BOTH (DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT)
 
-#define DCERPC_DEBUG_VALIDATE_IN  4
-#define DCERPC_DEBUG_VALIDATE_OUT 8
+#define DCERPC_DEBUG_VALIDATE_IN       (1<<2)
+#define DCERPC_DEBUG_VALIDATE_OUT      (1<<3)
 #define DCERPC_DEBUG_VALIDATE_BOTH (DCERPC_DEBUG_VALIDATE_IN | DCERPC_DEBUG_VALIDATE_OUT)
 
-#define DCERPC_SIGN            16
-#define DCERPC_SEAL            32
+#define DCERPC_SIGN                    (1<<4)
+#define DCERPC_SEAL                    (1<<5)
 
-#define DCERPC_PUSH_BIGENDIAN   64
-#define DCERPC_PULL_BIGENDIAN  128
+#define DCERPC_PUSH_BIGENDIAN          (1<<6)
+#define DCERPC_PULL_BIGENDIAN          (1<<7)
 
-#define DCERPC_SCHANNEL        256
+#define DCERPC_SCHANNEL_BDC            (1<<8)
+#define DCERPC_SCHANNEL_WORKSTATION    (1<<9)
+#define DCERPC_SCHANNEL_DOMAIN         (1<<10)
+#define DCERPC_SCHANNEL_ANY            (DCERPC_SCHANNEL_BDC| \
+                                       DCERPC_SCHANNEL_DOMAIN| \
+                                       DCERPC_SCHANNEL_WORKSTATION)
+
+#define DCERPC_AUTH_OPTIONS    (DCERPC_SEAL|DCERPC_SIGN|DCERPC_SCHANNEL_ANY)
 
 /*
   this is used to find pointers to calls
index 61db90d1e3fe5d2ac14b0a29b812d80ccb996736..f81429c1f3b91450617fe6138f116f0b1e8005b5 100644 (file)
@@ -81,7 +81,7 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
                             const char *username,
                             const char *password,
                             int chan_type,
-                            uint8_t new_session_key[8])
+                            uint8_t new_session_key[16])
 {
        NTSTATUS status;
        struct dcerpc_pipe *p2;
@@ -91,7 +91,7 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
        struct samr_Password mach_pwd;
        struct creds_CredentialState creds;
        const char *workgroup, *workstation;
-       uint32_t negotiate_flags = 0;
+       uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
 
        workstation = username;
        workgroup = domain;
@@ -99,10 +99,10 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
        /*
          step 1 - establish a netlogon connection, with no authentication
        */
-       status = dcerpc_secondary_smb(p, &p2, 
-                                     DCERPC_NETLOGON_NAME, 
-                                     DCERPC_NETLOGON_UUID, 
-                                     DCERPC_NETLOGON_VERSION);
+       status = dcerpc_secondary_connection(p, &p2, 
+                                            DCERPC_NETLOGON_NAME, 
+                                            DCERPC_NETLOGON_UUID, 
+                                            DCERPC_NETLOGON_VERSION);
 
 
        /*
@@ -152,7 +152,7 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
        */
        dcerpc_pipe_close(p2);
 
-       memcpy(new_session_key, creds.session_key, 8);
+       memcpy(new_session_key, creds.session_key, 16);
 
        return NT_STATUS_OK;
 }
@@ -167,17 +167,13 @@ NTSTATUS dcerpc_bind_auth_schannel_key(struct dcerpc_pipe *p,
                                       const char *uuid, uint_t version,
                                       const char *domain,
                                       const char *username,
-                                      const uint8_t session_key[8])
+                                      const uint8_t session_key[16])
 {
        NTSTATUS status;
-       uint8_t full_session_key[16];
        struct schannel_state *schannel_state;
        const char *workgroup, *workstation;
        struct dcerpc_bind_schannel bind_schannel;
 
-       memcpy(full_session_key, session_key, 8);
-       memset(full_session_key+8, 0, 8);
-
        workstation = username;
        workgroup = domain;
 
@@ -234,7 +230,7 @@ NTSTATUS dcerpc_bind_auth_schannel_key(struct dcerpc_pipe *p,
                goto done;
        }
 
-       status = schannel_start(&schannel_state, full_session_key, True);
+       status = schannel_start(&schannel_state, session_key, True);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -265,11 +261,19 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
                                   const char *password)
 {
        NTSTATUS status;
-       uint8_t session_key[8];
+       uint8_t session_key[16];
+       int chan_type = 0;
+
+       if (p->flags & DCERPC_SCHANNEL_BDC) {
+               chan_type = SEC_CHAN_BDC;
+       } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) {
+               chan_type = SEC_CHAN_WKSTA;
+       } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) {
+               chan_type = SEC_CHAN_DOMAIN;
+       } 
 
        status = dcerpc_schannel_key(p, domain, username, password, 
-                                    lp_server_role() == ROLE_DOMAIN_BDC? SEC_CHAN_BDC:SEC_CHAN_WKSTA,
-                                    session_key);
+                                    chan_type, session_key);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
index 623d5ec24a723aa4837b79eddbfa51ddbd1eaddf..c7edf043ece5735d9f1345cc7262869e88332858 100644 (file)
@@ -275,7 +275,6 @@ static const struct {
 } ncacn_options[] = {
        {"sign", DCERPC_SIGN},
        {"seal", DCERPC_SEAL},
-       {"schannel", DCERPC_SCHANNEL},
        {"validate", DCERPC_DEBUG_VALIDATE_BOTH},
        {"print", DCERPC_DEBUG_PRINT_BOTH},
        {"bigendian", DCERPC_PUSH_BIGENDIAN}
@@ -458,11 +457,18 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
                pipe_name += 6;
        }
            
-       status = cli_full_connection(&cli, lp_netbios_name(),
-                                    binding->host, NULL, 
-                                    "ipc$", "?????", 
-                                    username, username[0]?domain:"",
-                                    password, 0, &retry);
+       if ((binding->flags & DCERPC_SCHANNEL_ANY) || !username || !username[0]) {
+               status = cli_full_connection(&cli, lp_netbios_name(),
+                                            binding->host, NULL, 
+                                            "ipc$", "?????", 
+                                            "", "", NULL, 0, &retry);
+       } else {
+               status = cli_full_connection(&cli, lp_netbios_name(),
+                                            binding->host, NULL, 
+                                            "ipc$", "?????", 
+                                            username, domain,
+                                            password, 0, &retry);
+       }
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Failed to connect to %s - %s\n", binding->host, nt_errstr(status)));
                return status;
@@ -482,23 +488,15 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
        
        (*p)->flags = binding->flags;
 
-       if (binding->flags & DCERPC_SCHANNEL) {
-               const char *trust_password = NULL; // samdb_fetch_member_password();
-               if (!trust_password) {
-                       DEBUG(0,("Unable to fetch machine password\n"));
-                       goto done;
-               }
+       if (binding->flags & DCERPC_SCHANNEL_ANY) {
                status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, 
-                                                  lp_workgroup(), 
-                                                  lp_netbios_name(), 
-                                                  trust_password);
+                                                  domain, username, password);
        } else if (binding->flags & (DCERPC_SIGN | DCERPC_SEAL)) {
                status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password);
        } else {    
                status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version);
        }
 
-done:
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
                dcerpc_pipe_close(*p);
@@ -552,7 +550,10 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
 
        (*p)->flags = binding->flags;
 
-       if (!(binding->flags & (DCERPC_SIGN|DCERPC_SEAL)) && !username[0]) {
+       if (binding->flags & DCERPC_SCHANNEL_ANY) {
+               status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, 
+                                                  domain, username, password);
+       } else if (!(binding->flags & (DCERPC_SIGN|DCERPC_SEAL)) && !username[0]) {
                status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version);
        } else {
                status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version,
@@ -560,7 +561,8 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
+               DEBUG(0,("Failed to bind to uuid %s - %s\n", 
+                        pipe_uuid, nt_errstr(status)));
                dcerpc_pipe_close(*p);
                return status;
        }
@@ -635,28 +637,46 @@ NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **p,
 
 
 /*
-  create a secondary dcerpc connection from a primary SMB connection
+  create a secondary dcerpc connection from a primary connection
 
-  the secondary connection will be on the same SMB connection, but use a new fnum
+  if the primary is a SMB connection then the secondary connection
+  will be on the same SMB connection, but use a new fnum
 */
-NTSTATUS dcerpc_secondary_smb(struct dcerpc_pipe *p, struct dcerpc_pipe **p2,
-                             const char *pipe_name,
-                             const char *pipe_uuid,
-                             uint32_t pipe_version)
+NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe **p2,
+                                    const char *pipe_name,
+                                    const char *pipe_uuid,
+                                    uint32_t pipe_version)
 {
-       NTSTATUS status;
        struct cli_tree *tree;
+       NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+       struct dcerpc_binding b;
 
-       tree = dcerpc_smb_tree(p);
-       if (!tree) {
-               return NT_STATUS_INVALID_PARAMETER;
+       switch (p->transport.transport) {
+       case NCACN_NP:
+               tree = dcerpc_smb_tree(p);
+               if (!tree) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               status = dcerpc_pipe_open_smb(p2, tree, pipe_name);
+               break;
+
+       case NCACN_IP_TCP:
+               status = dcerpc_parse_binding(p->mem_ctx, p->binding_string, &b);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               b.flags &= ~DCERPC_AUTH_OPTIONS;
+               status = dcerpc_pipe_connect_ncacn_ip_tcp(p2, &b, pipe_uuid,
+                                                         pipe_version, NULL, 
+                                                         NULL, NULL);
+               break;
        }
 
-       status = dcerpc_pipe_open_smb(p2, tree, pipe_name);
        if (!NT_STATUS_IS_OK(status)) {
-                return status;
-        }
-       
+               return status;
+       }
+
        (*p2)->flags = p->flags;
 
        status = dcerpc_bind_auth_none(*p2, pipe_uuid, pipe_version);
index 4bbcf21b58c474786f904ec9cd73bac692a8e999..a4ec4b407646ebc9f28686d457fe93faf2d2dd63 100644 (file)
@@ -61,6 +61,8 @@ ADD_OBJ_FILES = \
                torture/rpc/mgmt.o \
                torture/rpc/scanner.o \
                torture/rpc/autoidl.o \
+               torture/rpc/testjoin.o \
+               torture/rpc/schannel.o \
                torture/rpc/netlogon.o
 REQUIRED_SUBSYSTEMS = \
                LIBSMB
index 04741d8b9077b13cf97507741485d9aee6dcbe83..68571a2f6c35be6c4e08723039e33de2c0f8541a 100644 (file)
 #include "includes.h"
 
 
-#define TEST_MACHINE_NAME "torturetest"
-
-static struct {
-       struct dcerpc_pipe *p;
-       const char *machine_password;
-       struct policy_handle acct_handle;
-} join;
-
-/*
-  join the domain as a BDC
-*/
-static BOOL join_domain_bdc(TALLOC_CTX *mem_ctx)
-{
-       NTSTATUS status;
-       struct samr_Connect c;
-       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;
-       struct policy_handle domain_handle;
-       uint32_t access_granted;
-       uint32_t rid;
-       BOOL ret = True;
-       DATA_BLOB session_key;
-       struct samr_Name name;
-       int policy_min_pw_len = 0;
-
-       printf("Connecting to SAMR\n");
-
-       status = torture_rpc_connection(&join.p, 
-                                       DCERPC_SAMR_NAME,
-                                       DCERPC_SAMR_UUID,
-                                       DCERPC_SAMR_VERSION);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
-
-       c.in.system_name = NULL;
-       c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
-       c.out.handle = &handle;
-
-       status = dcerpc_samr_Connect(join.p, mem_ctx, &c);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("samr_Connect failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       printf("Opening domain %s\n", lp_workgroup());
-
-       name.name = lp_workgroup();
-       l.in.handle = &handle;
-       l.in.domain = &name;
-
-       status = dcerpc_samr_LookupDomain(join.p, mem_ctx, &l);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("LookupDomain failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       o.in.handle = &handle;
-       o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
-       o.in.sid = l.out.sid;
-       o.out.domain_handle = &domain_handle;
-
-       status = dcerpc_samr_OpenDomain(join.p, mem_ctx, &o);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("OpenDomain failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       printf("Creating machine account %s\n", TEST_MACHINE_NAME);
-
-again:
-       name.name = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
-       r.in.handle = &domain_handle;
-       r.in.account_name = &name;
-       r.in.acct_flags = ACB_SVRTRUST;
-       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
-       r.out.acct_handle = &join.acct_handle;
-       r.out.access_granted = &access_granted;
-       r.out.rid = &rid;
-
-       status = dcerpc_samr_CreateUser2(join.p, mem_ctx, &r);
-
-       if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS) &&
-           test_DeleteUser_byname(join.p, mem_ctx, &domain_handle, name.name)) {
-               goto again;
-       }
-
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("CreateUser2 failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       pwp.in.handle = &join.acct_handle;
+static const char *machine_password;
 
-       status = dcerpc_samr_GetUserPwInfo(join.p, mem_ctx, &pwp);
-       if (NT_STATUS_IS_OK(status)) {
-               policy_min_pw_len = pwp.out.info.min_password_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);
-
-       s.in.handle = &join.acct_handle;
-       s.in.info = &u;
-       s.in.level = 24;
-
-       encode_pw_buffer(u.info24.password.data, join.machine_password, STR_UNICODE);
-       u.info24.pw_len = strlen(join.machine_password);
-
-       status = dcerpc_fetch_session_key(join.p, &session_key);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo level %u - no session key - %s\n",
-                      s.in.level, nt_errstr(status));
-               return False;
-       }
-
-       arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
-
-       status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       s.in.handle = &join.acct_handle;
-       s.in.info = &u;
-       s.in.level = 16;
-
-       u.info16.acct_flags = ACB_SVRTRUST;
-
-       printf("Resetting ACB flags\n");
-
-       status = dcerpc_samr_SetUserInfo(join.p, mem_ctx, &s);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("SetUserInfo failed - %s\n", nt_errstr(status));
-               return False;
-       }
-
-       return ret;
-}
-
-/*
-  leave the domain as a BDC
-*/
-static BOOL leave_domain_bdc(TALLOC_CTX *mem_ctx)
-{
-       struct samr_DeleteUser d;
-       NTSTATUS status;
-
-       d.in.handle = &join.acct_handle;
-       d.out.handle = &join.acct_handle;
-
-       status = dcerpc_samr_DeleteUser(join.p, mem_ctx, &d);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("Delete of machine account failed\n");
-               return False;
-       }
-
-       return True;
-}
+#define TEST_MACHINE_NAME "torturetest"
 
 static BOOL test_LogonUasLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 {
@@ -259,7 +96,7 @@ static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
-       plain_pass = join.machine_password;
+       plain_pass = machine_password;
        if (!plain_pass) {
                printf("Unable to fetch machine password!\n");
                return False;
@@ -319,7 +156,7 @@ static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
-       plain_pass = join.machine_password;
+       plain_pass = machine_password;
        if (!plain_pass) {
                printf("Unable to fetch machine password!\n");
                return False;
@@ -385,7 +222,7 @@ static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                return False;
        }
 
-       plain_pass = join.machine_password;
+       plain_pass = machine_password;
        if (!plain_pass) {
                printf("Unable to fetch machine password!\n");
                return False;
@@ -1157,7 +994,7 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                printf("Credential chaining failed\n");
        }
 
-       join.machine_password = password;
+       machine_password = password;
 
        if (!test_SetupCredentials(p, mem_ctx, &creds)) {
                printf("ServerPasswordSet failed to actually change the password\n");
@@ -1679,10 +1516,13 @@ BOOL torture_rpc_netlogon(int dummy)
         struct dcerpc_pipe *p;
        TALLOC_CTX *mem_ctx;
        BOOL ret = True;
+       void *join_ctx;
 
        mem_ctx = talloc_init("torture_rpc_netlogon");
 
-       if (!join_domain_bdc(mem_ctx)) {
+       join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
+                                      &machine_password);
+       if (!join_ctx) {
                printf("Failed to join as BDC\n");
                return False;
        }
@@ -1757,10 +1597,7 @@ BOOL torture_rpc_netlogon(int dummy)
 
         torture_rpc_close(p);
 
-       if (!leave_domain_bdc(mem_ctx)) {
-               printf("Failed to delete BDC machine account\n");
-               return False;
-       }
+       torture_leave_domain(join_ctx);
 
        return ret;
 }
diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c
new file mode 100644 (file)
index 0000000..8d30f16
--- /dev/null
@@ -0,0 +1,130 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   test suite for schannel operations
+
+   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
+   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"
+
+#define TEST_MACHINE_NAME "schanneltest"
+
+static BOOL test_samr_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+       NTSTATUS status;
+       struct samr_GetDomPwInfo r;
+       int i;
+       struct samr_Name name;
+
+       name.name = lp_workgroup();
+       r.in.name = &name;
+
+       printf("Testing GetDomPwInfo with name %s\n", r.in.name->name);
+       
+       /* do several ops to test credential chaining */
+       for (i=0;i<5;i++) {
+               status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("GetDomPwInfo op %d failed - %s\n", i, nt_errstr(status));
+                       return False;
+               }
+       }
+
+       return True;
+}
+
+
+static BOOL test_schannel(TALLOC_CTX *mem_ctx, 
+                         uint16 acct_flags, uint32 dcerpc_flags,
+                         uint32 schannel_type)
+{
+       void *join_ctx;
+       const char *machine_password;
+       NTSTATUS status;
+       char *binding = lp_parm_string(-1, "torture", "binding");
+       struct dcerpc_binding b;
+       struct dcerpc_pipe *p;
+
+       join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), acct_flags,
+                                      &machine_password);
+       if (!join_ctx) {
+               printf("Failed to join domain with acct_flags=0x%x\n", acct_flags);
+               return False;
+       }
+
+       status = dcerpc_parse_binding(mem_ctx, binding, &b);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Bad binding string %s\n", binding);
+               goto failed;
+       }
+
+       b.flags &= ~DCERPC_AUTH_OPTIONS;
+       b.flags |= dcerpc_flags;
+
+       status = dcerpc_pipe_connect_b(&p, &b, 
+                                      DCERPC_SAMR_UUID,
+                                      DCERPC_SAMR_VERSION,
+                                      lp_workgroup(), 
+                                      TEST_MACHINE_NAME,
+                                      machine_password);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Failed to connect with schannel\n");
+               goto failed;
+       }
+
+       test_samr_ops(p, mem_ctx);
+
+       torture_leave_domain(join_ctx);
+       return True;
+
+failed:
+       torture_leave_domain(join_ctx);
+       return False;   
+}
+
+
+BOOL torture_rpc_schannel(int dummy)
+{
+       TALLOC_CTX *mem_ctx;
+       BOOL ret = True;
+       struct {
+               uint16 acct_flags;
+               uint32 dcerpc_flags;
+               uint32 schannel_type;
+       } tests[] = {
+               { ACB_WSTRUST,   DCERPC_SCHANNEL_WORKSTATION | DCERPC_SIGN, 3 },
+               { ACB_WSTRUST,   DCERPC_SCHANNEL_WORKSTATION | DCERPC_SEAL, 3 },
+               { ACB_SVRTRUST,  DCERPC_SCHANNEL_BDC | DCERPC_SIGN,         3 },
+               { ACB_SVRTRUST,  DCERPC_SCHANNEL_BDC | DCERPC_SEAL,         3 }
+       };
+       int i;
+
+       mem_ctx = talloc_init("torture_rpc_schannel");
+
+       for (i=0;i<ARRAY_SIZE(tests);i++) {
+               if (!test_schannel(mem_ctx, 
+                                  tests[i].acct_flags, tests[i].dcerpc_flags, tests[i].schannel_type)) {
+                       printf("Failed with acct_flags=0x%x dcerpc_flags=0x%x schannel_type=%d\n",
+                              tests[i].acct_flags, tests[i].dcerpc_flags, tests[i].schannel_type);
+                       ret = False;
+                       break;
+               }
+       }
+
+       return ret;
+}
index 74860cd369e25e194929a454989a8c06910e8f8c..cbeaac8d9e60d60fd5ebb9740da64acf7fe7288e 100644 (file)
@@ -587,10 +587,10 @@ static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
 
        printf("testing close on secondary pipe\n");
 
-       status = dcerpc_secondary_smb(p, &p2, 
-                                     DCERPC_SPOOLSS_NAME, 
-                                     DCERPC_SPOOLSS_UUID, 
-                                     DCERPC_SPOOLSS_VERSION);
+       status = dcerpc_secondary_connection(p, &p2, 
+                                            DCERPC_SPOOLSS_NAME, 
+                                            DCERPC_SPOOLSS_UUID, 
+                                            DCERPC_SPOOLSS_VERSION);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Failed to create secondary connection\n");
                return False;
diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c
new file mode 100644 (file)
index 0000000..aab08c3
--- /dev/null
@@ -0,0 +1,277 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   utility code to join/leave a domain
+
+   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
+   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.
+*/
+
+/*
+  this code is used by other torture modules to join/leave a domain
+  as either a member, bdc or thru a trust relationship
+*/
+
+#include "includes.h"
+
+struct test_join {
+       TALLOC_CTX *mem_ctx;
+       struct dcerpc_pipe *p;
+       const char *machine_password;
+       struct policy_handle acct_handle;
+};
+
+
+static NTSTATUS DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                 struct policy_handle *handle, const char *name)
+{
+       NTSTATUS status;
+       struct samr_DeleteUser d;
+       struct policy_handle acct_handle;
+       uint32_t rid;
+       struct samr_LookupNames n;
+       struct samr_Name sname;
+       struct samr_OpenUser r;
+
+       sname.name = name;
+
+       n.in.handle = handle;
+       n.in.num_names = 1;
+       n.in.names = &sname;
+
+       status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
+       if (NT_STATUS_IS_OK(status)) {
+               rid = n.out.rids.ids[0];
+       } else {
+               return status;
+       }
+
+       r.in.handle = handle;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.in.rid = rid;
+       r.out.acct_handle = &acct_handle;
+
+       status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("OpenUser(%s) failed - %s\n", name, nt_errstr(status));
+               return status;
+       }
+
+       d.in.handle = &acct_handle;
+       d.out.handle = &acct_handle;
+       status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  join the domain as a test machine
+  an opaque pointer is returned. Pass it to torture_leave_domain() 
+  when finished
+*/
+void *torture_join_domain(const char *machine_name, 
+                         const char *domain,
+                         uint16 acct_flags,
+                         const char **machine_password)
+{
+       NTSTATUS status;
+       struct samr_Connect c;
+       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;
+       struct policy_handle domain_handle;
+       uint32_t access_granted;
+       uint32_t rid;
+       DATA_BLOB session_key;
+       struct samr_Name name;
+       int policy_min_pw_len = 0;
+       struct test_join *join;
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_init("torture_join_domain");
+       if (!mem_ctx) {
+               return NULL;
+       }
+
+       join = talloc_p(mem_ctx, struct test_join);
+       if (join == NULL) {
+               talloc_destroy(mem_ctx);
+               return NULL;
+       }
+
+       ZERO_STRUCTP(join);
+
+       join->mem_ctx = mem_ctx;
+
+       printf("Connecting to SAMR\n");
+
+       status = torture_rpc_connection(&join->p, 
+                                       DCERPC_SAMR_NAME,
+                                       DCERPC_SAMR_UUID,
+                                       DCERPC_SAMR_VERSION);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       c.in.system_name = NULL;
+       c.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       c.out.handle = &handle;
+
+       status = dcerpc_samr_Connect(join->p, mem_ctx, &c);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("samr_Connect failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       printf("Opening domain %s\n", domain);
+
+       name.name = domain;
+       l.in.handle = &handle;
+       l.in.domain = &name;
+
+       status = dcerpc_samr_LookupDomain(join->p, mem_ctx, &l);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("LookupDomain failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       o.in.handle = &handle;
+       o.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       o.in.sid = l.out.sid;
+       o.out.domain_handle = &domain_handle;
+
+       status = dcerpc_samr_OpenDomain(join->p, mem_ctx, &o);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("OpenDomain failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       printf("Creating machine account %s\n", machine_name);
+
+again:
+       name.name = talloc_asprintf(mem_ctx, "%s$", machine_name);
+       r.in.handle = &domain_handle;
+       r.in.account_name = &name;
+       r.in.acct_flags = acct_flags;
+       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       r.out.acct_handle = &join->acct_handle;
+       r.out.access_granted = &access_granted;
+       r.out.rid = &rid;
+
+       status = dcerpc_samr_CreateUser2(join->p, mem_ctx, &r);
+
+       if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
+               status = DeleteUser_byname(join->p, mem_ctx, &domain_handle, name.name);
+               if (NT_STATUS_IS_OK(status)) {
+                       goto again;
+               }
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("CreateUser2 failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       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_password_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);
+
+       s.in.handle = &join->acct_handle;
+       s.in.info = &u;
+       s.in.level = 24;
+
+       encode_pw_buffer(u.info24.password.data, join->machine_password, STR_UNICODE);
+       u.info24.pw_len = strlen(join->machine_password);
+
+       status = dcerpc_fetch_session_key(join->p, &session_key);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("SetUserInfo level %u - no session key - %s\n",
+                      s.in.level, nt_errstr(status));
+               torture_leave_domain(&join);
+               goto failed;
+       }
+
+       arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
+
+       status = dcerpc_samr_SetUserInfo(join->p, mem_ctx, &s);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("SetUserInfo failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       s.in.handle = &join->acct_handle;
+       s.in.info = &u;
+       s.in.level = 16;
+
+       u.info16.acct_flags = acct_flags;
+
+       printf("Resetting ACB flags\n");
+
+       status = dcerpc_samr_SetUserInfo(join->p, mem_ctx, &s);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("SetUserInfo failed - %s\n", nt_errstr(status));
+               goto failed;
+       }
+
+       *machine_password = join->machine_password;
+
+       return join;
+
+failed:
+       torture_leave_domain(join);
+       return NULL;
+}
+
+
+/*
+  leave the domain, deleting the machine acct
+*/
+void torture_leave_domain(void *join_ctx)
+{
+       struct test_join *join = join_ctx;
+       struct samr_DeleteUser d;
+       NTSTATUS status;
+
+       if (!uuid_all_zero(&join->acct_handle.uuid)) {
+               d.in.handle = &join->acct_handle;
+               d.out.handle = &join->acct_handle;
+               
+               status = dcerpc_samr_DeleteUser(join->p, join->mem_ctx, &d);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("Delete of machine account failed\n");
+               }
+       }
+
+       if (join->p) {
+               torture_rpc_close(join->p);
+       }
+
+       talloc_destroy(join->mem_ctx);
+}
index 2dcacf23881e1136a5bfaf4101db8da0a7b3148f..4ff340bdd0a58a57fcdb9b8f84adb4aca36014ef 100644 (file)
@@ -2795,7 +2795,7 @@ static BOOL run_vuidtest(int dummy)
        const char *fname = "\\vuid.tst";
        int fnum;
        size_t size;
-       time_t c_time, a_time, m_time, w_time, m_time2;
+       time_t c_time, a_time, m_time;
        BOOL correct = True;
 
        uint16_t orig_vuid;
@@ -4131,6 +4131,7 @@ static struct {
         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
         {"RPC-SAMR", torture_rpc_samr, 0},
         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
+        {"RPC-SCHANNEL", torture_rpc_schannel, 0},
         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
         {"RPC-ATSVC", torture_rpc_atsvc, 0},