If we've not been inited don't deinit
[openssl.git] / crypto / store / str_mem.c
1 /*
2  * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
3  * 2003.
4  */
5 /* ====================================================================
6  * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <string.h>
60 #include <openssl/err.h>
61 #include "str_locl.h"
62
63 /*
64  * The memory store is currently highly experimental.  It's meant to become a
65  * base store used by other stores for internal caching (for full caching
66  * support, aging needs to be added).
67  *
68  * The database use is meant to support as much attribute association as
69  * possible, while providing for as small search ranges as possible. This is
70  * currently provided for by sorting the entries by numbers that are composed
71  * of bits set at the positions indicated by attribute type codes.  This
72  * provides for ranges determined by the highest attribute type code value.
73  * A better idea might be to sort by values computed from the range of
74  * attributes associated with the object (basically, the difference between
75  * the highest and lowest attribute type code) and it's distance from a base
76  * (basically, the lowest associated attribute type code).
77  */
78
79 typedef struct mem_object_data_st {
80     STORE_OBJECT *object;
81     STORE_ATTR_INFO *attr_info;
82     int references;
83 } MEM_OBJECT_DATA;
84
85 DEFINE_STACK_OF(MEM_OBJECT_DATA)
86 struct mem_data_st {
87     /*
88      * sorted with
89      * STORE_ATTR_INFO_compare().
90      */
91     STACK_OF(MEM_OBJECT_DATA) *data;
92     /*
93      * Currently unused, but can
94      * be used to add attributes
95      * from parts of the data.
96      */
97     unsigned int compute_components:1;
98 };
99
100 DEFINE_STACK_OF(STORE_ATTR_INFO)
101 struct mem_ctx_st {
102     /* The type we're searching for */
103     int type;
104     /*
105      * Sets of
106      * attributes to search for.  Each
107      * element is a STORE_ATTR_INFO.
108      */
109     STACK_OF(STORE_ATTR_INFO) *search_attributes;
110     /*
111      * which of the search attributes we
112      * found a match for, -1 when we still
113      * haven't found any
114      */
115     int search_index;
116     /* -1 as long as we're searching for the first */
117     int index;
118 };
119
120 static int mem_init(STORE *s);
121 static void mem_clean(STORE *s);
122 static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
123                                   OPENSSL_ITEM attributes[],
124                                   OPENSSL_ITEM parameters[]);
125 static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
126                              OPENSSL_ITEM attributes[],
127                              OPENSSL_ITEM parameters[]);
128 static int mem_store(STORE *s, STORE_OBJECT_TYPES type, STORE_OBJECT *data,
129                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
130 static int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
131                       OPENSSL_ITEM search_attributes[],
132                       OPENSSL_ITEM add_attributes[],
133                       OPENSSL_ITEM modify_attributes[],
134                       OPENSSL_ITEM delete_attributes[],
135                       OPENSSL_ITEM parameters[]);
136 static int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
137                       OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
138 static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
139                             OPENSSL_ITEM attributes[],
140                             OPENSSL_ITEM parameters[]);
141 static STORE_OBJECT *mem_list_next(STORE *s, void *handle);
142 static int mem_list_end(STORE *s, void *handle);
143 static int mem_list_endp(STORE *s, void *handle);
144 static int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
145                     OPENSSL_ITEM parameters[]);
146 static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
147                       OPENSSL_ITEM parameters[]);
148 static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void));
149
150 static STORE_METHOD store_memory = {
151     "OpenSSL memory store interface",
152     mem_init,
153     mem_clean,
154     mem_generate,
155     mem_get,
156     mem_store,
157     mem_modify,
158     NULL,                       /* revoke */
159     mem_delete,
160     mem_list_start,
161     mem_list_next,
162     mem_list_end,
163     mem_list_endp,
164     NULL,                       /* update */
165     mem_lock,
166     mem_unlock,
167     mem_ctrl
168 };
169
170 const STORE_METHOD *STORE_Memory(void)
171 {
172     return &store_memory;
173 }
174
175 static int mem_init(STORE *s)
176 {
177     return 1;
178 }
179
180 static void mem_clean(STORE *s)
181 {
182     return;
183 }
184
185 static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
186                                   OPENSSL_ITEM attributes[],
187                                   OPENSSL_ITEM parameters[])
188 {
189     STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED);
190     return 0;
191 }
192
193 static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
194                              OPENSSL_ITEM attributes[],
195                              OPENSSL_ITEM parameters[])
196 {
197     void *context = mem_list_start(s, type, attributes, parameters);
198
199     if (context) {
200         STORE_OBJECT *object = mem_list_next(s, context);
201
202         if (mem_list_end(s, context))
203             return object;
204     }
205     return NULL;
206 }
207
208 static int mem_store(STORE *s, STORE_OBJECT_TYPES type,
209                      STORE_OBJECT *data, OPENSSL_ITEM attributes[],
210                      OPENSSL_ITEM parameters[])
211 {
212     STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
213     return 0;
214 }
215
216 static int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
217                       OPENSSL_ITEM search_attributes[],
218                       OPENSSL_ITEM add_attributes[],
219                       OPENSSL_ITEM modify_attributes[],
220                       OPENSSL_ITEM delete_attributes[],
221                       OPENSSL_ITEM parameters[])
222 {
223     STOREerr(STORE_F_MEM_MODIFY, STORE_R_NOT_IMPLEMENTED);
224     return 0;
225 }
226
227 static int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
228                       OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
229 {
230     STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED);
231     return 0;
232 }
233
234 /*
235  * The list functions may be the hardest to understand.  Basically,
236  * mem_list_start compiles a stack of attribute info elements, and puts that
237  * stack into the context to be returned.  mem_list_next will then find the
238  * first matching element in the store, and then walk all the way to the end
239  * of the store (since any combination of attribute bits above the starting
240  * point may match the searched for bit pattern...).
241  */
242 static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
243                             OPENSSL_ITEM attributes[],
244                             OPENSSL_ITEM parameters[])
245 {
246     struct mem_ctx_st *context = OPENSSL_zalloc(sizeof(*context));
247     void *attribute_context = NULL;
248     STORE_ATTR_INFO *attrs = NULL;
249
250     if (context == NULL) {
251         STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
252         return 0;
253     }
254
255     attribute_context = STORE_parse_attrs_start(attributes);
256     if (!attribute_context) {
257         STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB);
258         goto err;
259     }
260
261     while ((attrs = STORE_parse_attrs_next(attribute_context))) {
262         if (context->search_attributes == NULL) {
263             context->search_attributes =
264                 sk_STORE_ATTR_INFO_new(STORE_ATTR_INFO_compare);
265             if (context->search_attributes == NULL) {
266                 STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
267                 goto err;
268             }
269         }
270         sk_STORE_ATTR_INFO_push(context->search_attributes, attrs);
271     }
272     if (!STORE_parse_attrs_endp(attribute_context))
273         goto err;
274     STORE_parse_attrs_end(attribute_context);
275     context->search_index = -1;
276     context->index = -1;
277     return context;
278  err:
279     if (attribute_context)
280         STORE_parse_attrs_end(attribute_context);
281     mem_list_end(s, context);
282     return NULL;
283 }
284
285 static STORE_OBJECT *mem_list_next(STORE *s, void *handle)
286 {
287     int i;
288     struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
289     struct mem_object_data_st key = { 0, 0, 1 };
290     struct mem_data_st *store = (struct mem_data_st *)STORE_get_ex_data(s, 1);
291     int srch;
292     int cres = 0;
293
294     if (!context) {
295         STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
296         return NULL;
297     }
298     if (!store) {
299         STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE);
300         return NULL;
301     }
302
303     if (context->search_index == -1) {
304         for (i = 0;
305              i < sk_STORE_ATTR_INFO_num(context->search_attributes); i++) {
306             key.attr_info
307                 = sk_STORE_ATTR_INFO_value(context->search_attributes, i);
308             srch = sk_MEM_OBJECT_DATA_find_ex(store->data, &key);
309
310             if (srch >= 0) {
311                 context->search_index = srch;
312                 break;
313             }
314         }
315     }
316     if (context->search_index < 0)
317         return NULL;
318
319     key.attr_info =
320         sk_STORE_ATTR_INFO_value(context->search_attributes,
321                                  context->search_index);
322     for (srch = context->search_index;
323          srch < sk_MEM_OBJECT_DATA_num(store->data)
324          && STORE_ATTR_INFO_in_range(key.attr_info,
325                                      sk_MEM_OBJECT_DATA_value(store->data,
326                                                               srch)->attr_info)
327          && !(cres =
328               STORE_ATTR_INFO_in_ex(key.attr_info,
329                                     sk_MEM_OBJECT_DATA_value(store->data,
330                                                              srch)->attr_info));
331          srch++) ;
332
333     context->search_index = srch;
334     if (cres)
335         return (sk_MEM_OBJECT_DATA_value(store->data, srch))->object;
336     return NULL;
337 }
338
339 static int mem_list_end(STORE *s, void *handle)
340 {
341     struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
342
343     if (!context) {
344         STOREerr(STORE_F_MEM_LIST_END, ERR_R_PASSED_NULL_PARAMETER);
345         return 0;
346     }
347     if (context)
348         sk_STORE_ATTR_INFO_free(context->search_attributes);
349     OPENSSL_free(context);
350     return 1;
351 }
352
353 static int mem_list_endp(STORE *s, void *handle)
354 {
355     struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
356
357     if (!context
358         || context->search_index
359         == sk_STORE_ATTR_INFO_num(context->search_attributes))
360         return 1;
361     return 0;
362 }
363
364 static int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
365                     OPENSSL_ITEM parameters[])
366 {
367     return 1;
368 }
369
370 static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
371                       OPENSSL_ITEM parameters[])
372 {
373     return 1;
374 }
375
376 static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void))
377 {
378     return 1;
379 }