diff -Naur openconnect-2.12/http.c openconnect-2.12.ilap/http.c --- openconnect-2.12/http.c 2009-12-08 05:40:34.000000000 +1300 +++ openconnect-2.12.ilap/http.c 2009-12-18 00:28:54.000000000 +1300 @@ -637,3 +637,63 @@ return uagent; } + +void openconnect_parse_proxyurl(struct openconnect_info *vpninfo, char *url) +{ + char *proxy_port; + char *proxy = url; + vpninfo->proxy = proxy; + + /* + * if the format is hostname:port then we cut off the port from name + */ + proxy_port = strchr(proxy, ':'); + + if (proxy_port) { + *proxy_port = 0x0; + proxy_port++; + + vpninfo->proxy_port = proxy_port; + } + /* else the default one (1080) which is already set will be used */ +} + +int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock) +{ + char buf[MAX_BUF_LEN]; + int buflen; + + if(!vpninfo->proxy) { + return 1; + } else if (ssl_sock < 0) { + return -EINVAL; + } + + bzero(buf, MAX_BUF_LEN); + sprintf(buf, "CONNECT %s:%s HTTP/1.1\r\n", vpninfo->hostname, vpninfo->port); + sprintf(buf + strlen(buf), "Host: %s\r\n", vpninfo->hostname); + sprintf(buf + strlen(buf), "User-Agent: %s\r\n", vpninfo->useragent); + sprintf(buf + strlen(buf), "Proxy-Connection: keep-alive\r\n"); + sprintf(buf + strlen(buf), "Connection: keep-alive\r\n"); + sprintf(buf + strlen(buf), "Accept-Encoding: identity\r\n"); + sprintf(buf + strlen(buf), "\r\n"); + + vpninfo->progress(vpninfo, PRG_INFO, "Connecting to the proxy %s on port %s\n", + vpninfo->proxy, vpninfo->proxy_port); + vpninfo->progress(vpninfo, PRG_TRACE, "==>%s<==\n", buf); + + buflen = write(ssl_sock, buf, strlen(buf)); + if (buflen < 0) { + return -EINVAL; + } + + bzero(buf, MAX_BUF_LEN); + buflen = read(ssl_sock, buf, MAX_BUF_LEN); + + if ((buflen < 0) || strncmp(buf, "HTTP/1.1 200", 12)) { + vpninfo->progress(vpninfo, PRG_ERR,"Proxy connection failed!"); + return -EINVAL; + } + + return 1; +} diff -Naur openconnect-2.12/main.c openconnect-2.12.ilap/main.c --- openconnect-2.12/main.c 2009-12-08 05:40:34.000000000 +1300 +++ openconnect-2.12.ilap/main.c 2009-12-17 17:25:55.000000000 +1300 @@ -68,6 +68,7 @@ {"syslog", 0, 0, 'l'}, {"key-type", 1, 0, 'K'}, {"key-password", 1, 0, 'p'}, + {"proxy", 1, 0, 'P'}, {"user", 1, 0, 'u'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, @@ -109,10 +110,11 @@ printf(" -i, --interface=IFNAME Use IFNAME for tunnel interface\n"); printf(" -l, --syslog Use syslog for progress messages\n"); printf(" -U, --setuid=USER Drop privileges after connecting\n"); - printf(" --csd-user=USER Drop privileges during CSD execution\n"); + printf(" --csd-user=USER Drop privileges during CSD execution\n"); printf(" -m, --mtu=MTU Request MTU from server\n"); printf(" -p, --key-password=PASS Set key passphrase or TPM SRK PIN\n"); printf(" --key-password-from-fsid Key passphrase is fsid of file system\n"); + printf(" -P, --proxy=PROXY[:PORT] Set proxy server\n"); printf(" -q, --quiet Less output\n"); printf(" -Q, --queue-len=LEN Set packet queue limit to LEN pkts\n"); printf(" -s, --script=SCRIPT Use vpnc-compatible config script\n"); @@ -182,6 +184,9 @@ memset(vpninfo, 0, sizeof(*vpninfo)); /* Set up some defaults */ + vpninfo->proxy = NULL; + vpninfo->proxy_port = OC_DEF_PROXY_PORT; + vpninfo->port = OC_DEF_SSL_PORT; vpninfo->tun_fd = vpninfo->ssl_fd = vpninfo->dtls_fd = vpninfo->new_dtls_fd = -1; vpninfo->useragent = openconnect_create_useragent("Open AnyConnect VPN Agent"); vpninfo->mtu = 1406; @@ -202,7 +207,7 @@ else vpninfo->localname = "localhost"; - while ((opt = getopt_long(argc, argv, "bC:c:Ddg:hi:k:K:lp:Q:qSs:U:u:Vvx:", + while ((opt = getopt_long(argc, argv, "bC:c:Ddg:hi:k:K:lpP:Q:qSs:U:u:Vvx:", long_options, NULL))) { if (opt < 0) break; @@ -298,6 +303,9 @@ case 'p': vpninfo->cert_password = optarg; break; + case 'P': + openconnect_parse_proxyurl(vpninfo, optarg); + break; case 's': vpninfo->vpnc_script = optarg; break; diff -Naur openconnect-2.12/openconnect.h openconnect-2.12.ilap/openconnect.h --- openconnect-2.12/openconnect.h 2009-12-08 05:40:34.000000000 +1300 +++ openconnect-2.12.ilap/openconnect.h 2009-12-17 22:04:33.000000000 +1300 @@ -44,6 +44,9 @@ #define OC_FORM_OPT_SELECT 3 #define OC_FORM_OPT_HIDDEN 4 +#define OC_DEF_SSL_PORT "443" +#define OC_DEF_PROXY_PORT "8080" + /* char * fields are static (owned by XML parser) and don't need to be freed by the form handling code -- except for value, which for TEXT and PASSWORD options is allocated by process_form() when @@ -143,6 +146,10 @@ char sid_tokencode[9]; char sid_nexttokencode[9]; + char *proxy; + char *proxy_port; + char *port; + const char *localname; char *hostname; char *urlpath; @@ -319,6 +326,8 @@ /* http.c */ int openconnect_obtain_cookie(struct openconnect_info *vpninfo); char *openconnect_create_useragent(char *base); +void openconnect_parse_proxyurl(struct openconnect_info *vpninfo, char *url); +int process_http_proxy(struct openconnect_info *vpninfo, int ssl_sock); /* ssl_ui.c */ int set_openssl_ui(void); diff -Naur openconnect-2.12/ssl.c openconnect-2.12.ilap/ssl.c --- openconnect-2.12/ssl.c 2009-12-08 05:40:34.000000000 +1300 +++ openconnect-2.12.ilap/ssl.c 2009-12-18 00:30:04.000000000 +1300 @@ -477,17 +477,23 @@ int ssl_sock = -1; int err; + char *hostname = vpninfo->hostname; + char *port = vpninfo->port; + + if (vpninfo->proxy) { + hostname = vpninfo->proxy; + port = vpninfo->proxy_port; + } + if (vpninfo->peer_addr) { ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM, IPPROTO_IP); if (ssl_sock < 0) { reconn_err: - vpninfo->progress(vpninfo, PRG_ERR, "Failed to reconnect to host %s\n", vpninfo->hostname); + vpninfo->progress(vpninfo, PRG_ERR, "Failed to reconnect to host %s\n", hostname); return -EINVAL; } if (connect(ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen)) goto reconn_err; - - } else { struct addrinfo hints, *result, *rp; @@ -501,14 +507,15 @@ hints.ai_addr = NULL; hints.ai_next = NULL; - err = getaddrinfo(vpninfo->hostname, "443", &hints, &result); + err = getaddrinfo(hostname, port, &hints, &result); + if (err) { vpninfo->progress(vpninfo, PRG_ERR, "getaddrinfo failed: %s\n", gai_strerror(err)); return -EINVAL; } vpninfo->progress(vpninfo, PRG_INFO, - "Attempting to connect to %s\n", vpninfo->hostname); + "Attempting to connect to %s\n", hostname); for (rp = result; rp ; rp = rp->ai_next) { ssl_sock = socket(rp->ai_family, rp->ai_socktype, @@ -534,12 +541,19 @@ freeaddrinfo(result); if (ssl_sock < 0) { - vpninfo->progress(vpninfo, PRG_ERR, "Failed to connect to host %s\n", vpninfo->hostname); + vpninfo->progress(vpninfo, PRG_ERR, "Failed to connect to host %s\n", hostname); return -EINVAL; } } fcntl(ssl_sock, F_SETFD, FD_CLOEXEC); + if (process_http_proxy(vpninfo, ssl_sock) <= 0) { + vpninfo->progress(vpninfo, PRG_ERR, "Proxy connection failure\n"); + SSL_free(https_ssl); + close(ssl_sock); + return -EINVAL; + } + ssl3_method = TLSv1_client_method(); if (!vpninfo->https_ctx) { vpninfo->https_ctx = SSL_CTX_new(ssl3_method); diff -Naur openconnect-2.12/version.c openconnect-2.12.ilap/version.c --- openconnect-2.12/version.c 2009-12-08 05:40:34.000000000 +1300 +++ openconnect-2.12.ilap/version.c 2009-12-18 00:30:29.000000000 +1300 @@ -1 +1 @@ -char openconnect_version[] = "v2.12"; +char openconnect_version[] = "v2.12-unknown";