summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-05-02 20:15:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:05:32 -0500
commit742c110cd67f4995639822981e8bfcb1f652f2c4 (patch)
treecd6774c861b0a968c3d22b24b5a02a0be9c54043 /source4/lib
parent49994442bbb035b2c438a33f411d6b5a8b2313df (diff)
downloadsamba-742c110cd67f4995639822981e8bfcb1f652f2c4.tar.gz
samba-742c110cd67f4995639822981e8bfcb1f652f2c4.tar.bz2
samba-742c110cd67f4995639822981e8bfcb1f652f2c4.zip
r15400: Move the TLS code behind the socket interface.
This reduces caller complexity, because the TLS code is now called just like any other socket. (A new socket context is returned by the tls_init_server and tls_init_client routines). When TLS is not available, the original socket is returned. Andrew Bartlett (This used to be commit 09b2f30dfa7a640f5187b4933204e9680be61497)
Diffstat (limited to 'source4/lib')
-rw-r--r--source4/lib/socket/socket.c6
-rw-r--r--source4/lib/socket/socket.h3
-rw-r--r--source4/lib/stream/packet.c34
-rw-r--r--source4/lib/stream/packet.h3
-rw-r--r--source4/lib/tls/tls.c219
-rw-r--r--source4/lib/tls/tls.h26
6 files changed, 177 insertions, 114 deletions
diff --git a/source4/lib/socket/socket.c b/source4/lib/socket/socket.c
index 4f7f4ef4b9..b7d4431c94 100644
--- a/source4/lib/socket/socket.c
+++ b/source4/lib/socket/socket.c
@@ -37,9 +37,9 @@ static int socket_destructor(void *ptr)
return 0;
}
-static NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
- struct socket_context **new_sock,
- enum socket_type type, uint32_t flags)
+_PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
+ struct socket_context **new_sock,
+ enum socket_type type, uint32_t flags)
{
NTSTATUS status;
diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h
index 04ae53e464..fefa999e08 100644
--- a/source4/lib/socket/socket.h
+++ b/source4/lib/socket/socket.h
@@ -117,6 +117,9 @@ struct socket_context {
/* prototypes */
+NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
+ struct socket_context **new_sock,
+ enum socket_type type, uint32_t flags);
NTSTATUS socket_create(const char *name, enum socket_type type,
struct socket_context **new_sock, uint32_t flags);
NTSTATUS socket_connect(struct socket_context *sock,
diff --git a/source4/lib/stream/packet.c b/source4/lib/stream/packet.c
index 613400226b..1da7f5706b 100644
--- a/source4/lib/stream/packet.c
+++ b/source4/lib/stream/packet.c
@@ -26,7 +26,6 @@
#include "dlinklist.h"
#include "lib/events/events.h"
#include "lib/socket/socket.h"
-#include "lib/tls/tls.h"
#include "lib/stream/packet.h"
@@ -37,7 +36,6 @@ struct packet_context {
DATA_BLOB partial;
uint32_t num_read;
uint32_t initial_read;
- struct tls_context *tls;
struct socket_context *sock;
struct event_context *ev;
size_t packet_size;
@@ -126,15 +124,7 @@ _PUBLIC_ void packet_set_full_request(struct packet_context *pc, packet_full_req
}
/*
- set a tls context to use. You must either set a tls_context or a socket_context
-*/
-_PUBLIC_ void packet_set_tls(struct packet_context *pc, struct tls_context *tls)
-{
- pc->tls = tls;
-}
-
-/*
- set a socket context to use. You must either set a tls_context or a socket_context
+ set a socket context to use. You must set a socket_context
*/
_PUBLIC_ void packet_set_socket(struct packet_context *pc, struct socket_context *sock)
{
@@ -194,7 +184,6 @@ _PUBLIC_ void packet_set_nofree(struct packet_context *pc)
*/
static void packet_error(struct packet_context *pc, NTSTATUS status)
{
- pc->tls = NULL;
pc->sock = NULL;
if (pc->error_handler) {
pc->error_handler(pc->private, status);
@@ -266,9 +255,7 @@ _PUBLIC_ void packet_recv(struct packet_context *pc)
} else if (pc->initial_read != 0) {
npending = pc->initial_read - pc->num_read;
} else {
- if (pc->tls) {
- status = tls_socket_pending(pc->tls, &npending);
- } else if (pc->sock) {
+ if (pc->sock) {
status = socket_pending(pc->sock, &npending);
} else {
status = NT_STATUS_CONNECTION_DISCONNECTED;
@@ -293,13 +280,9 @@ _PUBLIC_ void packet_recv(struct packet_context *pc)
}
}
- if (pc->tls) {
- status = tls_socket_recv(pc->tls, pc->partial.data + pc->num_read,
- npending, &nread);
- } else {
- status = socket_recv(pc->sock, pc->partial.data + pc->num_read,
- npending, &nread);
- }
+ status = socket_recv(pc->sock, pc->partial.data + pc->num_read,
+ npending, &nread);
+
if (NT_STATUS_IS_ERR(status)) {
packet_error(pc, status);
return;
@@ -452,11 +435,8 @@ _PUBLIC_ void packet_queue_run(struct packet_context *pc)
DATA_BLOB blob = data_blob_const(el->blob.data + el->nsent,
el->blob.length - el->nsent);
- if (pc->tls) {
- status = tls_socket_send(pc->tls, &blob, &nwritten);
- } else {
- status = socket_send(pc->sock, &blob, &nwritten);
- }
+ status = socket_send(pc->sock, &blob, &nwritten);
+
if (NT_STATUS_IS_ERR(status)) {
packet_error(pc, NT_STATUS_NET_WRITE_FAULT);
return;
diff --git a/source4/lib/stream/packet.h b/source4/lib/stream/packet.h
index 79d4acacd0..b7ee428186 100644
--- a/source4/lib/stream/packet.h
+++ b/source4/lib/stream/packet.h
@@ -21,8 +21,6 @@
*/
-#include "lib/tls/tls.h"
-
typedef NTSTATUS (*packet_full_request_fn_t)(void *private,
DATA_BLOB blob, size_t *packet_size);
typedef NTSTATUS (*packet_callback_fn_t)(void *private, DATA_BLOB blob);
@@ -35,7 +33,6 @@ void packet_set_callback(struct packet_context *pc, packet_callback_fn_t callbac
void packet_set_error_handler(struct packet_context *pc, packet_error_handler_fn_t handler);
void packet_set_private(struct packet_context *pc, void *private);
void packet_set_full_request(struct packet_context *pc, packet_full_request_fn_t callback);
-void packet_set_tls(struct packet_context *pc, struct tls_context *tls);
void packet_set_socket(struct packet_context *pc, struct socket_context *sock);
void packet_set_event_context(struct packet_context *pc, struct event_context *ev);
void packet_set_fde(struct packet_context *pc, struct fd_event *fde);
diff --git a/source4/lib/tls/tls.c b/source4/lib/tls/tls.c
index 5fd80e383a..2872669948 100644
--- a/source4/lib/tls/tls.c
+++ b/source4/lib/tls/tls.c
@@ -3,8 +3,10 @@
transport layer security handling code
- Copyright (C) Andrew Tridgell 2005
-
+ Copyright (C) Andrew Tridgell 2004-2005
+ Copyright (C) Stefan Metzmacher 2004
+ Copyright (C) Andrew Bartlett 2006
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -35,23 +37,61 @@ struct tls_params {
gnutls_dh_params dh_params;
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
gnutls_session session;
BOOL done_handshake;
BOOL have_first_byte;
uint8_t first_byte;
- BOOL tls_enabled;
BOOL tls_detect;
const char *plain_chars;
BOOL output_pending;
gnutls_certificate_credentials xcred;
BOOL interrupted;
+#endif
};
+BOOL tls_enabled(struct socket_context *sock)
+{
+ struct tls_context *tls;
+ if (!sock) {
+ return False;
+ }
+ if (strcmp(sock->backend_name, "tls") != 0) {
+ return False;
+ }
+ tls = talloc_get_type(sock->private_data, struct tls_context);
+ if (!tls) {
+ return False;
+ }
+ return tls->tls_enabled;
+}
+
+
+#if HAVE_LIBGNUTLS
+
+static const struct socket_ops tls_socket_ops;
+
+static NTSTATUS tls_socket_init(struct socket_context *sock)
+{
+ switch (sock->type) {
+ case SOCKET_TYPE_STREAM:
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ sock->backend_name = "tls";
+
+ return NT_STATUS_OK;
+}
+
#define TLSCHECK(call) do { \
ret = call; \
if (ret < 0) { \
@@ -61,7 +101,6 @@ struct tls_context {
} while (0)
-
/*
callback for reading from a socket
*/
@@ -199,8 +238,9 @@ static NTSTATUS tls_interrupted(struct tls_context *tls)
/*
see how many bytes are pending on the connection
*/
-NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending)
+static NTSTATUS tls_socket_pending(struct socket_context *sock, size_t *npending)
{
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
if (!tls->tls_enabled || tls->tls_detect) {
return socket_pending(tls->socket, npending);
}
@@ -219,11 +259,13 @@ NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending)
/*
receive data either by tls or normal socket_recv
*/
-NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen,
- size_t *nread)
+static NTSTATUS tls_socket_recv(struct socket_context *sock, void *buf,
+ size_t wantlen, size_t *nread)
{
int ret;
NTSTATUS status;
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
+
if (tls->tls_enabled && tls->tls_detect) {
status = socket_recv(tls->socket, &tls->first_byte, 1, nread);
NT_STATUS_NOT_OK_RETURN(status);
@@ -268,10 +310,12 @@ NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen,
/*
send data either by tls or normal socket_recv
*/
-NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t *sendlen)
+static NTSTATUS tls_socket_send(struct socket_context *sock,
+ const DATA_BLOB *blob, size_t *sendlen)
{
NTSTATUS status;
int ret;
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
if (!tls->tls_enabled) {
return socket_send(tls->socket, blob, sendlen);
@@ -389,24 +433,41 @@ init_failed:
/*
setup for a new connection
*/
-struct tls_context *tls_init_server(struct tls_params *params,
+struct socket_context *tls_init_server(struct tls_params *params,
struct socket_context *socket,
struct fd_event *fde,
- const char *plain_chars,
- BOOL tls_enable)
+ const char *plain_chars)
{
struct tls_context *tls;
int ret;
+ struct socket_context *new_sock;
+ NTSTATUS nt_status;
+
+ nt_status = socket_create_with_ops(socket, &tls_socket_ops, &new_sock,
+ SOCKET_TYPE_STREAM, 0);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return NULL;
+ }
- tls = talloc(socket, struct tls_context);
- if (tls == NULL) return NULL;
+ tls = talloc(new_sock, struct tls_context);
+ if (tls == NULL) {
+ return NULL;
+ }
tls->socket = socket;
tls->fde = fde;
+ if (talloc_reference(tls, fde) == NULL) {
+ return NULL;
+ }
+ if (talloc_reference(tls, socket) == NULL) {
+ return NULL;
+ }
+
+ new_sock->private_data = tls;
- if (!params->tls_enabled || !tls_enable) {
+ if (!params->tls_enabled) {
tls->tls_enabled = False;
- return tls;
+ return new_sock;
}
TLSCHECK(gnutls_init(&tls->session, GNUTLS_SERVER));
@@ -436,38 +497,49 @@ struct tls_context *tls_init_server(struct tls_params *params,
tls->tls_enabled = True;
tls->interrupted = False;
- return tls;
+ new_sock->state = SOCKET_STATE_SERVER_CONNECTED;
+
+ return new_sock;
failed:
DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
tls->tls_enabled = False;
params->tls_enabled = False;
- return tls;
+ return new_sock;
}
/*
setup for a new client connection
*/
-struct tls_context *tls_init_client(struct socket_context *socket,
- struct fd_event *fde,
- BOOL tls_enable)
+struct socket_context *tls_init_client(struct socket_context *socket,
+ struct fd_event *fde)
{
struct tls_context *tls;
- int ret=0;
+ 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,
+ SOCKET_TYPE_STREAM, 0);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return NULL;
+ }
- tls = talloc(socket, struct tls_context);
+ tls = talloc(new_sock, struct tls_context);
if (tls == NULL) return NULL;
tls->socket = socket;
tls->fde = fde;
- tls->tls_enabled = tls_enable;
-
- if (!tls->tls_enabled) {
- return tls;
+ 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) {
@@ -498,76 +570,101 @@ struct tls_context *tls_init_client(struct socket_context *socket,
tls->tls_enabled = True;
tls->interrupted = False;
- return tls;
+ new_sock->state = SOCKET_STATE_CLIENT_CONNECTED;
+
+ return new_sock;
failed:
DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
tls->tls_enabled = False;
- return tls;
+ return new_sock;
}
-BOOL tls_enabled(struct tls_context *tls)
+static NTSTATUS tls_socket_set_option(struct socket_context *sock, const char *option, const char *val)
{
- return tls->tls_enabled;
+ set_socket_options(socket_get_fd(sock), option);
+ return NT_STATUS_OK;
}
-BOOL tls_support(struct tls_params *params)
+static char *tls_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
{
- return params->tls_enabled;
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
+ return socket_get_peer_name(tls->socket, mem_ctx);
}
-#else
-
-/* for systems without tls we just map the tls socket calls to the
- normal socket calls */
-
-struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
+static struct socket_address *tls_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
{
- return talloc_new(mem_ctx);
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
+ return socket_get_peer_addr(tls->socket, mem_ctx);
}
-struct tls_context *tls_init_server(struct tls_params *params,
- struct socket_context *sock,
- struct fd_event *fde,
- const char *plain_chars,
- BOOL tls_enable)
+static struct socket_address *tls_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
{
- if (tls_enable && plain_chars == NULL) return NULL;
- return (struct tls_context *)sock;
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
+ return socket_get_my_addr(tls->socket, mem_ctx);
}
-struct tls_context *tls_init_client(struct socket_context *sock,
- struct fd_event *fde,
- BOOL tls_enable)
+static int tls_socket_get_fd(struct socket_context *sock)
{
- return (struct tls_context *)sock;
+ struct tls_context *tls = talloc_get_type(sock->private_data, struct tls_context);
+ return socket_get_fd(tls->socket);
}
+static const struct socket_ops tls_socket_ops = {
+ .name = "tls",
+ .fn_init = tls_socket_init,
+ .fn_recv = tls_socket_recv,
+ .fn_send = tls_socket_send,
+ .fn_pending = tls_socket_pending,
+
+ .fn_set_option = tls_socket_set_option,
-NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen,
- size_t *nread)
+ .fn_get_peer_name = tls_socket_get_peer_name,
+ .fn_get_peer_addr = tls_socket_get_peer_addr,
+ .fn_get_my_addr = tls_socket_get_my_addr,
+ .fn_get_fd = tls_socket_get_fd
+};
+
+BOOL tls_support(struct tls_params *params)
{
- return socket_recv((struct socket_context *)tls, buf, wantlen, nread);
+ return params->tls_enabled;
}
-NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t *sendlen)
+#else
+
+/* for systems without tls we just map the tls socket calls to the
+ normal socket calls */
+
+struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
{
- return socket_send((struct socket_context *)tls, blob, sendlen);
+ return talloc_new(mem_ctx);
}
-BOOL tls_enabled(struct tls_context *tls)
+/*
+ setup for a new connection
+*/
+struct socket_context *tls_init_server(struct tls_params *params,
+ struct socket_context *socket,
+ struct fd_event *fde,
+ const char *plain_chars)
{
- return False;
+ return socket;
}
-BOOL tls_support(struct tls_params *params)
+
+/*
+ setup for a new client connection
+*/
+struct socket_context *tls_init_client(struct socket_context *socket,
+ struct fd_event *fde)
{
- return False;
+ return socket;
}
-NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending)
+BOOL tls_support(struct tls_params *params)
{
- return socket_pending((struct socket_context *)tls, npending);
+ return False;
}
#endif
+
diff --git a/source4/lib/tls/tls.h b/source4/lib/tls/tls.h
index df67bad0e4..00186408e0 100644
--- a/source4/lib/tls/tls.h
+++ b/source4/lib/tls/tls.h
@@ -37,31 +37,21 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx);
tls and non-tls servers on the same port. If this is NULL then only
tls connections will be allowed
*/
-struct tls_context *tls_init_server(struct tls_params *parms,
+struct socket_context *tls_init_server(struct tls_params *parms,
struct socket_context *sock,
struct fd_event *fde,
- const char *plain_chars,
- BOOL tls_enable);
+ const char *plain_chars);
/*
call tls_init_client() on each new client connection
*/
-struct tls_context *tls_init_client(struct socket_context *sock,
- struct fd_event *fde,
- BOOL tls_enable);
-
-/*
- call these to send and receive data. They behave like socket_send() and socket_recv()
- */
-NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen,
- size_t *nread);
-NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob,
- size_t *sendlen);
+struct socket_context *tls_init_client(struct socket_context *sock,
+ struct fd_event *fde);
/*
return True if a connection used tls
*/
-BOOL tls_enabled(struct tls_context *tls);
+BOOL tls_enabled(struct socket_context *tls);
/*
@@ -69,10 +59,6 @@ BOOL tls_enabled(struct tls_context *tls);
*/
BOOL tls_support(struct tls_params *parms);
-
-/*
- ask for the number of bytes in a pending incoming packet
-*/
-NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending);
+const struct socket_ops *socket_tls_ops(enum socket_type type);
#endif