Esempio n. 1
0
/*
 * Checks if CA a is trusted by CA b
 */
bool trusted_ca(chunk_t a, chunk_t b, int *pathlen)
{
	bool match = FALSE;
	char abuf[ASN1_BUF_LEN], bbuf[ASN1_BUF_LEN];

	dntoa(abuf, ASN1_BUF_LEN, a);
	dntoa(bbuf, ASN1_BUF_LEN, b);

	DBG(DBG_X509 | DBG_CONTROLMORE,
	    DBG_log("  trusted_ca called with a=%s b=%s",
		    abuf, bbuf));

	/* no CA b specified -> any CA a is accepted */
	if (b.ptr == NULL) {
		*pathlen = (a.ptr == NULL) ? 0 : MAX_CA_PATH_LEN;
		return TRUE;
	}

	/* no CA a specified -> trust cannot be established */
	if (a.ptr == NULL) {
		*pathlen = MAX_CA_PATH_LEN;
		return FALSE;
	}

	*pathlen = 0;

	/* CA a equals CA b -> we have a match */
	if (same_dn(a, b))
		return TRUE;

	/* CA a might be a subordinate CA of b */
	lock_authcert_list("trusted_ca");

	while ((*pathlen)++ < MAX_CA_PATH_LEN) {
		x509cert_t *cacert = get_authcert(a, empty_chunk, empty_chunk,
						  AUTH_CA);

		/* cacert not found or self-signed root cacert-> exit */
		if (cacert == NULL || same_dn(cacert->issuer, a))
			break;

		/* does the issuer of CA a match CA b? */
		match = same_dn(cacert->issuer, b);

		/* we have a match and exit the loop */
		if (match)
			break;

		/* go one level up in the CA chain */
		a = cacert->issuer;
	}

	unlock_authcert_list("trusted_ca");

	DBG(DBG_X509 | DBG_CONTROLMORE,
	    DBG_log("  trusted_ca returning with %s",
		    match ? "match" : "failed"));

	return match;
}
Esempio n. 2
0
/*
 * add an authority certificate to the chained list
 */
void add_authcert(x509cert_t *cert, u_char auth_flags)
{
	x509cert_t *old_cert;

	/* set authority flags */
	cert->authority_flags |= auth_flags;

	lock_authcert_list("add_authcert");

	old_cert = get_authcert(cert->subject, cert->serialNumber,
				cert->subjectKeyID, auth_flags);

	if (old_cert != NULL) {
		if (same_x509cert(cert, old_cert)) {
			/*
			 * cert is already present, just add additional
			 * authority flags
			 */
			old_cert->authority_flags |= cert->authority_flags;
			DBG(DBG_X509 | DBG_PARSING,
				DBG_log("  authcert is already present and identical");
				);
			unlock_authcert_list("add_authcert");

			free_x509cert(cert);
			return;
		} else {
Esempio n. 3
0
/*
 * add an authority certificate to the chained list
 */
void
add_authcert(x509cert_t *cert, u_char auth_flags)
{
    x509cert_t *old_cert;

    /* set authority flags */
    cert->authority_flags |= auth_flags;

    lock_authcert_list("add_authcert");

    old_cert = get_authcert(cert->subject, cert->serialNumber
	, cert->subjectKeyID, auth_flags);

    if (old_cert != NULL)
    {
	if (same_x509cert(cert, old_cert))
	{
	    /* cert is already present, just add additional authority flags */
	    old_cert->authority_flags |= cert->authority_flags;
	    DBG(DBG_X509 | DBG_PARSING ,
		DBG_log("  authcert is already present and identical")
	    )
	    unlock_authcert_list("add_authcert");
	    
	    free_x509cert(cert);
	    return;
	}
	else
	{
	    /* cert is already present but will be replaced by new cert */
	    free_first_authcert();
	    DBG(DBG_X509 | DBG_PARSING ,
		DBG_log("  existing authcert deleted")
	    )
	}
    }
    
    /* add new authcert to chained list */
    cert->next = x509authcerts;
    x509authcerts = cert;
    share_x509cert(cert);  /* set count to one */
    DBG(DBG_X509 | DBG_PARSING,
	DBG_log("  authcert inserted")
    )
    unlock_authcert_list("add_authcert");
}
Esempio n. 4
0
/* build an ocsp location from certificate information
 * without unsharing its contents
 */
static bool
build_ocsp_location(const x509cert_t *cert, ocsp_location_t *location)
{
    static u_char digest[SHA1_DIGEST_SIZE];  /* temporary storage */

    location->uri = (cert->accessLocation.ptr != NULL)
	? cert->accessLocation : ocsp_default_uri;

    /* abort if no ocsp location uri is defined */
    if (location->uri.ptr == NULL)
 	return FALSE;

    setchunk(location->authNameID, digest, SHA1_DIGEST_SIZE);
    compute_digest(cert->issuer, OID_SHA1, &location->authNameID);

    location->next = NULL;
    location->issuer = cert->issuer;
    location->authKeyID = cert->authKeyID;
    location->authKeySerialNumber = cert->authKeySerialNumber;
    
    if (cert->authKeyID.ptr == NULL) 
    {
	x509cert_t *authcert = get_authcert(cert->issuer
		, cert->authKeySerialNumber, cert->authKeyID, AUTH_CA);

	if (authcert != NULL)
	{
	    location->authKeyID = authcert->subjectKeyID;
	    location->authKeySerialNumber = authcert->serialNumber;
	}
    }

    location->nonce = empty_chunk;
    location->certinfo = NULL;

    return TRUE;
}
Esempio n. 5
0
File: x509.c Progetto: mkj/libreswan
/*
 * verify if a cert hasn't been revoked by a crl
 */
static bool verify_by_crl(/*const*/ x509cert_t *cert, bool strict,
				    realtime_t *until)
{
	x509crl_t *crl;
	char ibuf[ASN1_BUF_LEN], cbuf[ASN1_BUF_LEN];

	lock_crl_list("verify_by_crl");
	crl = get_x509crl(cert->issuer, cert->authKeySerialNumber,
			  cert->authKeyID);

	dntoa(ibuf, ASN1_BUF_LEN, cert->issuer);

	if (crl == NULL) {
		unlock_crl_list("verify_by_crl");
		libreswan_log("no crl from issuer \"%s\" found (strict=%s)",
			      ibuf,
			      strict ? "yes" : "no");

#if defined(LIBCURL) || defined(LDAP_VER)
		if (cert->crlDistributionPoints != NULL) {
			add_crl_fetch_request(cert->issuer,
					      cert->crlDistributionPoints);
			wake_fetch_thread("verify_by_crl");
		}
#endif
		if (strict)
			return FALSE;
	} else {
		x509cert_t *issuer_cert;
		bool valid;

		DBG(DBG_X509,
		    DBG_log("issuer crl \"%s\" found", ibuf));

#if defined(LIBCURL) || defined(LDAP_VER)
		add_distribution_points(cert->crlDistributionPoints,
					&crl->distributionPoints);
#endif

		lock_authcert_list("verify_by_crl");

		issuer_cert = get_authcert(crl->issuer,
					   crl->authKeySerialNumber,
					   crl->authKeyID, AUTH_CA);
		dntoa(cbuf, ASN1_BUF_LEN, crl->issuer);
		valid = check_signature(crl->tbsCertList, crl->signature,
					crl->algorithm, issuer_cert);

		unlock_authcert_list("verify_by_crl");

		if (valid) {
			bool revoked_crl, expired_crl;

			DBG(DBG_X509,
			    DBG_log("valid crl signature on \"%s\"", cbuf));

			/* with strict crl policy the public key must have the same
			 * lifetime as the crl
			 */
			if (strict && realbefore(crl->nextUpdate, *until))
				*until = crl->nextUpdate;

			/* has the certificate been revoked? */
			revoked_crl = x509_check_revocation(crl,
							    cert->serialNumber);

			/* is the crl still valid? */
			expired_crl = realbefore(crl->nextUpdate, realnow());

			unlock_crl_list("verify_by_crl");

			if (expired_crl) {
				char tbuf[REALTIMETOA_BUF];

				libreswan_log(
					"crl update for \"%s\" is overdue since %s",
					cbuf,
					realtimetoa(crl->nextUpdate, TRUE,
						tbuf, sizeof(tbuf)));

#if defined(LIBCURL) || defined(LDAP_VER)
				/* try to fetch a crl update */
				if (cert->crlDistributionPoints != NULL) {
					add_crl_fetch_request(cert->issuer,
							      cert->crlDistributionPoints);
					wake_fetch_thread("verify_by_crl");
				}
#endif
			} else {
				DBG(DBG_X509,
				    DBG_log("crl is \"%s\" valid", cbuf));
			}

			if (revoked_crl || (strict && expired_crl)) {
				/* remove any cached public keys */
				remove_x509_public_key(cert);
				return FALSE;
			}
		} else {
			unlock_crl_list("verify_by_crl");
			libreswan_log("invalid crl signature on \"%s\"", cbuf);
			if (strict)
				return FALSE;
		}
	}
	return TRUE;
}
Esempio n. 6
0
File: x509.c Progetto: mkj/libreswan
/*
 * Insert X.509 CRL into chained list
 */
bool insert_crl(chunk_t blob, chunk_t crl_uri)
{
	x509crl_t *crl = alloc_thing(x509crl_t, "x509crl");

	*crl = empty_x509crl;

	if (parse_x509crl(blob, 0, crl)) {
		x509cert_t *issuer_cert;
		x509crl_t *oldcrl;
		bool valid_sig;
		generalName_t *gn;

		/* add distribution point */
		gn = alloc_thing(generalName_t, "generalName");
		gn->kind = GN_URI;
		gn->name = crl_uri;
		gn->next = crl->distributionPoints;
		crl->distributionPoints = gn;

		lock_authcert_list("insert_crl");
		/* get the issuer cacert */
		issuer_cert = get_authcert(crl->issuer,
					   crl->authKeySerialNumber,
					   crl->authKeyID, AUTH_CA);

		if (issuer_cert == NULL) {
			chunk_t *n = &crl->distributionPoints->name;

			loglog(RC_LOG_SERIOUS,
			       "CRL rejected: crl issuer cacert not found for %.*s",
			       (int)n->len, (char *)n->ptr);

			free_crl(crl);
			unlock_authcert_list("insert_crl");
			return FALSE;
		}
		DBG(DBG_X509,
		    DBG_log("crl issuer cacert found"));

		/* check the issuer's signature of the crl */
		valid_sig = check_signature(crl->tbsCertList, crl->signature,
					    crl->algorithm, issuer_cert);
		unlock_authcert_list("insert_crl");

		if (!valid_sig) {
			free_crl(crl);
			return FALSE;
		}
		DBG(DBG_X509,
		    DBG_log("valid crl signature"));

		lock_crl_list("insert_crl");
		oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber,
				     crl->authKeyID);

		if (oldcrl != NULL) {
			if (realbefore(oldcrl->thisUpdate, crl->thisUpdate)) {
				/* old CRL is older than new CRL: replace */
#if defined(LIBCURL) || defined(LDAP_VER)
				/* keep any known CRL distribution points */
				add_distribution_points(
					oldcrl->distributionPoints,
					&crl->distributionPoints);
#endif

				/* now delete the old CRL */
				free_first_crl();
				DBG(DBG_X509,
				    DBG_log("thisUpdate is newer - existing crl deleted"));
			} else {
				/* old CRL is not older than new CRL: keep old one */
				unlock_crl_list("insert_crls");
				DBG(DBG_X509,
				    DBG_log("thisUpdate is not newer - existing crl not replaced"));
				free_crl(crl);
				/*
				 * is the fetched crl valid?
				 * now + 2 * crl_check_interval < oldcrl->nextUpdate
				 */
				return realbefore(realtimesum(realnow(), deltatimescale(2, 1, crl_check_interval)), oldcrl->nextUpdate);
			}
		}

		/* insert new CRL */
		crl->next = x509crls;
		x509crls = crl;

		unlock_crl_list("insert_crl");

		/*
		 * is the new crl valid?
		 * now + 2 * crl_check_interval < crl->nextUpdate
		 */
		return realbefore(realtimesum(realnow(), deltatimescale(2, 1, crl_check_interval)), crl->nextUpdate);
	} else {
		loglog(RC_LOG_SERIOUS, "  error in X.509 crl %s",
		       (char *)crl_uri.ptr);
		free_crl(crl);
		return FALSE;
	}
}
Esempio n. 7
0
/*
 * Build an ocsp location from certificate information
 * without unsharing its contents
 */
static bool build_ocsp_location(const cert_t *cert, ocsp_location_t *location)
{
	certificate_t *certificate = cert->cert;
	identification_t *issuer = certificate->get_issuer(certificate);
	x509_t *x509 = (x509_t*)certificate;
	chunk_t issuer_dn = issuer->get_encoding(issuer);
	chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
	hasher_t *hasher;
	static u_char digest[HASH_SIZE_SHA1];  /* temporary storage */

	enumerator_t *enumerator = x509->create_ocsp_uri_enumerator(x509);

	location->uri = NULL;
	while (enumerator->enumerate(enumerator, &location->uri))
	{
		break;
	}
	enumerator->destroy(enumerator);

	if (location->uri == NULL)
	{
		ca_info_t *ca = get_ca_info(issuer, authKeyID);
		if (ca && ca->ocspuri)
		{
			location->uri = ca->ocspuri;
		}
		else
		{   /* abort if no ocsp location uri is defined */
			return FALSE;
		}
	}

	/* compute authNameID from as SHA-1 hash of issuer DN */
	location->authNameID = chunk_create(digest, HASH_SIZE_SHA1);
	hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
	if (hasher == NULL)
	{
		return FALSE;
	}
	hasher->get_hash(hasher, issuer_dn, digest);
	hasher->destroy(hasher);

	location->next = NULL;
	location->issuer = issuer;
	location->authKeyID = authKeyID;

	if (authKeyID.ptr == NULL)
	{
		cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);

		if (authcert)
		{
			x509_t *x509 = (x509_t*)authcert->cert;

			location->authKeyID = x509->get_subjectKeyIdentifier(x509);
		}
	}

	location->nonce = chunk_empty;
	location->certinfo = NULL;

	return TRUE;
}
Esempio n. 8
0
File: x509.c Progetto: OPSF/uClinux
/*
 * Insert X.509 CRL into chained list
 */
bool
insert_crl(chunk_t blob, chunk_t crl_uri)
{
    x509crl_t *crl = alloc_thing(x509crl_t, "x509crl");

    *crl = empty_x509crl;

    if (parse_x509crl(blob, 0, crl))
    {
	x509cert_t *issuer_cert;
	x509crl_t *oldcrl;
	bool valid_sig;
	generalName_t *gn;

	/* add distribution point */
	gn = alloc_thing(generalName_t, "generalName");
	gn->kind = GN_URI;
	gn->name = crl_uri;
	gn->next = crl->distributionPoints;
	crl->distributionPoints = gn;

	lock_authcert_list("insert_crl");
	/* get the issuer cacert */
	issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
	    crl->authKeyID, AUTH_CA);

	if (issuer_cert == NULL)
	{
	    char distpoint[PATH_MAX];

	    distpoint[0] = '\0';
	    strncat(distpoint, (char *)crl->distributionPoints->name.ptr,
		    (crl->distributionPoints->name.len < PATH_MAX ?
		     crl->distributionPoints->name.len : PATH_MAX));
	    
	    openswan_log("crl issuer cacert not found for (%s)",
			 distpoint);;

	    free_crl(crl);
	    unlock_authcert_list("insert_crl");
	    return FALSE;
	}
	DBG(DBG_X509,
	    DBG_log("crl issuer cacert found")
	)

	/* check the issuer's signature of the crl */
	valid_sig = check_signature(crl->tbsCertList, crl->signature
			, crl->algorithm, issuer_cert);
	unlock_authcert_list("insert_crl");

	if (!valid_sig)
	{
	    free_crl(crl);
	    return FALSE;
	}
	DBG(DBG_X509,
	    DBG_log("valid crl signature")
	)

	lock_crl_list("insert_crl");
	oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
	    , crl->authKeyID);

	if (oldcrl != NULL)
	{
	    if (crl->thisUpdate > oldcrl->thisUpdate)
	    {
#ifdef HAVE_THREADS
		/* keep any known CRL distribution points */
		add_distribution_points(oldcrl->distributionPoints
		    , &crl->distributionPoints);
#endif

		/* now delete the old CRL */
		free_first_crl();
		DBG(DBG_X509,
		    DBG_log("thisUpdate is newer - existing crl deleted")
		)
	    }
	    else
	    {
Esempio n. 9
0
/* establish trust into a candidate authcert by going up the trust chain.
 * validity and revocation status are not checked.
 */
bool
trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chain)
{
    int pathlen;

    lock_authcert_list("trust_authcert_candidate");

    for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
    {
       const x509cert_t *authcert = NULL;

       DBG(DBG_CONTROL,
           char buf[ASN1_BUF_LEN];
           dntoa(buf, ASN1_BUF_LEN, cert->subject);
           DBG_log("subject: '%s'",buf);
           dntoa(buf, ASN1_BUF_LEN, cert->issuer);
           DBG_log("issuer:  '%s'",buf);
           if (cert->authKeyID.ptr != NULL)
           {
               datatot(cert->authKeyID.ptr, cert->authKeyID.len, ':'
                   , buf, ASN1_BUF_LEN);
               DBG_log("authkey:  %s", buf);
           }
	   );

       /* search in alternative chain first */
       authcert = get_alt_cacert(cert->issuer, cert->authKeySerialNumber
           , cert->authKeyID, alt_chain);

       if (authcert != NULL)
       {
           DBG(DBG_CONTROL,
               DBG_log("issuer cacert found in alternative chain")
           )
       }
       else
       {
           /* search in trusted chain */
           authcert = get_authcert(cert->issuer, cert->authKeySerialNumber
               , cert->authKeyID, AUTH_CA);

           if (authcert != NULL)
           {
               DBG(DBG_CONTROL,
                   DBG_log("issuer cacert found")
               )
           }
           else
           {
               plog("issuer cacert not found");
               unlock_authcert_list("trust_authcert_candidate");
               return FALSE;
           }
       }

       if (!check_signature(cert->tbsCertificate, cert->signature,
                            cert->algorithm, authcert))
       {
           plog("invalid certificate signature");
           unlock_authcert_list("trust_authcert_candidate");
           return FALSE;
       }
       DBG(DBG_CONTROL,
           DBG_log("valid certificate signature")
       )

       /* check if cert is a self-signed root ca */
       if (pathlen > 0 && same_dn(cert->issuer, cert->subject))
       {
           DBG(DBG_CONTROL,
               DBG_log("reached self-signed root ca")
           )
           unlock_authcert_list("trust_authcert_candidate");
           return TRUE;
       }

       /* go up one step in the trust chain */
       cert = authcert;
    }