Added a new oncp_setup_esp_keys() which handles the generation of new, random keys for Juniper, and then calls the generic setup_esp_keys(), which just initializes the cipher and MAC. Mostly reverts my previous take on this from 8796139f9. This was suggested by David Woodhouse: > Just make an oncp_setup_esp_keys() function which creates the new keys and > *then* calls the generic setup_esp_keys()? Note that the flip to the > new incoming ESP setup has to be done *first*, or at least taken into > account. Signed-off-by: Daniel Lenski <dlenski at gmail.com> --- gnutls-esp.c | 18 +++--------------- gpst.c | 5 +++-- oncp.c | 31 +++++++++++++++++++++++++++++-- openconnect-internal.h | 2 +- openssl-esp.c | 18 +++--------------- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/gnutls-esp.c b/gnutls-esp.c index 0b63e0f..7666f10 100644 --- a/gnutls-esp.c +++ b/gnutls-esp.c @@ -72,7 +72,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp, return 0; } -int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys) +int setup_esp_keys(struct openconnect_info *vpninfo) { struct esp *esp_in; gnutls_mac_algorithm_t macalg; @@ -106,23 +106,11 @@ int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys) return -EINVAL; } - if (new_keys) { - vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32; - vpninfo->current_esp_in ^= 1; - } + vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32; + vpninfo->current_esp_in ^= 1; esp_in = &vpninfo->esp_in[vpninfo->current_esp_in]; - if (new_keys) { - if ((ret = gnutls_rnd(GNUTLS_RND_NONCE, &esp_in->spi, sizeof(esp_in->spi))) || - (ret = gnutls_rnd(GNUTLS_RND_RANDOM, &esp_in->secrets, sizeof(esp_in->secrets)))) { - vpn_progress(vpninfo, PRG_ERR, - _("Failed to generate random keys for ESP: %s\n"), - gnutls_strerror(ret)); - return -EIO; - } - } - ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, macalg, encalg); if (ret) return ret; diff --git a/gpst.c b/gpst.c index 7179ecb..3346194 100644 --- a/gpst.c +++ b/gpst.c @@ -286,7 +286,8 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ } } else if (xmlnode_is_named(xml_node, "ipsec")) { #ifdef HAVE_ESP - int c = (vpninfo->current_esp_in ^= 1); + /* setup_esp_keys() will swap the active incoming key-set */ + int c = (vpninfo->current_esp_in ^ 1); int enclen=0, maclen=0; for (member = xml_node->children; member; member=member->next) { s = NULL; @@ -303,7 +304,7 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ free((void *)s); } if (vpninfo->dtls_state != DTLS_DISABLED) { - if (setup_esp_keys(vpninfo, 0)) + if (setup_esp_keys(vpninfo)) vpn_progress(vpninfo, PRG_ERR, "Failed to setup ESP keys.\n"); else vpninfo->dtls_times.last_rekey = time(NULL); diff --git a/oncp.c b/oncp.c index 61ff9cf..f58c389 100644 --- a/oncp.c +++ b/oncp.c @@ -523,6 +523,33 @@ static int parse_conf_pkt(struct openconnect_info *vpninfo, unsigned char *bytes return 0; } +static int oncp_setup_esp_keys(struct openconnect_info *vpninfo) +{ + int ret; + /* setup_esp_keys() will swap the active incoming key-set */ + struct esp *esp_in = &vpninfo->esp_in[vpninfo->current_esp_in ^ 1]; + +#if defined(OPENCONNECT_GNUTLS) + if ((ret = gnutls_rnd(GNUTLS_RND_NONCE, &esp_in->spi, sizeof(esp_in->spi))) || + (ret = gnutls_rnd(GNUTLS_RND_RANDOM, &esp_in->secrets, sizeof(esp_in->secrets)))) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to generate random keys for ESP: %s\n"), + gnutls_strerror(ret)); + return -EIO; + } +#elif defined(OPENCONNECT_OPENSSL) + if (!RAND_bytes((void *)&esp_in->spi, sizeof(esp_in->spi)) || + !RAND_bytes((void *)&esp_in->secrets, sizeof(esp_in->secrets))) { + vpn_progress(vpninfo, PRG_ERR, + _("Failed to generate random keys for ESP:\n")); + openconnect_report_ssl_errors(vpninfo); + return -EIO; + } +#endif + + return setup_esp_keys(vpninfo); +} + int oncp_connect(struct openconnect_info *vpninfo) { int ret, len, kmp, kmplen, group; @@ -762,7 +789,7 @@ int oncp_connect(struct openconnect_info *vpninfo) put_len16(reqbuf, kmp); #ifdef HAVE_ESP - if (!setup_esp_keys(vpninfo, 1)) { + if (!oncp_setup_esp_keys(vpninfo)) { struct esp *esp = &vpninfo->esp_in[vpninfo->current_esp_in]; /* Since we'll want to do this in the oncp_mainloop too, where it's easier * *not* to have an oc_text_buf and build it up manually, and since it's @@ -814,7 +841,7 @@ static int oncp_receive_espkeys(struct openconnect_info *vpninfo, int len) int ret; ret = parse_conf_pkt(vpninfo, vpninfo->cstp_pkt->oncp.kmp, len + 20, 301); - if (!ret && !setup_esp_keys(vpninfo, 1)) { + if (!ret && !oncp_setup_esp_keys(vpninfo)) { struct esp *esp = &vpninfo->esp_in[vpninfo->current_esp_in]; unsigned char *p = vpninfo->cstp_pkt->oncp.kmp; diff --git a/openconnect-internal.h b/openconnect-internal.h index 466828d..c9f7b08 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -922,7 +922,7 @@ int esp_catch_probe(struct openconnect_info *vpninfo, struct pkt *pkt); int esp_catch_probe_gp(struct openconnect_info *vpninfo, struct pkt *pkt); /* {gnutls,openssl}-esp.c */ -int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys); +int setup_esp_keys(struct openconnect_info *vpninfo); 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); diff --git a/openssl-esp.c b/openssl-esp.c index f58d32f..9224388 100644 --- a/openssl-esp.c +++ b/openssl-esp.c @@ -112,7 +112,7 @@ static int init_esp_ciphers(struct openconnect_info *vpninfo, struct esp *esp, return 0; } -int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys) +int setup_esp_keys(struct openconnect_info *vpninfo) { struct esp *esp_in; const EVP_CIPHER *encalg; @@ -146,23 +146,11 @@ int setup_esp_keys(struct openconnect_info *vpninfo, int new_keys) return -EINVAL; } - if (new_keys) { - vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32; - vpninfo->current_esp_in ^= 1; - } + vpninfo->old_esp_maxseq = vpninfo->esp_in[vpninfo->current_esp_in].seq + 32; + vpninfo->current_esp_in ^= 1; esp_in = &vpninfo->esp_in[vpninfo->current_esp_in]; - if (new_keys) { - if (!RAND_bytes((void *)&esp_in->spi, sizeof(esp_in->spi)) || - !RAND_bytes((void *)&esp_in->secrets, sizeof(esp_in->secrets))) { - vpn_progress(vpninfo, PRG_ERR, - _("Failed to generate random keys for ESP:\n")); - openconnect_report_ssl_errors(vpninfo); - return -EIO; - } - } - ret = init_esp_ciphers(vpninfo, &vpninfo->esp_out, macalg, encalg, 0); if (ret) return ret; -- 2.7.4