Define TLS API, update HttpClient to support optional TLS.

Also added a LibreSSL TLS implementation. Client is verified to work;
server has not been tested yet.
This commit is contained in:
Jordan Bancino 2023-03-22 00:41:21 +00:00
parent d1b4ecff48
commit 996356832e
6 changed files with 340 additions and 9 deletions

View file

@ -16,11 +16,12 @@ Milestone: v0.3.0
[x] Convert all code that deals with I/O [x] Convert all code that deals with I/O
[!] Multi-output (proof of concept) [!] Multi-output (proof of concept)
[!] Memory streams (proof of concept) [!] Memory streams (proof of concept)
[ ] TLS [~] TLS
[ ] SOCKS [ ] SOCKS
[x] Move/convert UtilStreamCopy() [x] Move/convert UtilStreamCopy()
[ ] Io man page [ ] Io man page
[ ] Stream man page [ ] Stream man page
[ ] Tls man page
[~] HTTP Client API [~] HTTP Client API
[x] Document HttpParseHeaders() [x] Document HttpParseHeaders()
[ ] HttpClient man page [ ] HttpClient man page
@ -42,6 +43,9 @@ Milestone: v0.3.0
[x] json man page [x] json man page
[ ] Update man pages for tp and send-patch [ ] Update man pages for tp and send-patch
[ ] Proper HTTP request router
- Support regex matching
[ ] Move configuration to database [ ] Move configuration to database
[ ] Initial configuration [ ] Initial configuration
[ ] If no config, create one-time use registration token that [ ] If no config, create one-time use registration token that

46
contrib/TlsImplTemplate.c Normal file
View file

@ -0,0 +1,46 @@
/*
* Telodendria TLS Implementation Template File.
*
* This file can serve as a baseline for new TLS implementations.
* Please consult the Tls(3) man page for details.
*/
#include <Tls.h>
#if TLS_IMPL == TLS_TEMPLATE /* Set your TLS_* implementation flag here */
/*
* #include statements and any implementation structures
* needed should go here.
*/
void *
TlsInitClient(int fd, const char *serverName)
{
return NULL;
}
void *
TlsInitServer(int fd, const char *crt, const char *key)
{
return NULL;
}
ssize_t
TlsRead(void *cookie, void *buf, size_t nBytes)
{
return -1;
}
ssize_t
TlsWrite(void *cookie, void *buf, size_t nBytes)
{
return -1;
}
int
TlsClose(void *cookie)
{
return -1;
}
#endif

View file

@ -36,12 +36,12 @@
#include <Http.h> #include <Http.h>
#include <Memory.h> #include <Memory.h>
#include <Util.h> #include <Util.h>
#include <Tls.h>
struct HttpClientContext struct HttpClientContext
{ {
HashMap *responseHeaders; HashMap *responseHeaders;
Stream *stream; Stream *stream;
int sd;
}; };
HttpClientContext * HttpClientContext *
@ -60,6 +60,13 @@ HttpRequest(HttpRequestMethod method, int flags, unsigned short port, char *host
return NULL; return NULL;
} }
#ifndef TLS_IMPL
if (flags & HTTP_TLS)
{
return NULL;
}
#endif
if (!port) if (!port)
{ {
if (flags & HTTP_TLS) if (flags & HTTP_TLS)
@ -76,11 +83,6 @@ HttpRequest(HttpRequestMethod method, int flags, unsigned short port, char *host
sprintf(serv, "%hu", port); sprintf(serv, "%hu", port);
} }
/* TODO: Not supported yet */
if (flags & HTTP_TLS)
{
return NULL;
}
context = Malloc(sizeof(HttpClientContext)); context = Malloc(sizeof(HttpClientContext));
if (!context) if (!context)
@ -127,8 +129,19 @@ HttpRequest(HttpRequestMethod method, int flags, unsigned short port, char *host
freeaddrinfo(res0); freeaddrinfo(res0);
context->sd = sd; #ifdef TLS_IMPL
if (flags & HTTP_TLS)
{
context->stream = TlsClientStream(sd, host);
}
else
{
context->stream = StreamFd(sd);
}
#else
context->stream = StreamFd(sd); context->stream = StreamFd(sd);
#endif
if (!context->stream) if (!context->stream)
{ {
Free(context); Free(context);
@ -185,7 +198,6 @@ HttpRequestSend(HttpClientContext * context)
} }
StreamFlush(context->stream); StreamFlush(context->stream);
shutdown(context->sd, SHUT_WR);
lineLen = UtilGetLine(&line, &lineSize, context->stream); lineLen = UtilGetLine(&line, &lineSize, context->stream);

62
src/Tls.c Normal file
View file

@ -0,0 +1,62 @@
#include <Tls.h>
#ifdef TLS_IMPL
#include <Io.h>
#include <Stream.h>
Stream *
TlsClientStream(int fd, const char *serverName)
{
Io *io;
void *cookie;
IoFunctions funcs;
cookie = TlsInitClient(fd, serverName);
if (!cookie)
{
return NULL;
}
funcs.read = TlsRead;
funcs.write = TlsWrite;
funcs.seek = NULL;
funcs.close = TlsClose;
io = IoCreate(cookie, funcs);
if (!io)
{
return NULL;
}
return StreamIo(io);
}
Stream *
TlsServerStream(int fd, const char *crt, const char *key)
{
Io *io;
void *cookie;
IoFunctions funcs;
cookie = TlsInitServer(fd, crt, key);
if (!cookie)
{
return NULL;
}
funcs.read = TlsRead;
funcs.write = TlsWrite;
funcs.seek = NULL;
funcs.close = TlsClose;
io = IoCreate(cookie, funcs);
if (!io)
{
return NULL;
}
return StreamIo(io);
}
#endif

172
src/Tls/TlsLibreSSL.c Normal file
View file

@ -0,0 +1,172 @@
#include <Tls.h>
#if TLS_IMPL == TLS_LIBRESSL
#include <Memory.h>
#include <tls.h> /* LibreSSL TLS */
typedef struct LibreSSLCookie
{
int fd;
struct tls *ctx;
struct tls *cctx;
struct tls_config *cfg;
} LibreSSLCookie;
void *
TlsInitClient(int fd, const char *serverName)
{
LibreSSLCookie *cookie = Malloc(sizeof(LibreSSLCookie));
if (!cookie)
{
return NULL;
}
cookie->ctx = tls_client();
cookie->cctx = NULL;
cookie->cfg = tls_config_new();
cookie->fd = fd;
if (!cookie->ctx || !cookie->cfg)
{
goto error;
}
if (tls_config_set_ca_file(cookie->cfg, tls_default_ca_cert_file()) == -1)
{
goto error;
}
if (tls_configure(cookie->ctx, cookie->cfg) == -1)
{
goto error;
}
if (tls_connect_socket(cookie->ctx, fd, serverName) == -1)
{
goto error;
}
return cookie;
error:
if (cookie->ctx)
{
tls_free(cookie->ctx);
}
if (cookie->cfg)
{
tls_config_free(cookie->cfg);
}
Free(cookie);
return NULL;
}
void *
TlsInitServer(int fd, const char *crt, const char *key)
{
LibreSSLCookie *cookie = Malloc(sizeof(LibreSSLCookie));
if (!cookie)
{
return NULL;
}
cookie->ctx = tls_server();
cookie->cctx = NULL;
cookie->cfg = tls_config_new();
cookie->fd = fd;
if (!cookie->ctx || !cookie->cfg)
{
goto error;
}
if (tls_config_set_cert_file(cookie->cfg, crt) == -1)
{
goto error;
}
if (tls_config_set_key_file(cookie->cfg, key) == -1)
{
goto error;
}
if (tls_configure(cookie->ctx, cookie->cfg) == -1)
{
goto error;
}
if (tls_accept_socket(cookie->ctx, &cookie->cctx, fd) == -1)
{
goto error;
}
return cookie;
error:
if (cookie->ctx)
{
tls_free(cookie->ctx);
}
if (cookie->cctx)
{
tls_free(cookie->cctx);
}
if (cookie->cfg)
{
tls_config_free(cookie->cfg);
}
Free(cookie);
return NULL;
}
ssize_t
TlsRead(void *cookie, void *buf, size_t nBytes)
{
LibreSSLCookie *tls = cookie;
return tls_read(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes);
}
ssize_t
TlsWrite(void *cookie, void *buf, size_t nBytes)
{
LibreSSLCookie *tls = cookie;
return tls_write(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes);
}
int
TlsClose(void *cookie)
{
LibreSSLCookie *tls = cookie;
int tlsRet = tls_close(tls->cctx ? tls->cctx : tls->ctx);
int sdRet;
if (tls->cctx)
{
tls_free(tls->cctx);
}
tls_free(tls->ctx);
tls_config_free(tls->cfg);
sdRet = close(tls->fd);
Free(tls);
return (tlsRet == -1 || sdRet == -1) ? -1 : 0;
}
#endif

35
src/include/Tls.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef TELODENDRIA_TLS_H
#define TELODENDRIA_TLS_H
#define TLS_LIBRESSL 1
#define TLS_MBEDTLS 2
#define TLS_OPENSSL 3
#include <Stream.h>
extern Stream *
TlsClientStream(int, const char *);
extern Stream *
TlsServerStream(int, const char *, const char *);
/*
* These are provided by individual TLS implementations.
*/
extern void *
TlsInitClient(int, const char *);
extern void *
TlsInitServer(int, const char *, const char *);
extern ssize_t
TlsRead(void *, void *, size_t);
extern ssize_t
TlsWrite(void *, void *, size_t);
extern int
TlsClose(void *);
#endif /* TELODENDRIA_TLS_H */