diff --git a/Makefile.am b/Makefile.am index d9672c62..c6900a35 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ EXTRA_DIST = m4/lib-link.m4 -SUBDIRS = gl libopts src +SUBDIRS = gl libopts src doc ACLOCAL_AMFLAGS = -I gl/m4 -I libopts/m4 -I m4 diff --git a/README b/README index a18e3f9f..f9786729 100644 --- a/README +++ b/README @@ -1,3 +1,14 @@ + +=== About === + +This program is openconnect VPN server (ocserv), a server compatible with the +openconnect VPN client [0]. It is believed to be compatible with the protocol +used by CISCO's AnyConnect SSL VPN. + +[0]. http://www.infradead.org/openconnect/ + +=== Build instructions === + To build from the git repository use: $ autoreconf -fvi diff --git a/configure.ac b/configure.ac index d047b8d0..7255e8eb 100644 --- a/configure.ac +++ b/configure.ac @@ -85,6 +85,7 @@ LIBOPTS_CHECK([libopts]) AC_CONFIG_FILES([ Makefile src/Makefile + doc/Makefile gl/Makefile ]) AC_OUTPUT diff --git a/src/config.c b/src/config.c index bb7b7131..345b4ebb 100644 --- a/src/config.c +++ b/src/config.c @@ -34,6 +34,7 @@ #define DEFAULT_CFG_FILE "/etc/ocserv.conf" static void write_pid_file(const char* pid_file); +static const char* cfg_file = DEFAULT_CFG_FILE; #define MAX_ENTRIES 64 @@ -233,7 +234,6 @@ static void check_cfg( struct cfg_st *config) int cmd_parser (int argc, char **argv, struct cfg_st* config) { - const char* cfg_file = DEFAULT_CFG_FILE; memset(config, 0, sizeof(*config)); @@ -263,6 +263,42 @@ int cmd_parser (int argc, char **argv, struct cfg_st* config) } +#define DEL(x) free(x);x=NULL +void reload_cfg_file(struct cfg_st* config) +{ +unsigned i; + + DEL(config->name); + DEL(config->cert); + DEL(config->key); + DEL(config->ca); + DEL(config->crl); + DEL(config->cert_user_oid); + DEL(config->priorities); + DEL(config->chroot_dir); + DEL(config->cookie_db_name); + DEL(config->connect_script); + DEL(config->disconnect_script); + + DEL(config->network.name); + DEL(config->network.ipv4); + DEL(config->network.ipv4_netmask); + DEL(config->network.ipv4_dns); + DEL(config->network.ipv6); + DEL(config->network.ipv6_netmask); + DEL(config->network.ipv6_dns); + for (i=0;inetwork.routes_size;i++) + DEL(config->network.routes[i]); + DEL(config->network.routes); + memset(config, 0, sizeof(*config)); + + parse_cfg_file(cfg_file, config); + + check_cfg(config); + + return; +} + static void write_pid_file(const char* pid_file) { FILE* fp; diff --git a/src/log.c b/src/log.c index 823db9a1..abeb520a 100644 --- a/src/log.c +++ b/src/log.c @@ -117,7 +117,7 @@ void __attribute__ ((format(printf, 4, 5))) if (ip) { syslog(priority, "%s %s", ip, buf); } else { - syslog(priority, "[unknown] %s", buf); + syslog(priority, "[main] %s", buf); } return; diff --git a/src/main.c b/src/main.c index b6be8b72..2abf3239 100644 --- a/src/main.c +++ b/src/main.c @@ -46,6 +46,7 @@ int syslog_open = 0; static unsigned int terminate = 0; +static unsigned int reload_conf = 0; static unsigned int need_maintainance = 0; static unsigned int need_children_cleanup = 0; @@ -380,6 +381,11 @@ static void handle_term(int signo) terminate = 1; } +static void handle_reload(int signo) +{ + reload_conf = 1; +} + #define RECORD_PAYLOAD_POS 13 #define HANDSHAKE_SESSION_ID_POS 46 @@ -491,7 +497,7 @@ int main(int argc, char** argv) signal(SIGINT, handle_term); signal(SIGTERM, handle_term); signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, SIG_IGN); + signal(SIGHUP, handle_reload); signal(SIGCHLD, handle_children); signal(SIGALRM, handle_alarm); @@ -547,6 +553,13 @@ int main(int argc, char** argv) syslog_open = 1; for (;;) { + if (reload_conf != 0) { + mslog(&s, NULL, LOG_INFO, "HUP signal was received; reloading configuration"); + reload_cfg_file(s.config); + tls_global_reinit(&s); + reload_conf = 0; + } + if (terminate != 0) { mslog(&s, NULL, LOG_DEBUG, "termination signal received; waiting for children to die"); kill_children(&s); diff --git a/src/main.h b/src/main.h index f1950a8e..a655bfc0 100644 --- a/src/main.h +++ b/src/main.h @@ -10,6 +10,7 @@ #include "ipc.h" int cmd_parser (int argc, char **argv, struct cfg_st* config); +void reload_cfg_file(struct cfg_st* config); struct listener_st { struct list_node list; diff --git a/src/tlslib.c b/src/tlslib.c index 80b6af3d..fd54f317 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -301,6 +301,74 @@ const char* perr; return; } +/* reload key files etc. */ +void tls_global_reinit(main_server_st* s) +{ +int ret; +const char* perr; + + gnutls_certificate_free_credentials(s->creds.xcred); + + 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) { + mslog(s, NULL, LOG_ERR, "Error setting the certificate (%s) or key (%s) files: %s\n", + s->config->cert, s->config->key, gnutls_strerror(ret)); + exit(1); + } + } else { +#ifdef HAVE_PKCS11 + mslog(s, NULL, LOG_ERR, "Cannot load key, GnuTLS is compiled without pkcs11 support\n"); + exit(1); +#endif + } + + 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) { + mslog(s, NULL, LOG_ERR, "Error setting the CA (%s) file.\n", + s->config->ca); + exit(1); + } + + mslog(s, NULL, LOG_ERR, "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); + if (ret < 0) { + mslog(s, NULL, LOG_ERR, "Error setting the CRL (%s) file.\n", + s->config->crl); + exit(1); + } + } + + 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) + mslog(s, NULL, LOG_ERR, "Error in TLS priority string: %s\n", perr); + GNUTLS_FATAL_ERR(ret); + + + return; +} + int tls_global_init_client(worker_st* ws) { int ret; diff --git a/src/tlslib.h b/src/tlslib.h index 522e1023..0f014062 100644 --- a/src/tlslib.h +++ b/src/tlslib.h @@ -19,6 +19,7 @@ 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_reinit(struct main_server_st* s); ssize_t tls_send_file(gnutls_session_t session, const char *file); diff --git a/src/vpn.h b/src/vpn.h index d1846ee2..d71684b9 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -37,33 +37,33 @@ typedef struct struct vpn_st { - const char *name; /* device name */ - const char *ipv4_netmask; - const char *ipv4; - const char *ipv4_local; /* local IPv4 address */ - const char *ipv6_netmask; - const char *ipv6; - const char *ipv6_local; /* local IPv6 address */ - const char *ipv4_dns; - const char *ipv6_dns; + char *name; /* device name */ + char *ipv4_netmask; + char *ipv4; + char *ipv4_local; /* local IPv4 address */ + char *ipv6_netmask; + char *ipv6; + char *ipv6_local; /* local IPv6 address */ + char *ipv4_dns; + char *ipv6_dns; unsigned int mtu; - const char **routes; + char **routes; unsigned int routes_size; }; struct cfg_st { - const char *name; + char *name; /* server name */ unsigned int port; unsigned int udp_port; - const char *cert; - const char *key; - const char *ca; - const char *crl; - const char *cert_user_oid; /* The OID that will be used to extract the username */ + char *cert; + char *key; + char *ca; + char *crl; + char *cert_user_oid; /* The OID that will be used to extract the username */ unsigned int auth_types; /* or'ed sequence of AUTH_TYPE */ gnutls_certificate_request_t cert_req; - const char *priorities; - const char *chroot_dir; /* where the xml files are served from */ + char *priorities; + char *chroot_dir; /* where the xml files are served from */ time_t cookie_validity; /* in seconds */ unsigned auth_timeout; /* timeout of HTTP auth */ unsigned keepalive; @@ -76,10 +76,10 @@ struct cfg_st { unsigned use_utmp; /* if gdbm is there */ - const char* cookie_db_name; + char* cookie_db_name; - const char *connect_script; - const char *disconnect_script; + char *connect_script; + char *disconnect_script; uid_t uid; gid_t gid; diff --git a/src/worker-tun.c b/src/worker-tun.c index 757cb8cf..f9e8800b 100644 --- a/src/worker-tun.c +++ b/src/worker-tun.c @@ -52,7 +52,7 @@ int get_ip(struct worker_st* ws, int fd, int family, unsigned int local, struct vpn_st* vinfo, char** buffer, size_t* buffer_size) { void* ptr; -const void* p; +void* p; struct ifreq ifr; unsigned int flags; int ret, e; @@ -82,7 +82,7 @@ int ret, e; return -1; } - p = inet_ntop(family, ptr, *buffer, *buffer_size); + p = (char*)inet_ntop(family, ptr, *buffer, *buffer_size); if (p == NULL) { e = errno; oclog(ws, LOG_DEBUG, "inet_ntop error: %s", strerror(e)); diff --git a/src/worker-vpn.c b/src/worker-vpn.c index f0f3bd0d..dd6e78c5 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -322,6 +322,7 @@ void vpn_server(struct worker_st* ws) signal(SIGTERM, handle_term); signal(SIGINT, handle_term); + signal(SIGHUP, SIG_IGN); signal(SIGALRM, handle_alarm); if (ws->config->auth_timeout)