1
0
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:
Andrew Tridgell 2010-09-07 11:57:44 +10:00
parent a8bac4a09a
commit 73c3932b2d
2 changed files with 60 additions and 0 deletions

View File

@ -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");

View File

@ -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"