From 0df9e85a1b085457b2314861d0c934bf6a3c79a9 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 15 Apr 2019 14:19:38 +0100 Subject: [PATCH] Allow ESP functions to be overridden Signed-off-by: David Woodhouse --- esp.c | 14 ++++++++------ gnutls-esp.c | 13 +++++++++++-- gpst.c | 2 +- oncp.c | 2 +- openconnect-internal.h | 7 ++++--- openssl-esp.c | 15 ++++++++++++--- 6 files changed, 37 insertions(+), 16 deletions(-) diff --git a/esp.c b/esp.c index 1b907435..48884b79 100644 --- a/esp.c +++ b/esp.c @@ -147,14 +147,14 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable) pkt->len = len; if (pkt->esp.spi == esp->spi) { - if (decrypt_esp_packet(vpninfo, esp, pkt)) + if (vpninfo->decrypt_esp_packet(vpninfo, esp, pkt)) continue; } else if (pkt->esp.spi == old_esp->spi && ntohl(pkt->esp.seq) + esp->seq < vpninfo->old_esp_maxseq) { vpn_progress(vpninfo, PRG_TRACE, _("Received ESP packet from old SPI 0x%x, seq %u\n"), (unsigned)ntohl(old_esp->spi), (unsigned)ntohl(pkt->esp.seq)); - if (decrypt_esp_packet(vpninfo, old_esp, pkt)) + if (vpninfo->decrypt_esp_packet(vpninfo, old_esp, pkt)) continue; } else { vpn_progress(vpninfo, PRG_DEBUG, @@ -272,7 +272,7 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable) if (!this) break; - len = encrypt_esp_packet(vpninfo, this); + len = vpninfo->encrypt_esp_packet(vpninfo, this); if (len < 0) { vpn_progress(vpninfo, PRG_ERR, _("Failed to encrypt ESP packet: %d\n"), @@ -339,9 +339,11 @@ void esp_close(struct openconnect_info *vpninfo) void esp_shutdown(struct openconnect_info *vpninfo) { - destroy_esp_ciphers(&vpninfo->esp_in[0]); - destroy_esp_ciphers(&vpninfo->esp_in[1]); - destroy_esp_ciphers(&vpninfo->esp_out); + if (vpninfo->destroy_esp_ciphers) { + vpninfo->destroy_esp_ciphers(&vpninfo->esp_in[0]); + vpninfo->destroy_esp_ciphers(&vpninfo->esp_in[1]); + vpninfo->destroy_esp_ciphers(&vpninfo->esp_out); + } if (vpninfo->proto->udp_close) vpninfo->proto->udp_close(vpninfo); if (vpninfo->dtls_state != DTLS_DISABLED) diff --git a/gnutls-esp.c b/gnutls-esp.c index 08adc115..d17ee8f8 100644 --- a/gnutls-esp.c +++ b/gnutls-esp.c @@ -27,7 +27,11 @@ #include "openconnect-internal.h" -void destroy_esp_ciphers(struct esp *esp) +static int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, + struct pkt *pkt); +static int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt); + +static void destroy_esp_ciphers(struct esp *esp) { if (esp->cipher) { gnutls_cipher_deinit(esp->cipher); @@ -110,11 +114,16 @@ int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp_out, stru return ret; } + vpninfo->decrypt_esp_packet = decrypt_esp_packet; + vpninfo->encrypt_esp_packet = encrypt_esp_packet; + vpninfo->destroy_esp_ciphers = destroy_esp_ciphers; + return 0; } /* pkt->len shall be the *payload* length. Omitting the header and the 12-byte HMAC */ -int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, struct pkt *pkt) +static int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, + struct pkt *pkt) { unsigned char hmac_buf[20]; int err; diff --git a/gpst.c b/gpst.c index 670c7e3e..f7b51a67 100644 --- a/gpst.c +++ b/gpst.c @@ -1285,7 +1285,7 @@ int gpst_esp_send_probes(struct openconnect_info *vpninfo) memcpy(pmagic, magic_ping_payload, sizeof(magic_ping_payload)); /* required to get gateway to respond */ icmph->icmp_cksum = csum((uint16_t *)icmph, (ICMP_MINLEN+sizeof(magic_ping_payload))/2); - pktlen = encrypt_esp_packet(vpninfo, pkt); + pktlen = vpninfo->encrypt_esp_packet(vpninfo, pkt); if (pktlen >= 0) send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0); } diff --git a/oncp.c b/oncp.c index 24b1e56c..26952994 100644 --- a/oncp.c +++ b/oncp.c @@ -1304,7 +1304,7 @@ int oncp_esp_send_probes(struct openconnect_info *vpninfo) for (seq=1; seq <= (vpninfo->dtls_state==DTLS_CONNECTED ? 1 : 2); seq++) { pkt->len = 1; pkt->data[0] = 0; - pktlen = encrypt_esp_packet(vpninfo, pkt); + pktlen = vpninfo->encrypt_esp_packet(vpninfo, pkt); if (pktlen >= 0) send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0); } diff --git a/openconnect-internal.h b/openconnect-internal.h index 091c8f7a..2e5e76d9 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -638,6 +638,10 @@ struct openconnect_info { const char *quit_reason; + void (*destroy_esp_ciphers)(struct esp *esp); + int (*decrypt_esp_packet)(struct openconnect_info *vpninfo, struct esp *esp, struct pkt *pkt); + int (*encrypt_esp_packet)(struct openconnect_info *vpninfo, struct pkt *pkt); + int verbose; void *cbdata; openconnect_validate_peer_cert_vfn validate_peer_cert; @@ -933,10 +937,7 @@ int print_esp_keys(struct openconnect_info *vpninfo, const char *name, struct es int openconnect_setup_esp_keys(struct openconnect_info *vpninfo, int new_keys); /* {gnutls,openssl}-esp.c */ -void destroy_esp_ciphers(struct esp *esp); int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *out, struct esp *in); -int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, struct pkt *pkt); -int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt); /* {gnutls,openssl}.c */ int ssl_nonblock_read(struct openconnect_info *vpninfo, void *buf, int maxlen); diff --git a/openssl-esp.c b/openssl-esp.c index 364bb283..c27ab954 100644 --- a/openssl-esp.c +++ b/openssl-esp.c @@ -27,6 +27,10 @@ #include #include +static int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, + struct pkt *pkt); +static int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt); + #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) #define EVP_CIPHER_CTX_free(c) do { \ @@ -45,7 +49,7 @@ static inline HMAC_CTX *HMAC_CTX_new(void) } #endif -void destroy_esp_ciphers(struct esp *esp) +static void destroy_esp_ciphers(struct esp *esp) { if (esp->cipher) { EVP_CIPHER_CTX_free(esp->cipher); @@ -103,6 +107,10 @@ static int init_esp_cipher(struct openconnect_info *vpninfo, struct esp *esp, destroy_esp_ciphers(esp); } + vpninfo->decrypt_esp_packet = decrypt_esp_packet; + vpninfo->encrypt_esp_packet = encrypt_esp_packet; + vpninfo->destroy_esp_ciphers = destroy_esp_ciphers; + return 0; } @@ -148,7 +156,8 @@ int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp_out, stru } /* pkt->len shall be the *payload* length. Omitting the header and the 12-byte HMAC */ -int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, struct pkt *pkt) +static int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, + struct pkt *pkt) { unsigned char hmac_buf[20]; unsigned int hmac_len = sizeof(hmac_buf); @@ -186,7 +195,7 @@ int decrypt_esp_packet(struct openconnect_info *vpninfo, struct esp *esp, struct return 0; } -int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt) +static int encrypt_esp_packet(struct openconnect_info *vpninfo, struct pkt *pkt) { int i, padlen; int blksize = 16; -- 2.50.1