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