openconnect_get_hostname() usually returns an IP, because it is used for two-stage connections. Add a new API call that returns a hostname so certificate validation can be handled externally. Signed-off-by: Kevin Cernekee <cernekee at gmail.com> --- java/src/org/infradead/libopenconnect/LibOpenConnect.java | 1 + jni.c | 8 ++++++++ libopenconnect.map.in | 1 + library.c | 5 +++++ openconnect.h | 14 ++++++++++++++ 5 files changed, 29 insertions(+) diff --git a/java/src/org/infradead/libopenconnect/LibOpenConnect.java b/java/src/org/infradead/libopenconnect/LibOpenConnect.java index 8dc7452..3f70b2b 100644 --- a/java/src/org/infradead/libopenconnect/LibOpenConnect.java +++ b/java/src/org/infradead/libopenconnect/LibOpenConnect.java @@ -139,6 +139,7 @@ public abstract class LibOpenConnect { /* connection info */ public synchronized native String getHostname(); + public synchronized native String getDNSName(); public synchronized native String getUrlpath(); public synchronized native int getPort(); public synchronized native String getCookie(); diff --git a/jni.c b/jni.c index b5aa92d..bfcdaa5 100644 --- a/jni.c +++ b/jni.c @@ -1084,6 +1084,14 @@ JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getHo RETURN_STRING_END } +JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getDNSName( + JNIEnv *jenv, jobject jobj) +{ + RETURN_STRING_START + buf = openconnect_get_dnsname(ctx->vpninfo); + RETURN_STRING_END +} + JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getUrlpath( JNIEnv *jenv, jobject jobj) { diff --git a/libopenconnect.map.in b/libopenconnect.map.in index 49c2b14..974ccf7 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -78,6 +78,7 @@ OPENCONNECT_5_3 { global: openconnect_override_getaddrinfo; openconnect_get_cstp_compression; + openconnect_get_dnsname; openconnect_get_dtls_compression; openconnect_disable_ipv6; openconnect_set_localname; diff --git a/library.c b/library.c index 97be310..8524c15 100644 --- a/library.c +++ b/library.c @@ -376,6 +376,11 @@ const char *openconnect_get_hostname(struct openconnect_info *vpninfo) return vpninfo->unique_hostname?:vpninfo->hostname; } +const char *openconnect_get_dnsname(struct openconnect_info *vpninfo) +{ + return vpninfo->hostname; +} + int openconnect_set_hostname(struct openconnect_info *vpninfo, const char *hostname) { diff --git a/openconnect.h b/openconnect.h index 22f7c5e..d34aae0 100644 --- a/openconnect.h +++ b/openconnect.h @@ -45,6 +45,7 @@ extern "C" { * - Add ip_info->gateway_addr. * - Add openconnect_set_setup_tun_handler(). * - Add openconnect_set_reconnected_handler(). + * - Add openconnect_get_dnsname(). * * API version 5.2 (v7.05; 2015-03-10): * - Add openconnect_set_http_auth(), openconnect_set_protocol(). @@ -391,7 +392,20 @@ const char *openconnect_get_dtls_cipher(struct openconnect_info *); const char *openconnect_get_cstp_compression(struct openconnect_info *); const char *openconnect_get_dtls_compression(struct openconnect_info *); +/* Returns the IP address of the exact host to which the connection + * was made. In --cookieonly mode or in any other scenario involving + * a "two stage" connection, it is important to reconnect by IP because + * the server side may be using DNS trickery for load balancing. + * + * If the IP address is unavailable due to the use of a proxy, this will + * fall back to returning the DNS name. */ const char *openconnect_get_hostname(struct openconnect_info *); + +/* Returns the hostname parsed out of the server name URL. This is + * intended to be used by the validate_peer_cert callback to check that + * the certificate matches the server name. */ +const char *openconnect_get_dnsname(struct openconnect_info *); + int openconnect_set_hostname(struct openconnect_info *, const char *); char *openconnect_get_urlpath(struct openconnect_info *); int openconnect_set_urlpath(struct openconnect_info *, const char *); -- 1.9.1