Add two new public functions: * int openconnect_get_supported_protocols(struct oc_vpn_proto **protos) Fetches a list of protocols supported by the client. Each supported protocol has a short name (as accepted by the --protocol command-line option), pretty name, longer description, and list of flags. The return value of the function is the number of protocols supported (or negative if an error occurred). The flags indicate features that are meaningful for this protocol, to be used by tools like the Networkmanager configuration UI. Current flags: * OC_PROTO_PROXY: can connect via HTTP or SOCKS proxy * OC_PROTO_CSD: supports verification of the client via CSD trojan * OC_PROTO_AUTH_CERT: supports authentication by client certificate * OC_PROTO_AUTH_OTP: supports authentication by OATH HOTP/TOTP token * OC_PROTO_AUTH_STOKEN: supports authentication by RSA SecurID token (stoken) * void openconnect_free_supported_protocols(struct oc_vpn_proto *protos) Frees the list of protocols fetched by openconnect_get_supported_protocols() The description of the "anyconnect" protocol matches the IETF draft standard for openconnect VPN (https://tools.ietf.org/html/draft-mavrogiannopoulos-openconnect-00). Signed-off-by: Daniel Lenski <dlenski at gmail.com> --- libopenconnect.map.in | 6 ++++++ library.c | 32 ++++++++++++++++++++++++++++++++ openconnect-internal.h | 3 +++ openconnect.h | 26 +++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/libopenconnect.map.in b/libopenconnect.map.in index 44eea34..04b8ed5 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -92,6 +92,12 @@ OPENCONNECT_5_4 { openconnect_set_pass_tos; } OPENCONNECT_5_3; +OPENCONNECT_5_5 { + global: + openconnect_get_supported_protocols; + openconnect_free_supported_protocols; +} 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 58ccf93..fb835ec 100644 --- a/library.c +++ b/library.c @@ -109,6 +109,9 @@ err: const struct vpn_proto openconnect_protos[] = { { .name = "anyconnect", + .pretty_name = N_("Cisco AnyConnect or openconnect"), + .description = N_("Compatible with Cisco AnyConnect SSL VPN, as well as ocserv"), + .flags = OC_PROTO_PROXY | OC_PROTO_CSD | OC_PROTO_AUTH_CERT | OC_PROTO_AUTH_OTP | OC_PROTO_AUTH_STOKEN, .vpn_close_session = cstp_bye, .tcp_connect = cstp_connect, .tcp_mainloop = cstp_mainloop, @@ -122,6 +125,9 @@ const struct vpn_proto openconnect_protos[] = { #endif }, { .name = "nc", + .pretty_name = N_("Juniper Network Connect"), + .description = N_("Compatible with Juniper Network Connect / Pulse Secure SSL VPN"), + .flags = OC_PROTO_PROXY | OC_PROTO_CSD | OC_PROTO_AUTH_CERT | OC_PROTO_AUTH_OTP, .vpn_close_session = oncp_bye, .tcp_connect = oncp_connect, .tcp_mainloop = oncp_mainloop, @@ -137,6 +143,9 @@ const struct vpn_proto openconnect_protos[] = { #endif }, { .name = "gp", + .pretty_name = _N("Palo Alto Networks GlobalProtect"), + .description = _N("Compatible with Palo Alto Networks (PAN) GlobalProtect SSL VPN"), + .flags = OC_PROTO_PROXY | OC_PROTO_AUTH_CERT, .vpn_close_session = gpst_bye, .tcp_connect = gpst_setup, .tcp_mainloop = gpst_mainloop, @@ -154,6 +163,29 @@ const struct vpn_proto openconnect_protos[] = { { /* NULL */ } }; +int openconnect_get_supported_protocols(struct oc_vpn_proto **protos) +{ + struct oc_vpn_proto *pr; + const struct vpn_proto *p; + + *protos = pr = calloc(sizeof(openconnect_protos)/sizeof(*openconnect_protos), sizeof(*pr)); + if (!pr) + return -ENOMEM; + + for (p = openconnect_protos; p->name; p++, pr++) { + pr->name = p->name; + pr->pretty_name = p->pretty_name; + pr->description = p->description; + pr->flags = p->flags; + } + return (p - openconnect_protos); +} + +void openconnect_free_supported_protocols(struct oc_vpn_proto *protos) +{ + free((void *)protos); +} + int openconnect_set_protocol(struct openconnect_info *vpninfo, const char *protocol) { const struct vpn_proto *p; diff --git a/openconnect-internal.h b/openconnect-internal.h index ee4edbd..67a122f 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -258,6 +258,9 @@ struct http_auth_state { struct vpn_proto { const char *name; + const char *pretty_name; + const char *description; + unsigned int flags; int (*vpn_close_session)(struct openconnect_info *vpninfo, const char *reason); /* This does the full authentication, calling back as appropriate */ diff --git a/openconnect.h b/openconnect.h index fc23c3c..e97dacb 100644 --- a/openconnect.h +++ b/openconnect.h @@ -33,9 +33,13 @@ extern "C" { #endif #define OPENCONNECT_API_VERSION_MAJOR 5 -#define OPENCONNECT_API_VERSION_MINOR 4 +#define OPENCONNECT_API_VERSION_MINOR 5 /* + * API version 5.5: + * - Add openconnect_get_supported_protocols() + * - Add openconnect_free_supported_protocols() + * * API version 5.4 (v7.08; 2016-12-13): * - Add openconnect_set_pass_tos() * @@ -166,6 +170,23 @@ extern "C" { /****************************************************************************/ +/* Enumeration of supported VPN protocols */ + +#define OC_PROTO_PROXY (1<<0) +#define OC_PROTO_CSD (1<<1) +#define OC_PROTO_AUTH_CERT (1<<2) +#define OC_PROTO_AUTH_OTP (1<<3) +#define OC_PROTO_AUTH_STOKEN (1<<4) + +struct oc_vpn_proto { + const char *name; + const char *pretty_name; + const char *description; + unsigned int flags; +}; + +/****************************************************************************/ + /* Authentication form processing */ #define OC_FORM_OPT_TEXT 1 @@ -640,6 +661,9 @@ int openconnect_has_oath_support(void); int openconnect_has_yubioath_support(void); int openconnect_has_system_key_support(void); +/* Query and select from among supported protocols */ +int openconnect_get_supported_protocols(struct oc_vpn_proto **protos); +void openconnect_free_supported_protocols(struct oc_vpn_proto *protos); int openconnect_set_protocol(struct openconnect_info *vpninfo, const char *protocol); struct addrinfo; -- 2.7.4