summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-02-18 17:47:43 +1100
committerAndrew Bartlett <abartlet@samba.org>2009-02-18 17:47:43 +1100
commit48ba64010046bece3b54009131f88c851ec82047 (patch)
tree0430d009052247af062a3f0f301f2eab33c4d969
parent6b8b7665bdbf47e70e0d6d904c1234c03321182d (diff)
parentbb7e6f0f51a91e461c18efd392af3e4fc6174c34 (diff)
downloadsamba-48ba64010046bece3b54009131f88c851ec82047.tar.gz
samba-48ba64010046bece3b54009131f88c851ec82047.tar.bz2
samba-48ba64010046bece3b54009131f88c851ec82047.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba into master-devel
-rw-r--r--source4/ldap_server/ldap_extended.c1
-rw-r--r--source4/ldap_server/ldap_server.c4
-rw-r--r--source4/lib/stream/packet.c38
-rw-r--r--source4/lib/stream/packet.h1
-rw-r--r--source4/lib/tls/config.m41
-rw-r--r--source4/lib/tls/tls.c10
-rw-r--r--source4/lib/tls/tlscert.c21
-rw-r--r--source4/libcli/ldap/ldap_client.c4
8 files changed, 69 insertions, 11 deletions
diff --git a/source4/ldap_server/ldap_extended.c b/source4/ldap_server/ldap_extended.c
index 4479eab560..66ab4eea32 100644
--- a/source4/ldap_server/ldap_extended.c
+++ b/source4/ldap_server/ldap_extended.c
@@ -38,6 +38,7 @@ static void ldapsrv_start_tls(void *private_data)
ctx->conn->sockets.tls = ctx->tls_socket;
ctx->conn->connection->socket = ctx->tls_socket;
packet_set_socket(ctx->conn->packet, ctx->conn->connection->socket);
+ packet_set_unreliable_select(ctx->conn->packet);
}
static NTSTATUS ldapsrv_StartTLS(struct ldapsrv_call *call,
diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c
index 61ff387152..da44c02aa8 100644
--- a/source4/ldap_server/ldap_server.c
+++ b/source4/ldap_server/ldap_server.c
@@ -386,6 +386,10 @@ static void ldapsrv_accept(struct stream_connection *c)
packet_set_event_context(conn->packet, c->event.ctx);
packet_set_fde(conn->packet, c->event.fde);
packet_set_serialise(conn->packet);
+
+ if (conn->sockets.tls) {
+ packet_set_unreliable_select(conn->packet);
+ }
/* Ensure we don't get packets until the database is ready below */
packet_recv_disable(conn->packet);
diff --git a/source4/lib/stream/packet.c b/source4/lib/stream/packet.c
index f614e9490a..f5e2b843cd 100644
--- a/source4/lib/stream/packet.c
+++ b/source4/lib/stream/packet.c
@@ -47,6 +47,8 @@ struct packet_context {
bool busy;
bool destructor_called;
+ bool unreliable_select;
+
struct send_element {
struct send_element *next, *prev;
DATA_BLOB blob;
@@ -176,6 +178,21 @@ _PUBLIC_ void packet_set_nofree(struct packet_context *pc)
pc->nofree = true;
}
+/*
+ tell the packet system that select/poll/epoll on the underlying
+ socket may not be a reliable way to determine if data is available
+ for receive. This happens with underlying socket systems such as the
+ one implemented on top of GNUTLS, where there may be data in
+ encryption/compression buffers that could be received by
+ socket_recv(), while there is no data waiting at the real socket
+ level as seen by select/poll/epoll. The GNUTLS library is supposed
+ to cope with this by always leaving some data sitting in the socket
+ buffer, but it does not seem to be reliable.
+ */
+_PUBLIC_ void packet_set_unreliable_select(struct packet_context *pc)
+{
+ pc->unreliable_select = true;
+}
/*
tell the caller we have an error
@@ -230,6 +247,7 @@ _PUBLIC_ void packet_recv(struct packet_context *pc)
NTSTATUS status;
size_t nread = 0;
DATA_BLOB blob;
+ bool recv_retry = false;
if (pc->processing) {
EVENT_FD_NOT_READABLE(pc->fde);
@@ -269,6 +287,8 @@ _PUBLIC_ void packet_recv(struct packet_context *pc)
return;
}
+again:
+
if (npending + pc->num_read < npending) {
packet_error(pc, NT_STATUS_INVALID_PARAMETER);
return;
@@ -308,17 +328,33 @@ _PUBLIC_ void packet_recv(struct packet_context *pc)
packet_error(pc, status);
return;
}
+ if (recv_retry && NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+ nread = 0;
+ status = NT_STATUS_OK;
+ }
if (!NT_STATUS_IS_OK(status)) {
return;
}
- if (nread == 0) {
+ if (nread == 0 && !recv_retry) {
packet_eof(pc);
return;
}
pc->num_read += nread;
+ if (pc->unreliable_select && nread != 0) {
+ recv_retry = true;
+ status = socket_pending(pc->sock, &npending);
+ if (!NT_STATUS_IS_OK(status)) {
+ packet_error(pc, status);
+ return;
+ }
+ if (npending != 0) {
+ goto again;
+ }
+ }
+
next_partial:
if (pc->partial.length != pc->num_read) {
if (!data_blob_realloc(pc, &pc->partial, pc->num_read)) {
diff --git a/source4/lib/stream/packet.h b/source4/lib/stream/packet.h
index 3c2fb0a683..85f0f26265 100644
--- a/source4/lib/stream/packet.h
+++ b/source4/lib/stream/packet.h
@@ -48,6 +48,7 @@ void packet_set_nofree(struct packet_context *pc);
void packet_recv(struct packet_context *pc);
void packet_recv_disable(struct packet_context *pc);
void packet_recv_enable(struct packet_context *pc);
+void packet_set_unreliable_select(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,
diff --git a/source4/lib/tls/config.m4 b/source4/lib/tls/config.m4
index 74c6bd1d44..0bafc5ddf1 100644
--- a/source4/lib/tls/config.m4
+++ b/source4/lib/tls/config.m4
@@ -39,4 +39,5 @@ if test x$use_gnutls = xyes; then
AC_CHECK_TYPES([gnutls_datum],,,[#include "gnutls/gnutls.h"])
AC_CHECK_TYPES([gnutls_datum_t],,,[#include "gnutls/gnutls.h"])
AC_DEFINE(ENABLE_GNUTLS,1,[Whether we have gnutls support (SSL)])
+ AC_CHECK_HEADERS(gcrypt.h)
fi
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index 99a15059ad..1014ab07a8 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -362,7 +362,7 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, struct loadparm_context *
const char *cafile = lp_tls_cafile(tmp_ctx, lp_ctx);
const char *crlfile = lp_tls_crlfile(tmp_ctx, lp_ctx);
const char *dhpfile = lp_tls_dhpfile(tmp_ctx, lp_ctx);
- void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *);
+ void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *, const char *);
params = talloc(mem_ctx, struct tls_params);
if (params == NULL) {
talloc_free(tmp_ctx);
@@ -376,7 +376,13 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, struct loadparm_context *
}
if (!file_exist(cafile)) {
- tls_cert_generate(params, keyfile, certfile, cafile);
+ char *hostname = talloc_asprintf(mem_ctx, "%s.%s",
+ lp_netbios_name(lp_ctx), lp_realm(lp_ctx));
+ if (hostname == NULL) {
+ goto init_failed;
+ }
+ tls_cert_generate(params, hostname, keyfile, certfile, cafile);
+ talloc_free(hostname);
}
ret = gnutls_global_init();
diff --git a/source4/lib/tls/tlscert.c b/source4/lib/tls/tlscert.c
index f2e79f2a89..62e7a72240 100644
--- a/source4/lib/tls/tlscert.c
+++ b/source4/lib/tls/tlscert.c
@@ -24,21 +24,20 @@
#if ENABLE_GNUTLS
#include "gnutls/gnutls.h"
#include "gnutls/x509.h"
+#if HAVE_GCRYPT_H
+#include <gcrypt.h>
+#endif
#define ORGANISATION_NAME "Samba Administration"
#define UNIT_NAME "Samba - temporary autogenerated certificate"
-#define COMMON_NAME "Samba"
#define LIFETIME 700*24*60*60
#define DH_BITS 1024
-void tls_cert_generate(TALLOC_CTX *mem_ctx,
- const char *keyfile, const char *certfile,
- const char *cafile);
-
/*
auto-generate a set of self signed certificates
*/
void tls_cert_generate(TALLOC_CTX *mem_ctx,
+ const char *hostname,
const char *keyfile, const char *certfile,
const char *cafile)
{
@@ -67,8 +66,14 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
TLSCHECK(gnutls_global_init());
- DEBUG(0,("Attempting to autogenerate TLS self-signed keys for https\n"));
+ DEBUG(0,("Attempting to autogenerate TLS self-signed keys for https for hostname '%s'\n",
+ hostname));
+#ifdef HAVE_GCRYPT_H
+ DEBUG(3,("Enabling QUICK mode in gcrypt\n"));
+ gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+#endif
+
DEBUG(3,("Generating private key\n"));
TLSCHECK(gnutls_x509_privkey_init(&key));
TLSCHECK(gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, DH_BITS, 0));
@@ -87,7 +92,7 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
UNIT_NAME, strlen(UNIT_NAME)));
TLSCHECK(gnutls_x509_crt_set_dn_by_oid(cacrt,
GNUTLS_OID_X520_COMMON_NAME, 0,
- COMMON_NAME, strlen(COMMON_NAME)));
+ hostname, strlen(hostname)));
TLSCHECK(gnutls_x509_crt_set_key(cacrt, cakey));
TLSCHECK(gnutls_x509_crt_set_serial(cacrt, &serial, sizeof(serial)));
TLSCHECK(gnutls_x509_crt_set_activation_time(cacrt, activation));
@@ -113,7 +118,7 @@ void tls_cert_generate(TALLOC_CTX *mem_ctx,
UNIT_NAME, strlen(UNIT_NAME)));
TLSCHECK(gnutls_x509_crt_set_dn_by_oid(crt,
GNUTLS_OID_X520_COMMON_NAME, 0,
- COMMON_NAME, strlen(COMMON_NAME)));
+ hostname, strlen(hostname)));
TLSCHECK(gnutls_x509_crt_set_key(crt, key));
TLSCHECK(gnutls_x509_crt_set_serial(crt, &serial, sizeof(serial)));
TLSCHECK(gnutls_x509_crt_set_activation_time(crt, activation));
diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c
index e30d5032fb..3e54d7fff0 100644
--- a/source4/libcli/ldap/ldap_client.c
+++ b/source4/libcli/ldap/ldap_client.c
@@ -438,6 +438,10 @@ static void ldap_connect_got_sock(struct composite_context *ctx,
packet_set_fde(conn->packet, conn->event.fde);
/* packet_set_serialise(conn->packet); */
+ if (conn->ldaps) {
+ packet_set_unreliable_select(conn->packet);
+ }
+
composite_done(ctx);
}