[Patches] The way to remove gensec_update_ev()
Stefan Metzmacher
metze at samba.org
Wed May 17 12:43:11 UTC 2017
Hi,
here's the next chunk on top.
Both are combined the following branch:
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-gensec-ok
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-gensec-tmp
contains the change for the LDAP server, which also pass a private
autobuild, but it needs some more tests to be written.
While
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-gensec
contains the unfinished parts:
- source4/libcli/smb_composite/sesssetup.c
- source4/lib/http/http_auth.c
- auth/gensec/spnego.c
While auth/gensec/spnego.c is the most difficult and time consuming part.
Please review and push:-)
Thanks!
metze
> I'm currently working on the removal of gensec_update_ev(),
> which relies on nested event loops to be activated.
>
> If we want to have proper support for trusted domains in the
> as AD DC, we need to use real async authentication because
> we still use a single process model for the rpc server.
>
> So the first step is to make all users of gensec_update_ev()
> use gensec_update_send/recv instead.
>
> Once we have that we need to make the low level auth stack async
> for NTLMSSP (as a server) and Kerberos (as a client).
>
> Here's the first chunk of patches, they passed a private autobuild.
>
> Please review and push:-)
-------------- next part --------------
From 76a4a6db252100f82d6f7449da69e45960b67401 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 14:15:41 +0200
Subject: [PATCH 01/24] s4:rpc_server: introduce call->ack_pkt and avoid pkt
variable for the response on the stack
This will be needed when we use async authentication using gensec_update_send/recv.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 64 +++++++++++++++++++-------------------
source4/rpc_server/dcerpc_server.h | 5 +++
2 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 9f62c11..a9f8854 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -773,7 +773,7 @@ _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *
*/
static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
{
- struct ncacn_packet pkt;
+ struct ncacn_packet *pkt = &call->ack_pkt;
struct data_blob_list_item *rep;
NTSTATUS status;
uint32_t extra_flags = 0;
@@ -984,14 +984,14 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
}
/* setup a bind_ack */
- dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
- pkt.auth_length = 0;
- pkt.call_id = call->pkt.call_id;
- pkt.ptype = DCERPC_PKT_BIND_ACK;
- pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
- pkt.u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
- pkt.u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
- pkt.u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
+ dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+ pkt->auth_length = 0;
+ pkt->call_id = call->pkt.call_id;
+ pkt->ptype = DCERPC_PKT_BIND_ACK;
+ pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
+ pkt->u.bind_ack.max_xmit_frag = call->conn->max_xmit_frag;
+ pkt->u.bind_ack.max_recv_frag = call->conn->max_recv_frag;
+ pkt->u.bind_ack.assoc_group_id = call->conn->assoc_group->id;
endpoint = dcerpc_binding_get_string_option(
call->conn->endpoint->ep_description,
@@ -1010,18 +1010,18 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
endpoint += 6;
}
- pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
+ pkt->u.bind_ack.secondary_address = talloc_asprintf(call, "%s%s",
ep_prefix,
endpoint);
- if (pkt.u.bind_ack.secondary_address == NULL) {
+ if (pkt->u.bind_ack.secondary_address == NULL) {
TALLOC_FREE(call->context);
return NT_STATUS_NO_MEMORY;
}
- pkt.u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
- pkt.u.bind_ack.ctx_list = ack_ctx_list;
- pkt.u.bind_ack.auth_info = data_blob_null;
+ pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
+ pkt->u.bind_ack.ctx_list = ack_ctx_list;
+ pkt->u.bind_ack.auth_info = data_blob_null;
- status = dcesrv_auth_bind_ack(call, &pkt);
+ status = dcesrv_auth_bind_ack(call, pkt);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(call->context);
return dcesrv_bind_nak(call, 0);
@@ -1033,7 +1033,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
return NT_STATUS_NO_MEMORY;
}
- status = ncacn_push_auth(&rep->blob, call, &pkt,
+ status = ncacn_push_auth(&rep->blob, call, pkt,
call->out_auth_info);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(call->context);
@@ -1337,7 +1337,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
{
NTSTATUS status;
bool auth_ok = false;
- struct ncacn_packet pkt;
+ struct ncacn_packet *pkt = &call->ack_pkt;
uint32_t extra_flags = 0;
struct data_blob_list_item *rep = NULL;
struct dcerpc_ack_ctx *ack_ctx_list = NULL;
@@ -1430,20 +1430,20 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
}
- dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
- pkt.auth_length = 0;
- pkt.call_id = call->pkt.call_id;
- pkt.ptype = DCERPC_PKT_ALTER_RESP;
- pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
- pkt.u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
- pkt.u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
- pkt.u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
- pkt.u.alter_resp.secondary_address = "";
- pkt.u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
- pkt.u.alter_resp.ctx_list = ack_ctx_list;
- pkt.u.alter_resp.auth_info = data_blob_null;
-
- status = dcesrv_auth_alter_ack(call, &pkt);
+ dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+ pkt->auth_length = 0;
+ pkt->call_id = call->pkt.call_id;
+ pkt->ptype = DCERPC_PKT_ALTER_RESP;
+ pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
+ pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
+ pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
+ pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
+ pkt->u.alter_resp.secondary_address = "";
+ pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
+ pkt->u.alter_resp.ctx_list = ack_ctx_list;
+ pkt->u.alter_resp.auth_info = data_blob_null;
+
+ status = dcesrv_auth_alter_ack(call, pkt);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
}
@@ -1453,7 +1453,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
return NT_STATUS_NO_MEMORY;
}
- status = ncacn_push_auth(&rep->blob, call, &pkt, call->out_auth_info);
+ status = ncacn_push_auth(&rep->blob, call, pkt, call->out_auth_info);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index 89377ab..9a64341 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -93,6 +93,11 @@ struct dcesrv_call_state {
struct ncacn_packet pkt;
/*
+ * Used during async bind/alter_context.
+ */
+ struct ncacn_packet ack_pkt;
+
+ /*
which list this request is in, if any
*/
enum dcesrv_call_list list;
--
1.9.1
From 2dae7992a0be8cce86e47fbd0c01d2c541114832 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 08:11:29 +0200
Subject: [PATCH 02/24] s4:rpc_server: add wait_send/recv infrastructure
This will be used to implement async BIND/ALTER_CONTEXT/AUTH3
using gensec_update_send/recv.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 63 ++++++++++++++++++++++++++++++++++++++
source4/rpc_server/dcerpc_server.h | 10 ++++++
2 files changed, 73 insertions(+)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index a9f8854..0a8e7e5 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -2160,6 +2160,10 @@ static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, cons
srv_conn = talloc_get_type(dce_conn->transport.private_data,
struct stream_connection);
+ dce_conn->wait_send = NULL;
+ dce_conn->wait_recv = NULL;
+ dce_conn->wait_private = NULL;
+
dce_conn->allow_bind = false;
dce_conn->allow_auth3 = false;
dce_conn->allow_alter = false;
@@ -2513,6 +2517,8 @@ static void dcesrv_sock_accept(struct stream_connection *srv_conn)
return;
}
+static void dcesrv_conn_wait_done(struct tevent_req *subreq);
+
static void dcesrv_read_fragment_done(struct tevent_req *subreq)
{
struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
@@ -2548,6 +2554,63 @@ static void dcesrv_read_fragment_done(struct tevent_req *subreq)
return;
}
+ /*
+ * This is used to block the connection during
+ * pending authentication.
+ */
+ if (dce_conn->wait_send != NULL) {
+ subreq = dce_conn->wait_send(dce_conn,
+ dce_conn->event_ctx,
+ dce_conn->wait_private);
+ if (!subreq) {
+ status = NT_STATUS_NO_MEMORY;
+ dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+ return;
+ }
+ tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
+ return;
+ }
+
+ subreq = dcerpc_read_ncacn_packet_send(dce_conn,
+ dce_conn->event_ctx,
+ dce_conn->stream);
+ if (!subreq) {
+ status = NT_STATUS_NO_MEMORY;
+ dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+ return;
+ }
+ tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
+}
+
+static void dcesrv_conn_wait_done(struct tevent_req *subreq)
+{
+ struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
+ struct dcesrv_connection);
+ struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
+ NTSTATUS status;
+
+ if (dce_conn->terminate) {
+ /*
+ * if the current connection is broken
+ * we need to clean it up before any other connection
+ */
+ dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
+ dcesrv_cleanup_broken_connections(dce_ctx);
+ return;
+ }
+
+ dcesrv_cleanup_broken_connections(dce_ctx);
+
+ status = dce_conn->wait_recv(subreq);
+ dce_conn->wait_send = NULL;
+ dce_conn->wait_recv = NULL;
+ dce_conn->wait_private = NULL;
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ dcesrv_terminate_connection(dce_conn, nt_errstr(status));
+ return;
+ }
+
subreq = dcerpc_read_ncacn_packet_send(dce_conn,
dce_conn->event_ctx,
dce_conn->stream);
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index 9a64341..c038075 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -288,6 +288,16 @@ struct dcesrv_connection {
/* the negotiated bind time features */
uint16_t bind_time_features;
+
+ /*
+ * This is used to block the connection during
+ * pending authentication.
+ */
+ struct tevent_req *(*wait_send)(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data);
+ NTSTATUS (*wait_recv)(struct tevent_req *req);
+ void *wait_private;
};
--
1.9.1
From cd3bd5fbb808d7288f53a608dfab737ae90dd203 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 09:00:45 +0200
Subject: [PATCH 03/24] s4:rpc_server: split out dcesrv_auth_complete() from
dcesrv_auth_bind_ack()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 67 +++++++++++++++++++++++++++-------------
1 file changed, 46 insertions(+), 21 deletions(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 7b63598..3fda2aa 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -241,6 +241,51 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
return true;
}
+NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
+{
+ struct dcesrv_connection *dce_conn = call->conn;
+ const char *pdu = "<unknown>";
+
+ switch (call->pkt.ptype) {
+ case DCERPC_PKT_BIND:
+ pdu = "BIND";
+ break;
+ case DCERPC_PKT_ALTER:
+ pdu = "ALTER";
+ break;
+ case DCERPC_PKT_AUTH3:
+ pdu = "AUTH3";
+ break;
+ default:
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(4, ("GENSEC mech rejected the incoming authentication "
+ "at %s: %s\n", pdu, nt_errstr(status)));
+ return status;
+ }
+
+ status = gensec_session_info(dce_conn->auth_state.gensec_security,
+ dce_conn,
+ &dce_conn->auth_state.session_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to establish session_info: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+ dce_conn->auth_state.auth_finished = true;
+ dce_conn->allow_request = true;
+
+ /* Now that we are authenticated, go back to the generic session key... */
+ dce_conn->auth_state.session_key = dcesrv_generic_session_key;
+ return NT_STATUS_OK;
+}
+
/*
add any auth information needed in a bind ack, and process the authentication
information found in the bind.
@@ -279,28 +324,8 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
call, call->event_ctx,
call->in_auth_info.credentials,
&call->out_auth_info->credentials);
-
- if (NT_STATUS_IS_OK(status)) {
- status = gensec_session_info(dce_conn->auth_state.gensec_security,
- dce_conn,
- &dce_conn->auth_state.session_info);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
- return status;
- }
- dce_conn->auth_state.auth_finished = true;
- dce_conn->allow_request = true;
- /* Now that we are authenticated, go back to the generic session key... */
- dce_conn->auth_state.session_key = dcesrv_generic_session_key;
- return NT_STATUS_OK;
- } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- return NT_STATUS_OK;
- } else {
- DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_ack: %s\n",
- nt_errstr(status)));
- return status;
- }
+ return dcesrv_auth_complete(call, status);
}
--
1.9.1
From 4dd75d3f43e8ccb6d8fee15a6e9637017cb34b56 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 09:14:21 +0200
Subject: [PATCH 04/24] s4:rpc_server: make use of dcesrv_auth_complete() in
dcesrv_auth_alter_ack()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 22 +---------------------
1 file changed, 1 insertion(+), 21 deletions(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 3fda2aa..3eeba2b 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -501,27 +501,7 @@ NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_pack
call->in_auth_info.credentials,
&call->out_auth_info->credentials);
- if (NT_STATUS_IS_OK(status)) {
- status = gensec_session_info(dce_conn->auth_state.gensec_security,
- dce_conn,
- &dce_conn->auth_state.session_info);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
- return status;
- }
- dce_conn->auth_state.auth_finished = true;
- dce_conn->allow_request = true;
-
- /* Now that we are authenticated, got back to the generic session key... */
- dce_conn->auth_state.session_key = dcesrv_generic_session_key;
- return NT_STATUS_OK;
- } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- return NT_STATUS_OK;
- }
-
- DEBUG(4, ("GENSEC mech rejected the incoming authentication at auth alter_ack: %s\n",
- nt_errstr(status)));
- return status;
+ return dcesrv_auth_complete(call, status);
}
/*
--
1.9.1
From 8ecf824614544256fafee0d7441a566c20d24ad7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 09:13:08 +0200
Subject: [PATCH 05/24] s4:rpc_server: prepare dcesrv_auth_complete() for AUTH3
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 3eeba2b..2a5271f 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -255,6 +255,10 @@ NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
break;
case DCERPC_PKT_AUTH3:
pdu = "AUTH3";
+ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ DEBUG(4, ("GENSEC not finished at at %s\n", pdu));
+ return NT_STATUS_RPC_SEC_PKG_ERROR;
+ }
break;
default:
return NT_STATUS_INTERNAL_ERROR;
@@ -283,6 +287,17 @@ NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
/* Now that we are authenticated, go back to the generic session key... */
dce_conn->auth_state.session_key = dcesrv_generic_session_key;
+
+ if (call->pkt.ptype != DCERPC_PKT_AUTH3) {
+ return NT_STATUS_OK;
+ }
+
+ if (call->out_auth_info->credentials.length != 0) {
+ DEBUG(4, ("GENSEC produced output token (len=%zu) at %s\n",
+ call->out_auth_info->credentials.length, pdu));
+ return NT_STATUS_RPC_SEC_PKG_ERROR;
+ }
+
return NT_STATUS_OK;
}
--
1.9.1
From 8976ff195ab91b861c2387be060045ccec8a1a90 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 09:13:08 +0200
Subject: [PATCH 06/24] s4:rpc_server: make use of dcesrv_auth_complete() in
dcesrv_auth_auth3()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 27 ++++-----------------------
1 file changed, 4 insertions(+), 23 deletions(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 2a5271f..5e3df04 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -401,32 +401,13 @@ bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
call, call->event_ctx,
call->in_auth_info.credentials,
&call->out_auth_info->credentials);
- if (NT_STATUS_IS_OK(status)) {
- status = gensec_session_info(dce_conn->auth_state.gensec_security,
- dce_conn,
- &dce_conn->auth_state.session_info);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
- return false;
- }
- dce_conn->auth_state.auth_finished = true;
- dce_conn->allow_request = true;
-
- /* Now that we are authenticated, go back to the generic session key... */
- dce_conn->auth_state.session_key = dcesrv_generic_session_key;
-
- if (call->out_auth_info->credentials.length != 0) {
- DEBUG(4, ("GENSEC produced output token (len=%u) at bind_auth3\n",
- (unsigned)call->out_auth_info->credentials.length));
- return false;
- }
- return true;
- } else {
- DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_auth3: %s\n",
- nt_errstr(status)));
+ status = dcesrv_auth_complete(call, status);
+ if (!NT_STATUS_IS_OK(status)) {
return false;
}
+
+ return true;
}
/*
--
1.9.1
From c1fb11d985d8a69c0f8ab166ce7a04d890a33d9c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 12:16:35 +0200
Subject: [PATCH 07/24] s4:rpc_server: split out dcesrv_auth_prepare_bind_ack()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 5e3df04..ae3cebc 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -305,10 +305,9 @@ NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
add any auth information needed in a bind ack, and process the authentication
information found in the bind.
*/
-NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
+NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
{
struct dcesrv_connection *dce_conn = call->conn;
- NTSTATUS status;
dce_conn->allow_alter = true;
dce_conn->allow_auth3 = true;
@@ -335,6 +334,23 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
};
call->out_auth_info = &call->_out_auth_info;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
+{
+ struct dcesrv_connection *dce_conn = call->conn;
+ NTSTATUS status;
+
+ status = dcesrv_auth_prepare_bind_ack(call, pkt);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (dce_conn->auth_state.auth_finished) {
+ return NT_STATUS_OK;
+ }
+
status = gensec_update_ev(dce_conn->auth_state.gensec_security,
call, call->event_ctx,
call->in_auth_info.credentials,
--
1.9.1
From 087dd09b0ca8916148ebb3ba0f3ffd396aa7ae0c Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 12:16:35 +0200
Subject: [PATCH 08/24] s4:rpc_server: split out dcesrv_auth_prepare_auth3()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index ae3cebc..502173a 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -363,7 +363,7 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe
/*
process the final stage of a auth request
*/
-bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
+bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
{
struct ncacn_packet *pkt = &call->pkt;
struct dcesrv_connection *dce_conn = call->conn;
@@ -412,6 +412,20 @@ bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
};
call->out_auth_info = &call->_out_auth_info;
+ return true;
+}
+
+bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
+{
+ struct dcesrv_connection *dce_conn = call->conn;
+ NTSTATUS status;
+ bool ok;
+
+ ok = dcesrv_auth_prepare_auth3(call);
+ if (!ok) {
+ return false;
+ }
+
/* Pass the extra data we got from the client down to gensec for processing */
status = gensec_update_ev(dce_conn->auth_state.gensec_security,
call, call->event_ctx,
--
1.9.1
From 6a9891118b689f81c3d21e5de937d456ace7e243 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 12:16:35 +0200
Subject: [PATCH 09/24] s4:rpc_server: split out
dcesrv_auth_prepare_alter_ack()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 502173a..108d268 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -500,10 +500,9 @@ bool dcesrv_auth_alter(struct dcesrv_call_state *call)
add any auth information needed in a alter ack, and process the authentication
information found in the alter.
*/
-NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
+NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
{
struct dcesrv_connection *dce_conn = call->conn;
- NTSTATUS status;
/* on a pure interface change there is no auth_info structure
setup */
@@ -522,6 +521,23 @@ NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_pack
};
call->out_auth_info = &call->_out_auth_info;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
+{
+ struct dcesrv_connection *dce_conn = call->conn;
+ NTSTATUS status;
+
+ status = dcesrv_auth_prepare_alter_ack(call, pkt);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (dce_conn->auth_state.auth_finished) {
+ return NT_STATUS_OK;
+ }
+
status = gensec_update_ev(dce_conn->auth_state.gensec_security,
call, call->event_ctx,
call->in_auth_info.credentials,
--
1.9.1
From 5bc31a79a2eb62fc56816c24bdf7193769d7a027 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 17:36:17 +0200
Subject: [PATCH 10/24] s4:rpc_server: remove useless
TALLOC_FREE(call->context) from dcesrv_bind()
This is not needed if we're terminating the connection anyway.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 0a8e7e5..34de071 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -965,8 +965,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
if (!dcesrv_auth_bind(call)) {
struct dcesrv_auth *auth = &call->conn->auth_state;
- TALLOC_FREE(call->context);
-
if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
/*
* With DCERPC_AUTH_LEVEL_NONE, we get the
@@ -1014,7 +1012,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
ep_prefix,
endpoint);
if (pkt->u.bind_ack.secondary_address == NULL) {
- TALLOC_FREE(call->context);
return NT_STATUS_NO_MEMORY;
}
pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
@@ -1023,20 +1020,17 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
status = dcesrv_auth_bind_ack(call, pkt);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(call->context);
return dcesrv_bind_nak(call, 0);
}
rep = talloc_zero(call, struct data_blob_list_item);
if (!rep) {
- TALLOC_FREE(call->context);
return NT_STATUS_NO_MEMORY;
}
status = ncacn_push_auth(&rep->blob, call, pkt,
call->out_auth_info);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(call->context);
return status;
}
--
1.9.1
From 63babe07a3ef9c3cadadd2294b1af3396073eb9f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 17:19:31 +0200
Subject: [PATCH 11/24] s4:rpc_server: split out dcesrv_auth_reply() from
dcesrv_bind()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 34de071..f89a3fa 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -768,13 +768,14 @@ _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *
return NT_STATUS_OK;
}
+static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
+
/*
handle a bind request
*/
static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
{
struct ncacn_packet *pkt = &call->ack_pkt;
- struct data_blob_list_item *rep;
NTSTATUS status;
uint32_t extra_flags = 0;
uint16_t max_req = 0;
@@ -1023,6 +1024,15 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
return dcesrv_bind_nak(call, 0);
}
+ return dcesrv_auth_reply(call);
+}
+
+static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
+{
+ struct ncacn_packet *pkt = &call->ack_pkt;
+ struct data_blob_list_item *rep = NULL;
+ NTSTATUS status;
+
rep = talloc_zero(call, struct data_blob_list_item);
if (!rep) {
return NT_STATUS_NO_MEMORY;
--
1.9.1
From c2bd66ccbc1e2c55cebe8304dc8e91c5ccb32a8f Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 17:37:05 +0200
Subject: [PATCH 12/24] s4:rpc_server: make use of dcesrv_auth_reply() in
dcesrv_alter()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 24 +-----------------------
1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index f89a3fa..c2b531f 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -1343,7 +1343,6 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
bool auth_ok = false;
struct ncacn_packet *pkt = &call->ack_pkt;
uint32_t extra_flags = 0;
- struct data_blob_list_item *rep = NULL;
struct dcerpc_ack_ctx *ack_ctx_list = NULL;
size_t i;
@@ -1452,28 +1451,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
}
- rep = talloc_zero(call, struct data_blob_list_item);
- if (!rep) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = ncacn_push_auth(&rep->blob, call, pkt, call->out_auth_info);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- dcerpc_set_frag_length(&rep->blob, rep->blob.length);
-
- DLIST_ADD_END(call->replies, rep);
- dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
-
- if (call->conn->call_list && call->conn->call_list->replies) {
- if (call->conn->transport.report_output_data) {
- call->conn->transport.report_output_data(call->conn);
- }
- }
-
- return NT_STATUS_OK;
+ return dcesrv_auth_reply(call);
}
/*
--
1.9.1
From eca76a8949c53436e1d9a8ceb8d3faac9e965f01 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 14:02:07 +0200
Subject: [PATCH 13/24] s4:rpc_server: make use of
dcesrv_auth_prepare_bind_ack() in dcesrv_bind()
It means we also need to call gensec_update_ev() and dcesrv_auth_complete()
directly in dcesrv_bind(). Doing that will make it easier to make dcesrv_bind()
async in the next commits.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index c2b531f..2f322ce 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -782,6 +782,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
uint16_t max_rep = 0;
const char *ep_prefix = "";
const char *endpoint = NULL;
+ struct dcesrv_auth *auth = &call->conn->auth_state;
struct dcerpc_ack_ctx *ack_ctx_list = NULL;
struct dcerpc_ack_ctx *ack_features = NULL;
size_t i;
@@ -964,7 +965,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
* is being requested.
*/
if (!dcesrv_auth_bind(call)) {
- struct dcesrv_auth *auth = &call->conn->auth_state;
if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
/*
@@ -1019,7 +1019,21 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
pkt->u.bind_ack.ctx_list = ack_ctx_list;
pkt->u.bind_ack.auth_info = data_blob_null;
- status = dcesrv_auth_bind_ack(call, pkt);
+ status = dcesrv_auth_prepare_bind_ack(call, pkt);
+ if (!NT_STATUS_IS_OK(status)) {
+ return dcesrv_bind_nak(call, 0);
+ }
+
+ if (auth->auth_finished) {
+ return dcesrv_auth_reply(call);
+ }
+
+ status = gensec_update_ev(auth->gensec_security,
+ call, call->event_ctx,
+ call->in_auth_info.credentials,
+ &call->out_auth_info->credentials);
+
+ status = dcesrv_auth_complete(call, status);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_bind_nak(call, 0);
}
--
1.9.1
From f6894d56fa833cddaabb9744b0d36c94cc0245d1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 14:02:07 +0200
Subject: [PATCH 14/24] s4:rpc_server: make use of
dcesrv_auth_prepare_alter_ack() in dcesrv_alter()
It means we also need to call gensec_update_ev() and dcesrv_auth_complete()
directly in dcesrv_alter(). Doing that will make it easier to make dcesrv_alter()
async in the next commits.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 2f322ce..c650c63 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -1357,6 +1357,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
bool auth_ok = false;
struct ncacn_packet *pkt = &call->ack_pkt;
uint32_t extra_flags = 0;
+ struct dcesrv_auth *auth = &call->conn->auth_state;
struct dcerpc_ack_ctx *ack_ctx_list = NULL;
size_t i;
@@ -1460,7 +1461,21 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
pkt->u.alter_resp.ctx_list = ack_ctx_list;
pkt->u.alter_resp.auth_info = data_blob_null;
- status = dcesrv_auth_alter_ack(call, pkt);
+ status = dcesrv_auth_prepare_alter_ack(call, pkt);
+ if (!NT_STATUS_IS_OK(status)) {
+ return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
+ }
+
+ if (auth->auth_finished) {
+ return dcesrv_auth_reply(call);
+ }
+
+ status = gensec_update_ev(auth->gensec_security,
+ call, call->event_ctx,
+ call->in_auth_info.credentials,
+ &call->out_auth_info->credentials);
+
+ status = dcesrv_auth_complete(call, status);
if (!NT_STATUS_IS_OK(status)) {
return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
}
--
1.9.1
From 4e545ce7b4ecd9421dee8e3d1510b030a0dcbcd8 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 14:02:07 +0200
Subject: [PATCH 15/24] s4:rpc_server: make use of dcesrv_auth_prepare_auth3()
in dcesrv_auth3()
It means we also need to call gensec_update_ev() and dcesrv_auth_complete()
directly in dcesrv_auth3(). Doing that will make it easier to make dcesrv_auth3()
async in the next commits.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 40 ++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index c650c63..40b942a 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -1078,6 +1078,7 @@ static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
*/
static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
{
+ struct dcesrv_auth *auth = &call->conn->auth_state;
NTSTATUS status;
if (!call->conn->allow_auth3) {
@@ -1105,17 +1106,48 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
}
/* handle the auth3 in the auth code */
- if (!dcesrv_auth_auth3(call)) {
+ if (!dcesrv_auth_prepare_auth3(call)) {
+ /*
+ * we don't send a reply to a auth3 request,
+ * except by a fault.
+ *
+ * In anycase we mark the connection as
+ * invalid.
+ */
call->conn->auth_state.auth_invalid = true;
if (call->fault_code != 0) {
return dcesrv_fault_disconnect(call, call->fault_code);
}
+ TALLOC_FREE(call);
+ return NT_STATUS_OK;
}
- talloc_free(call);
+ status = gensec_update_ev(auth->gensec_security,
+ call, call->event_ctx,
+ call->in_auth_info.credentials,
+ &call->out_auth_info->credentials);
- /* we don't send a reply to a auth3 request, except by a
- fault */
+ status = dcesrv_auth_complete(call, status);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * we don't send a reply to a auth3 request,
+ * except by a fault.
+ *
+ * In anycase we mark the connection as
+ * invalid.
+ */
+ call->conn->auth_state.auth_invalid = true;
+ if (call->fault_code != 0) {
+ return dcesrv_fault_disconnect(call, call->fault_code);
+ }
+ TALLOC_FREE(call);
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * we don't send a reply to a auth3 request.
+ */
+ TALLOC_FREE(call);
return NT_STATUS_OK;
}
--
1.9.1
From 9d03195213b3994a23ffc1206f8e48843845a866 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 14:03:54 +0200
Subject: [PATCH 16/24] s4:rpc_server: remove unused
dcesrv_auth_{bind_ack,auth3,alter_ack}()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcesrv_auth.c | 70 ----------------------------------------
1 file changed, 70 deletions(-)
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 108d268..d48d03e 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -337,29 +337,6 @@ NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct nca
return NT_STATUS_OK;
}
-NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
-{
- struct dcesrv_connection *dce_conn = call->conn;
- NTSTATUS status;
-
- status = dcesrv_auth_prepare_bind_ack(call, pkt);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (dce_conn->auth_state.auth_finished) {
- return NT_STATUS_OK;
- }
-
- status = gensec_update_ev(dce_conn->auth_state.gensec_security,
- call, call->event_ctx,
- call->in_auth_info.credentials,
- &call->out_auth_info->credentials);
-
- return dcesrv_auth_complete(call, status);
-}
-
-
/*
process the final stage of a auth request
*/
@@ -415,31 +392,6 @@ bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
return true;
}
-bool dcesrv_auth_auth3(struct dcesrv_call_state *call)
-{
- struct dcesrv_connection *dce_conn = call->conn;
- NTSTATUS status;
- bool ok;
-
- ok = dcesrv_auth_prepare_auth3(call);
- if (!ok) {
- return false;
- }
-
- /* Pass the extra data we got from the client down to gensec for processing */
- status = gensec_update_ev(dce_conn->auth_state.gensec_security,
- call, call->event_ctx,
- call->in_auth_info.credentials,
- &call->out_auth_info->credentials);
-
- status = dcesrv_auth_complete(call, status);
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
-
- return true;
-}
-
/*
parse any auth information from a dcerpc alter request
return false if we can't handle the auth request for some
@@ -524,28 +476,6 @@ NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct nc
return NT_STATUS_OK;
}
-NTSTATUS dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
-{
- struct dcesrv_connection *dce_conn = call->conn;
- NTSTATUS status;
-
- status = dcesrv_auth_prepare_alter_ack(call, pkt);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- if (dce_conn->auth_state.auth_finished) {
- return NT_STATUS_OK;
- }
-
- status = gensec_update_ev(dce_conn->auth_state.gensec_security,
- call, call->event_ctx,
- call->in_auth_info.credentials,
- &call->out_auth_info->credentials);
-
- return dcesrv_auth_complete(call, status);
-}
-
/*
check credentials on a packet
*/
--
1.9.1
From 98ddc599709f4f2f50dac0460159f4cde6e2c692 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 15:20:56 +0200
Subject: [PATCH 17/24] s4:rpc_server: implement async BIND using
gensec_update_send/recv
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 125 +++++++++++++++++++++++++++++++++++--
1 file changed, 119 insertions(+), 6 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 40b942a..225f5e7 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -41,6 +41,7 @@
#include "librpc/rpc/rpc_common.h"
#include "lib/util/samba_modules.h"
#include "librpc/gen_ndr/ndr_dcerpc.h"
+#include "../lib/util/tevent_ntstatus.h"
static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
const struct dcerpc_bind *b,
@@ -768,13 +769,102 @@ _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *
return NT_STATUS_OK;
}
+struct dcesrv_conn_auth_wait_context {
+ struct tevent_req *req;
+ bool done;
+ NTSTATUS status;
+};
+
+struct dcesrv_conn_auth_wait_state {
+ uint8_t dummy;
+};
+
+static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data)
+{
+ struct dcesrv_conn_auth_wait_context *auth_wait =
+ talloc_get_type_abort(private_data,
+ struct dcesrv_conn_auth_wait_context);
+ struct tevent_req *req = NULL;
+ struct dcesrv_conn_auth_wait_state *state = NULL;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct dcesrv_conn_auth_wait_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ auth_wait->req = req;
+
+ tevent_req_defer_callback(req, ev);
+
+ if (!auth_wait->done) {
+ return req;
+ }
+
+ if (tevent_req_nterror(req, auth_wait->status)) {
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+}
+
+static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
+{
+ struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
+
+ if (conn->wait_send != NULL) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
+ if (auth_wait == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ conn->wait_private = auth_wait;
+ conn->wait_send = dcesrv_conn_auth_wait_send;
+ conn->wait_recv = dcesrv_conn_auth_wait_recv;
+ return NT_STATUS_OK;
+}
+
+static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
+ NTSTATUS status)
+{
+ struct dcesrv_conn_auth_wait_context *auth_wait =
+ talloc_get_type_abort(conn->wait_private,
+ struct dcesrv_conn_auth_wait_context);
+
+ auth_wait->done = true;
+ auth_wait->status = status;
+
+ if (auth_wait->req == NULL) {
+ return;
+ }
+
+ if (tevent_req_nterror(auth_wait->req, status)) {
+ return;
+ }
+
+ tevent_req_done(auth_wait->req);
+}
+
static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
+static void dcesrv_bind_done(struct tevent_req *subreq);
+
/*
handle a bind request
*/
static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
{
+ struct dcesrv_connection *conn = call->conn;
struct ncacn_packet *pkt = &call->ack_pkt;
NTSTATUS status;
uint32_t extra_flags = 0;
@@ -785,6 +875,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
struct dcesrv_auth *auth = &call->conn->auth_state;
struct dcerpc_ack_ctx *ack_ctx_list = NULL;
struct dcerpc_ack_ctx *ack_features = NULL;
+ struct tevent_req *subreq = NULL;
size_t i;
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
@@ -1028,17 +1119,39 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
return dcesrv_auth_reply(call);
}
- status = gensec_update_ev(auth->gensec_security,
- call, call->event_ctx,
- call->in_auth_info.credentials,
- &call->out_auth_info->credentials);
+ subreq = gensec_update_send(call, call->event_ctx,
+ auth->gensec_security,
+ call->in_auth_info.credentials);
+ if (subreq == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ tevent_req_set_callback(subreq, dcesrv_bind_done, call);
+
+ return dcesrv_conn_auth_wait_setup(conn);
+}
+
+static void dcesrv_bind_done(struct tevent_req *subreq)
+{
+ struct dcesrv_call_state *call =
+ tevent_req_callback_data(subreq,
+ struct dcesrv_call_state);
+ struct dcesrv_connection *conn = call->conn;
+ NTSTATUS status;
+
+ status = gensec_update_recv(subreq, call,
+ &call->out_auth_info->credentials);
+ TALLOC_FREE(subreq);
status = dcesrv_auth_complete(call, status);
if (!NT_STATUS_IS_OK(status)) {
- return dcesrv_bind_nak(call, 0);
+ status = dcesrv_bind_nak(call, 0);
+ dcesrv_conn_auth_wait_finished(conn, status);
+ return;
}
- return dcesrv_auth_reply(call);
+ status = dcesrv_auth_reply(call);
+ dcesrv_conn_auth_wait_finished(conn, status);
+ return;
}
static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
--
1.9.1
From 5a7fd71bafa6b880186fb8dc06e57d9d17eeaae7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 15:20:56 +0200
Subject: [PATCH 18/24] s4:rpc_server: implement async ALTER_CONTEXT using
gensec_update_send/recv
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 38 ++++++++++++++++++++++++++++++++------
1 file changed, 32 insertions(+), 6 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 225f5e7..5deeb7c 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -1493,17 +1493,21 @@ static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
return NT_STATUS_OK;
}
+static void dcesrv_alter_done(struct tevent_req *subreq);
+
/*
handle a alter context request
*/
static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
{
+ struct dcesrv_connection *conn = call->conn;
NTSTATUS status;
bool auth_ok = false;
struct ncacn_packet *pkt = &call->ack_pkt;
uint32_t extra_flags = 0;
struct dcesrv_auth *auth = &call->conn->auth_state;
struct dcerpc_ack_ctx *ack_ctx_list = NULL;
+ struct tevent_req *subreq = NULL;
size_t i;
if (!call->conn->allow_alter) {
@@ -1615,17 +1619,39 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
return dcesrv_auth_reply(call);
}
- status = gensec_update_ev(auth->gensec_security,
- call, call->event_ctx,
- call->in_auth_info.credentials,
- &call->out_auth_info->credentials);
+ subreq = gensec_update_send(call, call->event_ctx,
+ auth->gensec_security,
+ call->in_auth_info.credentials);
+ if (subreq == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ tevent_req_set_callback(subreq, dcesrv_alter_done, call);
+
+ return dcesrv_conn_auth_wait_setup(conn);
+}
+
+static void dcesrv_alter_done(struct tevent_req *subreq)
+{
+ struct dcesrv_call_state *call =
+ tevent_req_callback_data(subreq,
+ struct dcesrv_call_state);
+ struct dcesrv_connection *conn = call->conn;
+ NTSTATUS status;
+
+ status = gensec_update_recv(subreq, call,
+ &call->out_auth_info->credentials);
+ TALLOC_FREE(subreq);
status = dcesrv_auth_complete(call, status);
if (!NT_STATUS_IS_OK(status)) {
- return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
+ status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
+ dcesrv_conn_auth_wait_finished(conn, status);
+ return;
}
- return dcesrv_auth_reply(call);
+ status = dcesrv_auth_reply(call);
+ dcesrv_conn_auth_wait_finished(conn, status);
+ return;
}
/*
--
1.9.1
From 76a42f71c961b76d869785660ba191fe1007061b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 15:20:56 +0200
Subject: [PATCH 19/24] s4:rpc_server: implement async AUTH3 using
gensec_update_send/recv
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/rpc_server/dcerpc_server.c | 40 +++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 5deeb7c..de919e2 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -1186,12 +1186,16 @@ static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
}
+static void dcesrv_auth3_done(struct tevent_req *subreq);
+
/*
handle a auth3 request
*/
static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
{
+ struct dcesrv_connection *conn = call->conn;
struct dcesrv_auth *auth = &call->conn->auth_state;
+ struct tevent_req *subreq = NULL;
NTSTATUS status;
if (!call->conn->allow_auth3) {
@@ -1235,10 +1239,28 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
return NT_STATUS_OK;
}
- status = gensec_update_ev(auth->gensec_security,
- call, call->event_ctx,
- call->in_auth_info.credentials,
- &call->out_auth_info->credentials);
+ subreq = gensec_update_send(call, call->event_ctx,
+ auth->gensec_security,
+ call->in_auth_info.credentials);
+ if (subreq == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
+
+ return dcesrv_conn_auth_wait_setup(conn);
+}
+
+static void dcesrv_auth3_done(struct tevent_req *subreq)
+{
+ struct dcesrv_call_state *call =
+ tevent_req_callback_data(subreq,
+ struct dcesrv_call_state);
+ struct dcesrv_connection *conn = call->conn;
+ NTSTATUS status;
+
+ status = gensec_update_recv(subreq, call,
+ &call->out_auth_info->credentials);
+ TALLOC_FREE(subreq);
status = dcesrv_auth_complete(call, status);
if (!NT_STATUS_IS_OK(status)) {
@@ -1251,17 +1273,21 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
*/
call->conn->auth_state.auth_invalid = true;
if (call->fault_code != 0) {
- return dcesrv_fault_disconnect(call, call->fault_code);
+ status = dcesrv_fault_disconnect(call, call->fault_code);
+ dcesrv_conn_auth_wait_finished(conn, status);
+ return;
}
TALLOC_FREE(call);
- return NT_STATUS_OK;
+ dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
+ return;
}
/*
* we don't send a reply to a auth3 request.
*/
TALLOC_FREE(call);
- return NT_STATUS_OK;
+ dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
+ return;
}
--
1.9.1
From a5ab80ac4596c48c3af70f08e70124c03ae355aa Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 22:36:20 +0200
Subject: [PATCH 20/24] s4:librpc: use gensec_update_send() in
dcerpc_bind_auth_send()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/librpc/rpc/dcerpc_auth.c | 53 ++++++++++++++++++++++++++--------------
1 file changed, 34 insertions(+), 19 deletions(-)
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index e790a9f..ee13a6b 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -136,6 +136,8 @@ _PUBLIC_ NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p,
struct bind_auth_state {
struct dcerpc_pipe *pipe;
+ struct ndr_syntax_id syntax;
+ struct ndr_syntax_id transfer_syntax;
struct dcerpc_auth out_auth_info;
struct dcerpc_auth in_auth_info;
bool more_processing; /* Is there anything more to do after the
@@ -289,6 +291,8 @@ static void bind_auth_recv_bindreply(struct tevent_req *subreq)
}
+static void dcerpc_bind_auth_gensec_done(struct tevent_req *subreq);
+
/**
Bind to a DCE/RPC pipe, send async request
@param mem_ctx TALLOC_CTX for the allocation of the composite_context
@@ -313,7 +317,6 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
struct bind_auth_state *state;
struct dcecli_security *sec;
struct tevent_req *subreq;
- struct ndr_syntax_id syntax, transfer_syntax;
const char *target_principal = NULL;
/* composite context allocation and setup */
@@ -327,8 +330,8 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
state->pipe = p;
c->status = dcerpc_init_syntaxes(p, table,
- &syntax,
- &transfer_syntax);
+ &state->syntax,
+ &state->transfer_syntax);
if (!composite_is_ok(c)) return c;
sec = &p->conn->security_state;
@@ -420,22 +423,34 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
* it doesn't like that either
*/
- state->pipe->inhibit_timeout_processing = true;
- state->pipe->timed_out = false;
- c->status = gensec_update_ev(sec->generic_state, state,
- p->conn->event_ctx,
- data_blob_null,
- &state->out_auth_info.credentials);
- if (state->pipe->timed_out) {
- composite_error(c, NT_STATUS_IO_TIMEOUT);
- return c;
- }
- state->pipe->inhibit_timeout_processing = false;
+ subreq = gensec_update_send(state,
+ p->conn->event_ctx,
+ sec->generic_state,
+ data_blob_null);
+ if (composite_nomem(subreq, c)) return c;
+ tevent_req_set_callback(subreq, dcerpc_bind_auth_gensec_done, c);
+ return c;
+}
+
+static void dcerpc_bind_auth_gensec_done(struct tevent_req *subreq)
+{
+ struct composite_context *c =
+ tevent_req_callback_data(subreq,
+ struct composite_context);
+ struct bind_auth_state *state =
+ talloc_get_type_abort(c->private_data,
+ struct bind_auth_state);
+ struct dcerpc_pipe *p = state->pipe;
+ struct dcecli_security *sec = &p->conn->security_state;
+
+ c->status = gensec_update_recv(subreq, state,
+ &state->out_auth_info.credentials);
+ TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(c->status) &&
!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
composite_error(c, c->status);
- return c;
+ return;
}
state->more_processing = NT_STATUS_EQUAL(c->status,
@@ -443,7 +458,7 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
if (state->out_auth_info.credentials.length == 0) {
composite_done(c);
- return c;
+ return;
}
if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) {
@@ -462,11 +477,11 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx,
/* The first request always is a dcerpc_bind. The subsequent ones
* depend on gensec results */
subreq = dcerpc_bind_send(state, p->conn->event_ctx, p,
- &syntax, &transfer_syntax);
- if (composite_nomem(subreq, c)) return c;
+ &state->syntax, &state->transfer_syntax);
+ if (composite_nomem(subreq, c)) return;
tevent_req_set_callback(subreq, bind_auth_recv_bindreply, c);
- return c;
+ return;
}
--
1.9.1
From 8cdce31c06d9b66e5178f60a9b63f8dcd7237564 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 22:46:39 +0200
Subject: [PATCH 21/24] s4:librpc: make use of gensec_update_send() in
bind_auth_next_step()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/librpc/rpc/dcerpc_auth.c | 35 +++++++++++++++++++++++------------
1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c
index ee13a6b..a2d1418 100644
--- a/source4/librpc/rpc/dcerpc_auth.c
+++ b/source4/librpc/rpc/dcerpc_auth.c
@@ -144,6 +144,7 @@ struct bind_auth_state {
* first bind itself received? */
};
+static void bind_auth_next_gensec_done(struct tevent_req *subreq);
static void bind_auth_recv_alter(struct tevent_req *subreq);
static void bind_auth_next_step(struct composite_context *c)
@@ -151,7 +152,6 @@ static void bind_auth_next_step(struct composite_context *c)
struct bind_auth_state *state;
struct dcecli_security *sec;
struct tevent_req *subreq;
- bool more_processing = false;
state = talloc_get_type(c->private_data, struct bind_auth_state);
sec = &state->pipe->conn->security_state;
@@ -187,18 +187,29 @@ static void bind_auth_next_step(struct composite_context *c)
* it doesn't like that either
*/
- state->pipe->inhibit_timeout_processing = true;
- state->pipe->timed_out = false;
+ subreq = gensec_update_send(state,
+ state->pipe->conn->event_ctx,
+ sec->generic_state,
+ state->in_auth_info.credentials);
+ if (composite_nomem(subreq, c)) return;
+ tevent_req_set_callback(subreq, bind_auth_next_gensec_done, c);
+}
- c->status = gensec_update_ev(sec->generic_state, state,
- state->pipe->conn->event_ctx,
- state->in_auth_info.credentials,
- &state->out_auth_info.credentials);
- if (state->pipe->timed_out) {
- composite_error(c, NT_STATUS_IO_TIMEOUT);
- return;
- }
- state->pipe->inhibit_timeout_processing = false;
+static void bind_auth_next_gensec_done(struct tevent_req *subreq)
+{
+ struct composite_context *c =
+ tevent_req_callback_data(subreq,
+ struct composite_context);
+ struct bind_auth_state *state =
+ talloc_get_type_abort(c->private_data,
+ struct bind_auth_state);
+ struct dcerpc_pipe *p = state->pipe;
+ struct dcecli_security *sec = &p->conn->security_state;
+ bool more_processing = false;
+
+ c->status = gensec_update_recv(subreq, state,
+ &state->out_auth_info.credentials);
+ TALLOC_FREE(subreq);
if (NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
more_processing = true;
--
1.9.1
From f9dbfce95beabcc54a24b69c59e384a9d54eb8db Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 22:49:09 +0200
Subject: [PATCH 22/24] s4:librpc: simplify dcerpc_connect_timeout_handler()
logic
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/librpc/rpc/dcerpc.h | 8 --------
source4/librpc/rpc/dcerpc_connect.c | 10 +---------
2 files changed, 1 insertion(+), 17 deletions(-)
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index 3223948..eaa3c62 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -136,14 +136,6 @@ struct dcerpc_pipe {
/** timeout for individual rpc requests, in seconds */
uint32_t request_timeout;
- /*
- * Set for the timeout in dcerpc_pipe_connect_b_send(), to
- * allow the timeout not to destory the stack during a nested
- * event loop caused by gensec_update()
- */
- bool inhibit_timeout_processing;
- bool timed_out;
-
bool verified_pcontext;
};
diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c
index 8ed1257..723e657 100644
--- a/source4/librpc/rpc/dcerpc_connect.c
+++ b/source4/librpc/rpc/dcerpc_connect.c
@@ -1004,12 +1004,7 @@ static void dcerpc_connect_timeout_handler(struct tevent_context *ev, struct tev
{
struct composite_context *c = talloc_get_type_abort(private_data,
struct composite_context);
- struct pipe_connect_state *s = talloc_get_type_abort(c->private_data, struct pipe_connect_state);
- if (!s->pipe->inhibit_timeout_processing) {
- composite_error(c, NT_STATUS_IO_TIMEOUT);
- } else {
- s->pipe->timed_out = true;
- }
+ composite_error(c, NT_STATUS_IO_TIMEOUT);
}
/*
@@ -1053,9 +1048,6 @@ _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent
s->credentials = credentials;
s->lp_ctx = lp_ctx;
- s->pipe->timed_out = false;
- s->pipe->inhibit_timeout_processing = false;
-
tevent_add_timer(c->event_ctx, c,
timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
dcerpc_connect_timeout_handler, c);
--
1.9.1
From 789053e634601ec485f9117577e1571e319cb40e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 23:37:22 +0200
Subject: [PATCH 23/24] s4:libcli/smb2: make smb2_session_setup_spnego_*
completely async
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/libcli/smb2/session.c | 253 ++++++++++++++++++++++++++----------------
1 file changed, 160 insertions(+), 93 deletions(-)
diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c
index c96693b..e3e54cb 100644
--- a/source4/libcli/smb2/session.c
+++ b/source4/libcli/smb2/session.c
@@ -115,11 +115,17 @@ struct smb2_session_setup_spnego_state {
bool session_bind;
bool reauth;
NTSTATUS gensec_status;
+ NTSTATUS remote_status;
DATA_BLOB in_secblob;
DATA_BLOB out_secblob;
+ struct iovec *recv_iov;
};
-static void smb2_session_setup_spnego_done(struct tevent_req *subreq);
+static void smb2_session_setup_spnego_gensec_next(struct tevent_req *req);
+static void smb2_session_setup_spnego_gensec_done(struct tevent_req *subreq);
+static void smb2_session_setup_spnego_smb2_next(struct tevent_req *req);
+static void smb2_session_setup_spnego_smb2_done(struct tevent_req *subreq);
+static void smb2_session_setup_spnego_both_ready(struct tevent_req *req);
/*
a composite function that does a full SPNEGO session setup
@@ -131,18 +137,15 @@ struct tevent_req *smb2_session_setup_spnego_send(
struct cli_credentials *credentials,
uint64_t previous_session_id)
{
+ struct smb2_transport *transport = session->transport;
struct tevent_req *req;
struct smb2_session_setup_spnego_state *state;
uint64_t current_session_id;
const char *chosen_oid;
- struct tevent_req *subreq;
NTSTATUS status;
const DATA_BLOB *server_gss_blob;
- DATA_BLOB negprot_secblob = data_blob_null;
- uint32_t timeout_msec;
- uint8_t in_flags = 0;
-
- timeout_msec = session->transport->options.request_timeout * 1000;
+ struct timeval endtime;
+ bool ok;
req = tevent_req_create(mem_ctx, &state,
struct smb2_session_setup_spnego_state);
@@ -153,6 +156,16 @@ struct tevent_req *smb2_session_setup_spnego_send(
state->session = session;
state->credentials = credentials;
state->previous_session_id = previous_session_id;
+ state->gensec_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+ state->remote_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+
+ endtime = timeval_current_ofs(transport->options.request_timeout, 0);
+
+ ok = tevent_req_set_endtime(req, ev, endtime);
+ if (!ok) {
+ tevent_req_oom(req);
+ return tevent_req_post(req, ev);
+ }
current_session_id = smb2cli_session_current_id(state->session->smbXcli);
if (state->session->needs_bind) {
@@ -162,7 +175,7 @@ struct tevent_req *smb2_session_setup_spnego_send(
}
server_gss_blob = smbXcli_conn_server_gss_blob(session->transport->conn);
if (server_gss_blob) {
- negprot_secblob = *server_gss_blob;
+ state->out_secblob = *server_gss_blob;
}
status = gensec_set_credentials(session->gensec, credentials);
@@ -181,7 +194,7 @@ struct tevent_req *smb2_session_setup_spnego_send(
return tevent_req_post(req, ev);
}
- if (negprot_secblob.length > 0) {
+ if (state->out_secblob.length > 0) {
chosen_oid = GENSEC_OID_SPNEGO;
} else {
chosen_oid = GENSEC_OID_NTLMSSP;
@@ -192,15 +205,83 @@ struct tevent_req *smb2_session_setup_spnego_send(
return tevent_req_post(req, ev);
}
- status = gensec_update_ev(session->gensec, state,
- state->ev,
- negprot_secblob,
- &state->in_secblob);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- tevent_req_nterror(req, status);
+ smb2_session_setup_spnego_gensec_next(req);
+ if (!tevent_req_is_in_progress(req)) {
return tevent_req_post(req, ev);
}
+
+ return req;
+}
+
+static void smb2_session_setup_spnego_gensec_next(struct tevent_req *req)
+{
+ struct smb2_session_setup_spnego_state *state =
+ tevent_req_data(req,
+ struct smb2_session_setup_spnego_state);
+ struct smb2_session *session = state->session;
+ struct tevent_req *subreq = NULL;
+
+ if (NT_STATUS_IS_OK(state->gensec_status)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ subreq = gensec_update_send(state, state->ev,
+ session->gensec,
+ state->out_secblob);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq,
+ smb2_session_setup_spnego_gensec_done,
+ req);
+}
+
+static void smb2_session_setup_spnego_gensec_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct smb2_session_setup_spnego_state *state =
+ tevent_req_data(req,
+ struct smb2_session_setup_spnego_state);
+ NTSTATUS status;
+
+ status = gensec_update_recv(subreq, state,
+ &state->in_secblob);
state->gensec_status = status;
+ state->out_secblob = data_blob_null;
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ if (NT_STATUS_IS_OK(state->remote_status) &&
+ NT_STATUS_IS_OK(state->gensec_status)) {
+ smb2_session_setup_spnego_both_ready(req);
+ return;
+ }
+
+ smb2_session_setup_spnego_smb2_next(req);
+}
+
+static void smb2_session_setup_spnego_smb2_next(struct tevent_req *req)
+{
+ struct smb2_session_setup_spnego_state *state =
+ tevent_req_data(req,
+ struct smb2_session_setup_spnego_state);
+ struct smb2_session *session = state->session;
+ uint32_t timeout_msec;
+ uint8_t in_flags = 0;
+ struct tevent_req *subreq = NULL;
+
+ if (NT_STATUS_IS_OK(state->remote_status)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ timeout_msec = session->transport->options.request_timeout * 1000;
if (state->session_bind) {
in_flags |= SMB2_SESSION_FLAG_BINDING;
@@ -216,17 +297,17 @@ struct tevent_req *smb2_session_setup_spnego_send(
state->previous_session_id,
&state->in_secblob);
if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
+ return;
}
- tevent_req_set_callback(subreq, smb2_session_setup_spnego_done, req);
-
- return req;
+ tevent_req_set_callback(subreq,
+ smb2_session_setup_spnego_smb2_done,
+ req);
}
/*
handle continuations of the spnego session setup
*/
-static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
+static void smb2_session_setup_spnego_smb2_done(struct tevent_req *subreq)
{
struct tevent_req *req =
tevent_req_callback_data(subreq,
@@ -234,104 +315,90 @@ static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
struct smb2_session_setup_spnego_state *state =
tevent_req_data(req,
struct smb2_session_setup_spnego_state);
- struct smb2_session *session = state->session;
- NTSTATUS peer_status;
NTSTATUS status;
- struct iovec *recv_iov;
- uint32_t timeout_msec;
- uint8_t in_flags = 0;
-
- timeout_msec = session->transport->options.request_timeout * 1000;
status = smb2cli_session_setup_recv(subreq, state,
- &recv_iov,
+ &state->recv_iov,
&state->out_secblob);
+ state->remote_status = status;
+ state->in_secblob = data_blob_null;
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
tevent_req_nterror(req, status);
return;
}
- peer_status = status;
- if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- status = gensec_update_ev(session->gensec, state,
- state->ev,
- state->out_secblob,
- &state->in_secblob);
- state->gensec_status = status;
- }
-
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- tevent_req_nterror(req, status);
+ if (NT_STATUS_IS_OK(state->remote_status) &&
+ NT_STATUS_IS_OK(state->gensec_status)) {
+ smb2_session_setup_spnego_both_ready(req);
return;
}
- if (NT_STATUS_IS_OK(peer_status) && NT_STATUS_IS_OK(state->gensec_status)) {
- DATA_BLOB session_key;
+ smb2_session_setup_spnego_gensec_next(req);
+}
- if (state->reauth) {
- tevent_req_done(req);
- return;
- }
+static void smb2_session_setup_spnego_both_ready(struct tevent_req *req)
+{
+ struct smb2_session_setup_spnego_state *state =
+ tevent_req_data(req,
+ struct smb2_session_setup_spnego_state);
+ struct smb2_session *session = state->session;
+ NTSTATUS status;
+ DATA_BLOB session_key;
- if (cli_credentials_is_anonymous(state->credentials)) {
- /*
- * Windows server does not set the
- * SMB2_SESSION_FLAG_IS_GUEST nor
- * SMB2_SESSION_FLAG_IS_NULL flag.
- *
- * This fix makes sure we do not try
- * to verify a signature on the final
- * session setup response.
- */
- tevent_req_done(req);
- return;
- }
+ if (state->out_secblob.length != 0) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
- status = gensec_session_key(session->gensec, state,
- &session_key);
- if (tevent_req_nterror(req, status)) {
- return;
- }
+ if (state->in_secblob.length != 0) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
- if (state->session_bind) {
- status = smb2cli_session_set_channel_key(session->smbXcli,
- session_key,
- recv_iov);
- if (tevent_req_nterror(req, status)) {
- return;
- }
- session->needs_bind = false;
- } else {
- status = smb2cli_session_set_session_key(session->smbXcli,
- session_key,
- recv_iov);
- if (tevent_req_nterror(req, status)) {
- return;
- }
- }
+ if (state->reauth) {
tevent_req_done(req);
return;
}
- if (state->session_bind) {
- in_flags |= SMB2_SESSION_FLAG_BINDING;
+ if (cli_credentials_is_anonymous(state->credentials)) {
+ /*
+ * Windows server does not set the
+ * SMB2_SESSION_FLAG_IS_GUEST nor
+ * SMB2_SESSION_FLAG_IS_NULL flag.
+ *
+ * This fix makes sure we do not try
+ * to verify a signature on the final
+ * session setup response.
+ */
+ tevent_req_done(req);
+ return;
}
- subreq = smb2cli_session_setup_send(state, state->ev,
- session->transport->conn,
- timeout_msec,
- session->smbXcli,
- in_flags,
- 0, /* in_capabilities */
- 0, /* in_channel */
- state->previous_session_id,
- &state->in_secblob);
- if (tevent_req_nomem(subreq, req)) {
+ status = gensec_session_key(session->gensec, state,
+ &session_key);
+ if (tevent_req_nterror(req, status)) {
return;
}
- tevent_req_set_callback(subreq, smb2_session_setup_spnego_done, req);
+
+ if (state->session_bind) {
+ status = smb2cli_session_set_channel_key(session->smbXcli,
+ session_key,
+ state->recv_iov);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ session->needs_bind = false;
+ } else {
+ status = smb2cli_session_set_session_key(session->smbXcli,
+ session_key,
+ state->recv_iov);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ }
+ tevent_req_done(req);
+ return;
}
/*
--
1.9.1
From 400853988e6303b7e59acbbcbf6ae0f73ced02ba Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 15 May 2017 23:53:38 +0200
Subject: [PATCH 24/24] s4:libcli/ldap: just use gensec_update() in
ldap_bind_sasl()
We're in a blocking/sync call, we should avoid using nested event loops for
this. As far as I can see ldap_bind_sasl() is only called from command
line tools, which are ok to block.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/libcli/ldap/ldap_bind.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c
index b8799dc..66fe9f5 100644
--- a/source4/libcli/ldap/ldap_bind.c
+++ b/source4/libcli/ldap/ldap_bind.c
@@ -379,8 +379,7 @@ try_logon_again:
struct ldap_request *req;
int result = LDAP_OTHER;
- status = gensec_update_ev(conn->gensec, tmp_ctx,
- conn->event.event_ctx,
+ status = gensec_update(conn->gensec, tmp_ctx,
input,
&output);
/* The status value here, from GENSEC is vital to the security
--
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20170517/6669c7ac/signature-0001.sig>
More information about the samba-technical
mailing list