Ejemplo n.º 1
0
void __certificate_properties_fill_cert_validity (GtkTreeStore *store, GtkTreeIter *parent, gnutls_x509_crt_t *certificate)
{
    time_t not_before;
#ifndef WIN32
    struct tm not_before_broken_down_time;
#else
    struct tm *not_before_broken_down_time = NULL;
#endif
    gchar not_before_asctime[32];
    time_t not_after;
#ifndef WIN32
    struct tm not_after_broken_down_time;
#else
    struct tm *not_after_broken_down_time = NULL;
#endif
    gchar not_after_asctime[32];
    GtkTreeIter j;
    GtkTreeIter k;

#ifndef WIN32
    not_before = gnutls_x509_crt_get_activation_time(*certificate);
    gmtime_r (&not_before, &not_before_broken_down_time);
    asctime_r(&not_before_broken_down_time, not_before_asctime);
    not_before_asctime[strlen(not_before_asctime) - 1] = 0;
#else
    not_before = gnutls_x509_crt_get_activation_time(*certificate);
    not_before_broken_down_time = gmtime(&not_before);
    snprintf(not_before_asctime, sizeof(not_before_asctime), "%s", asctime(not_before_broken_down_time));
    // not_before_asctime[strlen(not_before_asctime) - 1] = 0; // ???
#endif

#ifndef WIN32
    not_after = gnutls_x509_crt_get_expiration_time(*certificate);
    gmtime_r(&not_after, &not_after_broken_down_time);
    asctime_r(&not_after_broken_down_time, not_after_asctime);
    not_after_asctime[strlen(not_after_asctime) - 1] = 0;
#else
    not_after = gnutls_x509_crt_get_expiration_time(*certificate);
    not_after_broken_down_time = gmtime(&not_after);
    snprintf(not_after_asctime, sizeof(not_after_asctime), "%s", asctime(not_after_broken_down_time));
    // not_after_asctime[strlen(not_after_asctime) - 1] = 0; // ???
#endif

    gtk_tree_store_append(store, &j, parent);
    gtk_tree_store_set(store, &j, CERTIFICATE_PROPERTIES_COL_NAME, _("Validity"), -1);

    gtk_tree_store_append(store, &k, &j);
    gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("Not Before"), CERTIFICATE_PROPERTIES_COL_VALUE, not_before_asctime, -1);

    gtk_tree_store_append(store, &k, &j);
    gtk_tree_store_set(store, &k, CERTIFICATE_PROPERTIES_COL_NAME, _("Not After"), CERTIFICATE_PROPERTIES_COL_VALUE, not_after_asctime, -1);
}
Ejemplo n.º 2
0
int
verify_certificate (gnutls_session session, char* CN)
{
	unsigned int cert_list_size;
	const gnutls_datum *cert_list;
	int ret;
	char dn[MAX_DN_LEN];
	size_t dn_len = MAX_DN_LEN;
	gnutls_x509_crt cert;

	ret = gnutls_certificate_verify_peers(session);

	if (ret < 0)
	{
		quorum_debug(LOG_DEBUG,"gnutls_certificate_verify_peers2 returns error");
		return -1;
	}
	if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
		quorum_debug(LOG_DEBUG,"The certificate is not a x.509 cert");
    		return -1;
	}
	if (gnutls_x509_crt_init (&cert) < 0)
	{
		quorum_debug(LOG_DEBUG,"error in gnutls_x509_crt_init");
		return -1;
	}

	cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
	if (cert_list == NULL)
	{
		quorum_debug(LOG_DEBUG,"No certificate was found!");
		return -1;
	}

	if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
	{
		quorum_debug(LOG_DEBUG,"error parsing certificate");
		return -1;
	}

	if (gnutls_x509_crt_get_expiration_time (cert) < time (0))
	{
		quorum_debug(LOG_DEBUG,"The certificate has expired");
		return -1;
	}

	if (gnutls_x509_crt_get_activation_time (cert) > time (0))
	{
		quorum_debug(LOG_DEBUG,"The certificate is not yet activated");
		return -1;
	}
	memset(dn, 0, MAX_DN_LEN);
	gnutls_x509_crt_get_dn(cert, dn, &dn_len);
	strncpy(CN, strstr(dn, "CN=")+3, MAX_DN_LEN);
	CN[MAX_DN_LEN-1]= '\0';
	quorum_debug(LOG_DEBUG,"The certificate cn:%s",CN);
	gnutls_x509_crt_deinit (cert);

	return 0;
}
Ejemplo n.º 3
0
static int verify_issuer(gnutls_x509_crt_t crt,
                         gnutls_x509_crt_t issuer,
                         crypto_error **error)
{
    unsigned int output;
    time_t now = time (0);

    if (gnutls_x509_crt_verify(crt, &issuer, 1, 0, &output) < 0) {
        crypto_error_set(error, 1, 0, "failed to verify against issuer");
        return 1;
    }

    if (output & GNUTLS_CERT_INVALID) {
        if (output & GNUTLS_CERT_SIGNER_NOT_FOUND) {
            crypto_error_set(error, 1, 0, "certificate signer not found");
            return 1;
        }
        if (output & GNUTLS_CERT_SIGNER_NOT_CA) {
            crypto_error_set(error, 1, 0, "certificate signer not a CA");
            return 1;
        }
    }

    if (gnutls_x509_crt_get_activation_time(crt) > now) {
        crypto_error_set(error, 1, 0, "certificate activation in the future");
        return 1;
    }

    if (gnutls_x509_crt_get_expiration_time(crt) < now) {
        crypto_error_set(error, 1, 0, "certificate expired");
        return 1;
    }

    return 0;
}
Ejemplo n.º 4
0
static int verify_last(gnutls_x509_crt_t crt,
                       gnutls_x509_crt_t *ca_list,
                       size_t ca_list_size,
                       crypto_error **error)
{
    unsigned int output;
    time_t now = time (0);

    if (gnutls_x509_crt_verify (crt, ca_list, ca_list_size,
                                GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
                                &output) < 0) {
        crypto_error_set(error, 1, 0, "failed to verify against CA list");
        return 1;
    }

    if (output & GNUTLS_CERT_INVALID) {
        if (output & GNUTLS_CERT_SIGNER_NOT_CA) {
            crypto_error_set(error, 1, 0, "certificate signer not a CA");
            return 1;
        }
    }

    if (gnutls_x509_crt_get_activation_time(crt) > now) {
        crypto_error_set(error, 1, 0, "certificate activation in the future");
        return 1;
    }

    if (gnutls_x509_crt_get_expiration_time(crt) < now) {
        crypto_error_set(error, 1, 0, "certificate expired");
        return 1;
    }

    return 0;
}
Ejemplo n.º 5
0
static gboolean
x509_times (PurpleCertificate *crt, time_t *activation, time_t *expiration)
{
	gnutls_x509_crt_t crt_dat;
	/* GnuTLS time functions return this on error */
	const time_t errval = (time_t) (-1);
	gboolean success = TRUE;

	g_return_val_if_fail(crt, FALSE);
	g_return_val_if_fail(crt->scheme == &x509_gnutls, FALSE);

	crt_dat = X509_GET_GNUTLS_DATA(crt);

	if (activation) {
		*activation = gnutls_x509_crt_get_activation_time(crt_dat);
		if (*activation == errval)
			success = FALSE;
	}
	if (expiration) {
		*expiration = gnutls_x509_crt_get_expiration_time(crt_dat);
		if (*expiration == errval)
			success = FALSE;
	}

	return success;
}
Ejemplo n.º 6
0
/* Finds an issuer of the certificate. If multiple issuers
 * are present, returns one that is activated and not expired.
 */
static inline gnutls_x509_crt_t
find_issuer (gnutls_x509_crt_t cert,
             const gnutls_x509_crt_t * trusted_cas, int tcas_size)
{
int i;
gnutls_x509_crt_t issuer = NULL;

  /* this is serial search. 
   */

  for (i = 0; i < tcas_size; i++)
    {
      if (is_issuer (cert, trusted_cas[i]) == 1)
        {
          if (issuer == NULL) 
            {
              issuer = trusted_cas[i];
            }
          else
            {
              time_t now = gnutls_time(0);

              if (now < gnutls_x509_crt_get_expiration_time(trusted_cas[i]) && 
                now >= gnutls_x509_crt_get_activation_time(trusted_cas[i]))
                {
                  issuer = trusted_cas[i];
                }
            }
        }
    }

  return issuer;
}
Ejemplo n.º 7
0
bool
_gnutls_check_valid_key_id(gnutls_datum_t *key_id,
                           gnutls_x509_crt_t cert, time_t now)
{
	uint8_t id[MAX_KEY_ID_SIZE];
	size_t id_size;
	bool result = 0;

	if (now > gnutls_x509_crt_get_expiration_time(cert) ||
	    now < gnutls_x509_crt_get_activation_time(cert)) {
		/* don't bother, certificate is not yet activated or expired */
		gnutls_assert();
		goto out;
	}

	if (gnutls_x509_crt_get_subject_key_id(cert, id, &id_size, NULL) < 0) {
		gnutls_assert();
		goto out;
	}

	if (id_size == key_id->size && !memcmp(id, key_id->data, id_size))
		result = 1;

 out:
	return result;
}
Ejemplo n.º 8
0
uschar *
tls_cert_not_after(void * cert, uschar * mod)
{
    return time_copy(
               gnutls_x509_crt_get_expiration_time((gnutls_x509_crt_t)cert),
               mod);
}
Ejemplo n.º 9
0
/* Verifies a certificate against our trusted CA list.
 * Also checks the crl_list if the certificate is revoked.
 */
static void
verify_last_cert (gnutls_x509_crt_t crt,
		  gnutls_x509_crt_t * ca_list, int ca_list_size,
		  gnutls_x509_crl_t * crl_list, int crl_list_size)
{
  unsigned int output;
  int ret;
  time_t now = time (0);
  size_t name_size;
  char name[64];

  /* Print information about the certificates to
   * be checked.
   */
  name_size = sizeof (name);
  gnutls_x509_crt_get_dn (crt, name, &name_size);

  fprintf (stderr, "\nCertificate: %s\n", name);

  name_size = sizeof (name);
  gnutls_x509_crt_get_issuer_dn (crt, name, &name_size);

  fprintf (stderr, "Issued by: %s\n", name);

  /* Do the actual verification.
   */
  gnutls_x509_crt_verify (crt, ca_list, ca_list_size,
			  GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &output);

  if (output & GNUTLS_CERT_INVALID)
    {
      fprintf (stderr, "Not trusted");

      if (output & GNUTLS_CERT_SIGNER_NOT_CA)
	fprintf (stderr, ": Issuer is not a CA\n");
      else
	fprintf (stderr, "\n");
    }
  else
    fprintf (stderr, "Trusted\n");


  /* Now check the expiration dates.
   */
  if (gnutls_x509_crt_get_activation_time (crt) > now)
    fprintf (stderr, "Not yet activated\n");

  if (gnutls_x509_crt_get_expiration_time (crt) < now)
    fprintf (stderr, "Expired\n");

  /* Check if the certificate is revoked.
   */
  ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
  if (ret == 1)
    {				/* revoked */
      fprintf (stderr, "Revoked\n");
    }
}
Ejemplo n.º 10
0
static void ssl_manager_list_view_insert_cert(GtkWidget *list_view,
						  GtkTreeIter *row_iter,
						  gchar *host, 
						  gchar *port,
						  SSLCertificate *cert) 
{
	char *sig_status, *exp_date;
	char buf[100];
	time_t exp_time_t;
	struct tm lt;
	PangoWeight weight = PANGO_WEIGHT_NORMAL;
	GtkTreeIter iter, *iterptr;
	GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model
					(GTK_TREE_VIEW(list_view)));

	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("");

	if (exp_time_t < time(NULL))
		weight = PANGO_WEIGHT_BOLD;

	sig_status = ssl_certificate_check_signer(cert, cert->status);

	if (sig_status==NULL)
		sig_status = g_strdup_printf(_("Correct%s"),exp_time_t < time(NULL)? _(" (expired)"): "");
	else {
		 weight = PANGO_WEIGHT_BOLD;
		 if (exp_time_t < time(NULL))
			  sig_status = g_strconcat(sig_status,_(" (expired)"),NULL);
	}

	if (row_iter == NULL) {
		/* append new */
		gtk_list_store_append(list_store, &iter);
		iterptr = &iter;
	} else
		iterptr = row_iter;

	gtk_list_store_set(list_store, iterptr,
			   SSL_MANAGER_HOST, host,
			   SSL_MANAGER_PORT, port,
			   SSL_MANAGER_CERT, cert,
		    	   SSL_MANAGER_STATUS, sig_status,
		    	   SSL_MANAGER_EXPIRY, exp_date,
			   SSL_MANAGER_FONT_WEIGHT, weight,
			   -1);

	g_free(sig_status);
	g_free(exp_date);
}
Ejemplo n.º 11
0
void ne_ssl_cert_validity_time(const ne_ssl_certificate *cert,
                               time_t *from, time_t *until)
{
    if (from) {
        *from = gnutls_x509_crt_get_activation_time(cert->subject);
    }
    if (until) {
        *until = gnutls_x509_crt_get_expiration_time(cert->subject);
    }
}
Ejemplo n.º 12
0
static
int
__pkcs11h_crypto_gnutls_certificate_get_expiration (
	IN void * const global_data,
	IN const unsigned char * const blob,
	IN const size_t blob_size,
	OUT time_t * const expiration
) {
	gnutls_x509_crt_t cert = NULL;
	gnutls_datum_t datum;
	time_t now = time (NULL);
	time_t notBefore;
	time_t notAfter;

	(void)global_data;

	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
	_PKCS11H_ASSERT (blob!=NULL);
	_PKCS11H_ASSERT (expiration!=NULL);

	*expiration = (time_t)0;

	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
		/* gnutls sets output */
		cert = NULL;
		goto cleanup;
	}
	
	datum.data = (unsigned char *)blob;
	datum.size = blob_size;

	if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
		goto cleanup;
	}

	notBefore = gnutls_x509_crt_get_activation_time (cert);
	notAfter = gnutls_x509_crt_get_expiration_time (cert);

	if (
		now >= notBefore &&
		now <= notAfter
	) {
		*expiration = notAfter;
	}

cleanup:

	if (cert != NULL) {
		gnutls_x509_crt_deinit (cert);
		cert = NULL;
	}

	return *expiration != (time_t)0;
}
Ejemplo n.º 13
0
int
verify_certificate (gnutls_session session)
{
	unsigned int cert_list_size;
	const gnutls_datum *cert_list;
	int ret;
	gnutls_x509_crt cert;

	ret = gnutls_certificate_verify_peers (session);

	if (ret < 0)
	{
		printf("gnutls_certificate_verify_peers2 returns error.\n");
		return -1;
	}
	if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
		printf("The certificate is not a x.509 cert\n");
    		return -1;
	}
	if (gnutls_x509_crt_init (&cert) < 0)
	{
		printf("error in gnutls_x509_crt_init\n");
		return -1;
	}

	cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
	if (cert_list == NULL)
	{
		printf("No certificate was found!\n");
		return -1;
	}

	if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
	{
		printf("error parsing certificate\n");
		return -1;
	}

	if (gnutls_x509_crt_get_expiration_time (cert) < time (0))
	{
		printf("The certificate has expired\n");
		return -1;
	}

	if (gnutls_x509_crt_get_activation_time (cert) > time (0))
	{
		printf("The certificate is not yet activated\n");
		return -1;
	}
	
	gnutls_x509_crt_deinit (cert);

	return 0;
}
Ejemplo n.º 14
0
size_t					/* O - Total size of credentials string */
httpCredentialsString(
    cups_array_t *credentials,		/* I - Credentials */
    char         *buffer,		/* I - Buffer or @code NULL@ */
    size_t       bufsize)		/* I - Size of buffer */
{
  http_credential_t	*first;		/* First certificate */
  gnutls_x509_crt_t	cert;		/* Certificate */


  DEBUG_printf(("httpCredentialsString(credentials=%p, buffer=%p, bufsize=" CUPS_LLFMT ")", credentials, buffer, CUPS_LLCAST bufsize));

  if (!buffer)
    return (0);

  if (buffer && bufsize > 0)
    *buffer = '\0';

  if ((first = (http_credential_t *)cupsArrayFirst(credentials)) != NULL &&
      (cert = http_gnutls_create_credential(first)) != NULL)
  {
    char		name[256];	/* Common name associated with cert */
    size_t		namelen;	/* Length of name */
    time_t		expiration;	/* Expiration date of cert */
    _cups_md5_state_t	md5_state;	/* MD5 state */
    unsigned char	md5_digest[16];	/* MD5 result */

    namelen = sizeof(name) - 1;
    if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, name, &namelen) >= 0)
      name[namelen] = '\0';
    else
      strlcpy(name, "unknown", sizeof(name));

    expiration = gnutls_x509_crt_get_expiration_time(cert);

    _cupsMD5Init(&md5_state);
    _cupsMD5Append(&md5_state, first->data, (int)first->datalen);
    _cupsMD5Finish(&md5_state, md5_digest);

    snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]);

    gnutls_x509_crt_deinit(cert);
  }

  DEBUG_printf(("1httpCredentialsString: Returning \"%s\".", buffer));

  return (strlen(buffer));
}
Ejemplo n.º 15
0
time_t					/* O - Expiration date of credentials */
httpCredentialsGetExpiration(
    cups_array_t *credentials)		/* I - Credentials */
{
  gnutls_x509_crt_t	cert;		/* Certificate */
  time_t		result = 0;	/* Result */


  cert = http_gnutls_create_credential((http_credential_t *)cupsArrayFirst(credentials));
  if (cert)
  {
    result = gnutls_x509_crt_get_expiration_time(cert);
    gnutls_x509_crt_deinit(cert);
  }

  return (result);
}
Ejemplo n.º 16
0
/* Verifies an SSL server certificate. */
static int check_certificate(ne_session *sess, gnutls_session sock,
                             ne_ssl_certificate *chain)
{
    time_t before, after, now = time(NULL);
    int ret, failures = 0;

    before = gnutls_x509_crt_get_activation_time(chain->subject);
    after = gnutls_x509_crt_get_expiration_time(chain->subject);

    if (now < before)
        failures |= NE_SSL_NOTYETVALID;
    else if (now > after)
        failures |= NE_SSL_EXPIRED;

    ret = check_identity(sess->server.hostname, chain->subject, NULL);
    if (ret < 0) {
        ne_set_error(sess, _("Server certificate was missing commonName "
                             "attribute in subject name"));
        return NE_ERROR;
    } else if (ret > 0) {
        failures |= NE_SSL_IDMISMATCH;
    }

    if (gnutls_certificate_verify_peers(sock)) {
        failures |= NE_SSL_UNTRUSTED;
    }

    NE_DEBUG(NE_DBG_SSL, "Failures = %d\n", failures);

    if (failures == 0) {
        ret = NE_OK;
    } else {
        ne__ssl_set_verify_err(sess, failures);
        ret = NE_ERROR;
        if (sess->ssl_verify_fn
            && sess->ssl_verify_fn(sess->ssl_verify_ud, failures, chain) == 0)
            ret = NE_OK;
    }

    return ret;
}
Ejemplo n.º 17
0
static unsigned int check_time_status(gnutls_x509_crt_t crt, time_t now)
{
	int status = 0;
	time_t t;

	t = gnutls_x509_crt_get_activation_time(crt);
	if (t == (time_t) - 1 || now < t) {
		status |= GNUTLS_CERT_NOT_ACTIVATED;
		status |= GNUTLS_CERT_INVALID;
		return status;
	}

	t = gnutls_x509_crt_get_expiration_time(crt);
	if (t == (time_t) - 1 || now > t) {
		status |= GNUTLS_CERT_EXPIRED;
		status |= GNUTLS_CERT_INVALID;
		return status;
	}

	return 0;
}
Ejemplo n.º 18
0
/* Return NE_SSL_* failure bits after checking chain expiry. */
static int check_chain_expiry(ne_ssl_certificate *chain)
{
    time_t before, after, now = time(NULL);
    ne_ssl_certificate *cert;
    int failures = 0;
    
    /* Check that all certs within the chain are inside their defined
     * validity period.  Note that the errors flagged for the server
     * cert are different from the generic error for issues higher up
     * the chain. */
    for (cert = chain; cert; cert = cert->issuer) {
        before = gnutls_x509_crt_get_activation_time(cert->subject);
        after = gnutls_x509_crt_get_expiration_time(cert->subject);
        
        if (now < before)
            failures |= (cert == chain) ? NE_SSL_NOTYETVALID : NE_SSL_BADCHAIN;
        else if (now > after)
            failures |= (cert == chain) ? NE_SSL_EXPIRED : NE_SSL_BADCHAIN;
    }

    return failures;
}
Ejemplo n.º 19
0
static int
qcrypto_tls_creds_check_cert_times(gnutls_x509_crt_t cert,
                                   const char *certFile,
                                   bool isServer,
                                   bool isCA,
                                   Error **errp)
{
    time_t now = time(NULL);

    if (now == ((time_t)-1)) {
        error_setg_errno(errp, errno, "cannot get current time");
        return -1;
    }

    if (gnutls_x509_crt_get_expiration_time(cert) < now) {
        error_setg(errp,
                   (isCA ?
                    "The CA certificate %s has expired" :
                    (isServer ?
                     "The server certificate %s has expired" :
                     "The client certificate %s has expired")),
                   certFile);
        return -1;
    }

    if (gnutls_x509_crt_get_activation_time(cert) > now) {
        error_setg(errp,
                   (isCA ?
                    "The CA certificate %s is not yet active" :
                    (isServer ?
                     "The server certificate %s is not yet active" :
                     "The client certificate %s is not yet active")),
                   certFile);
        return -1;
    }

    return 0;
}
Ejemplo n.º 20
0
/*-
 * gnutls_x509_extract_certificate_expiration_time:
 * @cert: should contain an X.509 DER encoded certificate
 *
 * This function will return the certificate's expiration time in UNIX
 * time (ie seconds since 00:00:00 UTC January 1, 1970).  Returns a
 *
 * (time_t) -1 in case of an error.
 *
 -*/
static time_t
_gnutls_x509_get_raw_crt_expiration_time (const gnutls_datum_t * cert)
{
  gnutls_x509_crt_t xcert;
  time_t result;

  result = gnutls_x509_crt_init (&xcert);
  if (result < 0)
    return (time_t) - 1;

  result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
  if (result < 0)
    {
      gnutls_x509_crt_deinit (xcert);
      return (time_t) - 1;
    }

  result = gnutls_x509_crt_get_expiration_time (xcert);

  gnutls_x509_crt_deinit (xcert);

  return result;
}
Ejemplo n.º 21
0
/*-
  * gnutls_x509_extract_certificate_expiration_time - This function returns the certificate's expiration time
  * @cert: should contain an X.509 DER encoded certificate
  *
  * This function will return the certificate's expiration time in UNIX time 
  * (ie seconds since 00:00:00 UTC January 1, 1970).
  * Returns a (time_t) -1 in case of an error.
  *
  -*/
time_t
gnutls_x509_extract_certificate_expiration_time (const gnutls_datum_t * cert)
{
  gnutls_x509_crt_t xcert;
  time_t result;

  result = gnutls_x509_crt_init (&xcert);
  if (result < 0)
    return result;

  result = gnutls_x509_crt_import (xcert, cert, GNUTLS_X509_FMT_DER);
  if (result < 0)
    {
      gnutls_x509_crt_deinit (xcert);
      return result;
    }

  result = gnutls_x509_crt_get_expiration_time (xcert);

  gnutls_x509_crt_deinit (xcert);

  return result;
}
Ejemplo n.º 22
0
         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);
               }
         }
Ejemplo n.º 23
0
/*
 * This function is called after the TCP connect has completed. Setup the TLS
 * layer and do all necessary magic.
 */
CURLcode
Curl_gtls_connect(struct connectdata *conn,
                  int sockindex)

{
    const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
    struct SessionHandle *data = conn->data;
    gnutls_session session;
    int rc;
    unsigned int cert_list_size;
    const gnutls_datum *chainp;
    unsigned int verify_status;
    gnutls_x509_crt x509_cert;
    char certbuf[256]; /* big enough? */
    size_t size;
    unsigned int algo;
    unsigned int bits;
    time_t clock;
    const char *ptr;
    void *ssl_sessionid;
    size_t ssl_idsize;

    /* GnuTLS only supports TLSv1 (and SSLv3?) */
    if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
        failf(data, "GnuTLS does not support SSLv2");
        return CURLE_SSL_CONNECT_ERROR;
    }

    /* allocate a cred struct */
    rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
    if(rc < 0) {
        failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
        return CURLE_SSL_CONNECT_ERROR;
    }

    if(data->set.ssl.CAfile) {
        /* set the trusted CA cert bundle file */
        gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
                                            GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);

        rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
                data->set.ssl.CAfile,
                GNUTLS_X509_FMT_PEM);
        if(rc < 0) {
            infof(data, "error reading ca cert file %s (%s)\n",
                  data->set.ssl.CAfile, gnutls_strerror(rc));
            if (data->set.ssl.verifypeer)
                return CURLE_SSL_CACERT_BADFILE;
        }
        else
            infof(data, "found %d certificates in %s\n",
                  rc, data->set.ssl.CAfile);
    }

    /* Initialize TLS session as a client */
    rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
    if(rc) {
        failf(data, "gnutls_init() failed: %d", rc);
        return CURLE_SSL_CONNECT_ERROR;
    }

    /* convenient assign */
    session = conn->ssl[sockindex].session;

    /* Use default priorities */
    rc = gnutls_set_default_priority(session);
    if(rc < 0)
        return CURLE_SSL_CONNECT_ERROR;

    /* Sets the priority on the certificate types supported by gnutls. Priority
       is higher for types specified before others. After specifying the types
       you want, you must append a 0. */
    rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
    if(rc < 0)
        return CURLE_SSL_CONNECT_ERROR;

    if(data->set.cert) {
        if( gnutls_certificate_set_x509_key_file(
                    conn->ssl[sockindex].cred, data->set.cert,
                    data->set.key != 0 ? data->set.key : data->set.cert,
                    do_file_type(data->set.cert_type) ) ) {
            failf(data, "error reading X.509 key or certificate file");
            return CURLE_SSL_CONNECT_ERROR;
        }
    }

    /* put the credentials to the current session */
    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                                conn->ssl[sockindex].cred);

    /* set the connection handle (file descriptor for the socket) */
    gnutls_transport_set_ptr(session,
                             (gnutls_transport_ptr)conn->sock[sockindex]);

    /* register callback functions to send and receive data. */
    gnutls_transport_set_push_function(session, Curl_gtls_push);
    gnutls_transport_set_pull_function(session, Curl_gtls_pull);

    /* lowat must be set to zero when using custom push and pull functions. */
    gnutls_transport_set_lowat(session, 0);

    /* This might be a reconnect, so we check for a session ID in the cache
       to speed up things */

    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
        /* we got a session id, use it! */
        gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);

        /* Informational message */
        infof (data, "SSL re-using session ID\n");
    }

    rc = handshake(conn, session, sockindex, TRUE);
    if(rc)
        /* handshake() sets its own error message with failf() */
        return rc;

    /* This function will return the peer's raw certificate (chain) as sent by
       the peer. These certificates are in raw format (DER encoded for
       X.509). In case of a X.509 then a certificate list may be present. The
       first certificate in the list is the peer's certificate, following the
       issuer's certificate, then the issuer's issuer etc. */

    chainp = gnutls_certificate_get_peers(session, &cert_list_size);
    if(!chainp) {
        if(data->set.ssl.verifyhost) {
            failf(data, "failed to get server cert");
            return CURLE_SSL_PEER_CERTIFICATE;
        }
        infof(data, "\t common name: WARNING couldn't obtain\n");
    }

    /* This function will try to verify the peer's certificate and return its
       status (trusted, invalid etc.). The value of status should be one or more
       of the gnutls_certificate_status_t enumerated elements bitwise or'd. To
       avoid denial of service attacks some default upper limits regarding the
       certificate key size and chain size are set. To override them use
       gnutls_certificate_set_verify_limits(). */

    rc = gnutls_certificate_verify_peers2(session, &verify_status);
    if (rc < 0) {
        failf(data, "server cert verify failed: %d", rc);
        return CURLE_SSL_CONNECT_ERROR;
    }

    /* verify_status is a bitmask of gnutls_certificate_status bits */
    if(verify_status & GNUTLS_CERT_INVALID) {
        if (data->set.ssl.verifypeer) {
            failf(data, "server certificate verification failed. CAfile: %s",
                  data->set.ssl.CAfile?data->set.ssl.CAfile:"none");
            return CURLE_SSL_CACERT;
        }
        else
            infof(data, "\t server certificate verification FAILED\n");
    }
    else
        infof(data, "\t server certificate verification OK\n");

    /* initialize an X.509 certificate structure. */
    gnutls_x509_crt_init(&x509_cert);

    /* convert the given DER or PEM encoded Certificate to the native
       gnutls_x509_crt_t format */
    gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);

    size=sizeof(certbuf);
    rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
                                       0, /* the first and only one */
                                       FALSE,
                                       certbuf,
                                       &size);
    if(rc) {
        infof(data, "error fetching CN from cert:%s\n",
              gnutls_strerror(rc));
    }

    /* This function will check if the given certificate's subject matches the
       given hostname. This is a basic implementation of the matching described
       in RFC2818 (HTTPS), which takes into account wildcards, and the subject
       alternative name PKIX extension. Returns non zero on success, and zero on
       failure. */
    rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);

    if(!rc) {
        if (data->set.ssl.verifyhost > 1) {
            failf(data, "SSL: certificate subject name (%s) does not match "
                  "target host name '%s'", certbuf, conn->host.dispname);
            gnutls_x509_crt_deinit(x509_cert);
            return CURLE_SSL_PEER_CERTIFICATE;
        }
        else
            infof(data, "\t common name: %s (does not match '%s')\n",
                  certbuf, conn->host.dispname);
    }
    else
        infof(data, "\t common name: %s (matched)\n", certbuf);

    /* Show:

    - ciphers used
    - subject
    - start date
    - expire date
    - common name
    - issuer

    */

    /* public key algorithm's parameters */
    algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
    infof(data, "\t certificate public key: %s\n",
          gnutls_pk_algorithm_get_name(algo));

    /* version of the X.509 certificate. */
    infof(data, "\t certificate version: #%d\n",
          gnutls_x509_crt_get_version(x509_cert));


    size = sizeof(certbuf);
    gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
    infof(data, "\t subject: %s\n", certbuf);

    clock = gnutls_x509_crt_get_activation_time(x509_cert);
    showtime(data, "start date", clock);

    clock = gnutls_x509_crt_get_expiration_time(x509_cert);
    showtime(data, "expire date", clock);

    size = sizeof(certbuf);
    gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
    infof(data, "\t issuer: %s\n", certbuf);

    gnutls_x509_crt_deinit(x509_cert);

    /* compression algorithm (if any) */
    ptr = gnutls_compression_get_name(gnutls_compression_get(session));
    /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
    infof(data, "\t compression: %s\n", ptr);

    /* the name of the cipher used. ie 3DES. */
    ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
    infof(data, "\t cipher: %s\n", ptr);

    /* the MAC algorithms name. ie SHA1 */
    ptr = gnutls_mac_get_name(gnutls_mac_get(session));
    infof(data, "\t MAC: %s\n", ptr);

    if(!ssl_sessionid) {
        /* this session was not previously in the cache, add it now */

        /* get the session ID data size */
        gnutls_session_get_data(session, NULL, &ssl_idsize);
        ssl_sessionid = malloc(ssl_idsize); /* get a buffer for it */

        if(ssl_sessionid) {
            /* extract session ID to the allocated buffer */
            gnutls_session_get_data(session, ssl_sessionid, &ssl_idsize);

            /* store this session id */
            return Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_idsize);
        }
    }

    return CURLE_OK;
}
Ejemplo n.º 24
0
static CURLcode
gtls_connect_step3(struct connectdata *conn,
                   int sockindex)
{
  unsigned int cert_list_size;
  const gnutls_datum *chainp;
  unsigned int verify_status;
  gnutls_x509_crt x509_cert,x509_issuer;
  gnutls_datum issuerp;
  char certbuf[256]; /* big enough? */
  size_t size;
  unsigned int algo;
  unsigned int bits;
  time_t certclock;
  const char *ptr;
  struct SessionHandle *data = conn->data;
  gnutls_session session = conn->ssl[sockindex].session;
  int rc;
  int incache;
  void *ssl_sessionid;
  CURLcode result = CURLE_OK;

  /* This function will return the peer's raw certificate (chain) as sent by
     the peer. These certificates are in raw format (DER encoded for
     X.509). In case of a X.509 then a certificate list may be present. The
     first certificate in the list is the peer's certificate, following the
     issuer's certificate, then the issuer's issuer etc. */

  chainp = gnutls_certificate_get_peers(session, &cert_list_size);
  if(!chainp) {
    if(data->set.ssl.verifypeer ||
       data->set.ssl.verifyhost ||
       data->set.ssl.issuercert) {
#ifdef USE_TLS_SRP
      if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
         && data->set.ssl.username != NULL
         && !data->set.ssl.verifypeer
         && gnutls_cipher_get(session)) {
        /* no peer cert, but auth is ok if we have SRP user and cipher and no
           peer verify */
      }
      else {
#endif
        failf(data, "failed to get server cert");
        return CURLE_PEER_FAILED_VERIFICATION;
#ifdef USE_TLS_SRP
      }
#endif
    }
    infof(data, "\t common name: WARNING couldn't obtain\n");
  }

  if(data->set.ssl.verifypeer) {
    /* This function will try to verify the peer's certificate and return its
       status (trusted, invalid etc.). The value of status should be one or
       more of the gnutls_certificate_status_t enumerated elements bitwise
       or'd. To avoid denial of service attacks some default upper limits
       regarding the certificate key size and chain size are set. To override
       them use gnutls_certificate_set_verify_limits(). */

    rc = gnutls_certificate_verify_peers2(session, &verify_status);
    if(rc < 0) {
      failf(data, "server cert verify failed: %d", rc);
      return CURLE_SSL_CONNECT_ERROR;
    }

    /* verify_status is a bitmask of gnutls_certificate_status bits */
    if(verify_status & GNUTLS_CERT_INVALID) {
      if(data->set.ssl.verifypeer) {
        failf(data, "server certificate verification failed. CAfile: %s "
              "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
              data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
        return CURLE_SSL_CACERT;
      }
      else
        infof(data, "\t server certificate verification FAILED\n");
    }
    else
      infof(data, "\t server certificate verification OK\n");
  }
  else {
    infof(data, "\t server certificate verification SKIPPED\n");
    goto after_server_cert_verification;
  }

  /* initialize an X.509 certificate structure. */
  gnutls_x509_crt_init(&x509_cert);

  /* convert the given DER or PEM encoded Certificate to the native
     gnutls_x509_crt_t format */
  gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);

  if(data->set.ssl.issuercert) {
    gnutls_x509_crt_init(&x509_issuer);
    issuerp = load_file(data->set.ssl.issuercert);
    gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
    rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
    unload_file(issuerp);
    if(rc <= 0) {
      failf(data, "server certificate issuer check failed (IssuerCert: %s)",
            data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
      return CURLE_SSL_ISSUER_ERROR;
    }
    infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
          data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
  }

  size=sizeof(certbuf);
  rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
                                     0, /* the first and only one */
                                     FALSE,
                                     certbuf,
                                     &size);
  if(rc) {
    infof(data, "error fetching CN from cert:%s\n",
          gnutls_strerror(rc));
  }

  /* This function will check if the given certificate's subject matches the
     given hostname. This is a basic implementation of the matching described
     in RFC2818 (HTTPS), which takes into account wildcards, and the subject
     alternative name PKIX extension. Returns non zero on success, and zero on
     failure. */
  rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);

  if(!rc) {
    if(data->set.ssl.verifyhost) {
      failf(data, "SSL: certificate subject name (%s) does not match "
            "target host name '%s'", certbuf, conn->host.dispname);
      gnutls_x509_crt_deinit(x509_cert);
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else
      infof(data, "\t common name: %s (does not match '%s')\n",
            certbuf, conn->host.dispname);
  }
  else
    infof(data, "\t common name: %s (matched)\n", certbuf);

  /* Check for time-based validity */
  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);

  if(certclock == (time_t)-1) {
    failf(data, "server cert expiration date verify failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(certclock < time(NULL)) {
    if(data->set.ssl.verifypeer) {
      failf(data, "server certificate expiration date has passed.");
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else
      infof(data, "\t server certificate expiration date FAILED\n");
  }
  else
    infof(data, "\t server certificate expiration date OK\n");

  certclock = gnutls_x509_crt_get_activation_time(x509_cert);

  if(certclock == (time_t)-1) {
    failf(data, "server cert activation date verify failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  if(certclock > time(NULL)) {
    if(data->set.ssl.verifypeer) {
      failf(data, "server certificate not activated yet.");
      return CURLE_PEER_FAILED_VERIFICATION;
    }
    else
      infof(data, "\t server certificate activation date FAILED\n");
  }
  else
    infof(data, "\t server certificate activation date OK\n");

  /* Show:

  - ciphers used
  - subject
  - start date
  - expire date
  - common name
  - issuer

  */

  /* public key algorithm's parameters */
  algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
  infof(data, "\t certificate public key: %s\n",
        gnutls_pk_algorithm_get_name(algo));

  /* version of the X.509 certificate. */
  infof(data, "\t certificate version: #%d\n",
        gnutls_x509_crt_get_version(x509_cert));


  size = sizeof(certbuf);
  gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
  infof(data, "\t subject: %s\n", certbuf);

  certclock = gnutls_x509_crt_get_activation_time(x509_cert);
  showtime(data, "start date", certclock);

  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
  showtime(data, "expire date", certclock);

  size = sizeof(certbuf);
  gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
  infof(data, "\t issuer: %s\n", certbuf);

  gnutls_x509_crt_deinit(x509_cert);

after_server_cert_verification:

  /* compression algorithm (if any) */
  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
  infof(data, "\t compression: %s\n", ptr);

  /* the name of the cipher used. ie 3DES. */
  ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
  infof(data, "\t cipher: %s\n", ptr);

  /* the MAC algorithms name. ie SHA1 */
  ptr = gnutls_mac_get_name(gnutls_mac_get(session));
  infof(data, "\t MAC: %s\n", ptr);

  conn->ssl[sockindex].state = ssl_connection_complete;
  conn->recv[sockindex] = gtls_recv;
  conn->send[sockindex] = gtls_send;

  {
    /* we always unconditionally get the session id here, as even if we
       already got it from the cache and asked to use it in the connection, it
       might've been rejected and then a new one is in use now and we need to
       detect that. */
    void *connect_sessionid;
    size_t connect_idsize;

    /* get the session ID data size */
    gnutls_session_get_data(session, NULL, &connect_idsize);
    connect_sessionid = malloc(connect_idsize); /* get a buffer for it */

    if(connect_sessionid) {
      /* extract session ID to the allocated buffer */
      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);

      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
      if(incache) {
        /* there was one before in the cache, so instead of risking that the
           previous one was rejected, we just kill that and store the new */
        Curl_ssl_delsessionid(conn, ssl_sessionid);
      }

      /* store this session id */
      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
      if(result) {
        free(connect_sessionid);
        result = CURLE_OUT_OF_MEMORY;
      }
    }
    else
      result = CURLE_OUT_OF_MEMORY;
  }

  return result;
}
Ejemplo n.º 25
0
         bool gtlsGeneric::verifyCertificate(gnutls_session_t & _session)
         {
            bool status = true;

            unsigned int cert_status;
            const gnutls_datum_t *cert_list;
            int cert_list_size, ret;
            gnutls_x509_crt_t cert;

            ret = gnutls_certificate_verify_peers2(_session, &cert_status);

            if (ret < 0)
               {
                  status = false;
                  return status;
               }

            if (cert_status & GNUTLS_CERT_INVALID)
               {
                  //BTG_NOTICE("The certificate is not trusted.");
                  status = false;
               }

            if (cert_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
               {
                  //BTG_NOTICE("The certificate hasn't got a known issuer.");
                  status = false;
               }

            if (cert_status & GNUTLS_CERT_REVOKED)
               {
                  //BTG_NOTICE("The certificate has been revoked.\n");
                  status = false;
               }

            if (gnutls_x509_crt_init(&cert) < 0)
               {
                  //BTG_NOTICE("gnutls_x509_crt_init failed.");
                  status = false;
                  return status;
               }

            cert_list = gnutls_certificate_get_peers(_session, reinterpret_cast<unsigned int*>(&cert_list_size));
            if (cert_list == 0)
               {
                  //BTG_NOTICE("No certificate was found");
                  status = false;
                  return status;
               }

            // Just check the first certificate.
            if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
               {
                  //BTG_NOTICE("error parsing certificate.");
                  status = false;
                  return status;
               }

            time_t now       = time(0);
            time_t cert_exptime = gnutls_x509_crt_get_expiration_time(cert);

            if (cert_exptime == static_cast<time_t>(-1))
               {
                  //BTG_NOTICE("gnutls_x509_crt_get_expiration_time failed.");
                  status = false;
                  return status;
               }

            if (cert_exptime < now)
               {
                  //BTG_NOTICE("The certificate has expired.");
                  status = false;
                  return status;
               }

            time_t cert_act = gnutls_x509_crt_get_activation_time(cert);

            if (cert_exptime == static_cast<time_t>(-1))
               {
                  // BTG_NOTICE("gnutls_x509_crt_get_activation_time failed.");
                  status = false;
                  return status;
               }

            if (cert_act > now)
               {
                  // BTG_NOTICE("The certificate is not yet activated.");
                  status = false;
                  return status;
               }

            gnutls_x509_crt_deinit(cert);

            return status;
         }
Ejemplo n.º 26
0
static int tls_check_one_certificate (const gnutls_datum_t *certdata,
                                      gnutls_certificate_status certstat,
                                      const char* hostname, int idx, int len)
{
  int certerr, savedcert;
  gnutls_x509_crt cert;
  char buf[SHORT_STRING];
  char fpbuf[SHORT_STRING];
  size_t buflen;
  char dn_common_name[SHORT_STRING];
  char dn_email[SHORT_STRING];
  char dn_organization[SHORT_STRING];
  char dn_organizational_unit[SHORT_STRING];
  char dn_locality[SHORT_STRING];
  char dn_province[SHORT_STRING];
  char dn_country[SHORT_STRING];
  time_t t;
  char datestr[30];
  MUTTMENU *menu;
  char helpstr[LONG_STRING];
  char title[STRING];
  FILE *fp;
  gnutls_datum pemdata;
  int i, row, done, ret;

  if (!tls_check_preauth (certdata, certstat, hostname, idx, &certerr,
      &savedcert))
    return 1;

  /* skip signers if insecure algorithm was used */
  if (idx && (certerr & CERTERR_INSECUREALG))
  {
    if (idx == 1)
    {
      mutt_error (_("Warning: Server certificate was signed using an insecure algorithm"));
      mutt_sleep (2);
    }
    return 0;
  }

  /* interactive check from user */
  if (gnutls_x509_crt_init (&cert) < 0)
  {
    mutt_error (_("Error initialising gnutls certificate data"));
    mutt_sleep (2);
    return 0;
  }

  if (gnutls_x509_crt_import (cert, certdata, GNUTLS_X509_FMT_DER) < 0)
  {
    mutt_error (_("Error processing certificate data"));
    mutt_sleep (2);
    gnutls_x509_crt_deinit (cert);
    return -1;
  }

  menu = mutt_new_menu (-1);
  menu->max = 25;
  menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
  for (i = 0; i < menu->max; i++)
    menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));

  row = 0;
  strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING);
  row++;

  buflen = sizeof (dn_common_name);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
                                     dn_common_name, &buflen) != 0)
    dn_common_name[0] = '\0';
  buflen = sizeof (dn_email);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
                                     dn_email, &buflen) != 0)
    dn_email[0] = '\0';
  buflen = sizeof (dn_organization);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
                                     dn_organization, &buflen) != 0)
    dn_organization[0] = '\0';
  buflen = sizeof (dn_organizational_unit);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
                                     dn_organizational_unit, &buflen) != 0)
    dn_organizational_unit[0] = '\0';
  buflen = sizeof (dn_locality);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
                                     dn_locality, &buflen) != 0)
    dn_locality[0] = '\0';
  buflen = sizeof (dn_province);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
                                     dn_province, &buflen) != 0)
    dn_province[0] = '\0';
  buflen = sizeof (dn_country);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
                                     dn_country, &buflen) != 0)
    dn_country[0] = '\0';

  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name, dn_email);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organization);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organizational_unit);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s",
            dn_locality, dn_province, dn_country);
  row++;

  strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING);
  row++;

  buflen = sizeof (dn_common_name);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
                                            dn_common_name, &buflen) != 0)
    dn_common_name[0] = '\0';
  buflen = sizeof (dn_email);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
                                            dn_email, &buflen) != 0)
    dn_email[0] = '\0';
  buflen = sizeof (dn_organization);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
                                            dn_organization, &buflen) != 0)
    dn_organization[0] = '\0';
  buflen = sizeof (dn_organizational_unit);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
                                            dn_organizational_unit, &buflen) != 0)
    dn_organizational_unit[0] = '\0';
  buflen = sizeof (dn_locality);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
                                            dn_locality, &buflen) != 0)
    dn_locality[0] = '\0';
  buflen = sizeof (dn_province);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
                                            dn_province, &buflen) != 0)
    dn_province[0] = '\0';
  buflen = sizeof (dn_country);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
                                            dn_country, &buflen) != 0)
    dn_country[0] = '\0';

  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name, dn_email);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organization);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organizational_unit);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s",
            dn_locality, dn_province, dn_country);
  row++;

  snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));

  t = gnutls_x509_crt_get_activation_time (cert);
  snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
	    tls_make_date (t, datestr, 30));

  t = gnutls_x509_crt_get_expiration_time (cert);
  snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
	    tls_make_date (t, datestr, 30));

  fpbuf[0] = '\0';
  tls_fingerprint (GNUTLS_DIG_SHA, fpbuf, sizeof (fpbuf), certdata);
  snprintf (menu->dialog[row++], SHORT_STRING, _("SHA1 Fingerprint: %s"), fpbuf);
  fpbuf[0] = '\0';
  tls_fingerprint (GNUTLS_DIG_MD5, fpbuf, sizeof (fpbuf), certdata);
  snprintf (menu->dialog[row++], SHORT_STRING, _("MD5 Fingerprint: %s"), fpbuf);

  if (certerr & CERTERR_NOTYETVALID)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server certificate is not yet valid"), SHORT_STRING);
  }
  if (certerr & CERTERR_EXPIRED)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server certificate has expired"), SHORT_STRING);
  }
  if (certerr & CERTERR_REVOKED)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server certificate has been revoked"), SHORT_STRING);
  }
  if (certerr & CERTERR_HOSTNAME)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server hostname does not match certificate"), SHORT_STRING);
  }
  if (certerr & CERTERR_SIGNERNOTCA)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Signer of server certificate is not a CA"), SHORT_STRING);
  }

  snprintf (title, sizeof (title),
            _("SSL Certificate check (certificate %d of %d in chain)"),
            len - idx, len);
  menu->title = title;
  /* certificates with bad dates, or that are revoked, must be
   accepted manually each and every time */
  if (SslCertFile && !savedcert
        && !(certerr & (CERTERR_EXPIRED | CERTERR_NOTYETVALID
                        | CERTERR_REVOKED)))
  {
    menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
    menu->keys = _("roa");
  }
  else
  {
    menu->prompt = _("(r)eject, accept (o)nce");
    menu->keys = _("ro");
  }

  helpstr[0] = '\0';
  mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  menu->help = helpstr;

  done = 0;
  set_option (OPTUNBUFFEREDINPUT);
  while (!done)
  {
    switch (mutt_menuLoop (menu))
    {
      case -1:			/* abort */
      case OP_MAX + 1:		/* reject */
      case OP_EXIT:
        done = 1;
        break;
      case OP_MAX + 3:		/* accept always */
        done = 0;
        if ((fp = fopen (SslCertFile, "a")))
	{
	  /* save hostname if necessary */
	  if (certerr & CERTERR_HOSTNAME)
	  {
	    fprintf(fp, "#H %s %s\n", hostname, fpbuf);
	    done = 1;
	  }
	  if (certerr & CERTERR_NOTTRUSTED)
	  {
            done = 0;
	    ret = gnutls_pem_base64_encode_alloc ("CERTIFICATE", certdata,
                                                  &pemdata);
	    if (ret == 0)
	    {
	      if (fwrite (pemdata.data, pemdata.size, 1, fp) == 1)
	      {
		done = 1;
	      }
              gnutls_free (pemdata.data);
	    }
	  }
	  safe_fclose (&fp);
	}
	if (!done)
        {
	  mutt_error (_("Warning: Couldn't save certificate"));
	  mutt_sleep (2);
	}
	else
        {
	  mutt_message (_("Certificate saved"));
	  mutt_sleep (0);
	}
        /* fall through */
      case OP_MAX + 2:		/* accept once */
        done = 2;
        break;
    }
  }
  unset_option (OPTUNBUFFEREDINPUT);
  mutt_menuDestroy (&menu);
  gnutls_x509_crt_deinit (cert);

  return (done == 2);
}
Ejemplo n.º 27
0
static int tls_check_preauth (const gnutls_datum_t *certdata,
                              gnutls_certificate_status certstat,
                              const char *hostname, int chainidx, int* certerr,
                              int* savedcert)
{
  gnutls_x509_crt cert;

  *certerr = CERTERR_VALID;
  *savedcert = 0;

  if (gnutls_x509_crt_init (&cert) < 0)
  {
    mutt_error (_("Error initialising gnutls certificate data"));
    mutt_sleep (2);
    return -1;
  }

  if (gnutls_x509_crt_import (cert, certdata, GNUTLS_X509_FMT_DER) < 0)
  {
    mutt_error (_("Error processing certificate data"));
    mutt_sleep (2);
    gnutls_x509_crt_deinit (cert);
    return -1;
  }

  if (option (OPTSSLVERIFYDATES) != M_NO)
  {
    if (gnutls_x509_crt_get_expiration_time (cert) < time(NULL))
      *certerr |= CERTERR_EXPIRED;
    if (gnutls_x509_crt_get_activation_time (cert) > time(NULL))
      *certerr |= CERTERR_NOTYETVALID;
  }

  if (chainidx == 0 && option (OPTSSLVERIFYHOST) != M_NO
      && !gnutls_x509_crt_check_hostname (cert, hostname)
      && !tls_check_stored_hostname (certdata, hostname))
    *certerr |= CERTERR_HOSTNAME;

  /* see whether certificate is in our cache (certificates file) */
  if (tls_compare_certificates (certdata))
  {
    *savedcert = 1;

    if (chainidx == 0 && (certstat & GNUTLS_CERT_INVALID))
    {
      /* doesn't matter - have decided is valid because server
       certificate is in our trusted cache */
      certstat ^= GNUTLS_CERT_INVALID;
    }

    if (chainidx == 0 && (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND))
    {
      /* doesn't matter that we haven't found the signer, since
       certificate is in our trusted cache */
      certstat ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
    }

    if (chainidx <= 1 && (certstat & GNUTLS_CERT_SIGNER_NOT_CA))
    {
      /* Hmm. Not really sure how to handle this, but let's say
       that we don't care if the CA certificate hasn't got the
       correct X.509 basic constraints if server or first signer
       certificate is in our cache. */
      certstat ^= GNUTLS_CERT_SIGNER_NOT_CA;
    }

    if (chainidx == 0 && (certstat & GNUTLS_CERT_INSECURE_ALGORITHM))
    {
      /* doesn't matter that it was signed using an insecure
         algorithm, since certificate is in our trusted cache */
      certstat ^= GNUTLS_CERT_INSECURE_ALGORITHM;
    }
  }

  if (certstat & GNUTLS_CERT_REVOKED)
  {
    *certerr |= CERTERR_REVOKED;
    certstat ^= GNUTLS_CERT_REVOKED;
  }

  if (certstat & GNUTLS_CERT_INVALID)
  {
    *certerr |= CERTERR_NOTTRUSTED;
    certstat ^= GNUTLS_CERT_INVALID;
  }

  if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND)
  {
    /* NB: already cleared if cert in cache */
    *certerr |= CERTERR_NOTTRUSTED;
    certstat ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
  }

  if (certstat & GNUTLS_CERT_SIGNER_NOT_CA)
  {
    /* NB: already cleared if cert in cache */
    *certerr |= CERTERR_SIGNERNOTCA;
    certstat ^= GNUTLS_CERT_SIGNER_NOT_CA;
  }

  if (certstat & GNUTLS_CERT_INSECURE_ALGORITHM)
  {
    /* NB: already cleared if cert in cache */
    *certerr |= CERTERR_INSECUREALG;
    certstat ^= GNUTLS_CERT_INSECURE_ALGORITHM;
  }

  gnutls_x509_crt_deinit (cert);

  /* we've been zeroing the interesting bits in certstat -
   don't return OK if there are any unhandled bits we don't
   understand */
  if (*certerr == CERTERR_VALID && certstat == 0)
    return 0;

  return -1;
}
Ejemplo n.º 28
0
static int tls_connection_verify_peer(struct tls_connection *conn)
{
	unsigned int status, num_certs, i;
	struct os_time now;
	const gnutls_datum_t *certs;
	gnutls_x509_crt_t cert;

	if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
		wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
			   "certificate chain");
		return -1;
	}

	if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
		wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
		return -1;
	}

	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
		wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
			   "known issuer");
		return -1;
	}

	if (status & GNUTLS_CERT_REVOKED) {
		wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
		return -1;
	}

	os_get_time(&now);

	certs = gnutls_certificate_get_peers(conn->session, &num_certs);
	if (certs == NULL) {
		wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
			   "received");
		return -1;
	}

	for (i = 0; i < num_certs; i++) {
		char *buf;
		size_t len;
		if (gnutls_x509_crt_init(&cert) < 0) {
			wpa_printf(MSG_INFO, "TLS: Certificate initialization "
				   "failed");
			return -1;
		}

		if (gnutls_x509_crt_import(cert, &certs[i],
					   GNUTLS_X509_FMT_DER) < 0) {
			wpa_printf(MSG_INFO, "TLS: Could not parse peer "
				   "certificate %d/%d", i + 1, num_certs);
			gnutls_x509_crt_deinit(cert);
			return -1;
		}

		gnutls_x509_crt_get_dn(cert, NULL, &len);
		len++;
		buf = os_malloc(len + 1);
		if (buf) {
			buf[0] = buf[len] = '\0';
			gnutls_x509_crt_get_dn(cert, buf, &len);
		}
		wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
			   i + 1, num_certs, buf);

		if (i == 0) {
			/* TODO: validate subject_match and altsubject_match */
		}

		os_free(buf);

		if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
		    gnutls_x509_crt_get_activation_time(cert) > now.sec) {
			wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
				   "not valid at this time",
				   i + 1, num_certs);
			gnutls_x509_crt_deinit(cert);
			return -1;
		}

		gnutls_x509_crt_deinit(cert);
	}

	return 0;
}
Ejemplo n.º 29
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);
	}
Ejemplo n.º 30
0
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;
}