s4:libcli/ldap: conversion to tstream and more...
Stefan (metze) Metzmacher
metze at samba.org
Mon Jun 22 14:31:04 MDT 2015
Hi,
here're some patches which convert s4:libcli/ldap to tstream.
This allows us to finally remove gensec_socket_init() which
used the socket_context/packet_context.
Please review and push.
Thanks!
metze
-------------- next part --------------
From 8fed0572214650fa4567b41dc505359b1aa3bfe0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 18 Jun 2015 23:18:58 +0200
Subject: [PATCH 01/12] s4:gensec/gssapi: use
gensec_gssapi_max_{input,wrapped}_size() for all backends
This avoids calls to gensec_gssapi_sig_size() as fallback in
gensec_max_input_size().
gensec_gssapi_sig_size() needs to report the sig size
gensec_{sign,seal}_packet(), which could be different to the
overhead produced by gensec_wrap().
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/auth/gensec/gensec_gssapi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 5582102..fd0f2a1 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -1531,6 +1531,8 @@ static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
.check_packet = gensec_gssapi_check_packet,
.seal_packet = gensec_gssapi_seal_packet,
.unseal_packet = gensec_gssapi_unseal_packet,
+ .max_input_size = gensec_gssapi_max_input_size,
+ .max_wrapped_size = gensec_gssapi_max_wrapped_size,
.wrap = gensec_gssapi_wrap,
.unwrap = gensec_gssapi_unwrap,
.have_feature = gensec_gssapi_have_feature,
@@ -1556,6 +1558,8 @@ static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
.check_packet = gensec_gssapi_check_packet,
.seal_packet = gensec_gssapi_seal_packet,
.unseal_packet = gensec_gssapi_unseal_packet,
+ .max_input_size = gensec_gssapi_max_input_size,
+ .max_wrapped_size = gensec_gssapi_max_wrapped_size,
.wrap = gensec_gssapi_wrap,
.unwrap = gensec_gssapi_unwrap,
.have_feature = gensec_gssapi_have_feature,
--
1.9.1
From 0bbe1e633de0924b4d299622d2c0b2dc83132eca Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 18 Jun 2015 21:07:58 +0200
Subject: [PATCH 02/12] s4:gensec/gssapi: make calculation of
gensec_gssapi_sig_size() for aes keys more clear
This way the result matches what gss_wrap_iov_length() would return.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/auth/gensec/gensec_gssapi.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index fd0f2a1..b3a4697 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -1470,11 +1470,10 @@ static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, si
if (gensec_gssapi_state->lucid->protocol == 1) {
if (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG) {
- /*
- * TODO: windows uses 76 here, but we don't know
- * gss_wrap works with aes keys yet
- */
- gensec_gssapi_state->sig_size = 76;
+ gensec_gssapi_state->sig_size = 60;
+ if (gensec_gssapi_state->gss_got_flags & GSS_C_DCE_STYLE) {
+ gensec_gssapi_state->sig_size += 16;
+ }
} else {
gensec_gssapi_state->sig_size = 28;
}
--
1.9.1
From 259a98886ded42aece818ee47907615d385544be Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 01:07:49 +0200
Subject: [PATCH 03/12] s3:libads/sasl: use gensec_max_{input,wrapped}_size()
in ads_sasl_spnego_ntlmssp_bind
gensec_sig_size() is for gensec_{sign,seal}_packet() instead of gensec_wrap().
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/libads/sasl.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index db7335e..720ee78 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -250,11 +250,12 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
} while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
- uint32_t sig_size = gensec_sig_size(auth_generic_state->gensec_security, 0);
- ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - sig_size;
- ads->ldap.out.sig_size = sig_size;
+ size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security);
+ ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security);
+
+ ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped;
ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
- ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
+ ads->ldap.in.max_wrapped = max_wrapped;
status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, auth_generic_state->gensec_security);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
--
1.9.1
From bb29e9cb0f9bae168002b022e18112912dd231a6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 12:26:55 +0200
Subject: [PATCH 04/12] s4:lib/tls: fix tstream_tls_connect_send() define
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/lib/tls/tls.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h
index 64ab7c2..3ff009d 100644
--- a/source4/lib/tls/tls.h
+++ b/source4/lib/tls/tls.h
@@ -90,7 +90,7 @@ struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
struct tstream_context *plain_stream,
struct tstream_tls_params *tls_params,
const char *location);
-#define tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params); \
+#define tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params) \
_tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params, __location__)
int tstream_tls_connect_recv(struct tevent_req *req,
--
1.9.1
From cd74b52342cfa1b02fe07cf50dc6d89cd8ba3ee0 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 13:30:10 +0200
Subject: [PATCH 05/12] s4:lib/tls: ignore non-existing ca and crl files in
tstream_tls_params_client()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/lib/tls/tls_tstream.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/source4/lib/tls/tls_tstream.c b/source4/lib/tls/tls_tstream.c
index 5b2329b..113e03a 100644
--- a/source4/lib/tls/tls_tstream.c
+++ b/source4/lib/tls/tls_tstream.c
@@ -919,7 +919,7 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
- if (ca_file && *ca_file) {
+ if (ca_file && *ca_file && file_exist(ca_file)) {
ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
ca_file,
GNUTLS_X509_FMT_PEM);
@@ -931,7 +931,7 @@ NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
}
}
- if (crl_file && *crl_file) {
+ if (crl_file && *crl_file && file_exist(crl_file)) {
ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
crl_file,
GNUTLS_X509_FMT_PEM);
--
1.9.1
From 226ae2bf092075270be7c1a499dc5904a8a13e5d Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 12:26:06 +0200
Subject: [PATCH 06/12] s4:libcli/ldap: conversion to tstream
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/libcli/ldap/ldap_bind.c | 65 ++++--
source4/libcli/ldap/ldap_client.c | 443 +++++++++++++++++++++++++-------------
source4/libcli/ldap/ldap_client.h | 17 +-
source4/libcli/ldap/wscript_build | 4 +-
4 files changed, 357 insertions(+), 172 deletions(-)
diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c
index a96ea9f..daa7662 100644
--- a/source4/libcli/ldap/ldap_bind.c
+++ b/source4/libcli/ldap/ldap_bind.c
@@ -28,7 +28,7 @@
#include "lib/tls/tls.h"
#include "auth/gensec/gensec.h"
#include "auth/gensec/gensec_internal.h" /* TODO: remove this */
-#include "auth/gensec/gensec_socket.h"
+#include "source4/auth/gensec/gensec_tstream.h"
#include "auth/credentials/credentials.h"
#include "lib/stream/packet.h"
#include "param/param.h"
@@ -224,6 +224,27 @@ _PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn,
NULL
};
unsigned int logon_retries = 0;
+ size_t queue_length;
+
+ if (conn->sockets.active == NULL) {
+ status = NT_STATUS_CONNECTION_DISCONNECTED;
+ goto failed;
+ }
+
+ queue_length = tevent_queue_length(conn->sockets.send_queue);
+ if (queue_length != 0) {
+ status = NT_STATUS_INVALID_PARAMETER_MIX;
+ DEBUG(1, ("SASL bind triggered with non empty send_queue[%ju]: %s\n",
+ queue_length, nt_errstr(status)));
+ goto failed;
+ }
+
+ if (conn->pending != NULL) {
+ status = NT_STATUS_INVALID_PARAMETER_MIX;
+ DEBUG(1, ("SASL bind triggered with pending requests: %s\n",
+ nt_errstr(status)));
+ goto failed;
+ }
status = ildap_search(conn, "", LDAP_SEARCH_SCOPE_BASE, "", supported_sasl_mech_attrs,
false, NULL, NULL, &sasl_mechs_msgs);
@@ -281,7 +302,7 @@ try_logon_again:
/* require Kerberos SIGN/SEAL only if we don't use SSL
* Windows seem not to like double encryption */
old_gensec_features = cli_credentials_get_gensec_features(creds);
- if (tls_enabled(conn->sock)) {
+ if (conn->sockets.active == conn->sockets.tls) {
cli_credentials_set_gensec_features(creds, old_gensec_features & ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL));
}
@@ -436,27 +457,31 @@ try_logon_again:
}
}
- talloc_free(tmp_ctx);
+ TALLOC_FREE(tmp_ctx);
- if (NT_STATUS_IS_OK(status)) {
- struct socket_context *sasl_socket;
- status = gensec_socket_init(conn->gensec,
- conn,
- conn->sock,
- conn->event.event_ctx,
- ldap_read_io_handler,
- conn,
- &sasl_socket);
- if (!NT_STATUS_IS_OK(status)) goto failed;
-
- conn->sock = sasl_socket;
- packet_set_socket(conn->packet, conn->sock);
-
- conn->bind.type = LDAP_BIND_SASL;
- conn->bind.creds = creds;
+ if (!NT_STATUS_IS_OK(status)) {
+ goto failed;
}
- return status;
+ conn->bind.type = LDAP_BIND_SASL;
+ conn->bind.creds = creds;
+
+ if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) &&
+ !gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
+ return NT_STATUS_OK;
+ }
+
+ status = gensec_create_tstream(conn->sockets.raw,
+ conn->gensec,
+ conn->sockets.raw,
+ &conn->sockets.sasl);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto failed;
+ }
+
+ conn->sockets.active = conn->sockets.sasl;
+
+ return NT_STATUS_OK;
failed:
talloc_free(tmp_ctx);
diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c
index 7c8bb03..e49df9e 100644
--- a/source4/libcli/ldap/ldap_client.c
+++ b/source4/libcli/ldap/ldap_client.c
@@ -25,22 +25,36 @@
#include "includes.h"
#include <tevent.h>
#include "lib/socket/socket.h"
+#include "lib/tsocket/tsocket.h"
+#include "libcli/util/tstream.h"
#include "../lib/util/asn1.h"
#include "../lib/util/dlinklist.h"
#include "libcli/ldap/libcli_ldap.h"
#include "libcli/ldap/ldap_proto.h"
#include "libcli/ldap/ldap_client.h"
#include "libcli/composite/composite.h"
-#include "lib/stream/packet.h"
#include "lib/tls/tls.h"
#include "auth/gensec/gensec.h"
#include "system/time.h"
#include "param/param.h"
#include "libcli/resolve/resolve.h"
+static void ldap_connection_dead(struct ldap_connection *conn, NTSTATUS status);
+
+static int ldap_connection_destructor(struct ldap_connection *conn)
+{
+ /*
+ * NT_STATUS_OK means that callbacks of pending requests are not
+ * triggered
+ */
+ ldap_connection_dead(conn, NT_STATUS_OK);
+ return 0;
+}
+
/**
create a new ldap_connection stucture. The event context is optional
*/
+
_PUBLIC_ struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
struct loadparm_context *lp_ctx,
struct tevent_context *ev)
@@ -59,6 +73,13 @@ _PUBLIC_ struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
conn->next_messageid = 1;
conn->event.event_ctx = ev;
+ conn->sockets.send_queue = tevent_queue_create(conn,
+ "ldap_connection send_queue");
+ if (conn->sockets.send_queue == NULL) {
+ TALLOC_FREE(conn);
+ return NULL;
+ }
+
conn->lp_ctx = lp_ctx;
/* set a reasonable request timeout */
@@ -66,29 +87,35 @@ _PUBLIC_ struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
/* explicitly avoid reconnections by default */
conn->reconnect.max_retries = 0;
-
+
+ talloc_set_destructor(conn, ldap_connection_destructor);
return conn;
}
/*
the connection is dead
*/
-static void ldap_connection_dead(struct ldap_connection *conn)
+static void ldap_connection_dead(struct ldap_connection *conn, NTSTATUS status)
{
struct ldap_request *req;
- talloc_free(conn->sock); /* this will also free event.fde */
- talloc_free(conn->packet);
- conn->sock = NULL;
- conn->event.fde = NULL;
- conn->packet = NULL;
+ tevent_queue_stop(conn->sockets.send_queue);
+ TALLOC_FREE(conn->sockets.recv_subreq);
+ conn->sockets.active = NULL;
+ TALLOC_FREE(conn->sockets.sasl);
+ TALLOC_FREE(conn->sockets.tls);
+ TALLOC_FREE(conn->sockets.raw);
/* return an error for any pending request ... */
while (conn->pending) {
req = conn->pending;
DLIST_REMOVE(req->conn->pending, req);
+ req->conn = NULL;
req->state = LDAP_REQUEST_DONE;
- req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ if (NT_STATUS_IS_OK(status)) {
+ continue;
+ }
+ req->status = status;
if (req->async.fn) {
req->async.fn(req);
}
@@ -100,11 +127,9 @@ static void ldap_reconnect(struct ldap_connection *conn);
/*
handle packet errors
*/
-static void ldap_error_handler(void *private_data, NTSTATUS status)
+static void ldap_error_handler(struct ldap_connection *conn, NTSTATUS status)
{
- struct ldap_connection *conn = talloc_get_type(private_data,
- struct ldap_connection);
- ldap_connection_dead(conn);
+ ldap_connection_dead(conn, status);
/* but try to reconnect so that the ldb client can go on */
ldap_reconnect(conn);
@@ -130,7 +155,7 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
if (req == NULL) {
DEBUG(0,("ldap: no matching message id for %u\n",
msg->messageid));
- talloc_free(msg);
+ TALLOC_FREE(msg);
return;
}
@@ -138,6 +163,7 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
for (i=0; msg->controls && msg->controls[i]; i++) {
if (!msg->controls_decoded[i] &&
msg->controls[i]->critical) {
+ TALLOC_FREE(msg);
req->status = NT_STATUS_LDAP(LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
req->state = LDAP_REQUEST_DONE;
DLIST_REMOVE(conn->pending, req);
@@ -149,10 +175,10 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
}
/* add to the list of replies received */
- talloc_steal(req, msg);
req->replies = talloc_realloc(req, req->replies,
struct ldap_message *, req->num_replies+1);
if (req->replies == NULL) {
+ TALLOC_FREE(msg);
req->status = NT_STATUS_NO_MEMORY;
req->state = LDAP_REQUEST_DONE;
DLIST_REMOVE(conn->pending, req);
@@ -178,64 +204,120 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
}
}
+static void ldap_connection_recv_done(struct tevent_req *subreq);
+
+static void ldap_connection_recv_next(struct ldap_connection *conn)
+{
+ struct tevent_req *subreq = NULL;
+
+ if (conn->sockets.recv_subreq != NULL) {
+ return;
+ }
+
+ if (conn->sockets.active == NULL) {
+ return;
+ }
+
+ if (conn->pending == NULL) {
+ return;
+ }
+
+ /*
+ * The minimun size of a LDAP pdu is 7 bytes
+ *
+ * dumpasn1 -hh ldap-unbind-min.dat
+ *
+ * <30 05 02 01 09 42 00>
+ * 0 5: SEQUENCE {
+ * <02 01 09>
+ * 2 1: INTEGER 9
+ * <42 00>
+ * 5 0: [APPLICATION 2]
+ * : Error: Object has zero length.
+ * : }
+ *
+ * dumpasn1 -hh ldap-unbind-windows.dat
+ *
+ * <30 84 00 00 00 05 02 01 09 42 00>
+ * 0 5: SEQUENCE {
+ * <02 01 09>
+ * 6 1: INTEGER 9
+ * <42 00>
+ * 9 0: [APPLICATION 2]
+ * : Error: Object has zero length.
+ * : }
+ *
+ * This means using an initial read size
+ * of 7 is ok.
+ */
+ subreq = tstream_read_pdu_blob_send(conn,
+ conn->event.event_ctx,
+ conn->sockets.active,
+ 7, /* initial_read_size */
+ ldap_full_packet,
+ conn);
+ if (subreq == NULL) {
+ ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ tevent_req_set_callback(subreq, ldap_connection_recv_done, conn);
+ conn->sockets.recv_subreq = subreq;
+ return;
+}
/*
decode/process LDAP data
*/
-static NTSTATUS ldap_recv_handler(void *private_data, DATA_BLOB blob)
+static void ldap_connection_recv_done(struct tevent_req *subreq)
{
NTSTATUS status;
- struct ldap_connection *conn = talloc_get_type(private_data,
- struct ldap_connection);
- struct ldap_message *msg = talloc(conn, struct ldap_message);
- struct asn1_data *asn1 = asn1_init(conn);
-
- if (asn1 == NULL || msg == NULL) {
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+ struct ldap_connection *conn =
+ tevent_req_callback_data(subreq,
+ struct ldap_connection);
+ struct ldap_message *msg;
+ struct asn1_data *asn1;
+ DATA_BLOB blob;
+
+ msg = talloc_zero(conn, struct ldap_message);
+ if (msg == NULL) {
+ ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
+ return;
}
- if (!asn1_load(asn1, blob)) {
- talloc_free(msg);
- talloc_free(asn1);
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+ asn1 = asn1_init(conn);
+ if (asn1 == NULL) {
+ TALLOC_FREE(msg);
+ ldap_error_handler(conn, NT_STATUS_NO_MEMORY);
+ return;
}
-
- status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
+
+ conn->sockets.recv_subreq = NULL;
+
+ status = tstream_read_pdu_blob_recv(subreq,
+ asn1,
+ &blob);
+ TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(msg);
asn1_free(asn1);
- return status;
+ ldap_error_handler(conn, status);
+ return;
}
- ldap_match_message(conn, msg);
+ asn1_load_nocopy(asn1, blob.data, blob.length);
- data_blob_free(&blob);
+ status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
asn1_free(asn1);
- return NT_STATUS_OK;
-}
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(msg);
+ ldap_error_handler(conn, status);
+ return;
+ }
-/* 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);
- packet_recv(conn->packet);
-}
+ ldap_match_message(conn, msg);
+ ldap_connection_recv_next(conn);
-/*
- handle ldap socket events
-*/
-static void ldap_io_handler(struct tevent_context *ev, struct tevent_fd *fde,
- uint16_t flags, void *private_data)
-{
- struct ldap_connection *conn = talloc_get_type(private_data,
- struct ldap_connection);
- if (flags & TEVENT_FD_WRITE) {
- packet_queue_run(conn->packet);
- if (!tls_enabled(conn->sock)) return;
- }
- if (flags & TEVENT_FD_READ) {
- ldap_read_io_handler(private_data, flags);
- }
+ return;
}
/*
@@ -284,6 +366,10 @@ static NTSTATUS ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
struct ldap_connect_state {
struct composite_context *ctx;
struct ldap_connection *conn;
+ struct socket_context *sock;
+ struct tstream_context *raw;
+ struct tstream_tls_params *tls_params;
+ struct tstream_context *tls;
};
static void ldap_connect_recv_unix_conn(struct composite_context *ctx);
@@ -327,11 +413,11 @@ _PUBLIC_ struct composite_context *ldap_connect_send(struct ldap_connection *con
struct socket_address *unix_addr;
char path[1025];
- NTSTATUS status = socket_create("unix", SOCKET_TYPE_STREAM, &conn->sock, 0);
+ NTSTATUS status = socket_create("unix", SOCKET_TYPE_STREAM, &state->sock, 0);
if (!NT_STATUS_IS_OK(status)) {
return NULL;
}
- talloc_steal(conn, conn->sock);
+ talloc_steal(state, state->sock);
SMB_ASSERT(sizeof(protocol)>10);
SMB_ASSERT(sizeof(path)>1024);
@@ -354,29 +440,53 @@ _PUBLIC_ struct composite_context *ldap_connect_send(struct ldap_connection *con
}
rfc1738_unescape(path);
-
- unix_addr = socket_address_from_strings(conn, conn->sock->backend_name,
+
+ unix_addr = socket_address_from_strings(state, state->sock->backend_name,
path, 0);
- if (!unix_addr) {
- return NULL;
+ if (composite_nomem(unix_addr, result)) {
+ return result;
}
- ctx = socket_connect_send(conn->sock, NULL, unix_addr,
- 0, conn->event.event_ctx);
+
+ ctx = socket_connect_send(state->sock, NULL, unix_addr,
+ 0, result->event_ctx);
ctx->async.fn = ldap_connect_recv_unix_conn;
ctx->async.private_data = state;
return result;
} else {
NTSTATUS status = ldap_parse_basic_url(conn, url, &conn->host,
&conn->port, &conn->ldaps);
- if (!NT_STATUS_IS_OK(state->ctx->status)) {
- composite_error(state->ctx, status);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(result, status);
return result;
}
-
+
+ if (conn->ldaps) {
+ char *ca_file = lpcfg_tls_cafile(state, conn->lp_ctx);
+ char *crl_file = lpcfg_tls_crlfile(state, conn->lp_ctx);
+
+ if (!ca_file || !*ca_file) {
+ composite_error(result,
+ NT_STATUS_INVALID_PARAMETER_MIX);
+ return result;
+ }
+
+ status = tstream_tls_params_client(state,
+ ca_file,
+ crl_file,
+ &state->tls_params);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(result, status);
+ return result;
+ }
+ }
+
ctx = socket_connect_multi_send(state, conn->host, 1, &conn->port,
- lpcfg_resolve_context(conn->lp_ctx), conn->event.event_ctx);
- if (ctx == NULL) goto failed;
+ lpcfg_resolve_context(conn->lp_ctx),
+ result->event_ctx);
+ if (composite_nomem(ctx, result)) {
+ return result;
+ }
ctx->async.fn = ldap_connect_recv_tcp_conn;
ctx->async.private_data = state;
@@ -387,72 +497,80 @@ _PUBLIC_ struct composite_context *ldap_connect_send(struct ldap_connection *con
return NULL;
}
+static void ldap_connect_got_tls(struct tevent_req *subreq);
+
static void ldap_connect_got_sock(struct composite_context *ctx,
- struct ldap_connection *conn)
+ struct ldap_connection *conn)
{
- /* setup a handler for events on this socket */
- conn->event.fde = tevent_add_fd(conn->event.event_ctx, conn->sock,
- socket_get_fd(conn->sock),
- TEVENT_FD_READ, ldap_io_handler, conn);
- if (conn->event.fde == NULL) {
- composite_error(ctx, NT_STATUS_INTERNAL_ERROR);
- return;
- }
+ struct ldap_connect_state *state =
+ talloc_get_type_abort(ctx->private_data,
+ struct ldap_connect_state);
+ struct tevent_req *subreq = NULL;
+ int fd;
+ int ret;
- tevent_fd_set_close_fn(conn->event.fde, socket_tevent_fd_close_fn);
- socket_set_flags(conn->sock, SOCKET_FLAG_NOCLOSE);
+ socket_set_flags(state->sock, SOCKET_FLAG_NOCLOSE);
+ fd = socket_get_fd(state->sock);
+ TALLOC_FREE(state->sock);
- talloc_steal(conn, conn->sock);
- if (conn->ldaps) {
- struct socket_context *tls_socket;
- char *cafile = lpcfg_tls_cafile(conn->sock, conn->lp_ctx);
+ smb_set_close_on_exec(fd);
+ set_blocking(fd, false);
- if (!cafile || !*cafile) {
- talloc_free(conn->sock);
- return;
- }
-
- tls_socket = tls_init_client(conn->sock, conn->event.fde, cafile);
- talloc_free(cafile);
-
- if (tls_socket == NULL) {
- talloc_free(conn->sock);
- return;
- }
+ ret = tstream_bsd_existing_socket(state, fd, &state->raw);
+ if (ret == -1) {
+ NTSTATUS status = map_nt_error_from_unix_common(errno);
+ composite_error(state->ctx, status);
+ return;
+ }
- conn->sock = talloc_steal(conn, tls_socket);
+ if (!conn->ldaps) {
+ conn->sockets.raw = talloc_move(conn, &state->raw);
+ conn->sockets.active = conn->sockets.raw;
+ composite_done(state->ctx);
+ return;
}
- conn->packet = packet_init(conn);
- if (conn->packet == NULL) {
- talloc_free(conn->sock);
+ subreq = tstream_tls_connect_send(state, state->ctx->event_ctx,
+ state->raw, state->tls_params);
+ if (composite_nomem(subreq, state->ctx)) {
return;
}
+ tevent_req_set_callback(subreq, ldap_connect_got_tls, state);
+}
- 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_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);
-/* packet_set_serialise(conn->packet); */
+static void ldap_connect_got_tls(struct tevent_req *subreq)
+{
+ struct ldap_connect_state *state =
+ tevent_req_callback_data(subreq,
+ struct ldap_connect_state);
+ int err;
+ int ret;
- if (conn->ldaps) {
- packet_set_unreliable_select(conn->packet);
+ ret = tstream_tls_connect_recv(subreq, &err, state, &state->tls);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ NTSTATUS status = map_nt_error_from_unix_common(err);
+ composite_error(state->ctx, status);
+ return;
}
- composite_done(ctx);
+ talloc_steal(state->tls, state->tls_params);
+
+ state->conn->sockets.raw = talloc_move(state->conn, &state->raw);
+ state->conn->sockets.tls = talloc_move(state->conn->sockets.raw,
+ &state->tls);
+ state->conn->sockets.active = state->conn->sockets.tls;
+ composite_done(state->ctx);
}
static void ldap_connect_recv_tcp_conn(struct composite_context *ctx)
{
struct ldap_connect_state *state =
- talloc_get_type(ctx->async.private_data,
- struct ldap_connect_state);
+ talloc_get_type_abort(ctx->async.private_data,
+ struct ldap_connect_state);
struct ldap_connection *conn = state->conn;
uint16_t port;
- NTSTATUS status = socket_connect_multi_recv(ctx, state, &conn->sock,
+ NTSTATUS status = socket_connect_multi_recv(ctx, state, &state->sock,
&port);
if (!NT_STATUS_IS_OK(status)) {
composite_error(state->ctx, status);
@@ -465,8 +583,8 @@ static void ldap_connect_recv_tcp_conn(struct composite_context *ctx)
static void ldap_connect_recv_unix_conn(struct composite_context *ctx)
{
struct ldap_connect_state *state =
- talloc_get_type(ctx->async.private_data,
- struct ldap_connect_state);
+ talloc_get_type_abort(ctx->async.private_data,
+ struct ldap_connect_state);
struct ldap_connection *conn = state->conn;
NTSTATUS status = socket_connect_recv(ctx);
@@ -533,7 +651,7 @@ static void ldap_reconnect(struct ldap_connection *conn)
/* rebind */
status = ldap_rebind(conn);
if ( ! NT_STATUS_IS_OK(status)) {
- ldap_connection_dead(conn);
+ ldap_connection_dead(conn, status);
}
}
@@ -552,7 +670,10 @@ static int ldap_request_destructor(struct ldap_request *req)
static void ldap_request_timeout(struct tevent_context *ev, struct tevent_timer *te,
struct timeval t, void *private_data)
{
- struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
+ struct ldap_request *req =
+ talloc_get_type_abort(private_data,
+ struct ldap_request);
+
req->status = NT_STATUS_IO_TIMEOUT;
if (req->state == LDAP_REQUEST_PENDING) {
DLIST_REMOVE(req->conn->pending, req);
@@ -570,26 +691,17 @@ static void ldap_request_timeout(struct tevent_context *ev, struct tevent_timer
static void ldap_request_failed_complete(struct tevent_context *ev, struct tevent_timer *te,
struct timeval t, void *private_data)
{
- struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
- if (req->async.fn) {
- req->async.fn(req);
- }
-}
+ struct ldap_request *req =
+ talloc_get_type_abort(private_data,
+ struct ldap_request);
-/*
- called on completion of a one-way ldap request
-*/
-static void ldap_request_oneway_complete(void *private_data)
-{
- struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
- if (req->state == LDAP_REQUEST_PENDING) {
- DLIST_REMOVE(req->conn->pending, req);
- }
- req->state = LDAP_REQUEST_DONE;
if (req->async.fn) {
req->async.fn(req);
}
}
+
+static void ldap_request_written(struct tevent_req *subreq);
+
/*
send a ldap message - async interface
*/
@@ -598,12 +710,12 @@ _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
{
struct ldap_request *req;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- packet_send_callback_fn_t send_callback = NULL;
+ struct tevent_req *subreq = NULL;
req = talloc_zero(conn, struct ldap_request);
if (req == NULL) return NULL;
- if (conn->sock == NULL) {
+ if (conn->sockets.active == NULL) {
status = NT_STATUS_INVALID_CONNECTION;
goto failed;
}
@@ -628,25 +740,31 @@ _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
goto failed;
}
- if (req->type == LDAP_TAG_AbandonRequest ||
- req->type == LDAP_TAG_UnbindRequest) {
- send_callback = ldap_request_oneway_complete;
+ /* put a timeout on the request */
+ req->time_event = tevent_add_timer(conn->event.event_ctx, req,
+ timeval_current_ofs(conn->timeout, 0),
+ ldap_request_timeout, req);
+ if (req->time_event == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto failed;
}
- status = packet_send_callback(conn->packet, req->data,
- send_callback, req);
- if (!NT_STATUS_IS_OK(status)) {
+ req->write_iov.iov_base = req->data.data;
+ req->write_iov.iov_len = req->data.length;
+
+ subreq = tstream_writev_queue_send(req, conn->event.event_ctx,
+ conn->sockets.active,
+ conn->sockets.send_queue,
+ &req->write_iov, 1);
+ if (subreq == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto failed;
}
+ tevent_req_set_callback(subreq, ldap_request_written, req);
req->state = LDAP_REQUEST_PENDING;
DLIST_ADD(conn->pending, req);
- /* put a timeout on the request */
- req->time_event = tevent_add_timer(conn->event.event_ctx, req,
- timeval_current_ofs(conn->timeout, 0),
- ldap_request_timeout, req);
-
return req;
failed:
@@ -658,6 +776,38 @@ failed:
return req;
}
+static void ldap_request_written(struct tevent_req *subreq)
+{
+ struct ldap_request *req =
+ tevent_req_callback_data(subreq,
+ struct ldap_request);
+ int err;
+ ssize_t ret;
+
+ ret = tstream_writev_queue_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ NTSTATUS error = map_nt_error_from_unix_common(err);
+ ldap_error_handler(req->conn, error);
+ return;
+ }
+
+ if (req->type == LDAP_TAG_AbandonRequest ||
+ req->type == LDAP_TAG_UnbindRequest)
+ {
+ if (req->state == LDAP_REQUEST_PENDING) {
+ DLIST_REMOVE(req->conn->pending, req);
+ }
+ req->state = LDAP_REQUEST_DONE;
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
+ return;
+ }
+
+ ldap_connection_recv_next(req->conn);
+}
+
/*
wait for a request to complete
@@ -667,6 +817,7 @@ _PUBLIC_ NTSTATUS ldap_request_wait(struct ldap_request *req)
{
while (req->state < LDAP_REQUEST_DONE) {
if (tevent_loop_once(req->conn->event.event_ctx) != 0) {
+ req->state = LDAP_REQUEST_ERROR;
req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
break;
}
diff --git a/source4/libcli/ldap/ldap_client.h b/source4/libcli/ldap/ldap_client.h
index 3b4da6b..e2b1b30 100644
--- a/source4/libcli/ldap/ldap_client.h
+++ b/source4/libcli/ldap/ldap_client.h
@@ -20,6 +20,7 @@
*/
+#include "system/network.h" /* for struct iovec */
#include "libcli/ldap/libcli_ldap.h"
enum ldap_request_state { LDAP_REQUEST_SEND=1, LDAP_REQUEST_PENDING=2, LDAP_REQUEST_DONE=3, LDAP_REQUEST_ERROR=4 };
@@ -39,6 +40,8 @@ struct ldap_request {
NTSTATUS status;
DATA_BLOB data;
+ struct iovec write_iov;
+
struct {
void (*fn)(struct ldap_request *);
void *private_data;
@@ -50,7 +53,16 @@ struct ldap_request {
/* main context for a ldap client connection */
struct ldap_connection {
- struct socket_context *sock;
+ struct {
+ struct tstream_context *raw;
+ struct tstream_context *tls;
+ struct tstream_context *sasl;
+ struct tstream_context *active;
+
+ struct tevent_queue *send_queue;
+ struct tevent_req *recv_subreq;
+ } sockets;
+
struct loadparm_context *lp_ctx;
char *host;
@@ -89,10 +101,7 @@ struct ldap_connection {
struct {
struct tevent_context *event_ctx;
- struct tevent_fd *fde;
} event;
-
- struct packet_context *packet;
};
struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
diff --git a/source4/libcli/ldap/wscript_build b/source4/libcli/ldap/wscript_build
index f7afec7..f79cc2b 100644
--- a/source4/libcli/ldap/wscript_build
+++ b/source4/libcli/ldap/wscript_build
@@ -3,9 +3,9 @@
bld.SAMBA_LIBRARY('cli-ldap',
source='ldap_client.c ldap_bind.c ldap_ildap.c ldap_controls.c',
autoproto='ldap_proto.h',
- public_deps='errors tevent LIBPACKET',
+ public_deps='errors tevent',
public_headers='libcli_ldap.h:ldap-util.h',
- deps='cli_composite samba_socket NDR_SAMR LIBTLS ndr LP_RESOLVE gensec cli-ldap-common',
+ deps='cli_composite LIBSAMBA_TSOCKET samba_socket NDR_SAMR LIBTLS ndr LP_RESOLVE gensec cli-ldap-common',
private_library=True
)
--
1.9.1
From f3f985b24a14a7da00119e313f75617ec4f4f50e Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 13:30:54 +0200
Subject: [PATCH 07/12] s4:auth/gensec: remove unused and untested cyrus_sasl
module
There's not a high chance that this module worked at all.
Requesting SASL_SSF in order to get the max input length
is completely broken.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/auth/gensec/cyrus_sasl.c | 454 --------------------------------------
source4/auth/gensec/wscript_build | 10 -
source4/auth/wscript_configure | 4 -
3 files changed, 468 deletions(-)
delete mode 100644 source4/auth/gensec/cyrus_sasl.c
diff --git a/source4/auth/gensec/cyrus_sasl.c b/source4/auth/gensec/cyrus_sasl.c
deleted file mode 100644
index 72acc52..0000000
--- a/source4/auth/gensec/cyrus_sasl.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Connect GENSEC to an external SASL lib
-
- Copyright (C) Andrew Bartlett <abartlet at 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 3 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, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "lib/tsocket/tsocket.h"
-#include "auth/credentials/credentials.h"
-#include "auth/gensec/gensec.h"
-#include "auth/gensec/gensec_internal.h"
-#include "auth/gensec/gensec_proto.h"
-#include "auth/gensec/gensec_toplevel_proto.h"
-#include <sasl/sasl.h>
-
-NTSTATUS gensec_sasl_init(void);
-
-struct gensec_sasl_state {
- sasl_conn_t *conn;
- int step;
- bool wrap;
-};
-
-static NTSTATUS sasl_nt_status(int sasl_ret)
-{
- switch (sasl_ret) {
- case SASL_CONTINUE:
- return NT_STATUS_MORE_PROCESSING_REQUIRED;
- case SASL_NOMEM:
- return NT_STATUS_NO_MEMORY;
- case SASL_BADPARAM:
- case SASL_NOMECH:
- return NT_STATUS_INVALID_PARAMETER;
- case SASL_BADMAC:
- return NT_STATUS_ACCESS_DENIED;
- case SASL_OK:
- return NT_STATUS_OK;
- default:
- return NT_STATUS_UNSUCCESSFUL;
- }
-}
-
-static int gensec_sasl_get_user(void *context, int id,
- const char **result, unsigned *len)
-{
- struct gensec_security *gensec_security = talloc_get_type(context, struct gensec_security);
- const char *username = cli_credentials_get_username(gensec_get_credentials(gensec_security));
- if (id != SASL_CB_USER && id != SASL_CB_AUTHNAME) {
- return SASL_FAIL;
- }
-
- *result = username;
- return SASL_OK;
-}
-
-static int gensec_sasl_get_realm(void *context, int id,
- const char **availrealms,
- const char **result)
-{
- struct gensec_security *gensec_security = talloc_get_type(context, struct gensec_security);
- const char *realm = cli_credentials_get_realm(gensec_get_credentials(gensec_security));
- int i;
- if (id != SASL_CB_GETREALM) {
- return SASL_FAIL;
- }
-
- for (i=0; availrealms && availrealms[i]; i++) {
- if (strcasecmp_m(realm, availrealms[i]) == 0) {
- result[i] = availrealms[i];
- return SASL_OK;
- }
- }
- /* None of the realms match, so lets not specify one */
- *result = "";
- return SASL_OK;
-}
-
-static int gensec_sasl_get_password(sasl_conn_t *conn, void *context, int id,
- sasl_secret_t **psecret)
-{
- struct gensec_security *gensec_security = talloc_get_type(context, struct gensec_security);
- const char *password = cli_credentials_get_password(gensec_get_credentials(gensec_security));
-
- sasl_secret_t *secret;
- if (!password) {
- *psecret = NULL;
- return SASL_OK;
- }
- secret = talloc_size(gensec_security, sizeof(sasl_secret_t)+strlen(password)+1);
- if (!secret) {
- return SASL_NOMEM;
- }
- secret->len = strlen(password);
- strlcpy((char*)secret->data, password, secret->len+1);
- *psecret = secret;
- return SASL_OK;
-}
-
-static int gensec_sasl_dispose(struct gensec_sasl_state *gensec_sasl_state)
-{
- sasl_dispose(&gensec_sasl_state->conn);
- return SASL_OK;
-}
-
-typedef int (*__gensec_sasl_callback_t)(void);
-
-static NTSTATUS gensec_sasl_client_start(struct gensec_security *gensec_security)
-{
- struct gensec_sasl_state *gensec_sasl_state;
- const char *service = gensec_get_target_service(gensec_security);
- const char *target_name = gensec_get_target_hostname(gensec_security);
- const struct tsocket_address *tlocal_addr = gensec_get_local_address(gensec_security);
- const struct tsocket_address *tremote_addr = gensec_get_remote_address(gensec_security);
- char *local_addr = NULL;
- char *remote_addr = NULL;
- int sasl_ret;
-
- sasl_callback_t *callbacks;
-
- gensec_sasl_state = talloc_zero(gensec_security, struct gensec_sasl_state);
- if (!gensec_sasl_state) {
- return NT_STATUS_NO_MEMORY;
- }
-
- callbacks = talloc_array(gensec_sasl_state, sasl_callback_t, 5);
- callbacks[0].id = SASL_CB_USER;
- callbacks[0].proc = (__gensec_sasl_callback_t)gensec_sasl_get_user;
- callbacks[0].context = gensec_security;
-
- callbacks[1].id = SASL_CB_AUTHNAME;
- callbacks[1].proc = (__gensec_sasl_callback_t)gensec_sasl_get_user;
- callbacks[1].context = gensec_security;
-
- callbacks[2].id = SASL_CB_GETREALM;
- callbacks[2].proc = (__gensec_sasl_callback_t)gensec_sasl_get_realm;
- callbacks[2].context = gensec_security;
-
- callbacks[3].id = SASL_CB_PASS;
- callbacks[3].proc = (__gensec_sasl_callback_t)gensec_sasl_get_password;
- callbacks[3].context = gensec_security;
-
- callbacks[4].id = SASL_CB_LIST_END;
- callbacks[4].proc = NULL;
- callbacks[4].context = NULL;
-
- gensec_security->private_data = gensec_sasl_state;
-
- if (tlocal_addr) {
- local_addr = talloc_asprintf(gensec_sasl_state,
- "%s;%d",
- tsocket_address_inet_addr_string(tlocal_addr, gensec_sasl_state),
- tsocket_address_inet_port(tlocal_addr));
- }
-
- if (tremote_addr) {
- remote_addr = talloc_asprintf(gensec_sasl_state,
- "%s;%d",
- tsocket_address_inet_addr_string(tremote_addr, gensec_sasl_state),
- tsocket_address_inet_port(tremote_addr));
- }
- gensec_sasl_state->step = 0;
-
- sasl_ret = sasl_client_new(service,
- target_name,
- local_addr, remote_addr, callbacks, 0,
- &gensec_sasl_state->conn);
-
- if (sasl_ret == SASL_OK) {
- sasl_security_properties_t props;
- talloc_set_destructor(gensec_sasl_state, gensec_sasl_dispose);
-
- ZERO_STRUCT(props);
- if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
- props.min_ssf = 1;
- props.max_ssf = 1;
- props.maxbufsize = 65536;
- gensec_sasl_state->wrap = true;
- }
- if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
- props.min_ssf = 40;
- props.max_ssf = UINT_MAX;
- props.maxbufsize = 65536;
- gensec_sasl_state->wrap = true;
- }
-
- sasl_ret = sasl_setprop(gensec_sasl_state->conn, SASL_SEC_PROPS, &props);
- }
- if (sasl_ret != SASL_OK) {
- DEBUG(1, ("GENSEC SASL: client_new failed: %s\n", sasl_errdetail(gensec_sasl_state->conn)));
- }
- return sasl_nt_status(sasl_ret);
-}
-
-static NTSTATUS gensec_sasl_update(struct gensec_security *gensec_security,
- TALLOC_CTX *out_mem_ctx,
- struct tevent_context *ev,
- const DATA_BLOB in, DATA_BLOB *out)
-{
- struct gensec_sasl_state *gensec_sasl_state = talloc_get_type(gensec_security->private_data,
- struct gensec_sasl_state);
- int sasl_ret;
- const char *out_data;
- unsigned int out_len;
-
- if (gensec_sasl_state->step == 0) {
- const char *mech;
- sasl_ret = sasl_client_start(gensec_sasl_state->conn, gensec_security->ops->sasl_name,
- NULL, &out_data, &out_len, &mech);
- } else {
- sasl_ret = sasl_client_step(gensec_sasl_state->conn,
- (char*)in.data, in.length, NULL,
- &out_data, &out_len);
- }
- if (sasl_ret == SASL_OK || sasl_ret == SASL_CONTINUE) {
- *out = data_blob_talloc(out_mem_ctx, out_data, out_len);
- } else {
- DEBUG(1, ("GENSEC SASL: step %d update failed: %s\n", gensec_sasl_state->step,
- sasl_errdetail(gensec_sasl_state->conn)));
- }
- gensec_sasl_state->step++;
- return sasl_nt_status(sasl_ret);
-}
-
-static NTSTATUS gensec_sasl_unwrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *out_mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed)
-{
- struct gensec_sasl_state *gensec_sasl_state = talloc_get_type(gensec_security->private_data,
- struct gensec_sasl_state);
- const char *out_data;
- unsigned int out_len;
-
- int sasl_ret = sasl_decode(gensec_sasl_state->conn,
- (char*)in->data, in->length, &out_data,
- &out_len);
- if (sasl_ret == SASL_OK) {
- *out = data_blob_talloc(out_mem_ctx, out_data, out_len);
- *len_processed = in->length;
- } else {
- DEBUG(1, ("GENSEC SASL: unwrap failed: %s\n", sasl_errdetail(gensec_sasl_state->conn)));
- }
- return sasl_nt_status(sasl_ret);
-
-}
-
-static NTSTATUS gensec_sasl_wrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *out_mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed)
-{
- struct gensec_sasl_state *gensec_sasl_state = talloc_get_type(gensec_security->private_data,
- struct gensec_sasl_state);
- const char *out_data;
- unsigned int out_len;
- unsigned len_permitted;
- int sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF,
- (const void**)&len_permitted);
- if (sasl_ret != SASL_OK) {
- return sasl_nt_status(sasl_ret);
- }
- len_permitted = MIN(len_permitted, in->length);
-
- sasl_ret = sasl_encode(gensec_sasl_state->conn,
- (char*)in->data, len_permitted, &out_data,
- &out_len);
- if (sasl_ret == SASL_OK) {
- *out = data_blob_talloc(out_mem_ctx, out_data, out_len);
- *len_processed = in->length;
- } else {
- DEBUG(1, ("GENSEC SASL: wrap failed: %s\n", sasl_errdetail(gensec_sasl_state->conn)));
- }
- return sasl_nt_status(sasl_ret);
-}
-
-/* Try to figure out what features we actually got on the connection */
-static bool gensec_sasl_have_feature(struct gensec_security *gensec_security,
- uint32_t feature)
-{
- struct gensec_sasl_state *gensec_sasl_state = talloc_get_type(gensec_security->private_data,
- struct gensec_sasl_state);
- sasl_ssf_t ssf;
- int sasl_ret;
-
- /* If we did not elect to wrap, then we have neither sign nor seal, no matter what the SSF claims */
- if (!gensec_sasl_state->wrap) {
- return false;
- }
-
- sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF,
- (const void**)&ssf);
- if (sasl_ret != SASL_OK) {
- return false;
- }
- if (feature & GENSEC_FEATURE_SIGN) {
- if (ssf == 0) {
- return false;
- }
- if (ssf >= 1) {
- return true;
- }
- }
- if (feature & GENSEC_FEATURE_SEAL) {
- if (ssf <= 1) {
- return false;
- }
- if (ssf > 1) {
- return true;
- }
- }
- return false;
-}
-
-/* This could in theory work with any SASL mech */
-static const struct gensec_security_ops gensec_sasl_security_ops = {
- .name = "sasl-DIGEST-MD5",
- .sasl_name = "DIGEST-MD5",
- .client_start = gensec_sasl_client_start,
- .update = gensec_sasl_update,
- .wrap_packets = gensec_sasl_wrap_packets,
- .unwrap_packets = gensec_sasl_unwrap_packets,
- .have_feature = gensec_sasl_have_feature,
- .enabled = true,
- .priority = GENSEC_SASL
-};
-
-static int gensec_sasl_log(void *context,
- int sasl_log_level,
- const char *message)
-{
- int dl;
- switch (sasl_log_level) {
- case SASL_LOG_NONE:
- dl = 0;
- break;
- case SASL_LOG_ERR:
- dl = 1;
- break;
- case SASL_LOG_FAIL:
- dl = 2;
- break;
- case SASL_LOG_WARN:
- dl = 3;
- break;
- case SASL_LOG_NOTE:
- dl = 5;
- break;
- case SASL_LOG_DEBUG:
- dl = 10;
- break;
- case SASL_LOG_TRACE:
- dl = 11;
- break;
-#if DEBUG_PASSWORD
- case SASL_LOG_PASS:
- dl = 100;
- break;
-#endif
- default:
- dl = 0;
- break;
- }
- DEBUG(dl, ("gensec_sasl: %s\n", message));
-
- return SASL_OK;
-}
-
-NTSTATUS gensec_sasl_init(void)
-{
- NTSTATUS ret;
- int sasl_ret;
-#if 0
- int i;
- const char **sasl_mechs;
-#endif
-
- static const sasl_callback_t callbacks[] = {
- {
- .id = SASL_CB_LOG,
- .proc = (__gensec_sasl_callback_t)gensec_sasl_log,
- .context = NULL,
- },
- {
- .id = SASL_CB_LIST_END,
- .proc = NULL,
- .context = NULL,
- }
- };
- sasl_ret = sasl_client_init(callbacks);
-
- if (sasl_ret == SASL_NOMECH) {
- /* Nothing to do here */
- return NT_STATUS_OK;
- }
-
- if (sasl_ret != SASL_OK) {
- return sasl_nt_status(sasl_ret);
- }
-
- /* For now, we just register DIGEST-MD5 */
-#if 1
- ret = gensec_register(&gensec_sasl_security_ops);
- if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(0,("Failed to register '%s' gensec backend!\n",
- gensec_sasl_security_ops.name));
- return ret;
- }
-#else
- sasl_mechs = sasl_global_listmech();
- for (i = 0; sasl_mechs && sasl_mechs[i]; i++) {
- const struct gensec_security_ops *oldmech;
- struct gensec_security_ops *newmech;
- oldmech = gensec_security_by_sasl_name(NULL, sasl_mechs[i]);
- if (oldmech) {
- continue;
- }
- newmech = talloc(talloc_autofree_context(), struct gensec_security_ops);
- if (!newmech) {
- return NT_STATUS_NO_MEMORY;
- }
- *newmech = gensec_sasl_security_ops;
- newmech->sasl_name = talloc_strdup(newmech, sasl_mechs[i]);
- newmech->name = talloc_asprintf(newmech, "sasl-%s", sasl_mechs[i]);
- if (!newmech->sasl_name || !newmech->name) {
- return NT_STATUS_NO_MEMORY;
- }
-
- ret = gensec_register(newmech);
- if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(0,("Failed to register '%s' gensec backend!\n",
- gensec_sasl_security_ops.name));
- return ret;
- }
- }
-#endif
- return NT_STATUS_OK;
-}
diff --git a/source4/auth/gensec/wscript_build b/source4/auth/gensec/wscript_build
index 097a740..46915f0 100755
--- a/source4/auth/gensec/wscript_build
+++ b/source4/auth/gensec/wscript_build
@@ -22,16 +22,6 @@ bld.SAMBA_MODULE('gensec_gssapi',
deps='gssapi samba-credentials authkrb5 com_err gensec_util'
)
-
-bld.SAMBA_MODULE('cyrus_sasl',
- source='cyrus_sasl.c',
- subsystem='gensec',
- init_function='gensec_sasl_init',
- deps='samba-credentials sasl2',
- enabled=bld.CONFIG_SET('HAVE_SASL')
- )
-
-
bld.SAMBA_PYTHON('pygensec',
source='pygensec.c',
deps='gensec pytalloc-util pyparam_util',
diff --git a/source4/auth/wscript_configure b/source4/auth/wscript_configure
index 1d26cde..d25cc0b 100644
--- a/source4/auth/wscript_configure
+++ b/source4/auth/wscript_configure
@@ -2,7 +2,3 @@
conf.CHECK_HEADERS('security/pam_appl.h')
conf.CHECK_FUNCS_IN('pam_start', 'pam', checklibc=True)
-
-if (conf.CHECK_HEADERS('sasl/sasl.h') and
- conf.CHECK_FUNCS_IN('sasl_client_init', 'sasl2')):
- conf.DEFINE('HAVE_SASL', 1)
--
1.9.1
From 22abce6e7388c7fb010afa157af086902eda8f46 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 13:47:29 +0200
Subject: [PATCH 08/12] s4:auth/gensec: remove unused include of
lib/socket/socket.h
---
source4/auth/gensec/gensec_krb5.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index 362108e..b1ecd18 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -27,7 +27,6 @@
#include "system/kerberos.h"
#include "auth/kerberos/kerberos.h"
#include "auth/auth.h"
-#include "lib/socket/socket.h"
#include "lib/tsocket/tsocket.h"
#include "librpc/gen_ndr/dcerpc.h"
#include "auth/credentials/credentials.h"
--
1.9.1
From fee35de9172b157d987ecbb496044e9f8fc33b00 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 12:46:27 +0200
Subject: [PATCH 09/12] s4:auth/gensec: remove unused gensec_socket_init()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/auth/gensec/gensec_socket.h | 28 ---
source4/auth/gensec/socket.c | 435 ------------------------------------
source4/auth/gensec/wscript_build | 2 +-
3 files changed, 1 insertion(+), 464 deletions(-)
delete mode 100644 source4/auth/gensec/gensec_socket.h
delete mode 100644 source4/auth/gensec/socket.c
diff --git a/source4/auth/gensec/gensec_socket.h b/source4/auth/gensec/gensec_socket.h
deleted file mode 100644
index bb12cc0..0000000
--- a/source4/auth/gensec/gensec_socket.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- 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 3 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, see <http://www.gnu.org/licenses/>.
-*/
-
-NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- struct socket_context *current_socket,
- struct tevent_context *ev,
- void (*recv_handler)(void *, uint16_t),
- void *recv_private,
- struct socket_context **new_socket);
diff --git a/source4/auth/gensec/socket.c b/source4/auth/gensec/socket.c
deleted file mode 100644
index c89e080..0000000
--- a/source4/auth/gensec/socket.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- 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 3 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, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "lib/events/events.h"
-#include "lib/socket/socket.h"
-#include "lib/stream/packet.h"
-#include "auth/gensec/gensec.h"
-#include "auth/gensec/gensec_proto.h"
-#include "auth/gensec/gensec_socket.h"
-
-static const struct socket_ops gensec_socket_ops;
-
-struct gensec_socket {
- struct gensec_security *gensec_security;
- struct socket_context *socket;
- struct tevent_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;
- bool wrap; /* Should we be wrapping on this socket at all? */
-};
-
-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;
-}
-
-static NTSTATUS gensec_socket_full_request(void *private_data, DATA_BLOB blob, size_t *size)
-{
- struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
- struct gensec_security *gensec_security = gensec_socket->gensec_security;
- return gensec_packet_full_request(gensec_security, blob, size);
-}
-
-/* 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->wrap) {
- return socket_pending(gensec_socket->socket, npending);
- }
-
- 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_data, NTSTATUS status)
-{
- struct gensec_socket *gensec_socket = talloc_get_type(private_data, 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 tevent_context *ev,
- struct tevent_timer *te,
- struct timeval t, void *private_data)
-{
- struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
-
- gensec_socket->in_extra_read++;
- gensec_socket->recv_handler(gensec_socket->recv_private, TEVENT_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 > 0) {
- /* Schedule this funcion to run again */
- tevent_add_timer(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);
-
- if (!gensec_socket->wrap) {
- return socket_recv(gensec_socket->socket, buf, wantlen, nread);
- }
-
- 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) */
- tevent_add_timer(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, DATA_BLOB blob)
-{
- struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
- DATA_BLOB unwrapped;
- NTSTATUS nt_status;
- TALLOC_CTX *mem_ctx;
- size_t packet_size;
-
- mem_ctx = talloc_new(gensec_socket);
- if (!mem_ctx) {
- return NT_STATUS_NO_MEMORY;
- }
- nt_status = gensec_unwrap_packets(gensec_socket->gensec_security,
- mem_ctx,
- &blob, &unwrapped,
- &packet_size);
- if (!NT_STATUS_IS_OK(nt_status)) {
- talloc_free(mem_ctx);
- return nt_status;
- }
-
- if (packet_size != blob.length) {
- DEBUG(0, ("gensec_socket_unwrap: Did not consume entire packet!\n"));
- talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- /* We could change this into a linked list, and have
- * gensec_socket_recv() and gensec_socket_pending() walk the
- * linked list */
-
- if (!data_blob_append(gensec_socket, &gensec_socket->read_buffer,
- unwrapped.data, unwrapped.length)) {
- talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- talloc_free(mem_ctx);
- return NT_STATUS_OK;
-}
-
-/* when the data is sent, we know we have not been interrupted */
-static void send_callback(void *private_data)
-{
- struct gensec_socket *gensec_socket = talloc_get_type(private_data, 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 wrapped;
- TALLOC_CTX *mem_ctx;
-
- if (!gensec_socket->wrap) {
- return socket_send(gensec_socket->socket, blob, sendlen);
- }
-
- *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;
- }
-
- nt_status = gensec_wrap_packets(gensec_socket->gensec_security,
- mem_ctx,
- blob, &wrapped,
- &gensec_socket->orig_send_len);
- if (!NT_STATUS_IS_OK(nt_status)) {
- talloc_free(mem_ctx);
- return nt_status;
- }
-
- gensec_socket->interrupted = true;
- gensec_socket->error = NT_STATUS_OK;
-
- nt_status = packet_send_callback(gensec_socket->packet,
- wrapped,
- 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;
- }
-}
-
-/* Turn a normal socket into a potentially GENSEC wrapped socket */
-/* CAREFUL: this function will steal 'current_socket' */
-
-NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- struct socket_context *current_socket,
- struct tevent_context *ev,
- void (*recv_handler)(void *, uint16_t),
- void *recv_private,
- struct socket_context **new_socket)
-{
- struct gensec_socket *gensec_socket;
- struct socket_context *new_sock;
- NTSTATUS nt_status;
-
- nt_status = socket_create_with_ops(mem_ctx, &gensec_socket_ops, &new_sock,
- SOCKET_TYPE_STREAM, current_socket->flags | SOCKET_FLAG_ENCRYPT);
- if (!NT_STATUS_IS_OK(nt_status)) {
- *new_socket = NULL;
- return nt_status;
- }
-
- new_sock->state = current_socket->state;
-
- gensec_socket = talloc(new_sock, struct gensec_socket);
- if (gensec_socket == NULL) {
- *new_socket = NULL;
- talloc_free(new_sock);
- return NT_STATUS_NO_MEMORY;
- }
-
- new_sock->private_data = gensec_socket;
- gensec_socket->socket = current_socket;
-
- /* 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)) {
-
- gensec_socket->wrap = false;
- talloc_steal(gensec_socket, current_socket);
- *new_socket = new_sock;
- return NT_STATUS_OK;
- }
-
- gensec_socket->gensec_security = gensec_security;
-
- gensec_socket->wrap = true;
- 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->recv_handler = recv_handler;
- gensec_socket->recv_private = recv_private;
- gensec_socket->ev = ev;
-
- gensec_socket->packet = packet_init(gensec_socket);
- if (gensec_socket->packet == NULL) {
- *new_socket = NULL;
- talloc_free(new_sock);
- return NT_STATUS_NO_MEMORY;
- }
-
- packet_set_private(gensec_socket->packet, gensec_socket);
- packet_set_socket(gensec_socket->packet, gensec_socket->socket);
- packet_set_callback(gensec_socket->packet, gensec_socket_unwrap);
- packet_set_full_request(gensec_socket->packet, gensec_socket_full_request);
- 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 */
-
- talloc_steal(gensec_socket, current_socket);
- *new_socket = new_sock;
- return NT_STATUS_OK;
-}
-
-
-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/wscript_build b/source4/auth/gensec/wscript_build
index 46915f0..3c7cc2e 100755
--- a/source4/auth/gensec/wscript_build
+++ b/source4/auth/gensec/wscript_build
@@ -1,7 +1,7 @@
#!/usr/bin/env python
bld.SAMBA_SUBSYSTEM('gensec_util',
- source='socket.c gensec_tstream.c',
+ source='gensec_tstream.c',
deps='tevent-util tevent samba-util LIBTSOCKET',
autoproto='gensec_proto.h')
--
1.9.1
From 492dc521d22c890c112433528c8b595676e34305 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 12:47:10 +0200
Subject: [PATCH 10/12] auth/gensec: remove unused gensec_[un]wrap_packets()
hooks
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
auth/gensec/gensec.h | 21 --------
auth/gensec/gensec_internal.h | 12 -----
auth/gensec/gensec_util.c | 116 ------------------------------------------
auth/gensec/spnego.c | 56 --------------------
auth/gensec/wscript_build | 2 +-
5 files changed, 1 insertion(+), 206 deletions(-)
diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h
index 0d3a29c..d09813e 100644
--- a/auth/gensec/gensec.h
+++ b/auth/gensec/gensec.h
@@ -107,30 +107,9 @@ const struct gensec_critical_sizes *gensec_interface_version(void);
/* Socket wrapper */
struct gensec_security;
-struct socket_context;
struct auth4_context;
struct auth_user_info_dc;
-/* These functions are for use here only (public because SPNEGO must
- * use them for recursion) */
-NTSTATUS gensec_wrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed);
-/* These functions are for use here only (public because SPNEGO must
- * use them for recursion) */
-NTSTATUS gensec_unwrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed);
-
-/* These functions are for use here only (public because SPNEGO must
- * use them for recursion) */
-NTSTATUS gensec_packet_full_request(struct gensec_security *gensec_security,
- DATA_BLOB blob, size_t *size);
-
struct loadparm_context;
NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h
index c04164a..45a66f8 100644
--- a/auth/gensec/gensec_internal.h
+++ b/auth/gensec/gensec_internal.h
@@ -74,18 +74,6 @@ struct gensec_security_ops {
TALLOC_CTX *mem_ctx,
const DATA_BLOB *in,
DATA_BLOB *out);
- NTSTATUS (*wrap_packets)(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed);
- NTSTATUS (*unwrap_packets)(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed);
- NTSTATUS (*packet_full_request)(struct gensec_security *gensec_security,
- DATA_BLOB blob, size_t *size);
NTSTATUS (*session_key)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx,
DATA_BLOB *session_key);
NTSTATUS (*session_info)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx,
diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c
index b8e38b7..8ef4b25 100644
--- a/auth/gensec/gensec_util.c
+++ b/auth/gensec/gensec_util.c
@@ -68,122 +68,6 @@ NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx,
}
/*
- * These functions are for use in the deprecated
- * gensec_socket code (public because SPNEGO must
- * use them for recursion)
- */
-_PUBLIC_ NTSTATUS gensec_wrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed)
-{
- if (!gensec_security->ops->wrap_packets) {
- NTSTATUS nt_status;
- size_t max_input_size;
- DATA_BLOB unwrapped, wrapped;
- max_input_size = gensec_max_input_size(gensec_security);
- unwrapped = data_blob_const(in->data, MIN(max_input_size, (size_t)in->length));
-
- nt_status = gensec_wrap(gensec_security,
- mem_ctx,
- &unwrapped, &wrapped);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
-
- *out = data_blob_talloc(mem_ctx, NULL, 4);
- if (!out->data) {
- return NT_STATUS_NO_MEMORY;
- }
- RSIVAL(out->data, 0, wrapped.length);
-
- if (!data_blob_append(mem_ctx, out, wrapped.data, wrapped.length)) {
- return NT_STATUS_NO_MEMORY;
- }
- *len_processed = unwrapped.length;
- return NT_STATUS_OK;
- }
- return gensec_security->ops->wrap_packets(gensec_security, mem_ctx, in, out,
- len_processed);
-}
-
-/*
- * These functions are for use in the deprecated
- * gensec_socket code (public because SPNEGO must
- * use them for recursion)
- */
-NTSTATUS gensec_unwrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed)
-{
- if (!gensec_security->ops->unwrap_packets) {
- DATA_BLOB wrapped;
- NTSTATUS nt_status;
- size_t packet_size;
- if (in->length < 4) {
- /* Missing the header we already had! */
- DEBUG(0, ("Asked to unwrap packet of bogus length! How did we get the short packet?!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- packet_size = RIVAL(in->data, 0);
-
- wrapped = data_blob_const(in->data + 4, packet_size);
-
- if (wrapped.length > (in->length - 4)) {
- DEBUG(0, ("Asked to unwrap packed of bogus length %d > %d! How did we get this?!\n",
- (int)wrapped.length, (int)(in->length - 4)));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- nt_status = gensec_unwrap(gensec_security,
- mem_ctx,
- &wrapped, out);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
-
- *len_processed = packet_size + 4;
- return nt_status;
- }
- return gensec_security->ops->unwrap_packets(gensec_security, mem_ctx, in, out,
- len_processed);
-}
-
-/*
- * These functions are for use in the deprecated
- * gensec_socket code (public because SPNEGO must
- * use them for recursion)
- */
-NTSTATUS gensec_packet_full_request(struct gensec_security *gensec_security,
- DATA_BLOB blob, size_t *size)
-{
- if (gensec_security->ops->packet_full_request) {
- return gensec_security->ops->packet_full_request(gensec_security,
- blob, size);
- }
- if (gensec_security->ops->unwrap_packets) {
- if (blob.length) {
- *size = blob.length;
- return NT_STATUS_OK;
- }
- return STATUS_MORE_ENTRIES;
- }
-
- if (blob.length < 4) {
- return STATUS_MORE_ENTRIES;
- }
- *size = 4 + RIVAL(blob.data, 0);
- if (*size > blob.length) {
- return STATUS_MORE_ENTRIES;
- }
- return NT_STATUS_OK;
-}
-
-/*
magic check a GSS-API wrapper packet for an Kerberos OID
*/
static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c
index 20cacdb..85c70e1 100644
--- a/auth/gensec/spnego.c
+++ b/auth/gensec/spnego.c
@@ -221,59 +221,6 @@ static NTSTATUS gensec_spnego_unwrap(struct gensec_security *gensec_security,
mem_ctx, in, out);
}
-static NTSTATUS gensec_spnego_wrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed)
-{
- struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
-
- if (spnego_state->state_position != SPNEGO_DONE
- && spnego_state->state_position != SPNEGO_FALLBACK) {
- DEBUG(1, ("gensec_spnego_wrap: wrong state for wrap\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return gensec_wrap_packets(spnego_state->sub_sec_security,
- mem_ctx, in, out,
- len_processed);
-}
-
-static NTSTATUS gensec_spnego_packet_full_request(struct gensec_security *gensec_security,
- DATA_BLOB blob, size_t *size)
-{
- struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
-
- if (spnego_state->state_position != SPNEGO_DONE
- && spnego_state->state_position != SPNEGO_FALLBACK) {
- DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return gensec_packet_full_request(spnego_state->sub_sec_security,
- blob, size);
-}
-
-static NTSTATUS gensec_spnego_unwrap_packets(struct gensec_security *gensec_security,
- TALLOC_CTX *mem_ctx,
- const DATA_BLOB *in,
- DATA_BLOB *out,
- size_t *len_processed)
-{
- struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
-
- if (spnego_state->state_position != SPNEGO_DONE
- && spnego_state->state_position != SPNEGO_FALLBACK) {
- DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return gensec_unwrap_packets(spnego_state->sub_sec_security,
- mem_ctx, in, out,
- len_processed);
-}
-
static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security, size_t data_size)
{
struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data;
@@ -1384,11 +1331,8 @@ static const struct gensec_security_ops gensec_spnego_security_ops = {
.max_input_size = gensec_spnego_max_input_size,
.check_packet = gensec_spnego_check_packet,
.unseal_packet = gensec_spnego_unseal_packet,
- .packet_full_request = gensec_spnego_packet_full_request,
.wrap = gensec_spnego_wrap,
.unwrap = gensec_spnego_unwrap,
- .wrap_packets = gensec_spnego_wrap_packets,
- .unwrap_packets = gensec_spnego_unwrap_packets,
.session_key = gensec_spnego_session_key,
.session_info = gensec_spnego_session_info,
.want_feature = gensec_spnego_want_feature,
diff --git a/auth/gensec/wscript_build b/auth/gensec/wscript_build
index e6d179b..e4c4a08 100755
--- a/auth/gensec/wscript_build
+++ b/auth/gensec/wscript_build
@@ -3,7 +3,7 @@ bld.SAMBA_LIBRARY('gensec',
source='gensec.c gensec_start.c gensec_util.c',
pc_files='gensec.pc',
autoproto='gensec_toplevel_proto.h',
- public_deps='tevent-util samba-util errors LIBPACKET auth_system_session samba-modules gensec_util asn1util',
+ public_deps='tevent-util samba-util errors auth_system_session samba-modules gensec_util asn1util',
public_headers='gensec.h',
deps='com_err',
vnum='0.0.1'
--
1.9.1
From e798b83051d80beb1884bdb2fae266430d8d8e26 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sat, 20 Jun 2015 16:54:33 +0200
Subject: [PATCH 11/12] s3:ntlm_auth: don't start gensec backend twice
ntlm_auth_start_ntlmssp_server() was used in two cases
and both call gensec_start_mech_by_oid() again.
So we remove gensec_start_mech_by_oid() and rename the function
to ntlm_auth_prepare_gensec_server.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source3/utils/ntlm_auth.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index ca13481..a5fd249 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -1027,9 +1027,9 @@ static struct auth4_context *make_auth4_context_ntlm_auth(TALLOC_CTX *mem_ctx, b
return auth4_context;
}
-static NTSTATUS ntlm_auth_start_ntlmssp_server(TALLOC_CTX *mem_ctx,
- struct loadparm_context *lp_ctx,
- struct gensec_security **gensec_security_out)
+static NTSTATUS ntlm_auth_prepare_gensec_server(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct gensec_security **gensec_security_out)
{
struct gensec_security *gensec_security;
NTSTATUS nt_status;
@@ -1135,12 +1135,6 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(TALLOC_CTX *mem_ctx,
talloc_unlink(tmp_ctx, gensec_settings);
talloc_unlink(tmp_ctx, auth4_context);
- nt_status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_NTLMSSP);
- if (!NT_STATUS_IS_OK(nt_status)) {
- TALLOC_FREE(tmp_ctx);
- return nt_status;
- }
-
*gensec_security_out = talloc_steal(mem_ctx, gensec_security);
TALLOC_FREE(tmp_ctx);
return NT_STATUS_OK;
@@ -1541,8 +1535,8 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
case GSS_SPNEGO_SERVER:
case SQUID_2_5_NTLMSSP:
{
- nt_status = ntlm_auth_start_ntlmssp_server(state, lp_ctx,
- &state->gensec_state);
+ nt_status = ntlm_auth_prepare_gensec_server(state, lp_ctx,
+ &state->gensec_state);
if (!NT_STATUS_IS_OK(nt_status)) {
x_fprintf(x_stdout, "BH GENSEC mech failed to start: %s\n", nt_errstr(nt_status));
talloc_free(mem_ctx);
--
1.9.1
From 6ae27453a5f985be04a4b47a36d78e7fe55e9a2b Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 19 Jun 2015 00:35:29 +0200
Subject: [PATCH 12/12] s4:selftest: run rpc.echo tests also with krb5
krb5,sign krb5,seal
Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
source4/selftest/tests.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index da3cb98..c3f819e 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -187,7 +187,7 @@ for env in ["ad_dc_ntvfs", "fl2000dc", "fl2003dc", "fl2008r2dc", "ad_dc"]:
plansmbtorture4testsuite('rpc.echo', env, ["%s:$SERVER[]" % (transport,), '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN'], "samba4.rpc.echo on %s" % (transport, ))
# Echo tests test bulk Kerberos encryption of DCE/RPC
- for bindoptions in ["connect", "spnego", "spnego,sign", "spnego,seal"] + validate_list + ["padcheck", "bigendian", "bigendian,seal"]:
+ for bindoptions in ["connect", "krb5", "krb5,sign", "krb5,seal", "spnego", "spnego,sign", "spnego,seal"] + validate_list + ["padcheck", "bigendian", "bigendian,seal"]:
echooptions = "--option=socket:testnonblock=True --option=torture:quick=yes -k yes"
plansmbtorture4testsuite('rpc.echo', env, ["%s:$SERVER[%s]" % (transport, bindoptions), echooptions, '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN'], "samba4.rpc.echo on %s with %s and %s" % (transport, bindoptions, echooptions))
plansmbtorture4testsuite("net.api.become.dc", env, '$SERVER[%s] -U$USERNAME%%$PASSWORD -W$DOMAIN' % validate)
--
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150622/15f25911/attachment.pgp>
More information about the samba-technical
mailing list