mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
s4-ldapserver: serialise ldap server operations
This ensures that two ldap server operations cannot happen in parallel by using packet_recv_disable() and packet_recv_enable() to disable other interfaces during ldap calls. This prevents problems caused by parallel ldap operations where transactions could overlap.
This commit is contained in:
parent
a8bac4a09a
commit
73c3932b2d
@ -131,6 +131,32 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
disable packets on other sockets while processing this one
|
||||
*/
|
||||
static void ldapsrv_disable_recv(struct ldapsrv_connection *conn)
|
||||
{
|
||||
struct ldapsrv_packet_interfaces *p;
|
||||
for (p=conn->service->packet_interfaces; p; p=p->next) {
|
||||
if (p->packet != conn->packet) {
|
||||
packet_recv_disable(p->packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
disable packets on other sockets while processing this one
|
||||
*/
|
||||
static void ldapsrv_enable_recv(struct ldapsrv_connection *conn)
|
||||
{
|
||||
struct ldapsrv_packet_interfaces *p;
|
||||
for (p=conn->service->packet_interfaces; p; p=p->next) {
|
||||
if (p->packet != conn->packet) {
|
||||
packet_recv_enable(p->packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
decode/process data
|
||||
*/
|
||||
@ -162,7 +188,13 @@ static NTSTATUS ldapsrv_decode(void *private_data, DATA_BLOB blob)
|
||||
talloc_steal(conn, msg);
|
||||
asn1_free(asn1);
|
||||
|
||||
/* disable messages on other sockets while processing this one */
|
||||
ldapsrv_disable_recv(conn);
|
||||
|
||||
ldapsrv_process_message(conn, msg);
|
||||
|
||||
ldapsrv_enable_recv(conn);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -324,6 +356,15 @@ failed:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
remove a packet interface from the service level list
|
||||
*/
|
||||
static int packet_interface_destructor(struct ldapsrv_packet_interfaces *packet_interface)
|
||||
{
|
||||
DLIST_REMOVE(packet_interface->service->packet_interfaces, packet_interface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
initialise a server_context from a open socket and register a event handler
|
||||
for reading from that socket
|
||||
@ -397,6 +438,18 @@ static void ldapsrv_accept(struct stream_connection *c,
|
||||
/* Ensure we don't get packets until the database is ready below */
|
||||
packet_recv_disable(conn->packet);
|
||||
|
||||
/* add to the service level list of packet interfaces, to
|
||||
* allow us to serialise between connections
|
||||
*/
|
||||
conn->packet_interface = talloc(conn, struct ldapsrv_packet_interfaces);
|
||||
if (conn->packet_interface == NULL) {
|
||||
ldapsrv_terminate_connection(conn, "out of memory");
|
||||
}
|
||||
conn->packet_interface->service = ldapsrv_service;
|
||||
conn->packet_interface->packet = conn->packet;
|
||||
DLIST_ADD(conn->service->packet_interfaces, conn->packet_interface);
|
||||
talloc_set_destructor(conn->packet_interface, packet_interface_destructor);
|
||||
|
||||
server_credentials = cli_credentials_init(conn);
|
||||
if (!server_credentials) {
|
||||
stream_terminate_connection(c, "Failed to init server credentials\n");
|
||||
|
@ -50,6 +50,8 @@ struct ldapsrv_connection {
|
||||
struct tevent_timer *ite;
|
||||
struct tevent_timer *te;
|
||||
} limits;
|
||||
|
||||
struct ldapsrv_packet_interfaces *packet_interface;
|
||||
};
|
||||
|
||||
struct ldapsrv_call {
|
||||
@ -66,6 +68,11 @@ struct ldapsrv_call {
|
||||
struct ldapsrv_service {
|
||||
struct tls_params *tls_params;
|
||||
struct task_server *task;
|
||||
struct ldapsrv_packet_interfaces {
|
||||
struct ldapsrv_packet_interfaces *next, *prev;
|
||||
struct packet_context *packet;
|
||||
struct ldapsrv_service *service;
|
||||
} *packet_interfaces;
|
||||
};
|
||||
|
||||
#include "ldap_server/proto.h"
|
||||
|
Loading…
Reference in New Issue
Block a user