From 5a4ce846b7253c7edaf069bf8e86dd748c24945a Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 15 Mar 2013 17:54:36 +0100 Subject: [PATCH] The TLS private keys are kept into a privileged process. That process is called security-module (sec-mod) and communicates with the workers using a unix domain socket. --- .gitignore | 1 + NEWS | 5 +- TODO | 9 -- configure.ac | 2 +- doc/Makefile.am | 2 +- doc/design.dia | Bin 3240 -> 3836 bytes doc/sample.config | 5 +- doc/sample.passwd | 1 + src/Makefile.am | 3 +- src/common.c | 44 ++++++ src/common.h | 6 + src/config.c | 11 ++ src/main-misc.c | 63 +++++++++ src/main.c | 24 ++-- src/main.h | 6 + src/ocserv-args.c | 2 +- src/ocserv-args.def | 10 +- src/ocserv-args.h | 2 +- src/sec-mod.c | 264 +++++++++++++++++++++++++++++++++++ src/sec-mod.h | 5 + src/tlslib.c | 326 +++++++++++++++++++++++--------------------- src/tlslib.h | 5 - src/vpn.h | 4 +- src/worker-tun.c | 21 --- src/worker-vpn.c | 3 +- 25 files changed, 612 insertions(+), 212 deletions(-) create mode 100644 doc/sample.passwd create mode 100644 src/common.c create mode 100644 src/common.h create mode 100644 src/sec-mod.c create mode 100644 src/sec-mod.h diff --git a/.gitignore b/.gitignore index 08229753..ea349bc3 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ gl/stdlib.h gl/sys/stat.h gl/sys/time.h gl/sys/types.h +src/ocpasswd diff --git a/NEWS b/NEWS index ecc29837..b5e83bcd 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -* Version 0.0.3 (unreleased) +* Version 0.1.0 (unreleased) - Corrected issue with ocsp-response configuration field. - Added ability to specify multiple certificate and key pairs. @@ -6,6 +6,9 @@ - Added the "plain" authentication option, which allows a simple password file format. The ocpasswd tool can be used to generate entries for this file. +- The private key operations are performed on a special process to + prevent loss of the private key in case of compromise of a worker + process. * Version 0.0.2 (released 2013-03-05) diff --git a/TODO b/TODO index 47c30a6a..eaf26f44 100644 --- a/TODO +++ b/TODO @@ -10,15 +10,6 @@ * Handle users being in multiple groups. -* Keep the TLS key and certificates into the privileged process and use IPC - for operations. This currently cannot be done, because the main process is - the one that spawns the workers and there is no sane way to make the key - (or any temporal value depending on it) disappear from the main process - memory. Moreover, such a move will make the privileged process a bottleneck - on a multi-core system. If that functionality is desirable, it can be - obtained using a software security module (e.g. pkcs11 softoken), an HSM - or TPM. - * Certificate authentication to the main process. Possibly that is just wishful thinking. To verify the TLS client certificate verify signature one needs instead of the signature, the contents of all the handshake messages, diff --git a/configure.ac b/configure.ac index f0778976..ee508909 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,7 @@ fi AC_CHECK_SIZEOF([unsigned long]) AC_C_BIGENDIAN -PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.0.28]) +PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.1.9]) AC_CHECK_LIB(gnutls, gnutls_pkcs11_reinit, [ AC_DEFINE([HAVE_PKCS11], [], [PKCS11 detected in gnutls]) ]) diff --git a/doc/Makefile.am b/doc/Makefile.am index c6f05380..6f72d98d 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = design.dia sample.config scripts/ocserv-script +EXTRA_DIST = design.dia sample.config scripts/ocserv-script sample.passwd dist_man_MANS = ocserv.8 diff --git a/doc/design.dia b/doc/design.dia index bdc3614c112f1168263d3c311ac457638000f734..f95a4658b8564cdba662bd157d5adc00e8d6330a 100644 GIT binary patch literal 3836 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 a?p6AJP<+vUr)e;IKlne+<$d4GqyPXQD_@@g diff --git a/doc/sample.config b/doc/sample.config index 835a7860..7a5e6946 100644 --- a/doc/sample.config +++ b/doc/sample.config @@ -2,7 +2,7 @@ # all should succeed. # Options: certificate, pam. #auth = "certificate" -auth = "plain[./passwd]" +auth = "plain[./sample.passwd]" #auth = "pam" # A banner to be displayed on clients @@ -114,6 +114,9 @@ use-utmp = true # PID file pid-file = /var/run/ocserv.pid +# socket file +socket-file = /var/run/ocserv-socket + run-as-user = nobody run-as-group = nogroup diff --git a/doc/sample.passwd b/doc/sample.passwd new file mode 100644 index 00000000..6e6faf17 --- /dev/null +++ b/doc/sample.passwd @@ -0,0 +1 @@ +test:tost:$5$i6SNmLDCgBNjyJ7q$SZ4bVJb7I/DLgXo3txHBVohRFBjOtdbxGQZp.DOnrA. diff --git a/src/Makefile.am b/src/Makefile.am index 14336442..84682565 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,7 +17,8 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \ vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \ config.c pam.c pam.h worker-resume.c worker.h main-resume.c main.h \ main-user.c cookies-gdbm.c cookies-hash.c worker-misc.c setproctitle.h \ - setproctitle.c worker-privs.c plain.c plain.h \ + setproctitle.c worker-privs.c plain.c plain.h common.h common.c \ + sec-mod.c sec-mod.h \ $(CCAN_SOURCES) ocserv_SOURCES += ocserv-args.def ocserv-args.c ocserv-args.h diff --git a/src/common.c b/src/common.c new file mode 100644 index 00000000..c16e713c --- /dev/null +++ b/src/common.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +ssize_t force_write(int sockfd, const void *buf, size_t len) +{ +int left = len; +int ret; +const uint8_t * p = buf; + + while(left > 0) { + ret = write(sockfd, p, left); + if (ret == -1) { + if (errno != EAGAIN && errno != EINTR) + return ret; + } + + if (ret > 0) { + left -= ret; + p += ret; + } + } + + return len; +} diff --git a/src/common.h b/src/common.h new file mode 100644 index 00000000..93830353 --- /dev/null +++ b/src/common.h @@ -0,0 +1,6 @@ +#ifndef COMMON_H +# define COMMON_H +ssize_t force_write(int sockfd, const void *buf, size_t len); + +#endif + diff --git a/src/config.c b/src/config.c index d56f1fb0..97466f37 100644 --- a/src/config.c +++ b/src/config.c @@ -179,6 +179,8 @@ unsigned j; if (pid_file == NULL) READ_STRING("pid-file", pid_file, 0); + READ_STRING("socket-file", config->socket_file_prefix, 1); + READ_STRING("banner", config->banner, 0); READ_TF("always-require-cert", config->force_cert_auth, 0, 1); READ_TF("use-utmp", config->use_utmp, 0, 1); @@ -353,6 +355,7 @@ unsigned i; DEL(config->xml_config_hash); DEL(config->cert_hash); #endif + DEL(config->socket_file_prefix); DEL(config->plain_passwd); DEL(config->ocsp_response); DEL(config->banner); @@ -411,3 +414,11 @@ FILE* fp; fprintf(fp, "%u", (unsigned)getpid()); fclose(fp); } + +void remove_pid_file(void) +{ + if (pid_file==NULL) + return; + + remove(pid_file); +} diff --git a/src/main-misc.c b/src/main-misc.c index 5b29e869..f8bc5cec 100644 --- a/src/main-misc.c +++ b/src/main-misc.c @@ -34,7 +34,11 @@ #include #include #include +#include +#include #include "ipc.h" +#include "setproctitle.h" +#include #include #include @@ -372,3 +376,62 @@ struct banned_st *btmp; list_add(&s->ban_list.head, &(btmp->list)); } + +void run_sec_mod(main_server_st * s) +{ +struct sockaddr_un sa; +int sd, e, ret; +pid_t pid; + + sa.sun_family = AF_UNIX; + + /* make socket name */ + snprintf(s->socket_file, sizeof(s->socket_file), "%s.%u", s->config->socket_file_prefix, (unsigned)getpid()); + snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", s->socket_file); + + remove(s->socket_file); + + sd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sd == -1) { + e = errno; + mslog(s, NULL, LOG_ERR, "could not create socket '%s': %s", s->socket_file, strerror(e)); + exit(1); + } + + ret = bind(sd, (struct sockaddr *)&sa, sizeof(sa)); + if (ret == -1) { + e = errno; + mslog(s, NULL, LOG_ERR, "could not bind socket '%s': %s", s->socket_file, strerror(e)); + exit(1); + } + + ret = chown(sa.sun_path, s->config->uid, s->config->gid); + if (ret == -1) { + e = errno; + mslog(s, NULL, LOG_ERR, "could not chown socket '%s': %s", s->socket_file, strerror(e)); + } + + ret = listen(sd, 1024); + if (ret == -1) { + e = errno; + mslog(s, NULL, LOG_ERR, "could not listen to socket '%s': %s", s->socket_file, strerror(e)); + exit(1); + } + set_cloexec_flag (sd, 1); + + pid = fork(); + if (pid == 0) { /* child */ + setproctitle(PACKAGE_NAME"-secmod"); + + sec_mod_server(s->config, sd); + exit(0); + } else if (pid > 0) { /* parent */ + close(sd); + s->sec_mod_pid = pid; + } else { + e = errno; + mslog(s, NULL, LOG_ERR, "error in fork(): %s", strerror(e)); + exit(1); + } + +} diff --git a/src/main.c b/src/main.c index ed31c134..fb710143 100644 --- a/src/main.c +++ b/src/main.c @@ -313,6 +313,11 @@ struct script_wait_st *stmp, *spos; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { estatus = WEXITSTATUS(status); + + if (pid == s->sec_mod_pid) { + mslog(s, NULL, LOG_ERR, "ocserv-secmod died unexpectedly"); + terminate = 1; + } /* check if someone was waiting for that pid */ list_for_each_safe(&s->script_list.head, stmp, spos, list) { @@ -425,6 +430,8 @@ static void kill_children(main_server_st* s) { struct proc_st *ctmp; + /* kill the security module server */ + kill(s->sec_mod_pid, SIGTERM); list_for_each(&s->clist.head, ctmp, list) { if (ctmp->pid != -1) { kill(ctmp->pid, SIGTERM); @@ -536,7 +543,6 @@ static void check_other_work(main_server_st *s) if (reload_conf != 0) { mslog(s, NULL, LOG_INFO, "HUP signal was received; reloading configuration"); reload_cfg_file(s->config); - tls_global_init_certs(s); reload_conf = 0; } @@ -544,6 +550,8 @@ static void check_other_work(main_server_st *s) mslog(s, NULL, LOG_DEBUG, "termination signal received; waiting for children to die"); kill_children(s); closelog(); + remove(s->socket_file); + remove_pid_file(); while (waitpid(-1, NULL, 0) > 0); exit(0); } @@ -656,9 +664,6 @@ int main(int argc, char** argv) #endif memset(&ws, 0, sizeof(ws)); - /* Initialize GnuTLS */ - tls_global_init_certs(&s); - if (config.foreground == 0) { if (daemon(0, 0) == -1) { e = errno; @@ -668,6 +673,11 @@ int main(int argc, char** argv) } write_pid_file(); + + run_sec_mod(&s); + + /* Initialize certificates */ + tls_global_init_certs(&s); alarm(MAINTAINANCE_TIME(&s)); @@ -726,7 +736,7 @@ int main(int argc, char** argv) continue; } set_cloexec_flag (fd, 1); - + /* Check if the client is on the banned list */ ret = check_if_banned(&s, &ws.remote_addr, ws.remote_addr_len); if (ret < 0) { @@ -774,10 +784,6 @@ int main(int argc, char** argv) ws.conn_fd = fd; ws.creds = &s.creds; - ret = tls_global_init_client(&ws); - if (ret < 0) - exit(1); - /* Drop privileges after this point */ drop_privileges(&s); diff --git a/src/main.h b/src/main.h index 6e6c3a5f..ed8caf30 100644 --- a/src/main.h +++ b/src/main.h @@ -15,6 +15,7 @@ int cmd_parser (int argc, char **argv, struct cfg_st* config); void reload_cfg_file(struct cfg_st* config); void write_pid_file(void); +void remove_pid_file(void); /* set to 1 to start cleaning up cookies, sessions etc. */ extern unsigned int need_maintainance; @@ -102,6 +103,9 @@ typedef struct main_server_st { struct script_list_st script_list; struct ban_list_st ban_list; + char socket_file[_POSIX_PATH_MAX]; + pid_t sec_mod_pid; + unsigned active_clients; } main_server_st; @@ -155,4 +159,6 @@ int check_if_banned(main_server_st* s, struct sockaddr_storage *addr, socklen_t int handle_script_exit(main_server_st *s, struct proc_st* proc, int code); +void run_sec_mod(main_server_st * s); + #endif diff --git a/src/ocserv-args.c b/src/ocserv-args.c index 300ed854..69859046 100644 --- a/src/ocserv-args.c +++ b/src/ocserv-args.c @@ -2,7 +2,7 @@ * * DO NOT EDIT THIS FILE (ocserv-args.c) * - * It has been AutoGen-ed March 14, 2013 at 01:42:30 PM by AutoGen 5.16 + * It has been AutoGen-ed March 15, 2013 at 04:54:18 PM by AutoGen 5.16 * From the definitions ocserv-args.def * and the template file options * diff --git a/src/ocserv-args.def b/src/ocserv-args.def index 780892ab..fa6f6931 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -203,6 +203,9 @@ use-utmp = true # PID file pid-file = /var/run/ocserv.pid +# socket file used for IPC, will be appended with .PID +socket-file = /var/run/ocserv-socket + # The user the worker processes will be run as. run-as-user = nobody run-as-group = nogroup @@ -345,10 +348,9 @@ doc-section = { ds-format = 'texi'; ds-text = <<-_EOT_ Note that while this server utilizes privilege separation for password -authentication, this does not apply for TLS and client certificate authentication. -This has the advantage of spreading TLS calculations to multiple workers (i.e. cores) -if available, but at the cost of each worker having a copy of the server's -private key. +authentication, this does not apply for TLS client certificate authentication. +That is because the worker has no easy way to prove to the main server that +it performed the certificate verification. _EOT_; }; diff --git a/src/ocserv-args.h b/src/ocserv-args.h index a5fcf1ac..16e58da2 100644 --- a/src/ocserv-args.h +++ b/src/ocserv-args.h @@ -2,7 +2,7 @@ * * DO NOT EDIT THIS FILE (ocserv-args.h) * - * It has been AutoGen-ed March 14, 2013 at 01:42:30 PM by AutoGen 5.16 + * It has been AutoGen-ed March 15, 2013 at 04:54:18 PM by AutoGen 5.16 * From the definitions ocserv-args.def * and the template file options * diff --git a/src/sec-mod.c b/src/sec-mod.c new file mode 100644 index 00000000..de38656b --- /dev/null +++ b/src/sec-mod.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAX_PIN_SIZE GNUTLS_PKCS11_MAX_PIN_LEN + +struct pin_st { + char pin[MAX_PIN_SIZE]; + char srk_pin[MAX_PIN_SIZE]; +}; + +static +int pin_callback (void *user, int attempt, const char *token_url, + const char *token_label, unsigned int flags, char *pin, + size_t pin_max) +{ +struct pin_st * ps = user; +int srk = 0; +const char* p; +unsigned len; + + if (flags & GNUTLS_PIN_FINAL_TRY) { + syslog(LOG_ERR, "PIN callback: final try before locking; not attempting to unlock"); + return -1; + } + + if (flags & GNUTLS_PIN_WRONG) { + syslog(LOG_ERR, "PIN callback: wrong PIN was entered for '%s' (%s)", token_label, token_url); + return -1; + } + + if (ps->pin[0] == 0) { + syslog(LOG_ERR, "PIN required for '%s' but pin-file was not set", token_label); + return -1; + } + + if (strcmp(token_url, "SRK") == 0 || strcmp(token_label, "SRK") == 0) { + srk = 1; + p = ps->srk_pin; + } else { + p = ps->pin; + } + + if (srk != 0 && ps->srk_pin[0] == 0) { + syslog(LOG_ERR, "PIN required for '%s' but srk-pin-file was not set", token_label); + return -1; + } + + len = strlen(p); + if (len > pin_max-1) { + syslog(LOG_ERR, "Too long PIN (%u chars)", len); + return -1; + } + + memcpy(pin, p, len); + pin[len] = 0; + + return 0; +} + +static +int load_pins(struct cfg_st* config, struct pin_st* s) +{ +int fd, ret; + + s->srk_pin[0] = 0; + s->pin[0] = 0; + + if (config->srk_pin_file != NULL) { + fd = open(config->srk_pin_file, O_RDONLY); + if (fd < 0) { + syslog(LOG_ERR, "could not open SRK PIN file '%s'", config->srk_pin_file); + return -1; + } + + ret = read(fd, s->srk_pin, sizeof(s->srk_pin)); + close(fd); + if (ret <= 1) { + syslog(LOG_ERR, "could not read from PIN file '%s'", config->srk_pin_file); + return -1; + } + + if (s->srk_pin[ret-1] == '\n' || s->srk_pin[ret-1] == '\r') + s->srk_pin[ret-1] = 0; + s->srk_pin[ret] = 0; + } + + if (config->pin_file != NULL) { + fd = open(config->pin_file, O_RDONLY); + if (fd < 0) { + syslog(LOG_ERR, "could not open PIN file '%s'", config->pin_file); + return -1; + } + + ret = read(fd, s->pin, sizeof(s->pin)); + close(fd); + if (ret <= 1) { + syslog(LOG_ERR, "could not read from PIN file '%s'", config->pin_file); + return -1; + } + + if (s->pin[ret-1] == '\n' || s->pin[ret-1] == '\r') + s->pin[ret-1] = 0; + s->pin[ret] = 0; + } + + return 0; +} + +void +sec_mod_server(struct cfg_st* config, int sd) +{ +struct sockaddr_un sa; +socklen_t sa_len; +int cfd, ret, e; +unsigned i, buffer_size, type; +gnutls_privkey_t *key; +uint8_t *buffer; +unsigned key_size = config->key_size; +struct pin_st pins; +gnutls_datum_t data, out; +uint16_t length; + + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + + buffer_size = 8*1024; + buffer = malloc(buffer_size); + if (buffer == NULL) { + syslog(LOG_ERR, "error in memory allocation"); + exit(1); + } + + ret = load_pins(config, &pins); + if (ret < 0) { + syslog(LOG_ERR, "error loading PIN files"); + exit(1); + } + + key = malloc(sizeof(*key)*config->key_size); + if (key == NULL) { + syslog(LOG_ERR, "error in memory allocation"); + exit(1); + } + + /* read private keys */ + for (i=0;ikey[i]) != 0) { + gnutls_privkey_set_pin_function (key[i], pin_callback, &pins); + ret = gnutls_privkey_import_url(key[i], config->key[i], 0); + GNUTLS_FATAL_ERR(ret); + } else { + ret = gnutls_load_file(config->key[i], &data); + if (ret < 0) { + syslog(LOG_ERR, "error loading file '%s'", config->key[i]); + GNUTLS_FATAL_ERR(ret); + } + + ret = gnutls_privkey_import_x509_raw(key[i], &data, GNUTLS_X509_FMT_PEM, NULL, 0); + GNUTLS_FATAL_ERR(ret); + + gnutls_free(data.data); + } + } + + for (;;) { + sa_len = sizeof(sa); + cfd = accept(sd, (struct sockaddr *)&sa, &sa_len); + if (cfd == -1) { + e = errno; + syslog(LOG_ERR, "error accepting sec-mod connection: %s", strerror(e)); + continue; + } + + /* read request */ + ret = recv(cfd, buffer, buffer_size, 0); + if (ret <= 2) { + e = errno; + syslog(LOG_ERR, "error receiving sec-mod data: %s", strerror(e)); + goto cont; + } + + /* calculate */ + i = buffer[0]; + type = buffer[1]; + + if (i >= key_size) { + syslog(LOG_ERR, "sec-mod received out-of-bounds key index"); + goto cont; + } + + data.data = &buffer[2]; + data.size = ret - 2; + +#if GNUTLS_VERSION_NUMBER >= 0x03010a + if (type == 'S') { + ret = gnutls_privkey_sign_raw_data(key[i], 0, &data, &out); + } else +#endif + if (type == 'D') { + ret = gnutls_privkey_decrypt_data(key[i], 0, &data, &out); + } else { + syslog(LOG_ERR, "unknown type 0x%.2x", type); + goto cont; + } + + if (ret < 0) { + syslog(LOG_ERR, "sec-mod error in crypto operation: %s", gnutls_strerror(ret)); + goto cont; + } + + /* write reply */ + length = out.size; + force_write(cfd, &length, 2); + force_write(cfd, out.data, out.size); + gnutls_free(out.data); +cont: + close(cfd); + } +} + diff --git a/src/sec-mod.h b/src/sec-mod.h new file mode 100644 index 00000000..b1fb7e3b --- /dev/null +++ b/src/sec-mod.h @@ -0,0 +1,5 @@ +#ifndef SEC_MOD_H + +void sec_mod_server(struct cfg_st* config, int sd); + +#endif diff --git a/src/tlslib.c b/src/tlslib.c index 1cc075eb..ac276fac 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include ssize_t tls_send(gnutls_session_t session, const void *data, @@ -241,103 +243,6 @@ fail: } -int pin_callback (void *user, int attempt, const char *token_url, - const char *token_label, unsigned int flags, char *pin, - size_t pin_max) -{ -struct tls_st * ts = user; -int srk = 0; -const char* p; -unsigned len; - - if (flags & GNUTLS_PIN_FINAL_TRY) { - syslog(LOG_ERR, "PIN callback: final try before locking; not attempting to unlock"); - return -1; - } - - if (flags & GNUTLS_PIN_WRONG) { - syslog(LOG_ERR, "PIN callback: wrong PIN was entered for '%s' (%s)", token_label, token_url); - return -1; - } - - if (ts->pin[0] == 0) { - syslog(LOG_ERR, "PIN required for '%s' but pin-file was not set", token_label); - return -1; - } - - if (strcmp(token_url, "SRK") == 0 || strcmp(token_label, "SRK") == 0) { - srk = 1; - p = ts->srk_pin; - } else { - p = ts->pin; - } - - if (srk != 0 && ts->srk_pin[0] == 0) { - syslog(LOG_ERR, "PIN required for '%s' but srk-pin-file was not set", token_label); - return -1; - } - - len = strlen(p); - if (len > pin_max-1) { - syslog(LOG_ERR, "Too long PIN (%u chars)", len); - return -1; - } - - memcpy(pin, p, len); - pin[len] = 0; - - return 0; -} - -static -int load_pins(main_server_st* s) -{ -int fd, ret; - - s->creds.srk_pin[0] = 0; - s->creds.pin[0] = 0; - - if (s->config->srk_pin_file != NULL) { - fd = open(s->config->srk_pin_file, O_RDONLY); - if (fd < 0) { - mslog(s, NULL, LOG_ERR, "could not open SRK PIN file '%s'", s->config->srk_pin_file); - return -1; - } - - ret = read(fd, s->creds.srk_pin, sizeof(s->creds.srk_pin)); - close(fd); - if (ret <= 1) { - mslog(s, NULL, LOG_ERR, "could not read from PIN file '%s'", s->config->srk_pin_file); - return -1; - } - - if (s->creds.srk_pin[ret-1] == '\n' || s->creds.srk_pin[ret-1] == '\r') - s->creds.srk_pin[ret-1] = 0; - s->creds.srk_pin[ret] = 0; - } - - if (s->config->pin_file != NULL) { - fd = open(s->config->pin_file, O_RDONLY); - if (fd < 0) { - mslog(s, NULL, LOG_ERR, "could not open PIN file '%s'", s->config->pin_file); - return -1; - } - - ret = read(fd, s->creds.pin, sizeof(s->creds.pin)); - close(fd); - if (ret <= 1) { - mslog(s, NULL, LOG_ERR, "could not read from PIN file '%s'", s->config->pin_file); - return -1; - } - - if (s->creds.pin[ret-1] == '\n' || s->creds.pin[ret-1] == '\r') - s->creds.pin[ret-1] = 0; - s->creds.pin[ret] = 0; - } - - return 0; -} - void tls_global_init(main_server_st* s) { int ret; @@ -419,11 +324,175 @@ int ret; } } +struct key_cb_data { + unsigned idx; /* the index of the key */ + struct sockaddr_un sa; +}; + +static +int key_cb_common_func (gnutls_privkey_t key, void* userdata, const gnutls_datum_t * raw_data, + gnutls_datum_t * output, unsigned type) +{ + struct key_cb_data* cdata = userdata; + int sd, ret, e; + uint8_t header[2]; + struct iovec iov[2]; + uint16_t length; + + output->data = NULL; + + sd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sd == -1) { + e = errno; + syslog(LOG_ERR, "error opening socket: %s", strerror(e)); + return -1; + } + + ret = connect(sd, (struct sockaddr *)&cdata->sa, sizeof(cdata->sa)); + if (ret == -1) { + e = errno; + syslog(LOG_ERR, "error connecting to sec-mod socket '%s': %s", + cdata->sa.sun_path, strerror(e)); + return -1; + } + + header[0] = cdata->idx; + header[1] = type; + + iov[0].iov_base = header; + iov[0].iov_len = sizeof(header); + iov[1].iov_base = raw_data->data; + iov[1].iov_len = raw_data->size; + + ret = writev(sd, iov, 2); + if (ret == -1) { + e = errno; + syslog(LOG_ERR, "error writing to sec-mod: %s", strerror(e)); + goto error; + } + + ret = recv(sd, &length, 2, 0); + if (ret < 2) { + e = errno; + syslog(LOG_ERR, "error reading from sec-mod: %s", strerror(e)); + goto error; + } + + output->size = length; + output->data = gnutls_malloc(output->size); + if (output->data == NULL) { + syslog(LOG_ERR, "error allocating memory"); + goto error; + } + + ret = recv(sd, output->data, output->size, 0); + if (ret <= 0) { + e = errno; + syslog(LOG_ERR, "error reading from sec-mod: %s", strerror(e)); + goto error; + } + + output->size = ret; + + close(sd); + return 0; + +error: + close(sd); + gnutls_free(output->data); + return -1; + +} + +#if GNUTLS_VERSION_NUMBER >= 0x03010a +static +int key_cb_sign_func (gnutls_privkey_t key, void* userdata, const gnutls_datum_t * raw_data, + gnutls_datum_t * signature) +{ + return key_cb_common_func(key, userdata, raw_data, signature, 'S'); +} +#else +# define key_cb_sign_func NULL +#endif + +static int key_cb_decrypt_func(gnutls_privkey_t key, void* userdata, const gnutls_datum_t * ciphertext, + gnutls_datum_t * plaintext) +{ + return key_cb_common_func(key, userdata, ciphertext, plaintext, 'D'); +} + +static void key_cb_deinit_func(gnutls_privkey_t key, void* userdata) +{ + free(userdata); +} + +static +int load_key_files(main_server_st *s) +{ +int ret; +gnutls_pcert_st *pcert_list; +unsigned pcert_list_size, i; +gnutls_privkey_t key; +gnutls_datum_t data; +struct key_cb_data * cdata; + + for (i=0;iconfig->key_size;i++) { + /* load the certificate */ + if (gnutls_url_is_supported(s->config->cert[i]) != 0) { + mslog(s, NULL, LOG_ERR, "Loading a certificate from '%s' is unsupported", s->config->cert[i]); + return -1; + } else { + ret = gnutls_load_file(s->config->cert[i], &data); + if (ret < 0) { + mslog(s, NULL, LOG_ERR, "error loading file '%s'", s->config->key[i]); + GNUTLS_FATAL_ERR(ret); + } + + pcert_list_size = 8; + pcert_list = gnutls_malloc(sizeof(pcert_list[0])*pcert_list_size); + if (pcert_list == NULL) { + mslog(s, NULL, LOG_ERR, "error allocating memory"); + return -1; + } + + ret = gnutls_pcert_list_import_x509_raw(pcert_list, &pcert_list_size, + &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED|GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); + GNUTLS_FATAL_ERR(ret); + + gnutls_free(data.data); + } + + ret = gnutls_privkey_init(&key); + GNUTLS_FATAL_ERR(ret); + + cdata = malloc(sizeof(*cdata)); + if (cdata == NULL) { + mslog(s, NULL, LOG_ERR, "error allocating memory"); + return -1; + } + + cdata->idx = i; + cdata->sa.sun_family = AF_UNIX; + snprintf(cdata->sa.sun_path, sizeof(cdata->sa.sun_path), "%s", s->socket_file); + + /* load the private key */ + ret = gnutls_privkey_import_ext2(key, gnutls_pubkey_get_pk_algorithm(pcert_list[0].pubkey, NULL), + cdata, key_cb_sign_func, key_cb_decrypt_func, + key_cb_deinit_func, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); + GNUTLS_FATAL_ERR(ret); + + ret = gnutls_certificate_set_key(s->creds.xcred, NULL, 0, pcert_list, + pcert_list_size, key); + GNUTLS_FATAL_ERR(ret); + } + + return 0; +} + /* reload key files etc. */ void tls_global_init_certs(main_server_st* s) { int ret; -unsigned i; const char* perr; if (s->config->tls_debug) { @@ -437,14 +506,7 @@ const char* perr; ret = gnutls_certificate_allocate_credentials(&s->creds.xcred); GNUTLS_FATAL_ERR(ret); - ret = load_pins(s); - if (ret < 0) { - exit(1); - } - set_dh_params(s, s->creds.xcred); - - gnutls_certificate_set_pin_function (s->creds.xcred, pin_callback, &s->creds); if (s->config->key_size == 0 || s->config->cert_size == 0) { mslog(s, NULL, LOG_ERR, "no certificate or key files were specified.\n"); @@ -453,22 +515,10 @@ const char* perr; certificate_check(s); - for (i=0;iconfig->key_size;i++) { - if (strncmp(s->config->key[i], "pkcs11:", 7) != 0) { - ret = - gnutls_certificate_set_x509_key_file(s->creds.xcred, s->config->cert[i], - s->config->key[i], GNUTLS_X509_FMT_PEM); - if (ret < 0) { - mslog(s, NULL, LOG_ERR, "error setting the certificate (%s) or key (%s) files: %s\n", - s->config->cert[i], s->config->key[i], gnutls_strerror(ret)); - exit(1); - } - } else { -#ifndef HAVE_PKCS11 - mslog(s, NULL, LOG_ERR, "cannot load key, GnuTLS is compiled without pkcs11 support\n"); - exit(1); -#endif - } + ret = load_key_files(s); + if (ret < 0) { + mslog(s, NULL, LOG_ERR, "error loading the certificate or key file\n"); + exit(1); } if (s->config->cert_req != GNUTLS_CERT_IGNORE) { @@ -519,40 +569,6 @@ const char* perr; return; } -int tls_global_init_client(worker_st* ws) -{ -#ifdef HAVE_PKCS11 -int ret; -unsigned i; - - /* 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. */ - for (i=0;iconfig->key_size;i++) { - if (strncmp(ws->config->key[i], "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[i], - ws->config->key[i], - 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[i], ws->config->key[i], gnutls_strerror(ret)); - return -1; - } - } - } -#endif - - return 0; -} - void tls_cork(gnutls_session_t session) { #if GNUTLS_VERSION_NUMBER > 0x030109 diff --git a/src/tlslib.h b/src/tlslib.h index 998a8be4..f7310978 100644 --- a/src/tlslib.h +++ b/src/tlslib.h @@ -19,7 +19,6 @@ void tls_cork(gnutls_session_t session); int tls_uncork(gnutls_session_t session); void tls_global_init(struct main_server_st* s); -int tls_global_init_client(struct worker_st* ws); void tls_global_init_certs(struct main_server_st* s); ssize_t tls_send_file(gnutls_session_t session, const char *file); @@ -51,15 +50,11 @@ void tls_close(gnutls_session_t session); void tls_fatal_close(gnutls_session_t session, gnutls_alert_description_t a); -#define MAX_PIN_SIZE GNUTLS_PKCS11_MAX_PIN_LEN - struct tls_st { gnutls_certificate_credentials_t xcred; gnutls_priority_t cprio; gnutls_dh_params_t dh_params; gnutls_datum_t ticket_key; - char pin[MAX_PIN_SIZE]; - char srk_pin[MAX_PIN_SIZE]; }; typedef struct diff --git a/src/vpn.h b/src/vpn.h index f1f8a23b..01267a5f 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -75,6 +75,8 @@ struct cfg_st { char *chroot_dir; /* where the xml files are served from */ char *banner; char *ocsp_response; /* file with the OCSP response */ + + char* socket_file_prefix; time_t cookie_validity; /* in seconds */ time_t min_reauth_time; /* after a failed auth, how soon one can reauthenticate -> in seconds */ unsigned auth_timeout; /* timeout of HTTP auth */ @@ -104,7 +106,7 @@ struct cfg_st { uid_t uid; gid_t gid; - + /* the tun network */ struct vpn_st network; }; diff --git a/src/worker-tun.c b/src/worker-tun.c index 479fe07f..6dc12f91 100644 --- a/src/worker-tun.c +++ b/src/worker-tun.c @@ -191,25 +191,4 @@ fail: return ret; } -ssize_t tun_write(int sockfd, const void *buf, size_t len) -{ -int left = len; -int ret; -const uint8_t * p = buf; - - while(left > 0) { - ret = write(sockfd, p, left); - if (ret == -1) { - if (errno != EAGAIN && errno != EINTR) - return ret; - } - - if (ret > 0) { - left -= ret; - p += ret; - } - } - - return len; -} diff --git a/src/worker-vpn.c b/src/worker-vpn.c index 7f45270a..75cf8bc9 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "ipc.h" @@ -1217,7 +1218,7 @@ int ret, e, l; break; case AC_PKT_DATA: oclog(ws, LOG_DEBUG, "writing %d byte(s) to TUN", (int)buf_size); - ret = tun_write(ws->tun_fd, buf, buf_size); + ret = force_write(ws->tun_fd, buf, buf_size); if (ret == -1) { e = errno; oclog(ws, LOG_ERR, "could not write data to tun: %s", strerror(e));