xref: /openbsd-src/lib/libcrypto/x509/by_file.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /* $OpenBSD: by_file.c,v 1.15 2014/07/11 08:44:49 jsing Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <errno.h>
60 #include <stdio.h>
61 #include <time.h>
62 #include <unistd.h>
63 
64 #include <openssl/buffer.h>
65 #include <openssl/err.h>
66 #include <openssl/pem.h>
67 #include <openssl/lhash.h>
68 #include <openssl/x509.h>
69 
70 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
71     long argl, char **ret);
72 
73 X509_LOOKUP_METHOD x509_file_lookup = {
74 	"Load file into cache",
75 	NULL,		/* new */
76 	NULL,		/* free */
77 	NULL, 		/* init */
78 	NULL,		/* shutdown */
79 	by_file_ctrl,	/* ctrl */
80 	NULL,		/* get_by_subject */
81 	NULL,		/* get_by_issuer_serial */
82 	NULL,		/* get_by_fingerprint */
83 	NULL,		/* get_by_alias */
84 };
85 
86 X509_LOOKUP_METHOD *
87 X509_LOOKUP_file(void)
88 {
89 	return (&x509_file_lookup);
90 }
91 
92 static int
93 by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
94     char **ret)
95 {
96 	int ok = 0;
97 	char *file = NULL;
98 
99 	switch (cmd) {
100 	case X509_L_FILE_LOAD:
101 		if (argl == X509_FILETYPE_DEFAULT) {
102 			if (issetugid() == 0)
103 				file = getenv(X509_get_default_cert_file_env());
104 			if (file)
105 				ok = (X509_load_cert_crl_file(ctx, file,
106 				    X509_FILETYPE_PEM) != 0);
107 			else
108 				ok = (X509_load_cert_crl_file(ctx,
109 				    X509_get_default_cert_file(),
110 				    X509_FILETYPE_PEM) != 0);
111 
112 			if (!ok) {
113 				X509err(X509_F_BY_FILE_CTRL,
114 				    X509_R_LOADING_DEFAULTS);
115 			}
116 		} else {
117 			if (argl == X509_FILETYPE_PEM)
118 				ok = (X509_load_cert_crl_file(ctx, argp,
119 				    X509_FILETYPE_PEM) != 0);
120 			else
121 				ok = (X509_load_cert_file(ctx,
122 				    argp, (int)argl) != 0);
123 		}
124 		break;
125 	}
126 	return (ok);
127 }
128 
129 int
130 X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
131 {
132 	int ret = 0;
133 	BIO *in = NULL;
134 	int i, count = 0;
135 	X509 *x = NULL;
136 
137 	if (file == NULL)
138 		return (1);
139 	in = BIO_new(BIO_s_file_internal());
140 
141 	if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
142 		X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
143 		goto err;
144 	}
145 
146 	if (type == X509_FILETYPE_PEM) {
147 		for (;;) {
148 			x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
149 			if (x == NULL) {
150 				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
151 				    PEM_R_NO_START_LINE) && (count > 0)) {
152 					ERR_clear_error();
153 					break;
154 				} else {
155 					X509err(X509_F_X509_LOAD_CERT_FILE,
156 					    ERR_R_PEM_LIB);
157 					goto err;
158 				}
159 			}
160 			i = X509_STORE_add_cert(ctx->store_ctx, x);
161 			if (!i)
162 				goto err;
163 			count++;
164 			X509_free(x);
165 			x = NULL;
166 		}
167 		ret = count;
168 	} else if (type == X509_FILETYPE_ASN1) {
169 		x = d2i_X509_bio(in, NULL);
170 		if (x == NULL) {
171 			X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
172 			goto err;
173 		}
174 		i = X509_STORE_add_cert(ctx->store_ctx, x);
175 		if (!i)
176 			goto err;
177 		ret = i;
178 	} else {
179 		X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
180 		goto err;
181 	}
182 err:
183 	if (x != NULL)
184 		X509_free(x);
185 	if (in != NULL)
186 		BIO_free(in);
187 	return (ret);
188 }
189 
190 int
191 X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
192 {
193 	int ret = 0;
194 	BIO *in = NULL;
195 	int i, count = 0;
196 	X509_CRL *x = NULL;
197 
198 	if (file == NULL)
199 		return (1);
200 	in = BIO_new(BIO_s_file_internal());
201 
202 	if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
203 		X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
204 		goto err;
205 	}
206 
207 	if (type == X509_FILETYPE_PEM) {
208 		for (;;) {
209 			x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
210 			if (x == NULL) {
211 				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
212 				    PEM_R_NO_START_LINE) && (count > 0)) {
213 					ERR_clear_error();
214 					break;
215 				} else {
216 					X509err(X509_F_X509_LOAD_CRL_FILE,
217 					    ERR_R_PEM_LIB);
218 					goto err;
219 				}
220 			}
221 			i = X509_STORE_add_crl(ctx->store_ctx, x);
222 			if (!i)
223 				goto err;
224 			count++;
225 			X509_CRL_free(x);
226 			x = NULL;
227 		}
228 		ret = count;
229 	} else if (type == X509_FILETYPE_ASN1) {
230 		x = d2i_X509_CRL_bio(in, NULL);
231 		if (x == NULL) {
232 			X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
233 			goto err;
234 		}
235 		i = X509_STORE_add_crl(ctx->store_ctx, x);
236 		if (!i)
237 			goto err;
238 		ret = i;
239 	} else {
240 		X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
241 		goto err;
242 	}
243 err:
244 	if (x != NULL)
245 		X509_CRL_free(x);
246 	if (in != NULL)
247 		BIO_free(in);
248 	return (ret);
249 }
250 
251 int
252 X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
253 {
254 	STACK_OF(X509_INFO) *inf;
255 	X509_INFO *itmp;
256 	BIO *in;
257 	int i, count = 0;
258 	if (type != X509_FILETYPE_PEM)
259 		return X509_load_cert_file(ctx, file, type);
260 	in = BIO_new_file(file, "r");
261 	if (!in) {
262 		X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
263 		return 0;
264 	}
265 	inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
266 	BIO_free(in);
267 	if (!inf) {
268 		X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
269 		return 0;
270 	}
271 	for (i = 0; i < sk_X509_INFO_num(inf); i++) {
272 		itmp = sk_X509_INFO_value(inf, i);
273 		if (itmp->x509) {
274 			X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
275 			count++;
276 		}
277 		if (itmp->crl) {
278 			X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
279 			count++;
280 		}
281 	}
282 	sk_X509_INFO_pop_free(inf, X509_INFO_free);
283 	return count;
284 }
285 
286