1 /* $OpenBSD: sysdep.c,v 1.15 2001/08/12 12:03:02 heko 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/types.h> 38 #include <sys/socket.h> 39 #include <netinet/in.h> 40 #include <arpa/inet.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include "sysdep.h" 45 46 #include "util.h" 47 48 #ifdef NEED_SYSDEP_APP 49 #include "app.h" 50 #include "conf.h" 51 #include "ipsec.h" 52 53 #ifdef USE_PF_KEY_V2 54 #include "pf_key_v2.h" 55 #define KEY_API(x) pf_key_v2_##x 56 #endif 57 58 #endif /* NEED_SYSDEP_APP */ 59 #include "log.h" 60 61 extern char *__progname; 62 63 /* 64 * An as strong as possible random number generator, reverting to a 65 * deterministic pseudo-random one if regrand is set. 66 */ 67 u_int32_t 68 sysdep_random () 69 { 70 if (!regrand) 71 return arc4random (); 72 else 73 return random(); 74 } 75 76 /* Return the basename of the command used to invoke us. */ 77 char * 78 sysdep_progname () 79 { 80 return __progname; 81 } 82 83 /* As regress/ use this file I protect the sysdep_app_* stuff like this. */ 84 #ifdef NEED_SYSDEP_APP 85 /* 86 * Prepare the application we negotiate SAs for (i.e. the IPsec stack) 87 * for communication. We return a file descriptor useable to select(2) on. 88 */ 89 int 90 sysdep_app_open () 91 { 92 return KEY_API(open) (); 93 } 94 95 /* 96 * When select(2) has noticed our application needs attendance, this is what 97 * gets called. FD is the file descriptor causing the alarm. 98 */ 99 void 100 sysdep_app_handler (int fd) 101 { 102 KEY_API (handler) (fd); 103 } 104 105 /* Check that the connection named NAME is active, or else make it active. */ 106 void 107 sysdep_connection_check (char *name) 108 { 109 KEY_API (connection_check) (name); 110 } 111 112 /* 113 * Generate a SPI for protocol PROTO and the source/destination pair given by 114 * SRC, SRCLEN, DST & DSTLEN. Stash the SPI size in SZ. 115 */ 116 u_int8_t * 117 sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, 118 struct sockaddr *dst, u_int32_t seq) 119 { 120 if (app_none) 121 { 122 *sz = IPSEC_SPI_SIZE; 123 /* XXX should be random instead I think. */ 124 return strdup ("\x12\x34\x56\x78"); 125 } 126 return KEY_API (get_spi) (sz, proto, src, dst, seq); 127 } 128 129 /* Force communication on socket FD to go in the clear. */ 130 int 131 sysdep_cleartext (int fd, int af) 132 { 133 int level, sw; 134 struct 135 { 136 int ip_proto; /* IP protocol */ 137 int auth_level; 138 int esp_trans_level; 139 int esp_network_level; 140 } optsw[] = 141 { 142 { IPPROTO_IP, IP_AUTH_LEVEL, IP_ESP_TRANS_LEVEL, IP_ESP_NETWORK_LEVEL }, 143 { IPPROTO_IPV6, IPV6_AUTH_LEVEL, IPV6_ESP_TRANS_LEVEL, 144 IPV6_ESP_NETWORK_LEVEL }, 145 }; 146 147 if (app_none) 148 return 0; 149 150 switch (af) 151 { 152 case AF_INET: 153 sw = 0; 154 break; 155 case AF_INET6: 156 sw = 1; 157 break; 158 default: 159 log_print ("sysdep_cleartext: unsupported protocol family %d", af); 160 return -1; 161 } 162 163 /* 164 * Need to bypass system security policy, so I can send and 165 * receive key management datagrams in the clear. 166 */ 167 level = IPSEC_LEVEL_BYPASS; 168 if (setsockopt (fd, optsw[sw].ip_proto, optsw[sw].auth_level, (char *)&level, 169 sizeof level) == -1) 170 { 171 log_error ("sysdep_cleartext: " 172 "setsockopt (%d, %d, IP_AUTH_LEVEL, ...) failed", fd, 173 optsw[sw].ip_proto); 174 return -1; 175 } 176 if (setsockopt (fd, optsw[sw].ip_proto, optsw[sw].esp_trans_level, 177 (char *)&level, sizeof level) == -1) 178 { 179 log_error ("sysdep_cleartext: " 180 "setsockopt (%d, %d, IP_ESP_TRANS_LEVEL, ...) failed", fd, 181 optsw[sw].ip_proto); 182 return -1; 183 } 184 if (setsockopt (fd, optsw[sw].ip_proto, optsw[sw].esp_network_level, 185 (char *)&level, sizeof level) == -1) 186 { 187 log_error("sysdep_cleartext: " 188 "setsockopt (%d, %d, IP_ESP_NETWORK_LEVEL, ...) failed", fd, 189 optsw[sw].ip_proto); 190 return -1; 191 } 192 return 0; 193 } 194 195 int 196 sysdep_ipsec_delete_spi (struct sa *sa, struct proto *proto, int incoming) 197 { 198 if (app_none) 199 return 0; 200 return KEY_API (delete_spi) (sa, proto, incoming); 201 } 202 203 int 204 sysdep_ipsec_enable_sa (struct sa *sa, struct sa *isakmp_sa) 205 { 206 if (app_none) 207 return 0; 208 return KEY_API (enable_sa) (sa, isakmp_sa); 209 } 210 211 int 212 sysdep_ipsec_group_spis (struct sa *sa, struct proto *proto1, 213 struct proto *proto2, int incoming) 214 { 215 if (app_none) 216 return 0; 217 return KEY_API (group_spis) (sa, proto1, proto2, incoming); 218 } 219 220 int 221 sysdep_ipsec_set_spi (struct sa *sa, struct proto *proto, int incoming, 222 struct sa *isakmp_sa) 223 { 224 if (app_none) 225 return 0; 226 return KEY_API (set_spi) (sa, proto, incoming, isakmp_sa); 227 } 228 #endif 229