mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
Several updates to handle URLs requested by the cisco client.
This commit is contained in:
+1
-1
@@ -4,5 +4,5 @@ dist_man_MANS = ocserv.1
|
|||||||
|
|
||||||
ocserv.1: ../src/ocserv-args.def
|
ocserv.1: ../src/ocserv-args.def
|
||||||
-sed 's/@subheading \(.*\)/@*\n@var{\1}\n@*/' $< > "$<".tmp && \
|
-sed 's/@subheading \(.*\)/@*\n@var{\1}\n@*/' $< > "$<".tmp && \
|
||||||
-@AUTOGEN@ -DMAN_SECTION=1 -Tagman-cmd.tpl "$<".tmp && \
|
@AUTOGEN@ -DMAN_SECTION=1 -Tagman-cmd.tpl "$<".tmp && \
|
||||||
rm -f "$<".tmp
|
rm -f "$<".tmp
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<AnyConnectProfile xmlns="http://schemas.xmlsoap.org/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.xmlsoap.org/encoding/ AnyConnectProfile.xsd">
|
||||||
|
|
||||||
|
<ClientInitialization>
|
||||||
|
<UseStartBeforeLogon UserControllable="false">false</UseStartBeforeLogon>
|
||||||
|
<StrictCertificateTrust>false</StrictCertificateTrust>
|
||||||
|
<RestrictPreferenceCaching>false</RestrictPreferenceCaching>
|
||||||
|
<RestrictTunnelProtocols>IPSec</RestrictTunnelProtocols>
|
||||||
|
<BypassDownloader>true</BypassDownloader>
|
||||||
|
<CertEnrollmentPin>pinAllowed</CertEnrollmentPin>
|
||||||
|
<CertificateMatch>
|
||||||
|
<KeyUsage>
|
||||||
|
<MatchKey>Digital_Signature</MatchKey>
|
||||||
|
</KeyUsage>
|
||||||
|
<ExtendedKeyUsage>
|
||||||
|
<ExtendedMatchKey>ClientAuth</ExtendedMatchKey>
|
||||||
|
</ExtendedKeyUsage>
|
||||||
|
</CertificateMatch>
|
||||||
|
|
||||||
|
<BackupServerList>
|
||||||
|
<HostAddress>10.100.2.17</HostAddress>
|
||||||
|
</BackupServerList>
|
||||||
|
</ClientInitialization>
|
||||||
|
|
||||||
|
<ServerList>
|
||||||
|
<HostEntry>
|
||||||
|
<HostName>VPN Server</HostName>
|
||||||
|
<HostAddress>10.100.2.17</HostAddress>
|
||||||
|
</HostEntry>
|
||||||
|
</ServerList>
|
||||||
|
</AnyConnectProfile>
|
||||||
+10
-2
@@ -4,6 +4,14 @@
|
|||||||
#auth = "certificate"
|
#auth = "certificate"
|
||||||
auth = "pam"
|
auth = "pam"
|
||||||
|
|
||||||
|
# A banner to be displayed on clients
|
||||||
|
#banner = "Welcome"
|
||||||
|
|
||||||
|
# Client config xml. The variable $GROUP will be replaced by
|
||||||
|
# the user's group name. This file must be accessible from inside
|
||||||
|
# the worker's chroot. It is not used by the openconnect client.
|
||||||
|
user-profile = ../doc/profile.xml
|
||||||
|
|
||||||
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||||
#listen-host = [IP|HOSTNAME]
|
#listen-host = [IP|HOSTNAME]
|
||||||
|
|
||||||
@@ -16,8 +24,8 @@ max-clients = 16
|
|||||||
max-same-clients = 2
|
max-same-clients = 2
|
||||||
|
|
||||||
# TCP and UDP port number
|
# TCP and UDP port number
|
||||||
tcp-port = 3333
|
tcp-port = 443
|
||||||
udp-port = 3333
|
udp-port = 443
|
||||||
|
|
||||||
# Keepalive in seconds
|
# Keepalive in seconds
|
||||||
keepalive = 32400
|
keepalive = 32400
|
||||||
|
|||||||
+1
-1
@@ -28,4 +28,4 @@ ocserv_LDADD += $(LIBGNUTLS_LIBS) $(GDBM_LIBS) $(PAM_LIBS) $(LIBUTIL) \
|
|||||||
$(LIBSECCOMP) $(LIBWRAP)
|
$(LIBSECCOMP) $(LIBWRAP)
|
||||||
|
|
||||||
ocserv-args.c ocserv-args.h: $(srcdir)/ocserv-args.def
|
ocserv-args.c ocserv-args.h: $(srcdir)/ocserv-args.def
|
||||||
-@AUTOGEN@ $<
|
@AUTOGEN@ $<
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <autoopts/options.h>
|
#include <autoopts/options.h>
|
||||||
|
|
||||||
#include <vpn.h>
|
#include <vpn.h>
|
||||||
|
#include <tlslib.h>
|
||||||
|
|
||||||
#define DEFAULT_CFG_FILE "/etc/ocserv.conf"
|
#define DEFAULT_CFG_FILE "/etc/ocserv.conf"
|
||||||
|
|
||||||
@@ -146,6 +147,7 @@ unsigned j;
|
|||||||
READ_STRING("server-key", config->key, 1);
|
READ_STRING("server-key", config->key, 1);
|
||||||
READ_STRING("pin-file", config->pin_file, 0);
|
READ_STRING("pin-file", config->pin_file, 0);
|
||||||
READ_STRING("srk-pin-file", config->srk_pin_file, 0);
|
READ_STRING("srk-pin-file", config->srk_pin_file, 0);
|
||||||
|
READ_STRING("user-profile", config->xml_config_file, 0);
|
||||||
|
|
||||||
READ_STRING("ca-cert", config->ca, 0);
|
READ_STRING("ca-cert", config->ca, 0);
|
||||||
READ_STRING("crl", config->crl, 0);
|
READ_STRING("crl", config->crl, 0);
|
||||||
@@ -208,6 +210,7 @@ unsigned j;
|
|||||||
READ_MULTI_LINE("route", config->network.routes, config->network.routes_size, 0);
|
READ_MULTI_LINE("route", config->network.routes, config->network.routes_size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* sanity checks on config */
|
/* sanity checks on config */
|
||||||
static void check_cfg( struct cfg_st *config)
|
static void check_cfg( struct cfg_st *config)
|
||||||
{
|
{
|
||||||
@@ -230,6 +233,14 @@ static void check_cfg( struct cfg_st *config)
|
|||||||
fprintf(stderr, "Banner size is too long\n");
|
fprintf(stderr, "Banner size is too long\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->cert) {
|
||||||
|
config->cert_hash = calc_sha1_hash(config->cert, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->xml_config_file) {
|
||||||
|
config->xml_config_hash = calc_sha1_hash(config->xml_config_file, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (config->keepalive == 0)
|
if (config->keepalive == 0)
|
||||||
config->keepalive = 3600;
|
config->keepalive = 3600;
|
||||||
@@ -280,6 +291,9 @@ void reload_cfg_file(struct cfg_st* config)
|
|||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
DEL(config->xml_config_file);
|
||||||
|
DEL(config->xml_config_hash);
|
||||||
|
DEL(config->cert_hash);
|
||||||
DEL(config->banner);
|
DEL(config->banner);
|
||||||
DEL(config->name);
|
DEL(config->name);
|
||||||
DEL(config->cert);
|
DEL(config->cert);
|
||||||
|
|||||||
+6
-4
@@ -485,7 +485,7 @@ static void check_other_work(main_server_st *s)
|
|||||||
if (reload_conf != 0) {
|
if (reload_conf != 0) {
|
||||||
mslog(s, NULL, LOG_INFO, "HUP signal was received; reloading configuration");
|
mslog(s, NULL, LOG_INFO, "HUP signal was received; reloading configuration");
|
||||||
reload_cfg_file(s->config);
|
reload_cfg_file(s->config);
|
||||||
tls_global_reinit(s);
|
tls_global_init_certs(s);
|
||||||
reload_conf = 0;
|
reload_conf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,6 +559,9 @@ int main(int argc, char** argv)
|
|||||||
signal(SIGCHLD, handle_children);
|
signal(SIGCHLD, handle_children);
|
||||||
signal(SIGALRM, handle_alarm);
|
signal(SIGALRM, handle_alarm);
|
||||||
|
|
||||||
|
/* Initialize GnuTLS */
|
||||||
|
tls_global_init(&s);
|
||||||
|
|
||||||
/* load configuration */
|
/* load configuration */
|
||||||
ret = cmd_parser(argc, argv, &config);
|
ret = cmd_parser(argc, argv, &config);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -601,11 +604,10 @@ int main(int argc, char** argv)
|
|||||||
allow_severity = LOG_DAEMON|LOG_INFO;
|
allow_severity = LOG_DAEMON|LOG_INFO;
|
||||||
deny_severity = LOG_DAEMON|LOG_WARNING;
|
deny_severity = LOG_DAEMON|LOG_WARNING;
|
||||||
#endif
|
#endif
|
||||||
|
memset(&ws, 0, sizeof(ws));
|
||||||
|
|
||||||
/* Initialize GnuTLS */
|
/* Initialize GnuTLS */
|
||||||
tls_global_init(&s);
|
tls_global_init_certs(&s);
|
||||||
|
|
||||||
memset(&ws, 0, sizeof(ws));
|
|
||||||
|
|
||||||
if (config.foreground == 0) {
|
if (config.foreground == 0) {
|
||||||
if (daemon(0, 0) == -1) {
|
if (daemon(0, 0) == -1) {
|
||||||
|
|||||||
+4
-4
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||||
*
|
*
|
||||||
* It has been AutoGen-ed February 27, 2013 at 07:03:11 PM by AutoGen 5.16
|
* It has been AutoGen-ed March 1, 2013 at 07:46:59 PM by AutoGen 5.16
|
||||||
* From the definitions ocserv-args.def
|
* From the definitions ocserv-args.def
|
||||||
* and the template file options
|
* and the template file options
|
||||||
*
|
*
|
||||||
@@ -66,7 +66,7 @@ extern FILE * option_usage_fp;
|
|||||||
* ocserv option static const strings
|
* ocserv option static const strings
|
||||||
*/
|
*/
|
||||||
static char const ocserv_opt_strs[1840] =
|
static char const ocserv_opt_strs[1840] =
|
||||||
/* 0 */ "ocserv 0.0.1\n"
|
/* 0 */ "ocserv 0.0.2\n"
|
||||||
"Copyright (C) 2013 Nikos Mavrogiannopoulos, all rights reserved.\n"
|
"Copyright (C) 2013 Nikos Mavrogiannopoulos, all rights reserved.\n"
|
||||||
"This is free software. It is licensed for use, modification and\n"
|
"This is free software. It is licensed for use, modification and\n"
|
||||||
"redistribution under the terms of the\n"
|
"redistribution under the terms of the\n"
|
||||||
@@ -99,7 +99,7 @@ static char const ocserv_opt_strs[1840] =
|
|||||||
/* 1129 */ "Output version information and exit\0"
|
/* 1129 */ "Output version information and exit\0"
|
||||||
/* 1165 */ "version\0"
|
/* 1165 */ "version\0"
|
||||||
/* 1173 */ "OCSERV\0"
|
/* 1173 */ "OCSERV\0"
|
||||||
/* 1180 */ "ocserv - OpenConnect server - Ver. 0.0.1\n"
|
/* 1180 */ "ocserv - OpenConnect server - Ver. 0.0.2\n"
|
||||||
"USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
|
"USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
|
||||||
/* 1279 */ "openconnect-devel@lists.infradead.org\0"
|
/* 1279 */ "openconnect-devel@lists.infradead.org\0"
|
||||||
/* 1317 */ "\n\n\0"
|
/* 1317 */ "\n\n\0"
|
||||||
@@ -111,7 +111,7 @@ static char const ocserv_opt_strs[1840] =
|
|||||||
"authentication. Authenticated users are assigned an unprivileged worker\n"
|
"authentication. Authenticated users are assigned an unprivileged worker\n"
|
||||||
"process and obtain a networking (tun) device and IP from a configurable\n"
|
"process and obtain a networking (tun) device and IP from a configurable\n"
|
||||||
"pool of addresses.\n\0"
|
"pool of addresses.\n\0"
|
||||||
/* 1752 */ "ocserv 0.0.1\0"
|
/* 1752 */ "ocserv 0.0.2\0"
|
||||||
/* 1765 */ "Usage: ocserv [options] -c [config]\n"
|
/* 1765 */ "Usage: ocserv [options] -c [config]\n"
|
||||||
"ocserv --help for usage instructions.\n";
|
"ocserv --help for usage instructions.\n";
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,11 @@ auth = "pam"
|
|||||||
# A banner to be displayed on clients
|
# A banner to be displayed on clients
|
||||||
#banner = "Welcome"
|
#banner = "Welcome"
|
||||||
|
|
||||||
|
# Client profile xml. A sample file exists in doc/profile.xml.
|
||||||
|
# This file must be accessible from inside the worker's chroot.
|
||||||
|
# It is not used by the openconnect client.
|
||||||
|
#user-profile = /path/to/file.xml
|
||||||
|
|
||||||
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||||
#listen-host = [IP|HOSTNAME]
|
#listen-host = [IP|HOSTNAME]
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||||
*
|
*
|
||||||
* It has been AutoGen-ed February 27, 2013 at 07:03:10 PM by AutoGen 5.16
|
* It has been AutoGen-ed March 1, 2013 at 07:46:59 PM by AutoGen 5.16
|
||||||
* From the definitions ocserv-args.def
|
* From the definitions ocserv-args.def
|
||||||
* and the template file options
|
* and the template file options
|
||||||
*
|
*
|
||||||
@@ -76,8 +76,8 @@ typedef enum {
|
|||||||
} teOptIndex;
|
} teOptIndex;
|
||||||
|
|
||||||
#define OPTION_CT 7
|
#define OPTION_CT 7
|
||||||
#define OCSERV_VERSION "0.0.1"
|
#define OCSERV_VERSION "0.0.2"
|
||||||
#define OCSERV_FULL_VERSION "ocserv 0.0.1"
|
#define OCSERV_FULL_VERSION "ocserv 0.0.2"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface defines for all options. Replace "n" with the UPPER_CASED
|
* Interface defines for all options. Replace "n" with the UPPER_CASED
|
||||||
|
|||||||
+64
-7
@@ -19,6 +19,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <gnutls/gnutls.h>
|
#include <gnutls/gnutls.h>
|
||||||
|
#include <gnutls/crypto.h>
|
||||||
#include <gnutls/pkcs11.h>
|
#include <gnutls/pkcs11.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -333,25 +334,24 @@ void tls_global_init(main_server_st* s)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
gnutls_global_set_audit_log_function(tls_audit_log_func);
|
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();
|
ret = gnutls_global_init();
|
||||||
GNUTLS_FATAL_ERR(ret);
|
GNUTLS_FATAL_ERR(ret);
|
||||||
|
|
||||||
tls_global_reinit(s);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reload key files etc. */
|
/* reload key files etc. */
|
||||||
void tls_global_reinit(main_server_st* s)
|
void tls_global_init_certs(main_server_st* s)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
const char* perr;
|
const char* perr;
|
||||||
|
|
||||||
|
if (s->config->tls_debug) {
|
||||||
|
gnutls_global_set_log_function(tls_log_func);
|
||||||
|
gnutls_global_set_log_level(9);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->creds.xcred != NULL)
|
if (s->creds.xcred != NULL)
|
||||||
gnutls_certificate_free_credentials(s->creds.xcred);
|
gnutls_certificate_free_credentials(s->creds.xcred);
|
||||||
|
|
||||||
@@ -468,3 +468,60 @@ int tls_uncork(gnutls_session_t session)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *calc_sha1_hash(char* file, unsigned cert)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
gnutls_datum_t data;
|
||||||
|
uint8_t digest[20];
|
||||||
|
char * retval;
|
||||||
|
gnutls_x509_crt_t crt;
|
||||||
|
|
||||||
|
ret = gnutls_load_file(file, &data);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Cannot open file '%s': %s\n", file, gnutls_strerror(ret));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert != 0) {
|
||||||
|
ret = gnutls_x509_crt_init(&crt);
|
||||||
|
GNUTLS_FATAL_ERR(ret);
|
||||||
|
|
||||||
|
ret = gnutls_x509_crt_import(crt, &data, GNUTLS_X509_FMT_PEM);
|
||||||
|
if (ret == GNUTLS_E_BASE64_DECODING_ERROR)
|
||||||
|
ret = gnutls_x509_crt_import(crt, &data, GNUTLS_X509_FMT_DER);
|
||||||
|
GNUTLS_FATAL_ERR(ret);
|
||||||
|
|
||||||
|
gnutls_free(data.data);
|
||||||
|
|
||||||
|
ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &data);
|
||||||
|
GNUTLS_FATAL_ERR(ret);
|
||||||
|
gnutls_x509_crt_deinit(crt);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, digest);
|
||||||
|
gnutls_free(data.data);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Error calculating hash of '%s': %s\n", file, gnutls_strerror(ret));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ret_size = sizeof(digest)*2+1;
|
||||||
|
retval = malloc(ret_size);
|
||||||
|
if (retval == NULL) {
|
||||||
|
fprintf(stderr, "Memory error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.data = digest;
|
||||||
|
data.size = sizeof(digest);
|
||||||
|
ret = gnutls_hex_encode(&data, retval, &ret_size);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Error in hex encode: %s\n", gnutls_strerror(ret));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
retval[ret_size] = 0;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|||||||
+16
-2
@@ -20,19 +20,32 @@ int tls_uncork(gnutls_session_t session);
|
|||||||
|
|
||||||
void tls_global_init(struct main_server_st* s);
|
void tls_global_init(struct main_server_st* s);
|
||||||
int tls_global_init_client(struct worker_st* ws);
|
int tls_global_init_client(struct worker_st* ws);
|
||||||
void tls_global_reinit(struct main_server_st* s);
|
void tls_global_init_certs(struct main_server_st* s);
|
||||||
|
|
||||||
ssize_t tls_send_file(gnutls_session_t session, const char *file);
|
ssize_t tls_send_file(gnutls_session_t session, const char *file);
|
||||||
|
|
||||||
#define GNUTLS_FATAL_ERR(x) \
|
#define GNUTLS_FATAL_ERR(x) \
|
||||||
if (x < 0 && gnutls_error_is_fatal (x) != 0) { \
|
if (x < 0 && gnutls_error_is_fatal (x) != 0) { \
|
||||||
if (syslog_open) \
|
if (syslog_open) \
|
||||||
syslog(LOG_ERR, "GnuTLS error (at %s:%d): %s", __FILE__, __LINE__, gnutls_strerror(x)); \
|
syslog(LOG_ERR, "GnuTLS error (at %s:%d): %s", __FILE__, __LINE__, gnutls_strerror(x)); \
|
||||||
else \
|
else \
|
||||||
fprintf(stderr, "GnuTLS error (at %s:%d): %s\n", __FILE__, __LINE__, gnutls_strerror(x)); \
|
fprintf(stderr, "GnuTLS error (at %s:%d): %s\n", __FILE__, __LINE__, gnutls_strerror(x)); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GNUTLS_S_FATAL_ERR(session, x) \
|
||||||
|
if (x < 0 && gnutls_error_is_fatal (x) != 0) { \
|
||||||
|
if (syslog_open) { \
|
||||||
|
if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { \
|
||||||
|
syslog(LOG_ERR, "GnuTLS error (at %s:%d): %s: %s", __FILE__, __LINE__, gnutls_strerror(x), gnutls_alert_get_name(gnutls_alert_get(session))); \
|
||||||
|
} else { \
|
||||||
|
syslog(LOG_ERR, "GnuTLS error (at %s:%d): %s", __FILE__, __LINE__, gnutls_strerror(x)); \
|
||||||
|
} \
|
||||||
|
} else \
|
||||||
|
fprintf(stderr, "GnuTLS error (at %s:%d): %s\n", __FILE__, __LINE__, gnutls_strerror(x)); \
|
||||||
|
exit(1); \
|
||||||
|
}
|
||||||
|
|
||||||
void tls_close(gnutls_session_t session);
|
void tls_close(gnutls_session_t session);
|
||||||
|
|
||||||
void tls_fatal_close(gnutls_session_t session,
|
void tls_fatal_close(gnutls_session_t session,
|
||||||
@@ -66,5 +79,6 @@ typedef struct
|
|||||||
|
|
||||||
void tls_cache_init(hash_db_st** db);
|
void tls_cache_init(hash_db_st** db);
|
||||||
void tls_cache_deinit(hash_db_st* db);
|
void tls_cache_deinit(hash_db_st* db);
|
||||||
|
void *calc_sha1_hash(char* file, unsigned cert);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ struct cfg_st {
|
|||||||
char *pin_file;
|
char *pin_file;
|
||||||
char *srk_pin_file;
|
char *srk_pin_file;
|
||||||
char *cert;
|
char *cert;
|
||||||
|
char *cert_hash;
|
||||||
|
|
||||||
char *key;
|
char *key;
|
||||||
char *ca;
|
char *ca;
|
||||||
char *crl;
|
char *crl;
|
||||||
@@ -88,6 +90,9 @@ struct cfg_st {
|
|||||||
char *connect_script;
|
char *connect_script;
|
||||||
char *disconnect_script;
|
char *disconnect_script;
|
||||||
|
|
||||||
|
char *xml_config_file;
|
||||||
|
char *xml_config_hash;
|
||||||
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
|
||||||
|
|||||||
+72
-115
@@ -341,19 +341,84 @@ struct cmd_auth_cookie_req_st areq;
|
|||||||
return recv_auth_reply(ws);
|
return recv_auth_reply(ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int post_common_handler(worker_st *ws, unsigned http_ver)
|
||||||
|
{
|
||||||
|
int ret, size;
|
||||||
|
char str_cookie[2*COOKIE_SIZE+1];
|
||||||
|
char *p;
|
||||||
|
unsigned i;
|
||||||
|
char msg[MAX_BANNER_SIZE+32];
|
||||||
|
|
||||||
|
p = str_cookie;
|
||||||
|
for (i=0;i<sizeof(ws->cookie);i++) {
|
||||||
|
sprintf(p, "%.2x", (unsigned int)ws->cookie[i]);
|
||||||
|
p+=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reply */
|
||||||
|
tls_cork(ws->session);
|
||||||
|
|
||||||
|
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ws->config->banner) {
|
||||||
|
size = snprintf(msg, sizeof(msg), "<banner>%s</banner>", ws->config->banner);
|
||||||
|
if (size <= 0)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
msg[0] = 0;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size += (sizeof(SUCCESS_MSG_HEAD)-1) + (sizeof(SUCCESS_MSG_FOOT)-1);
|
||||||
|
|
||||||
|
ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)size);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_printf(ws->session, "Set-Cookie: webvpn=%s;Max-Age=%u\r\n", str_cookie, (unsigned)ws->config->cookie_validity);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ws->config->xml_config_file) {
|
||||||
|
ret = tls_printf(ws->session, "Set-Cookie: webvpnc=bu:/&p:t&iu:1/&sh:%s&lu:/+CSCOT+/translation-table?textdomain%%3DAnyConnect%%26type%%3Dmanifest&fu:profiles%%2Fprofile.xml&fh:%s\r\n", ws->config->cert_hash,ws->config->xml_config_hash);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tls_printf(ws->session, "\r\n"SUCCESS_MSG_HEAD"%s"SUCCESS_MSG_FOOT, msg);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_uncork(ws->session);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int post_old_auth_handler(worker_st *ws, unsigned http_ver)
|
int post_old_auth_handler(worker_st *ws, unsigned http_ver)
|
||||||
{
|
{
|
||||||
int ret, size;
|
int ret;
|
||||||
struct http_req_st *req = &ws->req;
|
struct http_req_st *req = &ws->req;
|
||||||
const char* reason = "Authentication failed";
|
const char* reason = "Authentication failed";
|
||||||
char str_cookie[2*COOKIE_SIZE+1];
|
|
||||||
char * username = NULL;
|
char * username = NULL;
|
||||||
char * password = NULL;
|
char * password = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
unsigned int i;
|
|
||||||
struct cmd_auth_req_st areq;
|
struct cmd_auth_req_st areq;
|
||||||
char msg[MAX_BANNER_SIZE+32];
|
|
||||||
|
|
||||||
memset(&areq, 0, sizeof(areq));
|
memset(&areq, 0, sizeof(areq));
|
||||||
|
|
||||||
@@ -412,59 +477,7 @@ char msg[MAX_BANNER_SIZE+32];
|
|||||||
|
|
||||||
oclog(ws, LOG_INFO, "User '%s' logged in", ws->username);
|
oclog(ws, LOG_INFO, "User '%s' logged in", ws->username);
|
||||||
|
|
||||||
p = str_cookie;
|
return post_common_handler(ws, http_ver);;
|
||||||
for (i=0;i<sizeof(ws->cookie);i++) {
|
|
||||||
sprintf(p, "%.2x", (unsigned int)ws->cookie[i]);
|
|
||||||
p+=2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reply */
|
|
||||||
tls_cork(ws->session);
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n");
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ws->config->banner) {
|
|
||||||
size = snprintf(msg, sizeof(msg), "<banner>%s</banner>", ws->config->banner);
|
|
||||||
if (size <= 0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
msg[0] = 0;
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size += (sizeof(SUCCESS_MSG_HEAD)-1) + (sizeof(SUCCESS_MSG_FOOT)-1);
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)size);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "Set-Cookie: webvpn=%s;Max-Age=%u\r\n", str_cookie, (unsigned)ws->config->cookie_validity);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "\r\n"SUCCESS_MSG_HEAD"%s"SUCCESS_MSG_FOOT, msg);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_uncork(ws->session);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auth_fail:
|
auth_fail:
|
||||||
tls_printf(ws->session,
|
tls_printf(ws->session,
|
||||||
@@ -480,16 +493,13 @@ auth_fail:
|
|||||||
|
|
||||||
int post_new_auth_handler(worker_st *ws, unsigned http_ver)
|
int post_new_auth_handler(worker_st *ws, unsigned http_ver)
|
||||||
{
|
{
|
||||||
int ret, size;
|
int ret;
|
||||||
struct http_req_st *req = &ws->req;
|
struct http_req_st *req = &ws->req;
|
||||||
const char* reason = "Authentication failed";
|
const char* reason = "Authentication failed";
|
||||||
char str_cookie[2*COOKIE_SIZE+1];
|
|
||||||
char * username = NULL;
|
char * username = NULL;
|
||||||
char * password = NULL;
|
char * password = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
unsigned int i;
|
|
||||||
struct cmd_auth_req_st areq;
|
struct cmd_auth_req_st areq;
|
||||||
char msg[MAX_BANNER_SIZE+32];
|
|
||||||
|
|
||||||
memset(&areq, 0, sizeof(areq));
|
memset(&areq, 0, sizeof(areq));
|
||||||
|
|
||||||
@@ -544,60 +554,7 @@ char msg[MAX_BANNER_SIZE+32];
|
|||||||
|
|
||||||
oclog(ws, LOG_INFO, "User '%s' logged in", ws->username);
|
oclog(ws, LOG_INFO, "User '%s' logged in", ws->username);
|
||||||
|
|
||||||
p = str_cookie;
|
return post_common_handler(ws, http_ver);;
|
||||||
for (i=0;i<sizeof(ws->cookie);i++) {
|
|
||||||
sprintf(p, "%.2x", (unsigned int)ws->cookie[i]);
|
|
||||||
p+=2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reply */
|
|
||||||
tls_cork(ws->session);
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n");
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ws->config->banner) {
|
|
||||||
size = snprintf(msg, sizeof(msg), "<banner>%s</banner>", ws->config->banner);
|
|
||||||
if (size <= 0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
msg[0] = 0;
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size += (sizeof(SUCCESS_MSG_HEAD)-1) + (sizeof(SUCCESS_MSG_FOOT)-1);
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)size);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "Set-Cookie: webvpn=%s;Max-Age=%u\r\n", str_cookie, (unsigned)ws->config->cookie_validity);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_printf(ws->session, "\r\n"SUCCESS_MSG_HEAD"%s"SUCCESS_MSG_FOOT, msg);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_uncork(ws->session);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ask_auth:
|
ask_auth:
|
||||||
return get_auth_handler(ws, http_ver);
|
return get_auth_handler(ws, http_ver);
|
||||||
|
|||||||
+114
-6
@@ -81,23 +81,128 @@ static int connect_handler(worker_st *ws);
|
|||||||
typedef int (*url_handler_fn)(worker_st*, unsigned http_ver);
|
typedef int (*url_handler_fn)(worker_st*, unsigned http_ver);
|
||||||
struct known_urls_st {
|
struct known_urls_st {
|
||||||
const char* url;
|
const char* url;
|
||||||
|
unsigned url_size;
|
||||||
url_handler_fn get_handler;
|
url_handler_fn get_handler;
|
||||||
url_handler_fn post_handler;
|
url_handler_fn post_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int get_config_handler(worker_st *ws, unsigned http_ver)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
oclog(ws, LOG_DEBUG, "requested config: %s", ws->req.url);
|
||||||
|
if (ws->config->xml_config_file == NULL) {
|
||||||
|
oclog(ws, LOG_INFO, "requested config but no config file is set");
|
||||||
|
tls_printf(ws->session, "HTTP/1.%u 404 Not found\r\n", http_ver);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = stat( ws->config->xml_config_file, &st);
|
||||||
|
if (ret == -1) {
|
||||||
|
oclog(ws, LOG_INFO, "cannot load config file '%s'", ws->config->xml_config_file);
|
||||||
|
tls_printf(ws->session, "HTTP/1.%u 404 Not found\r\n", http_ver);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_cork(ws->session);
|
||||||
|
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)st.st_size);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_uncork(ws->session);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_send_file(ws->session, ws->config->xml_config_file);
|
||||||
|
if (ret < 0) {
|
||||||
|
oclog(ws, LOG_ERR, "error sending file '%s': %s", ws->config->xml_config_file, gnutls_strerror(ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_cscot_handler(worker_st *ws, unsigned http_ver)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
oclog(ws, LOG_DEBUG, "requested CSCOT: %s", ws->req.url);
|
||||||
|
|
||||||
|
tls_cork(ws->session);
|
||||||
|
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "Connection: Keep-Alive\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#define MANIFEST "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<vpn rev=\"1.0\">\n" \
|
||||||
|
"</vpn>\n"
|
||||||
|
ret = tls_printf(ws->session, "Content-Length: %u\r\n\r\n", (unsigned)sizeof(MANIFEST)-1);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_puts(ws->session, MANIFEST);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = tls_uncork(ws->session);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LL(x,y,z) {x, sizeof(x)-1, y, z}
|
||||||
struct known_urls_st known_urls[] = {
|
struct known_urls_st known_urls[] = {
|
||||||
{"/", get_auth_handler, post_new_auth_handler},
|
LL("/", get_auth_handler, post_new_auth_handler),
|
||||||
{"/auth", get_auth_handler, post_old_auth_handler},
|
LL("/auth", get_auth_handler, post_old_auth_handler),
|
||||||
{NULL, NULL}
|
LL("/profiles", get_config_handler, NULL),
|
||||||
|
LL("/+CSCOT+/translation-table", get_cscot_handler, NULL),
|
||||||
|
{NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static url_handler_fn get_url_handler(const char* url)
|
static url_handler_fn get_url_handler(const char* url)
|
||||||
{
|
{
|
||||||
struct known_urls_st *p;
|
struct known_urls_st *p;
|
||||||
|
unsigned len = strlen(url);
|
||||||
|
|
||||||
p = known_urls;
|
p = known_urls;
|
||||||
do {
|
do {
|
||||||
if (p->url != NULL && strcmp(p->url, url)==0)
|
if (p->url != NULL && (
|
||||||
|
(len == p->url_size && strcmp(p->url, url)==0) ||
|
||||||
|
(len >= p->url_size && strncmp(p->url, url, p->url_size)==0 &&
|
||||||
|
(url[p->url_size] == '/' || url[p->url_size] == '?'))))
|
||||||
return p->get_handler;
|
return p->get_handler;
|
||||||
p++;
|
p++;
|
||||||
} while(p->url != NULL);
|
} while(p->url != NULL);
|
||||||
@@ -409,7 +514,7 @@ void vpn_server(struct worker_st* ws)
|
|||||||
do {
|
do {
|
||||||
ret = gnutls_handshake(session);
|
ret = gnutls_handshake(session);
|
||||||
} while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
|
} while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
|
||||||
GNUTLS_FATAL_ERR(ret);
|
GNUTLS_S_FATAL_ERR(session, ret);
|
||||||
|
|
||||||
oclog(ws, LOG_DEBUG, "TLS handshake completed");
|
oclog(ws, LOG_DEBUG, "TLS handshake completed");
|
||||||
|
|
||||||
@@ -988,7 +1093,10 @@ unsigned mtu_overhead, tls_mtu = 0;
|
|||||||
hsk_restart:
|
hsk_restart:
|
||||||
ret = gnutls_handshake(ws->dtls_session);
|
ret = gnutls_handshake(ws->dtls_session);
|
||||||
if (ret < 0 && gnutls_error_is_fatal(ret) != 0) {
|
if (ret < 0 && gnutls_error_is_fatal(ret) != 0) {
|
||||||
oclog(ws, LOG_ERR, "error in DTLS handshake: %s\n", gnutls_strerror(ret));
|
if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
|
||||||
|
oclog(ws, LOG_ERR, "error in DTLS handshake: %s: %s\n", gnutls_strerror(ret), gnutls_alert_get_name(gnutls_alert_get(ws->dtls_session)));
|
||||||
|
else
|
||||||
|
oclog(ws, LOG_ERR, "error in DTLS handshake: %s\n", gnutls_strerror(ret));
|
||||||
ws->udp_state = UP_DISABLED;
|
ws->udp_state = UP_DISABLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user