diff --git a/src/config.c b/src/config.c index 0888ee9d..cae5de98 100644 --- a/src/config.c +++ b/src/config.c @@ -116,6 +116,7 @@ static struct cfg_options available_options[] = { { .name = "run-as-group", .type = OPTION_STRING, .mandatory = 0 }, { .name = "device", .type = OPTION_STRING, .mandatory = 1 }, { .name = "cgroup", .type = OPTION_STRING, .mandatory = 0 }, + { .name = "proxy-url", .type = OPTION_STRING, .mandatory = 0 }, { .name = "ipv4-network", .type = OPTION_STRING, .mandatory = 0 }, { .name = "ipv4-netmask", .type = OPTION_STRING, .mandatory = 0 }, @@ -526,6 +527,7 @@ unsigned force_cert_auth; READ_STATIC_STRING("device", config->network.name); READ_STRING("cgroup", config->cgroup); + READ_STRING("proxy-url", config->proxy_url); READ_STRING("ipv4-network", config->network.ipv4); READ_STRING("ipv4-netmask", config->network.ipv4_netmask); @@ -743,6 +745,7 @@ unsigned i; DEL(config->chroot_dir); DEL(config->connect_script); DEL(config->disconnect_script); + DEL(config->proxy_url); DEL(config->network.ipv4); DEL(config->network.ipv4_netmask); diff --git a/src/ipc.proto b/src/ipc.proto index 55357d9e..d38c2484 100644 --- a/src/ipc.proto +++ b/src/ipc.proto @@ -27,6 +27,7 @@ message auth_reply_msg optional bytes session_id = 3; optional string vname = 4; optional string user_name = 5; + optional string group_name = 25; optional string msg = 6; /* the ips of the tun device */ @@ -46,6 +47,7 @@ message auth_reply_msg repeated string dns = 22; repeated string nbns = 23; optional bool no_udp = 24 [default = false]; + } /* RESUME_FETCH_REQ + RESUME_DELETE_REQ */ diff --git a/src/main-auth.c b/src/main-auth.c index 57666b16..1fdf6754 100644 --- a/src/main-auth.c +++ b/src/main-auth.c @@ -71,6 +71,7 @@ int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc, msg.vname = proc->tun_lease.name; msg.user_name = proc->username; + msg.group_name = proc->groupname; if (proc->ipv4 && proc->ipv4->rip_len > 0) { msg.ipv4 = human_addr2((struct sockaddr*)&proc->ipv4->rip, proc->ipv4->rip_len, diff --git a/src/ocserv-args.def b/src/ocserv-args.def index f2542cce..a22c17b9 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -392,6 +392,11 @@ route = 192.168.5.0/255.255.255.0 #route-add-cmd = "ip route add %R dev %D" #route-del-cmd = "ip route delete %R dev %D" +# This option allows to forward a proxy. The special strings '%U' +# and '%G', if present will be replaced by the username and group name. +#proxy-url = http://example.com/ +#proxy-url = http://example.com/%U/ + # # The following options are for (experimental) AnyConnect client # compatibility. diff --git a/src/str.c b/src/str.c index ebb55e50..8204e892 100644 --- a/src/str.c +++ b/src/str.c @@ -127,3 +127,41 @@ int str_append_str(str_st * dest, const char *src) return ret; } +int str_replace_str(str_st *str, const char *what, const char *with) +{ + uint8_t *p, *final; + unsigned what_len, final_len; + int ret; + + what_len = strlen(what); + + p = memmem(str->data, str->length, what, what_len); + if (p == NULL) + return 0; + + p += what_len; + final_len = str->length - (ptrdiff_t)(p-str->data); + + final = talloc_memdup(str->allocd, p, final_len); + if (final == NULL) + return -1; + + str->length -= final_len + what_len; + + ret = str_append_str(str, with); + if (ret < 0) { + talloc_free(final); + return ret; + } + + ret = str_append_data(str, final, final_len); + talloc_free(final); + + if (ret < 0) { + return ret; + } +fprintf(stderr, "str[%d]: %s\n", str->length, str->data); + /* allow multiple replacements */ + return str_replace_str(str, what, with); +} + diff --git a/src/str.h b/src/str.h index fa0d5a77..79808002 100644 --- a/src/str.h +++ b/src/str.h @@ -54,6 +54,7 @@ inline static void str_reset(str_st * buf) } int str_append_str(str_st *, const char *str); +int str_replace_str(str_st *, const char *what, const char *with); int str_append_data(str_st *, const void *data, size_t data_size); int str_append_size(str_st *, size_t data_size); int str_append_data_prefix1(str_st *, const void *data, size_t data_size); diff --git a/src/vpn.h b/src/vpn.h index 68e908a1..bb28c9e5 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -256,6 +256,7 @@ struct cfg_st { char *disconnect_script; char *cgroup; + char *proxy_url; #ifdef ANYCONNECT_CLIENT_COMPAT char *xml_config_file; diff --git a/src/worker-auth.c b/src/worker-auth.c index 21dee4be..39d3a3e7 100644 --- a/src/worker-auth.c +++ b/src/worker-auth.c @@ -465,6 +465,13 @@ static int recv_cookie_auth_reply(worker_st * ws) snprintf(ws->username, sizeof(ws->username), "%s", msg->user_name); + if (msg->group_name != NULL) { + snprintf(ws->groupname, sizeof(ws->groupname), "%s", + msg->group_name); + } else { + ws->groupname[0] = 0; + } + memcpy(ws->session_id, msg->session_id.data, msg->session_id.len); diff --git a/src/worker-vpn.c b/src/worker-vpn.c index 7ae498a6..f94121cd 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -1299,6 +1299,33 @@ static int tun_mainloop(struct worker_st *ws, struct timespec *tnow) return 0; } +static +char *replace_vals(worker_st *ws, const char *txt) +{ + str_st str; + int ret; + + str_init(&str, ws); + + ret = str_append_str(&str, txt); + if (ret < 0) + return NULL; + + ret = str_replace_str(&str, "%U", ws->username); + if (ret < 0) { + str_clear(&str); + return NULL; + } + + ret = str_replace_str(&str, "%G", ws->groupname); + if (ret < 0) { + str_clear(&str); + return NULL; + } + + return (char*)str.data; +} + /* connect_handler: * @ws: an initialized worker structure * @@ -1593,6 +1620,17 @@ static int connect_handler(worker_st * ws) SEND_ERR(ret); } + if (ws->config->proxy_url != NULL) { + const char *url = replace_vals(ws, ws->config->proxy_url); + if (url != NULL) { + ret = + tls_printf(ws->session, "X-CSTP-MSIE-Proxy-Pac-URL: %s\r\n", + url); + SEND_ERR(ret); + talloc_free(url); + } + } + ret = tls_puts(ws->session, "X-CSTP-Session-Timeout: none\r\n" "X-CSTP-Disconnected-Timeout: none\r\n" "X-CSTP-Keep: true\r\n"