Fix undefined behaviour when printing the X509 and CRL version
[openssl.git] / crypto / x509 / by_file.c
1 /*
2  * Copyright 1995-2016 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     if (file == NULL)
83         return (1);
84     in = BIO_new(BIO_s_file());
85
86     if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
87         X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
88         goto err;
89     }
90
91     if (type == X509_FILETYPE_PEM) {
92         for (;;) {
93             x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
94             if (x == NULL) {
95                 if ((ERR_GET_REASON(ERR_peek_last_error()) ==
96                      PEM_R_NO_START_LINE) && (count > 0)) {
97                     ERR_clear_error();
98                     break;
99                 } else {
100                     X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
101                     goto err;
102                 }
103             }
104             i = X509_STORE_add_cert(ctx->store_ctx, x);
105             if (!i)
106                 goto err;
107             count++;
108             X509_free(x);
109             x = NULL;
110         }
111         ret = count;
112     } else if (type == X509_FILETYPE_ASN1) {
113         x = d2i_X509_bio(in, NULL);
114         if (x == NULL) {
115             X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
116             goto err;
117         }
118         i = X509_STORE_add_cert(ctx->store_ctx, x);
119         if (!i)
120             goto err;
121         ret = i;
122     } else {
123         X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
124         goto err;
125     }
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     if (file == NULL)
140         return (1);
141     in = BIO_new(BIO_s_file());
142
143     if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
144         X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
145         goto err;
146     }
147
148     if (type == X509_FILETYPE_PEM) {
149         for (;;) {
150             x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
151             if (x == NULL) {
152                 if ((ERR_GET_REASON(ERR_peek_last_error()) ==
153                      PEM_R_NO_START_LINE) && (count > 0)) {
154                     ERR_clear_error();
155                     break;
156                 } else {
157                     X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_PEM_LIB);
158                     goto err;
159                 }
160             }
161             i = X509_STORE_add_crl(ctx->store_ctx, x);
162             if (!i)
163                 goto err;
164             count++;
165             X509_CRL_free(x);
166             x = NULL;
167         }
168         ret = count;
169     } else if (type == X509_FILETYPE_ASN1) {
170         x = d2i_X509_CRL_bio(in, NULL);
171         if (x == NULL) {
172             X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
173             goto err;
174         }
175         i = X509_STORE_add_crl(ctx->store_ctx, x);
176         if (!i)
177             goto err;
178         ret = i;
179     } else {
180         X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
181         goto err;
182     }
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     if (type != X509_FILETYPE_PEM)
196         return X509_load_cert_file(ctx, file, type);
197     in = BIO_new_file(file, "r");
198     if (!in) {
199         X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
200         return 0;
201     }
202     inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
203     BIO_free(in);
204     if (!inf) {
205         X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
206         return 0;
207     }
208     for (i = 0; i < sk_X509_INFO_num(inf); i++) {
209         itmp = sk_X509_INFO_value(inf, i);
210         if (itmp->x509) {
211             X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
212             count++;
213         }
214         if (itmp->crl) {
215             X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
216             count++;
217         }
218     }
219     sk_X509_INFO_pop_free(inf, X509_INFO_free);
220     return count;
221 }