mirror of
https://github.com/samba-team/samba.git
synced 2025-12-05 12:23:50 +03:00
r7769: added client support in the tls library api
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
e3e028a362
commit
71ee6a1df5
@@ -39,7 +39,6 @@ struct tls_params {
|
||||
|
||||
/* hold per connection tls data */
|
||||
struct tls_context {
|
||||
struct tls_params *params;
|
||||
struct socket_context *socket;
|
||||
struct fd_event *fde;
|
||||
gnutls_session session;
|
||||
@@ -50,8 +49,19 @@ struct tls_context {
|
||||
BOOL tls_detect;
|
||||
const char *plain_chars;
|
||||
BOOL output_pending;
|
||||
gnutls_certificate_credentials xcred;
|
||||
BOOL interrupted;
|
||||
};
|
||||
|
||||
#define TLSCHECK(call) do { \
|
||||
ret = call; \
|
||||
if (ret < 0) { \
|
||||
DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \
|
||||
goto failed; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
callback for reading from a socket
|
||||
@@ -80,7 +90,6 @@ static ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size)
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
EVENT_FD_READABLE(tls->fde);
|
||||
EVENT_FD_NOT_WRITEABLE(tls->fde);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
@@ -153,6 +162,9 @@ 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);
|
||||
}
|
||||
return STATUS_MORE_ENTRIES;
|
||||
}
|
||||
if (ret < 0) {
|
||||
@@ -163,6 +175,28 @@ static NTSTATUS tls_handshake(struct tls_context *tls)
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
possibly continue an interrupted operation
|
||||
*/
|
||||
static NTSTATUS tls_interrupted(struct tls_context *tls)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!tls->interrupted) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
if (gnutls_record_get_direction(tls->session) == 1) {
|
||||
ret = gnutls_record_send(tls->session, NULL, 0);
|
||||
} else {
|
||||
ret = gnutls_record_recv(tls->session, NULL, 0);
|
||||
}
|
||||
if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
|
||||
return STATUS_MORE_ENTRIES;
|
||||
}
|
||||
tls->interrupted = False;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
see how many bytes are pending on the connection
|
||||
*/
|
||||
@@ -173,7 +207,12 @@ NTSTATUS tls_socket_pending(struct tls_context *tls, size_t *npending)
|
||||
}
|
||||
*npending = gnutls_record_check_pending(tls->session);
|
||||
if (*npending == 0) {
|
||||
return socket_pending(tls->socket, npending);
|
||||
NTSTATUS status = socket_pending(tls->socket, npending);
|
||||
if (*npending == 0) {
|
||||
/* seems to be a gnutls bug */
|
||||
(*npending) = 100;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -208,8 +247,15 @@ NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen,
|
||||
status = tls_handshake(tls);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
status = tls_interrupted(tls);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
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);
|
||||
}
|
||||
tls->interrupted = True;
|
||||
return STATUS_MORE_ENTRIES;
|
||||
}
|
||||
if (ret < 0) {
|
||||
@@ -235,8 +281,15 @@ NTSTATUS tls_socket_send(struct tls_context *tls, const DATA_BLOB *blob, size_t
|
||||
status = tls_handshake(tls);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
status = tls_interrupted(tls);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
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);
|
||||
}
|
||||
tls->interrupted = True;
|
||||
return STATUS_MORE_ENTRIES;
|
||||
}
|
||||
if (ret < 0) {
|
||||
@@ -317,6 +370,7 @@ struct tls_params *tls_initialise(TALLOC_CTX *mem_ctx)
|
||||
gnutls_certificate_set_dh_params(params->x509_cred, params->dh_params);
|
||||
|
||||
params->tls_enabled = True;
|
||||
|
||||
return params;
|
||||
|
||||
init_failed:
|
||||
@@ -349,14 +403,6 @@ struct tls_context *tls_init_server(struct tls_params *params,
|
||||
return tls;
|
||||
}
|
||||
|
||||
#define TLSCHECK(call) do { \
|
||||
ret = call; \
|
||||
if (ret < 0) { \
|
||||
DEBUG(0,("TLS %s - %s\n", #call, gnutls_strerror(ret))); \
|
||||
goto failed; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
TLSCHECK(gnutls_init(&tls->session, GNUTLS_SERVER));
|
||||
|
||||
talloc_set_destructor(tls, tls_destructor);
|
||||
@@ -379,10 +425,10 @@ struct tls_context *tls_init_server(struct tls_params *params,
|
||||
}
|
||||
|
||||
tls->output_pending = False;
|
||||
tls->params = params;
|
||||
tls->done_handshake = False;
|
||||
tls->have_first_byte = False;
|
||||
tls->tls_enabled = True;
|
||||
tls->interrupted = False;
|
||||
|
||||
return tls;
|
||||
|
||||
@@ -393,6 +439,60 @@ failed:
|
||||
return tls;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup for a new client connection
|
||||
*/
|
||||
struct tls_context *tls_init_client(struct socket_context *socket,
|
||||
struct fd_event *fde,
|
||||
BOOL tls_enable)
|
||||
{
|
||||
struct tls_context *tls;
|
||||
int ret;
|
||||
const int cert_type_priority[] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
|
||||
tls = talloc(socket, 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;
|
||||
}
|
||||
|
||||
gnutls_global_init();
|
||||
|
||||
gnutls_certificate_allocate_credentials(&tls->xcred);
|
||||
gnutls_certificate_set_x509_trust_file(tls->xcred, lp_tls_cafile(),
|
||||
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);
|
||||
TLSCHECK(gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, tls->xcred));
|
||||
|
||||
talloc_set_destructor(tls, tls_destructor);
|
||||
|
||||
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);
|
||||
gnutls_transport_set_lowat(tls->session, 0);
|
||||
tls->tls_detect = False;
|
||||
|
||||
tls->output_pending = False;
|
||||
tls->done_handshake = False;
|
||||
tls->have_first_byte = False;
|
||||
tls->tls_enabled = True;
|
||||
tls->interrupted = False;
|
||||
|
||||
return tls;
|
||||
|
||||
failed:
|
||||
DEBUG(0,("TLS init connection failed - %s\n", gnutls_strerror(ret)));
|
||||
tls->tls_enabled = False;
|
||||
return tls;
|
||||
}
|
||||
|
||||
BOOL tls_enabled(struct tls_context *tls)
|
||||
{
|
||||
return tls->tls_enabled;
|
||||
@@ -423,6 +523,13 @@ struct tls_context *tls_init_server(struct tls_params *params,
|
||||
return (struct tls_context *)sock;
|
||||
}
|
||||
|
||||
struct tls_context *tls_init_client(struct socket_context *sock,
|
||||
struct fd_event *fde,
|
||||
BOOL tls_enable)
|
||||
{
|
||||
return (struct tls_context *)sock;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS tls_socket_recv(struct tls_context *tls, void *buf, size_t wantlen,
|
||||
size_t *nread)
|
||||
|
||||
Reference in New Issue
Block a user