OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
eng_list.c
Go to the documentation of this file.
1 /* crypto/engine/eng_list.c */
2 /* Written by Geoff Thorpe ([email protected]) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2001 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
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  * ([email protected]). This product includes software written by Tim
55  * Hudson ([email protected]).
56  *
57  */
58 /* ====================================================================
59  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60  * ECDH support in OpenSSL originally developed by
61  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62  */
63 
64 #include "eng_int.h"
65 
66 /* The linked-list of pointers to engine types. engine_list_head
67  * incorporates an implicit structural reference but engine_list_tail
68  * does not - the latter is a computational niceity and only points
69  * to something that is already pointed to by its predecessor in the
70  * list (or engine_list_head itself). In the same way, the use of the
71  * "prev" pointer in each ENGINE is to save excessive list iteration,
72  * it doesn't correspond to an extra structural reference. Hence,
73  * engine_list_head, and each non-null "next" pointer account for
74  * the list itself assuming exactly 1 structural reference on each
75  * list member. */
76 static ENGINE *engine_list_head = NULL;
77 static ENGINE *engine_list_tail = NULL;
78 
79 /* This cleanup function is only needed internally. If it should be called, we
80  * register it with the "ENGINE_cleanup()" stack to be called during cleanup. */
81 
82 static void engine_list_cleanup(void)
83  {
84  ENGINE *iterator = engine_list_head;
85 
86  while(iterator != NULL)
87  {
88  ENGINE_remove(iterator);
89  iterator = engine_list_head;
90  }
91  return;
92  }
93 
94 /* These static functions starting with a lower case "engine_" always
95  * take place when CRYPTO_LOCK_ENGINE has been locked up. */
96 static int engine_list_add(ENGINE *e)
97  {
98  int conflict = 0;
99  ENGINE *iterator = NULL;
100 
101  if(e == NULL)
102  {
105  return 0;
106  }
107  iterator = engine_list_head;
108  while(iterator && !conflict)
109  {
110  conflict = (strcmp(iterator->id, e->id) == 0);
111  iterator = iterator->next;
112  }
113  if(conflict)
114  {
117  return 0;
118  }
119  if(engine_list_head == NULL)
120  {
121  /* We are adding to an empty list. */
122  if(engine_list_tail)
123  {
126  return 0;
127  }
128  engine_list_head = e;
129  e->prev = NULL;
130  /* The first time the list allocates, we should register the
131  * cleanup. */
132  engine_cleanup_add_last(engine_list_cleanup);
133  }
134  else
135  {
136  /* We are adding to the tail of an existing list. */
137  if((engine_list_tail == NULL) ||
138  (engine_list_tail->next != NULL))
139  {
142  return 0;
143  }
144  engine_list_tail->next = e;
145  e->prev = engine_list_tail;
146  }
147  /* Having the engine in the list assumes a structural
148  * reference. */
149  e->struct_ref++;
150  engine_ref_debug(e, 0, 1)
151  /* However it came to be, e is the last item in the list. */
152  engine_list_tail = e;
153  e->next = NULL;
154  return 1;
155  }
156 
157 static int engine_list_remove(ENGINE *e)
158  {
159  ENGINE *iterator;
160 
161  if(e == NULL)
162  {
165  return 0;
166  }
167  /* We need to check that e is in our linked list! */
168  iterator = engine_list_head;
169  while(iterator && (iterator != e))
170  iterator = iterator->next;
171  if(iterator == NULL)
172  {
175  return 0;
176  }
177  /* un-link e from the chain. */
178  if(e->next)
179  e->next->prev = e->prev;
180  if(e->prev)
181  e->prev->next = e->next;
182  /* Correct our head/tail if necessary. */
183  if(engine_list_head == e)
184  engine_list_head = e->next;
185  if(engine_list_tail == e)
186  engine_list_tail = e->prev;
187  engine_free_util(e, 0);
188  return 1;
189  }
190 
191 /* Get the first/last "ENGINE" type available. */
193  {
194  ENGINE *ret;
195 
197  ret = engine_list_head;
198  if(ret)
199  {
200  ret->struct_ref++;
201  engine_ref_debug(ret, 0, 1)
202  }
204  return ret;
205  }
206 
208  {
209  ENGINE *ret;
210 
212  ret = engine_list_tail;
213  if(ret)
214  {
215  ret->struct_ref++;
216  engine_ref_debug(ret, 0, 1)
217  }
219  return ret;
220  }
221 
222 /* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
224  {
225  ENGINE *ret = NULL;
226  if(e == NULL)
227  {
230  return 0;
231  }
233  ret = e->next;
234  if(ret)
235  {
236  /* Return a valid structural refernce to the next ENGINE */
237  ret->struct_ref++;
238  engine_ref_debug(ret, 0, 1)
239  }
241  /* Release the structural reference to the previous ENGINE */
242  ENGINE_free(e);
243  return ret;
244  }
245 
247  {
248  ENGINE *ret = NULL;
249  if(e == NULL)
250  {
253  return 0;
254  }
256  ret = e->prev;
257  if(ret)
258  {
259  /* Return a valid structural reference to the next ENGINE */
260  ret->struct_ref++;
261  engine_ref_debug(ret, 0, 1)
262  }
264  /* Release the structural reference to the previous ENGINE */
265  ENGINE_free(e);
266  return ret;
267  }
268 
269 /* Add another "ENGINE" type into the list. */
271  {
272  int to_return = 1;
273  if(e == NULL)
274  {
277  return 0;
278  }
279  if((e->id == NULL) || (e->name == NULL))
280  {
283  }
285  if(!engine_list_add(e))
286  {
289  to_return = 0;
290  }
292  return to_return;
293  }
294 
295 /* Remove an existing "ENGINE" type from the array. */
297  {
298  int to_return = 1;
299  if(e == NULL)
300  {
303  return 0;
304  }
306  if(!engine_list_remove(e))
307  {
310  to_return = 0;
311  }
313  return to_return;
314  }
315 
316 static void engine_cpy(ENGINE *dest, const ENGINE *src)
317  {
318  dest->id = src->id;
319  dest->name = src->name;
320 #ifndef OPENSSL_NO_RSA
321  dest->rsa_meth = src->rsa_meth;
322 #endif
323 #ifndef OPENSSL_NO_DSA
324  dest->dsa_meth = src->dsa_meth;
325 #endif
326 #ifndef OPENSSL_NO_DH
327  dest->dh_meth = src->dh_meth;
328 #endif
329 #ifndef OPENSSL_NO_ECDH
330  dest->ecdh_meth = src->ecdh_meth;
331 #endif
332 #ifndef OPENSSL_NO_ECDSA
333  dest->ecdsa_meth = src->ecdsa_meth;
334 #endif
335  dest->rand_meth = src->rand_meth;
336  dest->store_meth = src->store_meth;
337  dest->ciphers = src->ciphers;
338  dest->digests = src->digests;
339  dest->pkey_meths = src->pkey_meths;
340  dest->destroy = src->destroy;
341  dest->init = src->init;
342  dest->finish = src->finish;
343  dest->ctrl = src->ctrl;
344  dest->load_privkey = src->load_privkey;
345  dest->load_pubkey = src->load_pubkey;
346  dest->cmd_defns = src->cmd_defns;
347  dest->flags = src->flags;
348  }
349 
350 ENGINE *ENGINE_by_id(const char *id)
351  {
352  ENGINE *iterator;
353  char *load_dir = NULL;
354  if(id == NULL)
355  {
358  return NULL;
359  }
361  iterator = engine_list_head;
362  while(iterator && (strcmp(id, iterator->id) != 0))
363  iterator = iterator->next;
364  if(iterator)
365  {
366  /* We need to return a structural reference. If this is an
367  * ENGINE type that returns copies, make a duplicate - otherwise
368  * increment the existing ENGINE's reference count. */
369  if(iterator->flags & ENGINE_FLAGS_BY_ID_COPY)
370  {
371  ENGINE *cp = ENGINE_new();
372  if(!cp)
373  iterator = NULL;
374  else
375  {
376  engine_cpy(cp, iterator);
377  iterator = cp;
378  }
379  }
380  else
381  {
382  iterator->struct_ref++;
383  engine_ref_debug(iterator, 0, 1)
384  }
385  }
387 #if 0
388  if(iterator == NULL)
389  {
392  ERR_add_error_data(2, "id=", id);
393  }
394  return iterator;
395 #else
396  /* EEK! Experimental code starts */
397  if(iterator) return iterator;
398  /* Prevent infinite recusrion if we're looking for the dynamic engine. */
399  if (strcmp(id, "dynamic"))
400  {
401 #ifdef OPENSSL_SYS_VMS
402  if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]";
403 #else
404  if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR;
405 #endif
406  iterator = ENGINE_by_id("dynamic");
407  if(!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
408  !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
409  !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
410  load_dir, 0) ||
411  !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
412  goto notfound;
413  return iterator;
414  }
415 notfound:
416  ENGINE_free(iterator);
418  ERR_add_error_data(2, "id=", id);
419  return NULL;
420  /* EEK! Experimental code ends */
421 #endif
422  }
423 
425  {
426  if (e == NULL)
427  {
429  return 0;
430  }
432  return 1;
433  }