aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-09-06 20:27:32 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2016-09-08 16:17:02 +0200
commitcf29fd7069948668891a620facfbea6dda194496 (patch)
tree9d9ef3bf3d12d5e45bc27c6e7f75d57c705d67b1
parentff3314e45c89b436ccc7ea48361b36df39be5458 (diff)
server: Add vty interface for the TLS configuration
Make the priority configurable, load DH params, allow to specify certificates or anonymous operations. Change-Id: I8ec3c0f8e1ee2089e1b7dacd9de842260930032f
-rw-r--r--include/osmo-pcap/osmo_pcap_server.h7
-rw-r--r--include/osmo-pcap/osmo_tls.h5
-rw-r--r--src/osmo_server_main.c2
-rw-r--r--src/osmo_server_network.c8
-rw-r--r--src/osmo_server_vty.c251
-rw-r--r--src/osmo_tls.c123
6 files changed, 381 insertions, 15 deletions
diff --git a/include/osmo-pcap/osmo_pcap_server.h b/include/osmo-pcap/osmo_pcap_server.h
index 89c3df2..c1d318e 100644
--- a/include/osmo-pcap/osmo_pcap_server.h
+++ b/include/osmo-pcap/osmo_pcap_server.h
@@ -118,11 +118,18 @@ struct osmo_pcap_server {
void *zmq_publ;
/* tls base */
+ bool tls_on;
+ bool tls_allow_anon;
+ bool tls_allow_x509;
unsigned tls_log_level;
char *tls_priority;
char *tls_capath;
+ char *tls_crlfile;
char *tls_server_cert;
char *tls_server_key;
+ char *tls_dh_pkcs3;
+ gnutls_dh_params_t dh_params;
+ bool dh_params_allocated;
char *base_path;
off_t max_size;
diff --git a/include/osmo-pcap/osmo_tls.h b/include/osmo-pcap/osmo_tls.h
index 54fea4d..0637739 100644
--- a/include/osmo-pcap/osmo_tls.h
+++ b/include/osmo-pcap/osmo_tls.h
@@ -67,9 +67,14 @@ void osmo_tls_init(void);
bool osmo_tls_init_client_session(struct osmo_pcap_client *client);
+
bool osmo_tls_init_server_session(struct osmo_pcap_conn *conn, struct osmo_pcap_server *server);
void osmo_tls_release(struct osmo_tls_session *);
int osmo_tls_client_bfd_cb(struct osmo_fd *fd, unsigned int what);
size_t osmo_tls_pending(struct osmo_tls_session *session);
+void osmo_tls_server_init(struct osmo_pcap_server *server);
+
+void osmo_tls_dh_load(struct osmo_pcap_server *server);
+void osmo_tls_dh_generate(struct osmo_pcap_server *server);
diff --git a/src/osmo_server_main.c b/src/osmo_server_main.c
index 27fb519..37a9632 100644
--- a/src/osmo_server_main.c
+++ b/src/osmo_server_main.c
@@ -247,6 +247,8 @@ int main(int argc, char **argv)
exit(1);
}
+ osmo_tls_server_init(pcap_server);
+
/* attempt to connect to the remote */
if (osmo_pcap_server_listen(pcap_server) != 0) {
LOGP(DSERVER, LOGL_ERROR,
diff --git a/src/osmo_server_network.c b/src/osmo_server_network.c
index 1b7addc..a854223 100644
--- a/src/osmo_server_network.c
+++ b/src/osmo_server_network.c
@@ -491,7 +491,13 @@ static void new_connection(struct osmo_pcap_server *server,
client->state = STATE_INITIAL;
client->pend = sizeof(*client->data);
- if (client->tls_use) {
+ if (client->tls_use && !server->tls_on) {
+ LOGP(DSERVER, LOGL_NOTICE,
+ "Require TLS but not enabled on conn=%s\n",
+ client->name);
+ close_connection(client);
+ return;
+ } else if (client->tls_use) {
if (!osmo_tls_init_server_session(client, server)) {
close_connection(client);
return;
diff --git a/src/osmo_server_vty.c b/src/osmo_server_vty.c
index 14cdb89..b2919ae 100644
--- a/src/osmo_server_vty.c
+++ b/src/osmo_server_vty.c
@@ -41,6 +41,45 @@ static struct cmd_node server_node = {
1,
};
+static void write_tls(struct vty *vty, struct osmo_pcap_server *pcap_server)
+{
+ if (!pcap_server->tls_on)
+ return;
+
+ vty_out(vty, " enable tls%s", VTY_NEWLINE);
+ vty_out(vty, " tls log-level %d%s",
+ pcap_server->tls_log_level, VTY_NEWLINE);
+
+ if (pcap_server->tls_allow_anon)
+ vty_out(vty, " tls allow-auth anonymous%s", VTY_NEWLINE);
+
+ if (pcap_server->tls_allow_x509)
+ vty_out(vty, " tls allow-auth x509%s", VTY_NEWLINE);
+
+ if (pcap_server->tls_priority)
+ vty_out(vty, " tls priority %s%s",
+ pcap_server->tls_priority, VTY_NEWLINE);
+ if (pcap_server->tls_capath)
+ vty_out(vty, " tls capath %s%s", pcap_server->tls_capath, VTY_NEWLINE);
+
+ if (pcap_server->tls_crlfile)
+ vty_out(vty, " tls crlfile %s%s", pcap_server->tls_crlfile, VTY_NEWLINE);
+
+ if (pcap_server->tls_server_cert)
+ vty_out(vty, " tls server-cert %s%s",
+ pcap_server->tls_server_cert, VTY_NEWLINE);
+
+ if (pcap_server->tls_server_key)
+ vty_out(vty, " tls server-key %s%s",
+ pcap_server->tls_server_key, VTY_NEWLINE);
+
+ if (pcap_server->tls_dh_pkcs3)
+ vty_out(vty, " tls dh pkcs3 %s%s",
+ pcap_server->tls_dh_pkcs3, VTY_NEWLINE);
+ else
+ vty_out(vty, " tls dh generate%s", VTY_NEWLINE);
+}
+
static int config_write_server(struct vty *vty)
{
struct osmo_pcap_conn *conn;
@@ -59,6 +98,8 @@ static int config_write_server(struct vty *vty)
vty_out(vty, " zeromq-publisher %s %d%s",
pcap_server->zmq_ip, pcap_server->zmq_port, VTY_NEWLINE);
+ write_tls(vty, pcap_server);
+
llist_for_each_entry(conn, &pcap_server->conn, entry) {
vty_out(vty, " client %s %s%s%s%s",
conn->name, conn->remote_host,
@@ -272,6 +313,195 @@ DEFUN(cfg_no_server_zmq_ip_port,
return CMD_SUCCESS;
}
+#define TLS_STR "Transport Layer Security\n"
+
+DEFUN(cfg_enable_tls,
+ cfg_enable_tls_cmd,
+ "enable tls",
+ "Enable\n" "Transport Layer Security\n")
+{
+ pcap_server->tls_on = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_disable_tls,
+ cfg_disable_tls_cmd,
+ "disable tls",
+ "Disable\n" "Transport Layer Security\n")
+{
+ pcap_server->tls_on = false;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_log_level,
+ cfg_tls_log_level_cmd,
+ "tls log-level <0-255>",
+ TLS_STR "Log-level\n" "GNUtls debug level\n")
+{
+ pcap_server->tls_log_level = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_allow_anon,
+ cfg_tls_allow_anon_cmd,
+ "tls allow-auth anonymous",
+ TLS_STR "allow authentication\n" "for anonymous\n")
+{
+ pcap_server->tls_allow_anon = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_allow_anon,
+ cfg_no_tls_allow_anon_cmd,
+ "no tls allow-auth anonymous",
+ NO_STR TLS_STR "allow authentication\n" "for anonymous\n")
+{
+ pcap_server->tls_allow_anon = false;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_allow_x509,
+ cfg_tls_allow_x509_cmd,
+ "tls allow-auth x509",
+ TLS_STR "allow authentication\n" "for certificates\n")
+{
+ pcap_server->tls_allow_x509 = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_allow_x509,
+ cfg_no_tls_allow_x509_cmd,
+ "no tls allow-auth x509",
+ NO_STR TLS_STR "allow authentication\n" "for certificates\n")
+{
+ pcap_server->tls_allow_x509 = false;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_priority,
+ cfg_tls_priority_cmd,
+ "tls priority STR",
+ TLS_STR "Priority string for GNUtls\n" "Priority string\n")
+{
+ talloc_free(pcap_server->tls_priority);
+ pcap_server->tls_priority = talloc_strdup(pcap_server, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_priority,
+ cfg_no_tls_priority_cmd,
+ "no tls priority",
+ NO_STR TLS_STR "Priority string for GNUtls\n")
+{
+ talloc_free(pcap_server->tls_priority);
+ pcap_server->tls_priority = NULL;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_capath,
+ cfg_tls_capath_cmd,
+ "tls capath .PATH",
+ TLS_STR "Trusted root certificates\n" "Filename\n")
+{
+ talloc_free(pcap_server->tls_capath);
+ pcap_server->tls_capath = talloc_strdup(pcap_server, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_capath,
+ cfg_no_tls_capath_cmd,
+ "no tls capath",
+ NO_STR TLS_STR "Trusted root certificates\n")
+{
+ talloc_free(pcap_server->tls_capath);
+ pcap_server->tls_capath = NULL;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_crlfile,
+ cfg_tls_crlfile_cmd,
+ "tls crlfile .PATH",
+ TLS_STR "CRL file\n" "Filename\n")
+{
+ talloc_free(pcap_server->tls_crlfile);
+ pcap_server->tls_crlfile = talloc_strdup(pcap_server, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_crlfile,
+ cfg_no_tls_crlfile_cmd,
+ "no tls crlfile",
+ NO_STR TLS_STR "CRL file\n")
+{
+ talloc_free(pcap_server->tls_crlfile);
+ pcap_server->tls_crlfile = NULL;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_server_cert,
+ cfg_tls_server_cert_cmd,
+ "tls server-cert .PATH",
+ TLS_STR "Server certificate\n" "Filename\n")
+{
+ talloc_free(pcap_server->tls_server_cert);
+ pcap_server->tls_server_cert = talloc_strdup(pcap_server, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_server_cert,
+ cfg_no_tls_server_cert_cmd,
+ "no tls server-cert",
+ NO_STR TLS_STR "Server certificate\n")
+{
+ talloc_free(pcap_server->tls_server_cert);
+ pcap_server->tls_server_cert = NULL;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_server_key,
+ cfg_tls_server_key_cmd,
+ "tls server-key .PATH",
+ TLS_STR "Server private key\n" "Filename\n")
+{
+ talloc_free(pcap_server->tls_server_key);
+ pcap_server->tls_server_key = talloc_strdup(pcap_server, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_tls_server_key,
+ cfg_no_tls_server_key_cmd,
+ "no tls server-key",
+ NO_STR TLS_STR "Server private key\n")
+{
+ talloc_free(pcap_server->tls_server_key);
+ pcap_server->tls_server_key = NULL;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_dh_pkcs3,
+ cfg_tls_dh_pkcs3_cmd,
+ "tls dh pkcs .FILE",
+ TLS_STR "Diffie-Hellman Key Exchange\n" "PKCS3\n" "Filename\n")
+{
+ talloc_free(pcap_server->tls_dh_pkcs3);
+ pcap_server->tls_dh_pkcs3 = talloc_strdup(pcap_server, argv[0]);
+
+ osmo_tls_dh_load(pcap_server);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tls_dh_generate,
+ cfg_tls_dh_generate_cmd,
+ "tls dh generate",
+ TLS_STR "Diffie-Hellman Key Exchange\n" "Generate prime\n")
+{
+ talloc_free(pcap_server->tls_dh_pkcs3);
+ pcap_server->tls_dh_pkcs3 = NULL;
+
+ osmo_tls_dh_generate(pcap_server);
+ return CMD_SUCCESS;
+}
+
void vty_server_init(struct osmo_pcap_server *server)
{
install_element(CONFIG_NODE, &cfg_server_cmd);
@@ -285,6 +515,27 @@ void vty_server_init(struct osmo_pcap_server *server)
install_element(SERVER_NODE, &cfg_server_zmq_ip_port_cmd);
install_element(SERVER_NODE, &cfg_no_server_zmq_ip_port_cmd);
+ /* tls for the server */
+ install_element(SERVER_NODE, &cfg_enable_tls_cmd);
+ install_element(SERVER_NODE, &cfg_disable_tls_cmd);
+ install_element(SERVER_NODE, &cfg_tls_log_level_cmd);
+ install_element(SERVER_NODE, &cfg_tls_allow_anon_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_allow_anon_cmd);
+ install_element(SERVER_NODE, &cfg_tls_allow_x509_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_allow_x509_cmd);
+ install_element(SERVER_NODE, &cfg_tls_priority_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_priority_cmd);
+ install_element(SERVER_NODE, &cfg_tls_capath_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_capath_cmd);
+ install_element(SERVER_NODE, &cfg_tls_crlfile_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_crlfile_cmd);
+ install_element(SERVER_NODE, &cfg_tls_server_cert_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_server_cert_cmd);
+ install_element(SERVER_NODE, &cfg_tls_server_key_cmd);
+ install_element(SERVER_NODE, &cfg_no_tls_server_key_cmd);
+ install_element(SERVER_NODE, &cfg_tls_dh_generate_cmd);
+ install_element(SERVER_NODE, &cfg_tls_dh_pkcs3_cmd);
+
install_element(SERVER_NODE, &cfg_server_client_cmd);
install_element(SERVER_NODE, &cfg_server_client_store_tls_cmd);
install_element(SERVER_NODE, &cfg_server_no_client_cmd);
diff --git a/src/osmo_tls.c b/src/osmo_tls.c
index c42d242..aeecf6d 100644
--- a/src/osmo_tls.c
+++ b/src/osmo_tls.c
@@ -35,15 +35,81 @@
exit(1); \
}
-static gnutls_dh_params_t dh_params;
-static int generate_dh_params (void)
+static int generate_dh_params(struct osmo_pcap_server *server)
{
+ int rc;
unsigned int bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
GNUTLS_SEC_PARAM_HIGH);
LOGP(DTLS, LOGL_NOTICE, "Going to create DH params for %d bits\n", bits);
- gnutls_dh_params_init (&dh_params);
- return gnutls_dh_params_generate2 (dh_params, bits);
+
+ /* allocate it */
+ rc = gnutls_dh_params_init (&server->dh_params);
+ if (rc != GNUTLS_E_SUCCESS) {
+ LOGP(DTLS, LOGL_ERROR, "Failed to allocate DH params rc=%d\n", rc);
+ server->dh_params_allocated = false;
+ return rc;
+ }
+
+ /* generate and check */
+ rc = gnutls_dh_params_generate2 (server->dh_params, bits);
+ if (rc == GNUTLS_E_SUCCESS)
+ server->dh_params_allocated = true;
+ else {
+ LOGP(DTLS, LOGL_ERROR, "Failed to generate DH params rc=%d\n", rc);
+ server->dh_params_allocated = false;
+ gnutls_dh_params_deinit(server->dh_params);
+ }
+ return rc;
+}
+
+void osmo_tls_dh_load(struct osmo_pcap_server *server)
+{
+ gnutls_datum_t data;
+ int rc;
+
+ /* free it before we start */
+ if (server->dh_params_allocated) {
+ gnutls_dh_params_deinit(server->dh_params);
+ server->dh_params_allocated = false;
+ }
+ /* check if we have all data */
+ if (!server->tls_dh_pkcs3) {
+ LOGP(DTLS, LOGL_ERROR, "Can not generate missing pkcs3=%p\n",
+ server->tls_dh_pkcs3);
+ return;
+ }
+ /* initialize it again */
+ rc = gnutls_dh_params_init (&server->dh_params);
+ if (rc != GNUTLS_E_SUCCESS) {
+ LOGP(DTLS, LOGL_ERROR, "Failed to allocate DH params rc=%d\n", rc);
+ server->dh_params_allocated = false;
+ return;
+ }
+ /* load prime and generator */
+ rc = gnutls_load_file(server->tls_dh_pkcs3, &data);
+ if (rc != GNUTLS_E_SUCCESS) {
+ LOGP(DTLS, LOGL_ERROR, "Failed to load DH params from=%s rc=%d\n",
+ server->tls_dh_pkcs3, rc);
+ gnutls_dh_params_deinit(server->dh_params);
+ return;
+ }
+ rc = gnutls_dh_params_import_pkcs3(server->dh_params, &data, GNUTLS_X509_FMT_PEM);
+ gnutls_free(data.data);
+ if (rc != GNUTLS_E_SUCCESS) {
+ LOGP(DTLS, LOGL_ERROR, "Failed to import DH params rc=%d\n", rc);
+ gnutls_dh_params_deinit(server->dh_params);
+ return;
+ }
+ /* done */
+ server->dh_params_allocated = true;
+}
+
+void osmo_tls_dh_generate(struct osmo_pcap_server *server)
+{
+ if (server->dh_params_allocated)
+ gnutls_dh_params_deinit(server->dh_params);
+ generate_dh_params(server);
}
static int cert_callback(gnutls_session_t tls_session,
@@ -105,7 +171,15 @@ void osmo_tls_init(void)
rc = gnutls_global_init();
CHECK_RC(rc, "init failed");
gnutls_global_set_log_function(tls_log_func);
- rc = generate_dh_params();
+}
+
+void osmo_tls_server_init(struct osmo_pcap_server *server)
+{
+ int rc;
+
+ if (server->dh_params_allocated)
+ return;
+ rc = generate_dh_params(server);
CHECK_RC(rc, "dh params failed");
}
@@ -312,10 +386,15 @@ bool osmo_tls_init_server_session(struct osmo_pcap_conn *conn,
sess->cert_alloc = true;
/* set the credentials now */
-#warning "Anon?"
- gnutls_anon_set_server_dh_params (sess->anon_serv_cred, dh_params);
- gnutls_credentials_set(sess->session, GNUTLS_CRD_ANON, sess->anon_serv_cred);
- gnutls_credentials_set(sess->session, GNUTLS_CRD_CERTIFICATE, sess->cert_cred);
+ if (server->dh_params_allocated) {
+ gnutls_anon_set_server_dh_params(sess->anon_serv_cred, server->dh_params);
+ gnutls_certificate_set_dh_params(sess->cert_cred, server->dh_params);
+ }
+
+ if (server->tls_allow_anon)
+ gnutls_credentials_set(sess->session, GNUTLS_CRD_ANON, sess->anon_serv_cred);
+ if (server->tls_allow_x509)
+ gnutls_credentials_set(sess->session, GNUTLS_CRD_CERTIFICATE, sess->cert_cred);
if (server->tls_capath) {
rc = gnutls_certificate_set_x509_trust_file(
@@ -328,12 +407,28 @@ bool osmo_tls_init_server_session(struct osmo_pcap_conn *conn,
}
}
-#if 0
- if (load_keys(client) != 0) {
- osmo_tls_release(sess);
- return false;
+ if (server->tls_crlfile) {
+ rc = gnutls_certificate_set_x509_crl_file(
+ sess->cert_cred, server->tls_crlfile, GNUTLS_X509_FMT_PEM);
+ if (rc != GNUTLS_E_SUCCESS) {
+ LOGP(DTLS, LOGL_ERROR, "Failed to load crlfile from path=%s rc=%d\n",
+ server->tls_crlfile, rc);
+ osmo_tls_release(sess);
+ return false;
+ }
+ }
+
+ if (server->tls_server_cert && server->tls_server_key) {
+ rc = gnutls_certificate_set_x509_key_file(
+ sess->cert_cred, server->tls_server_cert, server->tls_server_key,
+ GNUTLS_X509_FMT_PEM);
+ if (rc != GNUTLS_E_SUCCESS) {
+ LOGP(DTLS, LOGL_ERROR, "Failed to load crt/key from path=%s/%s rc=%d\n",
+ server->tls_server_cert, server->tls_server_key, rc);
+ osmo_tls_release(sess);
+ return false;
+ }
}
-#endif
#warning "TODO client certificates"