/* Checks if two certs are identical. Return 0 on match. */ int check_if_same_cert (gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2) { gnutls_datum_t cert1bin = { NULL, 0 }, cert2bin = { NULL, 0 }; int result; opaque serial1[128], serial2[128]; size_t serial1_size, serial2_size; serial1_size = sizeof (serial1); result = gnutls_x509_crt_get_serial (cert1, serial1, &serial1_size); if (result < 0) { gnutls_assert (); goto cmp; } serial2_size = sizeof (serial2); result = gnutls_x509_crt_get_serial (cert2, serial2, &serial2_size); if (result < 0) { gnutls_assert (); goto cmp; } if (serial2_size != serial1_size || memcmp (serial1, serial2, serial1_size) != 0) { return 1; } cmp: result = _gnutls_x509_der_encode (cert1->cert, "", &cert1bin, 0); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_der_encode (cert2->cert, "", &cert2bin, 0); if (result < 0) { gnutls_assert (); goto cleanup; } if ((cert1bin.size == cert2bin.size) && (memcmp (cert1bin.data, cert2bin.data, cert1bin.size) == 0)) result = 0; else result = 1; cleanup: _gnutls_free_datum (&cert1bin); _gnutls_free_datum (&cert2bin); return result; }
/*- * gnutls_x509_extract_certificate_serial - This function returns the certificate's serial number * @cert: is an X.509 DER encoded certificate * @result: The place where the serial number will be copied * @result_size: Holds the size of the result field. * * This function will return the X.509 certificate's serial number. * This is obtained by the X509 Certificate serialNumber * field. Serial is not always a 32 or 64bit number. Some CAs use * large serial numbers, thus it may be wise to handle it as something * opaque. * Returns a negative value in case of an error. * -*/ int gnutls_x509_extract_certificate_serial (const gnutls_datum_t * cert, char *result, int *result_size) { gnutls_x509_crt_t xcert; size_t size = *result_size; int ret; ret = gnutls_x509_crt_init (&xcert); if (ret < 0) return ret; ret = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_x509_crt_deinit (xcert); return ret; } ret = gnutls_x509_crt_get_serial (xcert, result, &size); *result_size = size; gnutls_x509_crt_deinit (xcert); return ret; }
/** * gnutls_x509_crl_set_crt: * @crl: should contain a gnutls_x509_crl_t type * @crt: a certificate of type #gnutls_x509_crt_t with the revoked certificate * @revocation_time: The time this certificate was revoked * * This function will set a revoked certificate's serial number to the CRL. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crl_set_crt(gnutls_x509_crl_t crl, gnutls_x509_crt_t crt, time_t revocation_time) { int ret; uint8_t serial[128]; size_t serial_size; if (crl == NULL || crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } serial_size = sizeof(serial); ret = gnutls_x509_crt_get_serial(crt, serial, &serial_size); if (ret < 0) { gnutls_assert(); return ret; } ret = gnutls_x509_crl_set_crt_serial(crl, serial, serial_size, revocation_time); if (ret < 0) { gnutls_assert(); return _gnutls_asn2err(ret); } return 0; }
const byteArray X509Certificate::getSerialNumber() const { char serial[64]; size_t serialSize = sizeof(serial); gnutls_x509_crt_get_serial(m_data->cert, serial, &serialSize); return byteArray(serial, serial + serialSize); }
void __certificate_properties_fill_cert_serialNumber(GtkTreeStore *store, GtkTreeIter *parent, gnutls_x509_crt_t *certificate) { gint result; gsize buffer_size = 0; GtkTreeIter j; gchar *buffer = NULL; gchar *value = NULL; result = gnutls_x509_crt_get_serial(*certificate, 0, &buffer_size); if (result != GNUTLS_E_SHORT_MEMORY_BUFFER) { fprintf(stderr, "Error: (%s,%d): %s\n", __FILE__, __LINE__, gnutls_strerror(result)); return; } buffer = g_new0(gchar, buffer_size); if (!buffer) { fprintf(stderr, "Error: (%s,%d): %s\n", __FILE__, __LINE__, "Not enough memory!"); return; } result = gnutls_x509_crt_get_serial(*certificate, buffer, &buffer_size); if (result < 0) { fprintf(stderr, "Error: (%s,%d): %s\n", __FILE__, __LINE__, gnutls_strerror(result)); return; } value = __certificate_properties_dump_raw_data((unsigned char *) buffer, buffer_size); g_free(buffer); gtk_tree_store_append(store, &j, parent); gtk_tree_store_set(store, &j, CERTIFICATE_PROPERTIES_COL_NAME, _("Serial Number"), CERTIFICATE_PROPERTIES_COL_VALUE, value, -1); g_free(value); }
uschar * tls_cert_serial_number(void * cert, uschar * mod) { uschar bin[50], txt[150]; size_t sz = sizeof(bin); uschar * sp; uschar * dp; int ret; if ((ret = gnutls_x509_crt_get_serial((gnutls_x509_crt_t)cert, bin, &sz))) return g_err("gs0", __FUNCTION__, ret); for(dp = txt, sp = bin; sz; dp += 2, sp++, sz--) sprintf(dp, "%.2x", *sp); for(sp = txt; sp[0]=='0' && sp[1]; ) sp++; /* leading zeroes */ return string_copy(sp); }
void gtlsGeneric::logX509CertificateInfo(LogWrapperType _logwrapper, gnutls_session_t _session) { char serial[40]; char dn[128]; size_t size; unsigned int algo, bits; time_t expiration_time, activation_time; const gnutls_datum_t *cert_list; int cert_list_size = 0; gnutls_x509_crt_t cert; if (gnutls_certificate_type_get (_session) != GNUTLS_CRT_X509) { BTG_NOTICE(_logwrapper, "Not a x509 certificate, abort."); return; } cert_list = gnutls_certificate_get_peers(_session, reinterpret_cast<unsigned int*>(&cert_list_size)); BTG_NOTICE(_logwrapper, "Peer provided " << cert_list_size << " certificates."); if (cert_list_size > 0) { /* we only print information about the first certificate. */ gnutls_x509_crt_init (&cert); gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); BTG_NOTICE(_logwrapper, "Certificate info:"); expiration_time = gnutls_x509_crt_get_expiration_time (cert); activation_time = gnutls_x509_crt_get_activation_time (cert); BTG_NOTICE(_logwrapper, " Certificate is valid since: " << ctime (&activation_time)); BTG_NOTICE(_logwrapper, " Certificate expires: " << ctime (&expiration_time)); /* Print the serial number of the certificate. */ size = sizeof (serial); gnutls_x509_crt_get_serial (cert, serial, &size); size = sizeof (serial); BTG_NOTICE(_logwrapper, " Certificate serial number: " << bin2hex(serial, size)); /* Extract some of the public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits); BTG_NOTICE(_logwrapper, "Certificate public key: " << gnutls_pk_algorithm_get_name(static_cast<gnutls_pk_algorithm_t>(algo))); /* Print the version of the X.509 * certificate. */ BTG_NOTICE(_logwrapper, " Certificate version: #" << gnutls_x509_crt_get_version(cert)); size = sizeof(dn); gnutls_x509_crt_get_dn(cert, dn, &size); BTG_NOTICE(_logwrapper, " DN: " << dn); size = sizeof(dn); gnutls_x509_crt_get_issuer_dn (cert, dn, &size); BTG_NOTICE(_logwrapper, " Issuer's DN: " << dn); 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; }
/** * gnutls_pkcs11_copy_x509_crt2: * @token_url: A PKCS #11 URL specifying a token * @crt: The certificate to copy * @label: The name to be used for the stored data * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_* * * This function will copy a certificate into a PKCS #11 token specified by * a URL. Valid flags to mark the certificate: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED, * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA, %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.4.0 **/ int gnutls_pkcs11_copy_x509_crt2(const char *token_url, gnutls_x509_crt_t crt, const char *label, const gnutls_datum_t *cid, unsigned int flags) { int ret; struct p11_kit_uri *info = NULL; ck_rv_t rv; size_t der_size, id_size, serial_size; gnutls_datum_t serial_der = {NULL, 0}; uint8_t *der = NULL; uint8_t serial[128]; uint8_t id[20]; struct ck_attribute a[MAX_ASIZE]; ck_object_class_t class = CKO_CERTIFICATE; ck_certificate_type_t type = CKC_X_509; ck_object_handle_t ctx; unsigned a_val; struct pkcs11_session_info sinfo; PKCS11_CHECK_INIT; ret = pkcs11_url_to_info(token_url, &info, 0); if (ret < 0) { gnutls_assert(); return ret; } ret = pkcs11_open_session(&sinfo, NULL, info, SESSION_WRITE | pkcs11_obj_flags_to_int(flags)); p11_kit_uri_free(info); if (ret < 0) { gnutls_assert(); return ret; } der_size = 0; ret = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL, &der_size); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert(); goto cleanup; } der = gnutls_malloc(der_size); if (der == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } ret = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der, &der_size); if (ret < 0) { gnutls_assert(); goto cleanup; } a[0].type = CKA_CLASS; a[0].value = &class; a[0].value_len = sizeof(class); a[1].type = CKA_ID; if (cid == NULL || cid->size == 0) { id_size = sizeof(id); ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL); if (ret < 0) { id_size = sizeof(id); ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size); if (ret < 0) { gnutls_assert(); goto cleanup; } } a[1].value = id; a[1].value_len = id_size; } else { a[1].value = cid->data; a[1].value_len = cid->size; } a[2].type = CKA_VALUE; a[2].value = der; a[2].value_len = der_size; a[3].type = CKA_TOKEN; a[3].value = (void *) &tval; a[3].value_len = sizeof(tval); a[4].type = CKA_CERTIFICATE_TYPE; a[4].value = &type; a[4].value_len = sizeof(type); /* FIXME: copy key usage flags */ a_val = 5; a[a_val].type = CKA_SUBJECT; a[a_val].value = crt->raw_dn.data; a[a_val].value_len = crt->raw_dn.size; a_val++; a[a_val].type = CKA_ISSUER; a[a_val].value = crt->raw_issuer_dn.data; a[a_val].value_len = crt->raw_issuer_dn.size; a_val++; serial_size = sizeof(serial); if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) { ret = _gnutls_x509_ext_gen_number(serial, serial_size, &serial_der); if (ret >= 0) { a[a_val].type = CKA_SERIAL_NUMBER; a[a_val].value = (void *) serial_der.data; a[a_val].value_len = serial_der.size; a_val++; } } if (label) { a[a_val].type = CKA_LABEL; a[a_val].value = (void *) label; a[a_val].value_len = strlen(label); a_val++; } mark_flags(flags, a, &a_val, sinfo.trusted); rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv)); ret = pkcs11_rv_to_err(rv); goto cleanup; } /* generated! */ ret = 0; cleanup: gnutls_free(der); gnutls_free(serial_der.data); pkcs11_close_session(&sinfo); return ret; }
static int ctx_ocsp_response(gnutls_session_t session, void* ptr, gnutls_datum_t* ocsp_resp) { liGnuTLSOCSP* ocsp = ptr; guint i; int r; gnutls_datum_t serial = { NULL, 0 }; gnutls_datum_t issuer_name = { NULL, 0 }; char* issuer_name_hash = NULL; if (0 == ocsp->responses->len) return GNUTLS_E_NO_CERTIFICATE_STATUS; serial.size = ocsp->max_serial_length; serial.data = gnutls_malloc(serial.size); issuer_name_hash = gnutls_malloc(ocsp->max_hash_length); { gnutls_datum_t const* crt_datum; gnutls_x509_crt_t crt = NULL; size_t serial_size = ocsp->max_serial_length; crt_datum = gnutls_certificate_get_ours(session); /* memory is NOT owned */ if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_init(&crt))) goto cleanup; if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_import(crt, crt_datum, GNUTLS_X509_FMT_DER))) { gnutls_x509_crt_deinit(crt); goto cleanup; } ; if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_get_serial(crt, serial.data, &serial_size))) { gnutls_x509_crt_deinit(crt); goto cleanup; } serial.size = serial_size; if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_get_raw_issuer_dn(crt, &issuer_name))) { gnutls_x509_crt_deinit(crt); goto cleanup; } gnutls_x509_crt_deinit(crt); } for (i = 0; i < ocsp->responses->len; ++i) { ocsp_response* response = &g_array_index(ocsp->responses, ocsp_response, i); guint j; for (j = 0; j < response->certificates->len; ++j) { ocsp_response_cert_entry* entry = &g_array_index(response->certificates, ocsp_response_cert_entry, i); if (serial.size != entry->serial.size || 0 != memcmp(serial.data, entry->serial.data, serial.size)) continue; if (GNUTLS_E_SUCCESS > (r = gnutls_hash_fast(entry->digest, issuer_name.data, issuer_name.size, issuer_name_hash))) goto cleanup; if (0 != memcmp(issuer_name_hash, entry->issuer_name_hash.data, entry->issuer_name_hash.size)) continue; ocsp_resp->size = response->resp_data.size; ocsp_resp->data = gnutls_malloc(ocsp_resp->size); memcpy(ocsp_resp->data, response->resp_data.data, ocsp_resp->size); r = GNUTLS_E_SUCCESS; goto cleanup; } } r = GNUTLS_E_NO_CERTIFICATE_STATUS; cleanup: gnutls_free(issuer_name_hash); gnutls_free(issuer_name.data); gnutls_free(serial.data); return r; }
/* This function will print information about this session's peer * certificate. */ void print_x509_certificate_info (gnutls_session_t session) { char serial[40]; char dn[128]; size_t size; unsigned int algo, bits; time_t expiration_time, activation_time; const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; gnutls_x509_crt_t cert; /* This function only works for X.509 certificates. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); printf ("Peer provided %d certificates.\n", cert_list_size); if (cert_list_size > 0) { /* we only print information about the first certificate. */ gnutls_x509_crt_init (&cert); gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); printf ("Certificate info:\n"); expiration_time = gnutls_x509_crt_get_expiration_time (cert); activation_time = gnutls_x509_crt_get_activation_time (cert); printf ("\tCertificate is valid since: %s", ctime (&activation_time)); printf ("\tCertificate expires: %s", ctime (&expiration_time)); /* Print the serial number of the certificate. */ size = sizeof (serial); gnutls_x509_crt_get_serial (cert, serial, &size); printf ("\tCertificate serial number: %s\n", bin2hex (serial, size)); /* Extract some of the public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits); printf ("Certificate public key: %s", gnutls_pk_algorithm_get_name (algo)); /* Print the version of the X.509 * certificate. */ printf ("\tCertificate version: #%d\n", gnutls_x509_crt_get_version (cert)); size = sizeof (dn); gnutls_x509_crt_get_dn (cert, dn, &size); printf ("\tDN: %s\n", dn); size = sizeof (dn); gnutls_x509_crt_get_issuer_dn (cert, dn, &size); printf ("\tIssuer's DN: %s\n", dn); gnutls_x509_crt_deinit (cert); } }
/* This function will print information about this session's peer * certificate. */ void print_x509_certificate_info (gnutls_session_t session) { char serial[40]; char dn[256]; size_t size; unsigned int algo, bits; time_t expiration_time, activation_time; const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; gnutls_x509_crt_t cert; gnutls_datum_t cinfo; /* This function only works for X.509 certificates. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); printf ("Peer provided %d certificates.\n", cert_list_size); if (cert_list_size > 0) { int ret; /* we only print information about the first certificate. */ gnutls_x509_crt_init (&cert); gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); printf ("Certificate info:\n"); /* This is the preferred way of printing short information about a certificate. */ ret = gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo); if (ret == 0) { printf ("\t%s\n", cinfo.data); gnutls_free (cinfo.data); } /* If you want to extract fields manually for some other reason, below are popular example calls. */ expiration_time = gnutls_x509_crt_get_expiration_time (cert); activation_time = gnutls_x509_crt_get_activation_time (cert); printf ("\tCertificate is valid since: %s", ctime (&activation_time)); printf ("\tCertificate expires: %s", ctime (&expiration_time)); /* Print the serial number of the certificate. */ size = sizeof (serial); gnutls_x509_crt_get_serial (cert, serial, &size); printf ("\tCertificate serial number: %s\n", bin2hex (serial, size)); /* Extract some of the public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits); printf ("Certificate public key: %s", gnutls_pk_algorithm_get_name (algo)); /* Print the version of the X.509 * certificate. */ printf ("\tCertificate version: #%d\n", gnutls_x509_crt_get_version (cert)); size = sizeof (dn); gnutls_x509_crt_get_dn (cert, dn, &size); printf ("\tDN: %s\n", dn); size = sizeof (dn); gnutls_x509_crt_get_issuer_dn (cert, dn, &size); printf ("\tIssuer's DN: %s\n", dn); gnutls_x509_crt_deinit (cert); } }
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 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; }
/* This function will print information about this session's peer * certificate. */ static void logcertinfo (gnutls_session_t session) { time_t now = time (NULL); const gnutls_datum_t *cert_list; unsigned cert_list_size = 0; gnutls_x509_crt_t cert; size_t i; int rc; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (!cert_list) return; rc = gnutls_x509_crt_init (&cert); if (rc < 0) { syslog (LOG_ERR | LOG_DAEMON, "TLS xci failed (%d): %s", rc, gnutls_strerror (rc)); return; } if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) for (i = 0; i < cert_list_size; i++) { time_t expiration_time, activation_time; char *expiration_time_str = NULL, *activation_time_str = NULL; unsigned char *serial = NULL, *serialhex = NULL; char *issuer = NULL, *subject = NULL; size_t seriallen, issuerlen, subjectlen; unsigned char md5fingerprint[16], md5fingerprinthex[3 * 16 + 1]; size_t md5fingerprintlen; int algo; unsigned bits; const char *keytype, *validity; rc = gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER); if (rc < 0) { syslog (LOG_ERR | LOG_DAEMON, "TLS xci[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } md5fingerprintlen = sizeof (md5fingerprint); rc = gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[i], md5fingerprint, &md5fingerprintlen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS f[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } for (i = 0; i < md5fingerprintlen; i++) sprintf ((char *) &md5fingerprinthex[3 * i], "%.2x:", md5fingerprint[i]); expiration_time = gnutls_x509_crt_get_expiration_time (cert); if (expiration_time == (time_t) - 1) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcget[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } activation_time = gnutls_x509_crt_get_activation_time (cert); if (expiration_time == (time_t) - 1) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgat[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } expiration_time_str = xstrdup (ctime (&expiration_time)); if (expiration_time_str[strlen (expiration_time_str) - 1] == '\n') expiration_time_str[strlen (expiration_time_str) - 1] = '\0'; activation_time_str = xstrdup (ctime (&activation_time)); if (activation_time_str[strlen (activation_time_str) - 1] == '\n') activation_time_str[strlen (activation_time_str) - 1] = '\0'; rc = gnutls_x509_crt_get_dn (cert, NULL, &subjectlen); if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgd[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } subject = xmalloc (++subjectlen); rc = gnutls_x509_crt_get_dn (cert, subject, &subjectlen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgd2[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } rc = gnutls_x509_crt_get_issuer_dn (cert, NULL, &issuerlen); if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgid[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } issuer = xmalloc (++issuerlen); rc = gnutls_x509_crt_get_issuer_dn (cert, issuer, &issuerlen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgid2[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } seriallen = 0; rc = gnutls_x509_crt_get_serial (cert, NULL, &seriallen); if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgs[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } serial = xmalloc (seriallen); rc = gnutls_x509_crt_get_serial (cert, serial, &seriallen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgs2[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } serialhex = xmalloc (2 * seriallen + 1); for (i = 0; i < seriallen; i++) sprintf ((char *) &serialhex[2 * i], "%.2x", serial[i]); algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits); if (algo == GNUTLS_PK_RSA) keytype = "RSA modulus"; else if (algo == GNUTLS_PK_DSA) keytype = "DSA exponent"; else keytype = "UNKNOWN"; if (expiration_time < now) validity = "EXPIRED"; else if (activation_time > now) validity = "NOT YET ACTIVATED"; else validity = "valid"; /* This message can arguably belong to LOG_AUTH. */ syslog (LOG_INFO, "TLS client certificate `%s', issued by `%s', " "serial number `%s', MD5 fingerprint `%s', activated `%s', " "expires `%s', version #%d, key %s %d bits, currently %s", subject, issuer, serialhex, md5fingerprinthex, activation_time_str, expiration_time_str, gnutls_x509_crt_get_version (cert), keytype, bits, validity); cleanup: free (serialhex); free (serial); free (expiration_time_str); free (activation_time_str); free (issuer); free (subject); } gnutls_x509_crt_deinit (cert); { unsigned int status; /* Accept default syslog facility for these errors. * They are clearly relevant as audit traces. */ rc = gnutls_certificate_verify_peers2 (session, &status); if (rc != GNUTLS_E_SUCCESS) syslog (LOG_ERR, "TLS client certificate failed (%d): %s", rc, gnutls_strerror (rc)); if (status != 0) syslog (LOG_ERR, "TLS client certificate verify failure (%d)", status); } }