Commit 136b6585 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

tls: add module test

parent 1617e9a8
......@@ -71,8 +71,9 @@ VLC_API vlc_tls_t *vlc_tls_ClientSessionCreate (vlc_tls_creds_t *, int fd,
const char *host, const char *service,
const char *const *alpn, char **alp);
vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *, int fd, const char *host,
const char *const *alpn);
VLC_API vlc_tls_t *vlc_tls_SessionCreate (vlc_tls_creds_t *, int fd,
const char *host,
const char *const *alpn);
/**
* Destroys a TLS session down.
......@@ -160,15 +161,16 @@ VLC_API vlc_tls_creds_t *vlc_tls_ClientCreate (vlc_object_t *);
/**
* Allocates server TLS credentials.
*
* @param cert_path required (Unicode) path to an x509 certificate,
* if NULL, anonymous key exchange will be used.
* @param key_path (UTF-8) path to the PKCS private key for the certificate,
* if NULL; cert_path will be used.
* @param cert required (Unicode) path to an x509 certificate,
* if NULL, anonymous key exchange will be used.
* @param key (UTF-8) path to the PKCS private key for the certificate,
* if NULL; cert will be used.
*
* @return TLS credentials object, or NULL on error.
*/
vlc_tls_creds_t *vlc_tls_ServerCreate (vlc_object_t *,
const char *cert, const char *key);
VLC_API vlc_tls_creds_t *vlc_tls_ServerCreate (vlc_object_t *,
const char *cert,
const char *key);
static inline int vlc_tls_SessionHandshake (vlc_tls_creds_t *crd,
vlc_tls_t *tls)
......
......@@ -428,8 +428,10 @@ text_segment_Delete
text_segment_ChainDelete
text_segment_Copy
vlc_tls_ClientCreate
vlc_tls_ServerCreate
vlc_tls_Delete
vlc_tls_ClientSessionCreate
vlc_tls_SessionCreate
vlc_tls_SessionDelete
vlc_tls_Read
vlc_tls_Write
......
......@@ -25,6 +25,7 @@ check_PROGRAMS = \
test_src_misc_bits \
test_modules_packetizer_hxxx \
test_modules_keystore \
test_modules_tls \
$(NULL)
check_SCRIPTS = \
......@@ -95,6 +96,8 @@ test_modules_packetizer_hxxx_SOURCES = modules/packetizer/hxxx.c
test_modules_packetizer_hxxx_LDADD = $(LIBVLC)
test_modules_keystore_SOURCES = modules/keystore/test.c
test_modules_keystore_LDADD = $(LIBVLCCORE) $(LIBVLC)
test_modules_tls_SOURCES = modules/misc/tls.c
test_modules_tls_LDADD = $(LIBVLCCORE) $(LIBVLC)
checkall:
$(MAKE) check_PROGRAMS="$(check_PROGRAMS) $(EXTRA_PROGRAMS)" check
......
This dummy self-signed certificate is ONLY for self-testing.
-----BEGIN CERTIFICATE-----
MIIDfDCCAmSgAwIBAgIIVpFEYRsdqg0wDQYJKoZIhvcNAQELBQAwOTESMBAGA1UE
AxMJbG9jYWxob3N0MRAwDgYDVQQLEwdUZXN0aW5nMREwDwYDVQQKEwhWaWRlb0xB
TjAiGA8yMDE2MDEwOTE3MzMyM1oYDzk5OTkxMjMxMjM1OTU5WjA5MRIwEAYDVQQD
Ewlsb2NhbGhvc3QxEDAOBgNVBAsTB1Rlc3RpbmcxETAPBgNVBAoTCFZpZGVvTEFO
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3Eo961mimhKzAm3Voqmx
kfzeWqecQ6RQDMPMUEBX0GEwAdGoQwNspraHglfELdgjshuwUUSdjqiCFZVXkQsj
JdqgpZoEPy8EDlm7Yd1q0yGB0gdNbEXithx1HgT8U5FLIjGNGP7fd9a/iSLL9e22
6DWf40md0BtWX7AdtnZImWjYQ46AUt26TY/LNw9mZ55/mJJebqba/lvMRmuCgnNh
WWIz389PbRp0PpDVfrq7khyaOwFp62BdwQLyko2lqLUI+0xJFMmp2QAFR6/LkSXQ
URvxOcf4mXKeeCFadtf8ck2AXm1EZ1GjoDGu2yHFxP+2SmMhXx2iHdOCPl4rN9hu
GwIDAQABo4GDMIGAMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIoIJbG9jYWxob3N0
ghVsb2NhbGhvc3QubG9jYWxkb21haW4wEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
VR0PAQH/BAUDAwegADAdBgNVHQ4EFgQUdwIsTYsGcjGhuO6Pd0ywkdIFnfswDQYJ
KoZIhvcNAQELBQADggEBAKcqKgkboAayyQMfjVZPgClmcMs3c7Wuk/ZtpCZyOthU
qoll0skmhSdrUOyTiE1A2oeZu/EnCjDzsxldOGcPzYP1T4A9jX99O9g3mdmdKSoQ
y4bGAMMdlf+ONm/2Esqkfw2pT1zOMqCiCHHkQWmsMkIdptbNnoobScuBiESSIqc+
63xmyUv9PWYu3RUD1KCT7bRa6rcXdqyPE8uToGKYa1Zp/dwJMyHN4Dn6Xgqbfwna
OB71+wLGP7JOBDHJaxZW/5lg0arhIBPerSHCj5l5dhlD+XC9kKKS8Lst0JbnUs4y
H7TY7+aZiDUoc6m5qHFJSTx1QvekZdXY2LoBiCjCLfU=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA3Eo961mimhKzAm3VoqmxkfzeWqecQ6RQDMPMUEBX0GEwAdGo
QwNspraHglfELdgjshuwUUSdjqiCFZVXkQsjJdqgpZoEPy8EDlm7Yd1q0yGB0gdN
bEXithx1HgT8U5FLIjGNGP7fd9a/iSLL9e226DWf40md0BtWX7AdtnZImWjYQ46A
Ut26TY/LNw9mZ55/mJJebqba/lvMRmuCgnNhWWIz389PbRp0PpDVfrq7khyaOwFp
62BdwQLyko2lqLUI+0xJFMmp2QAFR6/LkSXQURvxOcf4mXKeeCFadtf8ck2AXm1E
Z1GjoDGu2yHFxP+2SmMhXx2iHdOCPl4rN9huGwIDAQABAoIBAHsBzc+ETsJ/3Itn
r1pULT5amALBAwXWU4i9MHJDa4WFL1xkqPM6j0oMNGC5B2eeAFitE2hdyyjkuTa6
HJp2QJsbmIbAGMz7QOWOf46nJ8ZbOHWB9F6YK38LJu6rVAaJ5A1k4+foMfpl5K/7
yS47Hd5OS0iMS93v1ew6mGzRYbqfAnOSLM2Z7GxYvaVKRL8UFWow26PFzveb4irJ
LIAhxhImnCMo0G/giKtc1/8bVKWkkk1s6PxJd7pqBm7+WVk9101F4C8mAJq9zKwt
kd2XLqVDM4b4KQptsKqOtgtT03jpdl+5kicYQvv923ptlkL6a5yPf2sgM2BPOxrx
C32XmvECgYEA9tCGwX1OGFtDfjOFqD1OJe1e2sybQp8geUaeh5gf63Oy6S515NtO
pWLjZVKiHr6+06bF7gPfYMCmb9ECwqAO506y0hsad4+/6GBQ4nnSN1DKYizkIQLi
g0/GXbfO9EHEjlGbrCQEwAAjY7UWmfIX7bkr9urqSq8E4noPVllv4qMCgYEA5H0C
KRG+xJ8JXGy3QyIWnrnwVnHX3YiTfW3fU8p5P67D7vZm8P89pE/wYCHGh3uLG1t/
WCm4UpBoQdvVRkZR41YrP2HKOo59Lj7q6TV72RrVI3HLj4thBpidzdPDiklcxiNY
N4SAnsmuG/gRnb+baNkbfeffqG/jHjO+vEESdikCgYBk/HdWre2JO7ZG6c/TQZo7
HH+GKNeSD8fat1FgC5dr4EAg9riYNj9cnjSKnZ/l0ogD06YCuCTq0oiHEc7+UT0n
2WSDYUGYEAImk1olAFFJ/s2AE/wXobWKotZ4PB/6gvpofO2kJmynHqdcQZkIziyK
QQzDD+VjP29RNz4VR6zm3wKBgCUEw+bXgyrkAWZCDucHjNamlXPL+gdga1T1CivP
MBnLPN9oeIEvOVN3yCArGLk2oPELv/QOvlhSITIaZdF+7yGAAn3AYD1gfJOTigfC
rJAeMs4NT8ev80ZYT6jbWGD9RdSsQUytYRFY56aMaH5AXvN7yWJ6wNfPWOK5y3tA
p7cRAoGAeuSvIIx4SJkJnWHWYXip3Sq5c8P6d1yECkW+gdhKZoLqYlPtx0DtRUTt
SwLKHsrGaYSSzOGc+glHixKH3K7INOKn87Y1hbwlMyi7CJ0D4DaJSzvLKPN3thb5
tj3KXrg64Tbd1UxuJDNg17pLC1fbciryX9j6doe7uWeUAf2PiTw=
-----END RSA PRIVATE KEY-----
/*****************************************************************************
* tls.c: Transport Layer Security module test
*****************************************************************************
* Copyright © 2016 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
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#undef NDEBUG
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifndef SOCK_CLOEXEC
# define SOCK_CLOEXEC 0
#endif
#include <poll.h>
#include <fcntl.h>
#include <vlc_common.h>
#include <vlc_modules.h>
#include <vlc_tls.h>
#include <vlc_dialog.h>
#include "../../lib/libvlc_internal.h"
#include <vlc/vlc.h>
static int tlspair(int fds[2])
{
if (socketpair(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, fds))
return -1;
fcntl(fds[0], F_SETFL, O_NONBLOCK | fcntl(fds[0], F_GETFL));
fcntl(fds[1], F_SETFL, O_NONBLOCK | fcntl(fds[1], F_GETFL));
return 0;
}
static int question_callback(vlc_object_t *obj, const char *varname,
vlc_value_t old, vlc_value_t cur, void *data)
{
dialog_question_t *q = cur.p_address;
int *value = data;
q->answer = *value;
assert(obj == VLC_OBJECT(obj->p_libvlc));
assert(!strcmp(varname, "dialog-question"));
(void) old;
return VLC_SUCCESS;
}
static libvlc_instance_t *vlc;
static vlc_object_t *obj;
static vlc_tls_creds_t *server;
static vlc_tls_creds_t *client;
static void *tls_handshake(void *data)
{
vlc_tls_t *tls = data;
struct pollfd ufd;
int val;
ufd.fd = tls->fd;
while ((val = vlc_tls_SessionHandshake(server, tls)) > 0)
{
switch (val)
{
case 1: ufd.events = POLLIN; break;
case 2: ufd.events = POLLOUT; break;
default: vlc_assert_unreachable();
}
poll(&ufd, 1, -1);
}
return val == 0 ? tls : NULL;
}
static const char certpath[] = SRCDIR"/modules/misc/certkey.pem";
static const char *const alpn[] = { "foo", "bar", NULL };
int main(void)
{
vlc_thread_t th;
int insecurev[2];
vlc_tls_t *securev[2];
char *alp;
void *p;
int val;
int answer = 0;
setenv("VLC_PLUGIN_PATH", "../modules", 1);
vlc = libvlc_new(0, NULL);
assert(vlc != NULL);
obj = VLC_OBJECT(vlc->p_libvlc_int);
var_Create(obj, "dialog-question", VLC_VAR_ADDRESS);
var_AddCallback(obj, "dialog-question", question_callback, &answer);
dialog_Register(obj);
val = tlspair(insecurev);
assert(val == 0);
server = vlc_tls_ServerCreate(obj, SRCDIR"/does/not/exist", NULL);
assert(server == NULL);
server = vlc_tls_ServerCreate(obj, SRCDIR"/samples/empty.voc", NULL);
assert(server == NULL);
server = vlc_tls_ServerCreate(obj, certpath, SRCDIR"/does/not/exist");
assert(server == NULL);
server = vlc_tls_ServerCreate(obj, certpath, NULL);
if (server == NULL)
{
val = 77;
goto out;
}
assert(server != NULL);
client = vlc_tls_ClientCreate(obj);
assert(client != NULL);
securev[0] = vlc_tls_SessionCreate(server, insecurev[0], NULL, alpn + 1);
assert(securev[0] != NULL);
val = vlc_clone(&th, tls_handshake, securev[0], VLC_THREAD_PRIORITY_LOW);
assert(val == 0);
answer = 2;
securev[1] = vlc_tls_ClientSessionCreate(client, insecurev[1], "localhost",
"vlc-test-XXX", alpn, &alp);
assert(securev[1] != NULL);
assert(alp != NULL);
assert(!strcmp(alp, "bar"));
free(alp);
vlc_join(th, &p);
assert(p == securev[0]);
char buf[12];
val = securev[1]->recv(securev[1], buf, sizeof (buf));
assert(val == -1 && errno == EAGAIN);
val = vlc_tls_Write(securev[0], "Hello ", 6);
assert(val == 6);
val = vlc_tls_Write(securev[0], "world!", 6);
assert(val == 6);
val = vlc_tls_Read(securev[1], buf, sizeof (buf), true);
assert(val == 12);
assert(!memcmp(buf, "Hello world!", 12));
val = vlc_tls_Shutdown(securev[0], false);
assert(val == 0);
val = vlc_tls_Read(securev[1], buf, sizeof (buf), false);
assert(val == 0);
val = vlc_tls_Shutdown(securev[1], true);
assert(val == 0);
vlc_tls_SessionDelete(securev[1]);
vlc_tls_SessionDelete(securev[0]);
vlc_tls_Delete(client);
vlc_tls_Delete(server);
val = 0;
out:
dialog_Unregister(obj);
var_DelCallback(obj, "dialog-question", question_callback, &answer);
libvlc_release(vlc);
return val;
}
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