blob: 0ea75aea070822ccab43f7d4109e49e73d0c5cad [file] [log] [blame]
package com.android.server.wifi.hotspot2.omadm;
import android.util.Base64;
import android.util.Log;
import com.android.server.wifi.IMSIParameter;
import com.android.server.wifi.anqp.eap.EAP;
import com.android.server.wifi.anqp.eap.EAPMethod;
import com.android.server.wifi.anqp.eap.ExpandedEAPMethod;
import com.android.server.wifi.anqp.eap.InnerAuthEAP;
import com.android.server.wifi.anqp.eap.NonEAPInnerAuth;
import com.android.server.wifi.hotspot2.Utils;
import com.android.server.wifi.hotspot2.pps.Credential;
import com.android.server.wifi.hotspot2.pps.HomeSP;
import org.xml.sax.SAXException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
/**
* Handles provisioning of PerProviderSubscription data.
*/
public class MOManager {
public static final String TAG_AAAServerTrustRoot = "AAAServerTrustRoot";
public static final String TAG_AbleToShare = "AbleToShare";
public static final String TAG_CertificateType = "CertificateType";
public static final String TAG_CertSHA256Fingerprint = "CertSHA256Fingerprint";
public static final String TAG_CertURL = "CertURL";
public static final String TAG_CheckAAAServerCertStatus = "CheckAAAServerCertStatus";
public static final String TAG_Country = "Country";
public static final String TAG_CreationDate = "CreationDate";
public static final String TAG_Credential = "Credential";
public static final String TAG_CredentialPriority = "CredentialPriority";
public static final String TAG_DataLimit = "DataLimit";
public static final String TAG_DigitalCertificate = "DigitalCertificate";
public static final String TAG_DLBandwidth = "DLBandwidth";
public static final String TAG_EAPMethod = "EAPMethod";
public static final String TAG_EAPType = "EAPType";
public static final String TAG_ExpirationDate = "ExpirationDate";
public static final String TAG_Extension = "Extension";
public static final String TAG_FQDN = "FQDN";
public static final String TAG_FQDN_Match = "FQDN_Match";
public static final String TAG_FriendlyName = "FriendlyName";
public static final String TAG_HESSID = "HESSID";
public static final String TAG_HomeOI = "HomeOI";
public static final String TAG_HomeOIList = "HomeOIList";
public static final String TAG_HomeOIRequired = "HomeOIRequired";
public static final String TAG_HomeSP = "HomeSP";
public static final String TAG_IconURL = "IconURL";
public static final String TAG_IMSI = "IMSI";
public static final String TAG_InnerEAPType = "InnerEAPType";
public static final String TAG_InnerMethod = "InnerMethod";
public static final String TAG_InnerVendorID = "InnerVendorID";
public static final String TAG_InnerVendorType = "InnerVendorType";
public static final String TAG_IPProtocol = "IPProtocol";
public static final String TAG_MachineManaged = "MachineManaged";
public static final String TAG_MaximumBSSLoadValue = "MaximumBSSLoadValue";
public static final String TAG_MinBackhaulThreshold = "MinBackhaulThreshold";
public static final String TAG_NetworkID = "NetworkID";
public static final String TAG_NetworkType = "NetworkType";
public static final String TAG_Other = "Other";
public static final String TAG_OtherHomePartners = "OtherHomePartners";
public static final String TAG_Password = "Password";
public static final String TAG_PerProviderSubscription = "PerProviderSubscription";
public static final String TAG_Policy = "Policy";
public static final String TAG_PolicyUpdate = "PolicyUpdate";
public static final String TAG_PortNumber = "PortNumber";
public static final String TAG_PreferredRoamingPartnerList = "PreferredRoamingPartnerList";
public static final String TAG_Priority = "Priority";
public static final String TAG_Realm = "Realm";
public static final String TAG_RequiredProtoPortTuple = "RequiredProtoPortTuple";
public static final String TAG_Restriction = "Restriction";
public static final String TAG_RoamingConsortiumOI = "RoamingConsortiumOI";
public static final String TAG_SIM = "SIM";
public static final String TAG_SoftTokenApp = "SoftTokenApp";
public static final String TAG_SPExclusionList = "SPExclusionList";
public static final String TAG_SSID = "SSID";
public static final String TAG_StartDate = "StartDate";
public static final String TAG_SubscriptionParameters = "SubscriptionParameters";
public static final String TAG_SubscriptionUpdate = "SubscriptionUpdate";
public static final String TAG_TimeLimit = "TimeLimit";
public static final String TAG_TrustRoot = "TrustRoot";
public static final String TAG_TypeOfSubscription = "TypeOfSubscription";
public static final String TAG_ULBandwidth = "ULBandwidth";
public static final String TAG_UpdateIdentifier = "UpdateIdentifier";
public static final String TAG_UpdateInterval = "UpdateInterval";
public static final String TAG_UpdateMethod = "UpdateMethod";
public static final String TAG_URI = "URI";
public static final String TAG_UsageLimits = "UsageLimits";
public static final String TAG_UsageTimePeriod = "UsageTimePeriod";
public static final String TAG_Username = "Username";
public static final String TAG_UsernamePassword = "UsernamePassword";
public static final String TAG_VendorId = "VendorId";
public static final String TAG_VendorType = "VendorType";
private static final DateFormat DTFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
static {
DTFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
}
private final File mPpsFile;
private final boolean mEnabled;
private final Map<String, HomeSP> mSPs;
public MOManager(File ppsFile, boolean hs2enabled) {
mPpsFile = ppsFile;
mEnabled = hs2enabled;
mSPs = new HashMap<>();
}
public File getPpsFile() {
return mPpsFile;
}
public boolean isEnabled() {
return mEnabled;
}
public boolean isConfigured() {
return mEnabled && !mSPs.isEmpty();
}
public Map<String, HomeSP> getLoadedSPs() {
return Collections.unmodifiableMap(mSPs);
}
public List<HomeSP> loadAllSPs() throws IOException {
if (!mEnabled || !mPpsFile.exists()) {
return Collections.emptyList();
}
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
MOTree moTree = MOTree.unmarshal(in);
mSPs.clear();
if (moTree == null) {
return Collections.emptyList(); // Empty file
}
List<HomeSP> sps = buildSPs(moTree);
if (sps != null) {
for (HomeSP sp : sps) {
if (mSPs.put(sp.getFQDN(), sp) != null) {
throw new OMAException("Multiple SPs for FQDN '" + sp.getFQDN() + "'");
} else {
Log.d(Utils.hs2LogTag(getClass()), "retrieved " + sp.getFQDN() + " from PPS");
}
}
return sps;
} else {
throw new OMAException("Failed to build HomeSP");
}
}
}
public static HomeSP buildSP(String xml) throws IOException, SAXException {
OMAParser omaParser = new OMAParser();
MOTree tree = omaParser.parse(xml, OMAConstants.LOC_PPS + ":1.0");
List<HomeSP> spList = buildSPs(tree);
if (spList.size() != 1) {
throw new OMAException("Expected exactly one HomeSP, got " + spList.size());
}
return spList.iterator().next();
}
public HomeSP addSP(String xml) throws IOException, SAXException {
OMAParser omaParser = new OMAParser();
MOTree tree = omaParser.parse(xml, OMAConstants.LOC_PPS + ":1.0");
List<HomeSP> spList = buildSPs(tree);
if (spList.size() != 1) {
throw new OMAException("Expected exactly one HomeSP, got " + spList.size());
}
HomeSP sp = spList.iterator().next();
String fqdn = sp.getFQDN();
if (mSPs.put(fqdn, sp) != null) {
throw new OMAException("SP " + fqdn + " already exists");
}
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(mPpsFile, true));
tree.marshal(out);
out.flush();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
/**/
}
}
}
return sp;
}
public HomeSP getHomeSP(String fqdn) {
return mSPs.get(fqdn);
}
public void addSP(HomeSP homeSP) throws IOException {
if (!mEnabled) {
throw new IOException("HS2.0 not enabled on this device");
}
if (mSPs.containsKey(homeSP.getFQDN())) {
Log.d(Utils.hs2LogTag(getClass()), "HS20 profile for " +
homeSP.getFQDN() + " already exists");
return;
}
Log.d(Utils.hs2LogTag(getClass()), "Adding new HS20 profile for " + homeSP.getFQDN());
mSPs.put(homeSP.getFQDN(), homeSP);
writeMO(mSPs.values(), mPpsFile);
}
public void removeSP(String fqdn) throws IOException {
if (mSPs.remove(fqdn) == null) {
Log.d(Utils.hs2LogTag(getClass()), "No HS20 profile to delete for " + fqdn);
return;
}
Log.d(Utils.hs2LogTag(getClass()), "Deleting HS20 profile for " + fqdn);
writeMO(mSPs.values(), mPpsFile);
}
public void updateAndSaveAllSps(Collection<HomeSP> homeSPs) throws IOException {
boolean dirty = false;
List<HomeSP> newSet = new ArrayList<>(homeSPs.size());
Map<String, HomeSP> spClone = new HashMap<>(mSPs);
for (HomeSP homeSP : homeSPs) {
Log.d(Utils.hs2LogTag(getClass()), "Passed HomeSP: " + homeSP);
HomeSP existing = spClone.remove(homeSP.getFQDN());
if (existing == null) {
dirty = true;
newSet.add(homeSP);
Log.d(Utils.hs2LogTag(getClass()), "New HomeSP");
}
else if (!homeSP.deepEquals(existing)) {
dirty = true;
newSet.add(homeSP.getClone(existing.getCredential().getPassword()));
Log.d(Utils.hs2LogTag(getClass()), "Non-equal HomeSP: " + existing);
}
else {
newSet.add(existing);
Log.d(Utils.hs2LogTag(getClass()), "Keeping HomeSP: " + existing);
}
}
Log.d(Utils.hs2LogTag(getClass()),
String.format("Saving all SPs (%s): current %s (%d), new %s (%d)",
dirty ? "dirty" : "clean",
fqdnList(mSPs.values()), mSPs.size(),
fqdnList(newSet), newSet.size()));
if (!dirty && spClone.isEmpty()) {
Log.d(Utils.hs2LogTag(getClass()), "Not persisting");
return;
}
rewriteMO(newSet, mSPs, mPpsFile);
}
private static void rewriteMO(Collection<HomeSP> homeSPs, Map<String, HomeSP> current, File f)
throws IOException {
current.clear();
OMAConstructed ppsNode = new OMAConstructed(null, TAG_PerProviderSubscription, null);
int instance = 0;
for (HomeSP homeSP : homeSPs) {
buildHomeSPTree(homeSP, ppsNode, instance++);
current.put(homeSP.getFQDN(), homeSP);
}
MOTree tree = new MOTree(OMAConstants.LOC_PPS + ":1.0", "1.2", ppsNode);
try (BufferedOutputStream out =
new BufferedOutputStream(new FileOutputStream(f, false))) {
tree.marshal(out);
out.flush();
}
}
private static void writeMO(Collection<HomeSP> homeSPs, File f) throws IOException {
OMAConstructed ppsNode = new OMAConstructed(null, TAG_PerProviderSubscription, null);
int instance = 0;
for (HomeSP homeSP : homeSPs) {
buildHomeSPTree(homeSP, ppsNode, instance++);
}
MOTree tree = new MOTree(OMAConstants.LOC_PPS + ":1.0", "1.2", ppsNode);
try (BufferedOutputStream out =
new BufferedOutputStream(new FileOutputStream(f, false))) {
tree.marshal(out);
out.flush();
}
}
private static String fqdnList(Collection<HomeSP> sps) {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (HomeSP sp : sps) {
if (first) {
first = false;
}
else {
sb.append(", ");
}
sb.append(sp.getFQDN());
}
return sb.toString();
}
private static void buildHomeSPTree(HomeSP homeSP, OMAConstructed root, int spInstance)
throws IOException {
OMANode providerSubNode = root.addChild(getInstanceString(spInstance), null, null, null);
// The HomeSP:
OMANode homeSpNode = providerSubNode.addChild(TAG_HomeSP, null, null, null);
if (!homeSP.getSSIDs().isEmpty()) {
OMAConstructed nwkIDNode =
(OMAConstructed) homeSpNode.addChild(TAG_NetworkID, null, null, null);
int instance = 0;
for (Map.Entry<String, Long> entry : homeSP.getSSIDs().entrySet()) {
OMAConstructed inode =
(OMAConstructed) nwkIDNode.addChild(getInstanceString(instance++), null, null, null);
inode.addChild(TAG_SSID, null, entry.getKey(), null);
if (entry.getValue() != null) {
inode.addChild(TAG_HESSID, null, String.format("%012x", entry.getValue()), null);
}
}
}
homeSpNode.addChild(TAG_FriendlyName, null, homeSP.getFriendlyName(), null);
if (homeSP.getIconURL() != null) {
homeSpNode.addChild(TAG_IconURL, null, homeSP.getIconURL(), null);
}
homeSpNode.addChild(TAG_FQDN, null, homeSP.getFQDN(), null);
if (!homeSP.getMatchAllOIs().isEmpty() || !homeSP.getMatchAnyOIs().isEmpty()) {
OMAConstructed homeOIList =
(OMAConstructed) homeSpNode.addChild(TAG_HomeOIList, null, null, null);
int instance = 0;
for (Long oi : homeSP.getMatchAllOIs()) {
OMAConstructed inode =
(OMAConstructed) homeOIList.addChild(getInstanceString(instance++),
null, null, null);
inode.addChild(TAG_HomeOI, null, String.format("%x", oi), null);
inode.addChild(TAG_HomeOIRequired, null, "TRUE", null);
}
for (Long oi : homeSP.getMatchAnyOIs()) {
OMAConstructed inode =
(OMAConstructed) homeOIList.addChild(getInstanceString(instance++),
null, null, null);
inode.addChild(TAG_HomeOI, null, String.format("%x", oi), null);
inode.addChild(TAG_HomeOIRequired, null, "FALSE", null);
}
}
if (!homeSP.getOtherHomePartners().isEmpty()) {
OMAConstructed otherPartners =
(OMAConstructed) homeSpNode.addChild(TAG_OtherHomePartners, null, null, null);
int instance = 0;
for (String fqdn : homeSP.getOtherHomePartners()) {
OMAConstructed inode =
(OMAConstructed) otherPartners.addChild(getInstanceString(instance++),
null, null, null);
inode.addChild(TAG_FQDN, null, fqdn, null);
}
}
if (!homeSP.getRoamingConsortiums().isEmpty()) {
homeSpNode.addChild(TAG_RoamingConsortiumOI, null, getRCList(homeSP.getRoamingConsortiums()), null);
}
// The Credential:
OMANode credentialNode = providerSubNode.addChild(TAG_Credential, null, null, null);
Credential cred = homeSP.getCredential();
EAPMethod method = cred.getEAPMethod();
if (cred.getCtime() > 0) {
credentialNode.addChild(TAG_CreationDate,
null, DTFormat.format(new Date(cred.getCtime())), null);
}
if (cred.getExpTime() > 0) {
credentialNode.addChild(TAG_ExpirationDate,
null, DTFormat.format(new Date(cred.getExpTime())), null);
}
if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_SIM
|| method.getEAPMethodID() == EAP.EAPMethodID.EAP_AKA
|| method.getEAPMethodID() == EAP.EAPMethodID.EAP_AKAPrim) {
OMANode simNode = credentialNode.addChild(TAG_SIM, null, null, null);
simNode.addChild(TAG_IMSI, null, cred.getImsi().toString(), null);
simNode.addChild(TAG_EAPType, null,
Integer.toString(EAP.mapEAPMethod(method.getEAPMethodID())), null);
} else if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_TTLS) {
OMANode unpNode = credentialNode.addChild(TAG_UsernamePassword, null, null, null);
unpNode.addChild(TAG_Username, null, cred.getUserName(), null);
unpNode.addChild(TAG_Password, null,
Base64.encodeToString(cred.getPassword().getBytes(StandardCharsets.UTF_8),
Base64.DEFAULT), null);
OMANode eapNode = unpNode.addChild(TAG_EAPMethod, null, null, null);
eapNode.addChild(TAG_EAPType, null,
Integer.toString(EAP.mapEAPMethod(method.getEAPMethodID())), null);
eapNode.addChild(TAG_InnerMethod, null,
((NonEAPInnerAuth) method.getAuthParam()).getOMAtype(), null);
} else if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_TLS) {
OMANode certNode = credentialNode.addChild(TAG_DigitalCertificate, null, null, null);
certNode.addChild(TAG_CertificateType, null, Credential.CertTypeX509, null);
certNode.addChild(TAG_CertSHA256Fingerprint, null,
Utils.toHex(cred.getFingerPrint()), null);
} else {
throw new OMAException("Invalid credential on " + homeSP.getFQDN());
}
credentialNode.addChild(TAG_Realm, null, cred.getRealm(), null);
// !!! Note: This node defines CRL checking through OSCP, I suspect we won't be able
// to do that so it is commented out:
//credentialNode.addChild(TAG_CheckAAAServerCertStatus, null, "TRUE", null);
}
private static String getInstanceString(int instance) {
return "i" + instance;
}
private static String getRCList(Collection<Long> rcs) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Long roamingConsortium : rcs) {
if (first) {
first = false;
}
else {
builder.append(',');
}
builder.append(String.format("%x", roamingConsortium));
}
return builder.toString();
}
private static List<HomeSP> buildSPs(MOTree moTree) throws OMAException {
OMAConstructed spList;
if (moTree.getRoot().getName().equals(TAG_PerProviderSubscription)) {
// The PPS file is rooted at PPS instead of MgmtTree to conserve space
spList = moTree.getRoot();
}
else {
List<String> spPath = Arrays.asList(TAG_PerProviderSubscription);
spList = moTree.getRoot().getListValue(spPath.iterator());
}
List<HomeSP> homeSPs = new ArrayList<>();
if (spList == null) {
return homeSPs;
}
for (OMANode spRoot : spList.getChildren()) {
homeSPs.add(buildHomeSP(spRoot));
}
return homeSPs;
}
private static HomeSP buildHomeSP(OMANode ppsRoot) throws OMAException {
OMANode spRoot = ppsRoot.getChild(TAG_HomeSP);
String fqdn = spRoot.getScalarValue(Arrays.asList(TAG_FQDN).iterator());
String friendlyName = spRoot.getScalarValue(Arrays.asList(TAG_FriendlyName).iterator());
String iconURL = spRoot.getScalarValue(Arrays.asList(TAG_IconURL).iterator());
HashSet<Long> roamingConsortiums = new HashSet<>();
String oiString = spRoot.getScalarValue(Arrays.asList(TAG_RoamingConsortiumOI).iterator());
if (oiString != null) {
for (String oi : oiString.split(",")) {
roamingConsortiums.add(Long.parseLong(oi.trim(), 16));
}
}
Map<String, Long> ssids = new HashMap<>();
OMANode ssidListNode = spRoot.getListValue(Arrays.asList(TAG_NetworkID).iterator());
if (ssidListNode != null) {
for (OMANode ssidRoot : ssidListNode.getChildren()) {
OMANode hessidNode = ssidRoot.getChild(TAG_HESSID);
ssids.put(ssidRoot.getChild(TAG_SSID).getValue(), getMac(hessidNode));
}
}
Set<Long> matchAnyOIs = new HashSet<>();
List<Long> matchAllOIs = new ArrayList<>();
OMANode homeOIListNode = spRoot.getListValue(Arrays.asList(TAG_HomeOIList).iterator());
if (homeOIListNode != null) {
for (OMANode homeOIRoot : homeOIListNode.getChildren()) {
String homeOI = homeOIRoot.getChild(TAG_HomeOI).getValue();
if (Boolean.parseBoolean(homeOIRoot.getChild(TAG_HomeOIRequired).getValue())) {
matchAllOIs.add(Long.parseLong(homeOI, 16));
} else {
matchAnyOIs.add(Long.parseLong(homeOI, 16));
}
}
}
Set<String> otherHomePartners = new HashSet<>();
OMANode otherListNode =
spRoot.getListValue(Arrays.asList(TAG_OtherHomePartners).iterator());
if (otherListNode != null) {
for (OMANode fqdnNode : otherListNode.getChildren()) {
otherHomePartners.add(fqdnNode.getChild(TAG_FQDN).getValue());
}
}
Credential credential = buildCredential(ppsRoot.getChild(TAG_Credential));
return new HomeSP(ssids, fqdn, roamingConsortiums, otherHomePartners,
matchAnyOIs, matchAllOIs, friendlyName, iconURL, credential);
}
private static Credential buildCredential(OMANode credNode) throws OMAException {
long ctime = getTime(credNode.getChild(TAG_CreationDate));
long expTime = getTime(credNode.getChild(TAG_ExpirationDate));
String realm = getString(credNode.getChild(TAG_Realm));
boolean checkAAACert = getBoolean(credNode.getChild(TAG_CheckAAAServerCertStatus));
OMANode unNode = credNode.getChild(TAG_UsernamePassword);
OMANode certNode = credNode.getChild(TAG_DigitalCertificate);
OMANode simNode = credNode.getChild(TAG_SIM);
int alternatives = 0;
alternatives += unNode != null ? 1 : 0;
alternatives += certNode != null ? 1 : 0;
alternatives += simNode != null ? 1 : 0;
if (alternatives != 1) {
throw new OMAException("Expected exactly one credential type, got " + alternatives);
}
if (unNode != null) {
String userName = getString(unNode.getChild(TAG_Username));
String password = getString(unNode.getChild(TAG_Password));
boolean machineManaged = getBoolean(unNode.getChild(TAG_MachineManaged));
String softTokenApp = getString(unNode.getChild(TAG_SoftTokenApp));
boolean ableToShare = getBoolean(unNode.getChild(TAG_AbleToShare));
OMANode eapMethodNode = unNode.getChild(TAG_EAPMethod);
int eapID = getInteger(eapMethodNode.getChild(TAG_EAPType));
EAP.EAPMethodID eapMethodID = EAP.mapEAPMethod(eapID);
if (eapMethodID == null) {
throw new OMAException("Unknown EAP method: " + eapID);
}
Long vid = getOptionalInteger(eapMethodNode.getChild(TAG_VendorId));
Long vtype = getOptionalInteger(eapMethodNode.getChild(TAG_VendorType));
Long innerEAPType = getOptionalInteger(eapMethodNode.getChild(TAG_InnerEAPType));
EAP.EAPMethodID innerEAPMethod = null;
if (innerEAPType != null) {
innerEAPMethod = EAP.mapEAPMethod(innerEAPType.intValue());
if (innerEAPMethod == null) {
throw new OMAException("Bad inner EAP method: " + innerEAPType);
}
}
Long innerVid = getOptionalInteger(eapMethodNode.getChild(TAG_InnerVendorID));
Long innerVtype = getOptionalInteger(eapMethodNode.getChild(TAG_InnerVendorType));
String innerNonEAPMethod = getString(eapMethodNode.getChild(TAG_InnerMethod));
EAPMethod eapMethod;
if (innerEAPMethod != null) {
eapMethod = new EAPMethod(eapMethodID, new InnerAuthEAP(innerEAPMethod));
} else if (vid != null) {
eapMethod = new EAPMethod(eapMethodID,
new ExpandedEAPMethod(EAP.AuthInfoID.ExpandedEAPMethod,
vid.intValue(), vtype));
} else if (innerVid != null) {
eapMethod =
new EAPMethod(eapMethodID, new ExpandedEAPMethod(EAP.AuthInfoID
.ExpandedInnerEAPMethod, innerVid.intValue(), innerVtype));
} else if (innerNonEAPMethod != null) {
eapMethod = new EAPMethod(eapMethodID, new NonEAPInnerAuth(innerNonEAPMethod));
} else {
throw new OMAException("Incomplete set of EAP parameters");
}
return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, userName,
password, machineManaged, softTokenApp, ableToShare);
}
if (certNode != null) {
try {
String certTypeString = getString(certNode.getChild(TAG_CertificateType));
byte[] fingerPrint = getOctets(certNode.getChild(TAG_CertSHA256Fingerprint));
EAPMethod eapMethod = new EAPMethod(EAP.EAPMethodID.EAP_TLS, null);
return new Credential(ctime, expTime, realm, checkAAACert, eapMethod,
Credential.mapCertType(certTypeString), fingerPrint);
}
catch (NumberFormatException nfe) {
throw new OMAException("Bad hex string: " + nfe.toString());
}
}
if (simNode != null) {
try {
IMSIParameter imsi = new IMSIParameter(getString(simNode.getChild(TAG_IMSI)));
EAPMethod eapMethod =
new EAPMethod(EAP.mapEAPMethod(getInteger(simNode.getChild(TAG_EAPType))),
null);
return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, imsi);
}
catch (IOException ioe) {
throw new OMAException("Failed to parse IMSI: " + ioe);
}
}
throw new OMAException("Missing credential parameters");
}
private static boolean getBoolean(OMANode boolNode) {
return boolNode != null && Boolean.parseBoolean(boolNode.getValue());
}
private static String getString(OMANode stringNode) {
return stringNode != null ? stringNode.getValue() : null;
}
private static int getInteger(OMANode intNode) throws OMAException {
if (intNode == null) {
throw new OMAException("Missing integer value");
}
try {
return Integer.parseInt(intNode.getValue());
} catch (NumberFormatException nfe) {
throw new OMAException("Invalid integer: " + intNode.getValue());
}
}
private static Long getMac(OMANode macNode) throws OMAException {
if (macNode == null) {
return null;
}
try {
return Long.parseLong(macNode.getValue(), 16);
} catch (NumberFormatException nfe) {
throw new OMAException("Invalid MAC: " + macNode.getValue());
}
}
private static Long getOptionalInteger(OMANode intNode) throws OMAException {
if (intNode == null) {
return null;
}
try {
return Long.parseLong(intNode.getValue());
} catch (NumberFormatException nfe) {
throw new OMAException("Invalid integer: " + intNode.getValue());
}
}
private static long getTime(OMANode timeNode) throws OMAException {
if (timeNode == null) {
return Utils.UNSET_TIME;
}
String timeText = timeNode.getValue();
try {
Date date = DTFormat.parse(timeText);
return date.getTime();
} catch (ParseException pe) {
throw new OMAException("Badly formatted time: " + timeText);
}
}
private static byte[] getOctets(OMANode octetNode) throws OMAException {
if (octetNode == null) {
throw new OMAException("Missing byte value");
}
return Utils.hexToBytes(octetNode.getValue());
}
}