Commit 16d88a1a authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

tls: drop obj and sys from vlc_tls_t

parent 1d384b96
......@@ -38,9 +38,6 @@ typedef struct vlc_tls_creds vlc_tls_creds_t;
/** TLS session */
struct vlc_tls
{
vlc_object_t *obj;
void *sys;
int (*get_fd)(struct vlc_tls *);
ssize_t (*readv)(struct vlc_tls *, struct iovec *, unsigned);
ssize_t (*writev)(struct vlc_tls *, const struct iovec *, unsigned);
......@@ -180,8 +177,8 @@ struct vlc_tls_creds
module_t *module;
void *sys;
int (*open)(vlc_tls_creds_t *, vlc_tls_t *session, vlc_tls_t *sock,
const char *host, const char *const *alpn);
vlc_tls_t *(*open)(vlc_tls_creds_t *, vlc_tls_t *sock,
const char *host, const char *const *alpn);
int (*handshake)(vlc_tls_creds_t *, vlc_tls_t *session, const char *host,
const char *service, char ** /*restrict*/ alp);
};
......
......@@ -88,17 +88,24 @@ static struct vlc_http_msg *vlc_http_tunnel_open(struct vlc_http_conn *conn,
return resp;
}
typedef struct vlc_tls_proxy
{
vlc_tls_t tls;
vlc_tls_t *sock;
} vlc_tls_proxy_t;
static int vlc_tls_ProxyGetFD(vlc_tls_t *tls)
{
struct vlc_tls *sock = tls->sys;
vlc_tls_proxy_t *proxy = (vlc_tls_proxy_t *)tls;
return vlc_tls_GetFD(sock);
return vlc_tls_GetFD(proxy->sock);
}
static ssize_t vlc_tls_ProxyRead(vlc_tls_t *tls, struct iovec *iov,
unsigned count)
{
struct vlc_tls *sock = tls->sys;
vlc_tls_proxy_t *proxy = (vlc_tls_proxy_t *)tls;
vlc_tls_t *sock = proxy->sock;
return sock->readv(sock, iov, count);
}
......@@ -106,21 +113,24 @@ static ssize_t vlc_tls_ProxyRead(vlc_tls_t *tls, struct iovec *iov,
static ssize_t vlc_tls_ProxyWrite(vlc_tls_t *tls, const struct iovec *iov,
unsigned count)
{
struct vlc_tls *sock = tls->sys;
vlc_tls_proxy_t *proxy = (vlc_tls_proxy_t *)tls;
vlc_tls_t *sock = proxy->sock;
return sock->writev(sock, iov, count);
}
static int vlc_tls_ProxyShutdown(vlc_tls_t *tls, bool duplex)
{
struct vlc_tls *sock = tls->sys;
vlc_tls_proxy_t *proxy = (vlc_tls_proxy_t *)tls;
return vlc_tls_Shutdown(sock, duplex);
return vlc_tls_Shutdown(proxy->sock, duplex);
}
static void vlc_tls_ProxyClose(vlc_tls_t *tls)
{
(void) tls;
vlc_tls_proxy_t *proxy = (vlc_tls_proxy_t *)tls;
free(proxy);
}
vlc_tls_t *vlc_https_connect_proxy(void *ctx, vlc_tls_creds_t *creds,
......@@ -164,27 +174,26 @@ vlc_tls_t *vlc_https_connect_proxy(void *ctx, vlc_tls_creds_t *creds,
assert(!ptwo); /* HTTP/2 proxy not supported yet */
struct vlc_tls *psock = malloc(sizeof (*psock));
vlc_tls_proxy_t *psock = malloc(sizeof (*psock));
if (unlikely(psock == NULL))
{
vlc_UrlClean(&url);
goto error;
}
psock->obj = VLC_OBJECT(creds);
psock->sys = sock;
psock->get_fd = vlc_tls_ProxyGetFD;
psock->readv = vlc_tls_ProxyRead;
psock->writev = vlc_tls_ProxyWrite;
psock->shutdown = vlc_tls_ProxyShutdown;
psock->close = vlc_tls_ProxyClose;
psock->p = NULL;
struct vlc_http_conn *conn = /*ptwo ? vlc_h2_conn_create(ctx, psock)
:*/ vlc_h1_conn_create(ctx, psock, false);
psock->tls.get_fd = vlc_tls_ProxyGetFD;
psock->tls.readv = vlc_tls_ProxyRead;
psock->tls.writev = vlc_tls_ProxyWrite;
psock->tls.shutdown = vlc_tls_ProxyShutdown;
psock->tls.close = vlc_tls_ProxyClose;
psock->tls.p = NULL;
psock->sock = sock;
struct vlc_http_conn *conn = /*ptwo ? vlc_h2_conn_create(ctx, &psock->tls)
:*/ vlc_h1_conn_create(ctx, &psock->tls, false);
if (unlikely(conn == NULL))
{
vlc_tls_Close(psock);
vlc_tls_Close(&psock->tls);
vlc_UrlClean(&url);
goto error;
}
......
/*****************************************************************************
* gnutls.c
*****************************************************************************
* Copyright (C) 2004-2015 Rémi Denis-Courmont
* Copyright (C) 2004-2017 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
......@@ -39,6 +39,13 @@
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
typedef struct vlc_tls_gnutls
{
vlc_tls_t tls;
gnutls_session_t session;
vlc_object_t *obj;
} vlc_tls_gnutls_t;
static int gnutls_Init (vlc_object_t *obj)
{
const char *version = gnutls_check_version ("3.3.0");
......@@ -51,7 +58,7 @@ static int gnutls_Init (vlc_object_t *obj)
return 0;
}
static int gnutls_Error(vlc_tls_t *tls, int val)
static int gnutls_Error(vlc_tls_gnutls_t *priv, int val)
{
switch (val)
{
......@@ -70,10 +77,10 @@ static int gnutls_Error(vlc_tls_t *tls, int val)
break;
default:
msg_Err(tls->obj, "%s", gnutls_strerror (val));
msg_Err(priv->obj, "%s", gnutls_strerror (val));
#ifndef NDEBUG
if (!gnutls_error_is_fatal (val))
msg_Err(tls->obj, "Error above should be handled");
msg_Err(priv->obj, "Error above should be handled");
#endif
#ifdef _WIN32
WSASetLastError (WSAECONNRESET);
......@@ -125,22 +132,23 @@ static ssize_t vlc_gnutls_writev(gnutls_transport_ptr_t ptr,
static int gnutls_GetFD(vlc_tls_t *tls)
{
gnutls_session_t session = tls->sys;
vlc_tls_t *sock = gnutls_transport_get_ptr(session);
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
vlc_tls_t *sock = gnutls_transport_get_ptr(priv->session);
return vlc_tls_GetFD(sock);
}
static ssize_t gnutls_Recv(vlc_tls_t *tls, struct iovec *iov, unsigned count)
{
gnutls_session_t session = tls->sys;
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
gnutls_session_t session = priv->session;
size_t rcvd = 0;
while (count > 0)
{
ssize_t val = gnutls_record_recv(session, iov->iov_base, iov->iov_len);
if (val < 0)
return rcvd ? (ssize_t)rcvd : gnutls_Error(tls, val);
return rcvd ? (ssize_t)rcvd : gnutls_Error(priv, val);
rcvd += val;
......@@ -157,7 +165,8 @@ static ssize_t gnutls_Recv(vlc_tls_t *tls, struct iovec *iov, unsigned count)
static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
unsigned count)
{
gnutls_session_t session = tls->sys;
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
gnutls_session_t session = priv->session;
ssize_t val;
if (!gnutls_record_check_corked(session))
......@@ -176,37 +185,44 @@ static ssize_t gnutls_Send (vlc_tls_t *tls, const struct iovec *iov,
}
val = gnutls_record_uncork(session, 0);
return (val < 0) ? gnutls_Error (tls, val) : val;
return (val < 0) ? gnutls_Error(priv, val) : val;
}
static int gnutls_Shutdown(vlc_tls_t *tls, bool duplex)
{
gnutls_session_t session = tls->sys;
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
gnutls_session_t session = priv->session;
ssize_t val;
/* Flush any pending data */
val = gnutls_record_uncork(session, 0);
if (val < 0)
return gnutls_Error(tls, val);
return gnutls_Error(priv, val);
val = gnutls_bye(session, duplex ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
if (val < 0)
return gnutls_Error(tls, val);
return gnutls_Error(priv, val);
return 0;
}
static void gnutls_Close (vlc_tls_t *tls)
{
gnutls_session_t session = tls->sys;
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
gnutls_deinit (session);
gnutls_deinit(priv->session);
free(priv);
}
static int gnutls_SessionOpen(vlc_tls_creds_t *creds, vlc_tls_t *tls, int type,
gnutls_certificate_credentials_t x509,
vlc_tls_t *sock, const char *const *alpn)
static vlc_tls_gnutls_t *gnutls_SessionOpen(vlc_tls_creds_t *creds, int type,
gnutls_certificate_credentials_t x509,
vlc_tls_t *sock,
const char *const *alpn)
{
vlc_tls_gnutls_t *priv = malloc(sizeof (*priv));
if (unlikely(priv == NULL))
return NULL;
gnutls_session_t session;
const char *errp;
int val;
......@@ -221,7 +237,8 @@ static int gnutls_SessionOpen(vlc_tls_creds_t *creds, vlc_tls_t *tls, int type,
{
msg_Err(creds, "cannot initialize TLS session: %s",
gnutls_strerror(val));
return VLC_EGENERIC;
free(priv);
return NULL;
}
char *priorities = var_InheritString(creds, "gnutls-priorities");
......@@ -272,17 +289,23 @@ static int gnutls_SessionOpen(vlc_tls_creds_t *creds, vlc_tls_t *tls, int type,
gnutls_transport_set_ptr(session, sock);
gnutls_transport_set_vec_push_function(session, vlc_gnutls_writev);
gnutls_transport_set_pull_function(session, vlc_gnutls_read);
tls->sys = session;
priv->session = session;
priv->obj = VLC_OBJECT(creds);
vlc_tls_t *tls = &priv->tls;
tls->get_fd = gnutls_GetFD;
tls->readv = gnutls_Recv;
tls->writev = gnutls_Send;
tls->shutdown = gnutls_Shutdown;
tls->close = gnutls_Close;
return VLC_SUCCESS;
return priv;
error:
gnutls_deinit (session);
return VLC_EGENERIC;
free(priv);
return NULL;
}
/**
......@@ -292,10 +315,11 @@ error:
* 1 if more would-be blocking recv is needed,
* 2 if more would-be blocking send is required.
*/
static int gnutls_ContinueHandshake(vlc_tls_creds_t *crd, vlc_tls_t *tls,
static int gnutls_ContinueHandshake(vlc_tls_creds_t *crd,
vlc_tls_gnutls_t *priv,
char **restrict alp)
{
gnutls_session_t session = tls->sys;
gnutls_session_t session = priv->session;
int val;
#ifdef _WIN32
......@@ -359,15 +383,17 @@ done:
return 0;
}
static int gnutls_ClientSessionOpen(vlc_tls_creds_t *crd, vlc_tls_t *tls,
vlc_tls_t *sk, const char *hostname,
const char *const *alpn)
static vlc_tls_t *gnutls_ClientSessionOpen(vlc_tls_creds_t *crd,
vlc_tls_t *sk, const char *hostname,
const char *const *alpn)
{
int val = gnutls_SessionOpen(crd, tls, GNUTLS_CLIENT, crd->sys, sk, alpn);
if (val != VLC_SUCCESS)
return val;
vlc_tls_gnutls_t *priv;
gnutls_session_t session = tls->sys;
priv = gnutls_SessionOpen(crd, GNUTLS_CLIENT, crd->sys, sk, alpn);
if (priv == NULL)
return NULL;
gnutls_session_t session = priv->session;
/* minimum DH prime bits */
gnutls_dh_set_prime_bits (session, 1024);
......@@ -377,19 +403,21 @@ static int gnutls_ClientSessionOpen(vlc_tls_creds_t *crd, vlc_tls_t *tls,
gnutls_server_name_set (session, GNUTLS_NAME_DNS,
hostname, strlen (hostname));
return VLC_SUCCESS;
return &priv->tls;
}
static int gnutls_ClientHandshake(vlc_tls_creds_t *creds, vlc_tls_t *tls,
const char *host, const char *service,
char **restrict alp)
{
int val = gnutls_ContinueHandshake(creds, tls, alp);
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
int val = gnutls_ContinueHandshake(creds, priv, alp);
if (val)
return val;
/* certificates chain verification */
gnutls_session_t session = tls->sys;
gnutls_session_t session = priv->session;
unsigned status;
val = gnutls_certificate_verify_peers3 (session, host, &status);
......@@ -565,23 +593,26 @@ typedef struct vlc_tls_creds_sys
/**
* Initializes a server-side TLS session.
*/
static int gnutls_ServerSessionOpen(vlc_tls_creds_t *crd, vlc_tls_t *tls,
vlc_tls_t *sock, const char *hostname,
const char *const *alpn)
static vlc_tls_t *gnutls_ServerSessionOpen(vlc_tls_creds_t *crd,
vlc_tls_t *sk, const char *hostname,
const char *const *alpn)
{
vlc_tls_creds_sys_t *sys = crd->sys;
vlc_tls_gnutls_t *priv;
assert (hostname == NULL);
return gnutls_SessionOpen(crd, tls, GNUTLS_SERVER, sys->x509_cred, sock,
alpn);
priv = gnutls_SessionOpen(crd, GNUTLS_SERVER, sys->x509_cred, sk, alpn);
return (priv != NULL) ? &priv->tls : NULL;
}
static int gnutls_ServerHandshake(vlc_tls_creds_t *crd, vlc_tls_t *tls,
const char *host, const char *service,
char **restrict alp)
{
vlc_tls_gnutls_t *priv = (vlc_tls_gnutls_t *)tls;
(void) host; (void) service;
return gnutls_ContinueHandshake(crd, tls, alp);
return gnutls_ContinueHandshake(crd, priv, alp);
}
/**
......
......@@ -134,21 +134,9 @@ static vlc_tls_t *vlc_tls_SessionCreate(vlc_tls_creds_t *crd,
const char *host,
const char *const *alpn)
{
vlc_tls_t *session = malloc(sizeof (*session));
if (unlikely(session == NULL))
return NULL;
session->obj = crd->obj.parent;
session->p = NULL;
vlc_tls_t *session;
int canc = vlc_savecancel();
if (crd->open(crd, session, sock, host, alpn) != VLC_SUCCESS)
{
free(session);
session = NULL;
}
session = crd->open(crd, sock, host, alpn);
vlc_restorecancel(canc);
return session;
}
......@@ -158,7 +146,6 @@ void vlc_tls_SessionDelete (vlc_tls_t *session)
int canc = vlc_savecancel();
session->close(session);
vlc_restorecancel(canc);
free(session);
}
static void cleanup_tls(void *data)
......@@ -337,63 +324,70 @@ error:
return NULL;
}
typedef struct vlc_tls_socket
{
struct vlc_tls tls;
int fd;
} vlc_tls_socket_t;
static int vlc_tls_SocketGetFD(vlc_tls_t *tls)
{
return (intptr_t)tls->sys;
vlc_tls_socket_t *sock = (struct vlc_tls_socket *)tls;
return sock->fd;
}
static ssize_t vlc_tls_SocketRead(vlc_tls_t *tls, struct iovec *iov,
unsigned count)
{
int fd = (intptr_t)tls->sys;
struct msghdr msg =
{
.msg_iov = iov,
.msg_iovlen = count,
};
return recvmsg(fd, &msg, 0);
return recvmsg(vlc_tls_SocketGetFD(tls), &msg, 0);
}
static ssize_t vlc_tls_SocketWrite(vlc_tls_t *tls, const struct iovec *iov,
unsigned count)
{
int fd = (intptr_t)tls->sys;
const struct msghdr msg =
{
.msg_iov = (struct iovec *)iov,
.msg_iovlen = count,
};
return sendmsg(fd, &msg, MSG_NOSIGNAL);
return sendmsg(vlc_tls_SocketGetFD(tls), &msg, MSG_NOSIGNAL);
}
static int vlc_tls_SocketShutdown(vlc_tls_t *tls, bool duplex)
{
int fd = (intptr_t)tls->sys;
return shutdown(fd, duplex ? SHUT_RDWR : SHUT_WR);
return shutdown(vlc_tls_SocketGetFD(tls), duplex ? SHUT_RDWR : SHUT_WR);
}
static void vlc_tls_SocketClose(vlc_tls_t *tls)
{
int fd = (intptr_t)tls->sys;
net_Close(fd);
net_Close(vlc_tls_SocketGetFD(tls));
free(tls);
}
vlc_tls_t *vlc_tls_SocketOpen(vlc_object_t *obj, int fd)
{
vlc_tls_t *session = malloc(sizeof (*session));
if (unlikely(session == NULL))
vlc_tls_socket_t *sock = malloc(sizeof (*sock));
if (unlikely(sock == NULL))
return NULL;
session->obj = obj;
session->sys = (void *)(intptr_t)fd;
session->get_fd = vlc_tls_SocketGetFD;
session->readv = vlc_tls_SocketRead;
session->writev = vlc_tls_SocketWrite;
session->shutdown = vlc_tls_SocketShutdown;
session->close = vlc_tls_SocketClose;
session->p = NULL;
return session;
vlc_tls_t *tls = &sock->tls;
tls->get_fd = vlc_tls_SocketGetFD;
tls->readv = vlc_tls_SocketRead;
tls->writev = vlc_tls_SocketWrite;
tls->shutdown = vlc_tls_SocketShutdown;
tls->close = vlc_tls_SocketClose;
tls->p = NULL;
sock->fd = fd;
return tls;
}
static vlc_tls_t *vlc_tls_SocketOpenAddrInfoSingle(vlc_object_t *obj,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment