Commit 8b137a20 authored by Nikos Mavrogiannopoulos's avatar Nikos Mavrogiannopoulos Committed by Nikos Mavrogiannopoulos

Delay tun device creation until DTLS has been negotiated

Signed-off-by: default avatarNikos Mavrogiannopoulos <nmav@redhat.com>
parent 8b041c73
......@@ -971,7 +971,7 @@ int main(int argc, char **argv)
char *ip;
const char *compr = "";
char *proxy = getenv("https_proxy");
char *vpnc_script = NULL, *ifname = NULL;
char *vpnc_script = NULL;
const struct oc_ip_info *ip_info;
int autoproxy = 0;
int opt;
......@@ -989,9 +989,7 @@ int main(int argc, char **argv)
#ifndef _WIN32
struct sigaction sa;
struct utsname utsbuf;
uid_t uid = getuid();
int use_syslog = 0;
int script_tun = 0;
#endif
#ifdef ENABLE_NLS
......@@ -1033,6 +1031,8 @@ int main(int argc, char **argv)
#ifdef _WIN32
set_default_vpncscript();
#else
vpninfo->use_tun_script = 0;
vpninfo->uid = getuid();
if (!uname(&utsbuf)) {
free(vpninfo->localname);
vpninfo->localname = xstrdup(utsbuf.nodename);
......@@ -1053,11 +1053,11 @@ int main(int argc, char **argv)
use_syslog = 1;
break;
case 'S':
script_tun = 1;
vpninfo->use_tun_script = 1;
break;
case 'U': {
char *strend;
uid = strtol(config_arg, &strend, 0);
vpninfo->uid = strtol(config_arg, &strend, 0);
if (strend[0]) {
struct passwd *pw = getpwnam(config_arg);
if (!pw) {
......@@ -1065,7 +1065,7 @@ int main(int argc, char **argv)
config_arg);
exit(1);
}
uid = pw->pw_uid;
vpninfo->uid = pw->pw_uid;
}
break;
}
......@@ -1220,7 +1220,7 @@ int main(int argc, char **argv)
case 'h':
usage();
case 'i':
ifname = dup_config_arg();
vpninfo->ifname = dup_config_arg();
break;
case 'm': {
int mtu = atol(config_arg);
......@@ -1475,31 +1475,8 @@ int main(int argc, char **argv)
if (!vpnc_script)
vpnc_script = xstrdup(default_vpncscript);
#ifndef _WIN32
if (script_tun) {
if (openconnect_setup_tun_script(vpninfo, vpnc_script)) {
fprintf(stderr, _("Set up tun script failed\n"));
openconnect_vpninfo_free(vpninfo);
exit(1);
}
} else
#endif
if (openconnect_setup_tun_device(vpninfo, vpnc_script, ifname)) {
fprintf(stderr, _("Set up tun device failed\n"));
openconnect_vpninfo_free(vpninfo);
exit(1);
}
#ifndef _WIN32
if (uid != getuid()) {
if (setuid(uid)) {
fprintf(stderr, _("Failed to set uid %ld\n"),
(long)uid);
openconnect_vpninfo_free(vpninfo);
exit(1);
}
}
#endif
STRDUP(vpninfo->vpnc_script, vpnc_script);
if (vpninfo->dtls_state != DTLS_DISABLED &&
openconnect_setup_dtls(vpninfo, 60))
......@@ -1523,7 +1500,7 @@ int main(int argc, char **argv)
compr = " + lz4";
}
vpn_progress(vpninfo, PRG_INFO,
_("Connected %s as %s%s%s, using %s%s\n"), openconnect_get_ifname(vpninfo),
_("Connected as %s%s%s, using %s%s\n"),
ip_info->addr?:"",
(ip_info->netmask6 && ip_info->addr) ? " + " : "",
ip_info->netmask6 ? : "",
......
......@@ -45,6 +45,12 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
struct pkt *this;
int work_done = 0;
if (!vpninfo->tun_is_up) {
/* no tun yet, clear any queued packets */
while ((this = dequeue_packet(&vpninfo->incoming_queue)));
return 0;
}
if (read_fd_monitored(vpninfo, tun)) {
struct pkt *out_pkt = vpninfo->tun_pkt;
while (1) {
......@@ -95,6 +101,37 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
return work_done;
}
static int setup_tun_device(struct openconnect_info *vpninfo)
{
int ret;
#ifndef _WIN32
if (vpninfo->use_tun_script) {
ret = openconnect_setup_tun_script(vpninfo, vpninfo->vpnc_script);
if (ret) {
fprintf(stderr, _("Set up tun script failed\n"));
return ret;
}
} else
#endif
ret = openconnect_setup_tun_device(vpninfo, vpninfo->vpnc_script, vpninfo->ifname);
if (ret) {
fprintf(stderr, _("Set up tun device failed\n"));
return ret;
}
#ifndef _WIN32
if (vpninfo->uid != getuid()) {
if (setuid(vpninfo->uid)) {
fprintf(stderr, _("Failed to set uid %ld\n"),
(long)vpninfo->uid);
return -EPERM;
}
}
#endif
return 0;
}
/* Return value:
* = 0, when successfully paused (may call again)
* = -EINTR, if aborted locally via OC_CMD_CANCEL
......@@ -109,6 +146,7 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,
{
int ret = 0;
vpninfo->tun_is_up = 0;
vpninfo->reconnect_timeout = reconnect_timeout;
vpninfo->reconnect_interval = reconnect_interval;
......@@ -119,7 +157,7 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,
while (!vpninfo->quit_reason) {
int did_work = 0;
int timeout = INT_MAX;
int timeout;
#ifdef _WIN32
HANDLE events[4];
int nr_events = 0;
......@@ -128,11 +166,40 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,
fd_set rfds, wfds, efds;
#endif
/* If tun is not up, loop more often to detect
* a DTLS timeout (due to a firewall block) as soon. */
if (vpninfo->tun_is_up)
timeout = INT_MAX;
else
timeout = 1000;
if (vpninfo->dtls_state > DTLS_DISABLED) {
/* Postpone tun device creation after DTLS is connected so
* we have a better knowledge of the link MTU. We also
* force the creation if DTLS enters sleeping mode - i.e.,
* we failed to connect on time. */
if (vpninfo->tun_is_up == 0 && (vpninfo->dtls_state == DTLS_CONNECTED ||
vpninfo->dtls_state == DTLS_SLEEPING)) {
ret = setup_tun_device(vpninfo);
if (ret) {
break;
}
vpninfo->tun_is_up = 1;
}
ret = vpninfo->proto.udp_mainloop(vpninfo, &timeout);
if (vpninfo->quit_reason)
break;
did_work += ret;
} else if (vpninfo->tun_is_up == 0) {
/* No DTLS - setup TUN device unconditionally */
ret = setup_tun_device(vpninfo);
if (ret)
break;
vpninfo->tun_is_up = 1;
}
ret = vpninfo->proto.tcp_mainloop(vpninfo, &timeout);
......@@ -156,6 +223,7 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,
}
break;
}
if (vpninfo->got_pause_cmd) {
/* close all connections and wait for the user to call
openconnect_mainloop() again */
......
......@@ -536,8 +536,14 @@ struct openconnect_info {
char *dtls_cipher;
char *vpnc_script;
#ifndef _WIN32
uid_t uid;
#endif
int tun_is_up; /* whether the tun device is setup */
int use_tun_script;
int script_tun;
char *ifname;
char *cmd_ifname;
int reqmtu, basemtu;
const char *banner;
......@@ -1000,7 +1006,7 @@ static inline int strprefix_match(const char *str, int len, const char *match)
}
#define STRDUP(res, arg) \
do { \
if (res != arg) { \
free(res); \
if (arg) { \
res = strdup(arg); \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment