385 lines
14 KiB
Java
385 lines
14 KiB
Java
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.net.wifi.passpoint;
|
|
|
|
import android.net.wifi.WifiConfiguration;
|
|
import android.os.Parcelable;
|
|
import android.os.Parcel;
|
|
import android.security.Credentials;
|
|
import android.util.Log;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
|
|
|
|
/** @hide */
|
|
public class WifiPasspointPolicy implements Parcelable {
|
|
|
|
private final static String TAG = "PasspointPolicy";
|
|
|
|
/** @hide */
|
|
public static final int HOME_SP = 0;
|
|
|
|
/** @hide */
|
|
public static final int ROAMING_PARTNER = 1;
|
|
|
|
/** @hide */
|
|
public static final int UNRESTRICTED = 2;
|
|
|
|
private String mName;
|
|
private int mCredentialPriority;
|
|
private int mRoamingPriority;
|
|
private String mBssid;
|
|
private String mSsid;
|
|
private WifiPasspointCredential mCredential;
|
|
private int mRestriction;// Permitted values are "HomeSP", "RoamingPartner", or "Unrestricted"
|
|
private boolean mIsHomeSp;
|
|
|
|
private final String INT_PRIVATE_KEY = "private_key";
|
|
private final String INT_PHASE2 = "phase2";
|
|
private final String INT_PASSWORD = "password";
|
|
private final String INT_IDENTITY = "identity";
|
|
private final String INT_EAP = "eap";
|
|
private final String INT_CLIENT_CERT = "client_cert";
|
|
private final String INT_CA_CERT = "ca_cert";
|
|
private final String INT_ANONYMOUS_IDENTITY = "anonymous_identity";
|
|
private final String INT_SIM_SLOT = "sim_slot";
|
|
private final String INT_ENTERPRISEFIELD_NAME ="android.net.wifi.WifiConfiguration$EnterpriseField";
|
|
private final String ISO8601DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
|
private final String ENTERPRISE_PHASE2_MSCHAPV2 = "auth=MSCHAPV2";
|
|
private final String ENTERPRISE_PHASE2_MSCHAP = "auth=MSCHAP";
|
|
|
|
/** @hide */
|
|
public WifiPasspointPolicy(String name, String ssid,
|
|
String bssid, WifiPasspointCredential pc,
|
|
int restriction, boolean ishomesp) {
|
|
mName = name;
|
|
if (pc != null) {
|
|
mCredentialPriority = pc.getPriority();
|
|
}
|
|
//PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>/Priority
|
|
mRoamingPriority = 128; //default priority value of 128
|
|
mSsid = ssid;
|
|
mCredential = pc;
|
|
mBssid = bssid;
|
|
mRestriction = restriction;
|
|
mIsHomeSp = ishomesp;
|
|
}
|
|
|
|
public String getSsid() {
|
|
return mSsid;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setBssid(String bssid) {
|
|
mBssid = bssid;
|
|
}
|
|
|
|
public String getBssid() {
|
|
return mBssid;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setRestriction(int r) {
|
|
mRestriction = r;
|
|
}
|
|
|
|
/** @hide */
|
|
public int getRestriction() {
|
|
return mRestriction;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setHomeSp(boolean b) {
|
|
mIsHomeSp = b;
|
|
}
|
|
|
|
/** @hide */
|
|
public boolean isHomeSp() {
|
|
return mIsHomeSp;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setCredential(WifiPasspointCredential newCredential) {
|
|
mCredential = newCredential;
|
|
}
|
|
|
|
public WifiPasspointCredential getCredential() {
|
|
// TODO: return a copy
|
|
return mCredential;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setCredentialPriority(int priority) {
|
|
mCredentialPriority = priority;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setRoamingPriority(int priority) {
|
|
mRoamingPriority = priority;
|
|
}
|
|
|
|
public int getCredentialPriority() {
|
|
return mCredentialPriority;
|
|
}
|
|
|
|
public int getRoamingPriority() {
|
|
return mRoamingPriority;
|
|
}
|
|
|
|
public WifiConfiguration createWifiConfiguration() {
|
|
WifiConfiguration wfg = new WifiConfiguration();
|
|
if (mBssid != null) {
|
|
Log.d(TAG, "create bssid:" + mBssid);
|
|
wfg.BSSID = mBssid;
|
|
}
|
|
|
|
if (mSsid != null) {
|
|
Log.d(TAG, "create ssid:" + mSsid);
|
|
wfg.SSID = mSsid;
|
|
}
|
|
//TODO: 1. add pmf configuration
|
|
// 2. add ocsp configuration
|
|
// 3. add eap-sim configuration
|
|
/*Key management*/
|
|
wfg.status = WifiConfiguration.Status.ENABLED;
|
|
wfg.allowedKeyManagement.clear();
|
|
wfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
|
|
wfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
|
|
|
|
/*Group Ciphers*/
|
|
wfg.allowedGroupCiphers.clear();
|
|
wfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
|
|
wfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
|
|
|
|
/*Protocols*/
|
|
wfg.allowedProtocols.clear();
|
|
wfg.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
|
|
wfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
|
|
|
|
Class[] enterpriseFieldArray = WifiConfiguration.class.getClasses();
|
|
Class<?> enterpriseFieldClass = null;
|
|
|
|
|
|
for(Class<?> myClass : enterpriseFieldArray) {
|
|
if(myClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) {
|
|
enterpriseFieldClass = myClass;
|
|
break;
|
|
}
|
|
}
|
|
Log.d(TAG, "class chosen " + enterpriseFieldClass.getName() );
|
|
|
|
|
|
Field anonymousId = null, caCert = null, clientCert = null,
|
|
eap = null, identity = null, password = null,
|
|
phase2 = null, privateKey = null;
|
|
|
|
Field[] fields = WifiConfiguration.class.getFields();
|
|
|
|
|
|
for (Field tempField : fields) {
|
|
if (tempField.getName().trim().equals(INT_ANONYMOUS_IDENTITY)) {
|
|
anonymousId = tempField;
|
|
Log.d(TAG, "field " + anonymousId.getName() );
|
|
} else if (tempField.getName().trim().equals(INT_CA_CERT)) {
|
|
caCert = tempField;
|
|
} else if (tempField.getName().trim().equals(INT_CLIENT_CERT)) {
|
|
clientCert = tempField;
|
|
Log.d(TAG, "field " + clientCert.getName() );
|
|
} else if (tempField.getName().trim().equals(INT_EAP)) {
|
|
eap = tempField;
|
|
Log.d(TAG, "field " + eap.getName() );
|
|
} else if (tempField.getName().trim().equals(INT_IDENTITY)) {
|
|
identity = tempField;
|
|
Log.d(TAG, "field " + identity.getName() );
|
|
} else if (tempField.getName().trim().equals(INT_PASSWORD)) {
|
|
password = tempField;
|
|
Log.d(TAG, "field " + password.getName() );
|
|
} else if (tempField.getName().trim().equals(INT_PHASE2)) {
|
|
phase2 = tempField;
|
|
Log.d(TAG, "field " + phase2.getName() );
|
|
|
|
} else if (tempField.getName().trim().equals(INT_PRIVATE_KEY)) {
|
|
privateKey = tempField;
|
|
}
|
|
}
|
|
|
|
|
|
Method setValue = null;
|
|
|
|
for(Method m: enterpriseFieldClass.getMethods()) {
|
|
if(m.getName().trim().equals("setValue")) {
|
|
Log.d(TAG, "method " + m.getName() );
|
|
setValue = m;
|
|
break;
|
|
}
|
|
}
|
|
|
|
try {
|
|
// EAP
|
|
String eapmethod = mCredential.getType();
|
|
Log.d(TAG, "eapmethod:" + eapmethod);
|
|
setValue.invoke(eap.get(wfg), eapmethod);
|
|
|
|
// Username, password, EAP Phase 2
|
|
if ("TTLS".equals(eapmethod)) {
|
|
setValue.invoke(phase2.get(wfg), ENTERPRISE_PHASE2_MSCHAPV2);
|
|
setValue.invoke(identity.get(wfg), mCredential.getUserName());
|
|
setValue.invoke(password.get(wfg), mCredential.getPassword());
|
|
setValue.invoke(anonymousId.get(wfg), "anonymous@" + mCredential.getRealm());
|
|
}
|
|
|
|
// EAP CA Certificate
|
|
String cacertificate = null;
|
|
String rootCA = mCredential.getCaRootCertPath();
|
|
if (rootCA == null){
|
|
cacertificate = null;
|
|
} else {
|
|
cacertificate = "keystore://" + Credentials.WIFI + "HS20" + Credentials.CA_CERTIFICATE + rootCA;
|
|
}
|
|
Log.d(TAG, "cacertificate:" + cacertificate);
|
|
setValue.invoke(caCert.get(wfg), cacertificate);
|
|
|
|
//User certificate
|
|
if ("TLS".equals(eapmethod)) {
|
|
String usercertificate = null;
|
|
String privatekey = null;
|
|
String clientCertPath = mCredential.getClientCertPath();
|
|
if (clientCertPath != null){
|
|
privatekey = "keystore://" + Credentials.WIFI + "HS20" + Credentials.USER_PRIVATE_KEY + clientCertPath;
|
|
usercertificate = "keystore://" + Credentials.WIFI + "HS20" + Credentials.USER_CERTIFICATE + clientCertPath;
|
|
}
|
|
Log.d(TAG, "privatekey:" + privatekey);
|
|
Log.d(TAG, "usercertificate:" + usercertificate);
|
|
if (privatekey != null && usercertificate != null) {
|
|
setValue.invoke(privateKey.get(wfg), privatekey);
|
|
setValue.invoke(clientCert.get(wfg), usercertificate);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
Log.d(TAG, "createWifiConfiguration err:" + e);
|
|
}
|
|
|
|
return wfg;
|
|
}
|
|
|
|
/** {@inheritDoc} @hide */
|
|
public int compareTo(WifiPasspointPolicy another) {
|
|
Log.d(TAG, "this:" + this);
|
|
Log.d(TAG, "another:" + another);
|
|
|
|
if (another == null) {
|
|
return -1;
|
|
} else if (this.mIsHomeSp == true && another.isHomeSp() == false) {
|
|
//home sp priority is higher then roaming
|
|
Log.d(TAG, "compare HomeSP first, this is HomeSP, another isn't");
|
|
return -1;
|
|
} else if ((this.mIsHomeSp == true && another.isHomeSp() == true)) {
|
|
Log.d(TAG, "both HomeSP");
|
|
//if both home sp, compare credential priority
|
|
if (this.mCredentialPriority < another.getCredentialPriority()) {
|
|
Log.d(TAG, "this priority is higher");
|
|
return -1;
|
|
} else if (this.mCredentialPriority == another.getCredentialPriority()) {
|
|
Log.d(TAG, "both priorities equal");
|
|
//if priority still the same, compare name(ssid)
|
|
if (this.mName.compareTo(another.mName) != 0) {
|
|
Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
|
|
return this.mName.compareTo(another.mName);
|
|
}
|
|
/**
|
|
*if name still the same, compare credential
|
|
*the device may has two more credentials(TLS,SIM..etc)
|
|
*it can associate to one AP(same ssid). so we should compare by credential
|
|
*/
|
|
if (this.mCredential != null && another.mCredential != null) {
|
|
if (this.mCredential.compareTo(another.mCredential) != 0) {
|
|
Log.d(TAG,
|
|
"compare mCredential return:" + this.mName.compareTo(another.mName));
|
|
return this.mCredential.compareTo(another.mCredential);
|
|
}
|
|
}
|
|
} else {
|
|
return 1;
|
|
}
|
|
} else if ((this.mIsHomeSp == false && another.isHomeSp() == false)) {
|
|
Log.d(TAG, "both RoamingSp");
|
|
//if both roaming sp, compare roaming priority(preferredRoamingPartnerList/<X+>/priority)
|
|
if (this.mRoamingPriority < another.getRoamingPriority()) {
|
|
Log.d(TAG, "this priority is higher");
|
|
return -1;
|
|
} else if (this.mRoamingPriority == another.getRoamingPriority()) {//priority equals, compare name
|
|
Log.d(TAG, "both priorities equal");
|
|
//if priority still the same, compare name(ssid)
|
|
if (this.mName.compareTo(another.mName) != 0) {
|
|
Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
|
|
return this.mName.compareTo(another.mName);
|
|
}
|
|
//if name still the same, compare credential
|
|
if (this.mCredential != null && another.mCredential != null) {
|
|
if (this.mCredential.compareTo(another.mCredential) != 0) {
|
|
Log.d(TAG,
|
|
"compare mCredential return:"
|
|
+ this.mCredential.compareTo(another.mCredential));
|
|
return this.mCredential.compareTo(another.mCredential);
|
|
}
|
|
}
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
Log.d(TAG, "both policies equal");
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
/** @hide */
|
|
public String toString() {
|
|
return "PasspointPolicy: name=" + mName + " CredentialPriority=" + mCredentialPriority +
|
|
" mRoamingPriority" + mRoamingPriority +
|
|
" ssid=" + mSsid + " restriction=" + mRestriction +
|
|
" ishomesp=" + mIsHomeSp + " Credential=" + mCredential;
|
|
}
|
|
|
|
/** Implement the Parcelable interface {@hide} */
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
/** Implement the Parcelable interface {@hide} */
|
|
@Override
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
// TODO
|
|
}
|
|
|
|
/** Implement the Parcelable interface {@hide} */
|
|
public static final Creator<WifiPasspointPolicy> CREATOR =
|
|
new Creator<WifiPasspointPolicy>() {
|
|
@Override
|
|
public WifiPasspointPolicy createFromParcel(Parcel in) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public WifiPasspointPolicy[] newArray(int size) {
|
|
return new WifiPasspointPolicy[size];
|
|
}
|
|
};
|
|
}
|