Hello, ?Attached you'll find the changes in openconnect-2.25 as used in SPA525G. I didn't check the changes to vpnc-script which I attach verbatim. The changes, if we ignore debugging output, as far as I can see are: 1. Non-blocking connect for the CSTP socket (ssl.c) 2. Specify password on command line (main.c) 3. Added buffering when sending the CONNECT HTTP lines 4. Added some check for?form->auth_id == "main" in?parse_xml_response() which made that client fail with ocserv - and that's the reason I got to check these sources. regards, Nikos [0].?https://gitlab.com/ocserv/ocserv/issues/55 -------------- next part -------------- diff -ur /home/nmav/cvs/openconnect-2.25/auth.c openconnect-2.25/auth.c --- /home/nmav/cvs/openconnect-2.25/auth.c 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/auth.c 2011-07-07 02:29:03.000000000 +0200 @@ -300,6 +300,7 @@ * = 1, when response was cancelled by user * = 2, when form indicates that login was already successful */ +int auth_attemp = 0; int parse_xml_response(struct openconnect_info *vpninfo, char *response, char *request_body, int req_len, char **method, char **request_body_type) @@ -334,7 +335,15 @@ ret = 2; goto out; } - + if (!strcmp(form->auth_id, "main")) { + auth_attemp++; + if(auth_attemp > 1) { + LOG_VPNINFO("V_AuthFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); + exit(-1); + } + } + if (vpninfo->nopasswd) { vpninfo->progress(vpninfo, PRG_ERR, "Asked for password but '--no-passwd' set\n"); ret = -EPERM; diff -ur /home/nmav/cvs/openconnect-2.25/cstp.c openconnect-2.25/cstp.c --- /home/nmav/cvs/openconnect-2.25/cstp.c 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/cstp.c 2011-07-07 02:29:03.000000000 +0200 @@ -67,6 +67,7 @@ static int start_cstp_connection(struct openconnect_info *vpninfo) { char buf[65536]; + char sendbuf[65536]; int i; int retried = 0; struct vpn_option **next_dtls_option = &vpninfo->dtls_options; @@ -101,22 +102,45 @@ } vpninfo->split_includes = vpninfo->split_excludes = NULL; retry: - openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n"); - openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname); - openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent); - openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie); - openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n"); - openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname); - if (vpninfo->deflate) - openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n"); - openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu); - openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: %s\r\n", - vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4"); - openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: "); - for (i = 0; i < sizeof(vpninfo->dtls_secret); i++) - openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]); - openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: %s\r\n\r\n", - vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA"); + { + char *ptr = sendbuf; + memset(sendbuf, 0, 65535); + ptr += sprintf(ptr, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n"); + ptr += sprintf(ptr, "Host: %s\r\n", vpninfo->hostname); + ptr += sprintf(ptr, "User-Agent: %s\r\n", vpninfo->useragent); + ptr += sprintf(ptr, "Cookie: webvpn=%s\r\n", vpninfo->cookie); + ptr += sprintf(ptr, "X-CSTP-Version: 1\r\n"); + ptr += sprintf(ptr, "X-CSTP-Hostname: %s\r\n", vpninfo->localname); + if(vpninfo->deflate) + ptr += sprintf(ptr, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n"); + ptr += sprintf(ptr, "X-CSTP-MTU: %d\r\n", vpninfo->mtu); + ptr += sprintf(ptr, "X-CSTP-Address-Type: %s\r\n", vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4"); + ptr += sprintf(ptr, "X-DTLS-Master-Secret: "); + for (i = 0; i < sizeof(vpninfo->dtls_secret); i++) + ptr += sprintf(ptr, "%02X", vpninfo->dtls_secret[i]); + ptr += sprintf(ptr, "\r\nX-DTLS-CipherSuite: %s\r\n\r\n", + vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA"); + openconnect_SSL_printf(vpninfo->https_ssl, sendbuf); + +#if 0 + openconnect_SSL_printf(vpninfo->https_ssl, "CONNECT /CSCOSSLC/tunnel HTTP/1.1\r\n"); + openconnect_SSL_printf(vpninfo->https_ssl, "Host: %s\r\n", vpninfo->hostname); + openconnect_SSL_printf(vpninfo->https_ssl, "User-Agent: %s\r\n", vpninfo->useragent); + openconnect_SSL_printf(vpninfo->https_ssl, "Cookie: webvpn=%s\r\n", vpninfo->cookie); + openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Version: 1\r\n"); + openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Hostname: %s\r\n", vpninfo->localname); + if (vpninfo->deflate) + openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Accept-Encoding: deflate;q=1.0\r\n"); + openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-MTU: %d\r\n", vpninfo->mtu); + openconnect_SSL_printf(vpninfo->https_ssl, "X-CSTP-Address-Type: %s\r\n", + vpninfo->disable_ipv6?"IPv4":"IPv6,IPv4"); + openconnect_SSL_printf(vpninfo->https_ssl, "X-DTLS-Master-Secret: "); + for (i = 0; i < sizeof(vpninfo->dtls_secret); i++) + openconnect_SSL_printf(vpninfo->https_ssl, "%02X", vpninfo->dtls_secret[i]); + openconnect_SSL_printf(vpninfo->https_ssl, "\r\nX-DTLS-CipherSuite: %s\r\n\r\n", + vpninfo->dtls_ciphers?:"AES256-SHA:AES128-SHA:DES-CBC3-SHA:DES-CBC-SHA"); +#endif + } if (openconnect_SSL_gets(vpninfo->https_ssl, buf, 65536) < 0) { vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n"); @@ -128,6 +152,8 @@ vpninfo->progress(vpninfo, PRG_ERR, "Failed to open HTTPS connection to %s\n", vpninfo->hostname); + LOG_VPNINFO("V_HTTPSFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } goto retry; @@ -152,8 +178,11 @@ vpninfo->progress(vpninfo, PRG_ERR, "Got inappropriate HTTP CONNECT response: %s\n", buf); - if (!strncmp(buf, "HTTP/1.1 401 ", 13)) + if (!strncmp(buf, "HTTP/1.1 401 ", 13)) { + LOG_VPNINFO("V_HTTPSFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(2); + } return -EINVAL; } @@ -381,11 +410,12 @@ vpninfo->progress(vpninfo, PRG_INFO, "sleep %ds, remaining timeout %ds\n", interval, timeout); + VPN_DEBUG("[VPN] sleep %ds, remaining timeout %ds\n", interval, timeout); sleep(interval); if (killed) return 1; timeout -= interval; - interval += vpninfo->reconnect_interval; + //interval += vpninfo->reconnect_interval; if (interval > RECONNECT_INTERVAL_MAX) interval = RECONNECT_INTERVAL_MAX; } @@ -596,6 +626,9 @@ peer_dead: vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n"); do_reconnect: + LOG_VPNSTAT(S_VPN_RECONNECTING); + VPN_DEBUG("[VPN] Reconnecting..., please wait\n"); + openconnect_close_https(vpninfo); /* It's already deflated in the old stream. Extremely @@ -606,8 +639,11 @@ if (cstp_reconnect(vpninfo)) { vpninfo->progress(vpninfo, PRG_ERR, "Reconnect failed\n"); vpninfo->quit_reason = "CSTP reconnect failed"; + VPN_DEBUG("[VPN] Reconnect failed."); return 1; } + VPN_DEBUG("[VPN] Reconnect successed."); + LOG_VPNSTAT(S_VPN_CONNECTED); /* I think we can leave DTLS to its own devices; when we reconnect with the same master secret, we do seem to get the same sessid */ return 1; diff -ur /home/nmav/cvs/openconnect-2.25/http.c openconnect-2.25/http.c --- /home/nmav/cvs/openconnect-2.25/http.c 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/http.c 2011-07-07 02:29:03.000000000 +0200 @@ -636,6 +636,8 @@ buflen = process_http_response(vpninfo, &result, NULL, &form_buf); if (buflen < 0) { /* We'll already have complained about whatever offended us */ + LOG_VPNINFO("V_NegFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } diff -ur /home/nmav/cvs/openconnect-2.25/main.c openconnect-2.25/main.c --- /home/nmav/cvs/openconnect-2.25/main.c 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/main.c 2011-07-07 02:29:03.000000000 +0200 @@ -100,6 +100,7 @@ {"libproxy", 0, 0, 0x07}, {"no-http-keepalive", 0, 0, 0x08}, {"no-cert-check", 0, 0, 0x09}, + {"pwd", 1, 0, 'a'}, {NULL, 0, 0, 0}, }; @@ -193,6 +194,11 @@ uid_t uid = getuid(); int opt; + //update status - connecting + LOG_VPNSTAT(S_VPN_CONNECTING); + + VPN_DEBUG("[VPN] welcome to openconnect!!!\n"); + openconnect_init_openssl(); vpninfo = malloc(sizeof(*vpninfo)); @@ -224,7 +230,7 @@ else vpninfo->localname = "localhost"; - while ((opt = getopt_long(argc, argv, "bC:c:Ddg:hi:k:K:lpP:Q:qSs:U:u:Vvx:", + while ((opt = getopt_long(argc, argv, "a:bC:c:Ddg:hi:k:K:lpP:Q:qSs:U:u:Vvx:", long_options, NULL))) { if (opt < 0) break; @@ -411,6 +417,9 @@ free(vpninfo->useragent); vpninfo->useragent = optarg; break; + case 'a': + vpninfo->password = optarg; + break; default: usage(); } @@ -459,10 +468,14 @@ &group, 443)) { fprintf(stderr, "Failed to parse server URL '%s'\n", url); + LOG_VPNINFO("V_URLFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } if (scheme && strcmp(scheme, "https")) { fprintf(stderr, "Only https:// permitted for server URL\n"); + LOG_VPNINFO("V_HTTPSOnly"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } if (group) { @@ -477,11 +490,17 @@ set_openssl_ui(); #endif + VPN_DEBUG("[VPN] init OK.\n"); + if (!vpninfo->cookie && openconnect_obtain_cookie(vpninfo)) { fprintf(stderr, "Failed to obtain WebVPN cookie\n"); + LOG_VPNINFO("V_CookieFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } + VPN_DEBUG("[VPN] get cookie OK:\n%s\n", vpninfo->cookie); + if (cookieonly) { printf("%s\n", vpninfo->cookie); if (cookieonly == 1) @@ -490,14 +509,23 @@ } if (make_cstp_connection(vpninfo)) { fprintf(stderr, "Creating SSL connection failed\n"); + VPN_DEBUG("[VPN] cstp connection failed ...\n"); + LOG_VPNINFO("V_CSTPFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } + VPN_DEBUG("[VPN] cstp connection OK.\n"); + if (setup_tun(vpninfo)) { fprintf(stderr, "Set up tun device failed\n"); + LOG_VPNINFO("V_TUNFail"); + LOG_VPNSTAT(S_VPN_DISCONNECTED); exit(1); } + VPN_DEBUG("[VPN] tun setup OK.\n"); + if (uid != getuid()) { if (setuid(uid)) { fprintf(stderr, "Failed to set uid %d\n", uid); @@ -530,7 +558,11 @@ exit(0); } } - vpn_mainloop(vpninfo); + + //update status - connected + LOG_VPNSTAT(S_VPN_CONNECTED); + + vpn_mainloop(vpninfo); exit(1); } diff -ur /home/nmav/cvs/openconnect-2.25/mainloop.c openconnect-2.25/mainloop.c --- /home/nmav/cvs/openconnect-2.25/mainloop.c 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/mainloop.c 2011-07-07 02:29:03.000000000 +0200 @@ -130,8 +130,14 @@ select(vpninfo->select_nfds, &rfds, &wfds, &efds, &tv); } + //update status - disconnecting + LOG_VPNSTAT(S_VPN_DISCONNECTING); cstp_bye(vpninfo, vpninfo->quit_reason); + VPN_DEBUG("[VPN] Quit - %s\n", vpninfo->quit_reason); + //update status - disconnected + LOG_VPNSTAT(S_VPN_DISCONNECTED); + shutdown_tun(vpninfo); return 0; } diff -ur /home/nmav/cvs/openconnect-2.25/Makefile openconnect-2.25/Makefile --- /home/nmav/cvs/openconnect-2.25/Makefile 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/Makefile 2011-07-07 02:29:03.000000000 +0200 @@ -3,6 +3,10 @@ # set OPENSSL to the path to the source directory that you built openssl in # # OPENSSL := ../openssl-0.9.8i +OPENSSL := ../component/openssl-0.9.8k + +CC = arm-linux-gcc +AR = arm-linux-ar ifdef RPM_OPT_FLAGS OPT_FLAGS := $(RPM_OPT_FLAGS) @@ -15,7 +19,7 @@ # dir; there's no need to install it anywhere (we link it statically). ifdef OPENSSL SSL_CFLAGS += -I$(OPENSSL)/include -SSL_LDFLAGS += $(OPENSSL)/libssl.a $(OPENSSL)/libcrypto.a +SSL_LDFLAGS += $(OPENSSL)/libssl.so $(OPENSSL)/libcrypto.so else ifeq ($(wildcard /usr/include/openssl),) $(error "No OpenSSL in /usr/include/openssl. Cannot continue"); @@ -24,23 +28,25 @@ SSL_LDFLAGS += -lcrypto -lssl endif -XML2_CFLAGS += $(shell xml2-config --cflags) -XML2_LDFLAGS += $(shell xml2-config --libs) +#XML2_CFLAGS += $(shell xml2-config --cflags) +#XML2_LDFLAGS += $(shell xml2-config --libs) +XML2_CFLAGS += -I../component/libxml2-2.7.7/include/libxml2 +XML2_LDFLAGS += -L../component/libxml2-2.7.7/lib -lxml2 -lz -lm -ldl ifeq ($(XML2_LDFLAGS),) $(error "No libxml2 support. Cannot continue"); endif -GTK_CFLAGS += $(shell pkg-config --cflags gtk+-x11-2.0 gthread-2.0 2>/dev/null) -GTK_LDFLAGS += $(shell pkg-config --libs gtk+-x11-2.0 gthread-2.0 2>/dev/null) -ifeq ($(GTK_LDFLAGS),) +#GTK_CFLAGS += $(shell pkg-config --cflags gtk+-x11-2.0 gthread-2.0 2>/dev/null) +#GTK_LDFLAGS += $(shell pkg-config --libs gtk+-x11-2.0 gthread-2.0 2>/dev/null) +#ifeq ($(GTK_LDFLAGS),) MISSINGPKGS += gtk+-x11-2.0 -endif +#endif -GCONF_CFLAGS += $(shell pkg-config --cflags gconf-2.0 2>/dev/null) -GCONF_LDFLAGS += $(shell pkg-config --libs gconf-2.0 2>/dev/null) -ifeq ($(GCONF_LDFLAGS),) +#GCONF_CFLAGS += $(shell pkg-config --cflags gconf-2.0 2>/dev/null) +#GCONF_LDFLAGS += $(shell pkg-config --libs gconf-2.0 2>/dev/null) +#ifeq ($(GCONF_LDFLAGS),) MISSINGPKGS += gconf-2.0 -endif +#endif CFLAGS := $(OPT_FLAGS) $(SSL_CFLAGS) $(XML2_CFLAGS) $(EXTRA_CFLAGS) LDFLAGS := -lz $(SSL_LDFLAGS) $(XML2_LDFLAGS) $(EXTRA_LDFLAGS) diff -ur /home/nmav/cvs/openconnect-2.25/openconnect.h openconnect-2.25/openconnect.h --- /home/nmav/cvs/openconnect-2.25/openconnect.h 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/openconnect.h 2011-07-07 02:29:03.000000000 +0200 @@ -34,6 +34,7 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#include <sys/file.h> #ifdef OPENCONNECT_LIBPROXY #include LIBPROXY_HDR #endif @@ -274,6 +275,37 @@ #define AC_PKT_COMPRESSED 8 /* Compressed data */ #define AC_PKT_TERM_SERVER 9 /* Server kick */ +typedef enum { + S_VPN_CONNECTING = 0, + S_VPN_CONNECTED, + S_VPN_RECONNECTING, + S_VPN_DISCONNECTING, + S_VPN_DISCONNECTED, + S_VPN_PAUSING, + S_VPN_OPEN_PAUSED, +}vpn_state; + +#define LOG_VPNSTAT(x) \ + { \ + FILE *fp = fopen("/tmp/vpnstat", "w"); \ + if(fp) { \ + fprintf(fp, "%d", x); \ + fclose(fp); \ + } \ + } + +#define LOG_VPNINFO(f, args...) \ + { \ + FILE *fp = fopen("/tmp/vpninfo", "w"); \ + if(fp) { \ + flock(fp, LOCK_EX); \ + fprintf(fp, f, ## args); \ + flock(fp, LOCK_UN); \ + fsync(fp); \ + fclose(fp); \ + } \ + } + /* Ick */ #if OPENSSL_VERSION_NUMBER >= 0x00909000L #define method_const const @@ -350,4 +382,14 @@ /* version.c */ extern char openconnect_version[]; +#define VPN_DEBUG(f,args...) \ + {\ + FILE *fp_tty = fopen("/dev/console", "w" );\ + if (fp_tty) {\ + fprintf( fp_tty, f , ## args );\ + fclose( fp_tty );\ + }\ + } + + #endif /* __OPENCONNECT_ANYCONNECT_H */ diff -ur /home/nmav/cvs/openconnect-2.25/ssl.c openconnect-2.25/ssl.c --- /home/nmav/cvs/openconnect-2.25/ssl.c 2010-05-15 10:23:37.000000000 +0200 +++ openconnect-2.25/ssl.c 2011-07-07 02:29:03.000000000 +0200 @@ -801,9 +801,82 @@ vpninfo->proxy?:vpninfo->hostname); return -EINVAL; } - if (connect(ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen)) + + //use non-block connect instead, because block connect will block up to more than 5 minutes + //in the case server reboot, the recovery time will too long + // Set non-blocking + long arg; + int res; + struct timeval tv; + fd_set soc_set; + int valopt; + socklen_t lon; + if( (arg = fcntl(ssl_sock, F_GETFL, NULL)) < 0) { + fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno)); + goto reconn_err; + } + arg |= O_NONBLOCK; + if( fcntl(ssl_sock, F_SETFL, arg) < 0) { + fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno)); + goto reconn_err; + } + + //Try to connect with timeout + res = connect(ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen); + if(res < 0) { + if (errno == EINPROGRESS) { + fprintf(stderr, "EINPROGRESS in connect() - selecting\n"); + do { + tv.tv_sec = 10; + tv.tv_usec = 0; + FD_ZERO(&soc_set); + FD_SET(ssl_sock, &soc_set); + res = select(ssl_sock+1, NULL, &soc_set, NULL, &tv); + if (res < 0 && errno != EINTR) { + fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno)); + goto reconn_err; + } + else if (res > 0) { + // Socket selected for write + lon = sizeof(int); + if (getsockopt(ssl_sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) { + fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno)); + goto reconn_err; + } + // Check the value returned... + if (valopt) { + fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt)); + goto reconn_err; + } + break; + } + else { + fprintf(stderr, "Timeout in select() - Cancelling!\n"); + goto reconn_err; + } + } while (0); + } + else { + fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno)); + goto reconn_err; + } + } + + // Set to blocking mode again... + if( (arg = fcntl(ssl_sock, F_GETFL, NULL)) < 0) { + fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno)); + goto reconn_err; + } + arg &= (~O_NONBLOCK); + if( fcntl(ssl_sock, F_SETFL, arg) < 0) { + fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno)); goto reconn_err; + } + /* + if (connect(ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen)) + goto reconn_err; + */ } else { struct addrinfo hints, *result, *rp; char *hostname; -------------- next part -------------- A non-text attachment was scrubbed... Name: vpnc-script.xz Type: application/x-xz Size: 4480 bytes Desc: not available URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20160620/7a635531/attachment-0001.xz>