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"
35
36/*
37 * Should use two hash/tree certificates intead of a array.  Criteria
38 * should be subject and subjectKeyIdentifier since those two are
39 * commonly seached on in CMS and path building.
40 */
41
42struct mem_data {
43    char *name;
44    struct {
45	unsigned long len;
46	hx509_cert *val;
47    } certs;
48    hx509_private_key *keys;
49};
50
51static int
52mem_init(hx509_context context,
53	 hx509_certs certs, void **data, int flags,
54	 const char *residue, hx509_lock lock)
55{
56    struct mem_data *mem;
57    mem = calloc(1, sizeof(*mem));
58    if (mem == NULL)
59	return ENOMEM;
60    if (residue == NULL || residue[0] == '\0')
61	residue = "anonymous";
62    mem->name = strdup(residue);
63    if (mem->name == NULL) {
64	free(mem);
65	return ENOMEM;
66    }
67    *data = mem;
68    return 0;
69}
70
71static int
72mem_free(hx509_certs certs, void *data)
73{
74    struct mem_data *mem = data;
75    unsigned long i;
76
77    for (i = 0; i < mem->certs.len; i++)
78	hx509_cert_free(mem->certs.val[i]);
79    free(mem->certs.val);
80    for (i = 0; mem->keys && mem->keys[i]; i++)
81	hx509_private_key_free(&mem->keys[i]);
82    free(mem->keys);
83    free(mem->name);
84    free(mem);
85
86    return 0;
87}
88
89static int
90mem_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
91{
92    struct mem_data *mem = data;
93    hx509_cert *val;
94
95    val = realloc(mem->certs.val,
96		  (mem->certs.len + 1) * sizeof(mem->certs.val[0]));
97    if (val == NULL)
98	return ENOMEM;
99
100    mem->certs.val = val;
101    mem->certs.val[mem->certs.len] = hx509_cert_ref(c);
102    mem->certs.len++;
103
104    return 0;
105}
106
107static int
108mem_iter_start(hx509_context context,
109	       hx509_certs certs,
110	       void *data,
111	       void **cursor)
112{
113    unsigned long *iter = malloc(sizeof(*iter));
114
115    if (iter == NULL)
116	return ENOMEM;
117
118    *iter = 0;
119    *cursor = iter;
120
121    return 0;
122}
123
124static int
125mem_iter(hx509_context contexst,
126	 hx509_certs certs,
127	 void *data,
128	 void *cursor,
129	 hx509_cert *cert)
130{
131    unsigned long *iter = cursor;
132    struct mem_data *mem = data;
133
134    if (*iter >= mem->certs.len) {
135	*cert = NULL;
136	return 0;
137    }
138
139    *cert = hx509_cert_ref(mem->certs.val[*iter]);
140    (*iter)++;
141    return 0;
142}
143
144static int
145mem_iter_end(hx509_context context,
146	     hx509_certs certs,
147	     void *data,
148	     void *cursor)
149{
150    free(cursor);
151    return 0;
152}
153
154static int
155mem_getkeys(hx509_context context,
156	     hx509_certs certs,
157	     void *data,
158	     hx509_private_key **keys)
159{
160    struct mem_data *mem = data;
161    int i;
162
163    for (i = 0; mem->keys && mem->keys[i]; i++)
164	;
165    *keys = calloc(i + 1, sizeof(**keys));
166    for (i = 0; mem->keys && mem->keys[i]; i++) {
167	(*keys)[i] = _hx509_private_key_ref(mem->keys[i]);
168	if ((*keys)[i] == NULL) {
169	    while (--i >= 0)
170		hx509_private_key_free(&(*keys)[i]);
171	    hx509_set_error_string(context, 0, ENOMEM, "out of memory");
172	    return ENOMEM;
173	}
174    }
175    (*keys)[i] = NULL;
176    return 0;
177}
178
179static int
180mem_addkey(hx509_context context,
181	   hx509_certs certs,
182	   void *data,
183	   hx509_private_key key)
184{
185    struct mem_data *mem = data;
186    void *ptr;
187    int i;
188
189    for (i = 0; mem->keys && mem->keys[i]; i++)
190	;
191    ptr = realloc(mem->keys, (i + 2) * sizeof(*mem->keys));
192    if (ptr == NULL) {
193	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
194	return ENOMEM;
195    }
196    mem->keys = ptr;
197    mem->keys[i] = _hx509_private_key_ref(key);
198    mem->keys[i + 1] = NULL;
199    return 0;
200}
201
202
203static struct hx509_keyset_ops keyset_mem = {
204    "MEMORY",
205    0,
206    mem_init,
207    NULL,
208    mem_free,
209    mem_add,
210    NULL,
211    mem_iter_start,
212    mem_iter,
213    mem_iter_end,
214    NULL,
215    mem_getkeys,
216    mem_addkey
217};
218
219void
220_hx509_ks_mem_register(hx509_context context)
221{
222    _hx509_ks_register(context, &keyset_mem);
223}
224