diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/ldap_server/ldap_extended.c | 1 | ||||
-rw-r--r-- | source4/ldap_server/ldap_server.c | 4 | ||||
-rw-r--r-- | source4/lib/stream/packet.c | 38 | ||||
-rw-r--r-- | source4/lib/stream/packet.h | 1 | ||||
-rw-r--r-- | source4/lib/tls/config.m4 | 1 | ||||
-rw-r--r-- | source4/lib/tls/tls.c | 10 | ||||
-rw-r--r-- | source4/lib/tls/tlscert.c | 21 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_client.c | 4 |
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); } |