diff options
Diffstat (limited to 'src/lib/libcrypto/objects/o_names.c')
-rw-r--r-- | src/lib/libcrypto/objects/o_names.c | 229 |
1 files changed, 175 insertions, 54 deletions
diff --git a/src/lib/libcrypto/objects/o_names.c b/src/lib/libcrypto/objects/o_names.c index 4da5e45b9c..b4453b4a98 100644 --- a/src/lib/libcrypto/objects/o_names.c +++ b/src/lib/libcrypto/objects/o_names.c | |||
@@ -4,78 +4,119 @@ | |||
4 | 4 | ||
5 | #include <openssl/lhash.h> | 5 | #include <openssl/lhash.h> |
6 | #include <openssl/objects.h> | 6 | #include <openssl/objects.h> |
7 | #include <openssl/safestack.h> | ||
8 | #include <openssl/e_os2.h> | ||
9 | |||
10 | /* Later versions of DEC C has started to add lnkage information to certain | ||
11 | * functions, which makes it tricky to use them as values to regular function | ||
12 | * pointers. One way is to define a macro that takes care of casting them | ||
13 | * correctly. | ||
14 | */ | ||
15 | #ifdef OPENSSL_SYS_VMS_DECC | ||
16 | # define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp | ||
17 | #else | ||
18 | # define OPENSSL_strcmp strcmp | ||
19 | #endif | ||
7 | 20 | ||
8 | /* I use the ex_data stuff to manage the identifiers for the obj_name_types | 21 | /* I use the ex_data stuff to manage the identifiers for the obj_name_types |
9 | * that applications may define. I only really use the free function field. | 22 | * that applications may define. I only really use the free function field. |
10 | */ | 23 | */ |
11 | static LHASH *names_lh=NULL; | 24 | static LHASH *names_lh=NULL; |
12 | static int names_type_num=OBJ_NAME_TYPE_NUM; | 25 | static int names_type_num=OBJ_NAME_TYPE_NUM; |
13 | static STACK *names_cmp=NULL; | ||
14 | static STACK *names_hash=NULL; | ||
15 | static STACK *names_free=NULL; | ||
16 | 26 | ||
17 | static unsigned long obj_name_hash(OBJ_NAME *a); | 27 | typedef struct name_funcs_st |
18 | static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); | 28 | { |
29 | unsigned long (*hash_func)(const char *name); | ||
30 | int (*cmp_func)(const char *a,const char *b); | ||
31 | void (*free_func)(const char *, int, const char *); | ||
32 | } NAME_FUNCS; | ||
33 | |||
34 | DECLARE_STACK_OF(NAME_FUNCS) | ||
35 | IMPLEMENT_STACK_OF(NAME_FUNCS) | ||
36 | |||
37 | static STACK_OF(NAME_FUNCS) *name_funcs_stack; | ||
38 | |||
39 | /* The LHASH callbacks now use the raw "void *" prototypes and do per-variable | ||
40 | * casting in the functions. This prevents function pointer casting without the | ||
41 | * need for macro-generated wrapper functions. */ | ||
42 | |||
43 | /* static unsigned long obj_name_hash(OBJ_NAME *a); */ | ||
44 | static unsigned long obj_name_hash(const void *a_void); | ||
45 | /* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */ | ||
46 | static int obj_name_cmp(const void *a_void,const void *b_void); | ||
19 | 47 | ||
20 | int OBJ_NAME_init(void) | 48 | int OBJ_NAME_init(void) |
21 | { | 49 | { |
22 | if (names_lh != NULL) return(1); | 50 | if (names_lh != NULL) return(1); |
23 | MemCheck_off(); | 51 | MemCheck_off(); |
24 | names_lh=lh_new(obj_name_hash,obj_name_cmp); | 52 | names_lh=lh_new(obj_name_hash, obj_name_cmp); |
25 | MemCheck_on(); | 53 | MemCheck_on(); |
26 | return(names_lh != NULL); | 54 | return(names_lh != NULL); |
27 | } | 55 | } |
28 | 56 | ||
29 | int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(), | 57 | int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *), |
30 | void (*free_func)()) | 58 | int (*cmp_func)(const char *, const char *), |
59 | void (*free_func)(const char *, int, const char *)) | ||
31 | { | 60 | { |
32 | int ret; | 61 | int ret; |
33 | int i; | 62 | int i; |
63 | NAME_FUNCS *name_funcs; | ||
34 | 64 | ||
35 | if (names_free == NULL) | 65 | if (name_funcs_stack == NULL) |
36 | { | 66 | { |
37 | MemCheck_off(); | 67 | MemCheck_off(); |
38 | names_hash=sk_new_null(); | 68 | name_funcs_stack=sk_NAME_FUNCS_new_null(); |
39 | names_cmp=sk_new_null(); | ||
40 | names_free=sk_new_null(); | ||
41 | MemCheck_on(); | 69 | MemCheck_on(); |
42 | } | 70 | } |
43 | if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL)) | 71 | if ((name_funcs_stack == NULL)) |
44 | { | 72 | { |
45 | /* ERROR */ | 73 | /* ERROR */ |
46 | return(0); | 74 | return(0); |
47 | } | 75 | } |
48 | ret=names_type_num; | 76 | ret=names_type_num; |
49 | names_type_num++; | 77 | names_type_num++; |
50 | for (i=sk_num(names_free); i<names_type_num; i++) | 78 | for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++) |
51 | { | 79 | { |
52 | MemCheck_off(); | 80 | MemCheck_off(); |
53 | sk_push(names_hash,(char *)strcmp); | 81 | name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS)); |
54 | sk_push(names_cmp,(char *)lh_strhash); | 82 | MemCheck_on(); |
55 | sk_push(names_free,NULL); | 83 | if (!name_funcs) return(0); |
84 | name_funcs->hash_func = lh_strhash; | ||
85 | name_funcs->cmp_func = OPENSSL_strcmp; | ||
86 | name_funcs->free_func = 0; /* NULL is often declared to | ||
87 | * ((void *)0), which according | ||
88 | * to Compaq C is not really | ||
89 | * compatible with a function | ||
90 | * pointer. -- Richard Levitte*/ | ||
91 | MemCheck_off(); | ||
92 | sk_NAME_FUNCS_push(name_funcs_stack,name_funcs); | ||
56 | MemCheck_on(); | 93 | MemCheck_on(); |
57 | } | 94 | } |
95 | name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret); | ||
58 | if (hash_func != NULL) | 96 | if (hash_func != NULL) |
59 | sk_set(names_hash,ret,(char *)hash_func); | 97 | name_funcs->hash_func = hash_func; |
60 | if (cmp_func != NULL) | 98 | if (cmp_func != NULL) |
61 | sk_set(names_cmp,ret,(char *)cmp_func); | 99 | name_funcs->cmp_func = cmp_func; |
62 | if (free_func != NULL) | 100 | if (free_func != NULL) |
63 | sk_set(names_free,ret,(char *)free_func); | 101 | name_funcs->free_func = free_func; |
64 | return(ret); | 102 | return(ret); |
65 | } | 103 | } |
66 | 104 | ||
67 | static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) | 105 | /* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */ |
106 | static int obj_name_cmp(const void *a_void, const void *b_void) | ||
68 | { | 107 | { |
69 | int ret; | 108 | int ret; |
70 | int (*cmp)(); | 109 | OBJ_NAME *a = (OBJ_NAME *)a_void; |
110 | OBJ_NAME *b = (OBJ_NAME *)b_void; | ||
71 | 111 | ||
72 | ret=a->type-b->type; | 112 | ret=a->type-b->type; |
73 | if (ret == 0) | 113 | if (ret == 0) |
74 | { | 114 | { |
75 | if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type)) | 115 | if ((name_funcs_stack != NULL) |
116 | && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) | ||
76 | { | 117 | { |
77 | cmp=(int (*)())sk_value(names_cmp,a->type); | 118 | ret=sk_NAME_FUNCS_value(name_funcs_stack, |
78 | ret=cmp(a->name,b->name); | 119 | a->type)->cmp_func(a->name,b->name); |
79 | } | 120 | } |
80 | else | 121 | else |
81 | ret=strcmp(a->name,b->name); | 122 | ret=strcmp(a->name,b->name); |
@@ -83,15 +124,16 @@ static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) | |||
83 | return(ret); | 124 | return(ret); |
84 | } | 125 | } |
85 | 126 | ||
86 | static unsigned long obj_name_hash(OBJ_NAME *a) | 127 | /* static unsigned long obj_name_hash(OBJ_NAME *a) */ |
128 | static unsigned long obj_name_hash(const void *a_void) | ||
87 | { | 129 | { |
88 | unsigned long ret; | 130 | unsigned long ret; |
89 | unsigned long (*hash)(); | 131 | OBJ_NAME *a = (OBJ_NAME *)a_void; |
90 | 132 | ||
91 | if ((names_hash != NULL) && (sk_num(names_hash) > a->type)) | 133 | if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) |
92 | { | 134 | { |
93 | hash=(unsigned long (*)())sk_value(names_hash,a->type); | 135 | ret=sk_NAME_FUNCS_value(name_funcs_stack, |
94 | ret=hash(a->name); | 136 | a->type)->hash_func(a->name); |
95 | } | 137 | } |
96 | else | 138 | else |
97 | { | 139 | { |
@@ -116,8 +158,8 @@ const char *OBJ_NAME_get(const char *name, int type) | |||
116 | on.type=type; | 158 | on.type=type; |
117 | 159 | ||
118 | for (;;) | 160 | for (;;) |
119 | { | 161 | { |
120 | ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on); | 162 | ret=(OBJ_NAME *)lh_retrieve(names_lh,&on); |
121 | if (ret == NULL) return(NULL); | 163 | if (ret == NULL) return(NULL); |
122 | if ((ret->alias) && !alias) | 164 | if ((ret->alias) && !alias) |
123 | { | 165 | { |
@@ -133,7 +175,6 @@ const char *OBJ_NAME_get(const char *name, int type) | |||
133 | 175 | ||
134 | int OBJ_NAME_add(const char *name, int type, const char *data) | 176 | int OBJ_NAME_add(const char *name, int type, const char *data) |
135 | { | 177 | { |
136 | void (*f)(); | ||
137 | OBJ_NAME *onp,*ret; | 178 | OBJ_NAME *onp,*ret; |
138 | int alias; | 179 | int alias; |
139 | 180 | ||
@@ -142,7 +183,7 @@ int OBJ_NAME_add(const char *name, int type, const char *data) | |||
142 | alias=type&OBJ_NAME_ALIAS; | 183 | alias=type&OBJ_NAME_ALIAS; |
143 | type&= ~OBJ_NAME_ALIAS; | 184 | type&= ~OBJ_NAME_ALIAS; |
144 | 185 | ||
145 | onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME)); | 186 | onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME)); |
146 | if (onp == NULL) | 187 | if (onp == NULL) |
147 | { | 188 | { |
148 | /* ERROR */ | 189 | /* ERROR */ |
@@ -154,16 +195,20 @@ int OBJ_NAME_add(const char *name, int type, const char *data) | |||
154 | onp->type=type; | 195 | onp->type=type; |
155 | onp->data=data; | 196 | onp->data=data; |
156 | 197 | ||
157 | ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp); | 198 | ret=(OBJ_NAME *)lh_insert(names_lh,onp); |
158 | if (ret != NULL) | 199 | if (ret != NULL) |
159 | { | 200 | { |
160 | /* free things */ | 201 | /* free things */ |
161 | if ((names_free != NULL) && (sk_num(names_free) > ret->type)) | 202 | if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) |
162 | { | 203 | { |
163 | f=(void (*)())sk_value(names_free,ret->type); | 204 | /* XXX: I'm not sure I understand why the free |
164 | f(ret->name,ret->type,ret->data); | 205 | * function should get three arguments... |
206 | * -- Richard Levitte | ||
207 | */ | ||
208 | sk_NAME_FUNCS_value(name_funcs_stack, | ||
209 | ret->type)->free_func(ret->name,ret->type,ret->data); | ||
165 | } | 210 | } |
166 | Free((char *)ret); | 211 | OPENSSL_free(ret); |
167 | } | 212 | } |
168 | else | 213 | else |
169 | { | 214 | { |
@@ -179,35 +224,108 @@ int OBJ_NAME_add(const char *name, int type, const char *data) | |||
179 | int OBJ_NAME_remove(const char *name, int type) | 224 | int OBJ_NAME_remove(const char *name, int type) |
180 | { | 225 | { |
181 | OBJ_NAME on,*ret; | 226 | OBJ_NAME on,*ret; |
182 | void (*f)(); | ||
183 | 227 | ||
184 | if (names_lh == NULL) return(0); | 228 | if (names_lh == NULL) return(0); |
185 | 229 | ||
186 | type&= ~OBJ_NAME_ALIAS; | 230 | type&= ~OBJ_NAME_ALIAS; |
187 | on.name=name; | 231 | on.name=name; |
188 | on.type=type; | 232 | on.type=type; |
189 | ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on); | 233 | ret=(OBJ_NAME *)lh_delete(names_lh,&on); |
190 | if (ret != NULL) | 234 | if (ret != NULL) |
191 | { | 235 | { |
192 | /* free things */ | 236 | /* free things */ |
193 | if ((names_free != NULL) && (sk_num(names_free) > type)) | 237 | if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) |
194 | { | 238 | { |
195 | f=(void (*)())sk_value(names_free,type); | 239 | /* XXX: I'm not sure I understand why the free |
196 | f(ret->name,ret->type,ret->data); | 240 | * function should get three arguments... |
241 | * -- Richard Levitte | ||
242 | */ | ||
243 | sk_NAME_FUNCS_value(name_funcs_stack, | ||
244 | ret->type)->free_func(ret->name,ret->type,ret->data); | ||
197 | } | 245 | } |
198 | Free((char *)ret); | 246 | OPENSSL_free(ret); |
199 | return(1); | 247 | return(1); |
200 | } | 248 | } |
201 | else | 249 | else |
202 | return(0); | 250 | return(0); |
203 | } | 251 | } |
204 | 252 | ||
253 | struct doall | ||
254 | { | ||
255 | int type; | ||
256 | void (*fn)(const OBJ_NAME *,void *arg); | ||
257 | void *arg; | ||
258 | }; | ||
259 | |||
260 | static void do_all_fn(const OBJ_NAME *name,struct doall *d) | ||
261 | { | ||
262 | if(name->type == d->type) | ||
263 | d->fn(name,d->arg); | ||
264 | } | ||
265 | |||
266 | static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *) | ||
267 | |||
268 | void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg) | ||
269 | { | ||
270 | struct doall d; | ||
271 | |||
272 | d.type=type; | ||
273 | d.fn=fn; | ||
274 | d.arg=arg; | ||
275 | |||
276 | lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d); | ||
277 | } | ||
278 | |||
279 | struct doall_sorted | ||
280 | { | ||
281 | int type; | ||
282 | int n; | ||
283 | const OBJ_NAME **names; | ||
284 | }; | ||
285 | |||
286 | static void do_all_sorted_fn(const OBJ_NAME *name,void *d_) | ||
287 | { | ||
288 | struct doall_sorted *d=d_; | ||
289 | |||
290 | if(name->type != d->type) | ||
291 | return; | ||
292 | |||
293 | d->names[d->n++]=name; | ||
294 | } | ||
295 | |||
296 | static int do_all_sorted_cmp(const void *n1_,const void *n2_) | ||
297 | { | ||
298 | const OBJ_NAME * const *n1=n1_; | ||
299 | const OBJ_NAME * const *n2=n2_; | ||
300 | |||
301 | return strcmp((*n1)->name,(*n2)->name); | ||
302 | } | ||
303 | |||
304 | void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg), | ||
305 | void *arg) | ||
306 | { | ||
307 | struct doall_sorted d; | ||
308 | int n; | ||
309 | |||
310 | d.type=type; | ||
311 | d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names); | ||
312 | d.n=0; | ||
313 | OBJ_NAME_do_all(type,do_all_sorted_fn,&d); | ||
314 | |||
315 | qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp); | ||
316 | |||
317 | for(n=0 ; n < d.n ; ++n) | ||
318 | fn(d.names[n],arg); | ||
319 | |||
320 | OPENSSL_free((void *)d.names); | ||
321 | } | ||
322 | |||
205 | static int free_type; | 323 | static int free_type; |
206 | 324 | ||
207 | static void names_lh_free(OBJ_NAME *onp, int type) | 325 | static void names_lh_free(OBJ_NAME *onp) |
208 | { | 326 | { |
209 | if(onp == NULL) | 327 | if(onp == NULL) |
210 | return; | 328 | return; |
211 | 329 | ||
212 | if ((free_type < 0) || (free_type == onp->type)) | 330 | if ((free_type < 0) || (free_type == onp->type)) |
213 | { | 331 | { |
@@ -215,6 +333,13 @@ static void names_lh_free(OBJ_NAME *onp, int type) | |||
215 | } | 333 | } |
216 | } | 334 | } |
217 | 335 | ||
336 | static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *) | ||
337 | |||
338 | static void name_funcs_free(NAME_FUNCS *ptr) | ||
339 | { | ||
340 | OPENSSL_free(ptr); | ||
341 | } | ||
342 | |||
218 | void OBJ_NAME_cleanup(int type) | 343 | void OBJ_NAME_cleanup(int type) |
219 | { | 344 | { |
220 | unsigned long down_load; | 345 | unsigned long down_load; |
@@ -225,17 +350,13 @@ void OBJ_NAME_cleanup(int type) | |||
225 | down_load=names_lh->down_load; | 350 | down_load=names_lh->down_load; |
226 | names_lh->down_load=0; | 351 | names_lh->down_load=0; |
227 | 352 | ||
228 | lh_doall(names_lh,names_lh_free); | 353 | lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free)); |
229 | if (type < 0) | 354 | if (type < 0) |
230 | { | 355 | { |
231 | lh_free(names_lh); | 356 | lh_free(names_lh); |
232 | sk_free(names_hash); | 357 | sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free); |
233 | sk_free(names_cmp); | ||
234 | sk_free(names_free); | ||
235 | names_lh=NULL; | 358 | names_lh=NULL; |
236 | names_hash=NULL; | 359 | name_funcs_stack = NULL; |
237 | names_cmp=NULL; | ||
238 | names_free=NULL; | ||
239 | } | 360 | } |
240 | else | 361 | else |
241 | names_lh->down_load=down_load; | 362 | names_lh->down_load=down_load; |