#define DTLS_RECV gnutls_record_recv
#endif
+char *openconnect_bin2hex(const char *prefix, const uint8_t *data, unsigned len)
+{
+ char *v;
+ unsigned plen = strlen(prefix);
+ unsigned i;
+
+ v = malloc(len*2+plen+1);
+ if (v) {
+ snprintf(v, plen+1, "%s", prefix);
+ for (i = 0; i < len; i++)
+ sprintf(&v[i*2 + plen], "%02x", data[i]);
+ }
+ return v;
+}
+
static int connect_dtls_socket(struct openconnect_info *vpninfo)
{
int dtls_fd, ret;
static int set_peer_cert_hash(struct openconnect_info *vpninfo)
{
- unsigned char sha1[SHA1_SIZE];
+ unsigned char hash[SHA256_SIZE];
size_t shalen;
gnutls_pubkey_t pkey;
gnutls_datum_t d;
- int i, err;
+ int err;
err = gnutls_pubkey_init(&pkey);
if (err)
}
#endif
gnutls_pubkey_deinit(pkey);
- shalen = SHA1_SIZE;
+ shalen = SHA256_SIZE;
- err = gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, sha1, &shalen);
+ err = gnutls_fingerprint(GNUTLS_DIG_SHA256, &d, hash, &shalen);
if (err) {
gnutls_free(d.data);
return err;
}
- gnutls_free(d.data);
+ vpninfo->peer_cert_sha256 = openconnect_bin2hex("sha256:", hash, shalen);
- vpninfo->peer_cert_hash = malloc(SHA1_SIZE * 2 + 6);
- if (vpninfo->peer_cert_hash) {
- snprintf(vpninfo->peer_cert_hash, 6, "sha1:");
- for (i = 0; i < shalen; i++)
- sprintf(&vpninfo->peer_cert_hash[i*2 + 5], "%02x", sha1[i]);
+ shalen = SHA1_SIZE;
+ err = gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, hash, &shalen);
+ if (err) {
+ gnutls_free(d.data);
+ return err;
}
+ gnutls_free(d.data);
+
+ vpninfo->peer_cert_sha1 = openconnect_bin2hex("sha1:", hash, shalen);
+
return 0;
}
gnutls_x509_crt_deinit(vpninfo->peer_cert);
vpninfo->peer_cert = NULL;
}
- free(vpninfo->peer_cert_hash);
- vpninfo->peer_cert_hash = NULL;
+ free(vpninfo->peer_cert_sha1);
+ vpninfo->peer_cert_sha1 = NULL;
+ free(vpninfo->peer_cert_sha256);
+ vpninfo->peer_cert_sha256 = NULL;
gnutls_free(vpninfo->cstp_cipher);
vpninfo->cstp_cipher = NULL;
return 0;
}
+int openconnect_sha256(unsigned char *result, void *data, int datalen)
+{
+ gnutls_datum_t d;
+ size_t shalen = SHA256_SIZE;
+
+ d.data = data;
+ d.size = datalen;
+ if (gnutls_fingerprint(GNUTLS_DIG_SHA256, &d, result, &shalen))
+ return -1;
+
+ return 0;
+}
+
int openconnect_md5(unsigned char *result, void *data, int datalen)
{
gnutls_datum_t d;
free(cache);
}
- free(vpninfo->peer_cert_hash);
+ free(vpninfo->peer_cert_sha1);
+ free(vpninfo->peer_cert_sha256);
free(vpninfo->localname);
free(vpninfo->useragent);
free(vpninfo->authgroup);
const char *fingerprint;
if (strchr(old_hash, ':')) {
- fingerprint = openconnect_get_peer_cert_hash(vpninfo);
+ if (strncmp(old_hash, "sha1:", 5) == 0) {
+ fingerprint = vpninfo->peer_cert_sha1;
+ } else if (strncmp(old_hash, "sha256:", 7) == 0) {
+ fingerprint = vpninfo->peer_cert_sha256;
+ } else {
+ vpn_progress(vpninfo, PRG_ERR, _("Unknown certificate hash: %s.\n"), old_hash);
+ return -EIO;
+ }
+
if (!fingerprint)
return -EIO;
} else {
const char *openconnect_get_peer_cert_hash(struct openconnect_info *vpninfo)
{
- return vpninfo->peer_cert_hash;
+ return vpninfo->peer_cert_sha256;
}
int openconnect_set_compression_mode(struct openconnect_info *vpninfo,
#include <libxml/tree.h>
+#define SHA256_SIZE 32
#define SHA1_SIZE 20
#define MD5_SIZE 16
void *tok_cbdata;
void *peer_cert;
- char *peer_cert_hash;
+ char *peer_cert_sha1;
+ char *peer_cert_sha256;
void *cert_list_handle;
int cert_list_size;
void dtls_detect_mtu(struct openconnect_info *vpninfo);
int openconnect_dtls_read(struct openconnect_info *vpninfo, void *buf, size_t len, unsigned ms);
int openconnect_dtls_write(struct openconnect_info *vpninfo, void *buf, size_t len);
+char *openconnect_bin2hex(const char *prefix, const uint8_t *data, unsigned len);
/* cstp.c */
void cstp_common_headers(struct openconnect_info *vpninfo, struct oc_text_buf *buf);
int get_cert_md5_fingerprint(struct openconnect_info *vpninfo, void *cert,
char *buf);
int openconnect_sha1(unsigned char *result, void *data, int len);
+int openconnect_sha256(unsigned char *result, void *data, int len);
int openconnect_md5(unsigned char *result, void *data, int len);
int openconnect_random(void *bytes, int len);
int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
return 0;
}
+int openconnect_sha256(unsigned char *result, void *data, int len)
+{
+ EVP_MD_CTX *c = EVP_MD_CTX_new();
+
+ if (!c)
+ return -ENOMEM;
+
+ EVP_Digest(data, len, result, NULL, EVP_sha256(), NULL);
+ EVP_MD_CTX_free(c);
+
+ return 0;
+}
+
int openconnect_md5(unsigned char *result, void *data, int len)
{
EVP_MD_CTX *c = EVP_MD_CTX_new();
static int set_peer_cert_hash(struct openconnect_info *vpninfo)
{
- unsigned char sha1[SHA1_SIZE];
+ 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;
- int i;
/* We can't use X509_pubkey_digest() because it only hashes the
subjectPublicKey BIT STRING, and not the whole of the
BIO_get_mem_ptr(bp, &keyinfo);
- openconnect_sha1(sha1, keyinfo->data, keyinfo->length);
+ openconnect_sha256(sha256_hash, keyinfo->data, keyinfo->length);
+ openconnect_sha1(sha1_hash, keyinfo->data, keyinfo->length);
BIO_free(bp);
- vpninfo->peer_cert_hash = malloc(SHA1_SIZE * 2 + 6);
- if (vpninfo->peer_cert_hash) {
- snprintf(vpninfo->peer_cert_hash, 6, "sha1:");
- for (i = 0; i < sizeof(sha1); i++)
- sprintf(&vpninfo->peer_cert_hash[i*2 + 5], "%02x", sha1[i]);
- }
+ 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;
}
X509_free(vpninfo->peer_cert);
vpninfo->peer_cert = NULL;
}
- free (vpninfo->peer_cert_hash);
- vpninfo->peer_cert_hash = NULL;
+ free (vpninfo->peer_cert_sha1);
+ vpninfo->peer_cert_sha1 = NULL;
+ free (vpninfo->peer_cert_sha256);
+ vpninfo->peer_cert_sha256 = NULL;
vpninfo->cstp_cipher = NULL;
ssl_sock = connect_https_socket(vpninfo);