1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.ipsec.ike; 18 19 import static android.system.OsConstants.AF_INET; 20 import static android.system.OsConstants.AF_INET6; 21 22 import android.annotation.IntRange; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.SystemApi; 26 import android.net.LinkAddress; 27 28 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Address; 29 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Dhcp; 30 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Dns; 31 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; 32 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Address; 33 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Dns; 34 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.TunnelModeChildConfigAttribute; 35 36 import java.net.Inet4Address; 37 import java.net.Inet6Address; 38 import java.net.InetAddress; 39 import java.util.Arrays; 40 import java.util.Collections; 41 import java.util.LinkedList; 42 import java.util.List; 43 import java.util.Objects; 44 45 /** 46 * TunnelModeChildSessionParams represents proposed configurations for negotiating a tunnel mode 47 * Child Session. 48 * 49 * @hide 50 */ 51 @SystemApi 52 public final class TunnelModeChildSessionParams extends ChildSessionParams { 53 @NonNull private final TunnelModeChildConfigAttribute[] mConfigRequests; 54 TunnelModeChildSessionParams( @onNull IkeTrafficSelector[] inboundTs, @NonNull IkeTrafficSelector[] outboundTs, @NonNull ChildSaProposal[] proposals, @NonNull TunnelModeChildConfigAttribute[] configRequests, int hardLifetimeSec, int softLifetimeSec)55 private TunnelModeChildSessionParams( 56 @NonNull IkeTrafficSelector[] inboundTs, 57 @NonNull IkeTrafficSelector[] outboundTs, 58 @NonNull ChildSaProposal[] proposals, 59 @NonNull TunnelModeChildConfigAttribute[] configRequests, 60 int hardLifetimeSec, 61 int softLifetimeSec) { 62 super( 63 inboundTs, 64 outboundTs, 65 proposals, 66 hardLifetimeSec, 67 softLifetimeSec, 68 false /*isTransport*/); 69 mConfigRequests = configRequests; 70 } 71 72 /** @hide */ getConfigurationAttributesInternal()73 public TunnelModeChildConfigAttribute[] getConfigurationAttributesInternal() { 74 return mConfigRequests; 75 } 76 77 /** Retrieves the list of Configuration Requests */ 78 @NonNull getConfigurationRequests()79 public List<TunnelModeChildConfigRequest> getConfigurationRequests() { 80 return Collections.unmodifiableList(Arrays.asList(mConfigRequests)); 81 } 82 83 /** Represents a tunnel mode child session configuration request type */ 84 public interface TunnelModeChildConfigRequest {} 85 86 /** Represents an IPv4 Internal Address request */ 87 public interface ConfigRequestIpv4Address extends TunnelModeChildConfigRequest { 88 /** 89 * Retrieves the requested internal IPv4 address 90 * 91 * @return The requested IPv4 address, or null if no specific internal address was requested 92 */ 93 @Nullable getAddress()94 Inet4Address getAddress(); 95 } 96 97 /** Represents an IPv4 DHCP server request */ 98 public interface ConfigRequestIpv4DhcpServer extends TunnelModeChildConfigRequest {} 99 100 /** Represents an IPv4 DNS Server request */ 101 public interface ConfigRequestIpv4DnsServer extends TunnelModeChildConfigRequest {} 102 103 /** Represents an IPv4 Netmask request */ 104 public interface ConfigRequestIpv4Netmask extends TunnelModeChildConfigRequest {} 105 106 /** Represents an IPv6 Internal Address request */ 107 public interface ConfigRequestIpv6Address extends TunnelModeChildConfigRequest { 108 /** 109 * Retrieves the requested internal IPv6 address 110 * 111 * @return The requested IPv6 address, or null if no specific internal address was requested 112 */ 113 @Nullable getAddress()114 Inet6Address getAddress(); 115 116 /** 117 * Retrieves the prefix length 118 * 119 * @return The requested prefix length, or -1 if no specific IPv6 address was requested 120 */ getPrefixLength()121 int getPrefixLength(); 122 } 123 124 /** Represents an IPv6 DNS Server request */ 125 public interface ConfigRequestIpv6DnsServer extends TunnelModeChildConfigRequest {} 126 127 /** This class can be used to incrementally construct a {@link TunnelModeChildSessionParams}. */ 128 public static final class Builder extends ChildSessionParams.Builder { 129 private static final int IPv4_DEFAULT_PREFIX_LEN = 32; 130 131 private boolean mHasIp4AddressRequest; 132 private List<TunnelModeChildConfigAttribute> mConfigRequestList; 133 134 /** Create a Builder for negotiating a transport mode Child Session. */ Builder()135 public Builder() { 136 super(); 137 mHasIp4AddressRequest = false; 138 mConfigRequestList = new LinkedList<>(); 139 } 140 141 /** 142 * Adds an Child SA proposal to the {@link TunnelModeChildSessionParams} being built. 143 * 144 * @param proposal Child SA proposal. 145 * @return Builder this, to facilitate chaining. 146 */ 147 @NonNull addSaProposal(@onNull ChildSaProposal proposal)148 public Builder addSaProposal(@NonNull ChildSaProposal proposal) { 149 if (proposal == null) { 150 throw new NullPointerException("Required argument not provided"); 151 } 152 153 addProposal(proposal); 154 return this; 155 } 156 157 /** 158 * Adds an inbound {@link IkeTrafficSelector} to the {@link TunnelModeChildSessionParams} 159 * being built. 160 * 161 * <p>This method allows callers to limit the inbound traffic transmitted over the Child 162 * Session to the given range. The IKE server may further narrow the range. Callers should 163 * refer to {@link ChildSessionConfiguration} for the negotiated traffic selectors. 164 * 165 * <p>If no inbound {@link IkeTrafficSelector} is provided, a default value will be used 166 * that covers all IP addresses and ports. 167 * 168 * @param trafficSelector the inbound {@link IkeTrafficSelector}. 169 * @return Builder this, to facilitate chaining. 170 */ 171 @NonNull addInboundTrafficSelectors(@onNull IkeTrafficSelector trafficSelector)172 public Builder addInboundTrafficSelectors(@NonNull IkeTrafficSelector trafficSelector) { 173 Objects.requireNonNull(trafficSelector, "Required argument not provided"); 174 addInboundTs(trafficSelector); 175 return this; 176 } 177 178 /** 179 * Adds an outbound {@link IkeTrafficSelector} to the {@link TunnelModeChildSessionParams} 180 * being built. 181 * 182 * <p>This method allows callers to limit the outbound traffic transmitted over the Child 183 * Session to the given range. The IKE server may further narrow the range. Callers should 184 * refer to {@link ChildSessionConfiguration} for the negotiated traffic selectors. 185 * 186 * <p>If no outbound {@link IkeTrafficSelector} is provided, a default value will be used 187 * that covers all IP addresses and ports. 188 * 189 * @param trafficSelector the outbound {@link IkeTrafficSelector}. 190 * @return Builder this, to facilitate chaining. 191 */ 192 @NonNull addOutboundTrafficSelectors(@onNull IkeTrafficSelector trafficSelector)193 public Builder addOutboundTrafficSelectors(@NonNull IkeTrafficSelector trafficSelector) { 194 Objects.requireNonNull(trafficSelector, "Required argument not provided"); 195 addOutboundTs(trafficSelector); 196 return this; 197 } 198 199 /** 200 * Sets hard and soft lifetimes. 201 * 202 * <p>Lifetimes will not be negotiated with the remote IKE server. 203 * 204 * @param hardLifetimeSeconds number of seconds after which Child SA will expire. Defaults 205 * to 7200 seconds (2 hours). Considering IPsec packet lifetime, IKE library requires 206 * hard lifetime to be a value from 300 seconds (5 minutes) to 14400 seconds (4 hours), 207 * inclusive. 208 * @param softLifetimeSeconds number of seconds after which Child SA will request rekey. 209 * Defaults to 3600 seconds (1 hour). MUST be at least 120 seconds (2 minutes), and at 210 * least 60 seconds (1 minute) shorter than the hard lifetime. 211 */ 212 @NonNull setLifetimeSeconds( @ntRange from = CHILD_HARD_LIFETIME_SEC_MINIMUM, to = CHILD_HARD_LIFETIME_SEC_MAXIMUM) int hardLifetimeSeconds, @IntRange( from = CHILD_SOFT_LIFETIME_SEC_MINIMUM, to = CHILD_HARD_LIFETIME_SEC_MAXIMUM) int softLifetimeSeconds)213 public Builder setLifetimeSeconds( 214 @IntRange( 215 from = CHILD_HARD_LIFETIME_SEC_MINIMUM, 216 to = CHILD_HARD_LIFETIME_SEC_MAXIMUM) 217 int hardLifetimeSeconds, 218 @IntRange( 219 from = CHILD_SOFT_LIFETIME_SEC_MINIMUM, 220 to = CHILD_HARD_LIFETIME_SEC_MAXIMUM) 221 int softLifetimeSeconds) { 222 validateAndSetLifetime(hardLifetimeSeconds, softLifetimeSeconds); 223 mHardLifetimeSec = hardLifetimeSeconds; 224 mSoftLifetimeSec = softLifetimeSeconds; 225 return this; 226 } 227 228 /** 229 * Adds an internal IP address request to the {@link TunnelModeChildSessionParams} being 230 * built. 231 * 232 * @param addressFamily the address family. Only {@link OsConstants.AF_INET} and {@link 233 * OsConstants.AF_INET6} are allowed. 234 * @return Builder this, to facilitate chaining. 235 */ 236 @NonNull addInternalAddressRequest(int addressFamily)237 public Builder addInternalAddressRequest(int addressFamily) { 238 if (addressFamily == AF_INET) { 239 mHasIp4AddressRequest = true; 240 mConfigRequestList.add(new ConfigAttributeIpv4Address()); 241 return this; 242 } else if (addressFamily == AF_INET6) { 243 mConfigRequestList.add(new ConfigAttributeIpv6Address()); 244 return this; 245 } else { 246 throw new IllegalArgumentException("Invalid address family: " + addressFamily); 247 } 248 } 249 250 /** 251 * Adds a specific internal IPv4 address request to the {@link TunnelModeChildSessionParams} 252 * being built. 253 * 254 * @param address the requested IPv4 address. 255 * @return Builder this, to facilitate chaining. 256 */ 257 @NonNull addInternalAddressRequest(@onNull Inet4Address address)258 public Builder addInternalAddressRequest(@NonNull Inet4Address address) { 259 if (address == null) { 260 throw new NullPointerException("Required argument not provided"); 261 } 262 263 mHasIp4AddressRequest = true; 264 mConfigRequestList.add(new ConfigAttributeIpv4Address((Inet4Address) address)); 265 return this; 266 } 267 268 /** 269 * Adds a specific internal IPv6 address request to the {@link TunnelModeChildSessionParams} 270 * being built. 271 * 272 * @param address the requested IPv6 address. 273 * @param prefixLen length of the IPv6 address prefix length. 274 * @return Builder this, to facilitate chaining. 275 */ 276 @NonNull addInternalAddressRequest(@onNull Inet6Address address, int prefixLen)277 public Builder addInternalAddressRequest(@NonNull Inet6Address address, int prefixLen) { 278 if (address == null) { 279 throw new NullPointerException("Required argument not provided"); 280 } 281 282 mConfigRequestList.add( 283 new ConfigAttributeIpv6Address(new LinkAddress(address, prefixLen))); 284 return this; 285 } 286 287 /** 288 * Adds an internal DNS server request to the {@link TunnelModeChildSessionParams} being 289 * built. 290 * 291 * @param addressFamily the address family. Only {@link OsConstants.AF_INET} and {@link 292 * OsConstants.AF_INET6} are allowed. 293 * @return Builder this, to facilitate chaining. 294 */ 295 @NonNull addInternalDnsServerRequest(int addressFamily)296 public Builder addInternalDnsServerRequest(int addressFamily) { 297 if (addressFamily == AF_INET) { 298 mConfigRequestList.add(new ConfigAttributeIpv4Dns()); 299 return this; 300 } else if (addressFamily == AF_INET6) { 301 mConfigRequestList.add(new ConfigAttributeIpv6Dns()); 302 return this; 303 } else { 304 throw new IllegalArgumentException("Invalid address family: " + addressFamily); 305 } 306 } 307 308 /** 309 * Adds a specific internal DNS server request to the {@link TunnelModeChildSessionParams} 310 * being built. 311 * 312 * @param address the requested DNS server address. 313 * @return Builder this, to facilitate chaining. 314 * @hide 315 */ 316 @NonNull addInternalDnsServerRequest(@onNull InetAddress address)317 public Builder addInternalDnsServerRequest(@NonNull InetAddress address) { 318 if (address == null) { 319 throw new NullPointerException("Required argument not provided"); 320 } 321 322 if (address instanceof Inet4Address) { 323 mConfigRequestList.add(new ConfigAttributeIpv4Dns((Inet4Address) address)); 324 return this; 325 } else if (address instanceof Inet6Address) { 326 mConfigRequestList.add(new ConfigAttributeIpv6Dns((Inet6Address) address)); 327 return this; 328 } else { 329 throw new IllegalArgumentException("Invalid address " + address); 330 } 331 } 332 333 /** 334 * Adds internal DHCP server requests to the {@link TunnelModeChildSessionParams} being 335 * built. 336 * 337 * <p>Only DHCPv4 server requests are supported. 338 * 339 * @param addressFamily the address family. Only {@link OsConstants.AF_INET} is allowed. 340 * @return Builder this, to facilitate chaining. 341 */ 342 @NonNull addInternalDhcpServerRequest(int addressFamily)343 public Builder addInternalDhcpServerRequest(int addressFamily) { 344 if (addressFamily == AF_INET) { 345 mConfigRequestList.add(new ConfigAttributeIpv4Dhcp()); 346 return this; 347 } else { 348 throw new IllegalArgumentException("Invalid address family: " + addressFamily); 349 } 350 } 351 352 /** 353 * Adds a specific internal DHCP server request to the {@link TunnelModeChildSessionParams} 354 * being built. 355 * 356 * <p>Only DHCPv4 server requests are supported. 357 * 358 * @param address the requested DHCP server address. 359 * @return Builder this, to facilitate chaining. 360 * @hide 361 */ 362 @NonNull addInternalDhcpServerRequest(@onNull InetAddress address)363 public Builder addInternalDhcpServerRequest(@NonNull InetAddress address) { 364 if (address == null) { 365 throw new NullPointerException("Required argument not provided"); 366 } 367 368 if (address instanceof Inet4Address) { 369 mConfigRequestList.add(new ConfigAttributeIpv4Dhcp((Inet4Address) address)); 370 return this; 371 } else { 372 throw new IllegalArgumentException("Invalid address " + address); 373 } 374 } 375 376 /** 377 * Validates and builds the {@link TunnelModeChildSessionParams}. 378 * 379 * @return the validated {@link TunnelModeChildSessionParams}. 380 */ 381 @NonNull build()382 public TunnelModeChildSessionParams build() { 383 addDefaultTsIfNotConfigured(); 384 validateOrThrow(); 385 386 if (mHasIp4AddressRequest) { 387 mConfigRequestList.add(new ConfigAttributeIpv4Netmask()); 388 } 389 390 return new TunnelModeChildSessionParams( 391 mInboundTsList.toArray(new IkeTrafficSelector[0]), 392 mOutboundTsList.toArray(new IkeTrafficSelector[0]), 393 mSaProposalList.toArray(new ChildSaProposal[0]), 394 mConfigRequestList.toArray(new TunnelModeChildConfigAttribute[0]), 395 mHardLifetimeSec, 396 mSoftLifetimeSec); 397 } 398 } 399 } 400