From a1318baa5503648ffcff2e9cd625b6848ad285b8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 6 Jun 2004 07:14:10 +0000 Subject: r1041: - pulled the domain join code out of the netlogon test and made it a separate utility function, to allow 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/librpc/rpc/dcerpc.h | 25 +++++++---- source4/librpc/rpc/dcerpc_schannel.c | 36 +++++++++------- source4/librpc/rpc/dcerpc_util.c | 84 ++++++++++++++++++++++-------------- 3 files changed, 88 insertions(+), 57 deletions(-) (limited to 'source4/librpc/rpc') diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 74bdaf878e..d81f0ab965 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -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 diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 61db90d1e3..f81429c1f3 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -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; } diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 623d5ec24a..c7edf043ec 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -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); -- cgit