[GIT PULL] DTLS and other improvements to openconnect
David Woodhouse
dwmw2 at infradead.org
Mon Feb 3 10:48:29 EST 2014
On Mon, 2014-02-03 at 15:34 +0100, Nikos Mavrogiannopoulos wrote:
> On Mon, Feb 3, 2014 at 2:41 PM, David Woodhouse <dwmw2 at infradead.org> wrote:
> >> Still the most important addition is the support for AES-GCM, which is
> >> not only better to AES-CBC due to side-channels, but is also more
> >> UDP-friendly as it requires no padding and has a shorter nonce.
> >> They are available from:
> >> git://gitorious.org/openconnect-x/openconnect-x.git privacy-improvements
> > Please add the --pfs option to the man page too.
>
> Updated.
>
> > And shouldn't it affect
> > the DTLS setup too?
>
> The DTLS channel's key depends on a key which has been established
> with PFS, so if the server does not save the session keys somewhere,
> it is ok.
>
> > It probably also wants an openconnect_set_pfs()
> > function in the library, since we now support actually making
> > connections from the library too?
>
> Added in a followup commit as well as its JNI counterpart.
http://www.angryflower.com/itsits.gif (in the commit comment) :)
Could also do with an update to www/changelog.xml please. Sorry, I
should have noticed that before.
Btw I also looked at your outstanding win32 patch. Here's what I have so
far, which does at least build. I didn't need to use your Makefile; on
Fedora just installing mingw32-gnutls mingw32-libxml2 mingw32-p11-kit
and mingw32-zlib, then using 'mingw32-configure' seemed to suffice.
It builds, and then fails to connect (I was just uaing --authenticate)
because the command socket is non-blocking. Could do with cleaning up
into self-contained commits (for example, *one* commit adding
closesocket(), *one* commit switching to send/recv, etc...
The short option string passed to getopt_long() will also need fixing.
diff --git a/auth.c b/auth.c
index 5e866e0..f9249b9 100644
--- a/auth.c
+++ b/auth.c
@@ -25,8 +25,10 @@
*/
#include <stdio.h>
-#include <netdb.h>
-#include <unistd.h>
+#ifndef _WIN32
+# include <netdb.h>
+# include <unistd.h>
+#endif
#include <fcntl.h>
#include <time.h>
#include <string.h>
diff --git a/compat.c b/compat.c
index acb97d6..dcfdcf8 100644
--- a/compat.c
+++ b/compat.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <stdarg.h>
+#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
@@ -164,3 +165,33 @@ char *openconnect__strcasestr(const char *haystack, const char *needle)
return NULL;
}
#endif
+
+#ifndef HAVE_SETENV
+int openconnect__setenv(const char *name, const char *value, int overwrite)
+{
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%s=%s", name, value);
+ putenv(buf);
+ return 0;
+}
+#endif
+
+#ifndef HAVE_UNSETENV
+void openconnect__unsetenv(const char *name)
+{
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%s=", name);
+ putenv(buf);
+}
+#endif
+
+#ifndef HAVE_INET_ATON
+int
+openconnect__inet_aton(const char *cp, struct in_addr *addr)
+{
+ addr->s_addr = inet_addr(cp);
+ return (addr->s_addr == 0xffffffff) ? 0 : 1;
+}
+#endif
diff --git a/configure.ac b/configure.ac
index efb90f0..a6d9d8d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,6 +14,12 @@ AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
AC_PREREQ([2.60], [], [AC_SUBST([localedir], ['$(datadir)/locale'])])
+case "$host" in
+ *mingw32* | *mingw64*)
+ have_win=yes
+ ;;
+esac
+
# Upstream's pkg.m4 (since 0.27) offers this now, but define our own
# compatible version in case the local version of pkgconfig isn't new enough.
# https://bugs.freedesktop.org/show_bug.cgi?id=48743
@@ -92,6 +98,7 @@ case $host_os in
;;
esac
+AC_CHECK_FUNC(pipe2, [AC_DEFINE(HAVE_PIPE2, 1)], [])
AC_CHECK_FUNC(fdevname_r, [AC_DEFINE(HAVE_FDEVNAME_R, 1)], [])
AC_CHECK_FUNC(getline, [AC_DEFINE(HAVE_GETLINE, 1)], [symver_getline="openconnect__getline;"])
AC_CHECK_FUNC(strcasestr, [AC_DEFINE(HAVE_STRCASESTR, 1)], [])
@@ -141,10 +148,22 @@ AS_COMPILER_FLAGS(WFLAGS,
-Wwrite-strings")
AC_SUBST(WFLAGS, [$WFLAGS])
-AC_CHECK_FUNC(socket, [], AC_CHECK_LIB(socket, socket, [], AC_ERROR(Cannot find socket() function)))
-AC_CHECK_FUNC(inet_aton, [], AC_CHECK_LIB(nsl, inet_aton, [], AC_ERROR(Cannot find inet_aton() function)))
+if test "$have_win" = yes;then
+ LIBS="$LIBS -lws2_32"
+ AC_SUBST([HAVE_SOCKET], 1)
+ AC_SUBST([INET_ATON], 1)
+else
+ AC_CHECK_FUNC(socket, [], AC_CHECK_LIB(socket, socket, [], AC_ERROR(Cannot find socket() function)))
+ AC_CHECK_FUNC(inet_aton, [], AC_CHECK_LIB(nsl, inet_aton, [], AC_ERROR(Cannot find inet_aton() function)))
+fi
AC_CHECK_FUNC(__android_log_vprint, [], AC_CHECK_LIB(log, __android_log_vprint, [], []))
+AC_CHECK_FUNC(setenv, [AC_DEFINE(HAVE_SETENV, 1)], [symver_setenv="openconnect__setenv;"])
+AC_CHECK_FUNC(unsetenv, [AC_DEFINE(HAVE_UNSETENV, 1)], [symver_unsetenv="openconnect__unsetenv;"])
+
+AC_CHECK_FUNCS([asprintf mmap getpwnam fork fcntl sigaction inet_aton])
+AC_CHECK_HEADERS([sys/utsname.h termios.h poll.h sys/select.h])
+
AC_ENABLE_SHARED
AC_DISABLE_STATIC
diff --git a/cstp.c b/cstp.c
index 29371fe..b223082 100644
--- a/cstp.c
+++ b/cstp.c
@@ -23,7 +23,6 @@
* Boston, MA 02110-1301 USA
*/
-#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
@@ -33,9 +32,16 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
+#ifdef _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
#include <netinet/tcp.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
#include <stdarg.h>
#include "openconnect-internal.h"
diff --git a/dtls.c b/dtls.c
index eede71c..f7ff53a 100644
--- a/dtls.c
+++ b/dtls.c
@@ -24,10 +24,16 @@
#include <errno.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
+#ifdef _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
#include <unistd.h>
-#include <netinet/in.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
@@ -381,6 +387,12 @@ static int start_dtls_handshake(struct openconnect_info *vpninfo, int dtls_fd)
gnutls_transport_set_ptr(dtls_ssl,
(gnutls_transport_ptr_t)(long) dtls_fd);
+#ifdef _WIN32
+ gnutls_transport_set_pull_function(dtls_ssl, system_read);
+ gnutls_transport_set_push_function(dtls_ssl, system_write);
+ gnutls_transport_set_errno_function(dtls_ssl, neterrno);
+#endif
+
gnutls_record_disable_padding(dtls_ssl);
master_secret.data = vpninfo->dtls_secret;
master_secret.size = sizeof(vpninfo->dtls_secret);
@@ -500,7 +512,7 @@ int connect_dtls_socket(struct openconnect_info *vpninfo)
vpninfo->protect_socket(vpninfo->cbdata, dtls_fd);
sndbuf = vpninfo->ip_info.mtu * 2;
- setsockopt(dtls_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
+ setsockopt(dtls_fd, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf, sizeof(sndbuf));
if (vpninfo->dtls_local_port) {
union {
@@ -527,29 +539,31 @@ int connect_dtls_socket(struct openconnect_info *vpninfo)
_("Unknown protocol family %d. Cannot do DTLS\n"),
vpninfo->peer_addr->sa_family);
vpninfo->dtls_attempt_period = 0;
- close(dtls_fd);
+ closesocket(dtls_fd);
return -EINVAL;
}
if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
perror(_("Bind UDP socket for DTLS"));
- close(dtls_fd);
+ closesocket(dtls_fd);
return -EINVAL;
}
}
if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
perror(_("UDP (DTLS) connect:\n"));
- close(dtls_fd);
+ closesocket(dtls_fd);
return -EINVAL;
}
+#ifdef HAVE_FCNTL
fcntl(dtls_fd, F_SETFD, FD_CLOEXEC);
fcntl(dtls_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
+#endif
ret = start_dtls_handshake(vpninfo, dtls_fd);
if (ret) {
- close(dtls_fd);
+ closesocket(dtls_fd);
return ret;
}
@@ -569,7 +583,7 @@ void dtls_close(struct openconnect_info *vpninfo, int kill_handshake_too)
{
if (vpninfo->dtls_ssl) {
DTLS_FREE(vpninfo->dtls_ssl);
- close(vpninfo->dtls_fd);
+ closesocket(vpninfo->dtls_fd);
FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
@@ -578,7 +592,7 @@ void dtls_close(struct openconnect_info *vpninfo, int kill_handshake_too)
}
if (kill_handshake_too && vpninfo->new_dtls_ssl) {
DTLS_FREE(vpninfo->new_dtls_ssl);
- close(vpninfo->new_dtls_fd);
+ closesocket(vpninfo->new_dtls_fd);
FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
vpninfo->new_dtls_ssl = NULL;
diff --git a/gnutls.c b/gnutls.c
index 810053f..0d6ec8a 100644
--- a/gnutls.c
+++ b/gnutls.c
@@ -24,15 +24,17 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <unistd.h>
+#ifndef _WIN32
+# include <sys/socket.h>
+# include <netdb.h>
+# include <unistd.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+#endif
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -210,12 +212,17 @@ static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x50
reason = _("Client certificate expires soon at");
if (reason) {
- struct tm tm;
char buf[80];
+#ifdef _WIN32
+ struct tm *tm = gmtime(&expires);
+ strftime(buf, 80, "%a, %d %b %Y %H:%M:%S %Z", tm);
+#else
+ struct tm tm;
gmtime_r(&expires, &tm);
strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
-
+#endif
+
vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
}
return 0;
@@ -1852,7 +1859,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_free(datum.data);
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -ENOMEM;
}
err = gnutls_x509_crt_list_import(certs, &nr_certs, &datum,
@@ -1873,7 +1880,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_strerror(err));
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
}
@@ -1889,7 +1896,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
vpninfo->cafile, gnutls_strerror(err));
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
}
@@ -1901,7 +1908,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
_("Loading certificate failed. Aborting.\n"));
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return err;
}
}
@@ -1927,13 +1934,18 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_strerror(err));
gnutls_deinit(vpninfo->https_sess);
vpninfo->https_sess = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EIO;
}
gnutls_record_disable_padding(vpninfo->https_sess);
gnutls_credentials_set(vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
+#ifdef _WIN32
+ gnutls_transport_set_pull_function(vpninfo->https_sess, system_read);
+ gnutls_transport_set_push_function(vpninfo->https_sess, system_write);
+ gnutls_transport_set_errno_function(vpninfo->https_sess, neterrno);
+#endif
vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
vpninfo->hostname);
@@ -1957,7 +1969,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
gnutls_deinit(vpninfo->https_sess);
vpninfo->https_sess = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINTR;
}
} else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
@@ -1965,7 +1977,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_strerror(err));
gnutls_deinit(vpninfo->https_sess);
vpninfo->https_sess = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EIO;
} else {
/* non-fatal error or warning. Ignore it and continue */
@@ -1994,7 +2006,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final)
vpninfo->https_sess = NULL;
}
if (vpninfo->ssl_fd != -1) {
- close(vpninfo->ssl_fd);
+ closesocket(vpninfo->ssl_fd);
FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
diff --git a/http.c b/http.c
index cff4519..07e1d6a 100644
--- a/http.c
+++ b/http.c
@@ -23,13 +23,15 @@
* Boston, MA 02110-1301 USA
*/
-#include <netdb.h>
-#include <unistd.h>
+#ifndef _WIN32
+# include <netdb.h>
+# include <unistd.h>
+# include <pwd.h>
+#endif
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
-#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
@@ -529,6 +531,7 @@ static int fetch_config(struct openconnect_info *vpninfo, char *fu, char *bu,
static int run_csd_script(struct openconnect_info *vpninfo, char *buf, int buflen)
{
+#ifndef _WIN32
char fname[64];
int fd, ret;
@@ -658,7 +661,7 @@ out:
vpninfo->csd_scriptname = strdup(fname);
http_add_cookie(vpninfo, "sdesktop", vpninfo->csd_token);
-
+#endif
return 0;
}
@@ -1329,7 +1332,7 @@ static int proxy_write(struct openconnect_info *vpninfo, int fd,
if (!FD_ISSET(fd, &wr_set))
continue;
- i = write(fd, buf + count, len - count);
+ i = send(fd, (void *)&buf[count], len - count, 0);
if (i < 0)
return -errno;
@@ -1360,7 +1363,7 @@ static int proxy_read(struct openconnect_info *vpninfo, int fd,
if (!FD_ISSET(fd, &rd_set))
continue;
- i = read(fd, buf + count, len - count);
+ i = recv(fd, (void *)&buf[count], len - count, 0);
if (i < 0)
return -errno;
diff --git a/library.c b/library.c
index b1295de..3e27be5 100644
--- a/library.c
+++ b/library.c
@@ -367,10 +367,15 @@ void openconnect_set_cancel_fd(struct openconnect_info *vpninfo, int fd)
vpninfo->cmd_fd = fd;
}
+
int openconnect_setup_cmd_pipe(struct openconnect_info *vpninfo)
{
int pipefd[2];
+#ifdef HAVE_PIPE2
+ if (pipe2(pipefd, O_NONBLOCK))
+ return -EIO;
+#else
if (pipe(pipefd) < 0)
return -EIO;
if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) ||
@@ -379,6 +384,7 @@ int openconnect_setup_cmd_pipe(struct openconnect_info *vpninfo)
close(pipefd[1]);
return -EIO;
}
+#endif
vpninfo->cmd_fd = pipefd[0];
vpninfo->cmd_fd_write = pipefd[1];
return vpninfo->cmd_fd_write;
diff --git a/main.c b/main.c
index 1c9e5f6..759b62f 100644
--- a/main.c
+++ b/main.c
@@ -32,7 +32,7 @@
#include <stdio.h>
#ifdef __ANDROID__
#include <android/log.h>
-#else
+#elif !defined(_WIN32)
#include <syslog.h>
#endif
#include <stdarg.h>
@@ -45,16 +45,24 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
+#ifdef HAVE_GETPWNAM
#include <pwd.h>
+#endif
+#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
+#endif
#include <sys/types.h>
+#ifdef HAVE_TERMIOS_H
#include <termios.h>
+#endif
#ifdef LIBPROXY_HDR
#include LIBPROXY_HDR
#endif
#include <getopt.h>
#include <time.h>
-
+#ifdef _WIN32
+#include <conio.h>
+#endif
#include "openconnect-internal.h"
static int write_new_config(void *_vpninfo,
@@ -139,7 +147,9 @@ enum {
#endif
static struct option long_options[] = {
+#ifdef HAVE_FORK
OPTION("background", 0, 'b'),
+#endif
OPTION("pfs", 0, OPT_PFS),
OPTION("pid-file", 1, OPT_PIDFILE),
OPTION("certificate", 1, 'c'),
@@ -153,9 +163,14 @@ static struct option long_options[] = {
OPTION("interface", 1, 'i'),
OPTION("mtu", 1, 'm'),
OPTION("base-mtu", 1, OPT_BASEMTU),
+#ifdef HAVE_GETPWNAM
OPTION("setuid", 1, 'U'),
+ OPTION("csd-user", 1, OPT_CSD_USER),
+#endif
OPTION("script", 1, 's'),
+#ifndef _WIN32
OPTION("script-tun", 0, 'S'),
+#endif
OPTION("syslog", 0, 'l'),
OPTION("timestamp", 0, OPT_TIMESTAMP),
OPTION("key-password", 1, 'p'),
@@ -181,7 +196,6 @@ static struct option long_options[] = {
OPTION("servercert", 1, OPT_SERVERCERT),
OPTION("key-password-from-fsid", 0, OPT_KEY_PASSWORD_FROM_FSID),
OPTION("useragent", 1, OPT_USERAGENT),
- OPTION("csd-user", 1, OPT_CSD_USER),
OPTION("csd-wrapper", 1, OPT_CSD_WRAPPER),
OPTION("disable-ipv6", 0, OPT_DISABLE_IPV6),
OPTION("no-proxy", 0, OPT_NO_PROXY),
@@ -255,7 +269,9 @@ static void usage(void)
printf(_("Open client for Cisco AnyConnect VPN, version %s\n\n"), openconnect_version_str);
print_build_opts();
printf(" --config=CONFIGFILE %s\n", _("Read options from config file"));
+#ifdef HAVE_FORK
printf(" -b, --background %s\n", _("Continue in background after startup"));
+#endif
printf(" --pid-file=PIDFILE %s\n", _("Write the daemon's PID to this file"));
printf(" -c, --certificate=CERT %s\n", _("Use SSL client certificate CERT"));
printf(" -e, --cert-expire-warning=DAYS %s\n", _("Warn when certificate lifetime < DAYS"));
@@ -329,16 +345,17 @@ static void usage(void)
static void read_stdin(char **string, int hidden)
{
- struct termios t;
char *c = malloc(1025), *ret;
- int fd = fileno(stdin);
if (!c) {
fprintf(stderr, _("Allocation failure for string from stdin\n"));
exit(1);
}
-
+#ifndef _WIN32
if (hidden) {
+ int fd = fileno(stdin);
+ struct termios t;
+
tcgetattr(fd, &t);
t.c_lflag &= ~ECHO;
tcsetattr(fd, TCSANOW, &t);
@@ -349,6 +366,7 @@ static void read_stdin(char **string, int hidden)
tcsetattr(fd, TCSANOW, &t);
fprintf(stderr, "\n");
} else
+#endif
ret = fgets(c, 1025, stdin);
if (!ret) {
@@ -366,6 +384,7 @@ static void read_stdin(char **string, int hidden)
static int sig_cmd_fd;
static int sig_caught;
+#ifdef HAVE_SIGACTION
static void handle_sigint(int sig)
{
char x = OC_CMD_CANCEL;
@@ -383,6 +402,7 @@ static void handle_sigusr(int sig)
else if (sig == SIGUSR2)
verbose = PRG_INFO;
}
+#endif /* SIGACTION */
static FILE *config_file = NULL;
static int config_line_num = 0;
@@ -427,7 +447,11 @@ static int next_option(int argc, char **argv, char **config_arg)
next:
if (!config_file) {
opt = getopt_long(argc, argv,
+#ifdef HAVE_FORK
+ "b"
+#endif
"bC:c:Dde:g:hi:k:lm:P:p:Q:qSs:U:u:Vvx:",
+
long_options, NULL);
*config_arg = optarg;
@@ -511,16 +535,16 @@ static int next_option(int argc, char **argv, char **config_arg)
int main(int argc, char **argv)
{
struct openconnect_info *vpninfo;
- struct utsname utsbuf;
- struct sigaction sa;
int use_syslog = 0;
char *urlpath = NULL;
char *proxy = getenv("https_proxy");
- int script_tun = 0;
char *vpnc_script = NULL, *ifname = NULL;
const struct oc_ip_info *ip_info;
int autoproxy = 0;
+#ifndef _WIN32
+ int script_tun = 0;
uid_t uid = getuid();
+#endif
int opt;
char *pidfile = NULL;
int use_dtls = 1;
@@ -544,6 +568,17 @@ int main(int argc, char **argv)
openconnect_init_ssl();
+#ifdef _WIN32
+ {
+ WSADATA data;
+ if (WSAStartup (MAKEWORD(1, 1), &data) != 0) {
+ fprintf(stderr, _("ERROR: Cannot initialize sockets\n"));
+ exit(1);
+ }
+
+ }
+#endif
+
vpninfo = openconnect_vpninfo_new((char *)"Open AnyConnect VPN Agent",
validate_peer_cert, NULL, process_auth_form_cb, write_progress, NULL);
if (!vpninfo) {
@@ -552,10 +587,13 @@ int main(int argc, char **argv)
}
vpninfo->cbdata = vpninfo;
+#ifdef HAVE_SYS_UTSNAME
+ struct utsname utsbuf;
if (!uname(&utsbuf)) {
free(vpninfo->localname);
vpninfo->localname = xstrdup(utsbuf.nodename);
}
+#endif
while ((opt = next_option(argc, argv, &config_arg))) {
@@ -628,9 +666,11 @@ int main(int argc, char **argv)
case OPT_AUTHGROUP:
authgroup = keep_config_arg();
break;
+#ifdef HAVE_FORK
case 'b':
background = 1;
break;
+#endif
case 'C':
vpninfo->cookie = keep_config_arg();
break;
@@ -704,13 +744,16 @@ int main(int argc, char **argv)
case 's':
vpnc_script = xstrdup(config_arg);
break;
+#ifndef _WIN32
case 'S':
script_tun = 1;
break;
+#endif
case 'u':
free(username);
username = strdup(config_arg);
break;
+#ifdef HAVE_GETPWNAM
case 'U': {
char *strend;
uid = strtol(config_arg, &strend, 0);
@@ -740,6 +783,7 @@ int main(int argc, char **argv)
vpninfo->uid_csd_given = 1;
break;
}
+#endif
case OPT_CSD_WRAPPER:
vpninfo->csd_wrapper = keep_config_arg();
break;
@@ -826,6 +870,13 @@ int main(int argc, char **argv)
usage();
}
+#ifdef _WIN32
+ if (!(cookieonly & 1) && vpninfo->ifname == NULL) {
+ fprintf(stderr, _("The --interface option is mandatory on windows\n"));
+ usage();
+ }
+#endif
+
if (!vpninfo->sslkey)
vpninfo->sslkey = vpninfo->cert;
@@ -847,7 +898,7 @@ int main(int argc, char **argv)
exit(1);
if (use_syslog) {
-#ifndef __ANDROID__
+#if !defined (__ANDROID__) && !defined(_WIN32)
openlog("openconnect", LOG_PID, LOG_DAEMON);
#endif
vpninfo->progress = syslog_progress;
@@ -859,6 +910,9 @@ int main(int argc, char **argv)
exit(1);
}
+#ifdef HAVE_SIGACTION
+ {
+ struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handle_sigusr;
@@ -869,6 +923,8 @@ int main(int argc, char **argv)
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
+ }
+#endif
if (vpninfo->sslkey && do_passphrase_from_fsid)
openconnect_passphrase_from_fsid(vpninfo);
@@ -934,18 +990,22 @@ 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 if (openconnect_setup_tun_device(vpninfo, vpnc_script, ifname)) {
+ } 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"),
@@ -954,6 +1014,7 @@ int main(int argc, char **argv)
exit(1);
}
}
+#endif
if (use_dtls && openconnect_setup_dtls(vpninfo, 60))
fprintf(stderr, _("Set up DTLS failed; using SSL instead\n"));
@@ -975,6 +1036,7 @@ int main(int argc, char **argv)
_("See http://www.infradead.org/openconnect/vpnc-script.html\n"));
}
+#ifdef HAVE_FORK
if (background) {
int pid;
@@ -1004,12 +1066,14 @@ int main(int argc, char **argv)
if (fp)
fclose(fp);
}
+#endif /* !HAVE_FORK */
ret = openconnect_mainloop(vpninfo, reconnect_timeout, RECONNECT_INTERVAL_MIN);
if (fp)
unlink(pidfile);
if (sig_caught) {
- vpn_progress(vpninfo, PRG_INFO, _("Caught signal: %s\n"), strsignal(sig_caught));
+ vpn_progress(vpninfo, PRG_INFO, _("Caught signal: %s\n"),
+ strsignal(sig_caught));
ret = 0;
} else if (ret == -EPERM)
ret = 2;
@@ -1093,7 +1157,7 @@ void syslog_progress(void *_vpninfo, int level, const char *fmt, ...)
va_end(args2);
}
}
-#else /* !__ANDROID__ */
+#elif !defined(_WIN32) /* !__ANDROID__ */
void syslog_progress(void *_vpninfo, int level, const char *fmt, ...)
{
int priority = level ? LOG_INFO : LOG_NOTICE;
@@ -1105,6 +1169,11 @@ void syslog_progress(void *_vpninfo, int level, const char *fmt, ...)
va_end(args);
}
}
+#else
+void syslog_progress(void *_vpninfo, int level, const char *fmt, ...)
+{
+ return;
+}
#endif
struct accepted_cert {
diff --git a/mainloop.c b/mainloop.c
index 053c81b..8135674 100644
--- a/mainloop.c
+++ b/mainloop.c
@@ -23,9 +23,13 @@
*/
#include <errno.h>
+#ifdef HAVE_POLL_H
#include <poll.h>
+#endif
#include <limits.h>
+#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
+#endif
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
diff --git a/openconnect-internal.h b/openconnect-internal.h
index 632c2db..208f894 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -54,8 +54,15 @@
#include <zlib.h>
#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/select.h>
+#ifndef _WIN32
+# include <sys/socket.h>
+# include <sys/select.h>
+#else
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# define socklen_t int
+int asprintf (char **resultp, const char *format, ...);
+#endif
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
@@ -347,6 +354,56 @@ ssize_t openconnect__getline(char **lineptr, size_t *n, FILE *stream);
char *openconnect__strcasestr(const char *haystack, const char *needle);
#endif
+#ifndef HAVE_SETENV
+#define setenv openconnect__setenv
+int openconnect__setenv(const char *name, const char *value, int overwrite);
+#endif
+#ifndef HAVE_UNSETENV
+#define unsetenv openconnect__unsetenv
+void openconnect__unsetenv(const char *name);
+#endif
+
+#ifndef HAVE_INET_ATON
+#define inet_aton openconnect__inet_aton
+int openconnect__inet_aton(const char *cp, struct in_addr *addr);
+#endif
+
+#ifndef _WIN32
+# define neterrno() errno
+# define closesocket close
+# define socket(domain,type,proto) WSASocket(domain,type,proto,NULL,0,0)
+#else
+# include <errno.h>
+#define HAVE_PIPE2
+#define O_NONBLOCK 0/* XXX */
+#define pipe2(fds, flags) _pipe(fds, 4096, _O_BINARY|(flags))
+#define strsignal(sig) "<unknown>"
+static inline ssize_t
+system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size)
+{
+ return send((long)ptr, data, data_size, 0);
+}
+
+static inline ssize_t
+system_read(gnutls_transport_ptr_t ptr, void *data, size_t data_size)
+{
+ return recv((long)ptr, data, data_size, 0);
+}
+
+static inline int neterrno()
+{
+int err = WSAGetLastError();
+
+ if (err == WSAEWOULDBLOCK)
+ return EAGAIN;
+ else if (err == WSAEINTR)
+ return EINTR;
+ else if (err == WSAEINPROGRESS)
+ return EINPROGRESS;
+ return 0;
+}
+#endif
+
/* I always coded as if it worked like this. Now it does. */
#define realloc_inplace(p, size) do { \
void *__realloc_old = p; \
diff --git a/openconnect.h b/openconnect.h
index 0950162..7dc67db 100644
--- a/openconnect.h
+++ b/openconnect.h
@@ -31,6 +31,10 @@
#include <sys/types.h>
#include <unistd.h>
+#ifdef _WIN32
+#define uid_t unsigned
+#endif
+
#define OPENCONNECT_API_VERSION_MAJOR 3
#define OPENCONNECT_API_VERSION_MINOR 1
diff --git a/openssl.c b/openssl.c
index f8a6eb1..be157ef 100644
--- a/openssl.c
+++ b/openssl.c
@@ -1285,7 +1285,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
_("Loading certificate failed. Aborting.\n"));
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return err;
}
check_certificate_expiry(vpninfo);
@@ -1318,7 +1318,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
if (!b) {
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
@@ -1332,7 +1332,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
openconnect_report_ssl_errors(vpninfo);
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -ENOENT;
}
@@ -1356,7 +1356,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
openconnect_report_ssl_errors(vpninfo);
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
}
@@ -1388,7 +1388,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
openconnect_report_ssl_errors(vpninfo);
SSL_free(https_ssl);
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
@@ -1397,14 +1397,14 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
if (is_cancel_pending(vpninfo, &rd_set)) {
vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
SSL_free(https_ssl);
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
}
if (verify_peer(vpninfo, https_ssl)) {
SSL_free(https_ssl);
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
@@ -1432,7 +1432,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final)
vpninfo->https_ssl = NULL;
}
if (vpninfo->ssl_fd != -1) {
- close(vpninfo->ssl_fd);
+ closesocket(vpninfo->ssl_fd);
FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
diff --git a/ssl.c b/ssl.c
index 61d55b8..a6bfb66 100644
--- a/ssl.c
+++ b/ssl.c
@@ -23,11 +23,17 @@
*/
#include <sys/types.h>
-#include <sys/socket.h>
+
+#ifdef _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif
#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
@@ -58,6 +64,16 @@
#define AI_NUMERICSERV 0
#endif
+static inline int set_nonblock(int sockfd)
+{
+#ifdef _WIN32
+ unsigned long mode = 0;
+ return ioctlsocket(sockfd, FIONBIO, &mode);
+#else
+ return fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
+#endif
+}
+
static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
const struct sockaddr *addr, socklen_t addrlen)
{
@@ -66,27 +82,30 @@ static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
fd_set wr_set, rd_set;
int maxfd = sockfd;
- fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
+ set_nonblock(sockfd);
if (vpninfo->protect_socket)
vpninfo->protect_socket(vpninfo->cbdata, sockfd);
- if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS)
+ if (connect(sockfd, addr, addrlen) < 0 && neterrno() != EINPROGRESS)
return -1;
do {
+ printf("into loop\n");
FD_ZERO(&wr_set);
FD_ZERO(&rd_set);
FD_SET(sockfd, &wr_set);
cmd_fd_set(vpninfo, &rd_set, &maxfd);
-
+ printf("will select...\n");
select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
+ printf("done select...\n");
if (is_cancel_pending(vpninfo, &rd_set)) {
vpn_progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n"));
errno = EINTR;
return -1;
}
+ printf("no cancel pending. Again...\n");
} while (!FD_ISSET(sockfd, &wr_set) && !vpninfo->got_pause_cmd);
-
+ printf("try getpeername\n");
/* Check whether connect() succeeded or failed by using
getpeername(). See http://cr.yp.to/docs/connect.html */
return getpeername(sockfd, (void *)&peer, &peerlen);
@@ -109,7 +128,9 @@ int connect_https_socket(struct openconnect_info *vpninfo)
ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM, IPPROTO_IP);
if (ssl_sock < 0)
goto reconn_err;
+#ifndef _WIN32
fcntl(ssl_sock, F_SETFD, fcntl(ssl_sock, F_GETFD) | FD_CLOEXEC);
+#endif
}
if (cancellable_connect(vpninfo, ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen)) {
reconn_err:
@@ -123,7 +144,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
vpninfo->hostname);
}
if (ssl_sock >= 0)
- close(ssl_sock);
+ closesocket(ssl_sock);
return -EINVAL;
}
} else {
@@ -238,7 +259,9 @@ int connect_https_socket(struct openconnect_info *vpninfo)
rp->ai_protocol);
if (ssl_sock < 0)
continue;
+#ifndef _WIN32
fcntl(ssl_sock, F_SETFD, fcntl(ssl_sock, F_GETFD) | FD_CLOEXEC);
+#endif
if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
/* Store the peer address we actually used, so that DTLS can
use it again later */
@@ -246,7 +269,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (!vpninfo->peer_addr) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to allocate sockaddr storage\n"));
- close(ssl_sock);
+ closesocket(ssl_sock);
return -ENOMEM;
}
vpninfo->peer_addrlen = rp->ai_addrlen;
@@ -270,7 +293,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
}
break;
}
- close(ssl_sock);
+ closesocket(ssl_sock);
ssl_sock = -1;
}
freeaddrinfo(result);
@@ -286,7 +309,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (vpninfo->proxy) {
err = process_proxy(vpninfo, ssl_sock);
if (err) {
- close(ssl_sock);
+ closesocket(ssl_sock);
return err;
}
}
@@ -357,6 +380,12 @@ int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
return -ENOMEM;
return 0;
}
+#elif defined(_WIN32)
+int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
+{
+ /* Use GetVolumeInfo()? */
+ return -EINVAL;
+}
#else
int openconnect_passphrase_from_fsid(struct openconnect_info *vpninfo)
{
@@ -544,10 +573,12 @@ void check_cmd_fd(struct openconnect_info *vpninfo, fd_set *fds)
vpninfo->got_cancel_cmd = 1;
return;
}
-
- if (read(vpninfo->cmd_fd, &cmd, 1) != 1)
+ printf("read cmdfd...\n");
+ if (read(vpninfo->cmd_fd, &cmd, 1) != 1) {
+ printf("no\n");
return;
-
+ }
+ printf("done\n");
switch (cmd) {
case OC_CMD_CANCEL:
vpninfo->got_cancel_cmd = 1;
@@ -563,7 +594,9 @@ void check_cmd_fd(struct openconnect_info *vpninfo, fd_set *fds)
int is_cancel_pending(struct openconnect_info *vpninfo, fd_set *fds)
{
+ printf("is_cancel_pending()\n");
check_cmd_fd(vpninfo, fds);
+ printf("answer: %d\n", vpninfo->got_cancel_cmd);
return vpninfo->got_cancel_cmd;
}
diff --git a/tun.c b/tun.c
index 863a189..dfbdc00 100644
--- a/tun.c
+++ b/tun.c
@@ -24,18 +24,20 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
+#ifndef _WIN32
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <arpa/inet.h>
+#endif
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
@@ -79,7 +81,7 @@
static int set_tun_mtu(struct openconnect_info *vpninfo)
{
-#ifndef __sun__ /* We don't know how to do this on Solaris */
+#if !defined(__sun__) && !defined(_WIN32) /* We don't know how to do this on Solaris */
struct ifreq ifr;
int net_fd;
@@ -101,7 +103,6 @@ static int set_tun_mtu(struct openconnect_info *vpninfo)
return 0;
}
-
static int setenv_int(const char *opt, int value)
{
char buf[16];
@@ -372,6 +373,12 @@ static void set_script_env(struct openconnect_info *vpninfo)
setenv_cstp_opts(vpninfo);
}
+#ifdef _WIN32
+#define WIFEXITED(w) (((w) & 0xffffff00) == 0)
+#define WIFSIGNALED(w) (!WIFEXITED(w))
+#define WEXITSTATUS(w) (w)
+#endif
+
int script_config_tun(struct openconnect_info *vpninfo, const char *reason)
{
int ret;
@@ -388,12 +395,14 @@ int script_config_tun(struct openconnect_info *vpninfo, const char *reason)
vpninfo->vpnc_script, reason, strerror(e));
return -e;
}
+
if (!WIFEXITED(ret)) {
vpn_progress(vpninfo, PRG_ERR,
_("Script '%s' exited abnormally (%x)\n"),
vpninfo->vpnc_script, ret);
return -EIO;
}
+
ret = WEXITSTATUS(ret);
if (ret) {
vpn_progress(vpninfo, PRG_ERR,
@@ -401,6 +410,7 @@ int script_config_tun(struct openconnect_info *vpninfo, const char *reason)
vpninfo->vpnc_script, ret);
return -EIO;
}
+
return 0;
}
@@ -635,7 +645,10 @@ static int os_setup_tun(struct openconnect_info *vpninfo)
int openconnect_setup_tun_fd(struct openconnect_info *vpninfo, int tun_fd)
{
+#ifndef _WIN32
fcntl(tun_fd, F_SETFD, FD_CLOEXEC);
+ fcntl(vpninfo->tun_fd, F_SETFL, fcntl(dtls_fd, F_GETFL) | O_NONBLOCK);
+#endif
if (vpninfo->tun_fd != -1)
FD_CLR(vpninfo->tun_fd, &vpninfo->select_rfds);
@@ -646,11 +659,10 @@ int openconnect_setup_tun_fd(struct openconnect_info *vpninfo, int tun_fd)
FD_SET(tun_fd, &vpninfo->select_rfds);
- fcntl(vpninfo->tun_fd, F_SETFL, fcntl(vpninfo->tun_fd, F_GETFL) | O_NONBLOCK);
-
return 0;
}
+#ifndef _WIN32
int openconnect_setup_tun_script(struct openconnect_info *vpninfo, char *tun_script)
{
pid_t child;
@@ -683,6 +695,7 @@ int openconnect_setup_tun_script(struct openconnect_info *vpninfo, char *tun_scr
return openconnect_setup_tun_fd(vpninfo, fds[0]);
}
+#endif /* !_WIN32 */
int openconnect_setup_tun_device(struct openconnect_info *vpninfo, char *vpnc_script, char *ifname)
{
@@ -810,8 +823,10 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout)
void shutdown_tun(struct openconnect_info *vpninfo)
{
if (vpninfo->script_tun) {
+#ifndef _WIN32
/* nuke the whole process group */
kill(-vpninfo->script_tun, SIGHUP);
+#endif
} else {
script_config_tun(vpninfo, "disconnect");
#ifdef __sun__
diff --git a/xml.c b/xml.c
index 789bdbe..befdae7 100644
--- a/xml.c
+++ b/xml.c
@@ -29,30 +29,25 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef HAVE_MMAP
#include <sys/mman.h>
+#endif
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <string.h>
#include "openconnect-internal.h"
-int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
+static
+int load_xml_conf_file(const char* file, char** ptr, size_t* size)
{
- int fd, i;
struct stat st;
+ int fd;
char *xmlfile;
- unsigned char sha1[SHA1_SIZE];
- xmlDocPtr xml_doc;
- xmlNode *xml_node, *xml_node2;
- if (!vpninfo->xmlconfig)
- return 0;
-
- fd = open(vpninfo->xmlconfig, O_RDONLY);
+ fd = open(file, O_RDONLY);
if (fd < 0) {
perror(_("Open XML config file"));
- fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
- host);
return 0;
}
@@ -62,18 +57,64 @@ int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
return -1;
}
+#ifdef HAVE_MMAP
xmlfile = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (xmlfile == MAP_FAILED) {
perror(_("mmap XML config file"));
close(fd);
return -1;
}
+#else
+ xmlfile = malloc(st.st_size);
- if (openconnect_sha1(sha1, xmlfile, st.st_size)) {
- fprintf(stderr, _("Failed to SHA1 existing file\n"));
+ if (read(fd, xmlfile, st.st_size) != st.st_size) {
+ perror(_("read XML config file"));
close(fd);
return -1;
}
+#endif
+ *ptr = xmlfile;
+ *size = st.st_size;
+
+ close(fd);
+
+ return 1;
+}
+
+static
+void unload_xml_conf_file(void* ptr, size_t size)
+{
+#ifdef HAVE_MMAP
+ munmap(xmlfile, size);
+#else
+ free(ptr);
+#endif
+}
+
+int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
+{
+ int i, ret;
+ size_t size;
+ char *xmlfile;
+ unsigned char sha1[SHA1_SIZE];
+ xmlDocPtr xml_doc;
+ xmlNode *xml_node, *xml_node2;
+
+ if (!vpninfo->xmlconfig)
+ return 0;
+
+ ret = load_xml_conf_file(vpninfo->xmlconfig, &xmlfile, &size);
+ if (ret <= 0) {
+ if (ret == 0)
+ fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
+ host);
+ return ret;
+ }
+
+ if (openconnect_sha1(sha1, xmlfile, size)) {
+ fprintf(stderr, _("Failed to SHA1 existing file\n"));
+ return -1;
+ }
for (i = 0; i < SHA1_SIZE; i++)
sprintf(&vpninfo->xmlsha1[i*2], "%02x", sha1[i]);
@@ -81,9 +122,10 @@ int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
vpn_progress(vpninfo, PRG_TRACE, _("XML config file SHA1: %s\n"),
vpninfo->xmlsha1);
- xml_doc = xmlReadMemory(xmlfile, st.st_size, "noname.xml", NULL, 0);
- munmap(xmlfile, st.st_size);
- close(fd);
+ xml_doc = xmlReadMemory(xmlfile, size, "noname.xml", NULL, 0);
+
+ unload_xml_conf_file(xmlfile, size);
+
if (!xml_doc) {
fprintf(stderr, _("Failed to parse XML config file %s\n"),
vpninfo->xmlconfig);
--
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5745 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20140203/2abde52f/attachment-0001.bin>
More information about the openconnect-devel
mailing list