1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/x509/by_dir.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,408 @@
1.4 +/* crypto/x509/by_dir.c */
1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
1.6 + * All rights reserved.
1.7 + *
1.8 + * This package is an SSL implementation written
1.9 + * by Eric Young (eay@cryptsoft.com).
1.10 + * The implementation was written so as to conform with Netscapes SSL.
1.11 + *
1.12 + * This library is free for commercial and non-commercial use as long as
1.13 + * the following conditions are aheared to. The following conditions
1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
1.15 + * lhash, DES, etc., code; not just the SSL code. The SSL documentation
1.16 + * included with this distribution is covered by the same copyright terms
1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1.18 + *
1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
1.20 + * the code are not to be removed.
1.21 + * If this package is used in a product, Eric Young should be given attribution
1.22 + * as the author of the parts of the library used.
1.23 + * This can be in the form of a textual message at program startup or
1.24 + * in documentation (online or textual) provided with the package.
1.25 + *
1.26 + * Redistribution and use in source and binary forms, with or without
1.27 + * modification, are permitted provided that the following conditions
1.28 + * are met:
1.29 + * 1. Redistributions of source code must retain the copyright
1.30 + * notice, this list of conditions and the following disclaimer.
1.31 + * 2. Redistributions in binary form must reproduce the above copyright
1.32 + * notice, this list of conditions and the following disclaimer in the
1.33 + * documentation and/or other materials provided with the distribution.
1.34 + * 3. All advertising materials mentioning features or use of this software
1.35 + * must display the following acknowledgement:
1.36 + * "This product includes cryptographic software written by
1.37 + * Eric Young (eay@cryptsoft.com)"
1.38 + * The word 'cryptographic' can be left out if the rouines from the library
1.39 + * being used are not cryptographic related :-).
1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from
1.41 + * the apps directory (application code) you must include an acknowledgement:
1.42 + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
1.43 + *
1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.47 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.54 + * SUCH DAMAGE.
1.55 + *
1.56 + * The licence and distribution terms for any publically available version or
1.57 + * derivative of this code cannot be changed. i.e. this code cannot simply be
1.58 + * copied and put under another distribution licence
1.59 + * [including the GNU Public Licence.]
1.60 + */
1.61 + /*
1.62 + © Portions copyright (c) 2006 Nokia Corporation. All rights reserved.
1.63 + */
1.64 +
1.65 +#include <stdio.h>
1.66 +#include <time.h>
1.67 +#include <errno.h>
1.68 +
1.69 +#include "cryptlib.h"
1.70 +
1.71 +#ifndef NO_SYS_TYPES_H
1.72 +# include <sys/types.h>
1.73 +#endif
1.74 +#ifdef MAC_OS_pre_X
1.75 +# include <stat.h>
1.76 +#else
1.77 +# include <sys/stat.h>
1.78 +#endif
1.79 +
1.80 +#include <openssl/lhash.h>
1.81 +#include <openssl/x509.h>
1.82 +#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
1.83 +#include "libcrypto_wsd_macros.h"
1.84 +#include "libcrypto_wsd.h"
1.85 +#endif
1.86 +
1.87 +
1.88 +typedef struct lookup_dir_st
1.89 + {
1.90 + BUF_MEM *buffer;
1.91 + int num_dirs;
1.92 + char **dirs;
1.93 + int *dirs_type;
1.94 + int num_dirs_alloced;
1.95 + } BY_DIR;
1.96 +
1.97 +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
1.98 + char **ret);
1.99 +static int new_dir(X509_LOOKUP *lu);
1.100 +static void free_dir(X509_LOOKUP *lu);
1.101 +static int add_cert_dir(BY_DIR *ctx,const char *dir,int type);
1.102 +static int get_cert_by_subject(X509_LOOKUP *xl,int type,X509_NAME *name,
1.103 + X509_OBJECT *ret);
1.104 +#ifndef EMULATOR
1.105 +X509_LOOKUP_METHOD x509_dir_lookup=
1.106 + {
1.107 + "Load certs from files in a directory",
1.108 + new_dir, /* new */
1.109 + free_dir, /* free */
1.110 + NULL, /* init */
1.111 + NULL, /* shutdown */
1.112 + dir_ctrl, /* ctrl */
1.113 + get_cert_by_subject, /* get_by_subject */
1.114 + NULL, /* get_by_issuer_serial */
1.115 + NULL, /* get_by_fingerprint */
1.116 + NULL, /* get_by_alias */
1.117 + };
1.118 +#else
1.119 +GET_GLOBAL_VAR_FROM_TLS(x509_dir_lookup,by_dir,X509_LOOKUP_METHOD)
1.120 +#define x509_dir_lookup (*GET_WSD_VAR_NAME(x509_dir_lookup,by_dir, g)())
1.121 +const X509_LOOKUP_METHOD temp_g_x509_dir_lookup=
1.122 + {
1.123 + "Load certs from files in a directory",
1.124 + new_dir, /* new */
1.125 + free_dir, /* free */
1.126 + NULL, /* init */
1.127 + NULL, /* shutdown */
1.128 + dir_ctrl, /* ctrl */
1.129 + get_cert_by_subject, /* get_by_subject */
1.130 + NULL, /* get_by_issuer_serial */
1.131 + NULL, /* get_by_fingerprint */
1.132 + NULL, /* get_by_alias */
1.133 + };
1.134 +#endif
1.135 +
1.136 +EXPORT_C X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
1.137 + {
1.138 + return(&x509_dir_lookup);
1.139 + }
1.140 +
1.141 +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
1.142 + char **retp)
1.143 + {
1.144 + int ret=0;
1.145 + BY_DIR *ld;
1.146 + char *dir = NULL;
1.147 +
1.148 + ld=(BY_DIR *)ctx->method_data;
1.149 +
1.150 + switch (cmd)
1.151 + {
1.152 + case X509_L_ADD_DIR:
1.153 + if (argl == X509_FILETYPE_DEFAULT)
1.154 + {
1.155 + dir=(char *)Getenv(X509_get_default_cert_dir_env());
1.156 + if (dir)
1.157 + ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
1.158 + else
1.159 + ret=add_cert_dir(ld,X509_get_default_cert_dir(),
1.160 + X509_FILETYPE_PEM);
1.161 + if (!ret)
1.162 + {
1.163 + X509err(X509_F_DIR_CTRL,X509_R_LOADING_CERT_DIR);
1.164 + }
1.165 + }
1.166 + else
1.167 + ret=add_cert_dir(ld,argp,(int)argl);
1.168 + break;
1.169 + }
1.170 + return(ret);
1.171 + }
1.172 +
1.173 +static int new_dir(X509_LOOKUP *lu)
1.174 + {
1.175 + BY_DIR *a;
1.176 +
1.177 + if ((a=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
1.178 + return(0);
1.179 + if ((a->buffer=BUF_MEM_new()) == NULL)
1.180 + {
1.181 + OPENSSL_free(a);
1.182 + return(0);
1.183 + }
1.184 + a->num_dirs=0;
1.185 + a->dirs=NULL;
1.186 + a->dirs_type=NULL;
1.187 + a->num_dirs_alloced=0;
1.188 + lu->method_data=(char *)a;
1.189 + return(1);
1.190 + }
1.191 +
1.192 +static void free_dir(X509_LOOKUP *lu)
1.193 + {
1.194 + BY_DIR *a;
1.195 + int i;
1.196 +
1.197 + a=(BY_DIR *)lu->method_data;
1.198 + for (i=0; i<a->num_dirs; i++)
1.199 + if (a->dirs[i] != NULL) OPENSSL_free(a->dirs[i]);
1.200 + if (a->dirs != NULL) OPENSSL_free(a->dirs);
1.201 + if (a->dirs_type != NULL) OPENSSL_free(a->dirs_type);
1.202 + if (a->buffer != NULL) BUF_MEM_free(a->buffer);
1.203 + OPENSSL_free(a);
1.204 + }
1.205 +
1.206 +static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
1.207 + {
1.208 + int j,len;
1.209 + int *ip;
1.210 + const char *s,*ss,*p;
1.211 + char **pp;
1.212 +
1.213 + if (dir == NULL || !*dir)
1.214 + {
1.215 + X509err(X509_F_ADD_CERT_DIR,X509_R_INVALID_DIRECTORY);
1.216 + return 0;
1.217 + }
1.218 +
1.219 + s=dir;
1.220 + p=s;
1.221 + for (;;p++)
1.222 + {
1.223 + if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0'))
1.224 + {
1.225 + ss=s;
1.226 + s=p+1;
1.227 + len=(int)(p-ss);
1.228 + if (len == 0) continue;
1.229 + for (j=0; j<ctx->num_dirs; j++)
1.230 + if (strlen(ctx->dirs[j]) == (size_t)len &&
1.231 + strncmp(ctx->dirs[j],ss,(unsigned int)len) == 0)
1.232 + break;
1.233 + if (j<ctx->num_dirs)
1.234 + continue;
1.235 + if (ctx->num_dirs_alloced < (ctx->num_dirs+1))
1.236 + {
1.237 + ctx->num_dirs_alloced+=10;
1.238 + pp=(char **)OPENSSL_malloc(ctx->num_dirs_alloced*
1.239 + sizeof(char *));
1.240 + ip=(int *)OPENSSL_malloc(ctx->num_dirs_alloced*
1.241 + sizeof(int));
1.242 + if ((pp == NULL) || (ip == NULL))
1.243 + {
1.244 + X509err(X509_F_ADD_CERT_DIR,ERR_R_MALLOC_FAILURE);
1.245 + return(0);
1.246 + }
1.247 + memcpy(pp,ctx->dirs,(ctx->num_dirs_alloced-10)*
1.248 + sizeof(char *));
1.249 + memcpy(ip,ctx->dirs_type,(ctx->num_dirs_alloced-10)*
1.250 + sizeof(int));
1.251 + if (ctx->dirs != NULL)
1.252 + OPENSSL_free(ctx->dirs);
1.253 + if (ctx->dirs_type != NULL)
1.254 + OPENSSL_free(ctx->dirs_type);
1.255 + ctx->dirs=pp;
1.256 + ctx->dirs_type=ip;
1.257 + }
1.258 + ctx->dirs_type[ctx->num_dirs]=type;
1.259 + ctx->dirs[ctx->num_dirs]=(char *)OPENSSL_malloc((unsigned int)len+1);
1.260 + if (ctx->dirs[ctx->num_dirs] == NULL) return(0);
1.261 + strncpy(ctx->dirs[ctx->num_dirs],ss,(unsigned int)len);
1.262 + ctx->dirs[ctx->num_dirs][len]='\0';
1.263 + ctx->num_dirs++;
1.264 + }
1.265 + if (*p == '\0') break;
1.266 + }
1.267 + return(1);
1.268 + }
1.269 +
1.270 +static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
1.271 + X509_OBJECT *ret)
1.272 + {
1.273 + BY_DIR *ctx;
1.274 + union {
1.275 + struct {
1.276 + X509 st_x509;
1.277 + X509_CINF st_x509_cinf;
1.278 + } x509;
1.279 + struct {
1.280 + X509_CRL st_crl;
1.281 + X509_CRL_INFO st_crl_info;
1.282 + } crl;
1.283 + } data;
1.284 + int ok=0;
1.285 + int i,j,k;
1.286 + unsigned long h;
1.287 + BUF_MEM *b=NULL;
1.288 + struct stat st;
1.289 + X509_OBJECT stmp,*tmp;
1.290 + const char *postfix="";
1.291 +
1.292 + if (name == NULL) return(0);
1.293 +
1.294 + stmp.type=type;
1.295 + if (type == X509_LU_X509)
1.296 + {
1.297 + data.x509.st_x509.cert_info= &data.x509.st_x509_cinf;
1.298 + data.x509.st_x509_cinf.subject=name;
1.299 + stmp.data.x509= &data.x509.st_x509;
1.300 + postfix="";
1.301 + }
1.302 + else if (type == X509_LU_CRL)
1.303 + {
1.304 + data.crl.st_crl.crl= &data.crl.st_crl_info;
1.305 + data.crl.st_crl_info.issuer=name;
1.306 + stmp.data.crl= &data.crl.st_crl;
1.307 + postfix="r";
1.308 + }
1.309 + else
1.310 + {
1.311 + X509err(X509_F_GET_CERT_BY_SUBJECT,X509_R_WRONG_LOOKUP_TYPE);
1.312 + goto finish;
1.313 + }
1.314 +
1.315 + if ((b=BUF_MEM_new()) == NULL)
1.316 + {
1.317 + X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_BUF_LIB);
1.318 + goto finish;
1.319 + }
1.320 +
1.321 + ctx=(BY_DIR *)xl->method_data;
1.322 +
1.323 + h=X509_NAME_hash(name);
1.324 + for (i=0; i<ctx->num_dirs; i++)
1.325 + {
1.326 + j=strlen(ctx->dirs[i])+1+8+6+1+1;
1.327 + if (!BUF_MEM_grow(b,j))
1.328 + {
1.329 + X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_MALLOC_FAILURE);
1.330 + goto finish;
1.331 + }
1.332 + k=0;
1.333 + for (;;)
1.334 + {
1.335 + char c = '/';
1.336 +#ifdef OPENSSL_SYS_VMS
1.337 + c = ctx->dirs[i][strlen(ctx->dirs[i])-1];
1.338 + if (c != ':' && c != '>' && c != ']')
1.339 + {
1.340 + /* If no separator is present, we assume the
1.341 + directory specifier is a logical name, and
1.342 + add a colon. We really should use better
1.343 + VMS routines for merging things like this,
1.344 + but this will do for now...
1.345 + -- Richard Levitte */
1.346 + c = ':';
1.347 + }
1.348 + else
1.349 + {
1.350 + c = '\0';
1.351 + }
1.352 +#endif
1.353 + if (c == '\0')
1.354 + {
1.355 + /* This is special. When c == '\0', no
1.356 + directory separator should be added. */
1.357 + BIO_snprintf(b->data,b->max,
1.358 + "%s%08lx.%s%d",ctx->dirs[i],h,
1.359 + postfix,k);
1.360 + }
1.361 + else
1.362 + {
1.363 + BIO_snprintf(b->data,b->max,
1.364 + "%s%c%08lx.%s%d",ctx->dirs[i],c,h,
1.365 + postfix,k);
1.366 + }
1.367 + k++;
1.368 + if (stat(b->data,&st) < 0)
1.369 + break;
1.370 + /* found one. */
1.371 + if (type == X509_LU_X509)
1.372 + {
1.373 + if ((X509_load_cert_file(xl,b->data,
1.374 + ctx->dirs_type[i])) == 0)
1.375 + break;
1.376 + }
1.377 + else if (type == X509_LU_CRL)
1.378 + {
1.379 + if ((X509_load_crl_file(xl,b->data,
1.380 + ctx->dirs_type[i])) == 0)
1.381 + break;
1.382 + }
1.383 + /* else case will caught higher up */
1.384 + }
1.385 +
1.386 + /* we have added it to the cache so now pull
1.387 + * it out again */
1.388 + CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
1.389 + j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp);
1.390 + if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j);
1.391 + else tmp = NULL;
1.392 + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
1.393 +
1.394 + if (tmp != NULL)
1.395 + {
1.396 + ok=1;
1.397 + ret->type=tmp->type;
1.398 + memcpy(&ret->data,&tmp->data,sizeof(ret->data));
1.399 + /* If we were going to up the reference count,
1.400 + * we would need to do it on a perl 'type'
1.401 + * basis */
1.402 + /* CRYPTO_add(&tmp->data.x509->references,1,
1.403 + CRYPTO_LOCK_X509);*/
1.404 + goto finish;
1.405 + }
1.406 + }
1.407 +finish:
1.408 + if (b != NULL) BUF_MEM_free(b);
1.409 + return(ok);
1.410 + }
1.411 +