ssl/libcrypto/src/crypto/objects/o_names.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /*
       
     2 Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     3 
       
     4 Redistribution and use in source and binary forms, with or without 
       
     5 modification, are permitted provided that the following conditions are met:
       
     6 
       
     7 * Redistributions of source code must retain the above copyright notice, this 
       
     8   list of conditions and the following disclaimer.
       
     9 * Redistributions in binary form must reproduce the above copyright notice, 
       
    10   this list of conditions and the following disclaimer in the documentation 
       
    11   and/or other materials provided with the distribution.
       
    12 * Neither the name of Nokia Corporation nor the names of its contributors 
       
    13   may be used to endorse or promote products derived from this software 
       
    14   without specific prior written permission.
       
    15 
       
    16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
       
    17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
       
    18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
       
    19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
       
    20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
       
    21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
       
    22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
       
    23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
       
    24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
       
    25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    26 
       
    27 Description:
       
    28 */
       
    29 
       
    30 #include <stdio.h>
       
    31 #include <stdlib.h>
       
    32 #include <string.h>
       
    33 
       
    34 #include <openssl/err.h>
       
    35 #include <openssl/lhash.h>
       
    36 #include <openssl/objects.h>
       
    37 #include <openssl/safestack.h>
       
    38 #include <openssl/e_os2.h>
       
    39 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
       
    40 #include "libcrypto_wsd_macros.h"
       
    41 #include "libcrypto_wsd.h"
       
    42 #endif
       
    43 
       
    44 
       
    45 /* Later versions of DEC C has started to add lnkage information to certain
       
    46  * functions, which makes it tricky to use them as values to regular function
       
    47  * pointers.  One way is to define a macro that takes care of casting them
       
    48  * correctly.
       
    49  */
       
    50 #ifdef OPENSSL_SYS_VMS_DECC
       
    51 # define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp
       
    52 #else
       
    53 # define OPENSSL_strcmp strcmp
       
    54 #endif
       
    55 
       
    56 /* I use the ex_data stuff to manage the identifiers for the obj_name_types
       
    57  * that applications may define.  I only really use the free function field.
       
    58  */
       
    59 #ifndef EMULATOR 
       
    60 static LHASH *names_lh=NULL;
       
    61 static int names_type_num=OBJ_NAME_TYPE_NUM;
       
    62 #else
       
    63 GET_STATIC_VAR_FROM_TLS(names_lh,o_names,LHASH *)
       
    64 #define names_lh (*GET_WSD_VAR_NAME(names_lh,o_names, s)())
       
    65 
       
    66 GET_STATIC_VAR_FROM_TLS(names_type_num,o_names,int)
       
    67 #define names_type_num (*GET_WSD_VAR_NAME(names_type_num,o_names, s)())
       
    68 
       
    69 #endif
       
    70 
       
    71 typedef struct name_funcs_st
       
    72 	{
       
    73 	unsigned long (*hash_func)(const char *name);
       
    74 	int (*cmp_func)(const char *a,const char *b);
       
    75 	void (*free_func)(const char *, int, const char *);
       
    76 	} NAME_FUNCS;
       
    77 
       
    78 DECLARE_STACK_OF(NAME_FUNCS)
       
    79 IMPLEMENT_STACK_OF(NAME_FUNCS)
       
    80 
       
    81 #ifndef EMULATOR
       
    82 static STACK_OF(NAME_FUNCS) *name_funcs_stack;
       
    83 #else
       
    84 GET_STATIC_VAR_FROM_TLS(name_funcs_stack,o_names,STACK_OF(NAME_FUNCS)*)
       
    85 #define name_funcs_stack (*GET_WSD_VAR_NAME(name_funcs_stack,o_names, s)())
       
    86 #endif
       
    87 
       
    88 /* The LHASH callbacks now use the raw "void *" prototypes and do per-variable
       
    89  * casting in the functions. This prevents function pointer casting without the
       
    90  * need for macro-generated wrapper functions. */
       
    91 
       
    92 /* static unsigned long obj_name_hash(OBJ_NAME *a); */
       
    93 static unsigned long obj_name_hash(const void *a_void);
       
    94 /* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
       
    95 static int obj_name_cmp(const void *a_void,const void *b_void);
       
    96 
       
    97 EXPORT_C int OBJ_NAME_init(void)
       
    98 	{
       
    99 	if (names_lh != NULL) return(1);
       
   100 	MemCheck_off();
       
   101 	names_lh=lh_new(obj_name_hash, obj_name_cmp);
       
   102 	MemCheck_on();
       
   103 	return(names_lh != NULL);
       
   104 	}
       
   105 
       
   106 EXPORT_C int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
       
   107 	int (*cmp_func)(const char *, const char *),
       
   108 	void (*free_func)(const char *, int, const char *))
       
   109 	{
       
   110 	int ret;
       
   111 	int i;
       
   112 	NAME_FUNCS *name_funcs;
       
   113 
       
   114 	if (name_funcs_stack == NULL)
       
   115 		{
       
   116 		MemCheck_off();
       
   117 		name_funcs_stack=sk_NAME_FUNCS_new_null();
       
   118 		MemCheck_on();
       
   119 		}
       
   120 	if ((name_funcs_stack == NULL))
       
   121 		{
       
   122 		/* ERROR */
       
   123 		return(0);
       
   124 		}
       
   125 	ret=names_type_num;
       
   126 	names_type_num++;
       
   127 	for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++)
       
   128 		{
       
   129 		MemCheck_off();
       
   130 		name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS));
       
   131 		MemCheck_on();
       
   132 		if (!name_funcs)
       
   133 			{
       
   134 			OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX,ERR_R_MALLOC_FAILURE);
       
   135 			return(0);
       
   136 			}
       
   137 		name_funcs->hash_func = lh_strhash;
       
   138 		name_funcs->cmp_func = OPENSSL_strcmp;
       
   139 		name_funcs->free_func = 0; /* NULL is often declared to
       
   140 						* ((void *)0), which according
       
   141 						* to Compaq C is not really
       
   142 						* compatible with a function
       
   143 						* pointer.	-- Richard Levitte*/
       
   144 		MemCheck_off();
       
   145 		sk_NAME_FUNCS_push(name_funcs_stack,name_funcs);
       
   146 		MemCheck_on();
       
   147 		}
       
   148 	name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
       
   149 	if (hash_func != NULL)
       
   150 		name_funcs->hash_func = hash_func;
       
   151 	if (cmp_func != NULL)
       
   152 		name_funcs->cmp_func = cmp_func;
       
   153 	if (free_func != NULL)
       
   154 		name_funcs->free_func = free_func;
       
   155 	return(ret);
       
   156 	}
       
   157 
       
   158 /* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */
       
   159 static int obj_name_cmp(const void *a_void, const void *b_void)
       
   160 	{
       
   161 	int ret;
       
   162 	const OBJ_NAME *a = (const OBJ_NAME *)a_void;
       
   163 	const OBJ_NAME *b = (const OBJ_NAME *)b_void;
       
   164 
       
   165 	ret=a->type-b->type;
       
   166 	if (ret == 0)
       
   167 		{
       
   168 		if ((name_funcs_stack != NULL)
       
   169 			&& (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
       
   170 			{
       
   171 			ret=sk_NAME_FUNCS_value(name_funcs_stack,
       
   172 				a->type)->cmp_func(a->name,b->name);
       
   173 			}
       
   174 		else
       
   175 			ret=strcmp(a->name,b->name);
       
   176 		}
       
   177 	return(ret);
       
   178 	}
       
   179 
       
   180 /* static unsigned long obj_name_hash(OBJ_NAME *a) */
       
   181 static unsigned long obj_name_hash(const void *a_void)
       
   182 	{
       
   183 	unsigned long ret;
       
   184 	const OBJ_NAME *a = (const OBJ_NAME *)a_void;
       
   185 
       
   186 	if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
       
   187 		{
       
   188 		ret=sk_NAME_FUNCS_value(name_funcs_stack,
       
   189 			a->type)->hash_func(a->name);
       
   190 		}
       
   191 	else
       
   192 		{
       
   193 		ret=lh_strhash(a->name);
       
   194 		}
       
   195 	ret^=a->type;
       
   196 	return(ret);
       
   197 	}
       
   198 
       
   199 EXPORT_C const char *OBJ_NAME_get(const char *name, int type)
       
   200 	{
       
   201 	OBJ_NAME on,*ret;
       
   202 	int num=0,alias;
       
   203 
       
   204 	if (name == NULL) return(NULL);
       
   205 	if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
       
   206 
       
   207 	alias=type&OBJ_NAME_ALIAS;
       
   208 	type&= ~OBJ_NAME_ALIAS;
       
   209 
       
   210 	on.name=name;
       
   211 	on.type=type;
       
   212 
       
   213 	for (;;)
       
   214 	{
       
   215 		ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
       
   216 		if (ret == NULL) return(NULL);
       
   217 		if ((ret->alias) && !alias)
       
   218 			{
       
   219 			if (++num > 10) return(NULL);
       
   220 			on.name=ret->data;
       
   221 			}
       
   222 		else
       
   223 			{
       
   224 			return(ret->data);
       
   225 			}
       
   226 		}
       
   227 	}
       
   228 
       
   229 EXPORT_C int OBJ_NAME_add(const char *name, int type, const char *data)
       
   230 	{
       
   231 	OBJ_NAME *onp,*ret;
       
   232 	int alias;
       
   233 
       
   234 	if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
       
   235 
       
   236 	alias=type&OBJ_NAME_ALIAS;
       
   237 	type&= ~OBJ_NAME_ALIAS;
       
   238 
       
   239 	onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));
       
   240 	if (onp == NULL)
       
   241 		{
       
   242 		/* ERROR */
       
   243 		return(0);
       
   244 		}
       
   245 
       
   246 	onp->name=name;
       
   247 	onp->alias=alias;
       
   248 	onp->type=type;
       
   249 	onp->data=data;
       
   250 
       
   251 	ret=(OBJ_NAME *)lh_insert(names_lh,onp);
       
   252 	if (ret != NULL)
       
   253 		{
       
   254 		/* free things */
       
   255 		if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
       
   256 			{
       
   257 			/* XXX: I'm not sure I understand why the free
       
   258 			 * function should get three arguments...
       
   259 			 * -- Richard Levitte
       
   260 			 */
       
   261 			sk_NAME_FUNCS_value(name_funcs_stack,
       
   262 				ret->type)->free_func(ret->name,ret->type,ret->data);
       
   263 			}
       
   264 		OPENSSL_free(ret);
       
   265 		}
       
   266 	else
       
   267 		{
       
   268 		if (lh_error(names_lh))
       
   269 			{
       
   270 			/* ERROR */
       
   271 			return(0);
       
   272 			}
       
   273 		}
       
   274 	return(1);
       
   275 	}
       
   276 
       
   277 EXPORT_C int OBJ_NAME_remove(const char *name, int type)
       
   278 	{
       
   279 	OBJ_NAME on,*ret;
       
   280 
       
   281 	if (names_lh == NULL) return(0);
       
   282 
       
   283 	type&= ~OBJ_NAME_ALIAS;
       
   284 	on.name=name;
       
   285 	on.type=type;
       
   286 	ret=(OBJ_NAME *)lh_delete(names_lh,&on);
       
   287 	if (ret != NULL)
       
   288 		{
       
   289 		/* free things */
       
   290 		if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
       
   291 			{
       
   292 			/* XXX: I'm not sure I understand why the free
       
   293 			 * function should get three arguments...
       
   294 			 * -- Richard Levitte
       
   295 			 */
       
   296 			sk_NAME_FUNCS_value(name_funcs_stack,
       
   297 				ret->type)->free_func(ret->name,ret->type,ret->data);
       
   298 			}
       
   299 		OPENSSL_free(ret);
       
   300 		return(1);
       
   301 		}
       
   302 	else
       
   303 		return(0);
       
   304 	}
       
   305 
       
   306 struct doall
       
   307 	{
       
   308 	int type;
       
   309 	void (*fn)(const OBJ_NAME *,void *arg);
       
   310 	void *arg;
       
   311 	};
       
   312 
       
   313 static void do_all_fn(const OBJ_NAME *name,struct doall *d)
       
   314 	{
       
   315 	if(name->type == d->type)
       
   316 		d->fn(name,d->arg);
       
   317 	}
       
   318 
       
   319 static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *)
       
   320 
       
   321 EXPORT_C void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg)
       
   322 	{
       
   323 	struct doall d;
       
   324 
       
   325 	d.type=type;
       
   326 	d.fn=fn;
       
   327 	d.arg=arg;
       
   328 
       
   329 	lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d);
       
   330 	}
       
   331 
       
   332 struct doall_sorted
       
   333 	{
       
   334 	int type;
       
   335 	int n;
       
   336 	const OBJ_NAME **names;
       
   337 	};
       
   338 
       
   339 static void do_all_sorted_fn(const OBJ_NAME *name,void *d_)
       
   340 	{
       
   341 	struct doall_sorted *d=d_;
       
   342 
       
   343 	if(name->type != d->type)
       
   344 		return;
       
   345 
       
   346 	d->names[d->n++]=name;
       
   347 	}
       
   348 
       
   349 static int do_all_sorted_cmp(const void *n1_,const void *n2_)
       
   350 	{
       
   351 	const OBJ_NAME * const *n1=n1_;
       
   352 	const OBJ_NAME * const *n2=n2_;
       
   353 
       
   354 	return strcmp((*n1)->name,(*n2)->name);
       
   355 	}
       
   356 
       
   357 EXPORT_C void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
       
   358 				void *arg)
       
   359 	{
       
   360 	struct doall_sorted d;
       
   361 	int n;
       
   362 
       
   363 	d.type=type;
       
   364 	d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names);
       
   365 #ifdef SYMBIAN	
       
   366 	if(d.names==NULL)
       
   367 	{
       
   368 		return;
       
   369   }	
       
   370 #endif  
       
   371 	d.n=0;
       
   372 	OBJ_NAME_do_all(type,do_all_sorted_fn,&d);
       
   373 
       
   374 	qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp);
       
   375 
       
   376 	for(n=0 ; n < d.n ; ++n)
       
   377 		fn(d.names[n],arg);
       
   378 
       
   379 	OPENSSL_free((void *)d.names);
       
   380 	}
       
   381 
       
   382 #ifndef EMULATOR
       
   383 static int free_type;
       
   384 #else
       
   385 GET_STATIC_VAR_FROM_TLS(free_type,o_names,int)
       
   386 #define free_type (*GET_WSD_VAR_NAME(free_type,o_names, s)())
       
   387 #endif
       
   388 
       
   389 static void names_lh_free(OBJ_NAME *onp)
       
   390 {
       
   391 	if(onp == NULL)
       
   392 		return;
       
   393 
       
   394 	if ((free_type < 0) || (free_type == onp->type))
       
   395 		{
       
   396 		OBJ_NAME_remove(onp->name,onp->type);
       
   397 		}
       
   398 	}
       
   399 
       
   400 static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *)
       
   401 
       
   402 static void name_funcs_free(NAME_FUNCS *ptr)
       
   403 	{
       
   404 	OPENSSL_free(ptr);
       
   405 	}
       
   406 
       
   407 EXPORT_C void OBJ_NAME_cleanup(int type)
       
   408 	{
       
   409 	unsigned long down_load;
       
   410 
       
   411 	if (names_lh == NULL) return;
       
   412 
       
   413 	free_type=type;
       
   414 	down_load=names_lh->down_load;
       
   415 	names_lh->down_load=0;
       
   416 
       
   417 	lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
       
   418 	if (type < 0)
       
   419 		{
       
   420 		lh_free(names_lh);
       
   421 		sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
       
   422 		names_lh=NULL;
       
   423 		name_funcs_stack = NULL;
       
   424 		}
       
   425 	else
       
   426 		names_lh->down_load=down_load;
       
   427 	}
       
   428