Пример #1
0
X509 *
ca_by_subjectpubkey(X509_STORE *ctx, uint8_t *sig, size_t siglen)
{
	STACK_OF(X509_OBJECT)	*h;
	X509_OBJECT		*xo;
	X509			*ca;
	int			 i;
	unsigned int		 len;
	uint8_t			 md[EVP_MAX_MD_SIZE];

	h = ctx->objs;

	for (i = 0; i < sk_X509_OBJECT_num(h); i++) {
		xo = sk_X509_OBJECT_value(h, i);
		if (xo->type != X509_LU_X509)
			continue;

		ca = xo->data.x509;
		len = sizeof(md);
		ca_subjectpubkey_digest(ca, md, &len);

		if (len == siglen && memcmp(md, sig, len) == 0)
			return (ca);
	}

	return (NULL);
}
Пример #2
0
X509 *
ca_by_issuer(X509_STORE *ctx, X509_NAME *subject, struct iked_static_id *id)
{
	STACK_OF(X509_OBJECT)	*h;
	X509_OBJECT		*xo;
	X509			*cert;
	int			 i;
	X509_NAME		*issuer;

	if (subject == NULL)
		return (NULL);

	h = ctx->objs;
	for (i = 0; i < sk_X509_OBJECT_num(h); i++) {
		xo = sk_X509_OBJECT_value(h, i);
		if (xo->type != X509_LU_X509)
			continue;

		cert = xo->data.x509;
		if ((issuer = X509_get_issuer_name(cert)) == NULL)
			continue;
		else if (X509_NAME_cmp(subject, issuer) == 0) {
			if (ca_x509_subjectaltname_cmp(cert, id) != 0)
				continue;
			return (cert);
		}
	}

	return (NULL);
}
Пример #3
0
int
ca_reload(struct iked *env)
{
	struct ca_store		*store = env->sc_priv;
	uint8_t			 md[EVP_MAX_MD_SIZE];
	char			 file[PATH_MAX];
	struct iovec		 iov[2];
	struct dirent		*entry;
	STACK_OF(X509_OBJECT)	*h;
	X509_OBJECT		*xo;
	X509			*x509;
	DIR			*dir;
	int			 i, len, iovcnt = 0;

	/*
	 * Load CAs
	 */
	if ((dir = opendir(IKED_CA_DIR)) == NULL)
		return (-1);

	while ((entry = readdir(dir)) != NULL) {
		if ((entry->d_type != DT_REG) &&
		    (entry->d_type != DT_LNK))
			continue;

		if (snprintf(file, sizeof(file), "%s%s",
		    IKED_CA_DIR, entry->d_name) == -1)
			continue;

		if (!X509_load_cert_file(store->ca_calookup, file,
		    X509_FILETYPE_PEM)) {
			log_warn("%s: failed to load ca file %s", __func__,
			    entry->d_name);
			ca_sslerror(__func__);
			continue;
		}
		log_debug("%s: loaded ca file %s", __func__, entry->d_name);
	}
	closedir(dir);

	/*
	 * Load CRLs for the CAs
	 */
	if ((dir = opendir(IKED_CRL_DIR)) == NULL)
		return (-1);

	while ((entry = readdir(dir)) != NULL) {
		if ((entry->d_type != DT_REG) &&
		    (entry->d_type != DT_LNK))
			continue;

		if (snprintf(file, sizeof(file), "%s%s",
		    IKED_CRL_DIR, entry->d_name) == -1)
			continue;

		if (!X509_load_crl_file(store->ca_calookup, file,
		    X509_FILETYPE_PEM)) {
			log_warn("%s: failed to load crl file %s", __func__,
			    entry->d_name);
			ca_sslerror(__func__);
			continue;
		}

		/* Only enable CRL checks if we actually loaded a CRL */
		X509_STORE_set_flags(store->ca_cas, X509_V_FLAG_CRL_CHECK);

		log_debug("%s: loaded crl file %s", __func__, entry->d_name);
	}
	closedir(dir);

	/*
	 * Save CAs signatures for the IKEv2 CERTREQ
	 */
	ibuf_release(env->sc_certreq);
	if ((env->sc_certreq = ibuf_new(NULL, 0)) == NULL)
		return (-1);

	h = store->ca_cas->objs;
	for (i = 0; i < sk_X509_OBJECT_num(h); i++) {
		xo = sk_X509_OBJECT_value(h, i);
		if (xo->type != X509_LU_X509)
			continue;

		x509 = xo->data.x509;
		len = sizeof(md);
		ca_subjectpubkey_digest(x509, md, &len);
		log_debug("%s: %s", __func__, x509->name);

		if (ibuf_add(env->sc_certreq, md, len) != 0) {
			ibuf_release(env->sc_certreq);
			return (-1);
		}
	}

	if (ibuf_length(env->sc_certreq)) {
		env->sc_certreqtype = IKEV2_CERT_X509_CERT;
		iov[0].iov_base = &env->sc_certreqtype;
		iov[0].iov_len = sizeof(env->sc_certreqtype);
		iovcnt++;
		iov[1].iov_base = ibuf_data(env->sc_certreq);
		iov[1].iov_len = ibuf_length(env->sc_certreq);
		iovcnt++;

		log_debug("%s: loaded %zu ca certificate%s", __func__,
		    ibuf_length(env->sc_certreq) / SHA_DIGEST_LENGTH,
		    ibuf_length(env->sc_certreq) == SHA_DIGEST_LENGTH ?
		    "" : "s");

		(void)proc_composev(&env->sc_ps, PROC_IKEV2, IMSG_CERTREQ,
		    iov, iovcnt);
	}

	/*
	 * Load certificates
	 */
	if ((dir = opendir(IKED_CERT_DIR)) == NULL)
		return (-1);

	while ((entry = readdir(dir)) != NULL) {
		if ((entry->d_type != DT_REG) &&
		    (entry->d_type != DT_LNK))
			continue;

		if (snprintf(file, sizeof(file), "%s%s",
		    IKED_CERT_DIR, entry->d_name) == -1)
			continue;

		if (!X509_load_cert_file(store->ca_certlookup, file,
		    X509_FILETYPE_PEM)) {
			log_warn("%s: failed to load cert file %s", __func__,
			    entry->d_name);
			ca_sslerror(__func__);
			continue;
		}
		log_debug("%s: loaded cert file %s", __func__, entry->d_name);
	}
	closedir(dir);

	h = store->ca_certs->objs;
	for (i = 0; i < sk_X509_OBJECT_num(h); i++) {
		xo = sk_X509_OBJECT_value(h, i);
		if (xo->type != X509_LU_X509)
			continue;

		x509 = xo->data.x509;

		(void)ca_validate_cert(env, NULL, x509, 0);
	}

	if (!env->sc_certreqtype)
		env->sc_certreqtype = store->ca_pubkey.id_type;

	log_debug("%s: local cert type %s", __func__,
	    print_map(env->sc_certreqtype, ikev2_cert_map));

	iov[0].iov_base = &env->sc_certreqtype;
	iov[0].iov_len = sizeof(env->sc_certreqtype);
	if (iovcnt == 0)
		iovcnt++;
	(void)proc_composev(&env->sc_ps, PROC_IKEV2, IMSG_CERTREQ, iov, iovcnt);

	return (0);
}
Пример #4
0
static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
	     X509_OBJECT *ret)
	{
	BY_DIR *ctx;
	union	{
		struct	{
			X509 st_x509;
			X509_CINF st_x509_cinf;
			} x509;
		struct	{
			X509_CRL st_crl;
			X509_CRL_INFO st_crl_info;
			} crl;
		} data;
	int ok=0;
	int i,j,k;
	unsigned long h;
	BUF_MEM *b=NULL;
	struct stat st;
	X509_OBJECT stmp,*tmp;
	const char *postfix="";

	if (name == NULL) return(0);

	stmp.type=type;
	if (type == X509_LU_X509)
		{
		data.x509.st_x509.cert_info= &data.x509.st_x509_cinf;
		data.x509.st_x509_cinf.subject=name;
		stmp.data.x509= &data.x509.st_x509;
		postfix="";
		}
	else if (type == X509_LU_CRL)
		{
		data.crl.st_crl.crl= &data.crl.st_crl_info;
		data.crl.st_crl_info.issuer=name;
		stmp.data.crl= &data.crl.st_crl;
		postfix="r";
		}
	else
		{
		X509err(X509_F_GET_CERT_BY_SUBJECT,X509_R_WRONG_LOOKUP_TYPE);
		goto finish;
		}

	if ((b=BUF_MEM_new()) == NULL)
		{
		X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_BUF_LIB);
		goto finish;
		}
	
	ctx=(BY_DIR *)xl->method_data;

	h=X509_NAME_hash(name);
	for (i=0; i<ctx->num_dirs; i++)
		{
		j=strlen(ctx->dirs[i])+1+8+6+1+1;
		if (!BUF_MEM_grow(b,j))
			{
			X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_MALLOC_FAILURE);
			goto finish;
			}
		k=0;
		for (;;)
			{
			char c = '/';
#ifdef OPENSSL_SYS_VMS
			c = ctx->dirs[i][strlen(ctx->dirs[i])-1];
			if (c != ':' && c != '>' && c != ']')
				{
				/* If no separator is present, we assume the
				   directory specifier is a logical name, and
				   add a colon.  We really should use better
				   VMS routines for merging things like this,
				   but this will do for now...
				   -- Richard Levitte */
				c = ':';
				}
			else
				{
				c = '\0';
				}
#endif
			if (c == '\0')
				{
				/* This is special.  When c == '\0', no
				   directory separator should be added. */
				BIO_snprintf(b->data,b->max,
					"%s%08lx.%s%d",ctx->dirs[i],h,
					postfix,k);
				}
			else
				{
				BIO_snprintf(b->data,b->max,
					"%s%c%08lx.%s%d",ctx->dirs[i],c,h,
					postfix,k);
				}
			k++;
			if (stat(b->data,&st) < 0)
				break;
			/* found one. */
			if (type == X509_LU_X509)
				{
				if ((X509_load_cert_file(xl,b->data,
					ctx->dirs_type[i])) == 0)
					break;
				}
			else if (type == X509_LU_CRL)
				{
				if ((X509_load_crl_file(xl,b->data,
					ctx->dirs_type[i])) == 0)
					break;
				}
			/* else case will caught higher up */
			}

		/* we have added it to the cache so now pull
		 * it out again */
		CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
		j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp);
		if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j);
		else tmp = NULL;
		CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);

		if (tmp != NULL)
			{
			ok=1;
			ret->type=tmp->type;
			memcpy(&ret->data,&tmp->data,sizeof(ret->data));
			/* If we were going to up the reference count,
			 * we would need to do it on a perl 'type'
			 * basis */
	/*		CRYPTO_add(&tmp->data.x509->references,1,
				CRYPTO_LOCK_X509);*/
			goto finish;
			}
		}
finish:
	if (b != NULL) BUF_MEM_free(b);
	return(ok);
	}
Пример #5
0
static int
ldaplookup_by_subject(
	X509_LOOKUP *ctx,
	int          type,
	X509_NAME   *name,
	X509_OBJECT *ret
) {
	int count = 0;
	ldaphost *lh;
	const char *attrs[2];
	char *filter = NULL;


	if (ctx == NULL) return(0);
	if (name == NULL) return(0);

	lh = (ldaphost*) ctx->method_data;
	if (lh == NULL) return(0);

	switch(type) {
	case X509_LU_X509: {
		attrs[0] = ATTR_CACERT;
		} break;
	case X509_LU_CRL: {
		attrs[0] = ATTR_CACRL;
		} break;
	default: {
		X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_WRONG_LOOKUP_TYPE);
		goto done;
		}
	}
	attrs[1] = NULL;

	filter = ldaplookup_filter(name, attrs[0]);
	if (filter == NULL) {
		X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_GET_FILTER);
		goto done;
	}
#ifdef TRACE_BY_LDAP
fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: filter=%s\n", filter);
#endif

	for (; lh != NULL; lh = lh->next) {
		LDAPMessage *res = NULL;
		int result;

#ifdef TRACE_BY_LDAP
{
int version = -1;

ldap_get_option(lh->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject:"
" bind to \"%s://%s:%d\""
" using ldap v%d protocol\n"
, lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port
, version
);
}
#endif

		result = ldaplookup_bind_s(lh->ld);
		if (result != LDAP_SUCCESS) {
			X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_BIND);
			{
				char	buf[1024];
				snprintf(buf, sizeof(buf),
					" url=\"%s://%s:%d\""
					" ldaperror=0x%x(%.256s)"
					, lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port
					, result, ldap_err2string(result)
				);
				ERR_add_error_data(1, buf);
			}
			continue;
		}

		result = ldaplookup_search_s(lh->ld, lh->ldapurl->lud_dn,
				LDAP_SCOPE_SUBTREE, filter, (char**)attrs, 0, &res);
		if (result != LDAP_SUCCESS) {
			X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_SEARCH_FAIL);
			ldap_msgfree(res);
			continue;
		}

		result = ldaplookup_result2store(type, name, lh->ld, res, ctx->store_ctx);
		if (result > 0) count += result;

		ldap_msgfree(res);

		/*do not call ldap_unbind_s*/
	}

#ifdef TRACE_BY_LDAP
fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: count=%d\n", count);
#endif
	if (count > 0) {
		/*
		 * we have added at least one to the cache so now pull one out again
		 */
		union {
			struct {
				X509_CINF st_x509_cinf;
				X509 st_x509;
			} x509;
			struct {
				X509_CRL_INFO st_crl_info;
				X509_CRL st_crl;
			} crl;
		} data;

		X509_OBJECT stmp, *tmp;
		int k;

		memset(&data, 0, sizeof(data));
		stmp.type = type;
		switch(type) {
		case X509_LU_X509: {
			data.x509.st_x509_cinf.subject = name;
			data.x509.st_x509.cert_info = &data.x509.st_x509_cinf;
			stmp.data.x509 = &data.x509.st_x509;
			} break;
		case X509_LU_CRL: {
			data.crl.st_crl_info.issuer = name;
			data.crl.st_crl.crl = &data.crl.st_crl_info;
			stmp.data.crl = &data.crl.st_crl;
			} break;
		default:
			count = 0;
			goto done;
		}

		CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
		k = sk_X509_OBJECT_find(ctx->store_ctx->objs, &stmp);
		if (k >= 0)
			tmp = sk_X509_OBJECT_value(ctx->store_ctx->objs, k);
		else
			tmp = NULL;
		CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
#ifdef TRACE_BY_LDAP
fprintf(stderr, "TRACE_BY_LDAP ldaplookup_by_subject: k=%d, tmp=%p\n", k, (void*)tmp);
#endif

		if (tmp == NULL) {
			count = 0;
			goto done;
		}

		ret->type = tmp->type;
		memcpy(&ret->data, &tmp->data, sizeof(ret->data));
	}

done:
	if (filter != NULL) OPENSSL_free(filter);
	return(count > 0);
}