xref: /openbsd/lib/libcrypto/x509/by_file.c (revision a6445c1d)
1 /* $OpenBSD: by_file.c,v 1.16 2014/07/25 06:05:32 doug 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 	BIO_free(in);
186 	return (ret);
187 }
188 
189 int
190 X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
191 {
192 	int ret = 0;
193 	BIO *in = NULL;
194 	int i, count = 0;
195 	X509_CRL *x = NULL;
196 
197 	if (file == NULL)
198 		return (1);
199 	in = BIO_new(BIO_s_file_internal());
200 
201 	if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
202 		X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
203 		goto err;
204 	}
205 
206 	if (type == X509_FILETYPE_PEM) {
207 		for (;;) {
208 			x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
209 			if (x == NULL) {
210 				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
211 				    PEM_R_NO_START_LINE) && (count > 0)) {
212 					ERR_clear_error();
213 					break;
214 				} else {
215 					X509err(X509_F_X509_LOAD_CRL_FILE,
216 					    ERR_R_PEM_LIB);
217 					goto err;
218 				}
219 			}
220 			i = X509_STORE_add_crl(ctx->store_ctx, x);
221 			if (!i)
222 				goto err;
223 			count++;
224 			X509_CRL_free(x);
225 			x = NULL;
226 		}
227 		ret = count;
228 	} else if (type == X509_FILETYPE_ASN1) {
229 		x = d2i_X509_CRL_bio(in, NULL);
230 		if (x == NULL) {
231 			X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
232 			goto err;
233 		}
234 		i = X509_STORE_add_crl(ctx->store_ctx, x);
235 		if (!i)
236 			goto err;
237 		ret = i;
238 	} else {
239 		X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
240 		goto err;
241 	}
242 err:
243 	if (x != NULL)
244 		X509_CRL_free(x);
245 	BIO_free(in);
246 	return (ret);
247 }
248 
249 int
250 X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
251 {
252 	STACK_OF(X509_INFO) *inf;
253 	X509_INFO *itmp;
254 	BIO *in;
255 	int i, count = 0;
256 	if (type != X509_FILETYPE_PEM)
257 		return X509_load_cert_file(ctx, file, type);
258 	in = BIO_new_file(file, "r");
259 	if (!in) {
260 		X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
261 		return 0;
262 	}
263 	inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
264 	BIO_free(in);
265 	if (!inf) {
266 		X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
267 		return 0;
268 	}
269 	for (i = 0; i < sk_X509_INFO_num(inf); i++) {
270 		itmp = sk_X509_INFO_value(inf, i);
271 		if (itmp->x509) {
272 			X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
273 			count++;
274 		}
275 		if (itmp->crl) {
276 			X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
277 			count++;
278 		}
279 	}
280 	sk_X509_INFO_pop_free(inf, X509_INFO_free);
281 	return count;
282 }
283 
284