Restructure somewhat
authorDavid Woodhouse <David.Woodhouse@intel.com>
Mon, 22 Sep 2008 02:38:50 +0000 (19:38 -0700)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Mon, 22 Sep 2008 02:38:50 +0000 (19:38 -0700)
Makefile
cisco.c
dtls.c [new file with mode: 0644]
ssl.c [new file with mode: 0644]
tun.c [new file with mode: 0644]

index 0402328..c7ffbc0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 
-CFLAGS += -Lssl -I/usr/include/openssl
+CFLAGS += -I/usr/include/openssl -g -I/usr/include/libxml2 -Wall
 
 
-cisco: cisco.o
-       $(CC) -o $@ $<
+cisco: cisco.o tun.o dtls.o ssl.o
+       $(CC) -o $@ -lssl $^
diff --git a/cisco.c b/cisco.c
index 2ebca0c..23e85c3 100644 (file)
--- a/cisco.c
+++ b/cisco.c
 #include <fcntl.h>
 #include <unistd.h>
 #include <pwd.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <linux/if_tun.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
 #include <sys/utsname.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
+#include <openssl/rand.h>
 
 #define _GNU_SOURCE
 #include <getopt.h>
    session, bypassing all the initial setup of a normal DTLS connection.
    Or you can just send traffic over the HTTPS connection... */
 
-char *cookie;
-char *hostname;
-unsigned char dtls_secret[48];
-int mtu = 1406;
-int deflate;
-const char *useragent = "Open AnyConnect VPN Agent v0.01";
-int verbose;
-
-/* Set up a tuntap device. */
-int setup_tun(struct cstp_option *options)
-{
-       struct ifreq ifr;
-       int tun_fd;
-
-       tun_fd = open("/dev/net/tun", O_RDWR);
-       if (tun_fd == -1) {
-               perror("open tun");
-               exit(1);
-       }
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
-       strncpy(ifr.ifr_name, "cisco0", sizeof(ifr.ifr_name) - 1);
-       if (ioctl(tun_fd, TUNSETIFF, (void *) &ifr) < 0){
-               perror("TUNSETIFF");
-               exit(1);
-       }
-       /* FIXME: Configure it... */
-       /* Better still, use lwip and just provide a SOCKS server rather than
-          telling the kernel at all */
-       return tun_fd;
-}
-
-
-SSL *open_https(const char *host)
-{
-       SSL_METHOD *ssl3_method;
-       SSL_CTX *https_ctx;
-       SSL *https_ssl;
-       BIO *https_bio;
-       int ssl_sock;
-       int err;
-       struct addrinfo hints, *result, *rp;
-
-       memset(&hints, 0, sizeof(struct addrinfo));
-       hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
-       hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
-       hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
-       hints.ai_protocol = 0;          /* Any protocol */
-       hints.ai_canonname = NULL;
-       hints.ai_addr = NULL;
-       hints.ai_next = NULL;
-
-       err = getaddrinfo(host, "https", &hints, &result);
-       if (err) {
-               fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(err));
-               return NULL;
-       }
-
-       for (rp = result; rp ; rp = rp->ai_next) {
-               ssl_sock = socket(rp->ai_family, rp->ai_socktype,
-                                 rp->ai_protocol);
-               if (ssl_sock < 0)
-                       continue;
-
-               if (connect(ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0)
-                       break;
-
-               close(ssl_sock);
-       }
-       freeaddrinfo(result);
-
-       if (!rp) {
-               fprintf(stderr, "Failed to connect to host %s\n", host);
-               return NULL;
-       }
-
-       ssl3_method = SSLv23_client_method();
-       https_ctx = SSL_CTX_new(ssl3_method);
-       https_ssl = SSL_new(https_ctx);
-               
-       https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
-       SSL_set_bio(https_ssl, https_bio, https_bio);
-
-       if (SSL_connect(https_ssl) <= 0) {
-               fprintf(stderr, "SSL connection failure\n");
-               ERR_print_errors_fp(stderr);
-               SSL_free(https_ssl);
-               SSL_CTX_free(https_ctx);
-               return NULL;
-       }
-
-       return https_ssl;
-}
-
-
-int  __attribute__ ((format (printf, 2, 3))) my_SSL_printf(SSL *ssl, const char *fmt, ...) 
-{
-       char buf[1024];
-       va_list args;
-
-       
-       buf[1023] = 0;
-
-       va_start(args, fmt);
-       vsnprintf(buf, 1023, fmt, args);
-       va_end(args);
-       if (verbose)
-               printf("%s", buf);
-       return SSL_write(ssl, buf, strlen(buf));
-
-}
-
-int my_SSL_gets(SSL *ssl, char *buf, size_t len)
-{
-       int i = 0;
-       int ret;
-
-       if (len < 2)
-               return -EINVAL;
-
-       while ( (ret = SSL_read(ssl, buf + i, 1)) == 1) {
-               if (buf[i] == '\n') {
-                       buf[i] = 0;
-                       if (i && buf[i-1] == '\r') {
-                               buf[i-1] = 0;
-                               i--;
-                       }
-                       return i;
-               }
-               i++;
-
-               if (i >= len - 1) {
-                       buf[i] = 0;
-                       return i;
-               }
-       }
-
-       buf[i] = 0;
-       return i?:ret;
-}
-
-struct cstp_option *start_ssl_connection(SSL *ssl)
-{
-       char buf[65536];
-       int i;
-       struct utsname utsbuf;
-       struct cstp_option *options = NULL, **next_option = &options;
-
-       if (uname(&utsbuf))
-               printf(utsbuf.nodename, "localhost");
-
-       if (verbose)
-               printf("Connected to HTTPS on %s\n", hostname);
-
-       my_SSL_printf(ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
-       my_SSL_printf(ssl, "Host: %s\r\n", hostname);
-       my_SSL_printf(ssl, "User-Agent: %s\r\n", useragent);
-       my_SSL_printf(ssl, "Cookie: webvpn=%s\r\n", cookie);
-       my_SSL_printf(ssl, "X-CSTP-Version: 1\r\n");
-       my_SSL_printf(ssl, "X-CSTP-Hostname: %s\r\n", utsbuf.nodename);
-       if (deflate)
-               my_SSL_printf(ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
-       my_SSL_printf(ssl, "X-CSTP-MTU: %d\r\n", mtu);
-       my_SSL_printf(ssl, "X-CSTP-Address-Type: IPv6,IPv4\r\n");
-       my_SSL_printf(ssl, "X-DTLS-Master-Secret: ");
-       for (i = 0; i < sizeof(dtls_secret); i++)
-               my_SSL_printf(ssl, "%02X", dtls_secret[i]);
-       my_SSL_printf(ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
-
-       if (my_SSL_gets(ssl, buf, 65536) < 0) {
-               fprintf(stderr, "Error fetching HTTPS response\n");
-               return NULL;
-       }
-
-       if (verbose)
-               printf("Got CONNECT response: %s\n", buf);
-
-       if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
-               fprintf(stderr, "Got inappropriate HTTP CONNECT response: %s\n",
-                       buf);
-               return NULL;
-       }
-
-
-       while ((i=my_SSL_gets(ssl, buf, sizeof(buf)))) {
-               char *colon = strchr(buf, ':');
-               if (!colon)
-                       continue;
-
-               *colon = 0;
-               colon++;
-               if (*colon == ' ')
-                       colon++;
-
-               *next_option = malloc(sizeof(*options));
-               (*next_option)->option = strdup(buf);
-               (*next_option)->value = strdup(colon);
-               (*next_option)->next = NULL;
-               next_option = &(*next_option)->next;
-       }
-
-       if (verbose)
-               printf("Connected!\n");
-       return options;
-}
+int verbose = 0;
 
 static struct option long_options[] = {
        {"cookie", 1, 0, 'c'},
        {"host", 1, 0, 'h'},
        {"mtu", 1, 0, 'm'},
        {"verbose", 1, 0, 'v'},
-       {"deflate", 1, 0, 'd'},
+       {"deflate", 0, 0, 'd'},
+       {"useragent", 1, 0, 'u'},
 };
 
 int main(int argc, char **argv)
 {
-       SSL *https_ssl;
-       struct cstp_option *opts;
-       int tun_fd;
+       struct anyconnect_info *vpninfo;
+       struct utsname utsbuf;
        int optind;
        int opt;
-       char buf[65536 + 8];
 
-       SSL_library_init ();
-       ERR_clear_error ();
-       SSL_load_error_strings ();
-       OpenSSL_add_all_algorithms ();
+       vpn_init_openssl();
+
+       vpninfo = malloc(sizeof(*vpninfo));
+       if (!vpninfo) {
+               fprintf(stderr, "Failed to allocate vpninfo structure\n");
+               exit(1);
+       }
+       memset(vpninfo, 0, sizeof(*vpninfo));
+       /* Set up some defaults */
+       vpninfo->useragent = "Open AnyConnect VPN Agent v0.01";
+       vpninfo->mtu = 1406;
+       if (RAND_bytes(vpninfo->dtls_secret, sizeof(vpninfo->dtls_secret)) != 1) {
+               fprintf(stderr, "Failed to initialise DTLS secret\n");
+               exit(1);
+       }
+       if (!uname(&utsbuf))
+               vpninfo->localname = utsbuf.nodename;
+       else
+               vpninfo->localname = "localhost";
+
+       /* While we get it working, make it slightly easier... and don't forget */
+       fprintf(stderr, "HACKING DTLS SECRET TO 0x5A5A5A...\n");
+       memset(vpninfo->dtls_secret, 0x5a, sizeof(vpninfo->dtls_secret));
 
-       while ((opt = getopt_long(argc, argv, "c:h:vd", long_options, &optind))) {
+       while ((opt = getopt_long(argc, argv, "c:h:vdu:", long_options, &optind))) {
                if (opt < 0)
                        break;
 
                switch (opt) {
                case 'c':
-                       cookie = optarg;
+                       vpninfo->cookie = optarg;
                        break;
 
                case 'h':
-                       hostname = optarg;
+                       vpninfo->hostname = optarg;
                        break;
 
                case 'm':
-                       mtu = atol(optarg);
-                       if (mtu < 576) {
-                               fprintf(stderr, "MTU %d too small\n", mtu);
-                               exit(1);
+                       vpninfo->mtu = atol(optarg);
+                       if (vpninfo->mtu < 576) {
+                               fprintf(stderr, "MTU %d too small\n", vpninfo->mtu);
+                               vpninfo->mtu = 576;
                        }
                        break;
 
+               case 'u':
+                       vpninfo->useragent = optarg;
+                       break;
+
                case 'v':
                        verbose = 1;
                        break;
 
                case 'd':
                        fprintf(stderr, "Deflate not yet supported\n");
-                       //deflate = 1;
+                       //vpninfo->deflate = 1;
                        break;
                }
        }
-       if (!hostname || !cookie) {
+       if (!vpninfo->hostname || !vpninfo->cookie) {
                fprintf(stderr, "Need -h hostname, -c cookie\n");
                exit(1);
        }
 
-       https_ssl = open_https(hostname);
-       if (!https_ssl)
+       if (make_ssl_connection(vpninfo)) {
+               fprintf(stderr, "Creating SSL connection failed\n");
+               exit(1);
+       }
+       
+       if (setup_tun(vpninfo)) {
+               fprintf(stderr, "Set up tun device failed\n");
                exit(1);
-       int i;
-       for (i=0; i<48; i++) 
-               dtls_secret[i] = i;
-
-       opts = start_ssl_connection(https_ssl);
-
-       while (opts) {
-               printf ("Got opt %s, val %s\n", opts->option, opts->value);
-               opts = opts->next;
        }
-       exit(1);
+
+       if (setup_dtls(vpninfo))
+               fprintf(stderr, "Set up DTLS failed\n");
 
        printf("Connected\n");
+       exit(1);
 
-       tun_fd = setup_tun(NULL);
+#if 0
 
        if (fork()) {
                while (1) {
@@ -347,15 +158,15 @@ int main(int argc, char **argv)
                                buf[4] = len >> 8;
                                buf[5] = len & 0xff;
                        }
-                       SSL_write(https_ssl, buf, len + 8);
+                       SSL_write(https_info->https_ssl, buf, len + 8);
                }
        } else {
                while (1) {
                        int len;
-                       SSL_read(https_ssl, buf, 8);
+                       SSL_read(https_info->https_ssl, buf, 8);
                        
                        len = (buf[4] << 8) + buf [5];
-                       SSL_read(https_ssl, buf + 8, len);
+                       SSL_read(https_info->https_ssl, buf + 8, len);
                        if (buf[0] != 'S' ||
                            buf[1] != 'T' ||
                            buf[2] != 'F' ||
@@ -370,4 +181,5 @@ int main(int argc, char **argv)
                        }
                }
        }
+#endif
 }
diff --git a/dtls.c b/dtls.c
new file mode 100644 (file)
index 0000000..10f481e
--- /dev/null
+++ b/dtls.c
@@ -0,0 +1,36 @@
+/*
+ * Open AnyConnect (SSL + DTLS) client
+ *
+ * © 2008 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+
+#include "anyconnect.h"
+
+int setup_dtls(struct anyconnect_info *vpninfo)
+{
+       struct vpn_option *dtls_opt = vpninfo->dtls_options;
+
+       while (dtls_opt) {
+               printf("DTLS option %s : %s\n", dtls_opt->option, dtls_opt->value);
+               dtls_opt = dtls_opt->next;
+       }
+       /* No idea how to do this yet */
+       return -EINVAL;
+}
+
diff --git a/ssl.c b/ssl.c
new file mode 100644 (file)
index 0000000..aeff770
--- /dev/null
+++ b/ssl.c
@@ -0,0 +1,239 @@
+/*
+ * Open AnyConnect (SSL + DTLS) client
+ *
+ * © 2008 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "anyconnect.h"
+
+SSL *open_https(struct anyconnect_info *vpninfo)
+{
+       SSL_METHOD *ssl3_method;
+       SSL_CTX *https_ctx;
+       SSL *https_ssl;
+       BIO *https_bio;
+       int ssl_sock;
+       int err;
+       struct addrinfo hints, *result, *rp;
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
+       hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
+       hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
+       hints.ai_protocol = 0;          /* Any protocol */
+       hints.ai_canonname = NULL;
+       hints.ai_addr = NULL;
+       hints.ai_next = NULL;
+
+       err = getaddrinfo(vpninfo->hostname, "https", &hints, &result);
+       if (err) {
+               fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(err));
+               return NULL;
+       }
+
+       for (rp = result; rp ; rp = rp->ai_next) {
+               ssl_sock = socket(rp->ai_family, rp->ai_socktype,
+                                 rp->ai_protocol);
+               if (ssl_sock < 0)
+                       continue;
+
+               if (connect(ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0)
+                       break;
+
+               close(ssl_sock);
+       }
+       freeaddrinfo(result);
+
+       if (!rp) {
+               fprintf(stderr, "Failed to connect to host %s\n", vpninfo->hostname);
+               return NULL;
+       }
+
+       ssl3_method = SSLv23_client_method();
+       https_ctx = SSL_CTX_new(ssl3_method);
+       https_ssl = SSL_new(https_ctx);
+               
+       https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
+       SSL_set_bio(https_ssl, https_bio, https_bio);
+
+       if (SSL_connect(https_ssl) <= 0) {
+               fprintf(stderr, "SSL connection failure\n");
+               ERR_print_errors_fp(stderr);
+               SSL_free(https_ssl);
+               SSL_CTX_free(https_ctx);
+               return NULL;
+       }
+
+       return https_ssl;
+}
+
+
+int  __attribute__ ((format (printf, 2, 3))) my_SSL_printf(SSL *ssl, const char *fmt, ...) 
+{
+       char buf[1024];
+       va_list args;
+
+       
+       buf[1023] = 0;
+
+       va_start(args, fmt);
+       vsnprintf(buf, 1023, fmt, args);
+       va_end(args);
+       if (verbose)
+               printf("%s", buf);
+       return SSL_write(ssl, buf, strlen(buf));
+
+}
+
+int my_SSL_gets(SSL *ssl, char *buf, size_t len)
+{
+       int i = 0;
+       int ret;
+
+       if (len < 2)
+               return -EINVAL;
+
+       while ( (ret = SSL_read(ssl, buf + i, 1)) == 1) {
+               if (buf[i] == '\n') {
+                       buf[i] = 0;
+                       if (i && buf[i-1] == '\r') {
+                               buf[i-1] = 0;
+                               i--;
+                       }
+                       return i;
+               }
+               i++;
+
+               if (i >= len - 1) {
+                       buf[i] = 0;
+                       return i;
+               }
+       }
+
+       buf[i] = 0;
+       return i?:ret;
+}
+
+int start_ssl_connection(struct anyconnect_info *vpninfo)
+{
+       char buf[65536];
+       int i;
+       struct vpn_option **next_dtls_option = &vpninfo->dtls_options;
+       struct vpn_option **next_cstp_option = &vpninfo->cstp_options;
+
+       if (verbose)
+               printf("Connected to HTTPS on %s\n", vpninfo->hostname);
+
+       my_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n");
+       my_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname);
+       my_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent);
+       my_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie);
+       my_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n");
+       my_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname);
+       if (vpninfo->deflate)
+               my_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n");
+       my_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu);
+       my_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: IPv6,IPv4\r\n");
+       my_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: ");
+       for (i = 0; i < sizeof(vpninfo->dtls_secret); i++)
+               my_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]);
+       my_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA\r\n\r\n");
+
+       if (my_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) {
+               fprintf(stderr, "Error fetching HTTPS response\n");
+               return -EINVAL;
+       }
+
+       if (verbose)
+               printf("Got CONNECT response: %s\n", buf);
+
+       if (strncmp(buf, "HTTP/1.1 200 ", 13)) {
+               fprintf(stderr, "Got inappropriate HTTP CONNECT response: %s\n",
+                       buf);
+               return -EINVAL;
+       }
+
+
+       while ((i=my_SSL_gets(vpninfo->https_ssl, buf, sizeof(buf)))) {
+               struct vpn_option *new_option;
+               char *colon = strchr(buf, ':');
+               if (!colon)
+                       continue;
+
+               *colon = 0;
+               colon++;
+               if (*colon == ' ')
+                       colon++;
+
+               if (strncmp(buf, "X-DTLS-", 7) &&
+                   strncmp(buf, "X-CSTP-", 7))
+                       continue;
+
+               new_option = malloc(sizeof(*new_option));
+               if (!new_option) {
+                       fprintf(stderr, "No memory for allocation options\n");
+                       return -ENOMEM;
+               }
+               new_option->option = strdup(buf);
+               new_option->value = strdup(colon);
+               new_option->next = NULL;
+
+               if (!new_option->option || !new_option->value) {
+                       fprintf(stderr, "No memory for allocation options\n");
+                       return -ENOMEM;
+               }
+
+               if (!strncmp(buf, "X-DTLS-", 7)) {
+                       *next_dtls_option = new_option;
+                       next_dtls_option = &new_option->next;
+               } else {
+                       *next_cstp_option = new_option;
+                       next_cstp_option = &new_option->next;
+               }
+       }
+
+       if (verbose)
+               printf("Connected!\n");
+       return 0;
+}
+
+int make_ssl_connection(struct anyconnect_info *vpninfo)
+{
+       SSL *https_ssl = open_https(vpninfo);
+       if (!https_ssl)
+               exit(1);
+
+       vpninfo->https_ssl = https_ssl;
+       if (start_ssl_connection(vpninfo))
+               exit(1);
+       return 0;
+}
+
+
+void vpn_init_openssl(void)
+{
+       SSL_library_init ();
+       ERR_clear_error ();
+       SSL_load_error_strings ();
+       OpenSSL_add_all_algorithms ();
+}
diff --git a/tun.c b/tun.c
new file mode 100644 (file)
index 0000000..d1cc880
--- /dev/null
+++ b/tun.c
@@ -0,0 +1,62 @@
+/*
+ * Open AnyConnect (SSL + DTLS) client
+ *
+ * © 2008 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <linux/if_tun.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "anyconnect.h"
+
+/* Set up a tuntap device. */
+int setup_tun(struct anyconnect_info *vpninfo)
+{
+       struct vpn_option *cstp_opt = vpninfo->cstp_options;
+       struct ifreq ifr;
+       int tun_fd;
+
+       tun_fd = open("/dev/net/tun", O_RDWR);
+       if (tun_fd == -1) {
+               perror("open tun");
+               exit(1);
+       }
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+       strncpy(ifr.ifr_name, "cisco0", sizeof(ifr.ifr_name) - 1);
+       if (ioctl(tun_fd, TUNSETIFF, (void *) &ifr) < 0){
+               perror("TUNSETIFF");
+               exit(1);
+       }
+
+       /* FIXME: Configure it... */
+       while (cstp_opt) {
+               printf("CSTP option %s : %s\n", cstp_opt->option, cstp_opt->value);
+               cstp_opt = cstp_opt->next;
+       }
+
+       /* Better still, use lwip and just provide a SOCKS server rather than
+          telling the kernel about it at all */
+       vpninfo->tun_fd = tun_fd;
+       return 0;
+}
+