Yeah, right, an object file ending with .c, that'll work!
[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 struct mem_object_data_st
80         {
81         STORE_OBJECT *object;
82         STORE_ATTR_INFO *attr_info;
83         int references;
84         };
85
86 struct mem_data_st
87         {
88         STACK *data;            /* A stack of mem_object_data_st,
89                                    sorted with STORE_ATTR_INFO_compare(). */
90         unsigned int compute_components : 1; /* Currently unused, but can
91                                                 be used to add attributes
92                                                 from parts of the data. */
93         };
94
95 struct mem_ctx_st
96         {
97         int type;               /* The type we're searching for */
98         STACK *search_attributes; /* Sets of attributes to search for.
99                                      Each element is a STORE_ATTR_INFO. */
100         int search_index;       /* which of the search attributes we found a match
101                                    for, -1 when we still haven't found any */
102         int index;              /* -1 as long as we're searching for the first */
103         };
104
105 static int mem_init(STORE *s);
106 static void mem_clean(STORE *s);
107 static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
108         OPENSSL_ITEM parameters[], OPENSSL_ITEM attributes[]);
109 static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
110         OPENSSL_ITEM attributes[]);
111 static int mem_store(STORE *s, STORE_OBJECT_TYPES type,
112         STORE_OBJECT *data, OPENSSL_ITEM attributes[]);
113 static int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
114         OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[],
115         OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[]);
116 static int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
117         OPENSSL_ITEM attributes[]);
118 static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
119         OPENSSL_ITEM attributes[]);
120 static STORE_OBJECT *mem_list_next(STORE *s, void *handle);
121 static int mem_list_end(STORE *s, void *handle);
122 static int mem_list_endp(STORE *s, void *handle);
123 static int mem_lock(STORE *s, OPENSSL_ITEM attributes[]);
124 static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[]);
125 static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f)());
126
127 static STORE_METHOD store_memory =
128         {
129         "OpenSSL memory store interface",
130         mem_init,
131         mem_clean,
132         mem_generate,
133         mem_get,
134         mem_store,
135         mem_modify,
136         NULL, /* revoke */
137         mem_delete,
138         mem_list_start,
139         mem_list_next,
140         mem_list_end,
141         mem_list_endp,
142         NULL, /* update */
143         mem_lock,
144         mem_unlock,
145         mem_ctrl
146         };
147
148 const STORE_METHOD *STORE_Memory(void)
149         {
150         return &store_memory;
151         }
152
153 static int mem_init(STORE *s)
154         {
155         return 1;
156         }
157
158 static void mem_clean(STORE *s)
159         {
160         return;
161         }
162
163 static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
164         OPENSSL_ITEM parameters[], OPENSSL_ITEM attributes[])
165         {
166         STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED);
167         return 0;
168         }
169 static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
170         OPENSSL_ITEM attributes[])
171         {
172         void *context = mem_list_start(s, type, attributes);
173         
174         if (context)
175                 {
176                 STORE_OBJECT *object = mem_list_next(s, context);
177
178                 if (mem_list_end(s, context))
179                         return object;
180                 }
181         return NULL;
182         }
183 static int mem_store(STORE *s, STORE_OBJECT_TYPES type,
184         STORE_OBJECT *data, OPENSSL_ITEM attributes[])
185         {
186         STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
187         return 0;
188         }
189 static int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
190         OPENSSL_ITEM search_attributes[], OPENSSL_ITEM add_attributes[],
191         OPENSSL_ITEM modify_attributes[], OPENSSL_ITEM delete_attributes[])
192         {
193         STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
194         return 0;
195         }
196 static int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
197         OPENSSL_ITEM attributes[])
198         {
199         STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED);
200         return 0;
201         }
202
203 /* The list functions may be the hardest to nuderstand.  Basically,
204    mem_list_start compiles a stack of attribute info elements, and
205    puts that stack into the context to be returned.  mem_list_next
206    will then find the first matching element in the store, and then
207    walk all the way to the end of the store (since any combination
208    of attribute bits above the starting point may match the searched
209    for bit pattern...). */
210 static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
211         OPENSSL_ITEM attributes[])
212         {
213         struct mem_ctx_st *context =
214                 (struct mem_ctx_st *)OPENSSL_malloc(sizeof(struct mem_ctx_st));
215         void *attribute_context = NULL;
216         STORE_ATTR_INFO *attrs = NULL;
217
218         if (!context)
219                 {
220                 STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
221                 return 0;
222                 }
223         memset(context, 0, sizeof(struct mem_ctx_st));
224
225         attribute_context = STORE_parse_attrs_start(attributes);
226         if (!attribute_context)
227                 {
228                 STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB);
229                 goto err;
230                 }
231
232         while((attrs = STORE_parse_attrs_next(attribute_context)))
233                 {
234                 if (context->search_attributes == NULL)
235                         {
236                         context->search_attributes =
237                                 sk_new((int (*)(const char * const *, const char * const *))STORE_ATTR_INFO_compare);
238                         if (!context->search_attributes)
239                                 {
240                                 STOREerr(STORE_F_MEM_LIST_START,
241                                         ERR_R_MALLOC_FAILURE);
242                                 goto err;
243                                 }
244                         }
245                 sk_push(context->search_attributes,(char *)attrs);
246                 }
247         if (!STORE_parse_attrs_endp(attribute_context))
248                 goto err;
249         STORE_parse_attrs_end(attribute_context);
250         context->search_index = -1;
251         context->index = -1;
252         return context;
253  err:
254         if (attribute_context) STORE_parse_attrs_end(attribute_context);
255         mem_list_end(s, context);
256         return NULL;
257         }
258 static STORE_OBJECT *mem_list_next(STORE *s, void *handle)
259         {
260         int i;
261         struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
262         struct mem_object_data_st key = { 0, 0, 1 };
263         struct mem_data_st *store =
264                 (struct mem_data_st *)STORE_get_ex_data(s, 1);
265         int srch;
266         int cres = 0;
267
268         if (!context)
269                 {
270                 STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
271                 return NULL;
272                 }
273         if (!store)
274                 {
275                 STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE);
276                 return NULL;
277                 }
278
279         if (context->search_index == -1)
280                 {
281                 for (i = 0; i < sk_num(context->search_attributes); i++)
282                         {
283                         key.attr_info =
284                                 (STORE_ATTR_INFO *)sk_value(context->search_attributes, i);
285                         srch = sk_find_ex(store->data, (char *)&key);
286
287                         if (srch >= 0)
288                                 {
289                                 context->search_index = srch;
290                                 break;
291                                 }
292                         }
293                 }
294         if (context->search_index < 0)
295                 return NULL;
296         
297         key.attr_info =
298                 (STORE_ATTR_INFO *)sk_value(context->search_attributes,
299                         context->search_index);
300         for(srch = context->search_index;
301             srch < sk_num(store->data)
302                     && !(cres = STORE_ATTR_INFO_in_ex(key.attr_info,
303                                  (STORE_ATTR_INFO *)sk_value(store->data, srch)));
304             srch++)
305                 ;
306
307         context->search_index = srch;
308         if (cres)
309                 return ((struct mem_object_data_st *)sk_value(store->data,
310                                 srch))->object;
311         return NULL;
312         }
313 static int mem_list_end(STORE *s, void *handle)
314         {
315         struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
316
317         if (!context)
318                 {
319                 STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
320                 return 0;
321                 }
322         if (context && context->search_attributes)
323                 sk_free(context->search_attributes);
324         if (context) OPENSSL_free(context);
325         return 1;
326         }
327 static int mem_list_endp(STORE *s, void *handle)
328         {
329         struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
330
331         if (!context
332                 || context->search_index == sk_num(context->search_attributes))
333                 return 1;
334         return 0;
335         }
336 static int mem_lock(STORE *s, OPENSSL_ITEM attributes[])
337         {
338         return 1;
339         }
340 static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[])
341         {
342         return 1;
343         }
344 static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f)())
345         {
346         return 1;
347         }