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