summaryrefslogtreecommitdiff
path: root/source4/ldap_server
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2010-09-07 11:57:44 +1000
committerAndrew Tridgell <tridge@samba.org>2010-09-07 12:55:27 +1000
commit73c3932b2d0dac784a0605abf6e532dba5514a01 (patch)
tree14a8d7f2a514a4d2521c102cb13be67d11490ceb /source4/ldap_server
parenta8bac4a09a4a81c280c62fb4dcdbd0e61c782479 (diff)
downloadsamba-73c3932b2d0dac784a0605abf6e532dba5514a01.tar.gz
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.
Diffstat (limited to 'source4/ldap_server')
-rw-r--r--source4/ldap_server/ldap_server.c53
-rw-r--r--source4/ldap_server/ldap_server.h7
2 files changed, 60 insertions, 0 deletions
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 946e1bf3b7d..e975590d43b 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -132,6 +132,32 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
}
/*
+ 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
*/
static NTSTATUS ldapsrv_decode(void *private_data, DATA_BLOB blob)
@@ -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;
}
@@ -325,6 +357,15 @@ failed:
}
/*
+ 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");
diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h
index 8b45285463d..0fb8d2f4aca 100644
--- a/source4/ldap_server/ldap_server.h
+++ b/source4/ldap_server/ldap_server.h
@@ -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"