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
|
||||
-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
|
||||
|
||||
@@ -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 = "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.
|
||||
#listen-host = [IP|HOSTNAME]
|
||||
|
||||
@@ -16,8 +24,8 @@ max-clients = 16
|
||||
max-same-clients = 2
|
||||
|
||||
# TCP and UDP port number
|
||||
tcp-port = 3333
|
||||
udp-port = 3333
|
||||
tcp-port = 443
|
||||
udp-port = 443
|
||||
|
||||
# Keepalive in seconds
|
||||
keepalive = 32400
|
||||
|
||||
+1
-1
@@ -28,4 +28,4 @@ ocserv_LDADD += $(LIBGNUTLS_LIBS) $(GDBM_LIBS) $(PAM_LIBS) $(LIBUTIL) \
|
||||
$(LIBSECCOMP) $(LIBWRAP)
|
||||
|
||||
ocserv-args.c ocserv-args.h: $(srcdir)/ocserv-args.def
|
||||
-@AUTOGEN@ $<
|
||||
@AUTOGEN@ $<
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <autoopts/options.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
#define DEFAULT_CFG_FILE "/etc/ocserv.conf"
|
||||
|
||||
@@ -146,6 +147,7 @@ unsigned j;
|
||||
READ_STRING("server-key", config->key, 1);
|
||||
READ_STRING("pin-file", config->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("crl", config->crl, 0);
|
||||
@@ -208,6 +210,7 @@ unsigned j;
|
||||
READ_MULTI_LINE("route", config->network.routes, config->network.routes_size, 0);
|
||||
}
|
||||
|
||||
|
||||
/* sanity checks on config */
|
||||
static void check_cfg( struct cfg_st *config)
|
||||
{
|
||||
@@ -231,6 +234,14 @@ static void check_cfg( struct cfg_st *config)
|
||||
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)
|
||||
config->keepalive = 3600;
|
||||
|
||||
@@ -280,6 +291,9 @@ void reload_cfg_file(struct cfg_st* config)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
DEL(config->xml_config_file);
|
||||
DEL(config->xml_config_hash);
|
||||
DEL(config->cert_hash);
|
||||
DEL(config->banner);
|
||||
DEL(config->name);
|
||||
DEL(config->cert);
|
||||
|
||||
+6
-4
@@ -485,7 +485,7 @@ 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_reinit(s);
|
||||
tls_global_init_certs(s);
|
||||
reload_conf = 0;
|
||||
}
|
||||
|
||||
@@ -559,6 +559,9 @@ int main(int argc, char** argv)
|
||||
signal(SIGCHLD, handle_children);
|
||||
signal(SIGALRM, handle_alarm);
|
||||
|
||||
/* Initialize GnuTLS */
|
||||
tls_global_init(&s);
|
||||
|
||||
/* load configuration */
|
||||
ret = cmd_parser(argc, argv, &config);
|
||||
if (ret < 0) {
|
||||
@@ -601,11 +604,10 @@ int main(int argc, char** argv)
|
||||
allow_severity = LOG_DAEMON|LOG_INFO;
|
||||
deny_severity = LOG_DAEMON|LOG_WARNING;
|
||||
#endif
|
||||
memset(&ws, 0, sizeof(ws));
|
||||
|
||||
/* Initialize GnuTLS */
|
||||
tls_global_init(&s);
|
||||
|
||||
memset(&ws, 0, sizeof(ws));
|
||||
tls_global_init_certs(&s);
|
||||
|
||||
if (config.foreground == 0) {
|
||||
if (daemon(0, 0) == -1) {
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* and the template file options
|
||||
*
|
||||
@@ -66,7 +66,7 @@ extern FILE * option_usage_fp;
|
||||
* ocserv option static const strings
|
||||
*/
|
||||
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"
|
||||
"This is free software. It is licensed for use, modification and\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"
|
||||
/* 1165 */ "version\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"
|
||||
/* 1279 */ "openconnect-devel@lists.infradead.org\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"
|
||||
"process and obtain a networking (tun) device and IP from a configurable\n"
|
||||
"pool of addresses.\n\0"
|
||||
/* 1752 */ "ocserv 0.0.1\0"
|
||||
/* 1752 */ "ocserv 0.0.2\0"
|
||||
/* 1765 */ "Usage: ocserv [options] -c [config]\n"
|
||||
"ocserv --help for usage instructions.\n";
|
||||
|
||||
|
||||
@@ -82,6 +82,11 @@ auth = "pam"
|
||||
# A banner to be displayed on clients
|
||||
#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.
|
||||
#listen-host = [IP|HOSTNAME]
|
||||
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* and the template file options
|
||||
*
|
||||
@@ -76,8 +76,8 @@ typedef enum {
|
||||
} teOptIndex;
|
||||
|
||||
#define OPTION_CT 7
|
||||
#define OCSERV_VERSION "0.0.1"
|
||||
#define OCSERV_FULL_VERSION "ocserv 0.0.1"
|
||||
#define OCSERV_VERSION "0.0.2"
|
||||
#define OCSERV_FULL_VERSION "ocserv 0.0.2"
|
||||
|
||||
/*
|
||||
* Interface defines for all options. Replace "n" with the UPPER_CASED
|
||||
|
||||
+64
-7
@@ -19,6 +19,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <gnutls/pkcs11.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
@@ -333,25 +334,24 @@ void tls_global_init(main_server_st* s)
|
||||
int ret;
|
||||
|
||||
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);
|
||||
|
||||
tls_global_reinit(s);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* reload key files etc. */
|
||||
void tls_global_reinit(main_server_st* s)
|
||||
void tls_global_init_certs(main_server_st* s)
|
||||
{
|
||||
int ret;
|
||||
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)
|
||||
gnutls_certificate_free_credentials(s->creds.xcred);
|
||||
|
||||
@@ -468,3 +468,60 @@ int tls_uncork(gnutls_session_t session)
|
||||
return 0;
|
||||
#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);
|
||||
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);
|
||||
|
||||
#define GNUTLS_FATAL_ERR(x) \
|
||||
if (x < 0 && gnutls_error_is_fatal (x) != 0) { \
|
||||
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 \
|
||||
fprintf(stderr, "GnuTLS error (at %s:%d): %s\n", __FILE__, __LINE__, gnutls_strerror(x)); \
|
||||
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_fatal_close(gnutls_session_t session,
|
||||
@@ -66,5 +79,6 @@ typedef struct
|
||||
|
||||
void tls_cache_init(hash_db_st** db);
|
||||
void tls_cache_deinit(hash_db_st* db);
|
||||
void *calc_sha1_hash(char* file, unsigned cert);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -60,6 +60,8 @@ struct cfg_st {
|
||||
char *pin_file;
|
||||
char *srk_pin_file;
|
||||
char *cert;
|
||||
char *cert_hash;
|
||||
|
||||
char *key;
|
||||
char *ca;
|
||||
char *crl;
|
||||
@@ -88,6 +90,9 @@ struct cfg_st {
|
||||
char *connect_script;
|
||||
char *disconnect_script;
|
||||
|
||||
char *xml_config_file;
|
||||
char *xml_config_hash;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
|
||||
+72
-115
@@ -341,19 +341,84 @@ struct cmd_auth_cookie_req_st areq;
|
||||
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 ret, size;
|
||||
int ret;
|
||||
struct http_req_st *req = &ws->req;
|
||||
const char* reason = "Authentication failed";
|
||||
char str_cookie[2*COOKIE_SIZE+1];
|
||||
char * username = NULL;
|
||||
char * password = NULL;
|
||||
char *p;
|
||||
unsigned int i;
|
||||
struct cmd_auth_req_st areq;
|
||||
char msg[MAX_BANNER_SIZE+32];
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
return post_common_handler(ws, http_ver);;
|
||||
|
||||
auth_fail:
|
||||
tls_printf(ws->session,
|
||||
@@ -480,16 +493,13 @@ auth_fail:
|
||||
|
||||
int post_new_auth_handler(worker_st *ws, unsigned http_ver)
|
||||
{
|
||||
int ret, size;
|
||||
int ret;
|
||||
struct http_req_st *req = &ws->req;
|
||||
const char* reason = "Authentication failed";
|
||||
char str_cookie[2*COOKIE_SIZE+1];
|
||||
char * username = NULL;
|
||||
char * password = NULL;
|
||||
char *p;
|
||||
unsigned int i;
|
||||
struct cmd_auth_req_st areq;
|
||||
char msg[MAX_BANNER_SIZE+32];
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
return post_common_handler(ws, http_ver);;
|
||||
|
||||
ask_auth:
|
||||
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);
|
||||
struct known_urls_st {
|
||||
const char* url;
|
||||
unsigned url_size;
|
||||
url_handler_fn get_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[] = {
|
||||
{"/", get_auth_handler, post_new_auth_handler},
|
||||
{"/auth", get_auth_handler, post_old_auth_handler},
|
||||
{NULL, NULL}
|
||||
LL("/", get_auth_handler, post_new_auth_handler),
|
||||
LL("/auth", get_auth_handler, post_old_auth_handler),
|
||||
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)
|
||||
{
|
||||
struct known_urls_st *p;
|
||||
unsigned len = strlen(url);
|
||||
|
||||
p = known_urls;
|
||||
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;
|
||||
p++;
|
||||
} while(p->url != NULL);
|
||||
@@ -409,7 +514,7 @@ void vpn_server(struct worker_st* ws)
|
||||
do {
|
||||
ret = gnutls_handshake(session);
|
||||
} 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");
|
||||
|
||||
@@ -988,7 +1093,10 @@ unsigned mtu_overhead, tls_mtu = 0;
|
||||
hsk_restart:
|
||||
ret = gnutls_handshake(ws->dtls_session);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user