r3686: The results of some work on the NETLOGON pipe:
authorAndrew Bartlett <abartlet@samba.org>
Thu, 11 Nov 2004 23:24:30 +0000 (23:24 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:43 +0000 (13:05 -0500)
Break out the samsync tests from RPC-NETLOGON into a new RPC-SAMSYNC,
that will cross-verify all the values.

Add support for the way netlogon credentials are shared between the
pipe that sets up schannel and the pipe that is encrypted with it.

Test this support, by calling both NETLOGON and SAMR operations in the
RPC-SCHANNEL test.

Move some of the Netlogon NEG flags into the .idl, now we have an idea
what a few of them really are.

Rename the sam_pwd_hash into a name that has meaning (all other crypto
functions were renamed in Samba4 ages ago).

Break out NTLMv2 functionality for operation on the NT hash - I intend
to do NTLMv2 logins in the samsync test in future, and naturally I
only have the hash.

Andrew Bartlett
(This used to be commit 6e6cc6fb9842113a1b0c7f6904dac709b320a6e5)

12 files changed:
source4/libcli/auth/credentials.h
source4/libcli/auth/gensec.h
source4/libcli/util/smbdes.c
source4/libcli/util/smbencrypt.c
source4/librpc/idl/netlogon.idl
source4/librpc/rpc/dcerpc_schannel.c
source4/rpc_server/netlogon/schannel_state.c
source4/torture/config.mk
source4/torture/rpc/netlogon.c
source4/torture/rpc/schannel.c
source4/torture/rpc/xplogin.c
source4/torture/torture.c

index a6e119e1ad4407f029c8618e9a75ec287e5ce852..30114fe7faf5fe2b71a43d5c5e14ea3b77580791 100644 (file)
@@ -36,12 +36,6 @@ struct creds_CredentialState {
    to NT4.  Actually, anything other than 1ff would seem to do... */
 #define NETLOGON_NEG_AUTH2_FLAGS     0x000701ff
 
-
-#define NETLOGON_NEG_ARCFOUR         0x00000004
-#define NETLOGON_NEG_128BIT          0x00004000
-
-#define NETLOGON_NEG_SCHANNEL        0x40000000
-
 /* these are the flags that ADS clients use */
 #define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL)
 
index b2c685332b0ae32ffd1ee2ea8500de57e95a1c40..23d9861cb766d8dfdc45ef1d544f221b8711113a 100644 (file)
@@ -28,7 +28,6 @@ struct gensec_user {
        const char *realm;
        const char *name;
        const char *password;
-       char schan_session_key[16];
 };
 struct gensec_target {
        const char *principal;
index a7c8f760ea08192b90e5615eba543b38293b4129..4e4222b9e65989c17ab537d0f99efd9c413b0222 100644 (file)
@@ -439,7 +439,7 @@ void arcfour_crypt(uint8_t *data, const uint8_t keystr[16], int len)
 /* Decode a sam password hash into a password.  The password hash is the
    same method used to store passwords in the NT registry.  The DES key
    used is based on the RID of the user. */
-void sam_pwd_hash(uint_t rid, const uint8_t *in, uint8_t *out, int forw)
+void sam_rid_crypt(uint_t rid, const uint8_t *in, uint8_t *out, int forw)
 {
        uint8_t s[14];
 
index d327b53f9d6c8fd05a6bc783de86372847d697b8..dac8674f035b43f74ab4cd762c8d7a485fc1a24d 100644 (file)
@@ -374,15 +374,13 @@ static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
        return final_response;
 }
 
-BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, 
-                     const DATA_BLOB *server_chal, 
-                     const DATA_BLOB *names_blob,
-                     DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
-                     DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) 
+BOOL SMBNTLMv2encrypt_hash(const char *user, const char *domain, const char nt_hash[16],
+                          const DATA_BLOB *server_chal, 
+                          const DATA_BLOB *names_blob,
+                          DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
+                          DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) 
 {
-       uint8_t nt_hash[16];
        uint8_t ntlm_v2_hash[16];
-       E_md4hash(password, nt_hash);
 
        /* We don't use the NT# directly.  Instead we use it mashed up with
           the username and domain.
@@ -420,6 +418,19 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
        return True;
 }
 
+BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, 
+                     const DATA_BLOB *server_chal, 
+                     const DATA_BLOB *names_blob,
+                     DATA_BLOB *lm_response, DATA_BLOB *nt_response, 
+                     DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) 
+{
+       uint8_t nt_hash[16];
+       E_md4hash(password, nt_hash);
+
+       return SMBNTLMv2encrypt_hash(user, domain, nt_hash, server_chal, names_blob,
+                                    lm_response, nt_response, lm_session_key, user_session_key);
+}
+
 /***********************************************************
  encode a password buffer with a unicode password.  The buffer
  is filled with random data to make it harder to attack.
index f6677d96216e18bb7e4637e0d3dea17246a1f628..f55049d30e1c743fc542b7b6ec28791195372ddc 100644 (file)
@@ -285,6 +285,11 @@ interface netlogon
        /*****************/
        /* Function 0x07 */
 
+       /* SAM database types */
+       const int SAM_DATABASE_DOMAIN  = 0x00; /* Domain users and groups */
+       const int SAM_DATABASE_BUILTIN = 0x01; /* BUILTIN users and groups */
+       const int SAM_DATABASE_PRIVS   = 0x02; /* Privileges */
+
        typedef struct {
                unistr *account_name;
                netr_String unknown1;
@@ -313,19 +318,19 @@ interface netlogon
                netr_String logon_script;
                netr_String description;
                netr_String workstations;
-               NTTIME LastLogon;
-               NTTIME LastLogoff;
+               NTTIME last_logon;
+               NTTIME last_logoff;
                samr_LogonHours logon_hours;
                uint16 bad_pw_count;
                uint16 logon_count;
-               NTTIME PwLastSet;
-               NTTIME AccountExpires;
-               uint32 AccountControl;
-               samr_Password lmpw;
-               samr_Password ntpw;
-               bool8 NTPwPresent;
-               bool8 LMPwPresent;
-               bool8 PwExpired;
+               NTTIME last_password_change;
+               NTTIME acct_expiry;
+               uint32 acct_flags;
+               samr_Password lmpassword;
+               samr_Password ntpassword;
+               bool8 ntpassword_present;
+               bool8 lmpassword_present;
+               bool8 password_expired;
                netr_String UserComment;
                netr_String Parameters;
                uint16 CountryCode;
@@ -778,6 +783,13 @@ interface netlogon
                );
 
 
+       /* If this flag is not set, then the passwords and LM session keys are
+        * encrypted with DES calls.  (And the user session key is
+        * unencrypted) */ 
+       const int NETLOGON_NEG_ARCFOUR  = 0x00000004;
+       const int NETLOGON_NEG_128BIT   = 0x00004000;
+       const int NETLOGON_NEG_SCHANNEL = 0x40000000;
+
        /*****************/
        /* Function 0x0F */
 
index c0db63e8b86b04a14846831a29863fb66654b5c3..1e1bdb822741c2690453dfa3b8a8b0bbdd4d68c7 100644 (file)
@@ -32,7 +32,7 @@ enum schannel_position {
 struct dcerpc_schannel_state {
        enum schannel_position state;
        struct schannel_state *schannel_state;
-       struct creds_CredentialState creds;
+       struct creds_CredentialState *creds;
        char *account_name;
 };
 
@@ -41,7 +41,7 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
                                    const char *username,
                                    const char *password,
                                    int chan_type,
-                                   uint8_t new_session_key[16]);
+                                   struct creds_CredentialState *creds);
 
 /*
   wrappers for the schannel_*() functions
@@ -121,6 +121,15 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
                        return NT_STATUS_OK;
                }
                
+               status = schannel_start(&dce_schan_state->schannel_state, 
+                                       dce_schan_state->creds->session_key,
+                                       True);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(1, ("Failed to start schannel client\n"));
+                       return status;
+               }
+               talloc_steal(dce_schan_state, dce_schan_state->schannel_state);
+       
                bind_schannel.unknown1 = 0;
 #if 0
                /* to support this we'd need to have access to the full domain name */
@@ -178,7 +187,7 @@ static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security,
                
                /* start up the schannel server code */
                status = schannel_start(&dce_schan_state->schannel_state, 
-                                       dce_schan_state->creds.session_key, False);
+                                       dce_schan_state->creds->session_key, False);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(3, ("Could not initialise schannel state for account %s: %s\n",
                                  account_name, nt_errstr(status)));
@@ -249,12 +258,7 @@ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security,
 { 
        struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
 
-       *creds = talloc_p(mem_ctx, struct creds_CredentialState);
-       if (!*creds) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       **creds = dce_schan_state->creds;
+       *creds = dce_schan_state->creds;
        return NT_STATUS_OK;
 }
                
@@ -277,38 +281,23 @@ static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security)
 static NTSTATUS dcerpc_schannel_server_start(struct gensec_security *gensec_security) 
 {
        NTSTATUS status;
-       struct dcerpc_schannel_state *dce_schan_state;
 
        status = dcerpc_schannel_start(gensec_security);
-
-       dce_schan_state = gensec_security->private_data;
-       dce_schan_state->schannel_state = NULL;
-
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
+
        return NT_STATUS_OK;
 }
 
 static NTSTATUS dcerpc_schannel_client_start(struct gensec_security *gensec_security) 
 {
        NTSTATUS status;
-       struct dcerpc_schannel_state *dce_schan_state;
 
        status = dcerpc_schannel_start(gensec_security);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-       dce_schan_state = gensec_security->private_data;
-
-       status = schannel_start(&dce_schan_state->schannel_state, 
-                               gensec_security->user.schan_session_key, 
-                               True);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Failed to start schannel client\n"));
-               return status;
-       }
-       talloc_steal(dce_schan_state, dce_schan_state->schannel_state);
 
        return NT_STATUS_OK;
 }
@@ -336,7 +325,7 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
                                    const char *username,
                                    const char *password,
                                    int chan_type,
-                                   uint8_t new_session_key[16])
+                                   struct creds_CredentialState *creds)
 {
        NTSTATUS status;
        struct dcerpc_pipe *p2;
@@ -344,7 +333,6 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
        struct netr_ServerAuthenticate2 a;
        struct netr_Credential credentials1, credentials2, credentials3;
        struct samr_Password mach_pwd;
-       struct creds_CredentialState creds;
        const char *workgroup, *workstation;
        uint32_t negotiate_flags;
 
@@ -388,7 +376,7 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
          step 3 - authenticate on the netlogon pipe
        */
        E_md4hash(password, mach_pwd.hash);
-       creds_client_init(&creds, &credentials1, &credentials2, &mach_pwd, &credentials3,
+       creds_client_init(creds, &credentials1, &credentials2, &mach_pwd, &credentials3,
                          negotiate_flags);
 
        a.in.server_name = r.in.server_name;
@@ -405,7 +393,7 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
                return status;
        }
 
-       if (!creds_client_check(&creds, a.out.credentials)) {
+       if (!creds_client_check(creds, a.out.credentials)) {
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -416,8 +404,6 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
        */
        dcerpc_pipe_close(p2);
 
-       memcpy(new_session_key, creds.session_key, 16);
-
        return NT_STATUS_OK;
 }
 
@@ -430,18 +416,16 @@ NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
                                           const char *domain,
                                           const char *username,
                                           const char *password,
-                                          uint8_t session_key[16])
+                                          struct creds_CredentialState *creds)
 {
        NTSTATUS status;
+       struct dcerpc_schannel_state *dce_schan_state;
 
        status = gensec_client_start(p, &p->security_state.generic_state);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       memcpy(p->security_state.generic_state->user.schan_session_key,
-              session_key, 16);
-
        status = gensec_set_username(p->security_state.generic_state, username);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to set schannel username to %s: %s\n", username, nt_errstr(status)));
@@ -464,6 +448,9 @@ NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
                return status;
        }
 
+       dce_schan_state = p->security_state.generic_state->private_data;
+       dce_schan_state->creds = talloc_reference(dce_schan_state, creds);
+
        status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p),
                                  uuid, version);
 
@@ -484,7 +471,11 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
 {
        NTSTATUS status;
        int chan_type = 0;
-       uint8_t new_session_key[16];
+       struct creds_CredentialState *creds;
+       creds = talloc_p(p, struct creds_CredentialState);
+       if (!creds) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        if (p->flags & DCERPC_SCHANNEL_BDC) {
                chan_type = SEC_CHAN_BDC;
@@ -498,7 +489,7 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
                                     username,
                                     password, 
                                     chan_type,
-                                    new_session_key);
+                                    creds);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Failed to fetch schannel session key: %s\n",
@@ -508,7 +499,7 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
 
        return dcerpc_bind_auth_schannel_withkey(p, uuid, version, domain,
                                                 username, password,
-                                                new_session_key);
+                                                creds);
 }
 
 static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = {
index 8797ffa120d90cd7d47eaa17bc93d4c8a244e330..61e755bc0f3bbb7192b324a704e002e7c5e29a0b 100644 (file)
@@ -120,7 +120,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
 */
 NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
                                    const char *computer_name, 
-                                   struct creds_CredentialState *creds)
+                                   struct creds_CredentialState **creds)
 {
        struct ldb_wrap *ldb;
        time_t expiry;
@@ -129,7 +129,10 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
        const struct ldb_val *val;
        char *expr=NULL;
 
-       ZERO_STRUCTP(creds);
+       *creds = talloc_zero_p(mem_ctx, struct creds_CredentialState);
+       if (!*creds) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        ldb = schannel_db_connect(mem_ctx);
        if (ldb == NULL) {
@@ -161,7 +164,7 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       memcpy(creds->session_key, val->data, 16);
+       memcpy((*creds)->session_key, val->data, 16);
 
        val = ldb_msg_find_ldb_val(res[0], "seed");
        if (val == NULL || val->length != 8) {
@@ -169,7 +172,7 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       memcpy(creds->seed.data, val->data, 8);
+       memcpy((*creds)->seed.data, val->data, 8);
 
        talloc_free(ldb);
 
index cef76baac428c5d0da67ece7187c8937223abf1e..d939175bb32d001dd197fa4798ac45200a43c29b 100644 (file)
@@ -90,6 +90,7 @@ ADD_OBJ_FILES = \
                torture/rpc/schannel.o \
                torture/rpc/netlogon.o \
                torture/rpc/samlogon.o \
+               torture/rpc/samsync.o \
                torture/rpc/bind.o
 REQUIRED_SUBSYSTEMS = \
                LIBSMB
index fe64727d79444b3df921bfc27945ac0f2d6377ca..9c871065508e49b02e039764108b372f30cd870f 100644 (file)
@@ -316,6 +316,72 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        return True;
 }
 
+/*
+  try a netlogon SamLogon
+*/
+static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+       NTSTATUS status;
+       struct netr_LogonSamLogon r;
+       struct netr_Authenticator auth, auth2;
+       struct netr_NetworkInfo ninfo;
+       const char *username = lp_parm_string(-1, "torture", "username");
+       const char *password = lp_parm_string(-1, "torture", "password");
+       struct creds_CredentialState creds;
+
+       int i;
+       BOOL ret = True;
+
+       if (!test_SetupCredentials(p, mem_ctx, TEST_MACHINE_NAME, 
+                                  machine_password, &creds)) {
+               return False;
+       }
+
+       ninfo.identity_info.domain_name.string = lp_workgroup();
+       ninfo.identity_info.parameter_control = 0;
+       ninfo.identity_info.logon_id_low = 0;
+       ninfo.identity_info.logon_id_high = 0;
+       ninfo.identity_info.account_name.string = username;
+       ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
+       generate_random_buffer(ninfo.challenge, 
+                              sizeof(ninfo.challenge));
+       ninfo.nt.length = 24;
+       ninfo.nt.data = talloc(mem_ctx, 24);
+       SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data);
+       ninfo.lm.length = 24;
+       ninfo.lm.data = talloc(mem_ctx, 24);
+       SMBencrypt(password, ninfo.challenge, ninfo.lm.data);
+
+       r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.workstation = TEST_MACHINE_NAME;
+       r.in.credential = &auth;
+       r.in.return_authenticator = &auth2;
+       r.in.logon_level = 2;
+       r.in.logon.network = &ninfo;
+
+       for (i=2;i<=3;i++) {
+               ZERO_STRUCT(auth2);
+               creds_client_authenticator(&creds, &auth);
+
+               r.in.validation_level = i;
+
+               printf("Testing SamLogon with validation level %d\n", i);
+
+               status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("LogonSamLogon - %s\n", nt_errstr(status));
+                       ret = False;
+               }
+
+               if (!creds_client_check(&creds, &r.out.return_authenticator->cred)) {
+                       printf("Credential chaining failed\n");
+               }
+       }
+
+       return ret;
+}
+
+
 
 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
 static uint64_t sequence_nums[3];
@@ -328,7 +394,7 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        NTSTATUS status;
        struct netr_DatabaseSync r;
        struct creds_CredentialState creds;
-       const uint32_t database_ids[] = {0, 1, 2}; 
+       const uint32_t database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
        int i;
        BOOL ret = True;
 
@@ -366,7 +432,7 @@ static BOOL test_DatabaseSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 
                        if (r.out.delta_enum_array &&
                            r.out.delta_enum_array->num_deltas > 0 &&
-                           r.out.delta_enum_array->delta_enum[0].delta_type == 1 &&
+                           r.out.delta_enum_array->delta_enum[0].delta_type == NETR_DELTA_DOMAIN &&
                            r.out.delta_enum_array->delta_enum[0].delta_union.domain) {
                                sequence_nums[r.in.database_id] = 
                                        r.out.delta_enum_array->delta_enum[0].delta_union.domain->sequence_num;
@@ -969,7 +1035,7 @@ BOOL torture_rpc_netlogon(void)
         struct dcerpc_pipe *p;
        TALLOC_CTX *mem_ctx;
        BOOL ret = True;
-       void *join_ctx;
+       struct test_join *join_ctx;
 
        mem_ctx = talloc_init("torture_rpc_netlogon");
 
@@ -996,6 +1062,10 @@ BOOL torture_rpc_netlogon(void)
                ret = False;
        }
 
+       if (!test_SamLogon(p, mem_ctx)) {
+               ret = False;
+       }
+
        if (!test_SetPassword(p, mem_ctx)) {
                ret = False;
        }
index 323adde534a4850724691093e718468407006bd3..7a9786fa2d5239520dca3f175c9d3fbe33fffa6a 100644 (file)
@@ -53,6 +53,63 @@ static BOOL test_samr_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        return True;
 }
 
+
+/*
+  try a netlogon SamLogon
+*/
+static BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                 struct creds_CredentialState *creds)
+{
+       NTSTATUS status;
+       struct netr_LogonSamLogon r;
+       struct netr_Authenticator auth, auth2;
+       struct netr_NetworkInfo ninfo;
+       const char *username = lp_parm_string(-1, "torture", "username");
+       const char *password = lp_parm_string(-1, "torture", "password");
+
+       int i;
+       BOOL ret = True;
+
+       ninfo.identity_info.domain_name.string = lp_workgroup();
+       ninfo.identity_info.parameter_control = 0;
+       ninfo.identity_info.logon_id_low = 0;
+       ninfo.identity_info.logon_id_high = 0;
+       ninfo.identity_info.account_name.string = username;
+       ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
+       generate_random_buffer(ninfo.challenge, 
+                              sizeof(ninfo.challenge));
+       ninfo.nt.length = 24;
+       ninfo.nt.data = talloc(mem_ctx, 24);
+       SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data);
+       ninfo.lm.length = 24;
+       ninfo.lm.data = talloc(mem_ctx, 24);
+       SMBencrypt(password, ninfo.challenge, ninfo.lm.data);
+
+
+       r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.workstation = TEST_MACHINE_NAME;
+       r.in.credential = &auth;
+       r.in.return_authenticator = &auth2;
+       r.in.logon_level = 2;
+       r.in.logon.network = &ninfo;
+
+       for (i=2;i<3;i++) {
+               ZERO_STRUCT(auth2);
+               creds_client_authenticator(creds, &auth);
+               
+               r.in.validation_level = i;
+               
+               status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
+               
+               if (!creds_client_check(creds, &r.out.return_authenticator->cred)) {
+                       printf("Credential chaining failed\n");
+                       ret = False;
+               }
+               
+       }
+               return ret;
+}
+
 /*
   test a schannel connection with the given flags
  */
@@ -66,6 +123,8 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx,
        const char *binding = lp_parm_string(-1, "torture", "binding");
        struct dcerpc_binding b;
        struct dcerpc_pipe *p;
+       struct dcerpc_pipe *p_netlogon;
+       struct creds_CredentialState *creds;
 
        join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), acct_flags,
                                       &machine_password);
@@ -99,12 +158,51 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx,
                goto failed;
        }
 
+
+       status = dcerpc_parse_binding(mem_ctx, binding, &b);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Bad binding string %s\n", binding);
+               goto failed;
+       }
+
+
+       /* Also test that when we connect to the netlogon pipe, that
+        * the credentials we setup on the first pipe are valid for
+        * the second */
+
+       b.flags &= ~DCERPC_AUTH_OPTIONS;
+       b.flags |= dcerpc_flags;
+
+       status = dcerpc_pipe_connect_b(&p_netlogon, &b, 
+                                      DCERPC_NETLOGON_UUID,
+                                      DCERPC_NETLOGON_VERSION,
+                                      lp_workgroup(), 
+                                      TEST_MACHINE_NAME,
+                                      machine_password);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       status = dcerpc_schannel_creds(p_netlogon->security_state.generic_state, mem_ctx, &creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto failed;
+       }
+
+       /* do a couple of logins */
+       if (!test_netlogon_ops(p_netlogon, mem_ctx, creds)) {
+               printf("Failed to process schannel secured ops\n");
+               goto failed;
+       }
+
        torture_leave_domain(join_ctx);
+       dcerpc_pipe_close(p_netlogon);
        dcerpc_pipe_close(p);
        return True;
 
 failed:
        torture_leave_domain(join_ctx);
+       dcerpc_pipe_close(p_netlogon);
        dcerpc_pipe_close(p);
        return False;   
 }
index a3cca7003c90c4758b748b4e917c94fb1d32adb2..e0bb706255961e9f125d8cc59fc81817adcb102f 100644 (file)
@@ -1021,7 +1021,7 @@ static BOOL xp_login(const char *dcname, const char *wksname,
        struct smbcli_transport *transport;
 
         struct dcerpc_pipe *netlogon_pipe;
-       struct creds_CredentialState netlogon_creds;
+       struct creds_CredentialState *netlogon_creds;
 
        struct dcerpc_pipe *netlogon_schannel_pipe;
 
@@ -1032,13 +1032,18 @@ static BOOL xp_login(const char *dcname, const char *wksname,
        if (mem_ctx == NULL)
                return False;
 
+       netlogon_creds = talloc_p(mem_ctx, struct creds_CredentialState);
+       if (!netlogon_creds) {
+               return False;
+       }
+
        if (!NT_STATUS_IS_OK(after_negprot(&transport, dcname, 139,
                                           wksname)))
                return False;
 
        if (!NT_STATUS_IS_OK(setup_netlogon_creds(transport, &netlogon_pipe,
                                                  wksname, domain, wkspwd,
-                                                 &netlogon_creds)))
+                                                 netlogon_creds)))
                return False;
 
        if (!NT_STATUS_IS_OK(test_enumtrusts(transport)))
@@ -1063,13 +1068,13 @@ static BOOL xp_login(const char *dcname, const char *wksname,
                                                   DCERPC_NETLOGON_UUID,
                                                   DCERPC_NETLOGON_VERSION,
                                                   "", "", "",
-                                                  netlogon_creds.session_key);
+                                                  netlogon_creds);
 
        if (!NT_STATUS_IS_OK(status))
                 return False;
 
        status = torture_samlogon(netlogon_schannel_pipe,
-                                 &netlogon_creds, wksname, domain,
+                                 netlogon_creds, wksname, domain,
                                  user1name, user1pw);
 
        if (!NT_STATUS_IS_OK(status))
@@ -1078,7 +1083,7 @@ static BOOL xp_login(const char *dcname, const char *wksname,
        talloc_free(netlogon_pipe);
 
        status = torture_samlogon(netlogon_schannel_pipe,
-                                 &netlogon_creds, wksname, domain,
+                                 netlogon_creds, wksname, domain,
                                  user2name, user2pw);
 
        if (!NT_STATUS_IS_OK(status))
index 975b83e6ade259bdf28afbe341b0dae5359ba7d0..4db4662f6c6d412a427047452627ee0cfa59e581 100644 (file)
@@ -2439,6 +2439,7 @@ static struct {
         {"RPC-SAMR", torture_rpc_samr, 0},
         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
         {"RPC-SAMLOGON", torture_rpc_samlogon, 0},
+        {"RPC-SAMSYNC", torture_rpc_samsync, 0},
         {"RPC-SCHANNEL", torture_rpc_schannel, 0},
         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},