Make it possible to disable STORE.
[openssl.git] / crypto / store / str_mem.c
1 /* crypto/store/str_mem.c -*- mode:C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
3  * project 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 /* The memory store is currently highly experimental.  It's meant to become
64    a base store used by other stores for internal caching (for full caching
65    support, aging needs to be added).
66
67    The database use is meant to support as much attribute association as
68    possible, while providing for as small search ranges as possible.
69    This is currently provided for by sorting the entries by numbers that
70    are composed of bits set at the positions indicated by attribute type
71    codes.  This provides for ranges determined by the highest attribute
72    type code value.  A better idea might be to sort by values computed
73    from the range of attributes associated with the object (basically,
74    the difference between the highest and lowest attribute type code)
75    and it's distance from a base (basically, the lowest associated
76    attribute type code).
77 */
78
79 typedef struct mem_object_data_st
80         {
81         STORE_OBJECT *object;
82         STORE_ATTR_INFO *attr_info;
83         int references;
84         } MEM_OBJECT_DATA;
85
86 DECLARE_STACK_OF(MEM_OBJECT_DATA)
87 struct mem_data_st
88         {
89         STACK_OF(MEM_OBJECT_DATA) *data; /* sorted with
90                                           * STORE_ATTR_INFO_compare(). */
91         unsigned int compute_components : 1; /* Currently unused, but can
92                                                 be used to add attributes
93                                                 from parts of the data. */
94         };
95
96 DECLARE_STACK_OF(STORE_ATTR_INFO)
97 struct mem_ctx_st
98         {
99         int type;               /* The type we're searching for */
100         STACK_OF(STORE_ATTR_INFO) *search_attributes; /* Sets of
101                                      attributes to search for.  Each
102                                      element is a STORE_ATTR_INFO. */
103         int search_index;       /* which of the search attributes we
104                                    found a match for, -1 when we still
105                                    haven't found any */
106         int index;              /* -1 as long as we're searching for
107                                     the first */
108         };
109
110 static int mem_init(STORE *s);
111 static void mem_clean(STORE *s);
112 static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
113         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
114 static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
115         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
116 static int mem_store(STORE *s, STORE_OBJECT_TYPES type,
117         STORE_OBJECT *data, OPENSSL_ITEM attributes[],
118         OPENSSL_ITEM parameters[]);
119 static int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
120         OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[],
121         OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[],
122         OPENSSL_ITEM parameters[]);
123 static int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
124         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
125 static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
126         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
127 static STORE_OBJECT *mem_list_next(STORE *s, void *handle);
128 static int mem_list_end(STORE *s, void *handle);
129 static int mem_list_endp(STORE *s, void *handle);
130 static int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
131         OPENSSL_ITEM parameters[]);
132 static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
133         OPENSSL_ITEM parameters[]);
134 static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f)(void));
135
136 static STORE_METHOD store_memory =
137         {
138         "OpenSSL memory store interface",
139         mem_init,
140         mem_clean,
141         mem_generate,
142         mem_get,
143         mem_store,
144         mem_modify,
145         NULL, /* revoke */
146         mem_delete,
147         mem_list_start,
148         mem_list_next,
149         mem_list_end,
150         mem_list_endp,
151         NULL, /* update */
152         mem_lock,
153         mem_unlock,
154         mem_ctrl
155         };
156
157 const STORE_METHOD *STORE_Memory(void)
158         {
159         return &store_memory;
160         }
161
162 static int mem_init(STORE *s)
163         {
164         return 1;
165         }
166
167 static void mem_clean(STORE *s)
168         {
169         return;
170         }
171
172 static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
173         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
174         {
175         STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED);
176         return 0;
177         }
178 static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
179         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
180         {
181         void *context = mem_list_start(s, type, attributes, parameters);
182         
183         if (context)
184                 {
185                 STORE_OBJECT *object = mem_list_next(s, context);
186
187                 if (mem_list_end(s, context))
188                         return object;
189                 }
190         return NULL;
191         }
192 static int mem_store(STORE *s, STORE_OBJECT_TYPES type,
193         STORE_OBJECT *data, OPENSSL_ITEM attributes[],
194         OPENSSL_ITEM parameters[])
195         {
196         STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
197         return 0;
198         }
199 static int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
200         OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[],
201         OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[],
202         OPENSSL_ITEM parameters[])
203         {
204         STOREerr(STORE_F_MEM_MODIFY, STORE_R_NOT_IMPLEMENTED);
205         return 0;
206         }
207 static int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
208         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
209         {
210         STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED);
211         return 0;
212         }
213
214 /* The list functions may be the hardest to understand.  Basically,
215    mem_list_start compiles a stack of attribute info elements, and
216    puts that stack into the context to be returned.  mem_list_next
217    will then find the first matching element in the store, and then
218    walk all the way to the end of the store (since any combination
219    of attribute bits above the starting point may match the searched
220    for bit pattern...). */
221 static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
222         OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
223         {
224         struct mem_ctx_st *context =
225                 (struct mem_ctx_st *)OPENSSL_malloc(sizeof(struct mem_ctx_st));
226         void *attribute_context = NULL;
227         STORE_ATTR_INFO *attrs = NULL;
228
229         if (!context)
230                 {
231                 STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
232                 return 0;
233                 }
234         memset(context, 0, sizeof(struct mem_ctx_st));
235
236         attribute_context = STORE_parse_attrs_start(attributes);
237         if (!attribute_context)
238                 {
239                 STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB);
240                 goto err;
241                 }
242
243         while((attrs = STORE_parse_attrs_next(attribute_context)))
244                 {
245                 if (context->search_attributes == NULL)
246                         {
247                         context->search_attributes =
248                                 sk_STORE_ATTR_INFO_new(STORE_ATTR_INFO_compare);
249                         if (!context->search_attributes)
250                                 {
251                                 STOREerr(STORE_F_MEM_LIST_START,
252                                         ERR_R_MALLOC_FAILURE);
253                                 goto err;
254                                 }
255                         }
256                 sk_STORE_ATTR_INFO_push(context->search_attributes,attrs);
257                 }
258         if (!STORE_parse_attrs_endp(attribute_context))
259                 goto err;
260         STORE_parse_attrs_end(attribute_context);
261         context->search_index = -1;
262         context->index = -1;
263         return context;
264  err:
265         if (attribute_context) STORE_parse_attrs_end(attribute_context);
266         mem_list_end(s, context);
267         return NULL;
268         }
269 static STORE_OBJECT *mem_list_next(STORE *s, void *handle)
270         {
271         int i;
272         struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
273         struct mem_object_data_st key = { 0, 0, 1 };
274         struct mem_data_st *store =
275                 (struct mem_data_st *)STORE_get_ex_data(s, 1);
276         int srch;
277         int cres = 0;
278
279         if (!context)
280                 {
281                 STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
282                 return NULL;
283                 }
284         if (!store)
285                 {
286                 STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE);
287                 return NULL;
288                 }
289
290         if (context->search_index == -1)
291                 {
292                 for (i = 0;
293                      i < sk_STORE_ATTR_INFO_num(context->search_attributes);
294                      i++)
295                         {
296                         key.attr_info
297                           = sk_STORE_ATTR_INFO_value(context->search_attributes,
298                                                      i);
299                         srch = sk_MEM_OBJECT_DATA_find_ex(store->data, &key);
300
301                         if (srch >= 0)
302                                 {
303                                 context->search_index = srch;
304                                 break;
305                                 }
306                         }
307                 }
308         if (context->search_index < 0)
309                 return NULL;
310         
311         key.attr_info =
312                 sk_STORE_ATTR_INFO_value(context->search_attributes,
313                                          context->search_index);
314         for(srch = context->search_index;
315             srch < sk_MEM_OBJECT_DATA_num(store->data)
316                     && STORE_ATTR_INFO_in_range(key.attr_info,
317                             sk_MEM_OBJECT_DATA_value(store->data, srch)->attr_info)
318                     && !(cres = STORE_ATTR_INFO_in_ex(key.attr_info,
319                                  sk_MEM_OBJECT_DATA_value(store->data, srch)->attr_info));
320             srch++)
321                 ;
322
323         context->search_index = srch;
324         if (cres)
325                 return (sk_MEM_OBJECT_DATA_value(store->data, srch))->object;
326         return NULL;
327         }
328 static int mem_list_end(STORE *s, void *handle)
329         {
330         struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
331
332         if (!context)
333                 {
334                 STOREerr(STORE_F_MEM_LIST_END, ERR_R_PASSED_NULL_PARAMETER);
335                 return 0;
336                 }
337         if (context && context->search_attributes)
338                 sk_STORE_ATTR_INFO_free(context->search_attributes);
339         if (context) OPENSSL_free(context);
340         return 1;
341         }
342 static int mem_list_endp(STORE *s, void *handle)
343         {
344         struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
345
346         if (!context
347             || context->search_index
348                == sk_STORE_ATTR_INFO_num(context->search_attributes))
349                 return 1;
350         return 0;
351         }
352 static int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
353         OPENSSL_ITEM parameters[])
354         {
355         return 1;
356         }
357 static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
358         OPENSSL_ITEM parameters[])
359         {
360         return 1;
361         }
362 static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f)(void))
363         {
364         return 1;
365         }