1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/objects/o_names.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,428 @@
1.4 +/*
1.5 +Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
1.6 +
1.7 +Redistribution and use in source and binary forms, with or without
1.8 +modification, are permitted provided that the following conditions are met:
1.9 +
1.10 +* Redistributions of source code must retain the above copyright notice, this
1.11 + list of conditions and the following disclaimer.
1.12 +* Redistributions in binary form must reproduce the above copyright notice,
1.13 + this list of conditions and the following disclaimer in the documentation
1.14 + and/or other materials provided with the distribution.
1.15 +* Neither the name of Nokia Corporation nor the names of its contributors
1.16 + may be used to endorse or promote products derived from this software
1.17 + without specific prior written permission.
1.18 +
1.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.29 +
1.30 +Description:
1.31 +*/
1.32 +
1.33 +#include <stdio.h>
1.34 +#include <stdlib.h>
1.35 +#include <string.h>
1.36 +
1.37 +#include <openssl/err.h>
1.38 +#include <openssl/lhash.h>
1.39 +#include <openssl/objects.h>
1.40 +#include <openssl/safestack.h>
1.41 +#include <openssl/e_os2.h>
1.42 +#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
1.43 +#include "libcrypto_wsd_macros.h"
1.44 +#include "libcrypto_wsd.h"
1.45 +#endif
1.46 +
1.47 +
1.48 +/* Later versions of DEC C has started to add lnkage information to certain
1.49 + * functions, which makes it tricky to use them as values to regular function
1.50 + * pointers. One way is to define a macro that takes care of casting them
1.51 + * correctly.
1.52 + */
1.53 +#ifdef OPENSSL_SYS_VMS_DECC
1.54 +# define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp
1.55 +#else
1.56 +# define OPENSSL_strcmp strcmp
1.57 +#endif
1.58 +
1.59 +/* I use the ex_data stuff to manage the identifiers for the obj_name_types
1.60 + * that applications may define. I only really use the free function field.
1.61 + */
1.62 +#ifndef EMULATOR
1.63 +static LHASH *names_lh=NULL;
1.64 +static int names_type_num=OBJ_NAME_TYPE_NUM;
1.65 +#else
1.66 +GET_STATIC_VAR_FROM_TLS(names_lh,o_names,LHASH *)
1.67 +#define names_lh (*GET_WSD_VAR_NAME(names_lh,o_names, s)())
1.68 +
1.69 +GET_STATIC_VAR_FROM_TLS(names_type_num,o_names,int)
1.70 +#define names_type_num (*GET_WSD_VAR_NAME(names_type_num,o_names, s)())
1.71 +
1.72 +#endif
1.73 +
1.74 +typedef struct name_funcs_st
1.75 + {
1.76 + unsigned long (*hash_func)(const char *name);
1.77 + int (*cmp_func)(const char *a,const char *b);
1.78 + void (*free_func)(const char *, int, const char *);
1.79 + } NAME_FUNCS;
1.80 +
1.81 +DECLARE_STACK_OF(NAME_FUNCS)
1.82 +IMPLEMENT_STACK_OF(NAME_FUNCS)
1.83 +
1.84 +#ifndef EMULATOR
1.85 +static STACK_OF(NAME_FUNCS) *name_funcs_stack;
1.86 +#else
1.87 +GET_STATIC_VAR_FROM_TLS(name_funcs_stack,o_names,STACK_OF(NAME_FUNCS)*)
1.88 +#define name_funcs_stack (*GET_WSD_VAR_NAME(name_funcs_stack,o_names, s)())
1.89 +#endif
1.90 +
1.91 +/* The LHASH callbacks now use the raw "void *" prototypes and do per-variable
1.92 + * casting in the functions. This prevents function pointer casting without the
1.93 + * need for macro-generated wrapper functions. */
1.94 +
1.95 +/* static unsigned long obj_name_hash(OBJ_NAME *a); */
1.96 +static unsigned long obj_name_hash(const void *a_void);
1.97 +/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
1.98 +static int obj_name_cmp(const void *a_void,const void *b_void);
1.99 +
1.100 +EXPORT_C int OBJ_NAME_init(void)
1.101 + {
1.102 + if (names_lh != NULL) return(1);
1.103 + MemCheck_off();
1.104 + names_lh=lh_new(obj_name_hash, obj_name_cmp);
1.105 + MemCheck_on();
1.106 + return(names_lh != NULL);
1.107 + }
1.108 +
1.109 +EXPORT_C int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
1.110 + int (*cmp_func)(const char *, const char *),
1.111 + void (*free_func)(const char *, int, const char *))
1.112 + {
1.113 + int ret;
1.114 + int i;
1.115 + NAME_FUNCS *name_funcs;
1.116 +
1.117 + if (name_funcs_stack == NULL)
1.118 + {
1.119 + MemCheck_off();
1.120 + name_funcs_stack=sk_NAME_FUNCS_new_null();
1.121 + MemCheck_on();
1.122 + }
1.123 + if ((name_funcs_stack == NULL))
1.124 + {
1.125 + /* ERROR */
1.126 + return(0);
1.127 + }
1.128 + ret=names_type_num;
1.129 + names_type_num++;
1.130 + for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++)
1.131 + {
1.132 + MemCheck_off();
1.133 + name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS));
1.134 + MemCheck_on();
1.135 + if (!name_funcs)
1.136 + {
1.137 + OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX,ERR_R_MALLOC_FAILURE);
1.138 + return(0);
1.139 + }
1.140 + name_funcs->hash_func = lh_strhash;
1.141 + name_funcs->cmp_func = OPENSSL_strcmp;
1.142 + name_funcs->free_func = 0; /* NULL is often declared to
1.143 + * ((void *)0), which according
1.144 + * to Compaq C is not really
1.145 + * compatible with a function
1.146 + * pointer. -- Richard Levitte*/
1.147 + MemCheck_off();
1.148 + sk_NAME_FUNCS_push(name_funcs_stack,name_funcs);
1.149 + MemCheck_on();
1.150 + }
1.151 + name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
1.152 + if (hash_func != NULL)
1.153 + name_funcs->hash_func = hash_func;
1.154 + if (cmp_func != NULL)
1.155 + name_funcs->cmp_func = cmp_func;
1.156 + if (free_func != NULL)
1.157 + name_funcs->free_func = free_func;
1.158 + return(ret);
1.159 + }
1.160 +
1.161 +/* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */
1.162 +static int obj_name_cmp(const void *a_void, const void *b_void)
1.163 + {
1.164 + int ret;
1.165 + const OBJ_NAME *a = (const OBJ_NAME *)a_void;
1.166 + const OBJ_NAME *b = (const OBJ_NAME *)b_void;
1.167 +
1.168 + ret=a->type-b->type;
1.169 + if (ret == 0)
1.170 + {
1.171 + if ((name_funcs_stack != NULL)
1.172 + && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
1.173 + {
1.174 + ret=sk_NAME_FUNCS_value(name_funcs_stack,
1.175 + a->type)->cmp_func(a->name,b->name);
1.176 + }
1.177 + else
1.178 + ret=strcmp(a->name,b->name);
1.179 + }
1.180 + return(ret);
1.181 + }
1.182 +
1.183 +/* static unsigned long obj_name_hash(OBJ_NAME *a) */
1.184 +static unsigned long obj_name_hash(const void *a_void)
1.185 + {
1.186 + unsigned long ret;
1.187 + const OBJ_NAME *a = (const OBJ_NAME *)a_void;
1.188 +
1.189 + if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
1.190 + {
1.191 + ret=sk_NAME_FUNCS_value(name_funcs_stack,
1.192 + a->type)->hash_func(a->name);
1.193 + }
1.194 + else
1.195 + {
1.196 + ret=lh_strhash(a->name);
1.197 + }
1.198 + ret^=a->type;
1.199 + return(ret);
1.200 + }
1.201 +
1.202 +EXPORT_C const char *OBJ_NAME_get(const char *name, int type)
1.203 + {
1.204 + OBJ_NAME on,*ret;
1.205 + int num=0,alias;
1.206 +
1.207 + if (name == NULL) return(NULL);
1.208 + if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
1.209 +
1.210 + alias=type&OBJ_NAME_ALIAS;
1.211 + type&= ~OBJ_NAME_ALIAS;
1.212 +
1.213 + on.name=name;
1.214 + on.type=type;
1.215 +
1.216 + for (;;)
1.217 + {
1.218 + ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
1.219 + if (ret == NULL) return(NULL);
1.220 + if ((ret->alias) && !alias)
1.221 + {
1.222 + if (++num > 10) return(NULL);
1.223 + on.name=ret->data;
1.224 + }
1.225 + else
1.226 + {
1.227 + return(ret->data);
1.228 + }
1.229 + }
1.230 + }
1.231 +
1.232 +EXPORT_C int OBJ_NAME_add(const char *name, int type, const char *data)
1.233 + {
1.234 + OBJ_NAME *onp,*ret;
1.235 + int alias;
1.236 +
1.237 + if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
1.238 +
1.239 + alias=type&OBJ_NAME_ALIAS;
1.240 + type&= ~OBJ_NAME_ALIAS;
1.241 +
1.242 + onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));
1.243 + if (onp == NULL)
1.244 + {
1.245 + /* ERROR */
1.246 + return(0);
1.247 + }
1.248 +
1.249 + onp->name=name;
1.250 + onp->alias=alias;
1.251 + onp->type=type;
1.252 + onp->data=data;
1.253 +
1.254 + ret=(OBJ_NAME *)lh_insert(names_lh,onp);
1.255 + if (ret != NULL)
1.256 + {
1.257 + /* free things */
1.258 + if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
1.259 + {
1.260 + /* XXX: I'm not sure I understand why the free
1.261 + * function should get three arguments...
1.262 + * -- Richard Levitte
1.263 + */
1.264 + sk_NAME_FUNCS_value(name_funcs_stack,
1.265 + ret->type)->free_func(ret->name,ret->type,ret->data);
1.266 + }
1.267 + OPENSSL_free(ret);
1.268 + }
1.269 + else
1.270 + {
1.271 + if (lh_error(names_lh))
1.272 + {
1.273 + /* ERROR */
1.274 + return(0);
1.275 + }
1.276 + }
1.277 + return(1);
1.278 + }
1.279 +
1.280 +EXPORT_C int OBJ_NAME_remove(const char *name, int type)
1.281 + {
1.282 + OBJ_NAME on,*ret;
1.283 +
1.284 + if (names_lh == NULL) return(0);
1.285 +
1.286 + type&= ~OBJ_NAME_ALIAS;
1.287 + on.name=name;
1.288 + on.type=type;
1.289 + ret=(OBJ_NAME *)lh_delete(names_lh,&on);
1.290 + if (ret != NULL)
1.291 + {
1.292 + /* free things */
1.293 + if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
1.294 + {
1.295 + /* XXX: I'm not sure I understand why the free
1.296 + * function should get three arguments...
1.297 + * -- Richard Levitte
1.298 + */
1.299 + sk_NAME_FUNCS_value(name_funcs_stack,
1.300 + ret->type)->free_func(ret->name,ret->type,ret->data);
1.301 + }
1.302 + OPENSSL_free(ret);
1.303 + return(1);
1.304 + }
1.305 + else
1.306 + return(0);
1.307 + }
1.308 +
1.309 +struct doall
1.310 + {
1.311 + int type;
1.312 + void (*fn)(const OBJ_NAME *,void *arg);
1.313 + void *arg;
1.314 + };
1.315 +
1.316 +static void do_all_fn(const OBJ_NAME *name,struct doall *d)
1.317 + {
1.318 + if(name->type == d->type)
1.319 + d->fn(name,d->arg);
1.320 + }
1.321 +
1.322 +static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *)
1.323 +
1.324 +EXPORT_C void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg)
1.325 + {
1.326 + struct doall d;
1.327 +
1.328 + d.type=type;
1.329 + d.fn=fn;
1.330 + d.arg=arg;
1.331 +
1.332 + lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d);
1.333 + }
1.334 +
1.335 +struct doall_sorted
1.336 + {
1.337 + int type;
1.338 + int n;
1.339 + const OBJ_NAME **names;
1.340 + };
1.341 +
1.342 +static void do_all_sorted_fn(const OBJ_NAME *name,void *d_)
1.343 + {
1.344 + struct doall_sorted *d=d_;
1.345 +
1.346 + if(name->type != d->type)
1.347 + return;
1.348 +
1.349 + d->names[d->n++]=name;
1.350 + }
1.351 +
1.352 +static int do_all_sorted_cmp(const void *n1_,const void *n2_)
1.353 + {
1.354 + const OBJ_NAME * const *n1=n1_;
1.355 + const OBJ_NAME * const *n2=n2_;
1.356 +
1.357 + return strcmp((*n1)->name,(*n2)->name);
1.358 + }
1.359 +
1.360 +EXPORT_C void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
1.361 + void *arg)
1.362 + {
1.363 + struct doall_sorted d;
1.364 + int n;
1.365 +
1.366 + d.type=type;
1.367 + d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names);
1.368 +#ifdef SYMBIAN
1.369 + if(d.names==NULL)
1.370 + {
1.371 + return;
1.372 + }
1.373 +#endif
1.374 + d.n=0;
1.375 + OBJ_NAME_do_all(type,do_all_sorted_fn,&d);
1.376 +
1.377 + qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp);
1.378 +
1.379 + for(n=0 ; n < d.n ; ++n)
1.380 + fn(d.names[n],arg);
1.381 +
1.382 + OPENSSL_free((void *)d.names);
1.383 + }
1.384 +
1.385 +#ifndef EMULATOR
1.386 +static int free_type;
1.387 +#else
1.388 +GET_STATIC_VAR_FROM_TLS(free_type,o_names,int)
1.389 +#define free_type (*GET_WSD_VAR_NAME(free_type,o_names, s)())
1.390 +#endif
1.391 +
1.392 +static void names_lh_free(OBJ_NAME *onp)
1.393 +{
1.394 + if(onp == NULL)
1.395 + return;
1.396 +
1.397 + if ((free_type < 0) || (free_type == onp->type))
1.398 + {
1.399 + OBJ_NAME_remove(onp->name,onp->type);
1.400 + }
1.401 + }
1.402 +
1.403 +static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *)
1.404 +
1.405 +static void name_funcs_free(NAME_FUNCS *ptr)
1.406 + {
1.407 + OPENSSL_free(ptr);
1.408 + }
1.409 +
1.410 +EXPORT_C void OBJ_NAME_cleanup(int type)
1.411 + {
1.412 + unsigned long down_load;
1.413 +
1.414 + if (names_lh == NULL) return;
1.415 +
1.416 + free_type=type;
1.417 + down_load=names_lh->down_load;
1.418 + names_lh->down_load=0;
1.419 +
1.420 + lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
1.421 + if (type < 0)
1.422 + {
1.423 + lh_free(names_lh);
1.424 + sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
1.425 + names_lh=NULL;
1.426 + name_funcs_stack = NULL;
1.427 + }
1.428 + else
1.429 + names_lh->down_load=down_load;
1.430 + }
1.431 +