From 10246b78c41566978b86dbc1c96cd29086159a64 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 31 May 2013 17:29:52 +0200 Subject: [PATCH] Allow downloading raw files from 1/binaries --- doc/sample.config | 5 +- src/Makefile.am | 1 + src/config.c | 1 + src/ocserv-args.c | 10 ++-- src/ocserv-args.def | 4 ++ src/ocserv-args.h | 6 +- src/vpn.h | 1 + src/worker-extras.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ src/worker-vpn.c | 23 +++++--- src/worker.h | 3 + 10 files changed, 177 insertions(+), 17 deletions(-) create mode 100644 src/worker-extras.c diff --git a/doc/sample.config b/doc/sample.config index 1807985d..7cc1148c 100644 --- a/doc/sample.config +++ b/doc/sample.config @@ -175,7 +175,10 @@ route = 192.168.1.0/255.255.255.0 # Client profile xml. A sample file exists in doc/profile.xml. # This file must be accessible from inside the worker's chroot. # The profile is ignored by the openconnect client. -#user-profile = profile.xml +user-profile = profile.xml + +# Binary files' location. Must be within any chroot environment. +binary-files = ./binaries/ # Unless set to false it is required for clients to present their # certificate even if they are authenticating via a previously granted diff --git a/src/Makefile.am b/src/Makefile.am index 5e693b0b..ecbd4b59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,6 +16,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \ http-parser/http_parser.c ipc.h cookies.c worker-tun.c main-misc.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 \ + worker-extras.c \ main-user.c cookies-gdbm.c cookies-hash.c worker-misc.c setproctitle.h \ setproctitle.c worker-privs.c plain.c plain.h common.h common.c \ sec-mod.c sec-mod.h script-list.h system.c system.h icmp-ping.c icmp-ping.h \ diff --git a/src/config.c b/src/config.c index cc4124c9..5bd310a3 100644 --- a/src/config.c +++ b/src/config.c @@ -165,6 +165,7 @@ unsigned j; READ_STRING("pin-file", config->pin_file, 0); READ_STRING("srk-pin-file", config->srk_pin_file, 0); #ifdef ANYCONNECT_CLIENT_COMPAT + READ_STRING("binary-files", config->binary_path, 0); READ_STRING("user-profile", config->xml_config_file, 0); #endif diff --git a/src/ocserv-args.c b/src/ocserv-args.c index c9b27c53..fc4e7acf 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 May 23, 2013 at 04:06:00 PM by AutoGen 5.17.3 + * It has been AutoGen-ed May 31, 2013 at 04:46:50 PM by AutoGen 5.17.3 * From the definitions ocserv-args.def * and the template file options * @@ -63,7 +63,7 @@ extern FILE * option_usage_fp; * static const strings for ocserv options */ static char const ocserv_opt_strs[1795] = -/* 0 */ "ocserv 0.1.2\n" +/* 0 */ "ocserv 0.1.3\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 GNU General Public License,\n" @@ -107,7 +107,7 @@ static char const ocserv_opt_strs[1795] = "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" -/* 1707 */ "ocserv 0.1.2\0" +/* 1707 */ "ocserv 0.1.3\0" /* 1720 */ "Usage: ocserv [options] -c [config]\n" "ocserv --help for usage instructions.\n"; @@ -562,7 +562,7 @@ static void bogus_function(void) { translate option names. */ /* referenced via ocservOptions.pzCopyright */ - puts(_("ocserv 0.1.2\n\ + puts(_("ocserv 0.1.3\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 GNU General Public License,\n\ @@ -617,7 +617,7 @@ process and obtain a networking (tun) device and IP from a configurable\n\ pool of addresses.\n")); /* referenced via ocservOptions.pzFullVersion */ - puts(_("ocserv 0.1.2")); + puts(_("ocserv 0.1.3")); /* referenced via ocservOptions.pzFullUsage */ puts(_("<<>>")); diff --git a/src/ocserv-args.def b/src/ocserv-args.def index 4b25b24a..7f473e32 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -265,6 +265,10 @@ route = 192.168.5.0/255.255.255.0 # It is not used by the openconnect client. #user-profile = /path/to/file.xml +# Binary files that may be downloaded by the CISCO client. Must +# be within any chroot environment. +binary-files = /path/to/binaries + # Unless set to false it is required for clients to present their # certificate even if they are authenticating via a previously granted # cookie. Legacy CISCO clients do not do that, and thus this option diff --git a/src/ocserv-args.h b/src/ocserv-args.h index 428826fa..d6be226e 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 May 23, 2013 at 04:06:00 PM by AutoGen 5.17.3 + * It has been AutoGen-ed May 31, 2013 at 04:46:49 PM by AutoGen 5.17.3 * From the definitions ocserv-args.def * and the template file options * @@ -77,9 +77,9 @@ typedef enum { /** count of all options for ocserv */ #define OPTION_CT 7 /** ocserv version */ -#define OCSERV_VERSION "0.1.2" +#define OCSERV_VERSION "0.1.3" /** Full ocserv version text */ -#define OCSERV_FULL_VERSION "ocserv 0.1.2" +#define OCSERV_FULL_VERSION "ocserv 0.1.3" /** * Interface defines for all options. Replace "n" with the UPPER_CASED diff --git a/src/vpn.h b/src/vpn.h index 017bb861..0acaf364 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -114,6 +114,7 @@ struct cfg_st { char *disconnect_script; #ifdef ANYCONNECT_CLIENT_COMPAT + char *binary_path; /* a path to binary files */ char *xml_config_file; char *xml_config_hash; char *cert_hash; diff --git a/src/worker-extras.c b/src/worker-extras.c new file mode 100644 index 00000000..5a6a8b3a --- /dev/null +++ b/src/worker-extras.c @@ -0,0 +1,140 @@ +/* + * 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 "ipc.h" +#include +#include +#include + +const char empty_msg[] = "\n"; + +int get_empty_handler(worker_st *ws, unsigned http_ver) +{ +int ret; + + 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/html\r\n"); + if (ret < 0) + return -1; + + ret = tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned int)sizeof(empty_msg)-1); + if (ret < 0) + return -1; + + ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); + if (ret < 0) + return -1; + + ret = tls_puts(ws->session, "\r\n"); + if (ret < 0) + return -1; + + ret = tls_send(ws->session, empty_msg, sizeof(empty_msg)-1); + if (ret < 0) + return -1; + + ret = tls_uncork(ws->session); + if (ret < 0) + return -1; + + return 0; +} + +int get_file_handler(worker_st *ws, unsigned http_ver) +{ +int ret; +const char* file; +char path[_POSIX_PATH_MAX]; +struct stat st; + + if (ws->req.url == NULL) + return -1; + + file = strrchr(ws->req.url, '/'); + if (file == NULL) + return -1; + file++; + + snprintf(path, sizeof(path), "%s/%s", ws->config->binary_path, file); + + 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: application/x-executable\r\n"); + if (ret < 0) + return -1; + + if (stat(path, &st) < 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, "X-Transcend-Version: 1\r\n"); + 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, path); + if (ret < 0) + return -1; + + oclog(ws, LOG_DEBUG, "sent file %s", path); + + return 0; +} + diff --git a/src/worker-vpn.c b/src/worker-vpn.c index 4f4f69b6..19295ce5 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -61,7 +61,7 @@ #define DPD_MAX_TRIES 3 /* HTTP requests prior to disconnection */ -#define MAX_HTTP_REQUESTS 8 +#define MAX_HTTP_REQUESTS 16 static int terminate = 0; static int parse_cstp_data(struct worker_st* ws, uint8_t* buf, size_t buf_size, time_t); @@ -85,6 +85,7 @@ typedef int (*url_handler_fn)(worker_st*, unsigned http_ver); struct known_urls_st { const char* url; unsigned url_size; + unsigned partial_match; url_handler_fn get_handler; url_handler_fn post_handler; }; @@ -189,7 +190,8 @@ int ret; #endif -#define LL(x,y,z) {x, sizeof(x)-1, y, z} +#define LL(x,y,z) {x, sizeof(x)-1, 0, y, z} +#define LL_DIR(x,y,z) {x, sizeof(x)-1, 1, y, z} const static struct known_urls_st known_urls[] = { LL("/", get_auth_handler, post_auth_handler), LL("/auth", get_auth_handler, post_auth_handler), @@ -197,8 +199,12 @@ const static struct known_urls_st known_urls[] = { LL("/1/index.html", get_auth_handler, post_auth_handler), LL("/profiles", get_config_handler, NULL), LL("/+CSCOT+/translation-table", get_cscot_handler, NULL), + LL("/1/Windows", get_empty_handler, NULL), + LL("/1/Linux_64", get_empty_handler, NULL), + LL("/1/Linux_32", get_empty_handler, NULL), + LL_DIR("/1/binaries/", get_file_handler, NULL), #endif - {NULL, 0, NULL, NULL} + {NULL, 0, 0, NULL, NULL} }; static url_handler_fn get_url_handler(const char* url) @@ -208,11 +214,12 @@ unsigned len = strlen(url); p = known_urls; do { - 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; + if (p->url != NULL) { + if ((len == p->url_size && strcmp(p->url, url)==0) || + (len >= p->url_size && strncmp(p->url, url, p->url_size)==0 && + (p->partial_match != 0 || url[p->url_size] == '/' || url[p->url_size] == '?'))) + return p->get_handler; + } p++; } while(p->url != NULL); diff --git a/src/worker.h b/src/worker.h index bef7d2d2..a78f4b4a 100644 --- a/src/worker.h +++ b/src/worker.h @@ -120,6 +120,9 @@ int auth_cookie(worker_st *ws, void* cookie, size_t cookie_size); int get_auth_handler(worker_st *server, unsigned http_ver); int post_auth_handler(worker_st *server, unsigned http_ver); +int get_empty_handler(worker_st *server, unsigned http_ver); +int get_file_handler(worker_st *ws, unsigned http_ver); + void set_resume_db_funcs(gnutls_session_t);