const byteArray X509Certificate::getFingerprint(const DigestAlgorithm algo) const { gnutls_digest_algorithm galgo; switch (algo) { case DIGEST_MD5: galgo = GNUTLS_DIG_MD5; break; default: case DIGEST_SHA1: galgo = GNUTLS_DIG_SHA; break; } size_t bufferSize = 0; gnutls_x509_crt_get_fingerprint (m_data->cert, galgo, NULL, &bufferSize); std::vector <byte_t> buffer(bufferSize); if (gnutls_x509_crt_get_fingerprint (m_data->cert, galgo, &buffer[0], &bufferSize) == 0) { byteArray res; res.insert(res.end(), &buffer[0], &buffer[0] + bufferSize); return res; } return byteArray(); }
static GByteArray * x509_sha1sum(PurpleCertificate *crt) { size_t hashlen = 20; /* SHA1 hashes are 20 bytes */ size_t tmpsz = hashlen; /* Throw-away variable for GnuTLS to stomp on*/ gnutls_x509_crt_t crt_dat; GByteArray *hash; /**< Final hash container */ guchar hashbuf[hashlen]; /**< Temporary buffer to contain hash */ g_return_val_if_fail(crt, NULL); crt_dat = X509_GET_GNUTLS_DATA(crt); /* Extract the fingerprint */ g_return_val_if_fail( 0 == gnutls_x509_crt_get_fingerprint(crt_dat, GNUTLS_DIG_SHA, hashbuf, &tmpsz), NULL); /* This shouldn't happen */ g_return_val_if_fail(tmpsz == hashlen, NULL); /* Okay, now create and fill hash array */ hash = g_byte_array_new(); g_byte_array_append(hash, hashbuf, hashlen); return hash; }
int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method) { gnutls_x509_crt_t cert; gnutls_digest_algorithm_t algo; unsigned int cert_list_size; const gnutls_datum_t *cert_list; uint8_t digest[RB_SSL_CERTFP_LEN * 2]; size_t digest_size; int len; if (gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509) return 0; if (gnutls_x509_crt_init(&cert) < 0) return 0; cert_list_size = 0; cert_list = gnutls_certificate_get_peers(SSL_P(F), &cert_list_size); if (cert_list == NULL) { gnutls_x509_crt_deinit(cert); return 0; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { gnutls_x509_crt_deinit(cert); return 0; } switch(method) { case RB_SSL_CERTFP_METH_SHA1: algo = GNUTLS_DIG_SHA1; len = RB_SSL_CERTFP_LEN_SHA1; break; case RB_SSL_CERTFP_METH_SHA256: algo = GNUTLS_DIG_SHA256; len = RB_SSL_CERTFP_LEN_SHA256; break; case RB_SSL_CERTFP_METH_SHA512: algo = GNUTLS_DIG_SHA512; len = RB_SSL_CERTFP_LEN_SHA512; break; default: return 0; } if (gnutls_x509_crt_get_fingerprint(cert, algo, digest, &digest_size) < 0) { gnutls_x509_crt_deinit(cert); return 0; } memcpy(certfp, digest, len); gnutls_x509_crt_deinit(cert); return len; }
static gboolean inf_gtk_certificate_manager_compare_fingerprint(gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2, GError** error) { static const unsigned int SHA256_DIGEST_SIZE = 32; size_t size; guchar cert1_fingerprint[SHA256_DIGEST_SIZE]; guchar cert2_fingerprint[SHA256_DIGEST_SIZE]; int ret; int cmp; size = SHA256_DIGEST_SIZE; ret = gnutls_x509_crt_get_fingerprint( cert1, GNUTLS_DIG_SHA256, cert1_fingerprint, &size ); if(ret == GNUTLS_E_SUCCESS) { g_assert(size == SHA256_DIGEST_SIZE); ret = gnutls_x509_crt_get_fingerprint( cert2, GNUTLS_DIG_SHA256, cert2_fingerprint, &size ); } if(ret != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, ret); return FALSE; } cmp = memcmp(cert1_fingerprint, cert2_fingerprint, SHA256_DIGEST_SIZE); if(cmp != 0) return FALSE; return TRUE; }
static uschar * fingerprint(gnutls_x509_crt_t cert, gnutls_digest_algorithm_t algo) { int ret; size_t siz = 0; uschar * cp; uschar * cp2; uschar * cp3; if ((ret = gnutls_x509_crt_get_fingerprint(cert, algo, NULL, &siz)) != GNUTLS_E_SHORT_MEMORY_BUFFER) return g_err("gf0", __FUNCTION__, ret); cp = store_get(siz*3+1); if ((ret = gnutls_x509_crt_get_fingerprint(cert, algo, cp, &siz)) < 0) return g_err("gf1", __FUNCTION__, ret); for (cp3 = cp2 = cp+siz; cp < cp2; cp++, cp3+=2) sprintf(cp3, "%02X",*cp); return cp2; }
int ne_ssl_cert_digest(const ne_ssl_certificate *cert, char *digest) { char sha1[20], *p; int j; size_t len = sizeof sha1; if (gnutls_x509_crt_get_fingerprint(cert->subject, GNUTLS_DIG_SHA, sha1, &len) < 0) return -1; for (j = 0, p = digest; j < 20; j++) { *p++ = NE_HEX2ASC((sha1[j] >> 4) & 0x0f); *p++ = NE_HEX2ASC(sha1[j] & 0x0f); *p++ = ':'; } *--p = '\0'; return 0; }
int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN]) { gnutls_x509_crt_t cert; unsigned int cert_list_size; const gnutls_datum_t *cert_list; uint8_t digest[RB_SSL_CERTFP_LEN * 2]; size_t digest_size; if (gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509) return 0; if (gnutls_x509_crt_init(&cert) < 0) return 0; cert_list_size = 0; cert_list = gnutls_certificate_get_peers(SSL_P(F), &cert_list_size); if (cert_list == NULL) { gnutls_x509_crt_deinit(cert); return 0; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { gnutls_x509_crt_deinit(cert); return 0; } if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &digest_size) < 0) { gnutls_x509_crt_deinit(cert); return 0; } memcpy(certfp, digest, RB_SSL_CERTFP_LEN); gnutls_x509_crt_deinit(cert); return 1; }
void VerifyCertificate(issl_session* session, StreamSocket* user) { if (!session->sess || !user) return; unsigned int status; const gnutls_datum_t* cert_list; int ret; unsigned int cert_list_size; gnutls_x509_crt_t cert; char str[512]; unsigned char digest[512]; size_t digest_size = sizeof(digest); size_t name_size = sizeof(str); ssl_cert* certinfo = new ssl_cert; session->cert = certinfo; /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2(session->sess, &status); if (ret < 0) { certinfo->error = std::string(gnutls_strerror(ret)); return; } certinfo->invalid = (status & GNUTLS_CERT_INVALID); certinfo->unknownsigner = (status & GNUTLS_CERT_SIGNER_NOT_FOUND); certinfo->revoked = (status & GNUTLS_CERT_REVOKED); certinfo->trusted = !(status & GNUTLS_CERT_SIGNER_NOT_CA); /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get(session->sess) != GNUTLS_CRT_X509) { certinfo->error = "No X509 keys sent"; return; } ret = gnutls_x509_crt_init(&cert); if (ret < 0) { certinfo->error = gnutls_strerror(ret); return; } cert_list_size = 0; cert_list = gnutls_certificate_get_peers(session->sess, &cert_list_size); if (cert_list == NULL) { certinfo->error = "No certificate was found"; goto info_done_dealloc; } /* This is not a real world example, since we only check the first * certificate in the given chain. */ ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); if (ret < 0) { certinfo->error = gnutls_strerror(ret); goto info_done_dealloc; } gnutls_x509_crt_get_dn(cert, str, &name_size); certinfo->dn = str; gnutls_x509_crt_get_issuer_dn(cert, str, &name_size); certinfo->issuer = str; if ((ret = gnutls_x509_crt_get_fingerprint(cert, hash, digest, &digest_size)) < 0) { certinfo->error = gnutls_strerror(ret); } else { certinfo->fingerprint = BinToHex(digest, digest_size); } /* Beware here we do not check for errors. */ if ((gnutls_x509_crt_get_expiration_time(cert) < ServerInstance->Time()) || (gnutls_x509_crt_get_activation_time(cert) > ServerInstance->Time())) { certinfo->error = "Not activated, or expired certificate"; } info_done_dealloc: gnutls_x509_crt_deinit(cert); }
bool CTlsSocket::ExtractCert(const void* in, CCertificate& out) { const gnutls_datum_t* datum = reinterpret_cast<const gnutls_datum_t*>(in); gnutls_x509_crt_t cert; if (gnutls_x509_crt_init(&cert)) { m_pOwner->LogMessage(::Error, _("Could not initialize structure for peer certificates, gnutls_x509_crt_init failed")); return false; } if (gnutls_x509_crt_import(cert, datum, GNUTLS_X509_FMT_DER)) { m_pOwner->LogMessage(::Error, _("Could not import peer certificates, gnutls_x509_crt_import failed")); gnutls_x509_crt_deinit(cert); return false; } wxDateTime expirationTime = gnutls_x509_crt_get_expiration_time(cert); wxDateTime activationTime = gnutls_x509_crt_get_activation_time(cert); // Get the serial number of the certificate unsigned char buffer[40]; size_t size = sizeof(buffer); int res = gnutls_x509_crt_get_serial(cert, buffer, &size); if( res != 0 ) { size = 0; } wxString serial = bin2hex(buffer, size); unsigned int pkBits; int pkAlgo = gnutls_x509_crt_get_pk_algorithm(cert, &pkBits); wxString pkAlgoName; if (pkAlgo >= 0) { const char* pAlgo = gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)pkAlgo); if (pAlgo) pkAlgoName = wxString(pAlgo, wxConvUTF8); } int signAlgo = gnutls_x509_crt_get_signature_algorithm(cert); wxString signAlgoName; if (signAlgo >= 0) { const char* pAlgo = gnutls_sign_algorithm_get_name((gnutls_sign_algorithm_t)signAlgo); if (pAlgo) signAlgoName = wxString(pAlgo, wxConvUTF8); } wxString subject, issuer; size = 0; res = gnutls_x509_crt_get_dn(cert, 0, &size); if (size) { char* dn = new char[size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_dn(cert, dn, &size))) { dn[size] = 0; subject = wxString(dn, wxConvUTF8); } else LogError(res, _T("gnutls_x509_crt_get_dn")); delete [] dn; } else LogError(res, _T("gnutls_x509_crt_get_dn")); if (subject == _T("")) { m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate subject, gnutls_x509_get_dn failed")); gnutls_x509_crt_deinit(cert); return false; } size = 0; res = gnutls_x509_crt_get_issuer_dn(cert, 0, &size); if (size) { char* dn = new char[++size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_issuer_dn(cert, dn, &size))) { dn[size] = 0; issuer = wxString(dn, wxConvUTF8); } else LogError(res, _T("gnutls_x509_crt_get_issuer_dn")); delete [] dn; } else LogError(res, _T("gnutls_x509_crt_get_issuer_dn")); if (issuer == _T("")) { m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate issuer, gnutls_x509_get_issuer_dn failed")); gnutls_x509_crt_deinit(cert); return false; } wxString fingerprint_md5; wxString fingerprint_sha1; unsigned char digest[100]; size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &size)) { digest[size] = 0; fingerprint_md5 = bin2hex(digest, size); } size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &size)) { digest[size] = 0; fingerprint_sha1 = bin2hex(digest, size); } gnutls_x509_crt_deinit(cert); out = CCertificate( datum->data, datum->size, activationTime, expirationTime, serial, pkAlgoName, pkBits, signAlgoName, fingerprint_md5, fingerprint_sha1, subject, issuer); return true; }
static int ConnSSL_InitCertFp( CONNECTION *c ) { const char hex[] = "0123456789abcdef"; int i; #ifdef HAVE_LIBSSL unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_size; X509 *cert; cert = SSL_get_peer_certificate(c->ssl_state.ssl); if (!cert) return 0; if (!X509_digest(cert, EVP_sha256(), digest, &digest_size)) { X509_free(cert); return 0; } X509_free(cert); #endif /* HAVE_LIBSSL */ #ifdef HAVE_LIBGNUTLS gnutls_x509_crt_t cert; unsigned int cert_list_size; const gnutls_datum_t *cert_list; unsigned char digest[MAX_HASH_SIZE]; size_t digest_size; if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) != GNUTLS_CRT_X509) return 0; if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS) return 0; cert_list_size = 0; cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session, &cert_list_size); if (!cert_list) { gnutls_x509_crt_deinit(cert); return 0; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); return 0; } digest_size = sizeof(digest); if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, digest, &digest_size)) { gnutls_x509_crt_deinit(cert); return 0; } gnutls_x509_crt_deinit(cert); #endif /* HAVE_LIBGNUTLS */ assert(c->ssl_state.fingerprint == NULL); c->ssl_state.fingerprint = malloc(SHA256_STRING_LEN); if (!c->ssl_state.fingerprint) return 0; for (i = 0; i < (int)digest_size; i++) { c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16]; c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16]; } c->ssl_state.fingerprint[i * 2] = '\0'; return 1; }
int tls_check_cert(tls_t *tls, const char *hostname, char **errstr) { #ifdef HAVE_LIBGNUTLS int error_code; const char *error_msg; unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; unsigned int i; gnutls_x509_crt_t cert; time_t t1, t2; size_t size; unsigned char fingerprint[20]; char *idn_hostname = NULL; if (tls->have_trust_file || tls->have_sha1_fingerprint || tls->have_md5_fingerprint) { error_msg = _("TLS certificate verification failed"); } else { error_msg = _("TLS certificate check failed"); } if (tls->have_sha1_fingerprint || tls->have_md5_fingerprint) { /* If one of these matches, we trust the peer and do not perform any * other checks. */ if (!(cert_list = gnutls_certificate_get_peers( tls->session, &cert_list_size))) { *errstr = xasprintf(_("%s: no certificate was found"), error_msg); return TLS_ECERT; } if (gnutls_x509_crt_init(&cert) < 0) { *errstr = xasprintf( _("%s: cannot initialize certificate structure"), error_msg); return TLS_ECERT; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { *errstr = xasprintf(_("%s: error parsing certificate %u of %u"), error_msg, 0 + 1, cert_list_size); return TLS_ECERT; } if (tls->have_sha1_fingerprint) { size = 20; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA, fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 20) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } } else { size = 16; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 16) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } } gnutls_x509_crt_deinit(cert); return TLS_EOK; } /* If 'tls->have_trust_file' is true, this function uses the trusted CAs * in the credentials structure. So you must have installed one or more CA * certificates. */ gnutls_certificate_set_verify_flags(tls->cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); if ((error_code = gnutls_certificate_verify_peers2(tls->session, &status)) != 0) { *errstr = xasprintf("%s: %s", error_msg, gnutls_strerror(error_code)); return TLS_ECERT; } if (tls->have_trust_file) { if (status & GNUTLS_CERT_REVOKED) { *errstr = xasprintf(_("%s: the certificate has been revoked"), error_msg); return TLS_ECERT; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { *errstr = xasprintf( _("%s: the certificate hasn't got a known issuer"), error_msg); return TLS_ECERT; } if (status & GNUTLS_CERT_INVALID) { *errstr = xasprintf(_("%s: the certificate is not trusted"), error_msg); return TLS_ECERT; } } if (gnutls_certificate_type_get(tls->session) != GNUTLS_CRT_X509) { *errstr = xasprintf(_("%s: the certificate type is not X509"), error_msg); return TLS_ECERT; } if (!(cert_list = gnutls_certificate_get_peers( tls->session, &cert_list_size))) { *errstr = xasprintf(_("%s: no certificate was found"), error_msg); return TLS_ECERT; } /* Needed to check times: */ if ((t1 = time(NULL)) < 0) { *errstr = xasprintf("%s: cannot get system time: %s", error_msg, strerror(errno)); return TLS_ECERT; } /* Check the certificate chain. All certificates in the chain must have * valid activation/expiration times. The first certificate in the chain is * the host's certificate; it must match the hostname. */ for (i = 0; i < cert_list_size; i++) { if (gnutls_x509_crt_init(&cert) < 0) { *errstr = xasprintf( _("%s: cannot initialize certificate structure"), error_msg); return TLS_ECERT; } if (gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER) < 0) { *errstr = xasprintf(_("%s: error parsing certificate %u of %u"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } /* Check hostname */ if (i == 0) { #if GNUTLS_VERSION_NUMBER < 0x030400 && defined(HAVE_LIBIDN) idna_to_ascii_lz(hostname, &idn_hostname, 0); #endif error_code = gnutls_x509_crt_check_hostname(cert, idn_hostname ? idn_hostname : hostname); free(idn_hostname); if (error_code == 0) { *errstr = xasprintf(_("%s: the certificate owner does not " "match hostname %s"), error_msg, hostname); return TLS_ECERT; } } /* Check certificate times */ if ((t2 = gnutls_x509_crt_get_activation_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get activation time for " "certificate %u of %u"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } if (t2 > t1) { *errstr = xasprintf( _("%s: certificate %u of %u is not yet activated"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } if ((t2 = gnutls_x509_crt_get_expiration_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get expiration time for " "certificate %u of %u"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } if (t2 < t1) { *errstr = xasprintf(_("%s: certificate %u of %u has expired"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } gnutls_x509_crt_deinit(cert); } return TLS_EOK; #endif /* HAVE_LIBGNUTLS */ #ifdef HAVE_LIBSSL X509 *x509cert; long status; const char *error_msg; int i; /* hostname in ASCII format: */ char *idn_hostname = NULL; /* needed to get the common name: */ X509_NAME *x509_subject; char *buf; int length; /* needed to get the DNS subjectAltNames: */ void *subj_alt_names; int subj_alt_names_count; GENERAL_NAME *subj_alt_name; /* did we find a name matching hostname? */ int match_found; /* needed for fingerprint checking */ unsigned int usize; unsigned char fingerprint[20]; if (tls->have_trust_file) { error_msg = _("TLS certificate verification failed"); } else { error_msg = _("TLS certificate check failed"); } /* Get certificate */ if (!(x509cert = SSL_get_peer_certificate(tls->ssl))) { *errstr = xasprintf(_("%s: no certificate was sent"), error_msg); return TLS_ECERT; } if (tls->have_sha1_fingerprint || tls->have_md5_fingerprint) { /* If one of these matches, we trust the peer and do not perform any * other checks. */ if (tls->have_sha1_fingerprint) { usize = 20; if (!X509_digest(x509cert, EVP_sha1(), fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), error_msg); X509_free(x509cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 20) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); X509_free(x509cert); return TLS_ECERT; } } else { usize = 16; if (!X509_digest(x509cert, EVP_md5(), fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), error_msg); X509_free(x509cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 16) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); X509_free(x509cert); return TLS_ECERT; } } X509_free(x509cert); return TLS_EOK; } /* Get result of OpenSSL's default verify function */ if ((status = SSL_get_verify_result(tls->ssl)) != X509_V_OK) { if (tls->have_trust_file || (status != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY && status != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && status != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)) { *errstr = xasprintf("%s: %s", error_msg, X509_verify_cert_error_string(status)); X509_free(x509cert); return TLS_ECERT; } } /* Check if 'hostname' matches the one of the subjectAltName extensions of * type DNS or the Common Name (CN). */ #ifdef HAVE_LIBIDN idna_to_ascii_lz(hostname, &idn_hostname, 0); #endif /* Try the DNS subjectAltNames. */ match_found = 0; if ((subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name, NULL, NULL))) { subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names); for (i = 0; i < subj_alt_names_count; i++) { subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); if (subj_alt_name->type == GEN_DNS) { if ((size_t)(subj_alt_name->d.ia5->length) != strlen((char *)(subj_alt_name->d.ia5->data))) { *errstr = xasprintf(_("%s: certificate subject " "alternative name contains NUL"), error_msg); X509_free(x509cert); free(idn_hostname); return TLS_ECERT; } if ((match_found = hostname_match( idn_hostname ? idn_hostname : hostname, (char *)(subj_alt_name->d.ia5->data)))) { break; } } } } if (!match_found) { /* Try the common name */ if (!(x509_subject = X509_get_subject_name(x509cert))) { *errstr = xasprintf(_("%s: cannot get certificate subject"), error_msg); X509_free(x509cert); free(idn_hostname); return TLS_ECERT; } length = X509_NAME_get_text_by_NID(x509_subject, NID_commonName, NULL, 0); buf = xmalloc((size_t)length + 1); if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName, buf, length + 1) == -1) { *errstr = xasprintf(_("%s: cannot get certificate common name"), error_msg); X509_free(x509cert); free(idn_hostname); free(buf); return TLS_ECERT; } if ((size_t)length != strlen(buf)) { *errstr = xasprintf(_("%s: certificate common name contains NUL"), error_msg); X509_free(x509cert); free(idn_hostname); free(buf); return TLS_ECERT; } match_found = hostname_match(idn_hostname ? idn_hostname : hostname, buf); free(buf); } X509_free(x509cert); free(idn_hostname); if (!match_found) { *errstr = xasprintf( _("%s: the certificate owner does not match hostname %s"), error_msg, hostname); return TLS_ECERT; } return TLS_EOK; #endif /* HAVE_LIBSSL */ }
/** * ntfs_pkcs12_extract_rsa_key */ static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size, char *password, char *thumbprint, int thumbprint_size, NTFS_DF_TYPES *df_type) { int err, bag_index, flags; gnutls_datum_t dpfx, dkey; gnutls_pkcs12_t pkcs12 = NULL; gnutls_pkcs12_bag_t bag = NULL; gnutls_x509_privkey_t pkey = NULL; gnutls_x509_crt_t crt = NULL; ntfs_rsa_private_key rsa_key = NULL; char purpose_oid[100]; size_t purpose_oid_size = sizeof(purpose_oid); size_t tp_size = thumbprint_size; BOOL have_thumbprint = FALSE; *df_type = DF_TYPE_UNKNOWN; /* Create a pkcs12 structure. */ err = gnutls_pkcs12_init(&pkcs12); if (err) { ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n", gnutls_strerror(err)); return NULL; } /* Convert the PFX file (DER format) to native pkcs12 format. */ dpfx.data = pfx; dpfx.size = pfx_size; err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0); if (err) { ntfs_log_error("Failed to convert the PFX file from DER to " "native PKCS#12 format: %s\n", gnutls_strerror(err)); goto err; } /* * Verify that the password is correct and that the key file has not * been tampered with. Note if the password has zero length and the * verification fails, retry with password set to NULL. This is needed * to get passwordless .pfx files generated with Windows XP SP1 (and * probably earlier versions of Windows) to work. */ retry_verify: err = gnutls_pkcs12_verify_mac(pkcs12, password); if (err) { if (err == GNUTLS_E_MAC_VERIFY_FAILED && password && !strlen(password)) { password = NULL; goto retry_verify; } ntfs_log_error("Failed to verify the MAC: %s Is the " "password correct?\n", gnutls_strerror(err)); goto err; } for (bag_index = 0; ; bag_index++) { err = gnutls_pkcs12_bag_init(&bag); if (err) { ntfs_log_error("Failed to initialize PKCS#12 Bag " "structure: %s\n", gnutls_strerror(err)); goto err; } err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag); if (err) { if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { err = 0; break; } ntfs_log_error("Failed to obtain Bag from PKCS#12 " "structure: %s\n", gnutls_strerror(err)); goto err; } check_again: err = gnutls_pkcs12_bag_get_count(bag); if (err < 0) { ntfs_log_error("Failed to obtain Bag count: %s\n", gnutls_strerror(err)); goto err; } err = gnutls_pkcs12_bag_get_type(bag, 0); if (err < 0) { ntfs_log_error("Failed to determine Bag type: %s\n", gnutls_strerror(err)); goto err; } flags = 0; switch (err) { case GNUTLS_BAG_PKCS8_KEY: flags = GNUTLS_PKCS_PLAIN; case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey); if (err < 0) { ntfs_log_error("Failed to obtain Bag data: " "%s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_privkey_init(&pkey); if (err) { ntfs_log_error("Failed to initialized " "private key structure: %s\n", gnutls_strerror(err)); goto err; } /* Decrypt the private key into GNU TLS format. */ err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey, GNUTLS_X509_FMT_DER, password, flags); if (err) { ntfs_log_error("Failed to convert private " "key from DER to GNU TLS " "format: %s\n", gnutls_strerror(err)); goto err; } #if 0 /* * Export the key again, but unencrypted, and output it * to stderr. Note the output has an RSA header so to * compare to openssl pkcs12 -nodes -in myfile.pfx * output need to ignore the part of the key between * the first "MII..." up to the second "MII...". The * actual RSA private key begins at the second "MII..." * and in my testing at least was identical to openssl * output and was also identical both on big and little * endian so gnutls should be endianness safe. */ char *buf = malloc(8192); size_t bufsize = 8192; err = gnutls_x509_privkey_export_pkcs8(pkey, GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf, &bufsize); if (err) { ntfs_log_error("eek1\n"); exit(1); } ntfs_log_error("%s\n", buf); free(buf); #endif /* Convert the private key to our internal format. */ rsa_key = ntfs_rsa_private_key_import_from_gnutls(pkey); if (!rsa_key) goto err; break; case GNUTLS_BAG_ENCRYPTED: err = gnutls_pkcs12_bag_decrypt(bag, password); if (err) { ntfs_log_error("Failed to decrypt Bag: %s\n", gnutls_strerror(err)); goto err; } goto check_again; case GNUTLS_BAG_CERTIFICATE: err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey); if (err < 0) { ntfs_log_error("Failed to obtain Bag data: " "%s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_crt_init(&crt); if (err) { ntfs_log_error("Failed to initialize " "certificate structure: %s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_crt_import(crt, &dkey, GNUTLS_X509_FMT_DER); if (err) { ntfs_log_error("Failed to convert certificate " "from DER to GNU TLS format: " "%s\n", gnutls_strerror(err)); goto err; } err = gnutls_x509_crt_get_key_purpose_oid(crt, 0, purpose_oid, &purpose_oid_size, NULL); if (err) { ntfs_log_error("Failed to get key purpose " "OID: %s\n", gnutls_strerror(err)); goto err; } purpose_oid[purpose_oid_size - 1] = '\0'; if (!strcmp(purpose_oid, NTFS_EFS_CERT_PURPOSE_OID_DRF)) *df_type = DF_TYPE_DRF; else if (!strcmp(purpose_oid, NTFS_EFS_CERT_PURPOSE_OID_DDF)) *df_type = DF_TYPE_DDF; else { ntfs_log_error("Certificate has unknown " "purpose OID %s.\n", purpose_oid); err = EINVAL; goto err; } /* Return the thumbprint to the caller. */ err = gnutls_x509_crt_get_fingerprint(crt, GNUTLS_DIG_SHA1, thumbprint, &tp_size); if (err) { ntfs_log_error("Failed to get thumbprint: " "%s\n", gnutls_strerror(err)); goto err; } if (tp_size != NTFS_SHA1_THUMBPRINT_SIZE) { ntfs_log_error("Invalid thumbprint size %zd. " "Should be %d.\n", tp_size, thumbprint_size); err = EINVAL; goto err; } have_thumbprint = TRUE; gnutls_x509_crt_deinit(crt); crt = NULL; break; default: /* We do not care about other types. */ break; } gnutls_pkcs12_bag_deinit(bag); } err: if (rsa_key && (err || *df_type == DF_TYPE_UNKNOWN || !have_thumbprint)) { if (!err) ntfs_log_error("Key type or thumbprint not found, " "aborting.\n"); ntfs_rsa_private_key_release(rsa_key); rsa_key = NULL; } if (crt) gnutls_x509_crt_deinit(crt); if (pkey) gnutls_x509_privkey_deinit(pkey); if (bag) gnutls_pkcs12_bag_deinit(bag); if (pkcs12) gnutls_pkcs12_deinit(pkcs12); return rsa_key; }
static void ssl_gnutls_handshake_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleSslConnection *gsc = data; PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); ssize_t ret; /*purple_debug_info("gnutls", "Handshaking with %s\n", gsc->host);*/ ret = gnutls_handshake(gnutls_data->session); if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) return; purple_input_remove(gnutls_data->handshake_handler); gnutls_data->handshake_handler = 0; if(ret != 0) { purple_debug_error("gnutls", "Handshake failed. Error %s\n", gnutls_strerror(ret)); if(gsc->error_cb != NULL) gsc->error_cb(gsc, PURPLE_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); purple_ssl_close(gsc); } else { /* Now we are cooking with gas! */ PurpleSslOps *ops = purple_ssl_get_ops(); GList * peers = ops->get_peer_certificates(gsc); PurpleCertificateScheme *x509 = purple_certificate_find_scheme("x509"); GList * l; /* TODO: Remove all this debugging babble */ purple_debug_info("gnutls", "Handshake complete\n"); for (l=peers; l; l = l->next) { PurpleCertificate *crt = l->data; GByteArray *z = x509->get_fingerprint_sha1(crt); gchar * fpr = purple_base16_encode_chunked(z->data, z->len); purple_debug_info("gnutls/x509", "Key print: %s\n", fpr); /* Kill the cert! */ x509->destroy_certificate(crt); g_free(fpr); g_byte_array_free(z, TRUE); } g_list_free(peers); { const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; gnutls_session_t session=gnutls_data->session; guint i; cert_list = gnutls_certificate_get_peers(session, &cert_list_size); purple_debug_info("gnutls", "Peer provided %d certs\n", cert_list_size); for (i=0; i<cert_list_size; i++) { gchar fpr_bin[256]; gsize fpr_bin_sz = sizeof(fpr_bin); gchar * fpr_asc = NULL; gchar tbuf[256]; gsize tsz=sizeof(tbuf); gchar * tasc = NULL; gnutls_x509_crt_t cert; gnutls_x509_crt_init(&cert); gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER); gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA, fpr_bin, &fpr_bin_sz); fpr_asc = purple_base16_encode_chunked((const guchar *)fpr_bin, fpr_bin_sz); purple_debug_info("gnutls", "Lvl %d SHA1 fingerprint: %s\n", i, fpr_asc); tsz=sizeof(tbuf); gnutls_x509_crt_get_serial(cert,tbuf,&tsz); tasc=purple_base16_encode_chunked((const guchar *)tbuf, tsz); purple_debug_info("gnutls", "Serial: %s\n", tasc); g_free(tasc); tsz=sizeof(tbuf); gnutls_x509_crt_get_dn (cert, tbuf, &tsz); purple_debug_info("gnutls", "Cert DN: %s\n", tbuf); tsz=sizeof(tbuf); gnutls_x509_crt_get_issuer_dn (cert, tbuf, &tsz); purple_debug_info("gnutls", "Cert Issuer DN: %s\n", tbuf); g_free(fpr_asc); fpr_asc = NULL; gnutls_x509_crt_deinit(cert); } } /* TODO: The following logic should really be in libpurple */ /* If a Verifier was given, hand control over to it */ if (gsc->verifier) { GList *peers; /* First, get the peer cert chain */ peers = purple_ssl_get_peer_certificates(gsc); /* Now kick off the verification process */ purple_certificate_verify(gsc->verifier, gsc->host, peers, ssl_gnutls_verified_cb, gsc); purple_certificate_destroy_list(peers); } else { /* Otherwise, just call the "connection complete" callback */ gsc->connect_cb(gsc->connect_cb_data, gsc, cond); } } }
int tls_cert_info_get(tls_t *tls, tls_cert_info_t *tci, char **errstr) { #ifdef HAVE_LIBGNUTLS const gnutls_datum_t *cert_list; unsigned int cert_list_size; gnutls_x509_crt_t cert; size_t size; const char *oid[6] = { GNUTLS_OID_X520_COMMON_NAME, GNUTLS_OID_X520_ORGANIZATION_NAME, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, GNUTLS_OID_X520_LOCALITY_NAME, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, GNUTLS_OID_X520_COUNTRY_NAME }; int i; int e; char *p; const char *errmsg; errmsg = _("cannot get TLS certificate info"); if (!(cert_list = gnutls_certificate_get_peers(tls->session, &cert_list_size)) || cert_list_size == 0) { *errstr = xasprintf(_("%s: no certificate was found"), errmsg); return TLS_ECERT; } if (gnutls_x509_crt_init(&cert) != 0) { *errstr = xasprintf(_("%s: cannot initialize certificate structure"), errmsg); return TLS_ECERT; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) != 0) { *errstr = xasprintf(_("%s: error parsing certificate"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } /* certificate information */ size = 20; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA, tci->sha1_fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } size = 16; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, tci->md5_fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if ((tci->activation_time = gnutls_x509_crt_get_activation_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get activation time"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if ((tci->expiration_time = gnutls_x509_crt_get_expiration_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get expiration time"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } /* owner information */ for (i = 0; i < 6; i++) { size = 0; e = gnutls_x509_crt_get_dn_by_oid(cert, oid[i], 0, 0, NULL, &size); if (e == GNUTLS_E_SHORT_MEMORY_BUFFER) { p = xmalloc(size); e = gnutls_x509_crt_get_dn_by_oid(cert, oid[i], 0, 0, p, &size); if (e == 0) { tci->owner_info[i] = p; } else { free(p); } } } /* issuer information */ for (i = 0; i < 6; i++) { size = 0; e = gnutls_x509_crt_get_issuer_dn_by_oid( cert, oid[i], 0, 0, NULL, &size); if (e == GNUTLS_E_SHORT_MEMORY_BUFFER) { p = xmalloc(size); e = gnutls_x509_crt_get_issuer_dn_by_oid( cert, oid[i], 0, 0, p, &size); if (e == 0) { tci->issuer_info[i] = p; } else { free(p); } } } gnutls_x509_crt_deinit(cert); return TLS_EOK; #endif /* HAVE_LIBGNUTLS */ #ifdef HAVE_LIBSSL X509 *x509cert; X509_NAME *x509_subject; X509_NAME *x509_issuer; ASN1_TIME *asn1time; int nid[6] = { NID_commonName, NID_organizationName, NID_organizationalUnitName, NID_localityName, NID_stateOrProvinceName, NID_countryName }; int size; unsigned int usize; char *p; int i; const char *errmsg; errmsg = _("cannot get TLS certificate info"); if (!(x509cert = SSL_get_peer_certificate(tls->ssl))) { *errstr = xasprintf(_("%s: no certificate was found"), errmsg); return TLS_ECERT; } if (!(x509_subject = X509_get_subject_name(x509cert))) { *errstr = xasprintf(_("%s: cannot get certificate subject"), errmsg); X509_free(x509cert); return TLS_ECERT; } if (!(x509_issuer = X509_get_issuer_name(x509cert))) { *errstr = xasprintf(_("%s: cannot get certificate issuer"), errmsg); X509_free(x509cert); return TLS_ECERT; } /* certificate information */ usize = 20; if (!X509_digest(x509cert, EVP_sha1(), tci->sha1_fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), errmsg); return TLS_ECERT; } usize = 16; if (!X509_digest(x509cert, EVP_md5(), tci->md5_fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), errmsg); return TLS_ECERT; } asn1time = X509_get_notBefore(x509cert); if (asn1time_to_time_t((char *)asn1time->data, (asn1time->type != V_ASN1_GENERALIZEDTIME), &(tci->activation_time)) != 0) { *errstr = xasprintf(_("%s: cannot get activation time"), errmsg); X509_free(x509cert); tls_cert_info_free(tci); return TLS_ECERT; } asn1time = X509_get_notAfter(x509cert); if (asn1time_to_time_t((char *)asn1time->data, (asn1time->type != V_ASN1_GENERALIZEDTIME), &(tci->expiration_time)) != 0) { *errstr = xasprintf(_("%s: cannot get expiration time"), errmsg); X509_free(x509cert); tls_cert_info_free(tci); return TLS_ECERT; } /* owner information */ for (i = 0; i < 6; i++) { size = X509_NAME_get_text_by_NID(x509_subject, nid[i], NULL, 0); size++; p = xmalloc((size_t)size); if (X509_NAME_get_text_by_NID(x509_subject, nid[i], p, size) != -1) { tci->owner_info[i] = p; } else { free(p); } } /* issuer information */ for (i = 0; i < 6; i++) { size = X509_NAME_get_text_by_NID(x509_issuer, nid[i], NULL, 0); size++; p = xmalloc((size_t)size); if (X509_NAME_get_text_by_NID(x509_issuer, nid[i], p, size) != -1) { tci->issuer_info[i] = p; } else { free(p); } } X509_free(x509cert); return TLS_EOK; #endif /* HAVE_LIBSSL */ }
static GtkWidget *cert_presenter(SSLCertificate *cert) { GtkWidget *vbox = NULL; GtkWidget *hbox = NULL; GtkWidget *frame_owner = NULL; GtkWidget *frame_signer = NULL; GtkWidget *frame_status = NULL; GtkTable *owner_table = NULL; GtkTable *signer_table = NULL; GtkTable *status_table = NULL; GtkWidget *label = NULL; char *issuer_commonname, *issuer_location, *issuer_organization; char *subject_commonname, *subject_location, *subject_organization; char *sig_status, *exp_date; char *md5_fingerprint, *sha1_fingerprint, *fingerprint; size_t n; char buf[100]; unsigned char md[128]; char *tmp; time_t exp_time_t; struct tm lt; /* issuer */ issuer_commonname = g_malloc(BUFFSIZE); issuer_location = g_malloc(BUFFSIZE); issuer_organization = g_malloc(BUFFSIZE); subject_commonname = g_malloc(BUFFSIZE); subject_location = g_malloc(BUFFSIZE); subject_organization = g_malloc(BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, issuer_commonname, &n)) strncpy(issuer_commonname, _("<not in certificate>"), BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, issuer_location, &n)) { if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, issuer_location, &n)) { strncpy(issuer_location, _("<not in certificate>"), BUFFSIZE); } } else { tmp = g_malloc(BUFFSIZE); if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, tmp, &n) == 0) { strncat(issuer_location, ", ", BUFFSIZE-strlen(issuer_location)-1); strncat(issuer_location, tmp, BUFFSIZE-strlen(issuer_location)-1); } g_free(tmp); } n = BUFFSIZE; if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, issuer_organization, &n)) strncpy(issuer_organization, _("<not in certificate>"), BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, subject_commonname, &n)) strncpy(subject_commonname, _("<not in certificate>"), BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, subject_location, &n)) { if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, subject_location, &n)) { strncpy(subject_location, _("<not in certificate>"), BUFFSIZE); } } else { tmp = g_malloc(BUFFSIZE); if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, tmp, &n) == 0) { strncat(subject_location, ", ", BUFFSIZE-strlen(subject_location)-1); strncat(subject_location, tmp, BUFFSIZE-strlen(subject_location)-1); } g_free(tmp); } n = BUFFSIZE; if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, subject_organization, &n)) strncpy(subject_organization, _("<not in certificate>"), BUFFSIZE); exp_time_t = gnutls_x509_crt_get_expiration_time(cert->x509_cert); memset(buf, 0, sizeof(buf)); if (exp_time_t > 0) { fast_strftime(buf, sizeof(buf)-1, prefs_common.date_format, localtime_r(&exp_time_t, <)); exp_date = (*buf) ? g_strdup(buf):g_strdup("?"); } else exp_date = g_strdup(""); /* fingerprint */ n = 128; gnutls_x509_crt_get_fingerprint(cert->x509_cert, GNUTLS_DIG_MD5, md, &n); md5_fingerprint = readable_fingerprint(md, (int)n); n = 128; gnutls_x509_crt_get_fingerprint(cert->x509_cert, GNUTLS_DIG_SHA1, md, &n); sha1_fingerprint = readable_fingerprint(md, (int)n); /* signature */ sig_status = ssl_certificate_check_signer(cert->x509_cert, cert->status); if (sig_status==NULL) sig_status = g_strdup(_("Correct")); vbox = gtk_vbox_new(FALSE, 5); hbox = gtk_hbox_new(FALSE, 5); frame_owner = gtk_frame_new(_("Owner")); frame_signer = gtk_frame_new(_("Signer")); frame_status = gtk_frame_new(_("Status")); owner_table = GTK_TABLE(gtk_table_new(3, 2, FALSE)); signer_table = GTK_TABLE(gtk_table_new(3, 2, FALSE)); status_table = GTK_TABLE(gtk_table_new(3, 2, FALSE)); label = gtk_label_new(_("Name: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(owner_table, label, 0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(subject_commonname); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(owner_table, label, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Organization: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(owner_table, label, 0, 1, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(subject_organization); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(owner_table, label, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Location: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(owner_table, label, 0, 1, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(subject_location); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(owner_table, label, 1, 2, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Name: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(signer_table, label, 0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(issuer_commonname); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(signer_table, label, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Organization: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(signer_table, label, 0, 1, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(issuer_organization); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(signer_table, label, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Location: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(signer_table, label, 0, 1, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(issuer_location); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(signer_table, label, 1, 2, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Fingerprint: \n")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(status_table, label, 0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); fingerprint = g_strdup_printf("MD5: %s\nSHA1: %s", md5_fingerprint, sha1_fingerprint); label = gtk_label_new(fingerprint); g_free(fingerprint); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(status_table, label, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Signature status: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(status_table, label, 0, 1, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(sig_status); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(status_table, label, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Expires on: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(status_table, label, 0, 1, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(exp_date); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(status_table, label, 1, 2, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); gtk_container_add(GTK_CONTAINER(frame_owner), GTK_WIDGET(owner_table)); gtk_container_add(GTK_CONTAINER(frame_signer), GTK_WIDGET(signer_table)); gtk_container_add(GTK_CONTAINER(frame_status), GTK_WIDGET(status_table)); gtk_box_pack_end(GTK_BOX(hbox), frame_signer, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(hbox), frame_owner, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(vbox), frame_status, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gtk_widget_show_all(vbox); g_free(issuer_commonname); g_free(issuer_location); g_free(issuer_organization); g_free(subject_commonname); g_free(subject_location); g_free(subject_organization); g_free(md5_fingerprint); g_free(sha1_fingerprint); g_free(sig_status); g_free(exp_date); return vbox; }
int CTlsSocket::VerifyCertificate() { if (m_tlsState != handshake) { m_pOwner->LogMessage(Debug_Warning, _T("VerifyCertificate called at wrong time")); return FZ_REPLY_ERROR; } m_tlsState = verifycert; if (gnutls_certificate_type_get(m_session) != GNUTLS_CRT_X509) { m_pOwner->LogMessage(::Debug_Warning, _T("Unsupported certificate type")); Failure(0); return FZ_REPLY_ERROR; } unsigned int cert_list_size; const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(m_session, &cert_list_size); if (!cert_list || !cert_list_size) { m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_certificate_get_peers returned no certificates")); Failure(0); return FZ_REPLY_ERROR; } if (m_implicitTrustedCert.data) { if (m_implicitTrustedCert.size != cert_list[0].size || memcmp(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size)) { m_pOwner->LogMessage(::Error, _("Primary connection and data connection certificates don't match.")); Failure(0); return FZ_REPLY_ERROR; } TrustCurrentCert(true); return FZ_REPLY_OK; } gnutls_x509_crt_t cert; if (gnutls_x509_crt_init(&cert)) { m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_crt_init failed")); Failure(0); return FZ_REPLY_ERROR; } if (gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER)) { m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_crt_import failed")); Failure(0); gnutls_x509_crt_deinit(cert); return FZ_REPLY_ERROR; } wxDateTime expirationTime = gnutls_x509_crt_get_expiration_time(cert); wxDateTime activationTime = gnutls_x509_crt_get_activation_time(cert); // Get the serial number of the certificate unsigned char buffer[40]; size_t size = sizeof(buffer); int res = gnutls_x509_crt_get_serial(cert, buffer, &size); wxString serial = bin2hex(buffer, size); unsigned int bits; int algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits); wxString algoName; const char* pAlgo = gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo); if (pAlgo) algoName = wxString(pAlgo, wxConvUTF8); //int version = gnutls_x509_crt_get_version(cert); wxString subject, issuer; size = 0; res = gnutls_x509_crt_get_dn(cert, 0, &size); if (size) { char* dn = new char[size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_dn(cert, dn, &size))) { dn[size] = 0; subject = wxString(dn, wxConvUTF8); } else LogError(res); delete [] dn; } else LogError(res); if (subject == _T("")) { m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_get_dn failed")); Failure(0); gnutls_x509_crt_deinit(cert); return FZ_REPLY_ERROR; } size = 0; res = gnutls_x509_crt_get_issuer_dn(cert, 0, &size); if (size) { char* dn = new char[size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_issuer_dn(cert, dn, &size))) { dn[size] = 0; issuer = wxString(dn, wxConvUTF8); } else LogError(res); delete [] dn; } else LogError(res); if (issuer == _T("")) { m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_get_issuer_dn failed")); Failure(0); gnutls_x509_crt_deinit(cert); return FZ_REPLY_ERROR; } wxString fingerprint_md5; wxString fingerprint_sha1; unsigned char digest[100]; size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &size)) { digest[size] = 0; fingerprint_md5 = bin2hex(digest, size); } size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &size)) { digest[size] = 0; fingerprint_sha1 = bin2hex(digest, size); } CCertificateNotification *pNotification = new CCertificateNotification( m_pOwner->GetCurrentServer()->GetHost(), m_pOwner->GetCurrentServer()->GetPort(), cert_list->data, cert_list->size, activationTime, expirationTime, serial, algoName, bits, fingerprint_md5, fingerprint_sha1, subject, issuer); pNotification->requestNumber = m_pOwner->GetEngine()->GetNextAsyncRequestNumber(); m_pOwner->GetEngine()->AddNotification(pNotification); m_pOwner->LogMessage(Status, _("Verifying certificate...")); return FZ_REPLY_WOULDBLOCK; }
int CTlsSocket::VerifyCertificate() { if (m_tlsState != handshake) { m_pOwner->LogMessage(::Debug_Warning, _T("VerifyCertificate called at wrong time")); return FZ_REPLY_ERROR; } m_tlsState = verifycert; if (gnutls_certificate_type_get(m_session) != GNUTLS_CRT_X509) { m_pOwner->LogMessage(::Error, _("Unsupported certificate type")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } unsigned int status = 0; if (gnutls_certificate_verify_peers2(m_session, &status) < 0) { m_pOwner->LogMessage(::Error, _("Failed to verify peer certificate")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } if (status & GNUTLS_CERT_REVOKED) { m_pOwner->LogMessage(::Error, _("Beware! Certificate has been revoked")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } if (status & GNUTLS_CERT_SIGNER_NOT_CA) { m_pOwner->LogMessage(::Error, _("Incomplete chain, top certificate is not self-signed certificate authority certificate")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } if (m_require_root_trust && status & GNUTLS_CERT_SIGNER_NOT_FOUND) { m_pOwner->LogMessage(::Error, _("Root certificate is not trusted")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } unsigned int cert_list_size; const gnutls_datum_t* cert_list = gnutls_certificate_get_peers(m_session, &cert_list_size); if (!cert_list || !cert_list_size) { m_pOwner->LogMessage(::Error, _("gnutls_certificate_get_peers returned no certificates")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } if (m_implicitTrustedCert.data) { if (m_implicitTrustedCert.size != cert_list[0].size || memcmp(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size)) { m_pOwner->LogMessage(::Error, _("Primary connection and data connection certificates don't match.")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } TrustCurrentCert(true); if (m_tlsState != conn) return FZ_REPLY_ERROR; return FZ_REPLY_OK; } std::vector<CCertificate> certificates; for (unsigned int i = 0; i < cert_list_size; i++) { gnutls_x509_crt_t cert; if (gnutls_x509_crt_init(&cert)) { m_pOwner->LogMessage(::Error, _("Could not initialize structure for peer certificates, gnutls_x509_crt_init failed")); Failure(0, ECONNABORTED); return FZ_REPLY_ERROR; } if (gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER)) { m_pOwner->LogMessage(::Error, _("Could not import peer certificates, gnutls_x509_crt_import failed")); Failure(0, ECONNABORTED); gnutls_x509_crt_deinit(cert); return FZ_REPLY_ERROR; } wxDateTime expirationTime = gnutls_x509_crt_get_expiration_time(cert); wxDateTime activationTime = gnutls_x509_crt_get_activation_time(cert); // Get the serial number of the certificate unsigned char buffer[40]; size_t size = sizeof(buffer); int res = gnutls_x509_crt_get_serial(cert, buffer, &size); wxString serial = bin2hex(buffer, size); unsigned int bits; int algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits); wxString algoName; const char* pAlgo = gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo); if (pAlgo) algoName = wxString(pAlgo, wxConvUTF8); //int version = gnutls_x509_crt_get_version(cert); wxString subject, issuer; size = 0; res = gnutls_x509_crt_get_dn(cert, 0, &size); if (size) { char* dn = new char[size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_dn(cert, dn, &size))) { dn[size] = 0; subject = wxString(dn, wxConvUTF8); } else LogError(res); delete [] dn; } else LogError(res); if (subject == _T("")) { m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate subject, gnutls_x509_get_dn failed")); Failure(0, ECONNABORTED); gnutls_x509_crt_deinit(cert); return FZ_REPLY_ERROR; } size = 0; res = gnutls_x509_crt_get_issuer_dn(cert, 0, &size); if (size) { char* dn = new char[++size + 1]; dn[size] = 0; if (!(res = gnutls_x509_crt_get_issuer_dn(cert, dn, &size))) { dn[size] = 0; issuer = wxString(dn, wxConvUTF8); } else LogError(res); delete [] dn; } else LogError(res); if (issuer == _T("")) { m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate issuer, gnutls_x509_get_issuer_dn failed")); Failure(0, ECONNABORTED); gnutls_x509_crt_deinit(cert); return FZ_REPLY_ERROR; } wxString fingerprint_md5; wxString fingerprint_sha1; unsigned char digest[100]; size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &size)) { digest[size] = 0; fingerprint_md5 = bin2hex(digest, size); } size = sizeof(digest) - 1; if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &size)) { digest[size] = 0; fingerprint_sha1 = bin2hex(digest, size); } certificates.push_back(CCertificate( cert_list->data, cert_list->size, activationTime, expirationTime, serial, algoName, bits, fingerprint_md5, fingerprint_sha1, subject, issuer)); cert_list++; } CCertificateNotification *pNotification = new CCertificateNotification( m_pOwner->GetCurrentServer()->GetHost(), m_pOwner->GetCurrentServer()->GetPort(), GetCipherName(), GetMacName(), certificates); m_pOwner->SendAsyncRequest(pNotification); m_pOwner->LogMessage(Status, _("Verifying certificate...")); return FZ_REPLY_WOULDBLOCK; }