*/
#include "includes.h"
+#include "events.h"
+#include "auth/auth.h"
+#include "dlinklist.h"
+#include "asn_1.h"
+#include "ldap_server/ldap_server.h"
/*
close the socket and shutdown a server_context
add a socket address to the list of events, one event per port
*/
static void add_socket(struct server_service *service,
- const struct model_ops *model_ops,
- struct socket_context *socket_ctx,
- struct in_addr *ifip)
+ const struct model_ops *model_ops,
+ struct ipv4_addr *ifip)
{
+ struct server_socket *srv_sock;
uint16_t port = 389;
+ char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip));
- service_setup_socket(service, model_ops, socket_ctx, ifip, &port);
+ srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port);
+
+ port = 3268;
+ srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port);
+
+ talloc_free(ip_str);
}
/****************************************************************************
static void ldapsrv_init(struct server_service *service,
const struct model_ops *model_ops)
{
- DEBUG(1,("ldapsrv_init\n"));
+ struct ldapsrv_service *ldap_service;
+ struct ldapsrv_partition *part;
+
+ DEBUG(10,("ldapsrv_init\n"));
+
+ ldap_service = talloc_p(service, struct ldapsrv_service);
+ if (!ldap_service) {
+ DEBUG(0,("talloc_p(service, struct ldapsrv_service) failed\n"));
+ return;
+ }
+ ZERO_STRUCTP(ldap_service);
+
+ part = talloc_p(ldap_service, struct ldapsrv_partition);
+ if (!ldap_service) {
+ DEBUG(0,("talloc_p(ldap_service, struct ldapsrv_partition) failed\n"));
+ return;
+ }
+ part->base_dn = ""; /* RootDSE */
+ part->ops = ldapsrv_get_rootdse_partition_ops();
+
+ ldap_service->rootDSE = part;
+ DLIST_ADD_END(ldap_service->partitions, part, struct ldapsrv_partition *);
+
+ part = talloc_p(ldap_service, struct ldapsrv_partition);
+ if (!ldap_service) {
+ DEBUG(0,("talloc_p(ldap_service, struct ldapsrv_partition) failed\n"));
+ return;
+ }
+ part->base_dn = "*"; /* default partition */
+ part->ops = ldapsrv_get_sldb_partition_ops();
+
+ ldap_service->default_partition = part;
+ DLIST_ADD_END(ldap_service->partitions, part, struct ldapsrv_partition *);
+
+ service->private_data = ldap_service;
if (lp_interfaces() && lp_bind_interfaces_only()) {
int num_interfaces = iface_count();
socket per interface and bind to only these.
*/
for(i = 0; i < num_interfaces; i++) {
- struct in_addr *ifip = iface_n_ip(i);
+ struct ipv4_addr *ifip = iface_n_ip(i);
if (ifip == NULL) {
DEBUG(0,("ldapsrv_init: interface %d has NULL "
continue;
}
- add_socket(service, model_ops, NULL, ifip);
+ add_socket(service, model_ops, ifip);
}
} else {
- struct in_addr *ifip;
- TALLOC_CTX *mem_ctx = talloc_init("ldapsrv_init");
-
- if (!mem_ctx) {
- smb_panic("No memory");
- }
+ struct ipv4_addr ifip;
/* Just bind to lp_socket_address() (usually 0.0.0.0) */
- ifip = interpret_addr2(mem_ctx, lp_socket_address());
- add_socket(service, model_ops, NULL, ifip);
-
- talloc_destroy(mem_ctx);
+ ifip = interpret_addr2(lp_socket_address());
+ add_socket(service, model_ops, &ifip);
}
}
that a read(2) holds a complete request that is then thrown away
completely. */
-static BOOL append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
+void ldapsrv_consumed_from_buf(struct rw_buffer *buf,
+ size_t length)
+{
+ memcpy(buf->data, buf->data+length, buf->length-length);
+ buf->length -= length;
+}
+
+static void peek_into_read_buf(struct rw_buffer *buf, uint8_t **out,
+ size_t *out_length)
+{
+ *out = buf->data;
+ *out_length = buf->length;
+}
+
+BOOL ldapsrv_append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
{
buf->data = realloc(buf->data, buf->length+length);
return True;
}
-static BOOL read_into_buf(int fd, struct rw_buffer *buf)
+static BOOL read_into_buf(struct socket_context *sock, struct rw_buffer *buf)
{
- char tmp_buf[1024];
- int len;
+ NTSTATUS status;
+ DATA_BLOB tmp_blob;
+ BOOL ret;
+ size_t nread;
- len = read(fd, tmp_buf, sizeof(tmp_buf));
- if (len == 0)
+ tmp_blob = data_blob_talloc(sock, NULL, 1024);
+ if (tmp_blob.data == NULL) {
return False;
+ }
- return append_to_buf(buf, tmp_buf, len);
-}
+ status = socket_recv(sock, tmp_blob.data, tmp_blob.length, &nread, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
+ talloc_free(tmp_blob.data);
+ return False;
+ }
-static BOOL write_from_buf(int fd, struct rw_buffer *buf)
-{
- int len;
+ ret = ldapsrv_append_to_buf(buf, tmp_blob.data, tmp_blob.length);
- len = write(fd, buf->data, buf->length);
- if (len != buf->length)
- return False;
+ talloc_free(tmp_blob.data);
- return True;
+ return ret;
}
-static void peek_into_read_buf(struct rw_buffer *buf, uint8_t **out,
- size_t *out_length)
+static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
{
- *out = buf->data;
- *out_length = buf->length;
-}
+ NTSTATUS status;
+ DATA_BLOB tmp_blob;
+ DATA_BLOB creds;
+ BOOL ret;
+ uint8_t *buf;
+ int buf_length, sasl_length;
+ struct socket_context *sock = conn->connection->socket;
+ TALLOC_CTX *mem_ctx;
+ size_t nread;
+
+ if (!conn->gensec || !conn->session_info ||
+ !(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
+ gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL))) {
+ return read_into_buf(sock, &conn->in_buffer);
+ }
-static void consumed_from_read_buf(struct rw_buffer *buf,
- size_t length)
-{
- memcpy(buf->data, buf->data+length, buf->length-length);
- buf->length -= length;
-}
+ mem_ctx = talloc(conn, 0);
+ if (!mem_ctx) {
+ DEBUG(0,("no memory\n"));
+ return False;
+ }
-static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
-{
- DATA_BLOB blob;
- BOOL res;
+ tmp_blob = data_blob_talloc(mem_ctx, NULL, 1024);
+ if (tmp_blob.data == NULL) {
+ talloc_free(mem_ctx);
+ return False;
+ }
- if (!ldap_encode(msg, &blob))
+ status = socket_recv(sock, tmp_blob.data, tmp_blob.length, &nread, 0);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
+ talloc_free(mem_ctx);
return False;
+ }
+ tmp_blob.length = nread;
- res = append_to_buf(buf, blob.data, blob.length);
+ ret = ldapsrv_append_to_buf(&conn->sasl_in_buffer, tmp_blob.data, tmp_blob.length);
+ if (!ret) {
+ talloc_free(mem_ctx);
+ return False;
+ }
- data_blob_free(&blob);
- return res;
-}
+ peek_into_read_buf(&conn->sasl_in_buffer, &buf, &buf_length);
-static void reply_unwilling(struct ldapsrv_connection *ldap_conn, int error)
-{
- struct ldap_message *msg;
- struct ldap_ExtendedResponse *r;
+ if (buf_length < 4) {
+ /* not enough yet */
+ talloc_free(mem_ctx);
+ return True;
+ }
- msg = new_ldap_message();
+ sasl_length = RIVAL(buf, 0);
- if (msg == NULL) {
- ldapsrv_terminate_connection(ldap_conn, "new_ldap_message() failed");
- return;
+ if (buf_length < (4 + sasl_length)) {
+ /* not enough yet */
+ talloc_free(mem_ctx);
+ return True;
+ }
+
+ creds.data = buf + 4;
+ creds.length = gensec_sig_size(conn->gensec);
+
+ if (creds.length > sasl_length) {
+ /* invalid packet? */
+ talloc_free(mem_ctx);
+ return False;
}
- msg->messageid = 0;
- r = &msg->r.ExtendedResponse;
+ tmp_blob.data = buf + (4 + creds.length);
+ tmp_blob.length = (4 + sasl_length) - (4 + creds.length);
+
+ if (gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL)) {
+ status = gensec_unseal_packet(conn->gensec, mem_ctx,
+ tmp_blob.data, tmp_blob.length,
+ tmp_blob.data, tmp_blob.length,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("gensec_unseal_packet: %s\n",nt_errstr(status)));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ } else {
+ status = gensec_check_packet(conn->gensec, mem_ctx,
+ tmp_blob.data, tmp_blob.length,
+ tmp_blob.data, tmp_blob.length,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("gensec_check_packet: %s\n",nt_errstr(status)));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
- /* When completely freaking out, OpenLDAP responds with an ExtResp */
- msg->type = LDAP_TAG_ExtendedResponse;
- r->response.resultcode = error;
- r->response.dn = NULL;
- r->response.errormessage = NULL;
- r->response.referral = NULL;
- r->name = NULL;
- r->value.data = NULL;
- r->value.length = 0;
+ ret = ldapsrv_append_to_buf(&conn->in_buffer, tmp_blob.data, tmp_blob.length);
+ if (!ret) {
+ talloc_free(mem_ctx);
+ return False;
+ }
- ldap_append_to_buf(msg, &ldap_conn->out_buffer);
+ ldapsrv_consumed_from_buf(&conn->sasl_in_buffer, 4 + sasl_length);
- talloc_destroy(msg->mem_ctx);
+ talloc_free(mem_ctx);
+ return ret;
}
-static void ldap_reply_BindRequest(struct ldapsrv_connection *conn,
- struct ldap_message *request)
+static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
{
- struct ldap_BindRequest *req = &request->r.BindRequest;
-
- struct ldap_message *msg;
- struct ldap_BindResponse *resp;
+ NTSTATUS status;
+ DATA_BLOB tmp_blob;
+ size_t sendlen;
- DEBUG(5, ("Binding as %s with pw %s\n",
- req->dn, req->creds.password));
+ tmp_blob.data = buf->data;
+ tmp_blob.length = buf->length;
- msg = new_ldap_message();
-
- if (msg == NULL) {
- ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
- return;
+ status = socket_send(sock, &tmp_blob, &sendlen, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
+ return False;
}
- resp = &msg->r.BindResponse;
-
- msg->messageid = request->messageid;
- msg->type = LDAP_TAG_BindResponse;
- resp->response.resultcode = 0;
- resp->response.dn = NULL;
- resp->response.errormessage = NULL;
- resp->response.referral = NULL;
- resp->SASL.secblob = data_blob(NULL, 0);
+ ldapsrv_consumed_from_buf(buf, sendlen);
- ldap_append_to_buf(msg, &conn->out_buffer);
- talloc_destroy(msg->mem_ctx);
+ return True;
}
-static void ldap_reply_SearchRequest(struct ldapsrv_connection *conn,
- struct ldap_message *request)
+static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
{
- struct ldap_SearchRequest *req = &request->r.SearchRequest;
-
- struct ldap_message *msg;
- struct ldap_Result *resp;
+ NTSTATUS status;
+ DATA_BLOB tmp_blob;
+ DATA_BLOB creds;
+ DATA_BLOB sasl;
+ size_t sendlen;
+ BOOL ret;
+ struct socket_context *sock = conn->connection->socket;
+ TALLOC_CTX *mem_ctx;
+
+ if (!conn->gensec || !conn->session_info ||
+ !(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
+ gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL))) {
+ return write_from_buf(sock, &conn->out_buffer);
+ }
- DEBUG(10, ("Search filter: %s\n", req->filter));
+ mem_ctx = talloc(conn, 0);
+ if (!mem_ctx) {
+ DEBUG(0,("no memory\n"));
+ return False;
+ }
- msg = new_ldap_message();
+ tmp_blob.data = conn->out_buffer.data;
+ tmp_blob.length = conn->out_buffer.length;
- if (msg == NULL) {
- ldapsrv_terminate_connection(conn, "new_ldap_message() failed");
- return;
+ if (tmp_blob.length == 0) {
+ goto nodata;
}
- msg->messageid = request->messageid;
- resp = &msg->r.SearchResultDone;
-
- /* Is this a rootdse request? */
- if ((strlen(req->basedn) == 0) &&
- (req->scope == LDAP_SEARCH_SCOPE_BASE) &&
- strequal(req->filter, "(objectclass=*)")) {
-
-#define ATTR_BLOB_CONST(val) data_blob(val, sizeof(val)-1)
-#define ATTR_CONST_SINGLE(attr, blob, nam, val) do { \
- attr.name = nam; \
- attr.num_values = ARRAY_SIZE(blob); \
- attr.values = blob; \
- blob[0] = ATTR_BLOB_CONST(val); \
-} while(0)
-#define ATTR_CONST_SINGLE_NOVAL(attr, blob, nam) do { \
- attr.name = nam;\
- attr.num_values = ARRAY_SIZE(blob); \
- attr.values = blob;\
-} while(0)
- TALLOC_CTX *mem_ctx;
- struct ldap_attribute attrs[3];
- DATA_BLOB currentTime[1];
- DATA_BLOB supportedLDAPVersion[2];
- DATA_BLOB dnsHostName[1];
-
- mem_ctx = talloc_init("rootDSE");
- if (!mem_ctx) {
- ldapsrv_terminate_connection(conn, "no memory");
- return;
+ if (gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL)) {
+ status = gensec_seal_packet(conn->gensec, mem_ctx,
+ tmp_blob.data, tmp_blob.length,
+ tmp_blob.data, tmp_blob.length,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("gensec_seal_packet: %s\n",nt_errstr(status)));
+ talloc_free(mem_ctx);
+ return False;
}
+ } else {
+ status = gensec_sign_packet(conn->gensec, mem_ctx,
+ tmp_blob.data, tmp_blob.length,
+ tmp_blob.data, tmp_blob.length,
+ &creds);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("gensec_sign_packet: %s\n",nt_errstr(status)));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
- /*
- * currentTime
- * 20040918090350.0Z
- */
- ATTR_CONST_SINGLE_NOVAL(attrs[0], currentTime, "currentTime");
- {
- char *str = ldap_timestring(mem_ctx, time(NULL));
- if (!str) {
- ldapsrv_terminate_connection(conn, "no memory");
- return;
- }
- currentTime[0] = data_blob(str, strlen(str));
- talloc_free(str);
- }
+ sasl = data_blob_talloc(mem_ctx, NULL, 4 + creds.length + tmp_blob.length);
+ if (!sasl.data) {
+ DEBUG(0,("no memory\n"));
+ talloc_free(mem_ctx);
+ return False;
+ }
- /*
- * subschemaSubentry
- * CN=Aggregate,CN=Schema,CN=Configuration,DC=DOM,DC=TLD
- */
-
- /*
- * dsServiceName
- * CN=NTDS Settings,CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
- */
-
- /*
- * namingContexts
- * DC=DOM,DC=TLD
- * CN=Configuration,DC=DOM,DC=TLD
- * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
- * DC=DomainDnsZones,DC=DOM,DC=TLD
- * DC=ForestDnsZones,DC=DOM,DC=TLD
- */
-
- /*
- * defaultNamingContext
- * DC=DOM,DC=TLD
- */
-
- /*
- * schemaNamingContext
- * CN=Schema,CN=Configuration,DC=DOM,DC=TLD
- */
-
- /*
- * configurationNamingContext
- * CN=Configuration,DC=DOM,DC=TLD
- */
-
- /*
- * rootDomainNamingContext
- * DC=DOM,DC=TLD
- */
-
- /*
- * supportedControl
- * 1.2.840.113556.1.4.319
- * 1.2.840.113556.1.4.801
- * 1.2.840.113556.1.4.473
- * 1.2.840.113556.1.4.528
- * 1.2.840.113556.1.4.417
- * 1.2.840.113556.1.4.619
- * 1.2.840.113556.1.4.841
- * 1.2.840.113556.1.4.529
- * 1.2.840.113556.1.4.805
- * 1.2.840.113556.1.4.521
- * 1.2.840.113556.1.4.970
- * 1.2.840.113556.1.4.1338
- * 1.2.840.113556.1.4.474
- * 1.2.840.113556.1.4.1339
- * 1.2.840.113556.1.4.1340
- * 1.2.840.113556.1.4.1413
- * 2.16.840.1.113730.3.4.9
- * 2.16.840.1.113730.3.4.10
- * 1.2.840.113556.1.4.1504
- * 1.2.840.113556.1.4.1852
- * 1.2.840.113556.1.4.802
- */
-
- /*
- * supportedLDAPVersion
- * 3
- * 2
- */
- ATTR_CONST_SINGLE_NOVAL(attrs[1], supportedLDAPVersion, "supportedLDAPVersion");
- supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
- supportedLDAPVersion[1] = ATTR_BLOB_CONST("2");
-
- /*
- * supportedLDAPPolicies
- * MaxPoolThreads
- * MaxDatagramRecv
- * MaxReceiveBuffer
- * InitRecvTimeout
- * MaxConnections
- * MaxConnIdleTime
- * MaxPageSize
- * MaxQueryDuration
- * MaxTempTableSize
- * MaxResultSetSize
- * MaxNotificationPerConn
- * MaxValRange
- */
-
- /*
- * highestCommittedUSN
- * 4555
- */
-
- /*
- * supportedSASLMechanisms
- * GSSAPI
- * GSS-SPNEGO
- * EXTERNAL
- * DIGEST-MD5
- */
-
- /*
- * dnsHostName
- * netbiosname.dom.tld
- */
- ATTR_CONST_SINGLE_NOVAL(attrs[2], dnsHostName, "dnsHostName");
- dnsHostName[0] = data_blob(lp_netbios_name(),strlen(lp_netbios_name()));
-
- /*
- * ldapServiceName
- * dom.tld:netbiosname$@DOM.TLD
- */
-
- /*
- * serverName:
- * CN=NETBIOSNAME,CN=Servers,CN=Default-First-Site,CN=Sites,CN=Configuration,DC=DOM,DC=TLD
- */
-
- /*
- * supportedCapabilities
- * 1.2.840.113556.1.4.800
- * 1.2.840.113556.1.4.1670
- * 1.2.840.113556.1.4.1791
- */
-
- /*
- * isSynchronized:
- * TRUE/FALSE
- */
-
- /*
- * isGlobalCatalogReady
- * TRUE/FALSE
- */
-
- /*
- * domainFunctionality
- * 0
- */
-
- /*
- * forestFunctionality
- * 0
- */
-
- /*
- * domainControllerFunctionality
- * 2
- */
-
- msg->type = LDAP_TAG_SearchResultEntry;
- msg->r.SearchResultEntry.dn = "";
- msg->r.SearchResultEntry.num_attributes = ARRAY_SIZE(attrs);
- msg->r.SearchResultEntry.attributes = attrs;
-
- ldap_append_to_buf(msg, &conn->out_buffer);
+ RSIVAL(sasl.data, 0, creds.length + tmp_blob.length);
+ memcpy(sasl.data + 4, creds.data, creds.length);
+ memcpy(sasl.data + 4 + creds.length, tmp_blob.data, tmp_blob.length);
+
+ ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, sasl.data, sasl.length);
+ if (!ret) {
talloc_free(mem_ctx);
+ return False;
}
+ ldapsrv_consumed_from_buf(&conn->out_buffer, tmp_blob.length);
+nodata:
+ tmp_blob.data = conn->sasl_out_buffer.data;
+ tmp_blob.length = conn->sasl_out_buffer.length;
+
+ status = socket_send(sock, &tmp_blob, &sendlen, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ ldapsrv_consumed_from_buf(&conn->sasl_out_buffer, sendlen);
- msg->type = LDAP_TAG_SearchResultDone;
- resp->resultcode = 0;
- resp->dn = NULL;
- resp->errormessage = NULL;
- resp->referral = NULL;
+ talloc_free(mem_ctx);
- ldap_append_to_buf(msg, &conn->out_buffer);
- talloc_destroy(msg->mem_ctx);
+ return True;
}
-static void switch_ldap_message(struct ldapsrv_connection *conn,
- struct ldap_message *msg)
+static BOOL ldap_encode_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
{
- switch(msg->type) {
- case LDAP_TAG_BindRequest:
- ldap_reply_BindRequest(conn, msg);
- break;
- case LDAP_TAG_SearchRequest:
- ldap_reply_SearchRequest(conn, msg);
- break;
- default:
- reply_unwilling(conn, 2);
- break;
- }
+ DATA_BLOB blob;
+ BOOL res;
+
+ if (!ldap_encode(msg, &blob))
+ return False;
+
+ res = ldapsrv_append_to_buf(buf, blob.data, blob.length);
+
+ data_blob_free(&blob);
+ return res;
}
-static void ldap_queue_run(struct server_connection *conn)
+NTSTATUS ldapsrv_do_responses(struct ldapsrv_connection *conn)
{
- struct ldapsrv_connection *ldap_conn = conn->private_data;
-
- while (ldap_conn->in_queue) {
- struct ldap_message_queue *req = ldap_conn->in_queue;
- DLIST_REMOVE(ldap_conn->in_queue, req);
+ struct ldapsrv_call *call, *next_call = NULL;
+ struct ldapsrv_reply *reply, *next_reply = NULL;
- switch_ldap_message(ldap_conn, req->msg);
- talloc_destroy(req->msg->mem_ctx);
+ for (call=conn->calls; call; call=next_call) {
+ for (reply=call->replies; reply; reply=next_reply) {
+ if (!ldap_encode_to_buf(&reply->msg, &conn->out_buffer)) {
+ return NT_STATUS_FOOBAR;
+ }
+ next_reply = reply->next;
+ DLIST_REMOVE(call->replies, reply);
+ reply->state = LDAPSRV_REPLY_STATE_SEND;
+ talloc_free(reply);
+ }
+ next_call = call->next;
+ DLIST_REMOVE(conn->calls, call);
+ call->state = LDAPSRV_CALL_STATE_COMPLETE;
+ talloc_free(call);
}
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS ldapsrv_flush_responses(struct ldapsrv_connection *conn)
+{
+ return NT_STATUS_OK;
}
/*
called when a LDAP socket becomes readable
*/
-static void ldapsrv_recv(struct server_connection *conn, time_t t,
+static void ldapsrv_recv(struct server_connection *conn, struct timeval t,
uint16_t flags)
{
struct ldapsrv_connection *ldap_conn = conn->private_data;
uint8_t *buf;
int buf_length, msg_length;
DATA_BLOB blob;
- ASN1_DATA data;
- struct ldap_message *msg;
- struct ldap_message_queue *queue_entry;
+ struct asn1_data data;
+ struct ldapsrv_call *call;
+ NTSTATUS status;
DEBUG(10,("ldapsrv_recv\n"));
- if (!read_into_buf(conn->event.fde->fd, &ldap_conn->in_buffer)) {
- ldapsrv_terminate_connection(ldap_conn, "read_into_buf() failed");
+ if (!ldapsrv_read_buf(ldap_conn)) {
+ ldapsrv_terminate_connection(ldap_conn, "ldapsrv_read_buf() failed");
return;
}
peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
while (buf_length > 0) {
-
/* LDAP Messages are always SEQUENCES */
if (!asn1_object_length(buf, buf_length, ASN1_SEQUENCE(0),
return;
}
- msg = new_ldap_message();
-
- if ((msg == NULL) || !ldap_decode(&data, msg)) {
- ldapsrv_terminate_connection(ldap_conn, "ldap_decode() failed");
- return;
+ call = talloc_p(ldap_conn, struct ldapsrv_call);
+ if (!call) {
+ ldapsrv_terminate_connection(ldap_conn, "no memory");
+ return;
}
- queue_entry = talloc_p(msg->mem_ctx, struct ldap_message_queue);
+ ZERO_STRUCTP(call);
+ call->state = LDAPSRV_CALL_STATE_NEW;
+ call->conn = ldap_conn;
+ call->request.mem_ctx = call;
- if (queue_entry == NULL) {
- ldapsrv_terminate_connection(ldap_conn, "alloc_p(msg->mem_ctx, struct ldap_message_queue) failed");
+ if (!ldap_decode(&data, &call->request)) {
+ dump_data(0,buf, msg_length);
+ asn1_free(&data);
+ ldapsrv_terminate_connection(ldap_conn, "ldap_decode() failed");
return;
}
- queue_entry->msg = msg;
+ asn1_free(&data);
+
+ DLIST_ADD_END(ldap_conn->calls, call,
+ struct ldapsrv_call *);
- DLIST_ADD_END(ldap_conn->in_queue, queue_entry,
- struct ldap_message_queue *);
+ ldapsrv_consumed_from_buf(&ldap_conn->in_buffer, msg_length);
- consumed_from_read_buf(&ldap_conn->in_buffer, msg_length);
+ status = ldapsrv_do_call(call);
+ if (!NT_STATUS_IS_OK(status)) {
+ ldapsrv_terminate_connection(ldap_conn, "ldapsrv_do_call() failed");
+ return;
+ }
peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
}
- ldap_queue_run(conn);
+ status = ldapsrv_do_responses(ldap_conn);
+ if (!NT_STATUS_IS_OK(status)) {
+ ldapsrv_terminate_connection(ldap_conn, "ldapsrv_do_responses() failed");
+ return;
+ }
- conn->event.fde->flags |= EVENT_FD_WRITE;
+ if ((ldap_conn->out_buffer.length > 0)||(ldap_conn->sasl_out_buffer.length > 0)) {
+ conn->event.fde->flags |= EVENT_FD_WRITE;
+ }
return;
}
/*
called when a LDAP socket becomes writable
*/
-static void ldapsrv_send(struct server_connection *conn, time_t t,
+static void ldapsrv_send(struct server_connection *conn, struct timeval t,
uint16_t flags)
{
struct ldapsrv_connection *ldap_conn = conn->private_data;
DEBUG(10,("ldapsrv_send\n"));
- if (!write_from_buf(conn->event.fde->fd, &ldap_conn->out_buffer)) {
- ldapsrv_terminate_connection(ldap_conn, "write_from_buf() failed");
+ if (!ldapsrv_write_buf(ldap_conn)) {
+ ldapsrv_terminate_connection(ldap_conn, "ldapsrv_write_buf() failed");
return;
}
- conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ if (ldap_conn->out_buffer.length == 0 && ldap_conn->sasl_out_buffer.length == 0) {
+ conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ }
return;
}
/*
called when connection is idle
*/
-static void ldapsrv_idle(struct server_connection *conn, time_t t)
+static void ldapsrv_idle(struct server_connection *conn, struct timeval t)
{
DEBUG(10,("ldapsrv_idle: not implemented!\n"));
return;
static void ldapsrv_close(struct server_connection *conn, const char *reason)
{
- struct ldapsrv_connection *ldap_conn = conn->private_data;
-
- talloc_free(ldap_conn);
-
return;
}
{
struct ldapsrv_connection *ldap_conn;
- DEBUG(5, ("ldapsrv_accept\n"));
+ DEBUG(10, ("ldapsrv_accept\n"));
- ldap_conn = talloc_p(NULL, struct ldapsrv_connection);
+ ldap_conn = talloc_p(conn, struct ldapsrv_connection);
if (ldap_conn == NULL)
return;
ZERO_STRUCTP(ldap_conn);
ldap_conn->connection = conn;
+ ldap_conn->service = talloc_reference(ldap_conn, conn->service->private_data);
conn->private_data = ldap_conn;
-
+
return;
}
*/
static void ldapsrv_exit(struct server_service *service, const char *reason)
{
- DEBUG(1,("ldapsrv_exit\n"));
+ DEBUG(10,("ldapsrv_exit\n"));
return;
}