xref: /openbsd-src/sbin/isakmpd/sysdep/openbsd/sysdep.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: sysdep.c,v 1.25 2003/06/03 14:53:11 ho Exp $	*/
2 /*	$EOM: sysdep.c,v 1.9 2000/12/04 04:46:35 angelos Exp $	*/
3 
4 /*
5  * Copyright (c) 1998, 1999 Niklas Hallqvist.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * This code was written under funding by Ericsson Radio Systems.
30  */
31 
32 #include <sys/errno.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #include "sysdep.h"
41 
42 #include "monitor.h"
43 #include "util.h"
44 
45 #ifdef NEED_SYSDEP_APP
46 #include "app.h"
47 #include "conf.h"
48 #include "ipsec.h"
49 
50 #ifdef USE_PF_KEY_V2
51 #include "pf_key_v2.h"
52 #define KEY_API(x) pf_key_v2_##x
53 #endif
54 
55 #endif /* NEED_SYSDEP_APP */
56 #include "log.h"
57 
58 extern char *__progname;
59 
60 /*
61  * An as strong as possible random number generator, reverting to a
62  * deterministic pseudo-random one if regrand is set.
63  */
64 u_int32_t
65 sysdep_random ()
66 {
67   if (!regrand)
68     return arc4random ();
69   else
70     return random();
71 }
72 
73 /* Return the basename of the command used to invoke us.  */
74 char *
75 sysdep_progname ()
76 {
77   return __progname;
78 }
79 
80 /* Return the length of the sockaddr struct.  */
81 u_int8_t
82 sysdep_sa_len (struct sockaddr *sa)
83 {
84   return sa->sa_len;
85 }
86 
87 /* As regress/ use this file I protect the sysdep_app_* stuff like this.  */
88 #ifdef NEED_SYSDEP_APP
89 /*
90  * Prepare the application we negotiate SAs for (i.e. the IPsec stack)
91  * for communication.  We return a file descriptor useable to select(2) on.
92  */
93 int
94 sysdep_app_open ()
95 {
96   return KEY_API(open) ();
97 }
98 
99 /*
100  * When select(2) has noticed our application needs attendance, this is what
101  * gets called.  FD is the file descriptor causing the alarm.
102  */
103 void
104 sysdep_app_handler (int fd)
105 {
106   KEY_API (handler) (fd);
107 }
108 
109 /* Check that the connection named NAME is active, or else make it active.  */
110 void
111 sysdep_connection_check (char *name)
112 {
113   KEY_API (connection_check) (name);
114 }
115 
116 /*
117  * Generate a SPI for protocol PROTO and the source/destination pair given by
118  * SRC, SRCLEN, DST & DSTLEN.  Stash the SPI size in SZ.
119  */
120 u_int8_t *
121 sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src,
122 		      struct sockaddr *dst, u_int32_t seq)
123 {
124   if (app_none)
125     {
126       *sz = IPSEC_SPI_SIZE;
127       /* XXX should be random instead I think.  */
128       return (u_int8_t *)strdup ("\x12\x34\x56\x78");
129     }
130   return KEY_API (get_spi) (sz, proto, src, dst, seq);
131 }
132 
133 /* Force communication on socket FD to go in the clear.  */
134 int
135 sysdep_cleartext (int fd, int af)
136 {
137   int level, sw;
138   struct {
139     int ip_proto;		/* IP protocol */
140     int auth_level;
141     int esp_trans_level;
142     int esp_network_level;
143     int ipcomp_level;
144   } optsw[] =
145     {
146       {
147 	IPPROTO_IP,
148 	IP_AUTH_LEVEL,
149 	IP_ESP_TRANS_LEVEL,
150 	IP_ESP_NETWORK_LEVEL,
151 #ifdef IP_IPCOMP_LEVEL
152 	IP_IPCOMP_LEVEL
153 #else
154 	0
155 #endif
156       },
157       {
158 	IPPROTO_IPV6,
159 	IPV6_AUTH_LEVEL,
160 	IPV6_ESP_TRANS_LEVEL,
161 	IPV6_ESP_NETWORK_LEVEL,
162 #ifdef IPV6_IPCOMP_LEVEL
163 	IPV6_IPCOMP_LEVEL
164 #else
165 	0
166 #endif
167       },
168     };
169 
170   if (app_none)
171     return 0;
172 
173   switch (af)
174     {
175     case AF_INET:
176       sw = 0;
177       break;
178     case AF_INET6:
179       sw = 1;
180       break;
181     default:
182       log_print ("sysdep_cleartext: unsupported protocol family %d", af);
183       return -1;
184     }
185 
186   /*
187    * Need to bypass system security policy, so I can send and
188    * receive key management datagrams in the clear.
189    */
190   level = IPSEC_LEVEL_BYPASS;
191   if (monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].auth_level,
192 			  (char *)&level, sizeof level) == -1)
193     {
194       log_error ("sysdep_cleartext: "
195 		 "setsockopt (%d, %d, IP_AUTH_LEVEL, ...) failed", fd,
196 		 optsw[sw].ip_proto);
197       return -1;
198     }
199   if (monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].esp_trans_level,
200 			  (char *)&level, sizeof level) == -1)
201     {
202       log_error ("sysdep_cleartext: "
203 		 "setsockopt (%d, %d, IP_ESP_TRANS_LEVEL, ...) failed", fd,
204 		 optsw[sw].ip_proto);
205       return -1;
206     }
207   if (monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].esp_network_level,
208 			  (char *)&level, sizeof level) == -1)
209     {
210       log_error("sysdep_cleartext: "
211 		"setsockopt (%d, %d, IP_ESP_NETWORK_LEVEL, ...) failed", fd,
212 		optsw[sw].ip_proto);
213       return -1;
214     }
215   if (optsw[sw].ipcomp_level
216       && monitor_setsockopt (fd, optsw[sw].ip_proto, optsw[sw].ipcomp_level,
217 			     (char *)&level, sizeof level) == -1
218       && errno != ENOPROTOOPT)
219     {
220       log_error("sysdep_cleartext: "
221 		"setsockopt (%d, %d, IP_IPCOMP_LEVEL, ...) failed,", fd,
222 		optsw[sw].ip_proto);
223       return -1;
224     }
225   return 0;
226 }
227 
228 int
229 sysdep_ipsec_delete_spi (struct sa *sa, struct proto *proto, int incoming)
230 {
231   if (app_none)
232     return 0;
233   return KEY_API (delete_spi) (sa, proto, incoming);
234 }
235 
236 int
237 sysdep_ipsec_enable_sa (struct sa *sa, struct sa *isakmp_sa)
238 {
239   if (app_none)
240     return 0;
241   return KEY_API (enable_sa) (sa, isakmp_sa);
242 }
243 
244 int
245 sysdep_ipsec_group_spis (struct sa *sa, struct proto *proto1,
246 			 struct proto *proto2, int incoming)
247 {
248   if (app_none)
249     return 0;
250   return KEY_API (group_spis) (sa, proto1, proto2, incoming);
251 }
252 
253 int
254 sysdep_ipsec_set_spi (struct sa *sa, struct proto *proto, int incoming,
255 		      struct sa *isakmp_sa)
256 {
257   if (app_none)
258     return 0;
259   return KEY_API (set_spi) (sa, proto, incoming, isakmp_sa);
260 }
261 #endif
262