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