From 3f9a375785f8fb0fd936771c04c9323cf9a630fa Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 26 Dec 2016 17:20:46 +0100 Subject: [PATCH 3/3] RFC: Introduced functions to request the retrieval of server's XML config That is introduced openconnect_set_xmlconfig() and openconnect_get_xmlconfig(). The former instructs the library to retrieve the server's XML configuration and the latter retrieves the configuration for the application. These deprecate the openconnect_set_xmlsha1() and openconnect_write_new_config_vfn callback function. Signed-off-by: Nikos Mavrogiannopoulos --- auth.c | 17 +++++++++++++---- jni.c | 28 ++++++++++++++++++++++++++++ libopenconnect.map.in | 5 +++++ library.c | 20 ++++++++++++++++++++ main.c | 1 + openconnect-internal.h | 6 +++++- openconnect.h | 17 +++++++++++++++++ 7 files changed, 89 insertions(+), 5 deletions(-) diff --git a/auth.c b/auth.c index 9ccb08f..01f9709 100644 --- a/auth.c +++ b/auth.c @@ -907,10 +907,12 @@ static int fetch_config(struct openconnect_info *vpninfo) char local_sha1_ascii[(SHA1_SIZE * 2)+1]; int i; - if (!vpninfo->profile_url || !vpninfo->write_new_config) + if (!vpninfo->profile_url || (!vpninfo->retrieve_xmlconfig && !vpninfo->write_new_config)) { return -ENOENT; + } - if (vpninfo->profile_sha1 && !strncasecmp(vpninfo->xmlsha1, vpninfo->profile_sha1, SHA1_SIZE * 2)) { + if (vpninfo->write_new_config && vpninfo->profile_sha1 && + !strncasecmp(vpninfo->xmlsha1, vpninfo->profile_sha1, SHA1_SIZE * 2)) { vpn_progress(vpninfo, PRG_TRACE, _("Not downloading XML profile because SHA1 already matches\n")); return 0; @@ -972,8 +974,15 @@ static int fetch_config(struct openconnect_info *vpninfo) vpn_progress(vpninfo, PRG_DEBUG, _("Downloaded new XML profile\n")); - result = vpninfo->write_new_config(vpninfo->cbdata, buf->data, buf->pos); - buf_free(buf); + if (vpninfo->write_new_config) { + result = vpninfo->write_new_config(vpninfo->cbdata, buf->data, buf->pos); + buf_free(buf); + } else { + free(vpninfo->xmlconfig_data); + vpninfo->xmlconfig_data = (void*)buf->data; + vpninfo->xmlconfig_size = buf->buf_len; + } + return result; } diff --git a/jni.c b/jni.c index d72ac2e..1f86ea4 100644 --- a/jni.c +++ b/jni.c @@ -905,6 +905,34 @@ JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setMobil release_cstring(ctx->jenv, jarg2, arg2); } +JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setXmlConfig( + JNIEnv *jenv, jobject jobj, jstring jarg0) +{ + struct libctx *ctx = getctx(jenv, jobj); + + if (!ctx) + return; + openconnect_set_xmlconfig(ctx->vpninfo, arg); +} + +JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getXmlConfig( + JNIEnv *jenv, jobject jobj, jstring jarg0) +{ + struct libctx *ctx = getctx(jenv, jobj); + ssize_t str_size; + unsigned char *str; + + if (!ctx) + return NULL; + + str_size = openconnect_get_xmlconfig(ctx->vpninfo, &str); + if (str_size <= 0) { + return NULL; + } + + return dup_to_jstring(jenv, str); +} + /* class methods (general library info) */ JNIEXPORT jstring JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_getVersion( diff --git a/libopenconnect.map.in b/libopenconnect.map.in index 44eea34..ca5a95c 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -92,6 +92,11 @@ OPENCONNECT_5_4 { openconnect_set_pass_tos; } OPENCONNECT_5_3; +OPENCONNECT_5_5 { + global: + openconnect_set_xmlconfig; +} OPENCONNECT_5_4; + OPENCONNECT_PRIVATE { global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ @SYMVER_WIN32_STRERROR@ openconnect_fopen_utf8; diff --git a/library.c b/library.c index 824338e..6dc9619 100644 --- a/library.c +++ b/library.c @@ -288,6 +288,7 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo) free(vpninfo->cafile); free(vpninfo->ifname); free(vpninfo->dtls_cipher); + free(vpninfo->xmlconfig_data); #ifdef OPENCONNECT_GNUTLS gnutls_free(vpninfo->cstp_cipher); /* In OpenSSL this is const */ #ifdef HAVE_DTLS @@ -414,6 +415,25 @@ int openconnect_set_hostname(struct openconnect_info *vpninfo, return 0; } +void openconnect_set_xmlconfig(struct openconnect_info *vpninfo, + unsigned val) +{ + vpninfo->retrieve_xmlconfig = val; +} + +ssize_t openconnect_get_xmlconfig(struct openconnect_info *vpninfo, + unsigned char **xmlconfig) +{ + if (!vpninfo->retrieve_xmlconfig) + return -1; + + if (!vpninfo->xmlconfig_size) + return -1; + + *xmlconfig = vpninfo->xmlconfig_data; + return vpninfo->xmlconfig_size; +} + char *openconnect_get_urlpath(struct openconnect_info *vpninfo) { return vpninfo->urlpath; diff --git a/main.c b/main.c index 71be303..c41009b 100644 --- a/main.c +++ b/main.c @@ -1338,6 +1338,7 @@ int main(int argc, char **argv) case 'x': vpninfo->xmlconfig = keep_config_arg(); vpninfo->write_new_config = write_new_config; + openconnect_set_xmlconfig(vpninfo, 1); break; case OPT_KEY_PASSWORD_FROM_FSID: do_passphrase_from_fsid = 1; diff --git a/openconnect-internal.h b/openconnect-internal.h index a24a9e4..1cbc277 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -377,6 +377,10 @@ struct openconnect_info { char *csd_scriptname; xmlNode *opaque_srvdata; + unsigned retrieve_xmlconfig; + unsigned char *xmlconfig_data; + size_t xmlconfig_size; + char *profile_url; char *profile_sha1; @@ -406,7 +410,7 @@ struct openconnect_info { char *cert_password; char *cafile; unsigned no_system_trust; - const char *xmlconfig; + char *xmlconfig; char xmlsha1[(SHA1_SIZE * 2) + 1]; char *authgroup; int nopasswd; diff --git a/openconnect.h b/openconnect.h index fc23c3c..5efc911 100644 --- a/openconnect.h +++ b/openconnect.h @@ -36,6 +36,10 @@ extern "C" { #define OPENCONNECT_API_VERSION_MINOR 4 /* + * API version 5.5: + * - Add openconnect_set_xmlconfig() + * - Add openconnect_get_xmlconfig() + * * API version 5.4 (v7.08; 2016-12-13): * - Add openconnect_set_pass_tos() * @@ -427,6 +431,19 @@ const char *openconnect_get_hostname(struct openconnect_info *); * the certificate matches the server name. */ const char *openconnect_get_dnsname(struct openconnect_info *); +/* If called with non zero instructs the client to retrieve + * the server's XML configuration. This can be obtained + * using openconnect_get_xmlconfig() + */ +void openconnect_set_xmlconfig(struct openconnect_info *vpninfo, + unsigned val); + +/* returns a negative value if no config was present. The + * returned data should be treated as constant. + */ +ssize_t openconnect_get_xmlconfig(struct openconnect_info *vpninfo, + unsigned char **xmlconfig); + 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.8.3.1