X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source4%2Flib%2Ftls%2Ftls.c;h=7bf2ff8e432a3d7db24f29d08f9c7a714caf2af7;hb=32c82fe69b588fe18674c0bda49cd7fc0f73f50a;hp=c3a6047e065aee25eca68c861e893c7759ea6d76;hpb=84b0eb6a57226b49dc835dda1fa4ed56ebe00037;p=samba.git
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index c3a6047e065..7bf2ff8e432 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -9,7 +9,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ 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,
@@ -18,63 +18,68 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see .
*/
#include "includes.h"
#include "lib/events/events.h"
#include "lib/socket/socket.h"
+#include "lib/tls/tls.h"
+#include "param/param.h"
-#if HAVE_LIBGNUTLS
-#include "gnutls/gnutls.h"
+#if ENABLE_GNUTLS
+#include
#define DH_BITS 1024
+#if defined(HAVE_GNUTLS_DATUM) && !defined(HAVE_GNUTLS_DATUM_T)
+typedef gnutls_datum gnutls_datum_t;
+#endif
+
/* hold persistent tls data */
struct tls_params {
gnutls_certificate_credentials x509_cred;
gnutls_dh_params dh_params;
- BOOL tls_enabled;
+ bool tls_enabled;
};
#endif
/* hold per connection tls data */
struct tls_context {
struct socket_context *socket;
- struct fd_event *fde;
- BOOL tls_enabled;
-#if HAVE_LIBGNUTLS
+ struct tevent_fd *fde;
+ bool tls_enabled;
+#if ENABLE_GNUTLS
gnutls_session session;
- BOOL done_handshake;
- BOOL have_first_byte;
+ bool done_handshake;
+ bool have_first_byte;
uint8_t first_byte;
- BOOL tls_detect;
+ bool tls_detect;
const char *plain_chars;
- BOOL output_pending;
+ bool output_pending;
gnutls_certificate_credentials xcred;
- BOOL interrupted;
+ bool interrupted;
#endif
};
-BOOL tls_enabled(struct socket_context *sock)
+bool tls_enabled(struct socket_context *sock)
{
struct tls_context *tls;
if (!sock) {
- return False;
+ return false;
}
if (strcmp(sock->backend_name, "tls") != 0) {
- return False;
+ return false;
}
tls = talloc_get_type(sock->private_data, struct tls_context);
if (!tls) {
- return False;
+ return false;
}
return tls->tls_enabled;
}
-#if HAVE_LIBGNUTLS
+#if ENABLE_GNUTLS
static const struct socket_ops tls_socket_ops;
@@ -112,7 +117,7 @@ static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size)
if (tls->have_first_byte) {
*(uint8_t *)buf = tls->first_byte;
- tls->have_first_byte = False;
+ tls->have_first_byte = false;
return 1;
}
@@ -121,21 +126,21 @@ static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size)
return 0;
}
if (NT_STATUS_IS_ERR(status)) {
- EVENT_FD_NOT_READABLE(tls->fde);
- EVENT_FD_NOT_WRITEABLE(tls->fde);
+ TEVENT_FD_NOT_READABLE(tls->fde);
+ TEVENT_FD_NOT_WRITEABLE(tls->fde);
errno = EBADF;
return -1;
}
if (!NT_STATUS_IS_OK(status)) {
- EVENT_FD_READABLE(tls->fde);
+ TEVENT_FD_READABLE(tls->fde);
errno = EAGAIN;
return -1;
}
if (tls->output_pending) {
- EVENT_FD_WRITEABLE(tls->fde);
+ TEVENT_FD_WRITEABLE(tls->fde);
}
if (size != nread) {
- EVENT_FD_READABLE(tls->fde);
+ TEVENT_FD_READABLE(tls->fde);
}
return nread;
}
@@ -163,11 +168,11 @@ static ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size)
return -1;
}
if (!NT_STATUS_IS_OK(status)) {
- EVENT_FD_WRITEABLE(tls->fde);
+ TEVENT_FD_WRITEABLE(tls->fde);
return -1;
}
if (size != nwritten) {
- EVENT_FD_WRITEABLE(tls->fde);
+ TEVENT_FD_WRITEABLE(tls->fde);
}
return nwritten;
}
@@ -180,7 +185,7 @@ static int tls_destructor(struct tls_context *tls)
int ret;
ret = gnutls_bye(tls->session, GNUTLS_SHUT_WR);
if (ret < 0) {
- DEBUG(0,("TLS gnutls_bye failed - %s\n", gnutls_strerror(ret)));
+ DEBUG(4,("TLS gnutls_bye failed - %s\n", gnutls_strerror(ret)));
}
return 0;
}
@@ -200,7 +205,7 @@ static NTSTATUS tls_handshake(struct tls_context *tls)
ret = gnutls_handshake(tls->session);
if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
if (gnutls_record_get_direction(tls->session) == 1) {
- EVENT_FD_WRITEABLE(tls->fde);
+ TEVENT_FD_WRITEABLE(tls->fde);
}
return STATUS_MORE_ENTRIES;
}
@@ -208,7 +213,7 @@ static NTSTATUS tls_handshake(struct tls_context *tls)
DEBUG(0,("TLS gnutls_handshake failed - %s\n", gnutls_strerror(ret)));
return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
}
- tls->done_handshake = True;
+ tls->done_handshake = true;
return NT_STATUS_OK;
}
@@ -230,7 +235,7 @@ static NTSTATUS tls_interrupted(struct tls_context *tls)
if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
return STATUS_MORE_ENTRIES;
}
- tls->interrupted = False;
+ tls->interrupted = false;
return NT_STATUS_OK;
}
@@ -269,15 +274,15 @@ static NTSTATUS tls_socket_recv(struct socket_context *sock, void *buf,
status = socket_recv(tls->socket, &tls->first_byte, 1, nread);
NT_STATUS_NOT_OK_RETURN(status);
if (*nread == 0) return NT_STATUS_OK;
- tls->tls_detect = False;
+ tls->tls_detect = false;
/* look for the first byte of a valid HTTP operation */
if (strchr(tls->plain_chars, tls->first_byte)) {
/* not a tls link */
- tls->tls_enabled = False;
+ tls->tls_enabled = false;
*(uint8_t *)buf = tls->first_byte;
return NT_STATUS_OK;
}
- tls->have_first_byte = True;
+ tls->have_first_byte = true;
}
if (!tls->tls_enabled) {
@@ -293,9 +298,9 @@ static NTSTATUS tls_socket_recv(struct socket_context *sock, void *buf,
ret = gnutls_record_recv(tls->session, buf, wantlen);
if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
if (gnutls_record_get_direction(tls->session) == 1) {
- EVENT_FD_WRITEABLE(tls->fde);
+ TEVENT_FD_WRITEABLE(tls->fde);
}
- tls->interrupted = True;
+ tls->interrupted = true;
return STATUS_MORE_ENTRIES;
}
if (ret < 0) {
@@ -329,13 +334,13 @@ static NTSTATUS tls_socket_send(struct socket_context *sock,
ret = gnutls_record_send(tls->session, blob->data, blob->length);
if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
if (gnutls_record_get_direction(tls->session) == 1) {
- EVENT_FD_WRITEABLE(tls->fde);
+ TEVENT_FD_WRITEABLE(tls->fde);
}
- tls->interrupted = True;
+ tls->interrupted = true;
return STATUS_MORE_ENTRIES;
}
if (ret < 0) {
- DEBUG(0,("gnutls_record_send of %d failed - %s\n", blob->length, gnutls_strerror(ret)));
+ DEBUG(0,("gnutls_record_send of %d failed - %s\n", (int)blob->length, gnutls_strerror(ret)));
return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
}
*sendlen = ret;
@@ -347,31 +352,38 @@ static NTSTATUS tls_socket_send(struct socket_context *sock,
/*
initialise global tls state
*/
-struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
+struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
{
struct tls_params *params;
int ret;
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
- const char *keyfile = private_path(tmp_ctx, lp_tls_keyfile());
- const char *certfile = private_path(tmp_ctx, lp_tls_certfile());
- const char *cafile = private_path(tmp_ctx, lp_tls_cafile());
- const char *crlfile = private_path(tmp_ctx, lp_tls_crlfile());
- void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *);
-
+ const char *keyfile = lpcfg_tls_keyfile(tmp_ctx, lp_ctx);
+ const char *certfile = lpcfg_tls_certfile(tmp_ctx, lp_ctx);
+ const char *cafile = lpcfg_tls_cafile(tmp_ctx, lp_ctx);
+ const char *crlfile = lpcfg_tls_crlfile(tmp_ctx, lp_ctx);
+ const char *dhpfile = lpcfg_tls_dhpfile(tmp_ctx, lp_ctx);
+ 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);
return NULL;
}
- if (!lp_tls_enabled() || keyfile == NULL || *keyfile == 0) {
- params->tls_enabled = False;
+ if (!lpcfg_tls_enabled(lp_ctx) || keyfile == NULL || *keyfile == 0) {
+ params->tls_enabled = false;
talloc_free(tmp_ctx);
return params;
}
if (!file_exist(cafile)) {
- tls_cert_generate(params, keyfile, certfile, cafile);
+ char *hostname = talloc_asprintf(mem_ctx, "%s.%s",
+ lpcfg_netbios_name(lp_ctx),
+ lpcfg_dnsdomain(lp_ctx));
+ if (hostname == NULL) {
+ goto init_failed;
+ }
+ tls_cert_generate(params, hostname, keyfile, certfile, cafile);
+ talloc_free(hostname);
}
ret = gnutls_global_init();
@@ -408,22 +420,38 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
goto init_failed;
}
+
ret = gnutls_dh_params_init(¶ms->dh_params);
if (ret < 0) goto init_failed;
- ret = gnutls_dh_params_generate2(params->dh_params, DH_BITS);
- if (ret < 0) goto init_failed;
+ if (dhpfile && *dhpfile) {
+ gnutls_datum_t dhparms;
+ size_t size;
+ dhparms.data = (uint8_t *)file_load(dhpfile, &size, 0, mem_ctx);
+ if (!dhparms.data) {
+ DEBUG(0,("Failed to read DH Parms from %s\n", dhpfile));
+ goto init_failed;
+ }
+ dhparms.size = size;
+
+ ret = gnutls_dh_params_import_pkcs3(params->dh_params, &dhparms, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) goto init_failed;
+ } else {
+ ret = gnutls_dh_params_generate2(params->dh_params, DH_BITS);
+ if (ret < 0) goto init_failed;
+ }
+
gnutls_certificate_set_dh_params(params->x509_cred, params->dh_params);
- params->tls_enabled = True;
+ params->tls_enabled = true;
talloc_free(tmp_ctx);
return params;
init_failed:
DEBUG(0,("GNUTLS failed to initialise - %s\n", gnutls_strerror(ret)));
- params->tls_enabled = False;
+ params->tls_enabled = false;
talloc_free(tmp_ctx);
return params;
}
@@ -433,8 +461,8 @@ init_failed:
setup for a new connection
*/
struct socket_context *tls_init_server(struct tls_params *params,
- struct socket_context *socket,
- struct fd_event *fde,
+ struct socket_context *socket_ctx,
+ struct tevent_fd *fde,
const char *plain_chars)
{
struct tls_context *tls;
@@ -442,9 +470,9 @@ struct socket_context *tls_init_server(struct tls_params *params,
struct socket_context *new_sock;
NTSTATUS nt_status;
- nt_status = socket_create_with_ops(socket, &tls_socket_ops, &new_sock,
+ nt_status = socket_create_with_ops(socket_ctx, &tls_socket_ops, &new_sock,
SOCKET_TYPE_STREAM,
- socket->flags | SOCKET_FLAG_ENCRYPT);
+ socket_ctx->flags | SOCKET_FLAG_ENCRYPT);
if (!NT_STATUS_IS_OK(nt_status)) {
return NULL;
}
@@ -454,16 +482,9 @@ struct socket_context *tls_init_server(struct tls_params *params,
return NULL;
}
- tls->socket = socket;
+ tls->socket = socket_ctx;
+ talloc_steal(tls, socket_ctx);
tls->fde = fde;
- if (talloc_reference(tls, fde) == NULL) {
- talloc_free(new_sock);
- return NULL;
- }
- if (talloc_reference(tls, socket) == NULL) {
- talloc_free(new_sock);
- return NULL;
- }
new_sock->private_data = tls;
@@ -484,20 +505,22 @@ struct socket_context *tls_init_server(struct tls_params *params,
gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr)tls);
gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)tls_pull);
gnutls_transport_set_push_function(tls->session, (gnutls_push_func)tls_push);
+#if GNUTLS_VERSION_MAJOR < 3
gnutls_transport_set_lowat(tls->session, 0);
+#endif
tls->plain_chars = plain_chars;
if (plain_chars) {
- tls->tls_detect = True;
+ tls->tls_detect = true;
} else {
- tls->tls_detect = False;
+ tls->tls_detect = false;
}
- tls->output_pending = False;
- tls->done_handshake = False;
- tls->have_first_byte = False;
- tls->tls_enabled = True;
- tls->interrupted = False;
+ tls->output_pending = false;
+ tls->done_handshake = false;
+ tls->have_first_byte = false;
+ tls->tls_enabled = true;
+ tls->interrupted = false;
new_sock->state = SOCKET_STATE_SERVER_CONNECTED;
@@ -513,19 +536,19 @@ failed:
/*
setup for a new client connection
*/
-struct socket_context *tls_init_client(struct socket_context *socket,
- struct fd_event *fde)
+struct socket_context *tls_init_client(struct socket_context *socket_ctx,
+ struct tevent_fd *fde,
+ const char *ca_path)
{
struct tls_context *tls;
int ret = 0;
const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
- char *cafile;
struct socket_context *new_sock;
NTSTATUS nt_status;
- nt_status = socket_create_with_ops(socket, &tls_socket_ops, &new_sock,
+ nt_status = socket_create_with_ops(socket_ctx, &tls_socket_ops, &new_sock,
SOCKET_TYPE_STREAM,
- socket->flags | SOCKET_FLAG_ENCRYPT);
+ socket_ctx->flags | SOCKET_FLAG_ENCRYPT);
if (!NT_STATUS_IS_OK(nt_status)) {
return NULL;
}
@@ -533,26 +556,16 @@ struct socket_context *tls_init_client(struct socket_context *socket,
tls = talloc(new_sock, struct tls_context);
if (tls == NULL) return NULL;
- tls->socket = socket;
+ tls->socket = socket_ctx;
+ talloc_steal(tls, socket_ctx);
tls->fde = fde;
- if (talloc_reference(tls, fde) == NULL) {
- return NULL;
- }
- if (talloc_reference(tls, socket) == NULL) {
- return NULL;
- }
- new_sock->private_data = tls;
- cafile = private_path(tls, lp_tls_cafile());
- if (!cafile || !*cafile) {
- goto failed;
- }
+ new_sock->private_data = tls;
gnutls_global_init();
gnutls_certificate_allocate_credentials(&tls->xcred);
- gnutls_certificate_set_x509_trust_file(tls->xcred, cafile, GNUTLS_X509_FMT_PEM);
- talloc_free(cafile);
+ gnutls_certificate_set_x509_trust_file(tls->xcred, ca_path, GNUTLS_X509_FMT_PEM);
TLSCHECK(gnutls_init(&tls->session, GNUTLS_CLIENT));
TLSCHECK(gnutls_set_default_priority(tls->session));
gnutls_certificate_type_set_priority(tls->session, cert_type_priority);
@@ -563,14 +576,16 @@ struct socket_context *tls_init_client(struct socket_context *socket,
gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr)tls);
gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)tls_pull);
gnutls_transport_set_push_function(tls->session, (gnutls_push_func)tls_push);
+#if GNUTLS_VERSION_MAJOR < 3
gnutls_transport_set_lowat(tls->session, 0);
- tls->tls_detect = False;
+#endif
+ tls->tls_detect = false;
- tls->output_pending = False;
- tls->done_handshake = False;
- tls->have_first_byte = False;
- tls->tls_enabled = True;
- tls->interrupted = False;
+ tls->output_pending = false;
+ tls->done_handshake = false;
+ tls->have_first_byte = false;
+ tls->tls_enabled = true;
+ tls->interrupted = false;
new_sock->state = SOCKET_STATE_CLIENT_CONNECTED;
@@ -578,7 +593,7 @@ struct socket_context *tls_init_client(struct socket_context *socket,
failed:
DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
- tls->tls_enabled = False;
+ tls->tls_enabled = false;
return new_sock;
}
@@ -627,17 +642,12 @@ static const struct socket_ops tls_socket_ops = {
.fn_get_fd = tls_socket_get_fd
};
-BOOL tls_support(struct tls_params *params)
-{
- return params->tls_enabled;
-}
-
#else
/* for systems without tls we just fail the operations, and the caller
* will retain the original socket */
-struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
+struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
{
return talloc_new(mem_ctx);
}
@@ -647,7 +657,7 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
*/
struct socket_context *tls_init_server(struct tls_params *params,
struct socket_context *socket,
- struct fd_event *fde,
+ struct tevent_fd *fde,
const char *plain_chars)
{
return NULL;
@@ -658,15 +668,11 @@ struct socket_context *tls_init_server(struct tls_params *params,
setup for a new client connection
*/
struct socket_context *tls_init_client(struct socket_context *socket,
- struct fd_event *fde)
+ struct tevent_fd *fde,
+ const char *ca_path)
{
return NULL;
}
-BOOL tls_support(struct tls_params *params)
-{
- return False;
-}
-
#endif