1/*
2 * Copyright (c) 2005 - 2006 Kungliga Tekniska H�gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "hx_locl.h"
35RCSID("Id$");
36
37/*
38 * Should use two hash/tree certificates intead of a array.  Criteria
39 * should be subject and subjectKeyIdentifier since those two are
40 * commonly seached on in CMS and path building.
41 */
42
43struct mem_data {
44    char *name;
45    struct {
46	unsigned long len;
47	hx509_cert *val;
48    } certs;
49    hx509_private_key *keys;
50};
51
52static int
53mem_init(hx509_context context,
54	 hx509_certs certs, void **data, int flags,
55	 const char *residue, hx509_lock lock)
56{
57    struct mem_data *mem;
58    mem = calloc(1, sizeof(*mem));
59    if (mem == NULL)
60	return ENOMEM;
61    if (residue == NULL || residue[0] == '\0')
62	residue = "anonymous";
63    mem->name = strdup(residue);
64    if (mem->name == NULL) {
65	free(mem);
66	return ENOMEM;
67    }
68    *data = mem;
69    return 0;
70}
71
72static int
73mem_free(hx509_certs certs, void *data)
74{
75    struct mem_data *mem = data;
76    unsigned long i;
77
78    for (i = 0; i < mem->certs.len; i++)
79	hx509_cert_free(mem->certs.val[i]);
80    free(mem->certs.val);
81    for (i = 0; mem->keys && mem->keys[i]; i++)
82	_hx509_private_key_free(&mem->keys[i]);
83    free(mem->keys);
84    free(mem->name);
85    free(mem);
86
87    return 0;
88}
89
90static int
91mem_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
92{
93    struct mem_data *mem = data;
94    hx509_cert *val;
95
96    val = realloc(mem->certs.val,
97		  (mem->certs.len + 1) * sizeof(mem->certs.val[0]));
98    if (val == NULL)
99	return ENOMEM;
100
101    mem->certs.val = val;
102    mem->certs.val[mem->certs.len] = hx509_cert_ref(c);
103    mem->certs.len++;
104
105    return 0;
106}
107
108static int
109mem_iter_start(hx509_context context,
110	       hx509_certs certs,
111	       void *data,
112	       void **cursor)
113{
114    unsigned long *iter = malloc(sizeof(*iter));
115
116    if (iter == NULL)
117	return ENOMEM;
118
119    *iter = 0;
120    *cursor = iter;
121
122    return 0;
123}
124
125static int
126mem_iter(hx509_context contexst,
127	 hx509_certs certs,
128	 void *data,
129	 void *cursor,
130	 hx509_cert *cert)
131{
132    unsigned long *iter = cursor;
133    struct mem_data *mem = data;
134
135    if (*iter >= mem->certs.len) {
136	*cert = NULL;
137	return 0;
138    }
139
140    *cert = hx509_cert_ref(mem->certs.val[*iter]);
141    (*iter)++;
142    return 0;
143}
144
145static int
146mem_iter_end(hx509_context context,
147	     hx509_certs certs,
148	     void *data,
149	     void *cursor)
150{
151    free(cursor);
152    return 0;
153}
154
155static int
156mem_getkeys(hx509_context context,
157	     hx509_certs certs,
158	     void *data,
159	     hx509_private_key **keys)
160{
161    struct mem_data *mem = data;
162    int i;
163
164    for (i = 0; mem->keys && mem->keys[i]; i++)
165	;
166    *keys = calloc(i + 1, sizeof(**keys));
167    for (i = 0; mem->keys && mem->keys[i]; i++) {
168	(*keys)[i] = _hx509_private_key_ref(mem->keys[i]);
169	if ((*keys)[i] == NULL) {
170	    while (--i >= 0)
171		_hx509_private_key_free(&(*keys)[i]);
172	    hx509_set_error_string(context, 0, ENOMEM, "out of memory");
173	    return ENOMEM;
174	}
175    }
176    (*keys)[i] = NULL;
177    return 0;
178}
179
180static int
181mem_addkey(hx509_context context,
182	   hx509_certs certs,
183	   void *data,
184	   hx509_private_key key)
185{
186    struct mem_data *mem = data;
187    void *ptr;
188    int i;
189
190    for (i = 0; mem->keys && mem->keys[i]; i++)
191	;
192    ptr = realloc(mem->keys, (i + 2) * sizeof(*mem->keys));
193    if (ptr == NULL) {
194	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
195	return ENOMEM;
196    }
197    mem->keys = ptr;
198    mem->keys[i++] = _hx509_private_key_ref(key);
199    mem->keys[i++] = NULL;
200    return 0;
201}
202
203
204static struct hx509_keyset_ops keyset_mem = {
205    "MEMORY",
206    0,
207    mem_init,
208    NULL,
209    mem_free,
210    mem_add,
211    NULL,
212    mem_iter_start,
213    mem_iter,
214    mem_iter_end,
215    NULL,
216    mem_getkeys,
217    mem_addkey
218};
219
220void
221_hx509_ks_mem_register(hx509_context context)
222{
223    _hx509_ks_register(context, &keyset_mem);
224}
225