|
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 |