mirror of
https://github.com/samba-team/samba.git
synced 2025-01-25 06:04:04 +03:00
s4:rpc_server: make sure we don't terminate a connection with pending requests (bug #9820)
Sadly we may have nested event loops, which won't work correctly with broken connections, that's why we have to do this... Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Wed Jul 10 08:47:38 CEST 2013 on sn-devel-104
This commit is contained in:
parent
2505d48e4f
commit
e6a58d3704
@ -386,6 +386,8 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
|
|||||||
return NT_STATUS_NO_MEMORY;
|
return NT_STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->prev = NULL;
|
||||||
|
p->next = NULL;
|
||||||
p->dce_ctx = dce_ctx;
|
p->dce_ctx = dce_ctx;
|
||||||
p->endpoint = ep;
|
p->endpoint = ep;
|
||||||
p->contexts = NULL;
|
p->contexts = NULL;
|
||||||
@ -402,7 +404,7 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
|
|||||||
p->event_ctx = event_ctx;
|
p->event_ctx = event_ctx;
|
||||||
p->msg_ctx = msg_ctx;
|
p->msg_ctx = msg_ctx;
|
||||||
p->server_id = server_id;
|
p->server_id = server_id;
|
||||||
p->processing = false;
|
p->terminate = NULL;
|
||||||
p->state_flags = state_flags;
|
p->state_flags = state_flags;
|
||||||
ZERO_STRUCT(p->transport);
|
ZERO_STRUCT(p->transport);
|
||||||
|
|
||||||
@ -1143,6 +1145,7 @@ _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
|
|||||||
dce_ctx->lp_ctx = lp_ctx;
|
dce_ctx->lp_ctx = lp_ctx;
|
||||||
dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
|
dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
|
||||||
NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
|
NT_STATUS_HAVE_NO_MEMORY(dce_ctx->assoc_groups_idr);
|
||||||
|
dce_ctx->broken_connections = NULL;
|
||||||
|
|
||||||
for (i=0;endpoint_servers[i];i++) {
|
for (i=0;endpoint_servers[i];i++) {
|
||||||
const struct dcesrv_endpoint_server *ep_server;
|
const struct dcesrv_endpoint_server *ep_server;
|
||||||
@ -1269,12 +1272,45 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void)
|
|||||||
|
|
||||||
static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
|
static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
|
||||||
{
|
{
|
||||||
|
struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
|
||||||
struct stream_connection *srv_conn;
|
struct stream_connection *srv_conn;
|
||||||
srv_conn = talloc_get_type(dce_conn->transport.private_data,
|
srv_conn = talloc_get_type(dce_conn->transport.private_data,
|
||||||
struct stream_connection);
|
struct stream_connection);
|
||||||
|
|
||||||
stream_terminate_connection(srv_conn, reason);
|
if (dce_conn->pending_call_list == NULL) {
|
||||||
|
char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
|
||||||
|
|
||||||
|
DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
|
||||||
|
stream_terminate_connection(srv_conn, full_reason ? full_reason : reason);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dce_conn->terminate != NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(3,("dcesrv: terminating connection due to '%s' defered due to pending calls\n",
|
||||||
|
reason));
|
||||||
|
dce_conn->terminate = talloc_strdup(dce_conn, reason);
|
||||||
|
if (dce_conn->terminate == NULL) {
|
||||||
|
dce_conn->terminate = "dcesrv: defered terminating connection - no memory";
|
||||||
|
}
|
||||||
|
DLIST_ADD_END(dce_ctx->broken_connections, dce_conn, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
|
||||||
|
{
|
||||||
|
struct dcesrv_connection *cur, *next;
|
||||||
|
|
||||||
|
next = dce_ctx->broken_connections;
|
||||||
|
while (next != NULL) {
|
||||||
|
cur = next;
|
||||||
|
next = cur->next;
|
||||||
|
|
||||||
|
dcesrv_terminate_connection(cur, cur->terminate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We need this include to be able to compile on some plateforms
|
/* We need this include to be able to compile on some plateforms
|
||||||
* (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
|
* (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
|
||||||
* correctly.
|
* correctly.
|
||||||
@ -1386,6 +1422,8 @@ static void dcesrv_sock_accept(struct stream_connection *srv_conn)
|
|||||||
struct tevent_req *subreq;
|
struct tevent_req *subreq;
|
||||||
struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
|
struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
|
||||||
|
|
||||||
|
dcesrv_cleanup_broken_connections(dcesrv_sock->dcesrv_ctx);
|
||||||
|
|
||||||
if (!srv_conn->session_info) {
|
if (!srv_conn->session_info) {
|
||||||
status = auth_anonymous_session_info(srv_conn,
|
status = auth_anonymous_session_info(srv_conn,
|
||||||
lp_ctx,
|
lp_ctx,
|
||||||
@ -1473,10 +1511,23 @@ static void dcesrv_read_fragment_done(struct tevent_req *subreq)
|
|||||||
{
|
{
|
||||||
struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
|
struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
|
||||||
struct dcesrv_connection);
|
struct dcesrv_connection);
|
||||||
|
struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
|
||||||
struct ncacn_packet *pkt;
|
struct ncacn_packet *pkt;
|
||||||
DATA_BLOB buffer;
|
DATA_BLOB buffer;
|
||||||
NTSTATUS status;
|
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 = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
|
status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
|
||||||
&pkt, &buffer);
|
&pkt, &buffer);
|
||||||
TALLOC_FREE(subreq);
|
TALLOC_FREE(subreq);
|
||||||
|
@ -170,6 +170,9 @@ struct dcesrv_connection_context {
|
|||||||
|
|
||||||
/* the state associated with a dcerpc server connection */
|
/* the state associated with a dcerpc server connection */
|
||||||
struct dcesrv_connection {
|
struct dcesrv_connection {
|
||||||
|
/* for the broken_connections DLIST */
|
||||||
|
struct dcesrv_connection *prev, *next;
|
||||||
|
|
||||||
/* the top level context for this server */
|
/* the top level context for this server */
|
||||||
struct dcesrv_context *dce_ctx;
|
struct dcesrv_context *dce_ctx;
|
||||||
|
|
||||||
@ -208,7 +211,8 @@ struct dcesrv_connection {
|
|||||||
/* the transport level session key */
|
/* the transport level session key */
|
||||||
DATA_BLOB transport_session_key;
|
DATA_BLOB transport_session_key;
|
||||||
|
|
||||||
bool processing;
|
/* is this connection pending termination? If so, why? */
|
||||||
|
const char *terminate;
|
||||||
|
|
||||||
const char *packet_log_dir;
|
const char *packet_log_dir;
|
||||||
|
|
||||||
@ -288,6 +292,8 @@ struct dcesrv_context {
|
|||||||
struct loadparm_context *lp_ctx;
|
struct loadparm_context *lp_ctx;
|
||||||
|
|
||||||
struct idr_context *assoc_groups_idr;
|
struct idr_context *assoc_groups_idr;
|
||||||
|
|
||||||
|
struct dcesrv_connection *broken_connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* this structure is used by modules to determine the size of some critical types */
|
/* this structure is used by modules to determine the size of some critical types */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user