xref: /openbsd/sbin/isakmpd/sa.c (revision 78b63d65)
1 /*	$OpenBSD: sa.c,v 1.51 2001/11/21 10:01:43 ho Exp $	*/
2 /*	$EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $	*/
3 
4 /*
5  * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist.  All rights reserved.
6  * Copyright (c) 1999, 2001 Angelos D. Keromytis.  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  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
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  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by Ericsson Radio Systems.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * This code was written under funding by Ericsson Radio Systems.
36  */
37 
38 #include <sys/types.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #if defined (USE_KEYNOTE) || defined (USE_POLICY)
43 #include <regex.h>
44 #include <keynote.h>
45 #endif /* USE_KEYNOTE || USE_POLICY */
46 
47 #include "sysdep.h"
48 
49 #include "cookie.h"
50 #include "doi.h"
51 #include "exchange.h"
52 #include "isakmp.h"
53 #include "log.h"
54 #include "message.h"
55 #include "sa.h"
56 #include "timer.h"
57 #include "transport.h"
58 #include "util.h"
59 #include "cert.h"
60 #include "policy.h"
61 #include "key.h"
62 
63 /* Initial number of bits from the cookies used as hash.  */
64 #define INITIAL_BUCKET_BITS 6
65 
66 /*
67  * Don't try to use more bits than this as a hash.
68  * We only XOR 16 bits so going above that means changing the code below
69  * too.
70  */
71 #define MAX_BUCKET_BITS 16
72 
73 #if 0
74 static void sa_resize (void);
75 #endif
76 static void sa_dump (char *, struct sa *);
77 static void sa_soft_expire (void *);
78 static void sa_hard_expire (void *);
79 
80 static LIST_HEAD (sa_list, sa) *sa_tab;
81 
82 /* Works both as a maximum index and a mask.  */
83 static int bucket_mask;
84 
85 void
86 sa_init (void)
87 {
88   int i;
89 
90   bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1;
91   sa_tab = malloc ((bucket_mask + 1) * sizeof (struct sa_list));
92   if (!sa_tab)
93     log_fatal ("sa_init: malloc (%s) failed",
94 	       (bucket_mask + 1) * sizeof (struct sa_list));
95   for (i = 0; i <= bucket_mask; i++)
96     {
97       LIST_INIT (&sa_tab[i]);
98     }
99 }
100 
101 #if 0
102 /* XXX We don't yet resize.  */
103 static void
104 sa_resize (void)
105 {
106   int new_mask = (bucket_mask + 1) * 2 - 1;
107   int i;
108   struct sa_list *new_tab;
109 
110   new_tab = realloc (sa_tab, (new_mask + 1) * sizeof (struct sa_list));
111   if (!new_tab)
112     return;
113   sa_tab = new_tab;
114   for (i = bucket_mask + 1; i <= new_mask; i++)
115     {
116       LIST_INIT (&sa_tab[i]);
117     }
118   bucket_mask = new_mask;
119 
120   /* XXX Rehash existing entries.  */
121 }
122 #endif
123 
124 /* Lookup an SA with the help from a user-supplied checking function.  */
125 struct sa *
126 sa_find (int (*check) (struct sa *, void *), void *arg)
127 {
128   int i;
129   struct sa *sa;
130 
131   for (i = 0; i <= bucket_mask; i++)
132     for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = LIST_NEXT (sa, link))
133       if (check (sa, arg))
134       {
135 	LOG_DBG ((LOG_SA, 90, "sa_find: return SA %p", sa));
136 	return sa;
137       }
138   LOG_DBG ((LOG_SA, 90, "sa_find: no SA matched query"));
139   return 0;
140 }
141 
142 /* Check if SA is an ISAKMP SA with an initiar cookie equal to ICOOKIE.  */
143 static int
144 sa_check_icookie (struct sa *sa, void *icookie)
145 {
146   return sa->phase == 1
147     && memcmp (sa->cookies, icookie, ISAKMP_HDR_ICOOKIE_LEN) == 0;
148 }
149 
150 /* Lookup an ISAKMP SA out of just the initiator cookie.  */
151 struct sa *
152 sa_lookup_from_icookie (u_int8_t *cookie)
153 {
154   return sa_find (sa_check_icookie, cookie);
155 }
156 
157 struct name_phase_arg {
158   char *name;
159   u_int8_t phase;
160 };
161 
162 /* Check if SA has the name and phase given by V_ARG.  */
163 static int
164 sa_check_name_phase (struct sa *sa, void *v_arg)
165 {
166   struct name_phase_arg *arg = v_arg;
167 
168   return sa->name && strcasecmp (sa->name, arg->name) == 0 &&
169     sa->phase == arg->phase && !(sa->flags & SA_FLAG_REPLACED);
170 }
171 
172 /* Lookup an SA by name, case-independent, and phase.  */
173 struct sa *
174 sa_lookup_by_name (char *name, int phase)
175 {
176   struct name_phase_arg arg = { name, phase };
177 
178   return sa_find (sa_check_name_phase, &arg);
179 }
180 
181 struct addr_arg
182 {
183   struct sockaddr *addr;
184   socklen_t len;
185   int phase;
186   int flags;
187 };
188 
189 /*
190  * Check if SA is ready and has a peer with an address equal the one given
191  * by V_ADDR.  Furthermore if we are searching for a specific phase, check
192  * that too.
193  */
194 static int
195 sa_check_peer (struct sa *sa, void *v_addr)
196 {
197   struct addr_arg *addr = v_addr;
198   struct sockaddr *dst;
199 
200   if (!sa->transport || (sa->flags & SA_FLAG_READY) == 0
201       || (addr->phase && addr->phase != sa->phase))
202     return 0;
203 
204   sa->transport->vtbl->get_dst (sa->transport, &dst);
205   return sysdep_sa_len (dst) == addr->len
206     && memcmp (dst, addr->addr, sysdep_sa_len (dst)) == 0;
207 }
208 
209 struct dst_isakmpspi_arg {
210   struct sockaddr *dst;
211   u_int8_t *spi;			/* must be ISAKMP_SPI_SIZE octets */
212 };
213 
214 /*
215  * Check if SA matches what we are asking for through V_ARG.  It has to
216  * be a finished phaes 1 (ISAKMP) SA.
217  */
218 static int
219 isakmp_sa_check (struct sa *sa, void *v_arg)
220 {
221   struct dst_isakmpspi_arg *arg = v_arg;
222   struct sockaddr *dst, *src;
223 
224   if (sa->phase != 1 || !(sa->flags & SA_FLAG_READY))
225     return 0;
226 
227   /* verify address is either src or dst for this sa */
228   sa->transport->vtbl->get_dst (sa->transport, &dst);
229   sa->transport->vtbl->get_src (sa->transport, &src);
230   if (memcmp (src, arg->dst, sysdep_sa_len (src)) &&
231       memcmp (dst, arg->dst, sysdep_sa_len (dst)))
232     return 0;
233 
234   /* match icookie+rcookie against spi */
235   if (memcmp (sa->cookies, arg->spi, ISAKMP_HDR_COOKIES_LEN) == 0)
236     return 1;
237 
238   return 0;
239 }
240 
241 /*
242  * Find an ISAKMP SA with a "name" of DST & SPI.
243  */
244 struct sa *
245 sa_lookup_isakmp_sa (struct sockaddr *dst, u_int8_t *spi)
246 {
247   struct dst_isakmpspi_arg arg = { dst, spi };
248 
249   return sa_find (isakmp_sa_check, &arg);
250 }
251 
252 /* Lookup a ready SA by the peer's address.  */
253 struct sa *
254 sa_lookup_by_peer (struct sockaddr *dst, socklen_t dstlen)
255 {
256   struct addr_arg arg = { dst, dstlen, 0 };
257 
258   return sa_find (sa_check_peer, &arg);
259 }
260 
261 /* Lookup a ready ISAKMP SA given its peer address.  */
262 struct sa *
263 sa_isakmp_lookup_by_peer (struct sockaddr *dst, socklen_t dstlen)
264 {
265   struct addr_arg arg = { dst, dstlen, 1 };
266 
267   return sa_find (sa_check_peer, &arg);
268 }
269 
270 int
271 sa_enter (struct sa *sa)
272 {
273   u_int16_t bucket = 0;
274   int i;
275   u_int8_t *cp;
276 
277   /* XXX We might resize if we are crossing a certain threshold */
278 
279   for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2)
280     {
281       cp = sa->cookies + i;
282       /* Doing it this way avoids alignment problems.  */
283       bucket ^= cp[0] | cp[1] << 8;
284     }
285   for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2)
286     {
287       cp = sa->message_id + i;
288       /* Doing it this way avoids alignment problems.  */
289       bucket ^= cp[0] | cp[1] << 8;
290     }
291   bucket &= bucket_mask;
292   LIST_INSERT_HEAD (&sa_tab[bucket], sa, link);
293   sa_reference (sa);
294   LOG_DBG ((LOG_SA, 70, "sa_enter: SA %p added to SA list", sa));
295   return 1;
296 }
297 
298 /*
299  * Lookup the SA given by the header fields MSG.  PHASE2 is false when
300  * looking for phase 1 SAa and true otherwise.
301  */
302 struct sa *
303 sa_lookup_by_header (u_int8_t *msg, int phase2)
304 {
305   return sa_lookup (msg + ISAKMP_HDR_COOKIES_OFF,
306 		    phase2 ? msg + ISAKMP_HDR_MESSAGE_ID_OFF : 0);
307 }
308 
309 /*
310  * Lookup the SA given by the COOKIES and possibly the MESSAGE_ID unless
311  * a null pointer, meaning we are looking for phase 1 SAs.
312  */
313 struct sa *
314 sa_lookup (u_int8_t *cookies, u_int8_t *message_id)
315 {
316   u_int16_t bucket = 0;
317   int i;
318   struct sa *sa;
319   u_int8_t *cp;
320 
321   /*
322    * We use the cookies to get bits to use as an index into sa_tab, as at
323    * least one (our cookie) is a good hash, xoring all the bits, 16 at a
324    * time, and then masking, should do.  Doing it this way means we can
325    * validate cookies very fast thus delimiting the effects of "Denial of
326    * service"-attacks using packet flooding.
327    */
328   for (i = 0; i < ISAKMP_HDR_COOKIES_LEN; i += 2)
329     {
330       cp = cookies + i;
331       /* Doing it this way avoids alignment problems.  */
332       bucket ^= cp[0] | cp[1] << 8;
333     }
334   if (message_id)
335     for (i = 0; i < ISAKMP_HDR_MESSAGE_ID_LEN; i += 2)
336       {
337 	cp = message_id + i;
338 	/* Doing it this way avoids alignment problems.  */
339 	bucket ^= cp[0] | cp[1] << 8;
340       }
341   bucket &= bucket_mask;
342   for (sa = LIST_FIRST (&sa_tab[bucket]);
343        sa && (memcmp (cookies, sa->cookies, ISAKMP_HDR_COOKIES_LEN) != 0
344 	      || (message_id && memcmp (message_id, sa->message_id,
345 					ISAKMP_HDR_MESSAGE_ID_LEN)
346 		  != 0)
347 	      || (!message_id && !zero_test (sa->message_id,
348 					     ISAKMP_HDR_MESSAGE_ID_LEN)));
349        sa = LIST_NEXT (sa, link))
350     ;
351 
352   return sa;
353 }
354 
355 /* Create an SA.  */
356 int
357 sa_create (struct exchange *exchange, struct transport *t)
358 {
359   struct sa *sa;
360 
361   /*
362    * We want the SA zeroed for sa_free to be able to find out what fields
363    * have been filled-in.
364    */
365   sa = calloc (1, sizeof *sa);
366   if (!sa)
367     {
368       log_error ("sa_create: calloc (1, %d) failed", sizeof *sa);
369       return -1;
370     }
371   sa->transport = t;
372   if (t)
373     transport_reference (t);
374   sa->phase = exchange->phase;
375   memcpy (sa->cookies, exchange->cookies, ISAKMP_HDR_COOKIES_LEN);
376   memcpy (sa->message_id, exchange->message_id, ISAKMP_HDR_MESSAGE_ID_LEN);
377   sa->doi = exchange->doi;
378   sa->policy_id = -1;
379 
380   if (sa->doi->sa_size)
381     {
382       /* Allocate the DOI-specific structure and initialize it to zeroes.  */
383       sa->data = calloc (1, sa->doi->sa_size);
384       if (!sa->data)
385 	{
386 	  log_error ("sa_create: calloc (1, %d) failed", sa->doi->sa_size);
387 	  free (sa);
388 	  return -1;
389 	}
390     }
391 
392   TAILQ_INIT (&sa->protos);
393 
394   sa_enter (sa);
395   TAILQ_INSERT_TAIL (&exchange->sa_list, sa, next);
396   sa_reference (sa);
397 
398   LOG_DBG ((LOG_SA, 60,
399 	    "sa_create: sa %p phase %d added to exchange %p (%s)", sa,
400 	    sa->phase, exchange,
401 	    exchange->name ? exchange->name : "<unnamed>"));
402   return 0;
403 }
404 
405 /*
406  * Dump the internal state of SA to the report channel, with HEADER
407  * prepended to each line.
408  */
409 static void
410 sa_dump (char *header, struct sa *sa)
411 {
412   struct proto *proto;
413   char spi_header[80];
414   int i;
415 
416   LOG_DBG ((LOG_REPORT, 0, "%s: %p %s phase %d doi %d flags 0x%x",
417 	    header, sa, sa->name ? sa->name : "<unnamed>", sa->phase,
418 	    sa->doi->id, sa->flags));
419   LOG_DBG ((LOG_REPORT, 0,
420 	    "%s: icookie %08x%08x rcookie %08x%08x", header,
421 	    decode_32 (sa->cookies), decode_32 (sa->cookies + 4),
422 	    decode_32 (sa->cookies + 8), decode_32 (sa->cookies + 12)));
423   LOG_DBG ((LOG_REPORT, 0, "%s: msgid %08x refcnt %d", header,
424 	    decode_32 (sa->message_id), sa->refcnt));
425   LOG_DBG ((LOG_REPORT, 0, "%s: life secs %llu kb %llu", header,
426 	    sa->seconds, sa->kilobytes));
427   for (proto = TAILQ_FIRST (&sa->protos); proto;
428        proto = TAILQ_NEXT (proto, link))
429     {
430       LOG_DBG ((LOG_REPORT, 0,
431 		"%s: suite %d proto %d", header, proto->no, proto->proto));
432       LOG_DBG ((LOG_REPORT, 0,
433 		"%s: spi_sz[0] %d spi[0] %p spi_sz[1] %d spi[1] %p", header,
434 		proto->spi_sz[0], proto->spi[0], proto->spi_sz[1],
435 		proto->spi[1]));
436       LOG_DBG ((LOG_REPORT, 0, "%s: %s, %s", header,
437 		!sa->doi ? "<nodoi>"
438 		: sa->doi->decode_ids ("initiator id: %s, responder id: %s",
439 				     sa->id_i, sa->id_i_len,
440 				     sa->id_r, sa->id_r_len, 0),
441 		!sa->transport ? "<no transport>" :
442 		sa->transport->vtbl->decode_ids (sa->transport)));
443       for (i = 0; i < 2; i++)
444 	if (proto->spi[i])
445 	  {
446 	    snprintf (spi_header, 80, "%s: spi[%d]", header, i);
447 	    LOG_DBG_BUF ((LOG_REPORT, 0, spi_header, proto->spi[i],
448 			  proto->spi_sz[i]));
449 	  }
450     }
451 }
452 
453 /* Report all the SAs to the report channel.  */
454 void
455 sa_report (void)
456 {
457   int i;
458   struct sa *sa;
459 
460   for (i = 0; i <= bucket_mask; i++)
461     for (sa = LIST_FIRST (&sa_tab[i]); sa; sa = LIST_NEXT (sa, link))
462       sa_dump ("sa_report", sa);
463 }
464 
465 /* Free the protocol structure pointed to by PROTO.  */
466 void
467 proto_free (struct proto *proto)
468 {
469   int i;
470   struct sa *sa = proto->sa;
471 
472   for (i = 0; i < 2; i++)
473     if (proto->spi[i])
474       {
475 	if (sa->doi->delete_spi)
476 	  sa->doi->delete_spi (sa, proto, i);
477 	free (proto->spi[i]);
478       }
479   TAILQ_REMOVE (&sa->protos, proto, link);
480   if (proto->data)
481     {
482       if (sa->doi && sa->doi->free_proto_data)
483 	sa->doi->free_proto_data (proto->data);
484       free (proto->data);
485     }
486 
487   /* XXX Use class LOG_SA instead?  */
488   LOG_DBG ((LOG_MISC, 90, "proto_free: freeing %p", proto));
489 
490   free (proto);
491 }
492 
493 /* Release all resources this SA is using.  */
494 void
495 sa_free (struct sa *sa)
496 {
497   if (sa->death)
498     {
499       timer_remove_event (sa->death);
500       sa->death = 0;
501       sa->refcnt--;
502     }
503   if (sa->soft_death)
504     {
505       timer_remove_event (sa->soft_death);
506       sa->soft_death = 0;
507       sa->refcnt--;
508     }
509   sa_remove (sa);
510 }
511 
512 /* Remove the SA from the hash table of live SAs.  */
513 void
514 sa_remove (struct sa *sa)
515 {
516   LIST_REMOVE (sa, link);
517   LOG_DBG ((LOG_SA, 70, "sa_remove: SA %p removed from SA list", sa));
518   sa_release (sa);
519 }
520 
521 /* Raise the reference count of SA.  */
522 void
523 sa_reference (struct sa *sa)
524 {
525   sa->refcnt++;
526   LOG_DBG ((LOG_SA, 80, "sa_reference: SA %p now has %d references",
527 	    sa, sa->refcnt));
528 }
529 
530 /* Release a reference to SA.  */
531 void
532 sa_release (struct sa *sa)
533 {
534   struct proto *proto;
535   struct cert_handler *handler;
536 
537   LOG_DBG ((LOG_SA, 80, "sa_release: SA %p had %d references",
538 	    sa, sa->refcnt));
539 
540   if (--sa->refcnt)
541     return;
542 
543   LOG_DBG ((LOG_SA, 60, "sa_release: freeing SA %p", sa));
544 
545   while ((proto = TAILQ_FIRST (&sa->protos)) != 0)
546     proto_free (proto);
547   if (sa->data)
548     {
549       if (sa->doi && sa->doi->free_sa_data)
550 	sa->doi->free_sa_data (sa->data);
551       free (sa->data);
552     }
553   if (sa->id_i)
554     free (sa->id_i);
555   if (sa->id_r)
556     free (sa->id_r);
557   if (sa->recv_cert)
558     {
559 	handler = cert_get (sa->recv_certtype);
560 	if (handler)
561 	  handler->cert_free (sa->recv_cert);
562     }
563   if (sa->sent_cert)
564     {
565 	handler = cert_get (sa->sent_certtype);
566 	if (handler)
567 	  handler->cert_free (sa->sent_cert);
568     }
569   if (sa->recv_key)
570     key_free (sa->recv_keytype, ISAKMP_KEYTYPE_PUBLIC, sa->recv_key);
571   if (sa->sent_key)
572     key_free (sa->sent_keytype, ISAKMP_KEYTYPE_PRIVATE, sa->sent_key);
573   if (sa->keynote_key)
574     free (sa->keynote_key); /* This is just a string */
575 #if defined (USE_POLICY) || defined (USE_KEYNOTE)
576   if (sa->policy_id != -1)
577     LK (kn_close, (sa->policy_id));
578 #endif
579   if (sa->name)
580     free (sa->name);
581   if (sa->keystate)
582     free (sa->keystate);
583   if (sa->transport)
584     transport_release (sa->transport);
585   free (sa);
586 }
587 
588 /*
589  * Rehash the ISAKMP SA this MSG is negotiating with the responder cookie
590  * filled in.
591  */
592 void
593 sa_isakmp_upgrade (struct message *msg)
594 {
595   struct sa *sa = TAILQ_FIRST (&msg->exchange->sa_list);
596 
597   sa_remove (sa);
598   GET_ISAKMP_HDR_RCOOKIE (msg->iov[0].iov_base,
599 			  sa->cookies + ISAKMP_HDR_ICOOKIE_LEN);
600 
601   /*
602    * We don't install a transport in the initiator case as we don't know
603    * what local address will be chosen.  Do it now instead.
604    */
605   sa->transport = msg->transport;
606   transport_reference (sa->transport);
607   sa_enter (sa);
608 }
609 
610 /*
611  * Register the chosen transform XF into SA.  As a side effect set PROTOP
612  * to point at the corresponding proto structure.  INITIATOR is true if we
613  * are the initiator.
614  */
615 int
616 sa_add_transform (struct sa *sa, struct payload *xf, int initiator,
617 		  struct proto **protop)
618 {
619   struct proto *proto;
620   struct payload *prop = xf->context;
621 
622   *protop = 0;
623   if (!initiator)
624     {
625       proto = calloc (1, sizeof *proto);
626       if (!proto)
627 	log_error ("sa_add_transform: calloc (1, %d) failed", sizeof *proto);
628     }
629   else
630     /* Find the protection suite that were chosen.  */
631     for (proto = TAILQ_FIRST (&sa->protos);
632 	 proto && proto->no != GET_ISAKMP_PROP_NO (prop->p);
633 	 proto = TAILQ_NEXT (proto, link))
634       ;
635   if (!proto)
636     return -1;
637   *protop = proto;
638 
639   /* Allocate DOI-specific part.  */
640   if (!initiator)
641     {
642       proto->data = calloc (1, sa->doi->proto_size);
643       if (!proto->data)
644 	{
645 	  log_error ("sa_add_transform: calloc (1, %d) failed",
646 		     sa->doi->proto_size);
647 	  goto cleanup;
648 	}
649     }
650 
651   proto->no = GET_ISAKMP_PROP_NO (prop->p);
652   proto->proto = GET_ISAKMP_PROP_PROTO (prop->p);
653   proto->spi_sz[0] = GET_ISAKMP_PROP_SPI_SZ (prop->p);
654   if (proto->spi_sz[0])
655     {
656       proto->spi[0] = malloc (proto->spi_sz[0]);
657       if (!proto->spi[0])
658 	goto cleanup;
659       memcpy (proto->spi[0], prop->p + ISAKMP_PROP_SPI_OFF, proto->spi_sz[0]);
660     }
661   proto->chosen = xf;
662   proto->sa = sa;
663   proto->id = GET_ISAKMP_TRANSFORM_ID (xf->p);
664   if (!initiator)
665     TAILQ_INSERT_TAIL (&sa->protos, proto, link);
666 
667   /* Let the DOI get at proto for initializing its own data.  */
668   if (sa->doi->proto_init)
669     sa->doi->proto_init (proto, 0);
670 
671   LOG_DBG ((LOG_SA, 80,
672 	    "sa_add_transform: "
673 	    "proto %p no %d proto %d chosen %p sa %p id %d",
674 	    proto, proto->no, proto->proto, proto->chosen, proto->sa,
675 	    proto->id));
676 
677   return 0;
678 
679  cleanup:
680   if (!initiator)
681     {
682       if (proto->data)
683 	free (proto->data);
684       free (proto);
685     }
686   *protop = 0;
687   return -1;
688 }
689 
690 /* Delete an SA.  Tell the peer if NOTIFY is set.  */
691 void
692 sa_delete (struct sa *sa, int notify)
693 {
694   /* Don't bother notifying of Phase 1 SA deletes.  */
695   if (sa->phase != 1 && notify)
696     message_send_delete (sa);
697   sa_free (sa);
698 }
699 
700 /*
701  * This function will get called when we are closing in on the death time of SA
702  */
703 static void
704 sa_soft_expire (void *v_sa)
705 {
706   struct sa *sa = v_sa;
707 
708   sa->soft_death = 0;
709   sa_release (sa);
710 
711   if ((sa->flags & (SA_FLAG_STAYALIVE | SA_FLAG_REPLACED))
712       == SA_FLAG_STAYALIVE)
713     exchange_establish (sa->name, 0, 0);
714   else
715     /*
716      * Start to watch the use of this SA, so a renegotiation can
717      * happen as soon as it is shown to be alive.
718      */
719     sa->flags |= SA_FLAG_FADING;
720 }
721 
722 /* SA has passed its best before date.  */
723 static void
724 sa_hard_expire (void *v_sa)
725 {
726   struct sa *sa = v_sa;
727 
728   sa->death = 0;
729   sa_release (sa);
730 
731   if ((sa->flags & (SA_FLAG_STAYALIVE | SA_FLAG_REPLACED))
732       == SA_FLAG_STAYALIVE)
733     exchange_establish (sa->name, 0, 0);
734 
735   sa_delete (sa, 1);
736 }
737 
738 /*
739  * Get an SA attribute's flag value out of textual description.
740  */
741 int
742 sa_flag (char *attr)
743 {
744   static struct sa_flag_map {
745     char *name;
746     int flag;
747   } sa_flag_map[] = {
748     { "active-only", SA_FLAG_ACTIVE_ONLY },
749     /* Below this point are flags that are internal to the implementation.  */
750     { "__ondemand", SA_FLAG_ONDEMAND }
751   };
752   int i;
753 
754   for (i = 0; i < sizeof sa_flag_map / sizeof sa_flag_map[0]; i++)
755     if (strcasecmp (attr, sa_flag_map[i].name) == 0)
756       return sa_flag_map[i].flag;
757   log_print ("sa_flag: attribute \"%s\" unknown", attr);
758   return 0;
759 }
760 
761 /* Mark SA as replaced.  */
762 void
763 sa_mark_replaced (struct sa *sa)
764 {
765   LOG_DBG ((LOG_SA, 60, "sa_mark_replaced: SA %p (%s) marked as replaced",
766 	    sa, sa->name ? sa->name : "unnamed"));
767   sa->flags |= SA_FLAG_REPLACED;
768 }
769 
770 /*
771  * Setup expiration timers for SA.  This is used for ISAKMP SAs, but also
772  * possible to use for application SAs if the application does not deal
773  * with expirations itself.  An example is the Linux FreeS/WAN KLIPS IPsec
774  * stack.
775  */
776 int
777 sa_setup_expirations (struct sa *sa)
778 {
779   u_int64_t seconds = sa->seconds;
780   struct timeval expiration;
781 
782   /*
783    * Set the soft timeout to a random percentage between 85 & 95 of
784    * the negotiated lifetime to break strictly synchronized
785    * renegotiations.  This works better when the randomization is on the
786    * order of processing plus network-roundtrip times, or larger.
787    * I.e. it depends on configuration and negotiated lifetimes.
788    * It is not good to do the decrease on the hard timeout, because then
789    * we may drop our SA before our peer.
790    * XXX Better scheme to come?
791    */
792   if (!sa->soft_death)
793     {
794       gettimeofday (&expiration, 0);
795       /* XXX This should probably be configuration controlled somehow.  */
796       seconds = sa->seconds * (850 + sysdep_random () % 100) / 1000;
797       LOG_DBG ((LOG_TIMER, 95,
798 		"sa_setup_expirations: SA %p soft timeout in %llu seconds",
799 		sa, seconds));
800       expiration.tv_sec += seconds;
801       sa->soft_death
802 	= timer_add_event ("sa_soft_expire", sa_soft_expire, sa, &expiration);
803       if (!sa->soft_death)
804 	{
805 	  /* If we don't give up we might start leaking...  */
806 	  sa_delete (sa, 1);
807 	  return -1;
808 	}
809       sa_reference (sa);
810     }
811 
812   if (!sa->death)
813     {
814       gettimeofday (&expiration, 0);
815       LOG_DBG ((LOG_TIMER, 95,
816 		"sa_setup_expirations: SA %p hard timeout in %llu seconds",
817 		sa, sa->seconds));
818       expiration.tv_sec += sa->seconds;
819       sa->death
820 	= timer_add_event ("sa_hard_expire", sa_hard_expire, sa, &expiration);
821       if (!sa->death)
822 	{
823 	  /* If we don't give up we might start leaking...  */
824 	  sa_delete (sa, 1);
825 	  return -1;
826 	}
827       sa_reference (sa);
828     }
829   return 0;
830 }
831