10Sstevel@tonic-gate #include <stdio.h>
20Sstevel@tonic-gate #include <stdlib.h>
30Sstevel@tonic-gate #include <string.h>
40Sstevel@tonic-gate
5*2139Sjp161948 #include <openssl/err.h>
60Sstevel@tonic-gate #include <openssl/lhash.h>
70Sstevel@tonic-gate #include <openssl/objects.h>
80Sstevel@tonic-gate #include <openssl/safestack.h>
90Sstevel@tonic-gate #include <openssl/e_os2.h>
100Sstevel@tonic-gate
110Sstevel@tonic-gate /* Later versions of DEC C has started to add lnkage information to certain
120Sstevel@tonic-gate * functions, which makes it tricky to use them as values to regular function
130Sstevel@tonic-gate * pointers. One way is to define a macro that takes care of casting them
140Sstevel@tonic-gate * correctly.
150Sstevel@tonic-gate */
160Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS_DECC
170Sstevel@tonic-gate # define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp
180Sstevel@tonic-gate #else
190Sstevel@tonic-gate # define OPENSSL_strcmp strcmp
200Sstevel@tonic-gate #endif
210Sstevel@tonic-gate
220Sstevel@tonic-gate /* I use the ex_data stuff to manage the identifiers for the obj_name_types
230Sstevel@tonic-gate * that applications may define. I only really use the free function field.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate static LHASH *names_lh=NULL;
260Sstevel@tonic-gate static int names_type_num=OBJ_NAME_TYPE_NUM;
270Sstevel@tonic-gate
280Sstevel@tonic-gate typedef struct name_funcs_st
290Sstevel@tonic-gate {
300Sstevel@tonic-gate unsigned long (*hash_func)(const char *name);
310Sstevel@tonic-gate int (*cmp_func)(const char *a,const char *b);
320Sstevel@tonic-gate void (*free_func)(const char *, int, const char *);
330Sstevel@tonic-gate } NAME_FUNCS;
340Sstevel@tonic-gate
350Sstevel@tonic-gate DECLARE_STACK_OF(NAME_FUNCS)
360Sstevel@tonic-gate IMPLEMENT_STACK_OF(NAME_FUNCS)
370Sstevel@tonic-gate
380Sstevel@tonic-gate static STACK_OF(NAME_FUNCS) *name_funcs_stack;
390Sstevel@tonic-gate
400Sstevel@tonic-gate /* The LHASH callbacks now use the raw "void *" prototypes and do per-variable
410Sstevel@tonic-gate * casting in the functions. This prevents function pointer casting without the
420Sstevel@tonic-gate * need for macro-generated wrapper functions. */
430Sstevel@tonic-gate
440Sstevel@tonic-gate /* static unsigned long obj_name_hash(OBJ_NAME *a); */
450Sstevel@tonic-gate static unsigned long obj_name_hash(const void *a_void);
460Sstevel@tonic-gate /* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
470Sstevel@tonic-gate static int obj_name_cmp(const void *a_void,const void *b_void);
480Sstevel@tonic-gate
OBJ_NAME_init(void)490Sstevel@tonic-gate int OBJ_NAME_init(void)
500Sstevel@tonic-gate {
510Sstevel@tonic-gate if (names_lh != NULL) return(1);
520Sstevel@tonic-gate MemCheck_off();
530Sstevel@tonic-gate names_lh=lh_new(obj_name_hash, obj_name_cmp);
540Sstevel@tonic-gate MemCheck_on();
550Sstevel@tonic-gate return(names_lh != NULL);
560Sstevel@tonic-gate }
570Sstevel@tonic-gate
OBJ_NAME_new_index(unsigned long (* hash_func)(const char *),int (* cmp_func)(const char *,const char *),void (* free_func)(const char *,int,const char *))580Sstevel@tonic-gate int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
590Sstevel@tonic-gate int (*cmp_func)(const char *, const char *),
600Sstevel@tonic-gate void (*free_func)(const char *, int, const char *))
610Sstevel@tonic-gate {
620Sstevel@tonic-gate int ret;
630Sstevel@tonic-gate int i;
640Sstevel@tonic-gate NAME_FUNCS *name_funcs;
650Sstevel@tonic-gate
660Sstevel@tonic-gate if (name_funcs_stack == NULL)
670Sstevel@tonic-gate {
680Sstevel@tonic-gate MemCheck_off();
690Sstevel@tonic-gate name_funcs_stack=sk_NAME_FUNCS_new_null();
700Sstevel@tonic-gate MemCheck_on();
710Sstevel@tonic-gate }
720Sstevel@tonic-gate if ((name_funcs_stack == NULL))
730Sstevel@tonic-gate {
740Sstevel@tonic-gate /* ERROR */
750Sstevel@tonic-gate return(0);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate ret=names_type_num;
780Sstevel@tonic-gate names_type_num++;
790Sstevel@tonic-gate for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate MemCheck_off();
820Sstevel@tonic-gate name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS));
830Sstevel@tonic-gate MemCheck_on();
84*2139Sjp161948 if (!name_funcs)
85*2139Sjp161948 {
86*2139Sjp161948 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX,ERR_R_MALLOC_FAILURE);
87*2139Sjp161948 return(0);
88*2139Sjp161948 }
890Sstevel@tonic-gate name_funcs->hash_func = lh_strhash;
900Sstevel@tonic-gate name_funcs->cmp_func = OPENSSL_strcmp;
910Sstevel@tonic-gate name_funcs->free_func = 0; /* NULL is often declared to
920Sstevel@tonic-gate * ((void *)0), which according
930Sstevel@tonic-gate * to Compaq C is not really
940Sstevel@tonic-gate * compatible with a function
950Sstevel@tonic-gate * pointer. -- Richard Levitte*/
960Sstevel@tonic-gate MemCheck_off();
970Sstevel@tonic-gate sk_NAME_FUNCS_push(name_funcs_stack,name_funcs);
980Sstevel@tonic-gate MemCheck_on();
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
1010Sstevel@tonic-gate if (hash_func != NULL)
1020Sstevel@tonic-gate name_funcs->hash_func = hash_func;
1030Sstevel@tonic-gate if (cmp_func != NULL)
1040Sstevel@tonic-gate name_funcs->cmp_func = cmp_func;
1050Sstevel@tonic-gate if (free_func != NULL)
1060Sstevel@tonic-gate name_funcs->free_func = free_func;
1070Sstevel@tonic-gate return(ret);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */
obj_name_cmp(const void * a_void,const void * b_void)1110Sstevel@tonic-gate static int obj_name_cmp(const void *a_void, const void *b_void)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate int ret;
114*2139Sjp161948 const OBJ_NAME *a = (const OBJ_NAME *)a_void;
115*2139Sjp161948 const OBJ_NAME *b = (const OBJ_NAME *)b_void;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate ret=a->type-b->type;
1180Sstevel@tonic-gate if (ret == 0)
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate if ((name_funcs_stack != NULL)
1210Sstevel@tonic-gate && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate ret=sk_NAME_FUNCS_value(name_funcs_stack,
1240Sstevel@tonic-gate a->type)->cmp_func(a->name,b->name);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate else
1270Sstevel@tonic-gate ret=strcmp(a->name,b->name);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate return(ret);
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /* static unsigned long obj_name_hash(OBJ_NAME *a) */
obj_name_hash(const void * a_void)1330Sstevel@tonic-gate static unsigned long obj_name_hash(const void *a_void)
1340Sstevel@tonic-gate {
1350Sstevel@tonic-gate unsigned long ret;
136*2139Sjp161948 const OBJ_NAME *a = (const OBJ_NAME *)a_void;
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate ret=sk_NAME_FUNCS_value(name_funcs_stack,
1410Sstevel@tonic-gate a->type)->hash_func(a->name);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate else
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate ret=lh_strhash(a->name);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate ret^=a->type;
1480Sstevel@tonic-gate return(ret);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
OBJ_NAME_get(const char * name,int type)1510Sstevel@tonic-gate const char *OBJ_NAME_get(const char *name, int type)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate OBJ_NAME on,*ret;
1540Sstevel@tonic-gate int num=0,alias;
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate if (name == NULL) return(NULL);
1570Sstevel@tonic-gate if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate alias=type&OBJ_NAME_ALIAS;
1600Sstevel@tonic-gate type&= ~OBJ_NAME_ALIAS;
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate on.name=name;
1630Sstevel@tonic-gate on.type=type;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate for (;;)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
1680Sstevel@tonic-gate if (ret == NULL) return(NULL);
1690Sstevel@tonic-gate if ((ret->alias) && !alias)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate if (++num > 10) return(NULL);
1720Sstevel@tonic-gate on.name=ret->data;
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate else
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate return(ret->data);
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate
OBJ_NAME_add(const char * name,int type,const char * data)1810Sstevel@tonic-gate int OBJ_NAME_add(const char *name, int type, const char *data)
1820Sstevel@tonic-gate {
1830Sstevel@tonic-gate OBJ_NAME *onp,*ret;
1840Sstevel@tonic-gate int alias;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate alias=type&OBJ_NAME_ALIAS;
1890Sstevel@tonic-gate type&= ~OBJ_NAME_ALIAS;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));
1920Sstevel@tonic-gate if (onp == NULL)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate /* ERROR */
1950Sstevel@tonic-gate return(0);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate onp->name=name;
1990Sstevel@tonic-gate onp->alias=alias;
2000Sstevel@tonic-gate onp->type=type;
2010Sstevel@tonic-gate onp->data=data;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate ret=(OBJ_NAME *)lh_insert(names_lh,onp);
2040Sstevel@tonic-gate if (ret != NULL)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate /* free things */
2070Sstevel@tonic-gate if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate /* XXX: I'm not sure I understand why the free
2100Sstevel@tonic-gate * function should get three arguments...
2110Sstevel@tonic-gate * -- Richard Levitte
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate sk_NAME_FUNCS_value(name_funcs_stack,
2140Sstevel@tonic-gate ret->type)->free_func(ret->name,ret->type,ret->data);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate OPENSSL_free(ret);
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate else
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate if (lh_error(names_lh))
2210Sstevel@tonic-gate {
2220Sstevel@tonic-gate /* ERROR */
2230Sstevel@tonic-gate return(0);
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate return(1);
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate
OBJ_NAME_remove(const char * name,int type)2290Sstevel@tonic-gate int OBJ_NAME_remove(const char *name, int type)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate OBJ_NAME on,*ret;
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate if (names_lh == NULL) return(0);
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate type&= ~OBJ_NAME_ALIAS;
2360Sstevel@tonic-gate on.name=name;
2370Sstevel@tonic-gate on.type=type;
2380Sstevel@tonic-gate ret=(OBJ_NAME *)lh_delete(names_lh,&on);
2390Sstevel@tonic-gate if (ret != NULL)
2400Sstevel@tonic-gate {
2410Sstevel@tonic-gate /* free things */
2420Sstevel@tonic-gate if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate /* XXX: I'm not sure I understand why the free
2450Sstevel@tonic-gate * function should get three arguments...
2460Sstevel@tonic-gate * -- Richard Levitte
2470Sstevel@tonic-gate */
2480Sstevel@tonic-gate sk_NAME_FUNCS_value(name_funcs_stack,
2490Sstevel@tonic-gate ret->type)->free_func(ret->name,ret->type,ret->data);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate OPENSSL_free(ret);
2520Sstevel@tonic-gate return(1);
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate else
2550Sstevel@tonic-gate return(0);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate struct doall
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate int type;
2610Sstevel@tonic-gate void (*fn)(const OBJ_NAME *,void *arg);
2620Sstevel@tonic-gate void *arg;
2630Sstevel@tonic-gate };
2640Sstevel@tonic-gate
do_all_fn(const OBJ_NAME * name,struct doall * d)2650Sstevel@tonic-gate static void do_all_fn(const OBJ_NAME *name,struct doall *d)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate if(name->type == d->type)
2680Sstevel@tonic-gate d->fn(name,d->arg);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn,const OBJ_NAME *,struct doall *)2710Sstevel@tonic-gate static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *)
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg)
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate struct doall d;
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate d.type=type;
2780Sstevel@tonic-gate d.fn=fn;
2790Sstevel@tonic-gate d.arg=arg;
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate struct doall_sorted
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate int type;
2870Sstevel@tonic-gate int n;
2880Sstevel@tonic-gate const OBJ_NAME **names;
2890Sstevel@tonic-gate };
2900Sstevel@tonic-gate
do_all_sorted_fn(const OBJ_NAME * name,void * d_)2910Sstevel@tonic-gate static void do_all_sorted_fn(const OBJ_NAME *name,void *d_)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate struct doall_sorted *d=d_;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate if(name->type != d->type)
2960Sstevel@tonic-gate return;
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate d->names[d->n++]=name;
2990Sstevel@tonic-gate }
3000Sstevel@tonic-gate
do_all_sorted_cmp(const void * n1_,const void * n2_)3010Sstevel@tonic-gate static int do_all_sorted_cmp(const void *n1_,const void *n2_)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate const OBJ_NAME * const *n1=n1_;
3040Sstevel@tonic-gate const OBJ_NAME * const *n2=n2_;
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate return strcmp((*n1)->name,(*n2)->name);
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate
OBJ_NAME_do_all_sorted(int type,void (* fn)(const OBJ_NAME *,void * arg),void * arg)3090Sstevel@tonic-gate void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
3100Sstevel@tonic-gate void *arg)
3110Sstevel@tonic-gate {
3120Sstevel@tonic-gate struct doall_sorted d;
3130Sstevel@tonic-gate int n;
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate d.type=type;
3160Sstevel@tonic-gate d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names);
3170Sstevel@tonic-gate d.n=0;
3180Sstevel@tonic-gate OBJ_NAME_do_all(type,do_all_sorted_fn,&d);
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp);
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate for(n=0 ; n < d.n ; ++n)
3230Sstevel@tonic-gate fn(d.names[n],arg);
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate OPENSSL_free((void *)d.names);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate static int free_type;
3290Sstevel@tonic-gate
names_lh_free(OBJ_NAME * onp)3300Sstevel@tonic-gate static void names_lh_free(OBJ_NAME *onp)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate if(onp == NULL)
3330Sstevel@tonic-gate return;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate if ((free_type < 0) || (free_type == onp->type))
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate OBJ_NAME_remove(onp->name,onp->type);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
IMPLEMENT_LHASH_DOALL_FN(names_lh_free,OBJ_NAME *)3410Sstevel@tonic-gate static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *)
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate static void name_funcs_free(NAME_FUNCS *ptr)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate OPENSSL_free(ptr);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate
OBJ_NAME_cleanup(int type)3480Sstevel@tonic-gate void OBJ_NAME_cleanup(int type)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate unsigned long down_load;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate if (names_lh == NULL) return;
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate free_type=type;
3550Sstevel@tonic-gate down_load=names_lh->down_load;
3560Sstevel@tonic-gate names_lh->down_load=0;
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
3590Sstevel@tonic-gate if (type < 0)
3600Sstevel@tonic-gate {
3610Sstevel@tonic-gate lh_free(names_lh);
3620Sstevel@tonic-gate sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
3630Sstevel@tonic-gate names_lh=NULL;
3640Sstevel@tonic-gate name_funcs_stack = NULL;
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate else
3670Sstevel@tonic-gate names_lh->down_load=down_load;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
370