diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-11-11 23:24:30 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:43 -0500 |
commit | fd5135a63b4c81688c4e2d729380ca954f22286d (patch) | |
tree | 7179bf31f404359a702f94ed5db03a1a4732617c /source4 | |
parent | 32e368502d80517dd7b00c1c3bc8b042887d9db0 (diff) | |
download | samba-fd5135a63b4c81688c4e2d729380ca954f22286d.tar.gz samba-fd5135a63b4c81688c4e2d729380ca954f22286d.tar.bz2 samba-fd5135a63b4c81688c4e2d729380ca954f22286d.zip |
r3686: The results of some work on the NETLOGON pipe:
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)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/libcli/auth/credentials.h | 6 | ||||
-rw-r--r-- | source4/libcli/auth/gensec.h | 1 | ||||
-rw-r--r-- | source4/libcli/util/smbdes.c | 2 | ||||
-rw-r--r-- | source4/libcli/util/smbencrypt.c | 25 | ||||
-rw-r--r-- | source4/librpc/idl/netlogon.idl | 32 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_schannel.c | 67 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/schannel_state.c | 11 | ||||
-rw-r--r-- | source4/torture/config.mk | 1 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon.c | 76 | ||||
-rw-r--r-- | source4/torture/rpc/schannel.c | 98 | ||||
-rw-r--r-- | source4/torture/rpc/xplogin.c | 15 | ||||
-rw-r--r-- | source4/torture/torture.c | 1 |
12 files changed, 260 insertions, 75 deletions
diff --git a/source4/libcli/auth/credentials.h b/source4/libcli/auth/credentials.h index a6e119e1ad..30114fe7fa 100644 --- a/source4/libcli/auth/credentials.h +++ b/source4/libcli/auth/credentials.h @@ -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) diff --git a/source4/libcli/auth/gensec.h b/source4/libcli/auth/gensec.h index b2c685332b..23d9861cb7 100644 --- a/source4/libcli/auth/gensec.h +++ b/source4/libcli/auth/gensec.h @@ -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; diff --git a/source4/libcli/util/smbdes.c b/source4/libcli/util/smbdes.c index a7c8f760ea..4e4222b9e6 100644 --- a/source4/libcli/util/smbdes.c +++ b/source4/libcli/util/smbdes.c @@ -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]; diff --git a/source4/libcli/util/smbencrypt.c b/source4/libcli/util/smbencrypt.c index d327b53f9d..dac8674f03 100644 --- a/source4/libcli/util/smbencrypt.c +++ b/source4/libcli/util/smbencrypt.c @@ -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. diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl index f6677d9621..f55049d30e 100644 --- a/source4/librpc/idl/netlogon.idl +++ b/source4/librpc/idl/netlogon.idl @@ -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 */ diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index c0db63e8b8..1e1bdb8227 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -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 = { diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c index 8797ffa120..61e755bc0f 100644 --- a/source4/rpc_server/netlogon/schannel_state.c +++ b/source4/rpc_server/netlogon/schannel_state.c @@ -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); diff --git a/source4/torture/config.mk b/source4/torture/config.mk index cef76baac4..d939175bb3 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -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 diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index fe64727d79..9c87106550 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -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; } diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index 323adde534..7a9786fa2d 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -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; } diff --git a/source4/torture/rpc/xplogin.c b/source4/torture/rpc/xplogin.c index a3cca7003c..e0bb706255 100644 --- a/source4/torture/rpc/xplogin.c +++ b/source4/torture/rpc/xplogin.c @@ -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)) diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 975b83e6ad..4db4662f6c 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -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}, |