Exemplo n.º 1
0
void __certificate_properties_fill_cert_ext_BasicConstraints (GtkTreeStore *store,
        GtkTreeIter *parent,
        gnutls_x509_crt_t *certificate)
{
    guint critical;
    gint result;
    guint ca;
    gint path_len_constraint;
    gchar *pathlen_as_string = NULL;
    GtkTreeIter l;
    gchar *ca_as_string = NULL;

    result = gnutls_x509_crt_get_basic_constraints(*certificate, &critical, &ca, &path_len_constraint);

    if (result < 0)	{
        fprintf(stderr, "Error: %s\n", gnutls_strerror(result));
        return;
    }

    ca_as_string = ca ? _("TRUE") : _("FALSE");

    pathlen_as_string = g_strdup_printf ("%d", path_len_constraint);

    gtk_tree_store_append(store, &l, parent);
    gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("CA"),
                       CERTIFICATE_PROPERTIES_COL_VALUE, ca_as_string, -1);

    gtk_tree_store_append(store, &l, parent);
    gtk_tree_store_set(store, &l, CERTIFICATE_PROPERTIES_COL_NAME, _("Path Length Constraint"),
                       CERTIFICATE_PROPERTIES_COL_VALUE, pathlen_as_string, -1);

    g_free (pathlen_as_string);
}
Exemplo n.º 2
0
/* Returns true if the provided purpose is in accordance with the certificate.
 */
unsigned _gnutls_check_key_purpose(gnutls_x509_crt_t cert, const char *purpose, unsigned no_any)
{
	char oid[MAX_OID_SIZE];
	size_t oid_size;
	int ret;
	unsigned critical = 0;
	unsigned check_obsolete_oids = 0;
	unsigned i;

	/* The check_obsolete_oids hack is because of certain very old CA certificates
	 * around which instead of having the GNUTLS_KP_TLS_WWW_SERVER have some old
	 * OIDs for that purpose. Assume these OIDs equal GNUTLS_KP_TLS_WWW_SERVER in
	 * CA certs */
	if (strcmp(purpose, GNUTLS_KP_TLS_WWW_SERVER) == 0) {
		unsigned ca_status;
		ret =
		    gnutls_x509_crt_get_basic_constraints(cert, NULL, &ca_status,
							  NULL);
		if (ret < 0)
			ca_status = 0;

		if (ca_status)
			check_obsolete_oids = 1;
	}

	for (i=0;;i++) {
		oid_size = sizeof(oid);
		ret = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid, &oid_size, &critical);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
			if (i==0) {
				/* no key purpose in certificate, assume ANY */
				return 1;
			} else {
				gnutls_assert();
				break;
			}
		} else if (ret < 0) {
			gnutls_assert();
			break;
		}

		if (check_obsolete_oids) {
			if (strcmp(oid, PURPOSE_NSSGC) == 0) {
				return 1;
			} else if (strcmp(oid, PURPOSE_VSGC) == 0) {
				return 1;
			}
		}

		if (strcmp(oid, purpose) == 0 || (no_any == 0 && strcmp(oid, GNUTLS_KP_ANY) == 0)) {
			return 1;
		}
		_gnutls_debug_log("looking for key purpose '%s', but have '%s'\n", purpose, oid);
	}
	return 0;
}
Exemplo n.º 3
0
/*
 * The gnutls_x509_crt_get_basic_constraints function isn't
 * available in GNUTLS 1.0.x branches. This isn't critical
 * though, since gnutls_certificate_verify_peers2 will do
 * pretty much the same check at runtime, so we can just
 * disable this code
 */
static int
qcrypto_tls_creds_check_cert_basic_constraints(QCryptoTLSCredsX509 *creds,
                                               gnutls_x509_crt_t cert,
                                               const char *certFile,
                                               bool isServer,
                                               bool isCA,
                                               Error **errp)
{
    int status;

    status = gnutls_x509_crt_get_basic_constraints(cert, NULL, NULL, NULL);
    trace_qcrypto_tls_creds_x509_check_basic_constraints(
        creds, certFile, status);

    if (status > 0) { /* It is a CA cert */
        if (!isCA) {
            error_setg(errp, isServer ?
                       "The certificate %s basic constraints show a CA, "
                       "but we need one for a server" :
                       "The certificate %s basic constraints show a CA, "
                       "but we need one for a client",
                       certFile);
            return -1;
        }
    } else if (status == 0) { /* It is not a CA cert */
        if (isCA) {
            error_setg(errp,
                       "The certificate %s basic constraints do not "
                       "show a CA",
                       certFile);
            return -1;
        }
    } else if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
        /* Missing basicConstraints */
        if (isCA) {
            error_setg(errp,
                       "The certificate %s is missing basic constraints "
                       "for a CA",
                       certFile);
            return -1;
        }
    } else { /* General error */
        error_setg(errp,
                   "Unable to query certificate %s basic constraints: %s",
                   certFile, gnutls_strerror(status));
        return -1;
    }

    return 0;
}
Exemplo n.º 4
0
/* Checks if the issuer of a certificate is a
 * Certificate Authority, or if the certificate is the same
 * as the issuer (and therefore it doesn't need to be a CA).
 *
 * Returns true or false, if the issuer is a CA,
 * or not.
 */
static unsigned
check_if_ca(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer,
	    unsigned int *max_path, unsigned int flags)
{
	gnutls_datum_t cert_signed_data = { NULL, 0 };
	gnutls_datum_t issuer_signed_data = { NULL, 0 };
	gnutls_datum_t cert_signature = { NULL, 0 };
	gnutls_datum_t issuer_signature = { NULL, 0 };
	int pathlen = -1, ret;
	unsigned result;
	unsigned int ca_status = 0;

	/* Check if the issuer is the same with the
	 * certificate. This is added in order for trusted
	 * certificates to be able to verify themselves.
	 */

	ret =
	    _gnutls_x509_get_signed_data(issuer->cert, &issuer->der, "tbsCertificate",
					 &issuer_signed_data);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	ret =
	    _gnutls_x509_get_signed_data(cert->cert, &cert->der, "tbsCertificate",
					 &cert_signed_data);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	ret =
	    _gnutls_x509_get_signature(issuer->cert, "signature",
				       &issuer_signature);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	ret =
	    _gnutls_x509_get_signature(cert->cert, "signature",
				       &cert_signature);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	/* If the subject certificate is the same as the issuer
	 * return true.
	 */
	if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME))
		if (cert_signed_data.size == issuer_signed_data.size) {
			if ((memcmp
			     (cert_signed_data.data,
			      issuer_signed_data.data,
			      cert_signed_data.size) == 0)
			    && (cert_signature.size ==
				issuer_signature.size)
			    &&
			    (memcmp
			     (cert_signature.data, issuer_signature.data,
			      cert_signature.size) == 0)) {
				result = 1;
				goto cleanup;
			}
		}

	ret =
	    gnutls_x509_crt_get_basic_constraints(issuer, NULL, &ca_status,
						  &pathlen);
	if (ret < 0) {
		ca_status = 0;
		pathlen = -1;
	}

	if (ca_status != 0 && pathlen != -1) {
		if ((unsigned) pathlen < *max_path)
			*max_path = pathlen;
	}

	if (ca_status != 0) {
		result = 1;
		goto cleanup;
	}
	/* Handle V1 CAs that do not have a basicConstraint, but accept
	   these certs only if the appropriate flags are set. */
	else if ((ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) &&
		 ((flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT) ||
		  (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT) &&
		   (gnutls_x509_crt_check_issuer(issuer, issuer) != 0)))) {
		gnutls_assert();
		result = 1;
		goto cleanup;
	} else {
		gnutls_assert();
	}

 fail:
	result = 0;

 cleanup:
	_gnutls_free_datum(&cert_signed_data);
	_gnutls_free_datum(&issuer_signed_data);
	_gnutls_free_datum(&cert_signature);
	_gnutls_free_datum(&issuer_signature);
	return result;
}
Exemplo n.º 5
0
/** Determines whether one certificate has been issued and signed by another
 *
 * @param crt       Certificate to check the signature of
 * @param issuer    Issuer's certificate
 *
 * @return TRUE if crt was signed and issued by issuer, otherwise FALSE
 * @TODO  Modify this function to return a reason for invalidity?
 */
static gboolean
x509_certificate_signed_by(PurpleCertificate * crt,
			   PurpleCertificate * issuer)
{
	gnutls_x509_crt_t crt_dat;
	gnutls_x509_crt_t issuer_dat;
	unsigned int verify; /* used to store result from GnuTLS verifier */
	int ret;
	gchar *crt_id = NULL;
	gchar *issuer_id = NULL;

	g_return_val_if_fail(crt, FALSE);
	g_return_val_if_fail(issuer, FALSE);

	/* Verify that both certs are the correct scheme */
	g_return_val_if_fail(crt->scheme == &x509_gnutls, FALSE);
	g_return_val_if_fail(issuer->scheme == &x509_gnutls, FALSE);

	/* TODO: check for more nullness? */

	crt_dat = X509_GET_GNUTLS_DATA(crt);
	issuer_dat = X509_GET_GNUTLS_DATA(issuer);

	/* Ensure crt issuer matches the name on the issuer cert. */
	ret = gnutls_x509_crt_check_issuer(crt_dat, issuer_dat);
	if (ret <= 0) {

		if (ret < 0) {
			purple_debug_error("gnutls/x509",
					   "GnuTLS error %d while checking certificate issuer match.",
					   ret);
		} else {
			gchar *crt_id, *issuer_id, *crt_issuer_id;
			crt_id = purple_certificate_get_unique_id(crt);
			issuer_id = purple_certificate_get_unique_id(issuer);
			crt_issuer_id =
				purple_certificate_get_issuer_unique_id(crt);
			purple_debug_info("gnutls/x509",
					  "Certificate %s is issued by "
					  "%s, which does not match %s.\n",
					  crt_id ? crt_id : "(null)",
					  crt_issuer_id ? crt_issuer_id : "(null)",
					  issuer_id ? issuer_id : "(null)");
			g_free(crt_id);
			g_free(issuer_id);
			g_free(crt_issuer_id);
		}

		/* The issuer is not correct, or there were errors */
		return FALSE;
	}

	/* Check basic constraints extension (if it exists then the CA flag must
	   be set to true, and it must exist for certs with version 3 or higher. */
	ret = gnutls_x509_crt_get_basic_constraints(issuer_dat, NULL, NULL, NULL);
	if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
		if (gnutls_x509_crt_get_version(issuer_dat) >= 3) {
			/* Reject cert (no basic constraints and cert version is >= 3). */
			gchar *issuer_id = purple_certificate_get_unique_id(issuer);
			purple_debug_info("gnutls/x509", "Rejecting cert because the "
					"basic constraints extension is missing from issuer cert "
					"for %s. The basic constraints extension is required on "
					"all version 3 or higher certs (this cert is version %d).",
					issuer_id ? issuer_id : "(null)",
					gnutls_x509_crt_get_version(issuer_dat));
			g_free(issuer_id);
			return FALSE;
		} else {
			/* Allow cert (no basic constraints and cert version is < 3). */
			purple_debug_info("gnutls/x509", "Basic constraint extension is "
					"missing from issuer cert for %s. Allowing this because "
					"the cert is version %d and the basic constraints "
					"extension is only required for version 3 or higher "
					"certs.", issuer_id ? issuer_id : "(null)",
					gnutls_x509_crt_get_version(issuer_dat));
		}
	} else if (ret <= 0) {
		/* Reject cert (CA flag is false in basic constraints). */
		gchar *issuer_id = purple_certificate_get_unique_id(issuer);
		purple_debug_info("gnutls/x509", "Rejecting cert because the CA flag "
				"is set to false in the basic constraints extension for "
				"issuer cert %s. ret=%d\n",
				issuer_id ? issuer_id : "(null)", ret);
		g_free(issuer_id);
		return FALSE;
	}

	/* Now, check the signature */
	/* The second argument is a ptr to an array of "trusted" issuer certs,
	   but we're only using one trusted one */
	ret = gnutls_x509_crt_verify(crt_dat, &issuer_dat, 1,
				     /* Permit signings by X.509v1 certs
					(Verisign and possibly others have
					root certificates that predate the
					current standard) */
				     GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
				     &verify);

	if (ret != 0) {
		purple_debug_error("gnutls/x509",
				   "Attempted certificate verification caused a GnuTLS error code %d. I will just say the signature is bad, but you should look into this.\n", ret);
		return FALSE;
	}

#ifdef HAVE_GNUTLS_CERT_INSECURE_ALGORITHM
	if (verify & GNUTLS_CERT_INSECURE_ALGORITHM) {
		/*
		 * A certificate in the chain is signed with an insecure
		 * algorithm. Put a warning into the log to make this error
		 * perfectly clear as soon as someone looks at the debug log is
		 * generated.
		 */
		crt_id = purple_certificate_get_unique_id(crt);
		issuer_id = purple_certificate_get_issuer_unique_id(crt);
		purple_debug_warning("gnutls/x509",
				"Insecure hash algorithm used by %s to sign %s\n",
				issuer_id, crt_id);
	}
#endif

	if (verify & GNUTLS_CERT_INVALID) {
		/* Signature didn't check out, but at least
		   there were no errors*/
		if (!crt_id)
			crt_id = purple_certificate_get_unique_id(crt);
		if (!issuer_id)
			issuer_id = purple_certificate_get_issuer_unique_id(crt);
		purple_debug_error("gnutls/x509",
				  "Bad signature from %s on %s\n",
				  issuer_id, crt_id);
		g_free(crt_id);
		g_free(issuer_id);

		return FALSE;
	} /* if (ret, etc.) */

	/* If we got here, the signature is good */
	return TRUE;
}