summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/gensec/config.mk11
-rw-r--r--source4/auth/gensec/socket.c421
-rw-r--r--source4/auth/gensec/socket.h27
-rw-r--r--source4/auth/gensec/spnego.c62
-rw-r--r--source4/ldap_server/config.mk2
-rw-r--r--source4/ldap_server/ldap_bind.c28
-rw-r--r--source4/ldap_server/ldap_server.c127
-rw-r--r--source4/ldap_server/ldap_server.h7
-rw-r--r--source4/lib/socket/socket.c25
-rw-r--r--source4/lib/socket/socket.h8
-rw-r--r--source4/lib/stream/packet.c33
-rw-r--r--source4/lib/stream/packet.h6
-rw-r--r--source4/lib/tls/tls.c4
-rw-r--r--source4/libcli/ldap/config.mk2
-rw-r--r--source4/libcli/ldap/ldap_bind.c22
-rw-r--r--source4/libcli/ldap/ldap_client.c94
-rw-r--r--source4/libcli/ldap/ldap_client.h3
-rw-r--r--source4/smbd/service_stream.c5
18 files changed, 639 insertions, 248 deletions
diff --git a/source4/auth/gensec/config.mk b/source4/auth/gensec/config.mk
index 5aeca28689..0aaf82949e 100644
--- a/source4/auth/gensec/config.mk
+++ b/source4/auth/gensec/config.mk
@@ -67,3 +67,14 @@ OBJ_FILES = \
# End SUBSYSTEM SCHANNELDB
################################################
+################################################
+# Start SUBSYSTEM GENSEC_SOCKET
+[SUBSYSTEM::GENSEC_SOCKET]
+OBJ_FILES = \
+ socket.o
+PUBLIC_DEPENDENCIES = samba-socket
+#PUBLIC_DEPENDENCIES = gensec
+#
+# End SUBSYSTEM GENSEC_SOCKET
+################################################
+
diff --git a/source4/auth/gensec/socket.c b/source4/auth/gensec/socket.c
new file mode 100644
index 0000000000..f308f72712
--- /dev/null
+++ b/source4/auth/gensec/socket.c
@@ -0,0 +1,421 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ GENSEC socket interface
+
+ Copyright (C) Andrew Bartlett 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "lib/socket/socket.h"
+#include "lib/stream/packet.h"
+#include "auth/gensec/gensec.h"
+
+static const struct socket_ops gensec_socket_ops;
+
+struct gensec_socket {
+ struct gensec_security *gensec_security;
+ struct socket_context *socket;
+ struct event_context *ev;
+ struct packet_context *packet;
+ DATA_BLOB read_buffer; /* SASL packets are turned into liniarlised data here, for reading */
+ size_t orig_send_len;
+ BOOL eof;
+ NTSTATUS error;
+ BOOL interrupted;
+ void (*recv_handler)(void *, uint16_t);
+ void *recv_private;
+ int in_extra_read;
+};
+
+static NTSTATUS gensec_socket_init_fn(struct socket_context *sock)
+{
+ switch (sock->type) {
+ case SOCKET_TYPE_STREAM:
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ sock->backend_name = "gensec";
+
+ return NT_STATUS_OK;
+}
+
+/* Try to figure out how much data is waiting to be read */
+static NTSTATUS gensec_socket_pending(struct socket_context *sock, size_t *npending)
+{
+ struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
+ if (gensec_socket->read_buffer.length > 0) {
+ *npending = gensec_socket->read_buffer.length;
+ return NT_STATUS_OK;
+ }
+
+ /* This is a lie. We hope the decrypted data will always be
+ * less than this value, so the application just gets a short
+ * read. Without reading and decrypting it, we can't tell.
+ * If the SASL mech does compression, then we just need to
+ * manually trigger read events */
+ return socket_pending(gensec_socket->socket, npending);
+}
+
+/* Note if an error occours, so we can return it up the stack */
+static void gensec_socket_error_handler(void *private, NTSTATUS status)
+{
+ struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
+ gensec_socket->eof = True;
+ } else {
+ gensec_socket->error = status;
+ }
+}
+
+static void gensec_socket_trigger_read(struct event_context *ev,
+ struct timed_event *te,
+ struct timeval t, void *private)
+{
+ struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
+
+ gensec_socket->in_extra_read++;
+ gensec_socket->recv_handler(gensec_socket->recv_private, EVENT_FD_READ);
+ gensec_socket->in_extra_read--;
+
+ /* It may well be that, having run the recv handler, we still
+ * have even more data waiting for us!
+ */
+ if (gensec_socket->read_buffer.length && gensec_socket->recv_handler) {
+ /* Schedule this funcion to run again */
+ event_add_timed(gensec_socket->ev, gensec_socket, timeval_zero(),
+ gensec_socket_trigger_read, gensec_socket);
+ }
+}
+
+/* These two routines could be changed to use a circular buffer of
+ * some kind, or linked lists, or ... */
+static NTSTATUS gensec_socket_recv(struct socket_context *sock, void *buf,
+ size_t wantlen, size_t *nread)
+{
+ struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
+
+ gensec_socket->error = NT_STATUS_OK;
+
+ if (gensec_socket->read_buffer.length == 0) {
+ /* Process any data on the socket, into the read buffer. At
+ * this point, the socket is not available for read any
+ * longer */
+ packet_recv(gensec_socket->packet);
+
+ if (gensec_socket->eof) {
+ *nread = 0;
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(gensec_socket->error)) {
+ return gensec_socket->error;
+ }
+
+ if (gensec_socket->read_buffer.length == 0) {
+ /* Clearly we don't have the entire SASL packet yet,
+ * so it has not been written into the buffer */
+ *nread = 0;
+ return STATUS_MORE_ENTRIES;
+ }
+ }
+
+
+ *nread = MIN(wantlen, gensec_socket->read_buffer.length);
+ memcpy(buf, gensec_socket->read_buffer.data, *nread);
+
+ if (gensec_socket->read_buffer.length > *nread) {
+ memmove(gensec_socket->read_buffer.data,
+ gensec_socket->read_buffer.data + *nread,
+ gensec_socket->read_buffer.length - *nread);
+ }
+
+ gensec_socket->read_buffer.length -= *nread;
+ gensec_socket->read_buffer.data = talloc_realloc(gensec_socket,
+ gensec_socket->read_buffer.data,
+ uint8_t,
+ gensec_socket->read_buffer.length);
+
+ if (gensec_socket->read_buffer.length &&
+ gensec_socket->in_extra_read == 0 &&
+ gensec_socket->recv_handler) {
+ /* Manually call a read event, to get this moving
+ * again (as the socket should be dry, so the normal
+ * event handler won't trigger) */
+ event_add_timed(gensec_socket->ev, gensec_socket, timeval_zero(),
+ gensec_socket_trigger_read, gensec_socket);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/* Completed SASL packet callback. When we have a 'whole' SASL
+ * packet, decrypt it, and add it to the read buffer
+ *
+ * This function (and anything under it) MUST NOT call the event system
+ */
+static NTSTATUS gensec_socket_unwrap(void *private, DATA_BLOB blob)
+{
+ struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
+ DATA_BLOB wrapped;
+ DATA_BLOB unwrapped;
+ NTSTATUS nt_status;
+ TALLOC_CTX *mem_ctx;
+ uint32_t packet_size;
+
+ if (blob.length < 4) {
+ /* Missing the header we already had! */
+ DEBUG(0, ("Asked to unwrap packed of bogus length! How did we get the short packet?!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ wrapped = data_blob_const(blob.data + 4, blob.length - 4);
+
+ packet_size = RIVAL(blob.data, 0);
+ if (packet_size != wrapped.length) {
+ DEBUG(0, ("Asked to unwrap packed of bogus length! How did we get this?!\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ mem_ctx = talloc_new(gensec_socket);
+ if (!mem_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ nt_status = gensec_unwrap(gensec_socket->gensec_security,
+ mem_ctx,
+ &wrapped, &unwrapped);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
+ /* We could change this into a linked list, and have
+ * gensec_socket_recv() and gensec_socket_pending() walk the
+ * linked list */
+
+ nt_status = data_blob_append(gensec_socket, &gensec_socket->read_buffer,
+ unwrapped.data, unwrapped.length);
+ talloc_free(mem_ctx);
+ return nt_status;
+}
+
+/* when the data is sent, we know we have not been interrupted */
+static void send_callback(void *private)
+{
+ struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
+ gensec_socket->interrupted = False;
+}
+
+/*
+ send data, but only as much as we allow in one packet.
+
+ If this returns STATUS_MORE_ENTRIES, the caller must retry with
+ exactly the same data, or a NULL blob.
+*/
+static NTSTATUS gensec_socket_send(struct socket_context *sock,
+ const DATA_BLOB *blob, size_t *sendlen)
+{
+ NTSTATUS nt_status;
+ struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
+ DATA_BLOB unwrapped, wrapped, out;
+ TALLOC_CTX *mem_ctx;
+ size_t max_input_size;
+
+ *sendlen = 0;
+
+ /* We have have been interupted, so the caller should be
+ * giving us the same data again. */
+ if (gensec_socket->interrupted) {
+ packet_queue_run(gensec_socket->packet);
+
+ if (!NT_STATUS_IS_OK(gensec_socket->error)) {
+ return gensec_socket->error;
+ } else if (gensec_socket->interrupted) {
+ return STATUS_MORE_ENTRIES;
+ } else {
+ *sendlen = gensec_socket->orig_send_len;
+ gensec_socket->orig_send_len = 0;
+ return NT_STATUS_OK;
+ }
+ }
+
+ mem_ctx = talloc_new(gensec_socket);
+ if (!mem_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ max_input_size = gensec_max_input_size(gensec_socket->gensec_security);
+ unwrapped = data_blob_const(blob->data, MIN(max_input_size, (size_t)blob->length));
+
+ nt_status = gensec_wrap(gensec_socket->gensec_security,
+ mem_ctx,
+ &unwrapped, &wrapped);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
+
+ out = data_blob_talloc(mem_ctx, NULL, 4);
+ if (!out.data) {
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ RSIVAL(out.data, 0, wrapped.length);
+
+ nt_status = data_blob_append(gensec_socket, &out, wrapped.data, wrapped.length);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
+
+ gensec_socket->interrupted = True;
+ gensec_socket->error = NT_STATUS_OK;
+ gensec_socket->orig_send_len
+ = unwrapped.length;
+
+ nt_status = packet_send_callback(gensec_socket->packet,
+ out,
+ send_callback, gensec_socket);
+
+ talloc_free(mem_ctx);
+
+ packet_queue_run(gensec_socket->packet);
+
+ if (!NT_STATUS_IS_OK(gensec_socket->error)) {
+ return gensec_socket->error;
+ } else if (gensec_socket->interrupted) {
+ return STATUS_MORE_ENTRIES;
+ } else {
+ *sendlen = gensec_socket->orig_send_len;
+ gensec_socket->orig_send_len = 0;
+ return NT_STATUS_OK;
+ }
+}
+
+struct socket_context *gensec_socket_init(struct gensec_security *gensec_security,
+ struct socket_context *socket,
+ struct event_context *ev,
+ void (*recv_handler)(void *, uint16_t),
+ void *recv_private)
+{
+ struct gensec_socket *gensec_socket;
+ struct socket_context *new_sock;
+ NTSTATUS nt_status;
+
+ /* Nothing to do here, if we are not actually wrapping on this socket */
+ if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) &&
+ !gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
+ return socket;
+ }
+
+ nt_status = socket_create_with_ops(socket, &gensec_socket_ops, &new_sock,
+ SOCKET_TYPE_STREAM, socket->flags | SOCKET_FLAG_ENCRYPT);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return NULL;
+ }
+
+ gensec_socket = talloc(new_sock, struct gensec_socket);
+ if (gensec_socket == NULL) {
+ return NULL;
+ }
+
+ gensec_socket->eof = False;
+ gensec_socket->error = NT_STATUS_OK;
+ gensec_socket->interrupted = False;
+ gensec_socket->in_extra_read = 0;
+
+ gensec_socket->read_buffer = data_blob(NULL, 0);
+
+ gensec_socket->gensec_security = gensec_security;
+ gensec_socket->socket = socket;
+ if (talloc_reference(gensec_socket, socket) == NULL) {
+ return NULL;
+ }
+ gensec_socket->recv_handler = recv_handler;
+ gensec_socket->recv_private = recv_private;
+ gensec_socket->ev = ev;
+
+ new_sock->private_data = gensec_socket;
+
+ gensec_socket->packet = packet_init(gensec_socket);
+ if (gensec_socket->packet == NULL) {
+ return NULL;
+ }
+
+ packet_set_private(gensec_socket->packet, gensec_socket);
+ packet_set_socket(gensec_socket->packet, socket);
+ packet_set_callback(gensec_socket->packet, gensec_socket_unwrap);
+ packet_set_full_request(gensec_socket->packet, packet_full_request_u32);
+ packet_set_error_handler(gensec_socket->packet, gensec_socket_error_handler);
+ packet_set_serialise(gensec_socket->packet);
+
+ /* TODO: full-request that knows about maximum packet size */
+
+ new_sock->state = socket->state;
+
+ return new_sock;
+}
+
+
+static NTSTATUS gensec_socket_set_option(struct socket_context *sock, const char *option, const char *val)
+{
+ set_socket_options(socket_get_fd(sock), option);
+ return NT_STATUS_OK;
+}
+
+static char *gensec_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
+ return socket_get_peer_name(gensec->socket, mem_ctx);
+}
+
+static struct socket_address *gensec_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
+ return socket_get_peer_addr(gensec->socket, mem_ctx);
+}
+
+static struct socket_address *gensec_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+{
+ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
+ return socket_get_my_addr(gensec->socket, mem_ctx);
+}
+
+static int gensec_socket_get_fd(struct socket_context *sock)
+{
+ struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
+ return socket_get_fd(gensec->socket);
+}
+
+static const struct socket_ops gensec_socket_ops = {
+ .name = "gensec",
+ .fn_init = gensec_socket_init_fn,
+ .fn_recv = gensec_socket_recv,
+ .fn_send = gensec_socket_send,
+ .fn_pending = gensec_socket_pending,
+
+ .fn_set_option = gensec_socket_set_option,
+
+ .fn_get_peer_name = gensec_socket_get_peer_name,
+ .fn_get_peer_addr = gensec_socket_get_peer_addr,
+ .fn_get_my_addr = gensec_socket_get_my_addr,
+ .fn_get_fd = gensec_socket_get_fd
+};
+
diff --git a/source4/auth/gensec/socket.h b/source4/auth/gensec/socket.h
new file mode 100644
index 0000000000..1641e50868
--- /dev/null
+++ b/source4/auth/gensec/socket.h
@@ -0,0 +1,27 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Generic Authentication Interface (socket wrapper)
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+struct socket_context *gensec_socket_init(struct gensec_security *gensec_security,
+ struct socket_context *socket,
+ struct event_context *ev,
+ void (*recv_handler)(void *, uint16_t),
+ void *recv_private);
diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c
index 6ede774cc8..a57e8cc846 100644
--- a/source4/auth/gensec/spnego.c
+++ b/source4/auth/gensec/spnego.c
@@ -211,6 +211,30 @@ static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security, si
return gensec_sig_size(spnego_state->sub_sec_security, data_size);
}
+static size_t gensec_spnego_max_input_size(struct gensec_security *gensec_security)
+{
+ struct spnego_state *spnego_state = gensec_security->private_data;
+
+ if (spnego_state->state_position != SPNEGO_DONE
+ && spnego_state->state_position != SPNEGO_FALLBACK) {
+ return 0;
+ }
+
+ return gensec_max_input_size(spnego_state->sub_sec_security);
+}
+
+static size_t gensec_spnego_max_wrapped_size(struct gensec_security *gensec_security)
+{
+ struct spnego_state *spnego_state = gensec_security->private_data;
+
+ if (spnego_state->state_position != SPNEGO_DONE
+ && spnego_state->state_position != SPNEGO_FALLBACK) {
+ return 0;
+ }
+
+ return gensec_max_wrapped_size(spnego_state->sub_sec_security);
+}
+
static NTSTATUS gensec_spnego_session_key(struct gensec_security *gensec_security,
DATA_BLOB *session_key)
{
@@ -938,24 +962,26 @@ static const char *gensec_spnego_oids[] = {
};
static const struct gensec_security_ops gensec_spnego_security_ops = {
- .name = "spnego",
- .sasl_name = "GSS-SPNEGO",
- .auth_type = DCERPC_AUTH_TYPE_SPNEGO,
- .oid = gensec_spnego_oids,
- .client_start = gensec_spnego_client_start,
- .server_start = gensec_spnego_server_start,
- .update = gensec_spnego_update,
- .seal_packet = gensec_spnego_seal_packet,
- .sign_packet = gensec_spnego_sign_packet,
- .sig_size = gensec_spnego_sig_size,
- .check_packet = gensec_spnego_check_packet,
- .unseal_packet = gensec_spnego_unseal_packet,
- .wrap = gensec_spnego_wrap,
- .unwrap = gensec_spnego_unwrap,
- .session_key = gensec_spnego_session_key,
- .session_info = gensec_spnego_session_info,
- .have_feature = gensec_spnego_have_feature,
- .enabled = True,
+ .name = "spnego",
+ .sasl_name = "GSS-SPNEGO",
+ .auth_type = DCERPC_AUTH_TYPE_SPNEGO,
+ .oid = gensec_spnego_oids,
+ .client_start = gensec_spnego_client_start,
+ .server_start = gensec_spnego_server_start,
+ .update = gensec_spnego_update,
+ .seal_packet = gensec_spnego_seal_packet,
+ .sign_packet = gensec_spnego_sign_packet,
+ .sig_size = gensec_spnego_sig_size,
+ .max_wrapped_size = gensec_spnego_max_wrapped_size,
+ .max_input_size = gensec_spnego_max_input_size,
+ .check_packet = gensec_spnego_check_packet,
+ .unseal_packet = gensec_spnego_unseal_packet,
+ .wrap = gensec_spnego_wrap,
+ .unwrap = gensec_spnego_unwrap,
+ .session_key = gensec_spnego_session_key,
+ .session_info = gensec_spnego_session_info,
+ .have_feature = gensec_spnego_have_feature,
+ .enabled = True,
};
NTSTATUS gensec_spnego_init(void)
diff --git a/source4/ldap_server/config.mk b/source4/ldap_server/config.mk
index 0ef8ced928..fc9d04c46a 100644
--- a/source4/ldap_server/config.mk
+++ b/source4/ldap_server/config.mk
@@ -11,6 +11,6 @@ OBJ_FILES = \
ldap_backend.o \
ldap_bind.o
PUBLIC_DEPENDENCIES = \
- LIBCLI_LDAP SAMDB process_model auth
+ LIBCLI_LDAP SAMDB process_model auth GENSEC_SOCKET
# End SUBSYSTEM SMB
#######################
diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c
index 35b6ad5fbf..7fce390450 100644
--- a/source4/ldap_server/ldap_bind.c
+++ b/source4/ldap_server/ldap_bind.c
@@ -22,10 +22,11 @@
#include "ldap_server/ldap_server.h"
#include "auth/auth.h"
#include "libcli/ldap/ldap.h"
-#include "smbd/service_stream.h"
+#include "smbd/service.h"
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
#include "dsdb/samdb/samdb.h"
+#include "auth/gensec/socket.h"
static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
{
@@ -89,6 +90,23 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
return NT_STATUS_OK;
}
+static void ldapsrv_set_sasl(void *private)
+{
+ struct ldapsrv_connection *conn = talloc_get_type(private, struct ldapsrv_connection);
+ struct socket_context *socket = gensec_socket_init(conn->gensec,
+ conn->connection->socket,
+ conn->connection->event.ctx,
+ stream_io_handler_callback,
+ conn->connection);
+ if (socket) {
+ conn->connection->socket = socket;
+ talloc_steal(conn->connection->socket, socket);
+ packet_set_socket(conn->packet, socket);
+ } else {
+ ldapsrv_terminate_connection(conn, "Failed to setup SASL wrapping on socket");
+ }
+}
+
static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
{
struct ldap_BindRequest *req = &call->request->r.BindRequest;
@@ -175,10 +193,10 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
result = LDAP_SUCCESS;
errstr = NULL;
- if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL) ||
- gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
- conn->enable_wrap = True;
- }
+
+ call->send_callback = ldapsrv_set_sasl;
+ call->send_private = conn;
+
old_session_info = conn->session_info;
conn->session_info = NULL;
status = gensec_session_info(conn->gensec, &conn->session_info);
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 07b1bc6a27..cfbe6eb5b2 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -31,10 +31,8 @@
#include "smbd/service_task.h"
#include "smbd/service_stream.h"
#include "smbd/service.h"
-#include "lib/socket/socket.h"
#include "lib/tls/tls.h"
#include "lib/messaging/irpc.h"
-#include "lib/stream/packet.h"
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
#include "system/network.h"
@@ -43,7 +41,7 @@
/*
close the socket and shutdown a server_context
*/
-static void ldapsrv_terminate_connection(struct ldapsrv_connection *conn,
+void ldapsrv_terminate_connection(struct ldapsrv_connection *conn,
const char *reason)
{
stream_terminate_connection(conn->connection, reason);
@@ -68,7 +66,6 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
struct ldapsrv_call *call;
NTSTATUS status;
DATA_BLOB blob;
- BOOL enable_wrap = conn->enable_wrap;
call = talloc(conn, struct ldapsrv_call);
if (!call) {
@@ -79,11 +76,14 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
call->request = talloc_steal(call, msg);
call->conn = conn;
call->replies = NULL;
-
+ call->send_callback = NULL;
+ call->send_private = NULL;
+
/* make the call */
status = ldapsrv_do_call(call);
if (!NT_STATUS_IS_OK(status)) {
- goto failed;
+ talloc_free(call);
+ return;
}
blob = data_blob(NULL, 0);
@@ -100,49 +100,36 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
msg = call->replies->msg;
if (!ldap_encode(msg, &b, call)) {
DEBUG(0,("Failed to encode ldap reply of type %d\n", msg->type));
- goto failed;
+ talloc_free(call);
+ return;
}
status = data_blob_append(call, &blob, b.data, b.length);
data_blob_free(&b);
- if (!NT_STATUS_IS_OK(status)) goto failed;
-
- DLIST_REMOVE(call->replies, call->replies);
- }
+ talloc_set_name_const(blob.data, "Outgoing, encoded LDAP packet");
- /* possibly encrypt/sign the reply */
- if (enable_wrap) {
- DATA_BLOB wrapped;
-
- status = gensec_wrap(conn->gensec, call, &blob, &wrapped);
if (!NT_STATUS_IS_OK(status)) {
- goto failed;
- }
- data_blob_free(&blob);
- blob = data_blob_talloc(call, NULL, wrapped.length + 4);
- if (blob.data == NULL) {
- goto failed;
+ talloc_free(call);
+ return;
}
- RSIVAL(blob.data, 0, wrapped.length);
- memcpy(blob.data+4, wrapped.data, wrapped.length);
- data_blob_free(&wrapped);
+
+ DLIST_REMOVE(call->replies, call->replies);
}
- packet_send(conn->packet, blob);
+ packet_send_callback(conn->packet, blob,
+ call->send_callback, call->send_private);
talloc_free(call);
return;
-
-failed:
- talloc_free(call);
}
-
/*
- decode the input buffer
+ decode/process data
*/
-static NTSTATUS ldapsrv_decode_plain(struct ldapsrv_connection *conn, DATA_BLOB blob)
+static NTSTATUS ldapsrv_decode(void *private, DATA_BLOB blob)
{
+ struct ldapsrv_connection *conn = talloc_get_type(private,
+ struct ldapsrv_connection);
struct asn1_data asn1;
struct ldap_message *msg = talloc(conn, struct ldap_message);
@@ -165,63 +152,6 @@ static NTSTATUS ldapsrv_decode_plain(struct ldapsrv_connection *conn, DATA_BLOB
return NT_STATUS_OK;
}
-
-/*
- decode/process wrapped data
-*/
-static NTSTATUS ldapsrv_decode_wrapped(struct ldapsrv_connection *conn,
- DATA_BLOB blob)
-{
- DATA_BLOB wrapped, unwrapped;
- struct asn1_data asn1;
- struct ldap_message *msg = talloc(conn, struct ldap_message);
- NTSTATUS status;
-
- if (msg == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- wrapped = data_blob_const(blob.data+4, blob.length-4);
-
- status = gensec_unwrap(conn->gensec, msg, &wrapped, &unwrapped);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
- }
-
- data_blob_free(&blob);
-
- if (!asn1_load(&asn1, unwrapped)) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
- }
-
- while (ldap_decode(&asn1, msg)) {
- ldapsrv_process_message(conn, msg);
- msg = talloc(conn, struct ldap_message);
- }
-
- if (asn1.ofs < asn1.length) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
- }
-
- talloc_free(msg);
- asn1_free(&asn1);
-
- return NT_STATUS_OK;
-}
-
-/*
- decode/process data
-*/
-static NTSTATUS ldapsrv_decode(void *private, DATA_BLOB blob)
-{
- struct ldapsrv_connection *conn = talloc_get_type(private,
- struct ldapsrv_connection);
- if (conn->enable_wrap) {
- return ldapsrv_decode_wrapped(conn, blob);
- }
- return ldapsrv_decode_plain(conn, blob);
-}
-
/*
Idle timeout handler
*/
@@ -238,7 +168,7 @@ static void ldapsrv_conn_idle_timeout(struct event_context *ev,
/*
called when a LDAP socket becomes readable
*/
-static void ldapsrv_recv(struct stream_connection *c, uint16_t flags)
+void ldapsrv_recv(struct stream_connection *c, uint16_t flags)
{
struct ldapsrv_connection *conn =
talloc_get_type(c->private, struct ldapsrv_connection);
@@ -262,20 +192,6 @@ static void ldapsrv_recv(struct stream_connection *c, uint16_t flags)
}
/*
- check if a blob is a complete ldap packet
- handle wrapper or unwrapped connections
-*/
-NTSTATUS ldapsrv_complete_packet(void *private, DATA_BLOB blob, size_t *size)
-{
- struct ldapsrv_connection *conn = talloc_get_type(private,
- struct ldapsrv_connection);
- if (conn->enable_wrap) {
- return packet_full_request_u32(private, blob, size);
- }
- return ldap_full_packet(private, blob, size);
-}
-
-/*
called when a LDAP socket becomes writable
*/
static void ldapsrv_send(struct stream_connection *c, uint16_t flags)
@@ -411,7 +327,6 @@ static void ldapsrv_accept(struct stream_connection *c)
return;
}
- conn->enable_wrap = False;
conn->packet = NULL;
conn->connection = c;
conn->service = ldapsrv_service;
@@ -445,7 +360,7 @@ static void ldapsrv_accept(struct stream_connection *c)
packet_set_private(conn->packet, conn);
packet_set_socket(conn->packet, c->socket);
packet_set_callback(conn->packet, ldapsrv_decode);
- packet_set_full_request(conn->packet, ldapsrv_complete_packet);
+ packet_set_full_request(conn->packet, ldap_full_packet);
packet_set_error_handler(conn->packet, ldapsrv_error_handler);
packet_set_event_context(conn->packet, c->event.ctx);
packet_set_fde(conn->packet, c->event.fde);
diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h
index 0b0b78ea7f..c35f62f134 100644
--- a/source4/ldap_server/ldap_server.h
+++ b/source4/ldap_server/ldap_server.h
@@ -20,6 +20,8 @@
*/
#include "libcli/ldap/ldap.h"
+#include "lib/socket/socket.h"
+#include "lib/stream/packet.h"
struct ldapsrv_connection {
struct stream_connection *connection;
@@ -29,9 +31,6 @@ struct ldapsrv_connection {
struct cli_credentials *server_credentials;
struct ldb_context *ldb;
- /* are we using gensec wrapping? */
- BOOL enable_wrap;
-
BOOL global_catalog;
struct packet_context *packet;
@@ -54,6 +53,8 @@ struct ldapsrv_call {
struct ldapsrv_reply *prev, *next;
struct ldap_message *msg;
} *replies;
+ packet_send_callback_fn_t send_callback;
+ void *send_private;
};
struct ldapsrv_service;
diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c
index ac64bc4ddc..eca668885c 100644
--- a/source4/lib/socket/socket.c
+++ b/source4/lib/socket/socket.c
@@ -189,15 +189,9 @@ _PUBLIC_ NTSTATUS socket_recv(struct socket_context *sock, void *buf,
if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK)
&& wantlen > 1) {
- /* The returning of 0 and MORE_ENTRIES is incompatible
- with TLS and SASL sockets, as there is not a
- constant event source to re-trigger the reads */
-
- if (!(sock->flags & SOCKET_FLAG_FAKE)) {
- if (random() % 10 == 0) {
- *nread = 0;
- return STATUS_MORE_ENTRIES;
- }
+ if (random() % 10 == 0) {
+ *nread = 0;
+ return STATUS_MORE_ENTRIES;
}
return sock->ops->fn_recv(sock, buf, 1+(random() % wantlen), nread);
}
@@ -240,17 +234,22 @@ _PUBLIC_ NTSTATUS socket_send(struct socket_context *sock,
if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK)
&& blob->length > 1) {
+ DATA_BLOB blob2 = *blob;
if (random() % 10 == 0) {
*sendlen = 0;
return STATUS_MORE_ENTRIES;
}
- /* The variable size sends are incompatilbe with TLS and SASL
+ /* The random size sends are incompatible with TLS and SASL
* sockets, which require re-sends to be consistant */
- if (!(sock->flags & SOCKET_FLAG_FAKE)) {
- DATA_BLOB blob2 = *blob;
+ if (!(sock->flags & SOCKET_FLAG_ENCRYPT)) {
blob2.length = 1+(random() % blob2.length);
- return sock->ops->fn_send(sock, &blob2, sendlen);
+ } else {
+ /* This is particularly stressful on buggy
+ * LDAP clients, that don't expect on LDAP
+ * packet in many SASL packets */
+ blob2.length = 1 + blob2.length/2;
}
+ return sock->ops->fn_send(sock, &blob2, sendlen);
}
return sock->ops->fn_send(sock, blob, sendlen);
}
diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h
index c0cf429887..025fc7e13d 100644
--- a/source4/lib/socket/socket.h
+++ b/source4/lib/socket/socket.h
@@ -102,7 +102,13 @@ enum socket_state {
#define SOCKET_FLAG_BLOCK 0x00000001
#define SOCKET_FLAG_PEEK 0x00000002
#define SOCKET_FLAG_TESTNONBLOCK 0x00000004
-#define SOCKET_FLAG_FAKE 0x00000008 /* This is an implementation not directly on top of a real socket */
+#define SOCKET_FLAG_ENCRYPT 0x00000008 /* This socket
+ * implementation requires
+ * that re-sends be
+ * consistant, because it
+ * is encrypting data.
+ * This modifies the
+ * TESTNONBLOCK case */
struct socket_context {
enum socket_type type;
diff --git a/source4/lib/stream/packet.c b/source4/lib/stream/packet.c
index e06f4985ef..2759c75214 100644
--- a/source4/lib/stream/packet.c
+++ b/source4/lib/stream/packet.c
@@ -28,7 +28,6 @@
#include "lib/socket/socket.h"
#include "lib/stream/packet.h"
-
struct packet_context {
packet_callback_fn_t callback;
packet_full_request_fn_t full_request;
@@ -53,6 +52,8 @@ struct packet_context {
struct send_element *next, *prev;
DATA_BLOB blob;
size_t nsent;
+ packet_send_callback_fn_t send_callback;
+ void *send_callback_private;
} *send_queue;
};
@@ -374,6 +375,7 @@ next_partial:
return;
}
+ /* Have we consumed the whole buffer yet? */
if (pc->partial.length == 0) {
return;
}
@@ -436,7 +438,7 @@ _PUBLIC_ void packet_queue_run(struct packet_context *pc)
status = socket_send(pc->sock, &blob, &nwritten);
if (NT_STATUS_IS_ERR(status)) {
- packet_error(pc, NT_STATUS_NET_WRITE_FAULT);
+ packet_error(pc, status);
return;
}
if (!NT_STATUS_IS_OK(status)) {
@@ -445,6 +447,9 @@ _PUBLIC_ void packet_queue_run(struct packet_context *pc)
el->nsent += nwritten;
if (el->nsent == el->blob.length) {
DLIST_REMOVE(pc->send_queue, el);
+ if (el->send_callback) {
+ el->send_callback(el->send_callback_private);
+ }
talloc_free(el);
}
}
@@ -455,9 +460,15 @@ _PUBLIC_ void packet_queue_run(struct packet_context *pc)
}
/*
- put a packet in the send queue
+ put a packet in the send queue. When the packet is actually sent,
+ call send_callback.
+
+ Useful for operations that must occour after sending a message, such
+ as the switch to SASL encryption after as sucessful LDAP bind relpy.
*/
-_PUBLIC_ NTSTATUS packet_send(struct packet_context *pc, DATA_BLOB blob)
+_PUBLIC_ NTSTATUS packet_send_callback(struct packet_context *pc, DATA_BLOB blob,
+ packet_send_callback_fn_t send_callback,
+ void *private)
{
struct send_element *el;
el = talloc(pc, struct send_element);
@@ -466,6 +477,8 @@ _PUBLIC_ NTSTATUS packet_send(struct packet_context *pc, DATA_BLOB blob)
DLIST_ADD_END(pc->send_queue, el, struct send_element *);
el->blob = blob;
el->nsent = 0;
+ el->send_callback = send_callback;
+ el->send_callback_private = private;
/* if we aren't going to free the packet then we must reference it
to ensure it doesn't disappear before going out */
@@ -477,11 +490,23 @@ _PUBLIC_ NTSTATUS packet_send(struct packet_context *pc, DATA_BLOB blob)
talloc_steal(el, blob.data);
}
+ if (private && !talloc_reference(el, private)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
EVENT_FD_WRITEABLE(pc->fde);
return NT_STATUS_OK;
}
+/*
+ put a packet in the send queue
+*/
+_PUBLIC_ NTSTATUS packet_send(struct packet_context *pc, DATA_BLOB blob)
+{
+ return packet_send_callback(pc, blob, NULL, NULL);
+}
+
/*
a full request checker for NBT formatted packets (first 3 bytes are length)
diff --git a/source4/lib/stream/packet.h b/source4/lib/stream/packet.h
index b7ee428186..0d875d777c 100644
--- a/source4/lib/stream/packet.h
+++ b/source4/lib/stream/packet.h
@@ -24,6 +24,9 @@
typedef NTSTATUS (*packet_full_request_fn_t)(void *private,
DATA_BLOB blob, size_t *packet_size);
typedef NTSTATUS (*packet_callback_fn_t)(void *private, DATA_BLOB blob);
+
+/* Used to notify that a packet has been sent, and is on the wire */
+typedef void (*packet_send_callback_fn_t)(void *private);
typedef void (*packet_error_handler_fn_t)(void *private, NTSTATUS status);
@@ -43,6 +46,9 @@ void packet_recv(struct packet_context *pc);
void packet_recv_disable(struct packet_context *pc);
void packet_recv_enable(struct packet_context *pc);
NTSTATUS packet_send(struct packet_context *pc, DATA_BLOB blob);
+NTSTATUS packet_send_callback(struct packet_context *pc, DATA_BLOB blob,
+ packet_send_callback_fn_t send_callback,
+ void *private);
void packet_queue_run(struct packet_context *pc);
/*
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index 1ba8ae9779..f9213af2a7 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -444,7 +444,7 @@ struct socket_context *tls_init_server(struct tls_params *params,
nt_status = socket_create_with_ops(socket, &tls_socket_ops, &new_sock,
SOCKET_TYPE_STREAM,
- socket->flags | SOCKET_FLAG_FAKE);
+ socket->flags | SOCKET_FLAG_ENCRYPT);
if (!NT_STATUS_IS_OK(nt_status)) {
return NULL;
}
@@ -524,7 +524,7 @@ struct socket_context *tls_init_client(struct socket_context *socket,
nt_status = socket_create_with_ops(socket, &tls_socket_ops, &new_sock,
SOCKET_TYPE_STREAM,
- socket->flags | SOCKET_FLAG_FAKE);
+ socket->flags | SOCKET_FLAG_ENCRYPT);
if (!NT_STATUS_IS_OK(nt_status)) {
return NULL;
}
diff --git a/source4/libcli/ldap/config.mk b/source4/libcli/ldap/config.mk
index 88ebc3256f..e5a7133cfa 100644
--- a/source4/libcli/ldap/config.mk
+++ b/source4/libcli/ldap/config.mk
@@ -11,7 +11,7 @@ OBJ_FILES = ldap.o \
ldap_ildap.o \
ldap_controls.o
PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBEVENTS LIBPACKET
-PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE samba-socket LIBCLI_RESOLVE NDR_SAMR LIBTLS ASN1_UTIL
+PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE samba-socket LIBCLI_RESOLVE NDR_SAMR LIBTLS ASN1_UTIL GENSEC_SOCKET
#PRIVATE_DEPENDENCIES = gensec
# End SUBSYSTEM LIBCLI_LDAP
#################################
diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c
index 6714d68b0e..2b209c3871 100644
--- a/source4/libcli/ldap/ldap_bind.c
+++ b/source4/libcli/ldap/ldap_bind.c
@@ -27,6 +27,8 @@
#include "libcli/ldap/ldap_client.h"
#include "lib/tls/tls.h"
#include "auth/auth.h"
+#include "auth/gensec/socket.h"
+#include "lib/stream/packet.h"
struct ldap_simple_creds {
const char *dn;
@@ -365,15 +367,23 @@ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *cr
}
}
- if (NT_STATUS_IS_OK(status) &&
- (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL) ||
- gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN))) {
- conn->enable_wrap = True;
- }
-
talloc_free(tmp_ctx);
if (NT_STATUS_IS_OK(status)) {
+ struct socket_context *socket = gensec_socket_init(conn->gensec,
+ conn->sock,
+ conn->event.event_ctx,
+ ldap_read_io_handler,
+ conn);
+ if (socket) {
+ conn->sock = socket;
+ talloc_steal(conn->sock, socket);
+ packet_set_socket(conn->packet, socket);
+ } else {
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+
conn->bind.type = LDAP_BIND_SASL;
conn->bind.creds = creds;
}
diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c
index 07b7f2b412..2e834b5244 100644
--- a/source4/libcli/ldap/ldap_client.c
+++ b/source4/libcli/ldap/ldap_client.c
@@ -165,25 +165,13 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
/*
- check if a blob is a complete ldap packet
- handle wrapper or unwrapped connections
+ decode/process LDAP data
*/
-NTSTATUS ldap_complete_packet(void *private_data, DATA_BLOB blob, size_t *size)
-{
- struct ldap_connection *conn = talloc_get_type(private_data,
- struct ldap_connection);
- if (conn->enable_wrap) {
- return packet_full_request_u32(private_data, blob, size);
- }
- return ldap_full_packet(private_data, blob, size);
-}
-
-/*
- decode/process plain data
-*/
-static NTSTATUS ldap_decode_plain(struct ldap_connection *conn, DATA_BLOB blob)
+static NTSTATUS ldap_recv_handler(void *private_data, DATA_BLOB blob)
{
struct asn1_data asn1;
+ struct ldap_connection *conn = talloc_get_type(private_data,
+ struct ldap_connection);
struct ldap_message *msg = talloc(conn, struct ldap_message);
if (msg == NULL) {
@@ -205,60 +193,14 @@ static NTSTATUS ldap_decode_plain(struct ldap_connection *conn, DATA_BLOB blob)
return NT_STATUS_OK;
}
-/*
- decode/process wrapped data
-*/
-static NTSTATUS ldap_decode_wrapped(struct ldap_connection *conn, DATA_BLOB blob)
-{
- DATA_BLOB wrapped, unwrapped;
- struct asn1_data asn1;
- struct ldap_message *msg = talloc(conn, struct ldap_message);
- NTSTATUS status;
-
- if (msg == NULL) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
- }
-
- wrapped = data_blob_const(blob.data+4, blob.length-4);
-
- status = gensec_unwrap(conn->gensec, msg, &wrapped, &unwrapped);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
- }
-
- data_blob_free(&blob);
-
- if (!asn1_load(&asn1, unwrapped)) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
- }
-
- while (ldap_decode(&asn1, msg)) {
- ldap_match_message(conn, msg);
- msg = talloc(conn, struct ldap_message);
- }
-
- talloc_free(msg);
- asn1_free(&asn1);
-
- return NT_STATUS_OK;
-}
-
-
-/*
- handle ldap recv events
-*/
-static NTSTATUS ldap_recv_handler(void *private_data, DATA_BLOB blob)
+/* Handle read events, from the GENSEC socket callback, or real events */
+void ldap_read_io_handler(void *private_data, uint16_t flags)
{
struct ldap_connection *conn = talloc_get_type(private_data,
struct ldap_connection);
- if (conn->enable_wrap) {
- return ldap_decode_wrapped(conn, blob);
- }
-
- return ldap_decode_plain(conn, blob);
+ packet_recv(conn->packet);
}
-
/*
handle ldap socket events
*/
@@ -272,7 +214,7 @@ static void ldap_io_handler(struct event_context *ev, struct fd_event *fde,
if (!tls_enabled(conn->sock)) return;
}
if (flags & EVENT_FD_READ) {
- packet_recv(conn->packet);
+ ldap_read_io_handler(private_data, flags);
}
}
@@ -417,7 +359,7 @@ static void ldap_connect_recv_conn(struct composite_context *ctx)
packet_set_private(conn->packet, conn);
packet_set_socket(conn->packet, conn->sock);
packet_set_callback(conn->packet, ldap_recv_handler);
- packet_set_full_request(conn->packet, ldap_complete_packet);
+ packet_set_full_request(conn->packet, ldap_full_packet);
packet_set_error_handler(conn->packet, ldap_error_handler);
packet_set_event_context(conn->packet, conn->event.event_ctx);
packet_set_fde(conn->packet, conn->event.fde);
@@ -561,24 +503,6 @@ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
goto failed;
}
- /* possibly encrypt/sign the request */
- if (conn->enable_wrap) {
- DATA_BLOB wrapped;
-
- status = gensec_wrap(conn->gensec, req, &req->data, &wrapped);
- if (!NT_STATUS_IS_OK(status)) {
- goto failed;
- }
- data_blob_free(&req->data);
- req->data = data_blob_talloc(req, NULL, wrapped.length + 4);
- if (req->data.data == NULL) {
- goto failed;
- }
- RSIVAL(req->data.data, 0, wrapped.length);
- memcpy(req->data.data+4, wrapped.data, wrapped.length);
- data_blob_free(&wrapped);
- }
-
status = packet_send(conn->packet, req->data);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
diff --git a/source4/libcli/ldap/ldap_client.h b/source4/libcli/ldap/ldap_client.h
index 28b9f2763c..849737d8a9 100644
--- a/source4/libcli/ldap/ldap_client.h
+++ b/source4/libcli/ldap/ldap_client.h
@@ -80,9 +80,6 @@ struct ldap_connection {
/* Let's support SASL */
struct gensec_security *gensec;
- /* set if we are wrapping requests */
- BOOL enable_wrap;
-
/* the default timeout for messages */
int timeout;
diff --git a/source4/smbd/service_stream.c b/source4/smbd/service_stream.c
index 59e87304d3..d238fc4128 100644
--- a/source4/smbd/service_stream.c
+++ b/source4/smbd/service_stream.c
@@ -100,6 +100,11 @@ static void stream_io_handler(struct event_context *ev, struct fd_event *fde,
}
}
+void stream_io_handler_callback(void *conn, uint16_t flags)
+{
+ stream_io_handler(NULL, NULL, flags, conn);
+}
+
/*
this creates a stream_connection from an already existing connection,
used for protocols, where a client connection needs to switched into