diff --git a/dtls.c b/dtls.c index 28088fb8..a10d4ed3 100644 --- a/dtls.c +++ b/dtls.c @@ -72,7 +72,8 @@ char *openconnect_bin2hex(const char *prefix, const uint8_t *data, unsigned len) char *p = NULL; buf = buf_alloc(); - buf_append(buf, "%s", prefix); + if (prefix) + buf_append(buf, "%s", prefix); buf_append_hex(buf, data, len); if (!buf_error(buf)) { diff --git a/gnutls.c b/gnutls.c index b32d497b..ea96cef5 100644 --- a/gnutls.c +++ b/gnutls.c @@ -1927,7 +1927,6 @@ int get_cert_md5_fingerprint(struct openconnect_info *vpninfo, static int set_peer_cert_hash(struct openconnect_info *vpninfo) { - unsigned char hash[SHA256_SIZE]; size_t shalen; gnutls_pubkey_t pkey; gnutls_datum_t d; @@ -1969,18 +1968,16 @@ static int set_peer_cert_hash(struct openconnect_info *vpninfo) } #endif gnutls_pubkey_deinit(pkey); - shalen = SHA256_SIZE; - err = gnutls_fingerprint(GNUTLS_DIG_SHA256, &d, hash, &shalen); + shalen = sizeof(vpninfo->peer_cert_sha256_raw); + err = gnutls_fingerprint(GNUTLS_DIG_SHA256, &d, vpninfo->peer_cert_sha256_raw, &shalen); if (err) { gnutls_free(d.data); return err; } - vpninfo->peer_cert_sha256 = openconnect_bin2hex("sha256:", hash, shalen); - - shalen = SHA1_SIZE; - err = gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, hash, &shalen); + shalen = sizeof(vpninfo->peer_cert_sha1_raw); + err = gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, vpninfo->peer_cert_sha1_raw, &shalen); if (err) { gnutls_free(d.data); return err; @@ -1988,8 +1985,6 @@ static int set_peer_cert_hash(struct openconnect_info *vpninfo) gnutls_free(d.data); - vpninfo->peer_cert_sha1 = openconnect_bin2hex("sha1:", hash, shalen); - return 0; } @@ -2221,10 +2216,9 @@ int openconnect_open_https(struct openconnect_info *vpninfo) gnutls_x509_crt_deinit(vpninfo->peer_cert); vpninfo->peer_cert = NULL; } - free(vpninfo->peer_cert_sha1); - vpninfo->peer_cert_sha1 = NULL; - free(vpninfo->peer_cert_sha256); - vpninfo->peer_cert_sha256 = NULL; + + free(vpninfo->peer_cert_hash); + vpninfo->peer_cert_hash = NULL; gnutls_free(vpninfo->cstp_cipher); vpninfo->cstp_cipher = NULL; diff --git a/library.c b/library.c index 6ab74410..3ca1e7a5 100644 --- a/library.c +++ b/library.c @@ -368,8 +368,6 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo) free(cache); } - free(vpninfo->peer_cert_sha1); - free(vpninfo->peer_cert_sha256); free(vpninfo->localname); free(vpninfo->useragent); free(vpninfo->authgroup); @@ -968,29 +966,25 @@ int openconnect_set_csd_environ(struct openconnect_info *vpninfo, int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo, const char *old_hash) { - char sha1_text[41]; - const char *fingerprint; + char *fingerprint = NULL; unsigned min_match_len; unsigned real_min_match_len = 4; unsigned old_len, fingerprint_len; if (strchr(old_hash, ':')) { if (strncmp(old_hash, "sha1:", 5) == 0) { - fingerprint = vpninfo->peer_cert_sha1; + fingerprint = openconnect_bin2hex("sha1:", vpninfo->peer_cert_sha1_raw, sizeof(vpninfo->peer_cert_sha1_raw)); min_match_len = real_min_match_len + sizeof("sha1:")-1; } else if (strncmp(old_hash, "sha256:", 7) == 0) { - fingerprint = vpninfo->peer_cert_sha256; + fingerprint = openconnect_bin2hex("sha256:", vpninfo->peer_cert_sha256_raw, sizeof(vpninfo->peer_cert_sha256_raw)); min_match_len = real_min_match_len + sizeof("sha256:")-1; } else { vpn_progress(vpninfo, PRG_ERR, _("Unknown certificate hash: %s.\n"), old_hash); return -EIO; } - - if (!fingerprint) - return -EIO; } else { unsigned char *cert; - int len, i; + int len; unsigned char sha1_bin[SHA1_SIZE]; len = openconnect_get_peer_cert_DER(vpninfo, &cert); @@ -1000,13 +994,13 @@ int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo, if (openconnect_sha1(sha1_bin, cert, len)) return -EIO; - for (i = 0; i < sizeof(sha1_bin); i++) - sprintf(&sha1_text[i*2], "%02x", sha1_bin[i]); - - fingerprint = sha1_text; + fingerprint = openconnect_bin2hex(NULL, sha1_bin, sizeof(sha1_bin)); min_match_len = real_min_match_len; } + if (!fingerprint) + return -EIO; + old_len = strlen(old_hash); fingerprint_len = strlen(fingerprint); @@ -1033,7 +1027,9 @@ const char *openconnect_get_cstp_cipher(struct openconnect_info *vpninfo) const char *openconnect_get_peer_cert_hash(struct openconnect_info *vpninfo) { - return vpninfo->peer_cert_sha256; + if (vpninfo->peer_cert_hash == NULL) + vpninfo->peer_cert_hash = openconnect_bin2hex("sha256:", vpninfo->peer_cert_sha256_raw, sizeof(vpninfo->peer_cert_sha256_raw)); + return vpninfo->peer_cert_hash; } int openconnect_set_compression_mode(struct openconnect_info *vpninfo, diff --git a/openconnect-internal.h b/openconnect-internal.h index 117ca19e..291eb4b7 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -458,8 +458,11 @@ struct openconnect_info { void *tok_cbdata; void *peer_cert; - char *peer_cert_sha1; - char *peer_cert_sha256; + /* The SHA1 and SHA256 hashes of the peer's public key */ + uint8_t peer_cert_sha1_raw[SHA1_SIZE]; + uint8_t peer_cert_sha256_raw[SHA256_SIZE]; + /* this value is cache for openconnect_get_peer_cert_hash */ + char *peer_cert_hash; void *cert_list_handle; int cert_list_size; diff --git a/openssl.c b/openssl.c index 20226d55..52c95484 100644 --- a/openssl.c +++ b/openssl.c @@ -1099,8 +1099,6 @@ int get_cert_md5_fingerprint(struct openconnect_info *vpninfo, static int set_peer_cert_hash(struct openconnect_info *vpninfo) { - unsigned char sha256_hash[SHA256_SIZE]; - unsigned char sha1_hash[SHA1_SIZE]; EVP_PKEY *pkey; BIO *bp = BIO_new(BIO_s_mem()); BUF_MEM *keyinfo; @@ -1119,14 +1117,11 @@ static int set_peer_cert_hash(struct openconnect_info *vpninfo) BIO_get_mem_ptr(bp, &keyinfo); - openconnect_sha256(sha256_hash, keyinfo->data, keyinfo->length); - openconnect_sha1(sha1_hash, keyinfo->data, keyinfo->length); + openconnect_sha256(vpninfo->peer_cert_sha256_raw, keyinfo->data, keyinfo->length); + openconnect_sha1(vpninfo->peer_cert_sha1_raw, keyinfo->data, keyinfo->length); BIO_free(bp); - vpninfo->peer_cert_sha1 = openconnect_bin2hex("sha1:", sha1_hash, sizeof(sha1_hash)); - vpninfo->peer_cert_sha256 = openconnect_bin2hex("sha256:", sha256_hash, sizeof(sha256_hash)); - return 0; } @@ -1658,10 +1653,8 @@ int openconnect_open_https(struct openconnect_info *vpninfo) X509_free(vpninfo->peer_cert); vpninfo->peer_cert = NULL; } - free (vpninfo->peer_cert_sha1); - vpninfo->peer_cert_sha1 = NULL; - free (vpninfo->peer_cert_sha256); - vpninfo->peer_cert_sha256 = NULL; + free(vpninfo->peer_cert_hash); + vpninfo->peer_cert_hash = NULL; vpninfo->cstp_cipher = NULL; ssl_sock = connect_https_socket(vpninfo);