summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-09-25 07:25:51 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:59:12 -0500
commit642ba4bfeee9951957287647628fa82269a318b1 (patch)
treeb235192d584c043bb592a499c167d4906b6b1cdb /source4
parent4fa2904290e2c345eae76ad66fc284b76eccd5f8 (diff)
downloadsamba-642ba4bfeee9951957287647628fa82269a318b1.tar.gz
samba-642ba4bfeee9951957287647628fa82269a318b1.tar.bz2
samba-642ba4bfeee9951957287647628fa82269a318b1.zip
r2614: support CONNECT level DCE/RPC security in both client and
server. CONNECT security uses NTLMSSP, but does not do any signing or sealing (or equivalently, its like signing, but with a zero filled checksum). (This used to be commit f4660857bc708db7f5aa7487bf7ab04bffe68928)
Diffstat (limited to 'source4')
-rw-r--r--source4/librpc/rpc/dcerpc.c52
-rw-r--r--source4/librpc/rpc/dcerpc.h21
-rw-r--r--source4/librpc/rpc/dcerpc_ntlm.c4
-rw-r--r--source4/librpc/rpc/dcerpc_util.c11
-rw-r--r--source4/rpc_server/dcesrv_auth.c43
5 files changed, 108 insertions, 23 deletions
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index 99051e75b6..23e9f04d96 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -145,6 +145,32 @@ static NTSTATUS dcerpc_pull(struct dcerpc_pipe *p, DATA_BLOB *blob, TALLOC_CTX *
return ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
}
+/*
+ generate a CONNECT level verifier
+*/
+static NTSTATUS dcerpc_connect_verifier(TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
+{
+ *blob = data_blob_talloc(mem_ctx, NULL, 16);
+ if (blob->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ SIVAL(blob->data, 0, 1);
+ memset(blob->data+4, 0, 12);
+ return NT_STATUS_OK;
+}
+
+/*
+ generate a CONNECT level verifier
+*/
+static NTSTATUS dcerpc_check_connect_verifier(DATA_BLOB *blob)
+{
+ if (blob->length != 16 ||
+ IVAL(blob->data, 0) != 1) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
/*
parse a possibly signed blob into a dcerpc request packet structure
*/
@@ -158,7 +184,8 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
DATA_BLOB auth_blob;
/* non-signed packets are simpler */
- if (!p->security_state.auth_info || !p->security_state.generic_state) {
+ if (!p->security_state.auth_info ||
+ !p->security_state.generic_state) {
return dcerpc_pull(p, blob, mem_ctx, pkt);
}
@@ -181,6 +208,11 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
return status;
}
+ if (pkt->auth_length == 0 &&
+ p->security_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
+ return NT_STATUS_OK;
+ }
+
auth_blob.length = 8 + pkt->auth_length;
/* check for a valid length */
@@ -233,7 +265,11 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
blob->length - auth.credentials.length,
&auth.credentials);
break;
-
+
+ case DCERPC_AUTH_LEVEL_CONNECT:
+ status = dcerpc_check_connect_verifier(&auth.credentials);
+ break;
+
case DCERPC_AUTH_LEVEL_NONE:
break;
@@ -264,7 +300,8 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
DATA_BLOB creds2;
/* non-signed packets are simpler */
- if (!p->security_state.auth_info || !p->security_state.generic_state) {
+ if (!p->security_state.auth_info ||
+ !p->security_state.generic_state) {
return dcerpc_push_auth(blob, mem_ctx, pkt, p->security_state.auth_info);
}
@@ -297,6 +334,10 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
data_blob_clear(&p->security_state.auth_info->credentials);
break;
+ case DCERPC_AUTH_LEVEL_CONNECT:
+ status = dcerpc_connect_verifier(mem_ctx, &p->security_state.auth_info->credentials);
+ break;
+
case DCERPC_AUTH_LEVEL_NONE:
p->security_state.auth_info->credentials = data_blob(NULL, 0);
break;
@@ -351,6 +392,9 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
memcpy(blob->data + blob->length - creds2.length, creds2.data, creds2.length);
break;
+ case DCERPC_AUTH_LEVEL_CONNECT:
+ break;
+
case DCERPC_AUTH_LEVEL_NONE:
p->security_state.auth_info->credentials = data_blob(NULL, 0);
break;
@@ -1247,6 +1291,8 @@ uint32 dcerpc_auth_level(struct dcerpc_pipe *p)
auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
} else if (p->flags & DCERPC_SIGN) {
auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
+ } else if (p->flags & DCERPC_CONNECT) {
+ auth_level = DCERPC_AUTH_LEVEL_CONNECT;
} else {
auth_level = DCERPC_AUTH_LEVEL_NONE;
}
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 242a18368f..011d70ec0c 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -88,28 +88,29 @@ struct dcerpc_pipe {
#define DCERPC_DEBUG_VALIDATE_OUT (1<<3)
#define DCERPC_DEBUG_VALIDATE_BOTH (DCERPC_DEBUG_VALIDATE_IN | DCERPC_DEBUG_VALIDATE_OUT)
-#define DCERPC_SIGN (1<<4)
-#define DCERPC_SEAL (1<<5)
+#define DCERPC_CONNECT (1<<4)
+#define DCERPC_SIGN (1<<5)
+#define DCERPC_SEAL (1<<6)
-#define DCERPC_PUSH_BIGENDIAN (1<<6)
-#define DCERPC_PULL_BIGENDIAN (1<<7)
+#define DCERPC_PUSH_BIGENDIAN (1<<7)
+#define DCERPC_PULL_BIGENDIAN (1<<8)
-#define DCERPC_SCHANNEL_BDC (1<<8)
-#define DCERPC_SCHANNEL_WORKSTATION (1<<9)
-#define DCERPC_SCHANNEL_DOMAIN (1<<10)
+#define DCERPC_SCHANNEL_BDC (1<<9)
+#define DCERPC_SCHANNEL_WORKSTATION (1<<10)
+#define DCERPC_SCHANNEL_DOMAIN (1<<11)
#define DCERPC_SCHANNEL_ANY (DCERPC_SCHANNEL_BDC| \
DCERPC_SCHANNEL_DOMAIN| \
DCERPC_SCHANNEL_WORKSTATION)
/* use a 128 bit session key */
-#define DCERPC_SCHANNEL_128 (1<<11)
+#define DCERPC_SCHANNEL_128 (1<<12)
#define DCERPC_AUTH_OPTIONS (DCERPC_SEAL|DCERPC_SIGN|DCERPC_SCHANNEL_ANY)
/* check incoming pad bytes */
-#define DCERPC_DEBUG_PAD_CHECK (1<<12)
+#define DCERPC_DEBUG_PAD_CHECK (1<<13)
/* set LIBNDR_FLAG_REF_ALLOC flag when decoding NDR */
-#define DCERPC_NDR_REF_ALLOC (1<<13)
+#define DCERPC_NDR_REF_ALLOC (1<<14)
/*
this is used to find pointers to calls
diff --git a/source4/librpc/rpc/dcerpc_ntlm.c b/source4/librpc/rpc/dcerpc_ntlm.c
index eab80a333b..905be5b76c 100644
--- a/source4/librpc/rpc/dcerpc_ntlm.c
+++ b/source4/librpc/rpc/dcerpc_ntlm.c
@@ -33,6 +33,10 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p,
{
NTSTATUS status;
+ if (!(p->flags & (DCERPC_SIGN | DCERPC_SEAL))) {
+ p->flags |= DCERPC_CONNECT;
+ }
+
status = gensec_client_start(&p->security_state.generic_state);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status)));
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 2c9ae0354a..2a715eac1d 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -275,6 +275,7 @@ static const struct {
} ncacn_options[] = {
{"sign", DCERPC_SIGN},
{"seal", DCERPC_SEAL},
+ {"connect", DCERPC_CONNECT},
{"validate", DCERPC_DEBUG_VALIDATE_BOTH},
{"print", DCERPC_DEBUG_PRINT_BOTH},
{"padcheck", DCERPC_DEBUG_PAD_CHECK},
@@ -495,7 +496,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
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_SIGN | DCERPC_SEAL))) {
+ } 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);
@@ -548,12 +549,6 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
return status;
}
- /* it doesn't seem to work to do a null NTLMSSP session without either sign
- or seal, so force signing if we are doing ntlmssp */
- if (username && username[0] && !(binding->flags & (DCERPC_SIGN|DCERPC_SEAL))) {
- binding->flags |= DCERPC_SIGN;
- }
-
(*p)->flags = binding->flags;
/* remember the binding string for possible secondary connections */
@@ -562,7 +557,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p,
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_SIGN | DCERPC_SEAL))) {
+ } 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);
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index e2a798c1ae..bfdf557bdf 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -31,7 +31,8 @@ NTSTATUS dcesrv_crypto_select_type(struct dcesrv_connection *dce_conn,
{
NTSTATUS status;
if (auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
- auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+ auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_PRIVACY &&
+ auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_CONNECT) {
DEBUG(2,("auth_level %d not supported in dcesrv auth\n",
auth->auth_info->auth_level));
return NT_STATUS_INVALID_PARAMETER;
@@ -191,6 +192,34 @@ BOOL dcesrv_auth_auth3(struct dcesrv_call_state *call)
return True;
}
+
+/*
+ generate a CONNECT level verifier
+*/
+static NTSTATUS dcesrv_connect_verifier(TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
+{
+ *blob = data_blob_talloc(mem_ctx, NULL, 16);
+ if (blob->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ SIVAL(blob->data, 0, 1);
+ memset(blob->data+4, 0, 12);
+ return NT_STATUS_OK;
+}
+
+/*
+ generate a CONNECT level verifier
+*/
+static NTSTATUS dcesrv_check_connect_verifier(DATA_BLOB *blob)
+{
+ if (blob->length != 16 ||
+ IVAL(blob->data, 0) != 1) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
+
/*
check credentials on a request
*/
@@ -260,6 +289,10 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
&auth.credentials);
break;
+ case DCERPC_AUTH_LEVEL_CONNECT:
+ status = dcesrv_check_connect_verifier(&auth.credentials);
+ break;
+
default:
status = NT_STATUS_INVALID_LEVEL;
break;
@@ -340,7 +373,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
payload_length,
blob->data,
blob->length - dce_conn->auth_state.auth_info->credentials.length,
- &dce_conn->auth_state.auth_info->credentials);
+ &dce_conn->auth_state.auth_info->credentials);
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
@@ -353,6 +386,12 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
&dce_conn->auth_state.auth_info->credentials);
break;
+
+ case DCERPC_AUTH_LEVEL_CONNECT:
+ status = dcesrv_connect_verifier(call->mem_ctx,
+ &dce_conn->auth_state.auth_info->credentials);
+ break;
+
default:
status = NT_STATUS_INVALID_LEVEL;
break;