예제 #1
0
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();
}
예제 #2
0
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;
}
예제 #3
0
파일: gnutls.c 프로젝트: viatsko/charybdis
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;
}
예제 #5
0
파일: tlscert-gnu.c 프로젝트: toddr/exim
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;
}
예제 #6
0
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;
}
예제 #7
0
파일: gnutls.c 프로젝트: Macs/NeoIRCd
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;
}
예제 #8
0
	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);
	}
예제 #9
0
파일: tlssocket.cpp 프로젝트: jplee/MILF
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;
}
예제 #10
0
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;
}
예제 #11
0
파일: tls.c 프로젝트: yomei-o/msmtp
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 */
}
예제 #12
0
/**
 * 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;
}
예제 #13
0
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);
		}
	}

}
예제 #14
0
파일: tls.c 프로젝트: yomei-o/msmtp
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 */
}
예제 #15
0
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, &lt));
		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;
}
예제 #16
0
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;
}
예제 #17
0
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;
}