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