1e71b7053SJung-uk Kim /*
2*b077aed3SPierre Pronchery * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
374664626SKris Kennaway *
4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
874664626SKris Kennaway */
974664626SKris Kennaway
1074664626SKris Kennaway #include <stdio.h>
1174664626SKris Kennaway #include <time.h>
1274664626SKris Kennaway #include <errno.h>
1374664626SKris Kennaway
14e71b7053SJung-uk Kim #include "internal/cryptlib.h"
1574664626SKris Kennaway #include <openssl/buffer.h>
1674664626SKris Kennaway #include <openssl/x509.h>
1774664626SKris Kennaway #include <openssl/pem.h>
1817f01e99SJung-uk Kim #include "x509_local.h"
1974664626SKris Kennaway
2074664626SKris Kennaway static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
2174664626SKris Kennaway long argl, char **ret);
22*b077aed3SPierre Pronchery static int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc,
23*b077aed3SPierre Pronchery long argl, char **ret, OSSL_LIB_CTX *libctx,
24*b077aed3SPierre Pronchery const char *propq);
25*b077aed3SPierre Pronchery
26*b077aed3SPierre Pronchery
27e71b7053SJung-uk Kim static X509_LOOKUP_METHOD x509_file_lookup = {
2874664626SKris Kennaway "Load file into cache",
29e71b7053SJung-uk Kim NULL, /* new_item */
3074664626SKris Kennaway NULL, /* free */
3174664626SKris Kennaway NULL, /* init */
3274664626SKris Kennaway NULL, /* shutdown */
3374664626SKris Kennaway by_file_ctrl, /* ctrl */
3474664626SKris Kennaway NULL, /* get_by_subject */
3574664626SKris Kennaway NULL, /* get_by_issuer_serial */
3674664626SKris Kennaway NULL, /* get_by_fingerprint */
3774664626SKris Kennaway NULL, /* get_by_alias */
38*b077aed3SPierre Pronchery NULL, /* get_by_subject_ex */
39*b077aed3SPierre Pronchery by_file_ctrl_ex, /* ctrl_ex */
4074664626SKris Kennaway };
4174664626SKris Kennaway
X509_LOOKUP_file(void)4274664626SKris Kennaway X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
4374664626SKris Kennaway {
44e71b7053SJung-uk Kim return &x509_file_lookup;
4574664626SKris Kennaway }
4674664626SKris Kennaway
by_file_ctrl_ex(X509_LOOKUP * ctx,int cmd,const char * argp,long argl,char ** ret,OSSL_LIB_CTX * libctx,const char * propq)47*b077aed3SPierre Pronchery static int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp,
48*b077aed3SPierre Pronchery long argl, char **ret, OSSL_LIB_CTX *libctx,
49*b077aed3SPierre Pronchery const char *propq)
5074664626SKris Kennaway {
51f579bf8eSKris Kennaway int ok = 0;
5247902a71SJung-uk Kim const char *file;
5374664626SKris Kennaway
546f9291ceSJung-uk Kim switch (cmd) {
5574664626SKris Kennaway case X509_L_FILE_LOAD:
566f9291ceSJung-uk Kim if (argl == X509_FILETYPE_DEFAULT) {
57c9cf7b5cSJung-uk Kim file = ossl_safe_getenv(X509_get_default_cert_file_env());
585c87c606SMark Murray if (file)
59*b077aed3SPierre Pronchery ok = (X509_load_cert_crl_file_ex(ctx, file, X509_FILETYPE_PEM,
60*b077aed3SPierre Pronchery libctx, propq) != 0);
615c87c606SMark Murray
625c87c606SMark Murray else
63*b077aed3SPierre Pronchery ok = (X509_load_cert_crl_file_ex(
64*b077aed3SPierre Pronchery ctx, X509_get_default_cert_file(),
65*b077aed3SPierre Pronchery X509_FILETYPE_PEM, libctx, propq) != 0);
665c87c606SMark Murray
676f9291ceSJung-uk Kim if (!ok) {
68*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, X509_R_LOADING_DEFAULTS);
6974664626SKris Kennaway }
706f9291ceSJung-uk Kim } else {
71f579bf8eSKris Kennaway if (argl == X509_FILETYPE_PEM)
72*b077aed3SPierre Pronchery ok = (X509_load_cert_crl_file_ex(ctx, argp, X509_FILETYPE_PEM,
73*b077aed3SPierre Pronchery libctx, propq) != 0);
74f579bf8eSKris Kennaway else
75*b077aed3SPierre Pronchery ok = (X509_load_cert_file_ex(ctx, argp, (int)argl, libctx,
76*b077aed3SPierre Pronchery propq) != 0);
7774664626SKris Kennaway }
7874664626SKris Kennaway break;
7974664626SKris Kennaway }
80e71b7053SJung-uk Kim return ok;
8174664626SKris Kennaway }
8274664626SKris Kennaway
by_file_ctrl(X509_LOOKUP * ctx,int cmd,const char * argp,long argl,char ** ret)83*b077aed3SPierre Pronchery static int by_file_ctrl(X509_LOOKUP *ctx, int cmd,
84*b077aed3SPierre Pronchery const char *argp, long argl, char **ret)
85*b077aed3SPierre Pronchery {
86*b077aed3SPierre Pronchery return by_file_ctrl_ex(ctx, cmd, argp, argl, ret, NULL, NULL);
87*b077aed3SPierre Pronchery }
88*b077aed3SPierre Pronchery
X509_load_cert_file_ex(X509_LOOKUP * ctx,const char * file,int type,OSSL_LIB_CTX * libctx,const char * propq)89*b077aed3SPierre Pronchery int X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type,
90*b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx, const char *propq)
9174664626SKris Kennaway {
9274664626SKris Kennaway int ret = 0;
9374664626SKris Kennaway BIO *in = NULL;
9474664626SKris Kennaway int i, count = 0;
9574664626SKris Kennaway X509 *x = NULL;
9674664626SKris Kennaway
97e71b7053SJung-uk Kim in = BIO_new(BIO_s_file());
9874664626SKris Kennaway
996f9291ceSJung-uk Kim if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
100*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB);
101*b077aed3SPierre Pronchery goto err;
102*b077aed3SPierre Pronchery }
103*b077aed3SPierre Pronchery
104*b077aed3SPierre Pronchery if (type != X509_FILETYPE_PEM && type != X509_FILETYPE_ASN1) {
105*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE);
106*b077aed3SPierre Pronchery goto err;
107*b077aed3SPierre Pronchery }
108*b077aed3SPierre Pronchery x = X509_new_ex(libctx, propq);
109*b077aed3SPierre Pronchery if (x == NULL) {
110*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
11174664626SKris Kennaway goto err;
11274664626SKris Kennaway }
11374664626SKris Kennaway
1146f9291ceSJung-uk Kim if (type == X509_FILETYPE_PEM) {
1156f9291ceSJung-uk Kim for (;;) {
116*b077aed3SPierre Pronchery ERR_set_mark();
117*b077aed3SPierre Pronchery if (PEM_read_bio_X509_AUX(in, &x, NULL, "") == NULL) {
1183b4e3dcbSSimon L. B. Nielsen if ((ERR_GET_REASON(ERR_peek_last_error()) ==
1196f9291ceSJung-uk Kim PEM_R_NO_START_LINE) && (count > 0)) {
120*b077aed3SPierre Pronchery ERR_pop_to_mark();
12174664626SKris Kennaway break;
1226f9291ceSJung-uk Kim } else {
123*b077aed3SPierre Pronchery ERR_clear_last_mark();
12474664626SKris Kennaway goto err;
12574664626SKris Kennaway }
12674664626SKris Kennaway }
127*b077aed3SPierre Pronchery ERR_clear_last_mark();
12874664626SKris Kennaway i = X509_STORE_add_cert(ctx->store_ctx, x);
1296f9291ceSJung-uk Kim if (!i)
1306f9291ceSJung-uk Kim goto err;
13174664626SKris Kennaway count++;
13274664626SKris Kennaway X509_free(x);
13374664626SKris Kennaway x = NULL;
13474664626SKris Kennaway }
13574664626SKris Kennaway ret = count;
1366f9291ceSJung-uk Kim } else if (type == X509_FILETYPE_ASN1) {
137*b077aed3SPierre Pronchery if (d2i_X509_bio(in, &x) == NULL) {
138*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
13974664626SKris Kennaway goto err;
14074664626SKris Kennaway }
14174664626SKris Kennaway i = X509_STORE_add_cert(ctx->store_ctx, x);
1426f9291ceSJung-uk Kim if (!i)
1436f9291ceSJung-uk Kim goto err;
14474664626SKris Kennaway ret = i;
14574664626SKris Kennaway }
146e71b7053SJung-uk Kim if (ret == 0)
147*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND);
14874664626SKris Kennaway err:
1496f9291ceSJung-uk Kim X509_free(x);
1506f9291ceSJung-uk Kim BIO_free(in);
151e71b7053SJung-uk Kim return ret;
15274664626SKris Kennaway }
15374664626SKris Kennaway
X509_load_cert_file(X509_LOOKUP * ctx,const char * file,int type)154*b077aed3SPierre Pronchery int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
155*b077aed3SPierre Pronchery {
156*b077aed3SPierre Pronchery return X509_load_cert_file_ex(ctx, file, type, NULL, NULL);
157*b077aed3SPierre Pronchery }
158*b077aed3SPierre Pronchery
X509_load_crl_file(X509_LOOKUP * ctx,const char * file,int type)15974664626SKris Kennaway int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
16074664626SKris Kennaway {
16174664626SKris Kennaway int ret = 0;
16274664626SKris Kennaway BIO *in = NULL;
16374664626SKris Kennaway int i, count = 0;
16474664626SKris Kennaway X509_CRL *x = NULL;
16574664626SKris Kennaway
166e71b7053SJung-uk Kim in = BIO_new(BIO_s_file());
16774664626SKris Kennaway
1686f9291ceSJung-uk Kim if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
169*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB);
17074664626SKris Kennaway goto err;
17174664626SKris Kennaway }
17274664626SKris Kennaway
1736f9291ceSJung-uk Kim if (type == X509_FILETYPE_PEM) {
1746f9291ceSJung-uk Kim for (;;) {
17547902a71SJung-uk Kim x = PEM_read_bio_X509_CRL(in, NULL, NULL, "");
1766f9291ceSJung-uk Kim if (x == NULL) {
1773b4e3dcbSSimon L. B. Nielsen if ((ERR_GET_REASON(ERR_peek_last_error()) ==
1786f9291ceSJung-uk Kim PEM_R_NO_START_LINE) && (count > 0)) {
17974664626SKris Kennaway ERR_clear_error();
18074664626SKris Kennaway break;
1816f9291ceSJung-uk Kim } else {
182*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB);
18374664626SKris Kennaway goto err;
18474664626SKris Kennaway }
18574664626SKris Kennaway }
18674664626SKris Kennaway i = X509_STORE_add_crl(ctx->store_ctx, x);
1876f9291ceSJung-uk Kim if (!i)
1886f9291ceSJung-uk Kim goto err;
18974664626SKris Kennaway count++;
19074664626SKris Kennaway X509_CRL_free(x);
19174664626SKris Kennaway x = NULL;
19274664626SKris Kennaway }
19374664626SKris Kennaway ret = count;
1946f9291ceSJung-uk Kim } else if (type == X509_FILETYPE_ASN1) {
19574664626SKris Kennaway x = d2i_X509_CRL_bio(in, NULL);
1966f9291ceSJung-uk Kim if (x == NULL) {
197*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB);
19874664626SKris Kennaway goto err;
19974664626SKris Kennaway }
20074664626SKris Kennaway i = X509_STORE_add_crl(ctx->store_ctx, x);
2016f9291ceSJung-uk Kim if (!i)
2026f9291ceSJung-uk Kim goto err;
20374664626SKris Kennaway ret = i;
2046f9291ceSJung-uk Kim } else {
205*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE);
20674664626SKris Kennaway goto err;
20774664626SKris Kennaway }
208e71b7053SJung-uk Kim if (ret == 0)
209*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_FOUND);
21074664626SKris Kennaway err:
2116f9291ceSJung-uk Kim X509_CRL_free(x);
2126f9291ceSJung-uk Kim BIO_free(in);
213e71b7053SJung-uk Kim return ret;
21474664626SKris Kennaway }
21574664626SKris Kennaway
X509_load_cert_crl_file_ex(X509_LOOKUP * ctx,const char * file,int type,OSSL_LIB_CTX * libctx,const char * propq)216*b077aed3SPierre Pronchery int X509_load_cert_crl_file_ex(X509_LOOKUP *ctx, const char *file, int type,
217*b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx, const char *propq)
218f579bf8eSKris Kennaway {
219f579bf8eSKris Kennaway STACK_OF(X509_INFO) *inf;
220f579bf8eSKris Kennaway X509_INFO *itmp;
221f579bf8eSKris Kennaway BIO *in;
222f579bf8eSKris Kennaway int i, count = 0;
223e71b7053SJung-uk Kim
224f579bf8eSKris Kennaway if (type != X509_FILETYPE_PEM)
225*b077aed3SPierre Pronchery return X509_load_cert_file_ex(ctx, file, type, libctx, propq);
226f579bf8eSKris Kennaway in = BIO_new_file(file, "r");
227f579bf8eSKris Kennaway if (!in) {
228*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB);
229f579bf8eSKris Kennaway return 0;
230f579bf8eSKris Kennaway }
231*b077aed3SPierre Pronchery inf = PEM_X509_INFO_read_bio_ex(in, NULL, NULL, "", libctx, propq);
232f579bf8eSKris Kennaway BIO_free(in);
233f579bf8eSKris Kennaway if (!inf) {
234*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB);
235f579bf8eSKris Kennaway return 0;
236f579bf8eSKris Kennaway }
237f579bf8eSKris Kennaway for (i = 0; i < sk_X509_INFO_num(inf); i++) {
238f579bf8eSKris Kennaway itmp = sk_X509_INFO_value(inf, i);
239f579bf8eSKris Kennaway if (itmp->x509) {
240e71b7053SJung-uk Kim if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509))
241e71b7053SJung-uk Kim goto err;
242f579bf8eSKris Kennaway count++;
24350ef0093SJacques Vidrine }
24450ef0093SJacques Vidrine if (itmp->crl) {
245e71b7053SJung-uk Kim if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl))
246e71b7053SJung-uk Kim goto err;
247f579bf8eSKris Kennaway count++;
248f579bf8eSKris Kennaway }
249f579bf8eSKris Kennaway }
250e71b7053SJung-uk Kim if (count == 0)
251*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
252e71b7053SJung-uk Kim err:
253f579bf8eSKris Kennaway sk_X509_INFO_pop_free(inf, X509_INFO_free);
254f579bf8eSKris Kennaway return count;
255f579bf8eSKris Kennaway }
256*b077aed3SPierre Pronchery
X509_load_cert_crl_file(X509_LOOKUP * ctx,const char * file,int type)257*b077aed3SPierre Pronchery int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
258*b077aed3SPierre Pronchery {
259*b077aed3SPierre Pronchery return X509_load_cert_crl_file_ex(ctx, file, type, NULL, NULL);
260*b077aed3SPierre Pronchery }
261*b077aed3SPierre Pronchery
262