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