1/* crypto/x509/by_file.c */
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#include <stdlib.h>
59
60#include <openssl/buf.h>
61#include <openssl/err.h>
62#include <openssl/lhash.h>
63#include <openssl/pem.h>
64#include <openssl/thread.h>
65
66
67#ifndef OPENSSL_NO_STDIO
68
69static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
70	long argl, char **ret);
71static X509_LOOKUP_METHOD x509_file_lookup=
72	{
73	"Load file into cache",
74	NULL,		/* new */
75	NULL,		/* free */
76	NULL, 		/* init */
77	NULL,		/* shutdown */
78	by_file_ctrl,	/* ctrl */
79	NULL,		/* get_by_subject */
80	NULL,		/* get_by_issuer_serial */
81	NULL,		/* get_by_fingerprint */
82	NULL,		/* get_by_alias */
83	};
84
85X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
86	{
87	return(&x509_file_lookup);
88	}
89
90static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
91	     char **ret)
92	{
93	int ok=0;
94	char *file;
95
96	switch (cmd)
97		{
98	case X509_L_FILE_LOAD:
99		if (argl == X509_FILETYPE_DEFAULT)
100			{
101			file = (char *)getenv(X509_get_default_cert_file_env());
102			if (file)
103				ok = (X509_load_cert_crl_file(ctx,file,
104					      X509_FILETYPE_PEM) != 0);
105
106			else
107				ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
108					      X509_FILETYPE_PEM) != 0);
109
110			if (!ok)
111				{
112				OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS);
113				}
114			}
115		else
116			{
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,argp,(int)argl) != 0);
122			}
123		break;
124		}
125	return(ok);
126	}
127
128int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
129	{
130	int ret=0;
131	BIO *in=NULL;
132	int i,count=0;
133	X509 *x=NULL;
134
135	if (file == NULL) return(1);
136	in=BIO_new(BIO_s_file());
137
138	if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
139		{
140		OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
141		goto err;
142		}
143
144	if (type == X509_FILETYPE_PEM)
145		{
146		for (;;)
147			{
148			x=PEM_read_bio_X509_AUX(in,NULL,NULL,NULL);
149			if (x == NULL)
150				{
151				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
152					PEM_R_NO_START_LINE) && (count > 0))
153					{
154					ERR_clear_error();
155					break;
156					}
157				else
158					{
159					OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
160					goto err;
161					}
162				}
163			i=X509_STORE_add_cert(ctx->store_ctx,x);
164			if (!i) goto err;
165			count++;
166			X509_free(x);
167			x=NULL;
168			}
169		ret=count;
170		}
171	else if (type == X509_FILETYPE_ASN1)
172		{
173		x=d2i_X509_bio(in,NULL);
174		if (x == NULL)
175			{
176			OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
177			goto err;
178			}
179		i=X509_STORE_add_cert(ctx->store_ctx,x);
180		if (!i) goto err;
181		ret=i;
182		}
183	else
184		{
185		OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
186		goto err;
187		}
188err:
189	if (x != NULL) X509_free(x);
190	if (in != NULL) BIO_free(in);
191	return(ret);
192	}
193
194int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
195	{
196	int ret=0;
197	BIO *in=NULL;
198	int i,count=0;
199	X509_CRL *x=NULL;
200
201	if (file == NULL) return(1);
202	in=BIO_new(BIO_s_file());
203
204	if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
205		{
206		OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
207		goto err;
208		}
209
210	if (type == X509_FILETYPE_PEM)
211		{
212		for (;;)
213			{
214			x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
215			if (x == NULL)
216				{
217				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
218					PEM_R_NO_START_LINE) && (count > 0))
219					{
220					ERR_clear_error();
221					break;
222					}
223				else
224					{
225					OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
226					goto err;
227					}
228				}
229			i=X509_STORE_add_crl(ctx->store_ctx,x);
230			if (!i) goto err;
231			count++;
232			X509_CRL_free(x);
233			x=NULL;
234			}
235		ret=count;
236		}
237	else if (type == X509_FILETYPE_ASN1)
238		{
239		x=d2i_X509_CRL_bio(in,NULL);
240		if (x == NULL)
241			{
242			OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
243			goto err;
244			}
245		i=X509_STORE_add_crl(ctx->store_ctx,x);
246		if (!i) goto err;
247		ret=i;
248		}
249	else
250		{
251		OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
252		goto err;
253		}
254err:
255	if (x != NULL) X509_CRL_free(x);
256	if (in != NULL) BIO_free(in);
257	return(ret);
258	}
259
260int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
261{
262	STACK_OF(X509_INFO) *inf;
263	X509_INFO *itmp;
264	BIO *in;
265	size_t i;
266	int count = 0;
267	if(type != X509_FILETYPE_PEM)
268		return X509_load_cert_file(ctx, file, type);
269	in = BIO_new_file(file, "r");
270	if(!in) {
271		OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
272		return 0;
273	}
274	inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
275	BIO_free(in);
276	if(!inf) {
277		OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
278		return 0;
279	}
280	for(i = 0; i < sk_X509_INFO_num(inf); i++) {
281		itmp = sk_X509_INFO_value(inf, i);
282		if(itmp->x509) {
283			X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
284			count++;
285		}
286		if(itmp->crl) {
287			X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
288			count++;
289		}
290	}
291	sk_X509_INFO_pop_free(inf, X509_INFO_free);
292	return count;
293}
294
295#endif /* OPENSSL_NO_STDIO */
296