cleaned up TLS code which was moved to tlslib

This commit is contained in:
Nikos Mavrogiannopoulos
2013-02-08 17:46:16 +01:00
parent 8f77d18b28
commit bacf821953
8 changed files with 189 additions and 133 deletions

View File

@@ -48,11 +48,6 @@ static unsigned int terminate = 0;
static unsigned int need_maintainance = 0;
static unsigned int need_children_cleanup = 0;
static void tls_log_func(int level, const char *str)
{
syslog(LOG_DEBUG, "TLS[<%d>]: %s", level, str);
}
static
int _listen_ports(struct cfg_st* config, struct addrinfo *res, struct listen_list_st *list)
{
@@ -301,65 +296,6 @@ static void handle_alarm(int signo)
}
static void tls_audit_log_func(gnutls_session_t session, const char *str)
{
worker_st * ws;
if (session == NULL)
syslog(LOG_AUTH, "Warning: %s", str);
else {
ws = gnutls_session_get_ptr(session);
oclog(ws, LOG_ERR, "Warning: %s", str);
}
}
static int verify_certificate_cb(gnutls_session_t session)
{
unsigned int status;
int ret;
worker_st * ws;
ws = gnutls_session_get_ptr(session);
if (ws == NULL) {
syslog(LOG_ERR, "%s:%d: Could not obtain worker state.", __func__, __LINE__);
return -1;
}
/* This verification function uses the trusted CAs in the credentials
* structure. So you must have installed one or more CA certificates.
*/
ret = gnutls_certificate_verify_peers2(session, &status);
if (ret < 0) {
oclog(ws, LOG_ERR, "Error verifying client certificate");
return GNUTLS_E_CERTIFICATE_ERROR;
}
if (status != 0) {
#if GNUTLS_VERSION_NUMBER > 0x030106
type = gnutls_certificate_type_get(session);
ret =
gnutls_certificate_verification_status_print(status, type,
&out, 0);
if (ret < 0)
return GNUTLS_E_CERTIFICATE_ERROR;
oclog(ws, LOG_INFO, "Client certificate verification failed: %s", out.data);
gnutls_free(out.data);
#else
oclog(ws, LOG_INFO, "Client certificate verification failed.");
#endif
return GNUTLS_E_CERTIFICATE_ERROR;
} else {
oclog(ws, LOG_INFO, "Client certificate verification succeeded");
}
/* notify gnutls to continue handshake normally */
return 0;
}
static void drop_privileges(main_server_st* s)
{
@@ -521,13 +457,11 @@ fail:
int main(int argc, char** argv)
{
int fd, pid, e;
struct tls_st creds;
struct listen_list_st llist;
struct proc_list_st clist;
struct listener_st *ltmp;
struct proc_st *ctmp, *cpos;
struct tun_st tun;
const char* perr;
fd_set rd;
int val, n = 0, ret;
struct timeval tv;
@@ -579,59 +513,7 @@ int main(int argc, char** argv)
}
/* Initialize GnuTLS */
gnutls_global_set_audit_log_function(tls_audit_log_func);
if (config.tls_debug) {
gnutls_global_set_log_function(tls_log_func);
gnutls_global_set_log_level(9);
}
ret = gnutls_global_init();
GNUTLS_FATAL_ERR(ret);
ret = gnutls_certificate_allocate_credentials(&creds.xcred);
GNUTLS_FATAL_ERR(ret);
ret =
gnutls_certificate_set_x509_key_file(creds.xcred, config.cert,
config.key,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
fprintf(stderr, "Error setting the certificate (%s) or key (%s) files.\n",
config.cert, config.key);
exit(1);
}
if (config.cert_req != GNUTLS_CERT_IGNORE) {
if (config.ca != NULL) {
ret =
gnutls_certificate_set_x509_trust_file(creds.xcred,
config.ca,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
fprintf(stderr, "Error setting the CA (%s) file.\n",
config.ca);
exit(1);
}
printf("Processed %d CA certificate(s).\n", ret);
}
if (config.crl != NULL) {
ret =
gnutls_certificate_set_x509_crl_file(creds.xcred,
config.crl,
GNUTLS_X509_FMT_PEM);
GNUTLS_FATAL_ERR(ret);
}
gnutls_certificate_set_verify_function(creds.xcred,
verify_certificate_cb);
}
ret = gnutls_priority_init(&creds.cprio, config.priorities, &perr);
if (ret == GNUTLS_E_PARSING_ERROR)
fprintf(stderr, "Error in TLS priority string: %s\n", perr);
GNUTLS_FATAL_ERR(ret);
tls_global_init(&s);
memset(&ws, 0, sizeof(ws));
@@ -717,22 +599,25 @@ int main(int argc, char** argv)
pid = fork();
if (pid == 0) { /* child */
/* Drop privileges after this point */
drop_privileges(&s);
/* close any open descriptors before
* running the server
*/
close(cmd_fd[0]);
clear_lists(&s);
ws.config = &config;
ws.cmd_fd = cmd_fd[1];
ws.tun_fd = -1;
ws.udp_fd = -1;
ws.conn_fd = fd;
ws.creds = &creds;
ws.creds = &s.creds;
ret = tls_global_init_client(&ws);
if (ret < 0)
exit(1);
/* Drop privileges after this point */
drop_privileges(&s);
vpn_server(&ws);
exit(0);

View File

@@ -56,6 +56,9 @@ typedef struct main_server_st {
hash_db_st *tls_db;
hash_db_st *cookie_db;
/* tls credentials */
struct tls_st creds;
struct listen_list_st* llist;
struct proc_list_st* clist;
} main_server_st;

View File

@@ -79,6 +79,7 @@ tcp-port = 3333
udp-port = 3333
# The key and the certificates of the server
# The key may be a file, or any URL supported by GnuTLS (i.e., tpmkey or pkcs11)
server-cert = /path/to/cert.pem
server-key = /path/to/key.pem

View File

@@ -26,6 +26,7 @@ udp-port = 3333
keepalive = 90
# The key and the certificates of the server
# The key may be a file, or any URL supported by GnuTLS (i.e., tpmkey or pkcs11)
server-cert = ./test-cert.pem
server-key = ./test-key.pem

View File

@@ -19,6 +19,7 @@
#include <config.h>
#include <gnutls/gnutls.h>
#include <gnutls/pkcs11.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -29,10 +30,11 @@
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <tlslib.h>
#include <ccan/hash/hash.h>
#include <vpn.h>
#include <main.h>
#include <worker.h>
ssize_t tls_send(gnutls_session_t session, const void *data,
@@ -159,3 +161,162 @@ struct htable_iter iter;
return;
}
static void tls_log_func(int level, const char *str)
{
syslog(LOG_DEBUG, "TLS[<%d>]: %s", level, str);
}
static void tls_audit_log_func(gnutls_session_t session, const char *str)
{
worker_st * ws;
if (session == NULL)
syslog(LOG_AUTH, "Warning: %s", str);
else {
ws = gnutls_session_get_ptr(session);
oclog(ws, LOG_ERR, "Warning: %s", str);
}
}
static int verify_certificate_cb(gnutls_session_t session)
{
unsigned int status;
int ret;
worker_st * ws;
ws = gnutls_session_get_ptr(session);
if (ws == NULL) {
syslog(LOG_ERR, "%s:%d: Could not obtain worker state.", __func__, __LINE__);
return -1;
}
/* This verification function uses the trusted CAs in the credentials
* structure. So you must have installed one or more CA certificates.
*/
ret = gnutls_certificate_verify_peers2(session, &status);
if (ret < 0) {
oclog(ws, LOG_ERR, "Error verifying client certificate");
return GNUTLS_E_CERTIFICATE_ERROR;
}
if (status != 0) {
#if GNUTLS_VERSION_NUMBER > 0x030106
type = gnutls_certificate_type_get(session);
ret =
gnutls_certificate_verification_status_print(status, type,
&out, 0);
if (ret < 0)
return GNUTLS_E_CERTIFICATE_ERROR;
oclog(ws, LOG_INFO, "Client certificate verification failed: %s", out.data);
gnutls_free(out.data);
#else
oclog(ws, LOG_INFO, "Client certificate verification failed.");
#endif
return GNUTLS_E_CERTIFICATE_ERROR;
} else {
oclog(ws, LOG_INFO, "Client certificate verification succeeded");
}
/* notify gnutls to continue handshake normally */
return 0;
}
void tls_global_init(main_server_st* s)
{
int ret;
const char* perr;
gnutls_global_set_audit_log_function(tls_audit_log_func);
if (s->config->tls_debug) {
gnutls_global_set_log_function(tls_log_func);
gnutls_global_set_log_level(9);
}
ret = gnutls_global_init();
GNUTLS_FATAL_ERR(ret);
ret = gnutls_certificate_allocate_credentials(&s->creds.xcred);
GNUTLS_FATAL_ERR(ret);
if (s->config->key != NULL && strncmp(s->config->key, "pkcs11:", 7) != 0) {
ret =
gnutls_certificate_set_x509_key_file(s->creds.xcred, s->config->cert,
s->config->key,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
fprintf(stderr, "Error setting the certificate (%s) or key (%s) files: %s\n",
s->config->cert, s->config->key, gnutls_strerror(ret));
exit(1);
}
}
if (s->config->cert_req != GNUTLS_CERT_IGNORE) {
if (s->config->ca != NULL) {
ret =
gnutls_certificate_set_x509_trust_file(s->creds.xcred,
s->config->ca,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
fprintf(stderr, "Error setting the CA (%s) file.\n",
s->config->ca);
exit(1);
}
fprintf(stderr, "Processed %d CA certificate(s).\n", ret);
}
if (s->config->crl != NULL) {
ret =
gnutls_certificate_set_x509_crl_file(s->creds.xcred,
s->config->crl,
GNUTLS_X509_FMT_PEM);
GNUTLS_FATAL_ERR(ret);
}
gnutls_certificate_set_verify_function(s->creds.xcred,
verify_certificate_cb);
}
ret = gnutls_priority_init(&s->creds.cprio, s->config->priorities, &perr);
if (ret == GNUTLS_E_PARSING_ERROR)
fprintf(stderr, "Error in TLS priority string: %s\n", perr);
GNUTLS_FATAL_ERR(ret);
return;
}
int tls_global_init_client(worker_st* ws)
{
int ret;
/* when we have PKCS #11 keys we cannot open them and then fork(), we need
* to open them at the process they are going to be used. */
if (ws->config->key != NULL && strncmp(ws->config->key, "pkcs11:", 7) == 0) {
ret = gnutls_pkcs11_reinit();
if (ret < 0) {
oclog(ws, LOG_ERR, "Could not reinitialize PKCS #11 subsystem: %s\n",
gnutls_strerror(ret));
return -1;
}
ret =
gnutls_certificate_set_x509_key_file(ws->creds->xcred, ws->config->cert,
ws->config->key,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
oclog(ws, LOG_ERR, "Error setting the certificate (%s) or key (%s) files: %s\n",
ws->config->cert, ws->config->key, gnutls_strerror(ret));
return -1;
}
}
return 0;
}

View File

@@ -14,6 +14,9 @@ ssize_t tls_recv(gnutls_session_t session, void *data, size_t data_size);
ssize_t tls_send(gnutls_session_t session, const void *data,
size_t data_size);
void tls_global_init(struct main_server_st* s);
int tls_global_init_client(struct worker_st* ws);
ssize_t tls_send_file(gnutls_session_t session, const char *file);
#define GNUTLS_FATAL_ERR(x) \
@@ -30,6 +33,11 @@ void tls_close(gnutls_session_t session);
void tls_fatal_close(gnutls_session_t session,
gnutls_alert_description_t a);
struct tls_st {
gnutls_certificate_credentials_t xcred;
gnutls_priority_t cprio;
};
typedef struct
{
/* does not allow resumption from different address

View File

@@ -86,6 +86,10 @@ struct cfg_st {
struct vpn_st network;
};
/* generic thing to stop complaints */
struct worker_st;
struct main_server_st;
#include <tun.h>
#define MAX_USERNAME_SIZE 64

View File

@@ -11,13 +11,6 @@
#include <cookies.h>
#include <tlslib.h>
struct tls_st {
gnutls_certificate_credentials_t xcred;
gnutls_priority_t cprio;
};
typedef enum {
UP_DISABLED,
UP_SETUP,