Esempio n. 1
0
STACK_OF(X509) *TS_CONF_load_certs(const char *file)
{
    BIO *certs = NULL;
    STACK_OF(X509) *othercerts = NULL;
    STACK_OF(X509_INFO) *allcerts = NULL;
    int i;

    if ((certs = BIO_new_file(file, "r")) == NULL)
        goto end;
    if ((othercerts = sk_X509_new_null()) == NULL)
        goto end;

    allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL);
    for (i = 0; i < sk_X509_INFO_num(allcerts); i++) {
        X509_INFO *xi = sk_X509_INFO_value(allcerts, i);
        if (xi->x509) {
            sk_X509_push(othercerts, xi->x509);
            xi->x509 = NULL;
        }
    }
 end:
    if (othercerts == NULL)
        TSerr(TS_F_TS_CONF_LOAD_CERTS, TS_R_CANNOT_LOAD_CERT);
    sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
    BIO_free(certs);
    return othercerts;
}
Esempio n. 2
0
STACK_OF(X509) *TS_CONF_load_certs(const char *file)
	{
	BIO *certs = NULL;
	STACK_OF(X509) *othercerts = NULL;
	STACK_OF(X509_INFO) *allcerts = NULL;
	int i;

	if (!(certs = BIO_new_file(file, "r"))) goto end;

	if (!(othercerts = sk_X509_new_null())) goto end;
	allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL);
	for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
		{
		X509_INFO *xi = sk_X509_INFO_value(allcerts, i);
		if (xi->x509)
			{
			sk_X509_push(othercerts, xi->x509);
			xi->x509 = NULL;
			}
		}
end:
	if (othercerts == NULL)
		fprintf(stderr, "unable to load certificates: %s\n", file);
	sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
	BIO_free(certs);
	return othercerts;
	}
Esempio n. 3
0
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
    STACK_OF(X509_INFO) *inf;
    X509_INFO *itmp;
    BIO *in;
    int i, count = 0;
    if (type != X509_FILETYPE_PEM)
        return X509_load_cert_file(ctx, file, type);
    in = BIO_new_file(file, "r");
    if (!in) {
        X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
        return 0;
    }
    inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
    BIO_free(in);
    if (!inf) {
        X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
        return 0;
    }
    for (i = 0; i < sk_X509_INFO_num(inf); i++) {
        itmp = sk_X509_INFO_value(inf, i);
        if (itmp->x509) {
            X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
            count++;
        }
        if (itmp->crl) {
            X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
            count++;
        }
    }
    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    return count;
}
Esempio n. 4
0
static int handle_certificate(const char *filename, const char *fullpath)
{
	STACK_OF(X509_INFO) *inf;
	X509_INFO *x;
	BIO *b;
	const char *ext;
	unsigned char digest[EVP_MAX_MD_SIZE];
	X509_NAME *name = NULL;
	int i, type, ret = -1;

	ext = strrchr(filename, '.');
	if (ext == NULL) return 0;
	for (i = 0; i < countof(file_extensions); i++) {
		if (strcasecmp(file_extensions[i], ext+1) == 0)
			break;
	}
	if (i >= countof(file_extensions)) return -1;

	b = BIO_new_file(fullpath, "r");
	if (!b) return -1;
	inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
	BIO_free(b);
	if (!inf) return -1;

	if (sk_X509_INFO_num(inf) == 1) {
		x = sk_X509_INFO_value(inf, 0);
		if (x->x509) {
			type = TYPE_CERT;
			name = X509_get_subject_name(x->x509);
			X509_digest(x->x509, evpmd, digest, NULL);
		} else if (x->crl) {
			type = TYPE_CRL;
			name = X509_CRL_get_issuer(x->crl);
			X509_CRL_digest(x->crl, evpmd, digest, NULL);
		}
		if (name && do_hash_new)
			add_entry(type, X509_NAME_hash(name), filename, digest, 1, ~0);
		if (name && do_hash_old)
			add_entry(type, X509_NAME_hash_old(name), filename, digest, 1, ~0);
	} else {
		fprintf(stderr,
			"WARNING: %s does not contain exactly one certificate or CRL: skipping\n",
			filename);
	}

	sk_X509_INFO_pop_free(inf, X509_INFO_free);

	return ret;
}
Esempio n. 5
0
/**
 * Parses X.509 PEM formatted certificates from file. The file can contain multiple
 * certificates. You can just use 'cat' command in linux to add multiple PEM formatted
 * X.509 certificates to one file (e.g. <code>cat cert1.pem cert2.pem > certs.pem</code>).
 * NB! This struct must be freed using sk_X509_free() function from OpenSSL or
 * with X509Stack_scope struct.
 *
 * @param path PEM formatted X.509 certificates file path.
 * @return returns stack of parsed X.509 certificates.
 * @throws IOException throws exception if the file does not contain X.509
 *         PEM formatted certificate(s).
 */
STACK_OF(X509)* digidoc::X509Cert::loadX509Stack(const std::string& path) throw(IOException)
{
    // Create an empty X.509 stack.
    STACK_OF(X509)* stack = sk_X509_new_null();
    if(stack == NULL)
    {
        THROW_IOEXCEPTION("Failed to create X.509 certificate stack.");
    }

    // Initialize OpenSSL file.
    BIO* file = BIO_new(BIO_s_file()); BIO_scope fileScope(&file);
    if(file == NULL)
    {
        THROW_IOEXCEPTION("Failed to open X.509 certificates file '%s': %s",
                path.c_str(), ERR_reason_error_string(ERR_get_error()));
    }

    // Open file, which can contain multiple X.509 certificates.
    if(BIO_read_filename(file, path.c_str()) <= 0)
    {
        THROW_IOEXCEPTION("Failed to open X.509 certificates file '%s': %s",
                path.c_str(), ERR_reason_error_string(ERR_get_error()));
    }

    // Read certificates info from the file.
    STACK_OF(X509_INFO)* certsInfo = PEM_X509_INFO_read_bio(file, NULL, NULL, NULL);
    if(certsInfo == NULL)
    {
        THROW_IOEXCEPTION("Failed to read X.509 certificates from file '%s': %s",
                path.c_str(), ERR_reason_error_string(ERR_get_error()));
    }

    // Put all found certificates to the stack.
    for(int i = 0; i < sk_X509_INFO_num(certsInfo); i++)
    {
        X509_INFO* xi = sk_X509_INFO_value(certsInfo, i);
        if(xi->x509 != NULL)
        {
            sk_X509_push(stack, xi->x509);
            xi->x509 = NULL;
        }
    }

    // Release resources.
    sk_X509_INFO_pop_free(certsInfo, X509_INFO_free);

    return stack;
}
Esempio n. 6
0
static STACK_OF(X509) *
read_fullchain(const char *file, int *count)
{
	int i;
	BIO *bio;
	STACK_OF(X509_INFO) *xis = NULL;
	X509_INFO *xi;
	STACK_OF(X509) *rv = NULL;

	*count = 0;

	if ((bio = BIO_new_file(file, "r")) == NULL) {
		warn("Unable to read a certificate from %s", file);
		return NULL;
	}
	if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) {
		warnx("Unable to read PEM format from %s", file);
		return NULL;
	}
	BIO_free(bio);

	if (sk_X509_INFO_num(xis) <= 0) {
		warnx("No certificates in file %s", file);
		goto end;
	}
	if ((rv = sk_X509_new_null()) == NULL) {
		warnx("malloc failed");
		goto end;
	}

	for (i = 0; i < sk_X509_INFO_num(xis); i++) {
		xi = sk_X509_INFO_value(xis, i);
		if (xi->x509 == NULL)
		    continue;
		if (!sk_X509_push(rv, xi->x509)) {
			warnx("unable to build x509 chain");
			sk_X509_pop_free(rv, X509_free);
			rv = NULL;
			goto end;
		}
		xi->x509 = NULL;
		(*count)++;
	}
end:
	sk_X509_INFO_pop_free(xis, X509_INFO_free);
	return rv;
}
Esempio n. 7
0
/*
 * This function is used to load an X509_STORE using raw
 * data from a buffer.  The data is expected to be PEM
 * encoded.
 *
 * Returns the number of certs added to the store
 */
static int ossl_init_cert_store_from_raw (X509_STORE *store,
                                           unsigned char *raw, int size)
{
    STACK_OF(X509_INFO) * sk = NULL;
    X509_INFO *xi;
    BIO *in;
    int cert_cnt = 0;

    in = BIO_new_mem_buf(raw, size);
    if (in == NULL) {
        EST_LOG_ERR("Unable to open the raw CA cert buffer");
        return 0;
    }

    /* This loads from a file, a stack of x509/crl/pkey sets */
    sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
    if (sk == NULL) {
        EST_LOG_ERR("Unable to read PEM encoded certs from BIO");
        BIO_free(in);
        return 0;
    }
    BIO_free(in);

    /* scan over it and pull out the CRL's */
    while (sk_X509_INFO_num(sk)) {
        xi = sk_X509_INFO_shift(sk);
        if (xi->x509 != NULL) {
            EST_LOG_INFO("Adding cert to store (%s)", xi->x509->name);
            X509_STORE_add_cert(store, xi->x509);
	    cert_cnt++;
        }
        if (xi->crl != NULL) {
            EST_LOG_INFO("Adding CRL to store");
            X509_STORE_add_crl(store, xi->crl);
        }
        X509_INFO_free(xi);
    }

    if (sk != NULL) {
        sk_X509_INFO_pop_free(sk, X509_INFO_free);
    }
    return (cert_cnt);
}
Esempio n. 8
0
static int hash_file(int dirfd, const char *filename)
{
	STACK_OF(X509_INFO) *inf;
	X509_INFO *x;
	BIO *b;
	int i, count = 0;
	unsigned char digest[EVP_MAX_MD_SIZE];

	b = BIO_openat(dirfd, filename);
	if (!b)
		return -1;

	inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
	BIO_free(b);
	if (!inf)
		return -1;

	for(i = 0; i < sk_X509_INFO_num(inf); i++) {
		x = sk_X509_INFO_value(inf, i);
		if (x->x509) {
			X509_digest(x->x509, evpmd, digest, NULL);
			link_file(dirfd, filename, TYPE_CERT,
				  X509_subject_name_hash(x->x509), digest);
			count++;
		}
		if (x->crl) {
			X509_CRL_digest(x->crl, evpmd, digest, NULL);
			link_file(dirfd, filename, TYPE_CRL,
				  X509_NAME_hash(X509_CRL_get_issuer(x->crl)),
				  digest);
			count++;
		}
	}
	sk_X509_INFO_pop_free(inf, X509_INFO_free);

	if (count == 0) {
		fprintf(stderr,
			"WARNING: %s does not contain a certificate or CRL: skipping\n",
			filename);
	}

	return count;
}
Esempio n. 9
0
/* load a stack of x509 certificates */
STACK_OF(X509)*
ocsp_load_certs(const char *file)
{
	BIO			*bio = NULL;
	STACK_OF(X509)		*certs = NULL;
	STACK_OF(X509_INFO)	*xis = NULL;
	X509_INFO		*xi;
	int			 i;

	if ((bio = BIO_new_file(file, "r")) == NULL) {
		log_warn("%s: BIO_new_file failed for %s",
		    __func__, file);
		return (NULL);
	}
	if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) {
		ca_sslerror(__func__);
		goto done;
	}
	if ((certs = sk_X509_new_null()) == NULL) {
		log_debug("%s: sk_X509_new_null failed for %s", __func__, file);
		goto done;
	}
	for (i = 0; i < sk_X509_INFO_num(xis); i++) {
		xi = sk_X509_INFO_value(xis, i);
		if (xi->x509) {
			if (!sk_X509_push(certs, xi->x509))
				goto done;
			xi->x509 = NULL;
		}
	}

 done:
	if (bio)
		BIO_free(bio);
	if (xis)
		sk_X509_INFO_pop_free(xis, X509_INFO_free);
	if (certs && sk_X509_num(certs) <= 0) {
		sk_X509_pop_free(certs, X509_free);
		certs = NULL;
	}
	return (certs);
}
Esempio n. 10
0
int
ssl_by_mem_ctrl(X509_LOOKUP *lu, int cmd, const char *buf,
    long type, char **ret)
{
	STACK_OF(X509_INFO)	*inf;
	const struct iovec	*iov;
	X509_INFO		*itmp;
	BIO			*in = NULL;
	int			 i, count = 0;

	iov = (const struct iovec *)buf;

	if (type != X509_FILETYPE_PEM)
		goto done;

	if ((in = BIO_new_mem_buf(iov->iov_base, iov->iov_len)) == NULL)
		goto done;

	if ((inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL)
		goto done;

	for (i = 0; i < sk_X509_INFO_num(inf); i++) {
		itmp = sk_X509_INFO_value(inf, i);
		if (itmp->x509) {
			X509_STORE_add_cert(lu->store_ctx, itmp->x509);
			count++;
		}
		if (itmp->crl) {
			X509_STORE_add_crl(lu->store_ctx, itmp->crl);
			count++;
		}
	}
	sk_X509_INFO_pop_free(inf, X509_INFO_free);

 done:
	if (!count)
		X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB);

	if (in != NULL)
		BIO_free(in);
	return (count);
}
Esempio n. 11
0
static int X509_load_cert_crl_mem(X509_LOOKUP *ctx, const char *mem)
{
  STACK_OF(X509_INFO) *inf;
  X509_INFO *itmp;
  BIO *in;
  int i, count = 0;

  in = BIO_new(BIO_s_mem());
  if (!in) {
    printk("X509_load_cert_crl_mem: cannot allocate BIO\n");
    return 0;
  }

  BIO_write(in, mem, strlen(mem));

  inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
  BIO_free(in);

  if (!inf) {
    printk("X509_load_cert_crl_mem: cannot read X509_INFO\n");
    return 0;
  }

  for (i = 0; i < sk_X509_INFO_num(inf); i++) {
    itmp = sk_X509_INFO_value(inf, i);
    if (itmp->x509) {
      X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
      count++;
    }
    else if (itmp->crl) {
      X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
      count++;
    }
  }

  sk_X509_INFO_pop_free(inf, X509_INFO_free);

  return count;
}
Esempio n. 12
0
int SSL_CTX_load_verify_mem(SSL_CTX *ctx, void *data, int data_len)
{
	STACK_OF(X509_INFO) *stack = NULL;
	X509_INFO *info;
	int nstack, i, ret = 0, got = 0;
	BIO *bio;

	/* Read from memory */
	bio = BIO_new_mem_buf(data, data_len);
	if (!bio)
		goto failed;

	/* Parse X509_INFO records */
	stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
	if (!stack)
		goto failed;

	/* Loop over stack, add certs and revocation records to store */
	nstack = sk_X509_INFO_num(stack);
	for (i = 0; i < nstack; i++) {
		info = sk_X509_INFO_value(stack, i);
		if (info->x509 && !X509_STORE_add_cert(ctx->cert_store, info->x509))
			goto failed;
		if (info->crl && !X509_STORE_add_crl(ctx->cert_store, info->crl))
			goto failed;
		if (info->x509 || info->crl)
			got = 1;
	}
	ret = got;
failed:
	if (bio)
		BIO_free(bio);
	if (stack)
		sk_X509_INFO_pop_free(stack, X509_INFO_free);
	if (!ret)
		X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
	return ret;
}
Esempio n. 13
0
STACK_OF(X509)* bdoc::X509Cert::loadX509Stack(const std::string& path)
{
	STACK_OF(X509)* stack = sk_X509_new_null();
	if (stack == NULL) {
		THROW_STACK_EXCEPTION("Failed to create X.509 certificate stack.");
	}

	BIO* file = BIO_new(BIO_s_file());
	BIO_scope fileScope(&file);
	if (file == NULL) {
		THROW_STACK_EXCEPTION("Failed to open X.509 certificates file '%s': %s",
				path.c_str(), ERR_reason_error_string(ERR_get_error()));
	}

	if (BIO_read_filename(file, path.c_str()) <= 0) {
		THROW_STACK_EXCEPTION("Failed to open X.509 certificates file '%s': %s",
				path.c_str(), ERR_reason_error_string(ERR_get_error()));
	}

	STACK_OF(X509_INFO)* certsInfo = PEM_X509_INFO_read_bio(file, NULL, NULL, NULL);
	if (certsInfo == NULL) {
		THROW_STACK_EXCEPTION("Failed to read X.509 certificates from file '%s': %s",
				path.c_str(), ERR_reason_error_string(ERR_get_error()));
	}

	for (int i = 0; i < sk_X509_INFO_num(certsInfo); i++) {
		X509_INFO* xi = sk_X509_INFO_value(certsInfo, i);
		if (xi->x509 != NULL) {
			sk_X509_push(stack, xi->x509);
			xi->x509 = NULL;
		}
	}

	sk_X509_INFO_pop_free(certsInfo, X509_INFO_free);

	return stack;
}
Esempio n. 14
0
int openconnect_open_https(struct openconnect_info *vpninfo)
{
	method_const SSL_METHOD *ssl3_method;
	SSL *https_ssl;
	BIO *https_bio;
	int ssl_sock;
	int err;

	if (vpninfo->https_ssl)
		return 0;

	if (vpninfo->peer_cert) {
		X509_free(vpninfo->peer_cert);
		vpninfo->peer_cert = NULL;
	}

	ssl_sock = connect_https_socket(vpninfo);
	if (ssl_sock < 0)
		return ssl_sock;

	ssl3_method = TLSv1_client_method();
	if (!vpninfo->https_ctx) {
		vpninfo->https_ctx = SSL_CTX_new(ssl3_method);

		/* Some servers (or their firewalls) really don't like seeing
		   extensions. */
#ifdef SSL_OP_NO_TICKET
		SSL_CTX_set_options(vpninfo->https_ctx, SSL_OP_NO_TICKET);
#endif

		if (vpninfo->cert) {
			err = load_certificate(vpninfo);
			if (err) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Loading certificate failed. Aborting.\n"));
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return err;
			}
			check_certificate_expiry(vpninfo);
		}

		/* We just want to do:
		   SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY);
		   ... but it doesn't work with OpenSSL < 0.9.8k because of
		   problems with inheritance (fixed in v1.1.4.6 of
		   crypto/x509/x509_vpm.c) so we have to play silly buggers
		   instead. This trick doesn't work _either_ in < 0.9.7 but
		   I don't know of _any_ workaround which will, and can't
		   be bothered to find out either. */
#if OPENSSL_VERSION_NUMBER >= 0x00908000
		SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
						 ssl_app_verify_callback, NULL);
#endif
		SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);

#ifdef ANDROID_KEYSTORE
		if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) {
			STACK_OF(X509_INFO) *stack;
			X509_STORE *store;
			X509_INFO *info;
			BIO *b = BIO_from_keystore(vpninfo, vpninfo->cafile);

			if (!b) {
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return -EINVAL;
			}

			stack = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
			BIO_free(b);

			if (!stack) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to read certs from CA file '%s'\n"),
					     vpninfo->cafile);
				openconnect_report_ssl_errors(vpninfo);
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return -ENOENT;
			}

			store = SSL_CTX_get_cert_store(vpninfo->https_ctx);

			while ((info = sk_X509_INFO_pop(stack))) {
				if (info->x509)
					X509_STORE_add_cert(store, info->x509);
				if (info->crl)
					X509_STORE_add_crl(store, info->crl);
				X509_INFO_free(info);
			}
			sk_X509_INFO_free(stack);
		} else
#endif
		if (vpninfo->cafile) {
			if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to open CA file '%s'\n"),
					     vpninfo->cafile);
				openconnect_report_ssl_errors(vpninfo);
				SSL_CTX_free(vpninfo->https_ctx);
				vpninfo->https_ctx = NULL;
				close(ssl_sock);
				return -EINVAL;
			}
		}

	}
	https_ssl = SSL_new(vpninfo->https_ctx);
	workaround_openssl_certchain_bug(vpninfo, https_ssl);

	https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
	BIO_set_nbio(https_bio, 1);
	SSL_set_bio(https_ssl, https_bio, https_bio);

	vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
		     vpninfo->hostname);

	while ((err = SSL_connect(https_ssl)) <= 0) {
		fd_set wr_set, rd_set;
		int maxfd = ssl_sock;

		FD_ZERO(&wr_set);
		FD_ZERO(&rd_set);

		err = SSL_get_error(https_ssl, err);
		if (err == SSL_ERROR_WANT_READ)
			FD_SET(ssl_sock, &rd_set);
		else if (err == SSL_ERROR_WANT_WRITE)
			FD_SET(ssl_sock, &wr_set);
		else {
			vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
			openconnect_report_ssl_errors(vpninfo);
			SSL_free(https_ssl);
			close(ssl_sock);
			return -EINVAL;
		}

		cmd_fd_set(vpninfo, &rd_set, &maxfd);
		select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
		if (is_cancel_pending(vpninfo, &rd_set)) {
			vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
			SSL_free(https_ssl);
			close(ssl_sock);
			return -EINVAL;
		}
	}

	if (verify_peer(vpninfo, https_ssl)) {
		SSL_free(https_ssl);
		close(ssl_sock);
		return -EINVAL;
	}

	vpninfo->ssl_fd = ssl_sock;
	vpninfo->https_ssl = https_ssl;

	/* Stash this now, because it might not be available later if the
	   server has disconnected. */
	vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);

	vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
		     vpninfo->hostname);

	return 0;
}
Esempio n. 15
0
int
tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify)
{
	size_t ca_len = ctx->config->ca_len;
	char *ca_mem = ctx->config->ca_mem;
	char *crl_mem = ctx->config->crl_mem;
	size_t crl_len = ctx->config->crl_len;
	char *ca_free = NULL;
	STACK_OF(X509_INFO) *xis = NULL;
	X509_STORE *store;
	X509_INFO *xi;
	BIO *bio = NULL;
	int rv = -1;
	int i;

	SSL_CTX_set_verify(ssl_ctx, verify, NULL);
	SSL_CTX_set_cert_verify_callback(ssl_ctx, tls_ssl_cert_verify_cb, ctx);

	if (ctx->config->verify_depth >= 0)
		SSL_CTX_set_verify_depth(ssl_ctx, ctx->config->verify_depth);

	if (ctx->config->verify_cert == 0)
		goto done;

	/* If no CA has been specified, attempt to load the default. */
	if (ctx->config->ca_mem == NULL && ctx->config->ca_path == NULL) {
		if (tls_config_load_file(&ctx->error, "CA", _PATH_SSL_CA_FILE,
		    &ca_mem, &ca_len) != 0)
			goto err;
		ca_free = ca_mem;
	}

	if (ca_mem != NULL) {
		if (ca_len > INT_MAX) {
			tls_set_errorx(ctx, "ca too long");
			goto err;
		}
		if (SSL_CTX_load_verify_mem(ssl_ctx, ca_mem, ca_len) != 1) {
			tls_set_errorx(ctx, "ssl verify memory setup failure");
			goto err;
		}
	} else if (SSL_CTX_load_verify_locations(ssl_ctx, NULL,
	    ctx->config->ca_path) != 1) {
		tls_set_errorx(ctx, "ssl verify locations failure");
		goto err;
	}

	if (crl_mem != NULL) {
		if (crl_len > INT_MAX) {
			tls_set_errorx(ctx, "crl too long");
			goto err;
		}
		if ((bio = BIO_new_mem_buf(crl_mem, crl_len)) == NULL) {
			tls_set_errorx(ctx, "failed to create buffer");
			goto err;
		}
		if ((xis = PEM_X509_INFO_read_bio(bio, NULL, tls_password_cb,
		    NULL)) == NULL) {
			tls_set_errorx(ctx, "failed to parse crl");
			goto err;
		}
		store = SSL_CTX_get_cert_store(ssl_ctx);
		for (i = 0; i < sk_X509_INFO_num(xis); i++) {
			xi = sk_X509_INFO_value(xis, i);
			if (xi->crl == NULL)
				continue;
			if (!X509_STORE_add_crl(store, xi->crl)) {
				tls_set_error(ctx, "failed to add crl");
				goto err;
			}
			xi->crl = NULL;
		}
		X509_VERIFY_PARAM_set_flags(store->param,
		    X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
	}

 done:
	rv = 0;

 err:
	sk_X509_INFO_pop_free(xis, X509_INFO_free);
	BIO_free(bio);
	free(ca_free);

	return (rv);
}
Esempio n. 16
0
void
tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
    const char *ca_file_inline,
    const char *ca_path, bool tls_server
    )
{
  STACK_OF(X509_INFO) *info_stack = NULL;
  STACK_OF(X509_NAME) *cert_names = NULL;
  X509_LOOKUP *lookup = NULL;
  X509_STORE *store = NULL;
  X509_NAME *xn = NULL;
  BIO *in = NULL;
  int i, added = 0;

  ASSERT(NULL != ctx);

  store = SSL_CTX_get_cert_store(ctx->ctx);
  if (!store)
    msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)");

  /* Try to add certificates and CRLs from ca_file */
  if (ca_file)
    {
      if (!strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline)
        in = BIO_new_mem_buf ((char *)ca_file_inline, -1);
      else
        in = BIO_new_file (ca_file, "r");

      if (in)
        info_stack = PEM_X509_INFO_read_bio (in, NULL, NULL, NULL);

      if (info_stack)
        {
          for (i = 0; i < sk_X509_INFO_num (info_stack); i++)
            {
              X509_INFO *info = sk_X509_INFO_value (info_stack, i);
              if (info->crl)
                  X509_STORE_add_crl (store, info->crl);

              if (info->x509)
                {
                  X509_STORE_add_cert (store, info->x509);
                  added++;

                  if (!tls_server)
                    continue;

                  /* Use names of CAs as a client CA list */
                  if (cert_names == NULL)
                    {
                      cert_names = sk_X509_NAME_new (sk_x509_name_cmp);
                      if (!cert_names)
                        continue;
                    }

                  xn = X509_get_subject_name (info->x509);
                  if (!xn)
                    continue;

                  /* Don't add duplicate CA names */
                  if (sk_X509_NAME_find (cert_names, xn) == -1)
                    {
                      xn = X509_NAME_dup (xn);
                      if (!xn)
                        continue;
                      sk_X509_NAME_push (cert_names, xn);
                    }
                }
            }
          sk_X509_INFO_pop_free (info_stack, X509_INFO_free);
        }

      if (tls_server)
        SSL_CTX_set_client_CA_list (ctx->ctx, cert_names);

      if (!added || (tls_server && sk_X509_NAME_num (cert_names) != added))
        msg (M_SSLERR, "Cannot load CA certificate file %s", np(ca_file));
      if (in)
        BIO_free (in);
    }

  /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
  if (ca_path)
    {
      lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir ());
      if (lookup && X509_LOOKUP_add_dir (lookup, ca_path, X509_FILETYPE_PEM))
        msg(M_WARN, "WARNING: experimental option --capath %s", ca_path);
      else
        msg(M_SSLERR, "Cannot add lookup at --capath %s", ca_path);
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
      X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
#else
      msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath");
#endif
    }
}