Skip to content

Instantly share code, notes, and snippets.

@robbat2
Created November 15, 2019 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robbat2/ba6758d57c5571382c68f36585992b66 to your computer and use it in GitHub Desktop.
Save robbat2/ba6758d57c5571382c68f36585992b66 to your computer and use it in GitHub Desktop.
From: Corey Wright <cwright@digitalocean.com>
Date: 2019/10/21 08:39 UTC
Subject: Combined HIP patch
Fixes: https://jira.internal.digitalocean.com/browse/SEC-2994
Signed-off-by: Robin H. Johnson <rjohnson@digitalocean.com>
diff -urNpd openconnect-8.05~/gpst.c openconnect-8.05/gpst.c
--- openconnect-8.05~/gpst.c 2019-07-16 05:40:28.000000000 -0500
+++ openconnect-8.05/gpst.c 2019-10-21 10:35:09.029687027 -0500
@@ -603,6 +603,12 @@ static int gpst_parse_config_xml(struct
vpninfo->ssl_times.dpd = 10;
vpninfo->ssl_times.keepalive = vpninfo->esp_ssl_fallback = vpninfo->ssl_times.dpd;
+ /* Set 1-hour/3600-second HIP check (same as official client) unless
+ * overridden with --force-hip-check */
+ if (!vpninfo->ssl_times.hip)
+ vpninfo->ssl_times.hip = 3600;
+ vpninfo->ssl_times.last_hip = time(NULL);
+
free(s);
return 0;
}
@@ -1000,6 +1006,22 @@ static int run_hip_script(struct opencon
#endif /* !_WIN32 && !__native_client__ */
}
+static int check_and_maybe_submit_hip_report(struct openconnect_info *vpninfo)
+{
+ int ret;
+
+ ret = check_or_submit_hip_report(vpninfo, NULL);
+ if (ret == -EAGAIN) {
+ vpn_progress(vpninfo, PRG_DEBUG,
+ _("Gateway says HIP report submission is needed.\n"));
+ ret = run_hip_script(vpninfo);
+ } else if (ret == 0)
+ vpn_progress(vpninfo, PRG_DEBUG,
+ _("Gateway says no HIP report submission is needed.\n"));
+
+ return ret;
+}
+
int gpst_setup(struct openconnect_info *vpninfo)
{
int ret;
@@ -1014,16 +1036,9 @@ int gpst_setup(struct openconnect_info *
goto out;
/* Check HIP */
- ret = check_or_submit_hip_report(vpninfo, NULL);
- if (ret == -EAGAIN) {
- vpn_progress(vpninfo, PRG_DEBUG,
- _("Gateway says HIP report submission is needed.\n"));
- ret = run_hip_script(vpninfo);
- if (ret != 0)
- goto out;
- } else if (ret == 0)
- vpn_progress(vpninfo, PRG_DEBUG,
- _("Gateway says no HIP report submission is needed.\n"));
+ ret = check_and_maybe_submit_hip_report(vpninfo);
+ if (ret)
+ goto out;
/* We do NOT actually start the HTTPS tunnel yet if we want to
* use ESP, because the ESP tunnel won't work if the HTTPS tunnel
@@ -1054,9 +1069,12 @@ int gpst_mainloop(struct openconnect_inf
vpninfo->dtls_state = DTLS_CONNECTED;
/* fall through */
case DTLS_CONNECTED:
+ ret = keepalive_action(&vpninfo->ssl_times, timeout);
/* Rekey if needed */
- if (keepalive_action(&vpninfo->ssl_times, timeout) == KA_REKEY)
+ if (ret == KA_REKEY)
goto do_rekey;
+ else if (ret == KA_HIP)
+ goto do_hip;
return 0;
case DTLS_SECRET:
case DTLS_SLEEPING:
@@ -1238,6 +1256,19 @@ int gpst_mainloop(struct openconnect_inf
vpninfo->current_ssl_pkt = (struct pkt *)&dpd_pkt;
goto handle_outgoing;
+ case KA_HIP:
+ do_hip:
+ vpn_progress(vpninfo, PRG_INFO, _("GlobalProtect HIP check due\n"));
+ ret = check_and_maybe_submit_hip_report(vpninfo);
+ /* Close HTTPS socket or server will probably close it before
+ we need it again, eg next HIP check, and then it'll just
+ blow up on us after we write to it, but can't read from it */
+ openconnect_close_https(vpninfo, 0);
+ if (ret) {
+ vpn_progress(vpninfo, PRG_ERR, _("HIP check or report failed\n"));
+ vpninfo->quit_reason = "HIP check or report failed";
+ return ret;
+ }
}
diff -urNpd openconnect-8.05~/libopenconnect.map.in openconnect-8.05/libopenconnect.map.in
--- openconnect-8.05~/libopenconnect.map.in 2018-12-21 06:20:31.000000000 -0600
+++ openconnect-8.05/libopenconnect.map.in 2019-10-21 10:35:09.033687030 -0500
@@ -103,6 +103,11 @@ OPENCONNECT_5_5 {
openconnect_set_version_string;
} OPENCONNECT_5_4;
+OPENCONNECT_5_6 {
+ global:
+ openconnect_set_hip_check;
+} OPENCONNECT_5_5;
+
OPENCONNECT_PRIVATE {
global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ @SYMVER_WIN32_STRERROR@
openconnect_fopen_utf8;
diff -urNpd openconnect-8.05~/library.c openconnect-8.05/library.c
--- openconnect-8.05~/library.c 2019-08-02 12:52:36.000000000 -0500
+++ openconnect-8.05/library.c 2019-10-21 10:35:09.029687027 -0500
@@ -577,6 +577,11 @@ void openconnect_set_dpd(struct openconn
vpninfo->dtls_times.dpd = vpninfo->ssl_times.dpd = 2;
}
+void openconnect_set_hip_check(struct openconnect_info *vpninfo, int seconds)
+{
+ vpninfo->ssl_times.hip = seconds;
+}
+
int openconnect_get_idle_timeout(struct openconnect_info *vpninfo)
{
return vpninfo->idle_timeout;
diff -urNpd openconnect-8.05~/main.c openconnect-8.05/main.c
--- openconnect-8.05~/main.c 2019-05-18 12:51:27.000000000 -0500
+++ openconnect-8.05/main.c 2019-10-21 10:35:09.033687030 -0500
@@ -161,6 +161,7 @@ enum {
OPT_DTLS12_CIPHERS,
OPT_DUMP_HTTP,
OPT_FORCE_DPD,
+ OPT_FORCE_HIP_CHECK,
OPT_GNUTLS_DEBUG,
OPT_JUNIPER,
OPT_KEY_PASSWORD_FROM_FSID,
@@ -266,6 +267,7 @@ static const struct option long_options[
OPTION("no-http-keepalive", 0, OPT_NO_HTTP_KEEPALIVE),
OPTION("no-cert-check", 0, OPT_NO_CERT_CHECK),
OPTION("force-dpd", 1, OPT_FORCE_DPD),
+ OPTION("force-hip-check", 1, OPT_FORCE_HIP_CHECK),
OPTION("non-inter", 0, OPT_NON_INTER),
OPTION("dtls-local-port", 1, OPT_DTLS_LOCAL_PORT),
OPTION("token-mode", 1, OPT_TOKEN_MODE),
@@ -900,6 +902,7 @@ static void usage(void)
printf("\n%s:\n", _("Server bugs"));
printf(" --no-http-keepalive %s\n", _("Disable HTTP connection re-use"));
printf(" --no-xmlpost %s\n", _("Do not attempt XML POST authentication"));
+ printf(" --force-hip-check=INTERVAL %s\n", _("Set HIP check interval in seconds"));
printf("\n");
@@ -1447,6 +1450,9 @@ int main(int argc, char **argv)
case OPT_FORCE_DPD:
openconnect_set_dpd(vpninfo, atoi(config_arg));
break;
+ case OPT_FORCE_HIP_CHECK:
+ openconnect_set_hip_check(vpninfo, atoi(config_arg));
+ break;
case OPT_DTLS_LOCAL_PORT:
vpninfo->dtls_local_port = atoi(config_arg);
break;
diff -urNpd openconnect-8.05~/mainloop.c openconnect-8.05/mainloop.c
--- openconnect-8.05~/mainloop.c 2019-07-16 05:40:28.000000000 -0500
+++ openconnect-8.05/mainloop.c 2019-10-21 10:33:47.917637304 -0500
@@ -361,6 +361,12 @@ int keepalive_action(struct keepalive_in
return KA_REKEY;
}
+ if (ka->hip &&
+ ka_check_deadline(timeout, now, ka->last_hip + ka->hip)) {
+ ka->last_hip = now;
+ return KA_HIP;
+ }
+
/* DPD is bidirectional -- PKT 3 out, PKT 4 back */
if (ka->dpd) {
time_t due = ka->last_rx + ka->dpd;
diff -urNpd openconnect-8.05~/openconnect.h openconnect-8.05/openconnect.h
--- openconnect-8.05~/openconnect.h 2019-09-11 18:31:04.000000000 -0500
+++ openconnect-8.05/openconnect.h 2019-10-21 10:35:09.033687030 -0500
@@ -33,9 +33,12 @@ extern "C" {
#endif
#define OPENCONNECT_API_VERSION_MAJOR 5
-#define OPENCONNECT_API_VERSION_MINOR 5
+#define OPENCONNECT_API_VERSION_MINOR 6
/*
+ * API version 5.6 (v8.02; 2019-08-04):
+ * - Add openconnect_set_hip_check()
+ *
* API version 5.5 (v8.00; 2019-01-05):
* - add openconnect_set_version_string()
* - add openconnect_set_key_password()
@@ -521,6 +524,7 @@ int openconnect_set_key_password(struct
const char *openconnect_get_ifname(struct openconnect_info *);
void openconnect_set_reqmtu(struct openconnect_info *, int reqmtu);
void openconnect_set_dpd(struct openconnect_info *, int min_seconds);
+void openconnect_set_hip_check(struct openconnect_info *, int seconds);
int openconnect_get_idle_timeout(struct openconnect_info *);
/* The returned structures are owned by the library and may be freed/replaced
diff -urNpd openconnect-8.05~/openconnect-internal.h openconnect-8.05/openconnect-internal.h
--- openconnect-8.05~/openconnect-internal.h 2019-07-16 06:30:34.000000000 -0500
+++ openconnect-8.05/openconnect-internal.h 2019-10-21 10:33:47.917637304 -0500
@@ -163,6 +163,7 @@ struct pkt {
#define KA_DPD_DEAD 2
#define KA_KEEPALIVE 3
#define KA_REKEY 4
+#define KA_HIP 5
#define DTLS_NOSECRET 0 /* Random secret has not been generated yet */
#define DTLS_SECRET 1 /* Secret is present, ready to attempt DTLS */
@@ -191,10 +192,12 @@ struct keepalive_info {
int keepalive;
int rekey;
int rekey_method;
+ int hip;
time_t last_rekey;
time_t last_tx;
time_t last_rx;
time_t last_dpd;
+ time_t last_hip;
};
struct pin_cache {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment