mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
r4627: - simplified the dcerpc auth code using a common function
- added support for "spnego" in binding strings. This enables SPNEGO auth in the dcerpc client code, using as many allter_context calls as are needed To try SPNEGO do this: smbtorture ncacn_ip_tcp:SERVER[spnego,seal] -Uadministrator%password RPC-SAMR (This used to be commit 9c0a3423f03111c110d21c0d3910e16aa1a8bf87)
This commit is contained in:
parent
f6596e4ae7
commit
5da3f75a59
@ -119,17 +119,21 @@ struct dcerpc_pipe {
|
||||
#define DCERPC_SCHANNEL_ANY (DCERPC_SCHANNEL_BDC| \
|
||||
DCERPC_SCHANNEL_DOMAIN| \
|
||||
DCERPC_SCHANNEL_WORKSTATION)
|
||||
/* use a 128 bit session key */
|
||||
#define DCERPC_SCHANNEL_128 (1<<12)
|
||||
|
||||
#define DCERPC_AUTH_OPTIONS (DCERPC_SEAL|DCERPC_SIGN|DCERPC_SCHANNEL_ANY)
|
||||
|
||||
/* use a 128 bit session key */
|
||||
#define DCERPC_SCHANNEL_128 (1<<12)
|
||||
|
||||
/* check incoming pad bytes */
|
||||
#define DCERPC_DEBUG_PAD_CHECK (1<<13)
|
||||
|
||||
/* set LIBNDR_FLAG_REF_ALLOC flag when decoding NDR */
|
||||
#define DCERPC_NDR_REF_ALLOC (1<<14)
|
||||
|
||||
/* enable spnego auth */
|
||||
#define DCERPC_AUTH_SPNEGO (1<<15)
|
||||
|
||||
/*
|
||||
this is used to find pointers to calls
|
||||
*/
|
||||
|
@ -30,45 +30,33 @@
|
||||
NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p,
|
||||
const char *uuid, uint_t version)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(p);
|
||||
NTSTATUS status;
|
||||
|
||||
mem_ctx = talloc_init("dcerpc_bind_auth_ntlm");
|
||||
if (!mem_ctx) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version);
|
||||
talloc_destroy(mem_ctx);
|
||||
status = dcerpc_bind_byuuid(p, tmp_ctx, uuid, version);
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level,
|
||||
/*
|
||||
perform a multi-part authenticated bind
|
||||
*/
|
||||
NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level,
|
||||
const char *uuid, uint_t version)
|
||||
{
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(p);
|
||||
DATA_BLOB credentials;
|
||||
DATA_BLOB null_data_blob = data_blob(NULL, 0);
|
||||
|
||||
mem_ctx = talloc_init("dcerpc_bind_auth");
|
||||
if (!mem_ctx) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!p->conn->security_state.generic_state) {
|
||||
status = gensec_client_start(p, &p->conn->security_state.generic_state);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) goto done;
|
||||
|
||||
status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state,
|
||||
auth_type, auth_level);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) goto done;
|
||||
}
|
||||
|
||||
p->conn->security_state.auth_info = talloc(p, struct dcerpc_auth);
|
||||
@ -84,34 +72,44 @@ NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut
|
||||
p->conn->security_state.auth_info->auth_context_id = random();
|
||||
p->conn->security_state.auth_info->credentials = null_data_blob;
|
||||
|
||||
status = gensec_update(p->conn->security_state.generic_state, mem_ctx,
|
||||
status = gensec_update(p->conn->security_state.generic_state, tmp_ctx,
|
||||
null_data_blob,
|
||||
&credentials);
|
||||
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
p->conn->security_state.auth_info->credentials = credentials;
|
||||
|
||||
status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version);
|
||||
status = dcerpc_bind_byuuid(p, tmp_ctx, uuid, version);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = gensec_update(p->conn->security_state.generic_state, mem_ctx,
|
||||
status = gensec_update(p->conn->security_state.generic_state, tmp_ctx,
|
||||
p->conn->security_state.auth_info->credentials,
|
||||
&credentials);
|
||||
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
p->conn->security_state.auth_info->credentials = credentials;
|
||||
|
||||
status = dcerpc_auth3(p->conn, mem_ctx);
|
||||
do {
|
||||
p->conn->security_state.auth_info->credentials = credentials;
|
||||
|
||||
if (auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
|
||||
status = dcerpc_alter_context(p, tmp_ctx, &p->syntax, &p->transfer_syntax);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
status = gensec_update(p->conn->security_state.generic_state, tmp_ctx,
|
||||
p->conn->security_state.auth_info->credentials,
|
||||
&credentials);
|
||||
}
|
||||
} else {
|
||||
status = dcerpc_auth3(p->conn, tmp_ctx);
|
||||
}
|
||||
} while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
|
||||
|
||||
done:
|
||||
talloc_destroy(mem_ctx);
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(p->conn->security_state.generic_state);
|
||||
@ -123,3 +121,4 @@ done:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -72,9 +72,9 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p,
|
||||
return status;
|
||||
}
|
||||
|
||||
status = dcerpc_bind_auth3(p, DCERPC_AUTH_TYPE_NTLMSSP,
|
||||
dcerpc_auth_level(p->conn),
|
||||
uuid, version);
|
||||
status = dcerpc_bind_auth(p, DCERPC_AUTH_TYPE_NTLMSSP,
|
||||
dcerpc_auth_level(p->conn),
|
||||
uuid, version);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(2, ("Failed to bind to pipe with NTLMSSP: %s\n", nt_errstr(status)));
|
||||
|
@ -448,8 +448,8 @@ NTSTATUS dcerpc_bind_auth_schannel_withkey(struct dcerpc_pipe *p,
|
||||
dce_schan_state = p->conn->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->conn),
|
||||
uuid, version);
|
||||
status = dcerpc_bind_auth(p, DCERPC_AUTH_TYPE_SCHANNEL, dcerpc_auth_level(p->conn),
|
||||
uuid, version);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to bind to pipe with SCHANNEL: %s\n", nt_errstr(status)));
|
||||
|
@ -24,22 +24,21 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if 0
|
||||
/*
|
||||
metze, can you tell me what you're trying to do with this?
|
||||
*/
|
||||
|
||||
/*
|
||||
do spnego style authentication on a gensec pipe
|
||||
*/
|
||||
NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p,
|
||||
const char *uuid, uint_t version,
|
||||
const char *domain,
|
||||
const char *username,
|
||||
const char *password)
|
||||
const char *uuid, uint_t version,
|
||||
const char *domain,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(p->conn->flags & (DCERPC_SIGN | DCERPC_SEAL))) {
|
||||
p->conn->flags |= DCERPC_CONNECT;
|
||||
}
|
||||
|
||||
status = gensec_client_start(p, &p->conn->security_state.generic_state);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status)));
|
||||
@ -84,10 +83,9 @@ NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p,
|
||||
return status;
|
||||
}
|
||||
|
||||
status = dcerpc_bind_alter(p, DCERPC_AUTH_TYPE_SPNEGO,
|
||||
dcerpc_auth_level(p->conn),
|
||||
uuid, version);
|
||||
|
||||
status = dcerpc_bind_auth(p, DCERPC_AUTH_TYPE_SPNEGO,
|
||||
dcerpc_auth_level(p->conn),
|
||||
uuid, version);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(2, ("Failed to bind to pipe with SPNEGO: %s\n", nt_errstr(status)));
|
||||
return status;
|
||||
@ -95,4 +93,3 @@ NTSTATUS dcerpc_bind_auth_spnego(struct dcerpc_pipe *p,
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
@ -176,6 +176,7 @@ static const struct {
|
||||
{"sign", DCERPC_SIGN},
|
||||
{"seal", DCERPC_SEAL},
|
||||
{"connect", DCERPC_CONNECT},
|
||||
{"spnego", DCERPC_AUTH_SPNEGO},
|
||||
{"validate", DCERPC_DEBUG_VALIDATE_BOTH},
|
||||
{"print", DCERPC_DEBUG_PRINT_BOTH},
|
||||
{"padcheck", DCERPC_DEBUG_PAD_CHECK},
|
||||
@ -772,6 +773,42 @@ NTSTATUS dcerpc_epm_map_binding(TALLOC_CTX *mem_ctx, struct dcerpc_binding *bind
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
perform an authenticated bind if needed
|
||||
*/
|
||||
static NTSTATUS dcerpc_pipe_auth(struct dcerpc_pipe *p,
|
||||
struct dcerpc_binding *binding,
|
||||
const char *pipe_uuid,
|
||||
uint32_t pipe_version,
|
||||
const char *domain,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
p->conn->flags = binding->flags;
|
||||
|
||||
/* remember the binding string for possible secondary connections */
|
||||
p->conn->binding_string = dcerpc_binding_string(p, binding);
|
||||
|
||||
if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) {
|
||||
status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version,
|
||||
domain, username, password);
|
||||
} else if (username && username[0] && (binding->flags & DCERPC_AUTH_SPNEGO)) {
|
||||
status = dcerpc_bind_auth_spnego(p, pipe_uuid, pipe_version, domain, username, password);
|
||||
} else if (username && username[0]) {
|
||||
status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password);
|
||||
} else {
|
||||
status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* open a rpc connection to a rpc pipe on SMB using the binding
|
||||
structure to determine the endpoint and options */
|
||||
static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp,
|
||||
@ -846,24 +883,8 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **pp,
|
||||
return status;
|
||||
}
|
||||
|
||||
p->conn->flags = binding->flags;
|
||||
|
||||
/* remember the binding string for possible secondary connections */
|
||||
p->conn->binding_string = dcerpc_binding_string(p, binding);
|
||||
|
||||
if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) {
|
||||
status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version,
|
||||
domain, username, password);
|
||||
} else if (username && username[0] &&
|
||||
(binding->flags & (DCERPC_CONNECT|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);
|
||||
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
|
||||
talloc_free(p);
|
||||
return status;
|
||||
}
|
||||
@ -916,22 +937,8 @@ static NTSTATUS dcerpc_pipe_connect_ncalrpc(struct dcerpc_pipe **pp,
|
||||
return status;
|
||||
}
|
||||
|
||||
p->conn->flags = binding->flags;
|
||||
|
||||
/* remember the binding string for possible secondary connections */
|
||||
p->conn->binding_string = dcerpc_binding_string(p, binding);
|
||||
|
||||
if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) {
|
||||
status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version,
|
||||
domain, username, password);
|
||||
} else if (username && username[0]) {
|
||||
status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password);
|
||||
} else {
|
||||
status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version);
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
|
||||
talloc_free(p);
|
||||
return status;
|
||||
}
|
||||
@ -977,22 +984,8 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_unix_stream(struct dcerpc_pipe **pp,
|
||||
return status;
|
||||
}
|
||||
|
||||
p->conn->flags = binding->flags;
|
||||
|
||||
/* remember the binding string for possible secondary connections */
|
||||
p->conn->binding_string = dcerpc_binding_string(p, binding);
|
||||
|
||||
if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) {
|
||||
status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version,
|
||||
domain, username, password);
|
||||
} else if (username && username[0]) {
|
||||
status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password);
|
||||
} else {
|
||||
status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version);
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status)));
|
||||
talloc_free(p);
|
||||
return status;
|
||||
}
|
||||
@ -1047,23 +1040,8 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **pp,
|
||||
return status;
|
||||
}
|
||||
|
||||
p->conn->flags = binding->flags;
|
||||
|
||||
/* remember the binding string for possible secondary connections */
|
||||
p->conn->binding_string = dcerpc_binding_string(p, binding);
|
||||
|
||||
if (username && username[0] && (binding->flags & DCERPC_SCHANNEL_ANY)) {
|
||||
status = dcerpc_bind_auth_schannel(p, pipe_uuid, pipe_version,
|
||||
domain, username, password);
|
||||
} else if (username && username[0]) {
|
||||
status = dcerpc_bind_auth_ntlm(p, pipe_uuid, pipe_version, domain, username, password);
|
||||
} else {
|
||||
status = dcerpc_bind_auth_none(p, pipe_uuid, pipe_version);
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_auth(p, binding, pipe_uuid, pipe_version, domain, username, password);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to bind to uuid %s - %s\n",
|
||||
pipe_uuid, nt_errstr(status)));
|
||||
talloc_free(p);
|
||||
return status;
|
||||
}
|
||||
@ -1171,7 +1149,6 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe *
|
||||
if (!tree) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
status = dcerpc_pipe_open_smb((*p2)->conn, tree, pipe_name);
|
||||
break;
|
||||
|
||||
@ -1180,7 +1157,6 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe *
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
b.flags &= ~DCERPC_AUTH_OPTIONS;
|
||||
status = dcerpc_pipe_open_tcp((*p2)->conn, b.host, atoi(b.endpoint));
|
||||
break;
|
||||
|
||||
@ -1189,7 +1165,6 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe *
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
b.flags &= ~DCERPC_AUTH_OPTIONS;
|
||||
status = dcerpc_pipe_open_pipe((*p2)->conn, b.endpoint);
|
||||
break;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user