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 com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_APPLICATION_VERSION;
20 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_IP4_PCSCF;
21 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_IP6_PCSCF;
22 
23 import android.annotation.IntDef;
24 import android.annotation.NonNull;
25 import android.annotation.SystemApi;
26 
27 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload;
28 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttribute;
29 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeAppVersion;
30 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Pcscf;
31 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Pcscf;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.net.InetAddress;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Objects;
41 import java.util.Set;
42 
43 /**
44  * IkeSessionConfiguration represents the negotiated configuration for a {@link IkeSession}.
45  *
46  * <p>Configurations include remote application version and enabled IKE extensions..
47  *
48  * @hide
49  */
50 @SystemApi
51 public final class IkeSessionConfiguration {
52     /** @hide */
53     @Retention(RetentionPolicy.SOURCE)
54     @IntDef({EXTENSION_TYPE_FRAGMENTATION, EXTENSION_TYPE_MOBIKE})
55     public @interface ExtensionType {}
56 
57     /** IKE Message Fragmentation */
58     public static final int EXTENSION_TYPE_FRAGMENTATION = 1;
59     /** IKEv2 Mobility and Multihoming Protocol */
60     public static final int EXTENSION_TYPE_MOBIKE = 2;
61 
62     private final String mRemoteApplicationVersion;
63     private final IkeSessionConnectionInfo mIkeConnInfo;
64     private final List<InetAddress> mPcscfServers = new ArrayList<>();
65     private final List<byte[]> mRemoteVendorIds = new ArrayList<>();
66     private final Set<Integer> mEnabledExtensions = new HashSet<>();
67 
68     /**
69      * Construct an instance of {@link IkeSessionConfiguration}.
70      *
71      * <p>IkeSessionConfigurations may only be built with a with a Configure(Reply) Payload.
72      *
73      * @hide
74      */
IkeSessionConfiguration( IkeSessionConnectionInfo ikeConnInfo, IkeConfigPayload configPayload, List<byte[]> remoteVendorIds, List<Integer> enabledExtensions)75     public IkeSessionConfiguration(
76             IkeSessionConnectionInfo ikeConnInfo,
77             IkeConfigPayload configPayload,
78             List<byte[]> remoteVendorIds,
79             List<Integer> enabledExtensions) {
80         String errMsg = " not provided";
81         Objects.requireNonNull(ikeConnInfo, "ikeConnInfo" + errMsg);
82         Objects.requireNonNull(remoteVendorIds, "remoteVendorIds" + errMsg);
83         Objects.requireNonNull(enabledExtensions, "enabledExtensions" + errMsg);
84 
85         mIkeConnInfo = ikeConnInfo;
86         mRemoteVendorIds.addAll(remoteVendorIds);
87         mEnabledExtensions.addAll(enabledExtensions);
88 
89         String appVersion = "";
90         if (configPayload != null) {
91             if (configPayload.configType != IkeConfigPayload.CONFIG_TYPE_REPLY) {
92                 throw new IllegalArgumentException(
93                         "Cannot build IkeSessionConfiguration with configuration type: "
94                                 + configPayload.configType);
95             }
96 
97             for (ConfigAttribute attr : configPayload.recognizedAttributeList) {
98                 if (attr.isEmptyValue()) continue;
99                 switch (attr.attributeType) {
100                     case CONFIG_ATTR_APPLICATION_VERSION:
101                         ConfigAttributeAppVersion appVersionAttr = (ConfigAttributeAppVersion) attr;
102                         appVersion = appVersionAttr.applicationVersion;
103                         break;
104                     case CONFIG_ATTR_IP4_PCSCF:
105                         ConfigAttributeIpv4Pcscf ip4Pcscf = (ConfigAttributeIpv4Pcscf) attr;
106                         mPcscfServers.add(ip4Pcscf.getAddress());
107                         break;
108                     case CONFIG_ATTR_IP6_PCSCF:
109                         ConfigAttributeIpv6Pcscf ip6Pcscf = (ConfigAttributeIpv6Pcscf) attr;
110                         mPcscfServers.add(ip6Pcscf.getAddress());
111                         break;
112                     default:
113                         // Not relevant to IKE session
114                 }
115             }
116         }
117         mRemoteApplicationVersion = appVersion;
118     }
119 
120     /**
121      * Gets remote (server) version information.
122      *
123      * @return application version of the remote server, or an empty string if the remote server did
124      *     not provide the application version.
125      */
126     @NonNull
getRemoteApplicationVersion()127     public String getRemoteApplicationVersion() {
128         return mRemoteApplicationVersion;
129     }
130 
131     /**
132      * Returns remote vendor IDs received during IKE Session setup.
133      *
134      * @return the vendor IDs of the remote server, or an empty list if no vendor ID is received
135      *     during IKE Session setup.
136      */
137     @NonNull
getRemoteVendorIds()138     public List<byte[]> getRemoteVendorIds() {
139         return Collections.unmodifiableList(mRemoteVendorIds);
140     }
141 
142     /**
143      * Checks if an IKE extension is enabled.
144      *
145      * <p>An IKE extension is enabled when both sides can support it. This negotiation always
146      * happens in IKE initial exchanges (IKE INIT and IKE AUTH).
147      *
148      * @param extensionType the extension type.
149      * @return {@code true} if this extension is enabled.
150      */
isIkeExtensionEnabled(@xtensionType int extensionType)151     public boolean isIkeExtensionEnabled(@ExtensionType int extensionType) {
152         return mEnabledExtensions.contains(extensionType);
153     }
154 
155     /**
156      * Returns the assigned P_CSCF servers.
157      *
158      * @return the assigned P_CSCF servers, or an empty list when no servers are assigned by the
159      *     remote IKE server
160      */
161     @NonNull
getPcscfServers()162     public List<InetAddress> getPcscfServers() {
163         return Collections.unmodifiableList(mPcscfServers);
164     }
165 
166     /**
167      * Returns the connection information.
168      *
169      * @return the IKE Session connection information.
170      */
171     @NonNull
getIkeSessionConnectionInfo()172     public IkeSessionConnectionInfo getIkeSessionConnectionInfo() {
173         return mIkeConnInfo;
174     }
175 }
176