mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 16:57:00 +08:00
cleaned up TLS code which was moved to tlslib
This commit is contained in:
135
src/main.c
135
src/main.c
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
163
src/tlslib.c
163
src/tlslib.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user