LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/x509 - by_dir.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 143 0.0 %
Date: 2015-10-10 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /* crypto/x509/by_dir.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             : 
      59             : #include <stdio.h>
      60             : #include <time.h>
      61             : #include <errno.h>
      62             : 
      63             : #include "cryptlib.h"
      64             : 
      65             : #ifndef NO_SYS_TYPES_H
      66             : # include <sys/types.h>
      67             : #endif
      68             : #ifndef OPENSSL_NO_POSIX_IO
      69             : # include <sys/stat.h>
      70             : #endif
      71             : 
      72             : #include <openssl/lhash.h>
      73             : #include <openssl/x509.h>
      74             : 
      75             : typedef struct lookup_dir_hashes_st {
      76             :     unsigned long hash;
      77             :     int suffix;
      78             : } BY_DIR_HASH;
      79             : 
      80             : typedef struct lookup_dir_entry_st {
      81             :     char *dir;
      82             :     int dir_type;
      83             :     STACK_OF(BY_DIR_HASH) *hashes;
      84             : } BY_DIR_ENTRY;
      85             : 
      86             : typedef struct lookup_dir_st {
      87             :     BUF_MEM *buffer;
      88             :     STACK_OF(BY_DIR_ENTRY) *dirs;
      89             : } BY_DIR;
      90             : 
      91             : DECLARE_STACK_OF(BY_DIR_HASH)
      92             : DECLARE_STACK_OF(BY_DIR_ENTRY)
      93             : 
      94             : static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
      95             :                     char **ret);
      96             : static int new_dir(X509_LOOKUP *lu);
      97             : static void free_dir(X509_LOOKUP *lu);
      98             : static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
      99             : static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
     100             :                                X509_OBJECT *ret);
     101             : X509_LOOKUP_METHOD x509_dir_lookup = {
     102             :     "Load certs from files in a directory",
     103             :     new_dir,                    /* new */
     104             :     free_dir,                   /* free */
     105             :     NULL,                       /* init */
     106             :     NULL,                       /* shutdown */
     107             :     dir_ctrl,                   /* ctrl */
     108             :     get_cert_by_subject,        /* get_by_subject */
     109             :     NULL,                       /* get_by_issuer_serial */
     110             :     NULL,                       /* get_by_fingerprint */
     111             :     NULL,                       /* get_by_alias */
     112             : };
     113             : 
     114           0 : X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
     115             : {
     116           0 :     return (&x509_dir_lookup);
     117             : }
     118             : 
     119           0 : static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
     120             :                     char **retp)
     121             : {
     122             :     int ret = 0;
     123             :     BY_DIR *ld;
     124             :     char *dir = NULL;
     125             : 
     126           0 :     ld = (BY_DIR *)ctx->method_data;
     127             : 
     128           0 :     switch (cmd) {
     129             :     case X509_L_ADD_DIR:
     130           0 :         if (argl == X509_FILETYPE_DEFAULT) {
     131           0 :             dir = (char *)getenv(X509_get_default_cert_dir_env());
     132           0 :             if (dir)
     133           0 :                 ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM);
     134             :             else
     135           0 :                 ret = add_cert_dir(ld, X509_get_default_cert_dir(),
     136             :                                    X509_FILETYPE_PEM);
     137           0 :             if (!ret) {
     138           0 :                 X509err(X509_F_DIR_CTRL, X509_R_LOADING_CERT_DIR);
     139             :             }
     140             :         } else
     141           0 :             ret = add_cert_dir(ld, argp, (int)argl);
     142             :         break;
     143             :     }
     144           0 :     return (ret);
     145             : }
     146             : 
     147           0 : static int new_dir(X509_LOOKUP *lu)
     148             : {
     149             :     BY_DIR *a;
     150             : 
     151           0 :     if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
     152             :         return (0);
     153           0 :     if ((a->buffer = BUF_MEM_new()) == NULL) {
     154           0 :         OPENSSL_free(a);
     155           0 :         return (0);
     156             :     }
     157           0 :     a->dirs = NULL;
     158           0 :     lu->method_data = (char *)a;
     159           0 :     return (1);
     160             : }
     161             : 
     162           0 : static void by_dir_hash_free(BY_DIR_HASH *hash)
     163             : {
     164           0 :     OPENSSL_free(hash);
     165           0 : }
     166             : 
     167           0 : static int by_dir_hash_cmp(const BY_DIR_HASH *const *a,
     168             :                            const BY_DIR_HASH *const *b)
     169             : {
     170           0 :     if ((*a)->hash > (*b)->hash)
     171             :         return 1;
     172           0 :     if ((*a)->hash < (*b)->hash)
     173             :         return -1;
     174           0 :     return 0;
     175             : }
     176             : 
     177           0 : static void by_dir_entry_free(BY_DIR_ENTRY *ent)
     178             : {
     179           0 :     if (ent->dir)
     180           0 :         OPENSSL_free(ent->dir);
     181           0 :     if (ent->hashes)
     182           0 :         sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
     183           0 :     OPENSSL_free(ent);
     184           0 : }
     185             : 
     186           0 : static void free_dir(X509_LOOKUP *lu)
     187             : {
     188             :     BY_DIR *a;
     189             : 
     190           0 :     a = (BY_DIR *)lu->method_data;
     191           0 :     if (a->dirs != NULL)
     192           0 :         sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
     193           0 :     if (a->buffer != NULL)
     194           0 :         BUF_MEM_free(a->buffer);
     195           0 :     OPENSSL_free(a);
     196           0 : }
     197             : 
     198           0 : static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
     199             : {
     200             :     int j, len;
     201             :     const char *s, *ss, *p;
     202             : 
     203           0 :     if (dir == NULL || !*dir) {
     204           0 :         X509err(X509_F_ADD_CERT_DIR, X509_R_INVALID_DIRECTORY);
     205             :         return 0;
     206             :     }
     207             : 
     208             :     s = dir;
     209             :     p = s;
     210             :     do {
     211           0 :         if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) {
     212             :             BY_DIR_ENTRY *ent;
     213             :             ss = s;
     214           0 :             s = p + 1;
     215           0 :             len = (int)(p - ss);
     216           0 :             if (len == 0)
     217           0 :                 continue;
     218           0 :             for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) {
     219           0 :                 ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
     220           0 :                 if (strlen(ent->dir) == (size_t)len &&
     221           0 :                     strncmp(ent->dir, ss, (unsigned int)len) == 0)
     222             :                     break;
     223             :             }
     224           0 :             if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
     225           0 :                 continue;
     226           0 :             if (ctx->dirs == NULL) {
     227           0 :                 ctx->dirs = sk_BY_DIR_ENTRY_new_null();
     228           0 :                 if (!ctx->dirs) {
     229           0 :                     X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
     230             :                     return 0;
     231             :                 }
     232             :             }
     233           0 :             ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
     234           0 :             if (!ent)
     235             :                 return 0;
     236           0 :             ent->dir_type = type;
     237           0 :             ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
     238           0 :             ent->dir = OPENSSL_malloc((unsigned int)len + 1);
     239           0 :             if (!ent->dir || !ent->hashes) {
     240           0 :                 by_dir_entry_free(ent);
     241             :                 return 0;
     242             :             }
     243           0 :             strncpy(ent->dir, ss, (unsigned int)len);
     244           0 :             ent->dir[len] = '\0';
     245           0 :             if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
     246           0 :                 by_dir_entry_free(ent);
     247             :                 return 0;
     248             :             }
     249             :         }
     250           0 :     } while (*p++ != '\0');
     251             :     return 1;
     252             : }
     253             : 
     254           0 : static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
     255             :                                X509_OBJECT *ret)
     256             : {
     257             :     BY_DIR *ctx;
     258             :     union {
     259             :         struct {
     260             :             X509 st_x509;
     261             :             X509_CINF st_x509_cinf;
     262             :         } x509;
     263             :         struct {
     264             :             X509_CRL st_crl;
     265             :             X509_CRL_INFO st_crl_info;
     266             :         } crl;
     267             :     } data;
     268             :     int ok = 0;
     269             :     int i, j, k;
     270             :     unsigned long h;
     271             :     BUF_MEM *b = NULL;
     272             :     X509_OBJECT stmp, *tmp;
     273             :     const char *postfix = "";
     274             : 
     275           0 :     if (name == NULL)
     276             :         return (0);
     277             : 
     278           0 :     stmp.type = type;
     279           0 :     if (type == X509_LU_X509) {
     280           0 :         data.x509.st_x509.cert_info = &data.x509.st_x509_cinf;
     281           0 :         data.x509.st_x509_cinf.subject = name;
     282           0 :         stmp.data.x509 = &data.x509.st_x509;
     283             :         postfix = "";
     284           0 :     } else if (type == X509_LU_CRL) {
     285           0 :         data.crl.st_crl.crl = &data.crl.st_crl_info;
     286           0 :         data.crl.st_crl_info.issuer = name;
     287           0 :         stmp.data.crl = &data.crl.st_crl;
     288             :         postfix = "r";
     289             :     } else {
     290           0 :         X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);
     291           0 :         goto finish;
     292             :     }
     293             : 
     294           0 :     if ((b = BUF_MEM_new()) == NULL) {
     295           0 :         X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);
     296           0 :         goto finish;
     297             :     }
     298             : 
     299           0 :     ctx = (BY_DIR *)xl->method_data;
     300             : 
     301           0 :     h = X509_NAME_hash(name);
     302           0 :     for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
     303             :         BY_DIR_ENTRY *ent;
     304             :         int idx;
     305             :         BY_DIR_HASH htmp, *hent;
     306           0 :         ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
     307           0 :         j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
     308           0 :         if (!BUF_MEM_grow(b, j)) {
     309           0 :             X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
     310           0 :             goto finish;
     311             :         }
     312           0 :         if (type == X509_LU_CRL && ent->hashes) {
     313           0 :             htmp.hash = h;
     314           0 :             CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
     315           0 :             idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
     316           0 :             if (idx >= 0) {
     317           0 :                 hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
     318           0 :                 k = hent->suffix;
     319             :             } else {
     320             :                 hent = NULL;
     321             :                 k = 0;
     322             :             }
     323           0 :             CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
     324             :         } else {
     325             :             k = 0;
     326             :             hent = NULL;
     327             :         }
     328             :         for (;;) {
     329             :             char c = '/';
     330             : #ifdef OPENSSL_SYS_VMS
     331             :             c = ent->dir[strlen(ent->dir) - 1];
     332             :             if (c != ':' && c != '>' && c != ']') {
     333             :                 /*
     334             :                  * If no separator is present, we assume the directory
     335             :                  * specifier is a logical name, and add a colon.  We really
     336             :                  * should use better VMS routines for merging things like
     337             :                  * this, but this will do for now... -- Richard Levitte
     338             :                  */
     339             :                 c = ':';
     340             :             } else {
     341             :                 c = '\0';
     342             :             }
     343             : #endif
     344             :             if (c == '\0') {
     345             :                 /*
     346             :                  * This is special.  When c == '\0', no directory separator
     347             :                  * should be added.
     348             :                  */
     349             :                 BIO_snprintf(b->data, b->max,
     350             :                              "%s%08lx.%s%d", ent->dir, h, postfix, k);
     351             :             } else {
     352           0 :                 BIO_snprintf(b->data, b->max,
     353             :                              "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);
     354             :             }
     355             : #ifndef OPENSSL_NO_POSIX_IO
     356             : # ifdef _WIN32
     357             : #  define stat _stat
     358             : # endif
     359             :             {
     360             :                 struct stat st;
     361           0 :                 if (stat(b->data, &st) < 0)
     362             :                     break;
     363             :             }
     364             : #endif
     365             :             /* found one. */
     366           0 :             if (type == X509_LU_X509) {
     367           0 :                 if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)
     368             :                     break;
     369           0 :             } else if (type == X509_LU_CRL) {
     370           0 :                 if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
     371             :                     break;
     372             :             }
     373             :             /* else case will caught higher up */
     374           0 :             k++;
     375           0 :         }
     376             : 
     377             :         /*
     378             :          * we have added it to the cache so now pull it out again
     379             :          */
     380           0 :         CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
     381           0 :         j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
     382           0 :         if (j != -1)
     383           0 :             tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
     384             :         else
     385             :             tmp = NULL;
     386           0 :         CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
     387             : 
     388             :         /* If a CRL, update the last file suffix added for this */
     389             : 
     390           0 :         if (type == X509_LU_CRL) {
     391           0 :             CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
     392             :             /*
     393             :              * Look for entry again in case another thread added an entry
     394             :              * first.
     395             :              */
     396           0 :             if (!hent) {
     397           0 :                 htmp.hash = h;
     398           0 :                 idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
     399           0 :                 if (idx >= 0)
     400           0 :                     hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
     401             :             }
     402           0 :             if (!hent) {
     403           0 :                 hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
     404           0 :                 hent->hash = h;
     405           0 :                 hent->suffix = k;
     406           0 :                 if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
     407           0 :                     CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
     408           0 :                     OPENSSL_free(hent);
     409             :                     ok = 0;
     410           0 :                     goto finish;
     411             :                 }
     412           0 :             } else if (hent->suffix < k)
     413           0 :                 hent->suffix = k;
     414             : 
     415           0 :             CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
     416             : 
     417             :         }
     418             : 
     419           0 :         if (tmp != NULL) {
     420             :             ok = 1;
     421           0 :             ret->type = tmp->type;
     422           0 :             memcpy(&ret->data, &tmp->data, sizeof(ret->data));
     423             :             /*
     424             :              * If we were going to up the reference count, we would need to
     425             :              * do it on a perl 'type' basis
     426             :              */
     427             :         /*- CRYPTO_add(&tmp->data.x509->references,1,
     428             :                     CRYPTO_LOCK_X509);*/
     429             :             goto finish;
     430             :         }
     431             :     }
     432             :  finish:
     433           0 :     if (b != NULL)
     434           0 :         BUF_MEM_free(b);
     435           0 :     return (ok);
     436             : }

Generated by: LCOV version 1.10