Ignore dups in X509_STORE_add_*
[openssl.git] / crypto / x509 / by_file.c
1 /*
2  * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include <time.h>
12 #include <errno.h>
13
14 #include "internal/cryptlib.h"
15 #include <openssl/lhash.h>
16 #include <openssl/buffer.h>
17 #include <openssl/x509.h>
18 #include <openssl/pem.h>
19 #include "x509_lcl.h"
20
21 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
22                         long argl, char **ret);
23 static X509_LOOKUP_METHOD x509_file_lookup = {
24     "Load file into cache",
25     NULL,                       /* new */
26     NULL,                       /* free */
27     NULL,                       /* init */
28     NULL,                       /* shutdown */
29     by_file_ctrl,               /* ctrl */
30     NULL,                       /* get_by_subject */
31     NULL,                       /* get_by_issuer_serial */
32     NULL,                       /* get_by_fingerprint */
33     NULL,                       /* get_by_alias */
34 };
35
36 X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
37 {
38     return (&x509_file_lookup);
39 }
40
41 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
42                         long argl, char **ret)
43 {
44     int ok = 0;
45     char *file;
46
47     switch (cmd) {
48     case X509_L_FILE_LOAD:
49         if (argl == X509_FILETYPE_DEFAULT) {
50             file = (char *)getenv(X509_get_default_cert_file_env());
51             if (file)
52                 ok = (X509_load_cert_crl_file(ctx, file,
53                                               X509_FILETYPE_PEM) != 0);
54
55             else
56                 ok = (X509_load_cert_crl_file
57                       (ctx, X509_get_default_cert_file(),
58                        X509_FILETYPE_PEM) != 0);
59
60             if (!ok) {
61                 X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS);
62             }
63         } else {
64             if (argl == X509_FILETYPE_PEM)
65                 ok = (X509_load_cert_crl_file(ctx, argp,
66                                               X509_FILETYPE_PEM) != 0);
67             else
68                 ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
69         }
70         break;
71     }
72     return (ok);
73 }
74
75 int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
76 {
77     int ret = 0;
78     BIO *in = NULL;
79     int i, count = 0;
80     X509 *x = NULL;
81
82     in = BIO_new(BIO_s_file());
83
84     if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
85         X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
86         goto err;
87     }
88
89     if (type == X509_FILETYPE_PEM) {
90         for (;;) {
91             x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
92             if (x == NULL) {
93                 if ((ERR_GET_REASON(ERR_peek_last_error()) ==
94                      PEM_R_NO_START_LINE) && (count > 0)) {
95                     ERR_clear_error();
96                     break;
97                 } else {
98                     X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
99                     goto err;
100                 }
101             }
102             i = X509_STORE_add_cert(ctx->store_ctx, x);
103             if (!i)
104                 goto err;
105             count++;
106             X509_free(x);
107             x = NULL;
108         }
109         ret = count;
110     } else if (type == X509_FILETYPE_ASN1) {
111         x = d2i_X509_bio(in, NULL);
112         if (x == NULL) {
113             X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
114             goto err;
115         }
116         i = X509_STORE_add_cert(ctx->store_ctx, x);
117         if (!i)
118             goto err;
119         ret = i;
120     } else {
121         X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
122         goto err;
123     }
124     if (ret == 0)
125         X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND);
126  err:
127     X509_free(x);
128     BIO_free(in);
129     return (ret);
130 }
131
132 int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
133 {
134     int ret = 0;
135     BIO *in = NULL;
136     int i, count = 0;
137     X509_CRL *x = NULL;
138
139     in = BIO_new(BIO_s_file());
140
141     if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
142         X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
143         goto err;
144     }
145
146     if (type == X509_FILETYPE_PEM) {
147         for (;;) {
148             x = PEM_read_bio_X509_CRL(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_CRL_FILE, ERR_R_PEM_LIB);
156                     goto err;
157                 }
158             }
159             i = X509_STORE_add_crl(ctx->store_ctx, x);
160             if (!i)
161                 goto err;
162             count++;
163             X509_CRL_free(x);
164             x = NULL;
165         }
166         ret = count;
167     } else if (type == X509_FILETYPE_ASN1) {
168         x = d2i_X509_CRL_bio(in, NULL);
169         if (x == NULL) {
170             X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
171             goto err;
172         }
173         i = X509_STORE_add_crl(ctx->store_ctx, x);
174         if (!i)
175             goto err;
176         ret = i;
177     } else {
178         X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
179         goto err;
180     }
181     if (ret == 0)
182         X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_NO_CRL_FOUND);
183  err:
184     X509_CRL_free(x);
185     BIO_free(in);
186     return (ret);
187 }
188
189 int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
190 {
191     STACK_OF(X509_INFO) *inf;
192     X509_INFO *itmp;
193     BIO *in;
194     int i, count = 0;
195
196     if (type != X509_FILETYPE_PEM)
197         return X509_load_cert_file(ctx, file, type);
198     in = BIO_new_file(file, "r");
199     if (!in) {
200         X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
201         return 0;
202     }
203     inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
204     BIO_free(in);
205     if (!inf) {
206         X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
207         return 0;
208     }
209     for (i = 0; i < sk_X509_INFO_num(inf); i++) {
210         itmp = sk_X509_INFO_value(inf, i);
211         if (itmp->x509) {
212             if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509))
213                 goto err;
214             count++;
215         }
216         if (itmp->crl) {
217             if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl))
218                 goto err;
219             count++;
220         }
221     }
222     if (count == 0)
223         X509err(X509_F_X509_LOAD_CERT_CRL_FILE,
224                 X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
225  err:
226     sk_X509_INFO_pop_free(inf, X509_INFO_free);
227     return count;
228 }