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