MOManager.java revision 820d73615f338d6c71f2d75aba0ad8410e9eed3e
1package com.android.server.wifi.hotspot2.omadm; 2 3import android.util.Base64; 4import android.util.Log; 5 6import com.android.server.wifi.anqp.eap.EAP; 7import com.android.server.wifi.anqp.eap.EAPMethod; 8import com.android.server.wifi.anqp.eap.ExpandedEAPMethod; 9import com.android.server.wifi.anqp.eap.InnerAuthEAP; 10import com.android.server.wifi.anqp.eap.NonEAPInnerAuth; 11import com.android.server.wifi.hotspot2.Utils; 12import com.android.server.wifi.hotspot2.pps.Credential; 13import com.android.server.wifi.hotspot2.pps.HomeSP; 14 15import org.xml.sax.SAXException; 16 17import java.io.BufferedInputStream; 18import java.io.BufferedOutputStream; 19import java.io.File; 20import java.io.FileInputStream; 21import java.io.FileOutputStream; 22import java.io.IOException; 23import java.nio.charset.StandardCharsets; 24import java.text.DateFormat; 25import java.text.ParseException; 26import java.text.SimpleDateFormat; 27import java.util.ArrayList; 28import java.util.Arrays; 29import java.util.Collection; 30import java.util.Collections; 31import java.util.Date; 32import java.util.HashMap; 33import java.util.HashSet; 34import java.util.List; 35import java.util.Map; 36import java.util.Set; 37import java.util.TimeZone; 38 39/** 40 * Handles provisioning of PerProviderSubscription data. 41 */ 42public class MOManager { 43 44 public static final String TAG_AAAServerTrustRoot = "AAAServerTrustRoot"; 45 public static final String TAG_AbleToShare = "AbleToShare"; 46 public static final String TAG_CertificateType = "CertificateType"; 47 public static final String TAG_CertSHA256Fingerprint = "CertSHA256Fingerprint"; 48 public static final String TAG_CertURL = "CertURL"; 49 public static final String TAG_CheckAAAServerCertStatus = "CheckAAAServerCertStatus"; 50 public static final String TAG_Country = "Country"; 51 public static final String TAG_CreationDate = "CreationDate"; 52 public static final String TAG_Credential = "Credential"; 53 public static final String TAG_CredentialPriority = "CredentialPriority"; 54 public static final String TAG_DataLimit = "DataLimit"; 55 public static final String TAG_DigitalCertificate = "DigitalCertificate"; 56 public static final String TAG_DLBandwidth = "DLBandwidth"; 57 public static final String TAG_EAPMethod = "EAPMethod"; 58 public static final String TAG_EAPType = "EAPType"; 59 public static final String TAG_ExpirationDate = "ExpirationDate"; 60 public static final String TAG_Extension = "Extension"; 61 public static final String TAG_FQDN = "FQDN"; 62 public static final String TAG_FQDN_Match = "FQDN_Match"; 63 public static final String TAG_FriendlyName = "FriendlyName"; 64 public static final String TAG_HESSID = "HESSID"; 65 public static final String TAG_HomeOI = "HomeOI"; 66 public static final String TAG_HomeOIList = "HomeOIList"; 67 public static final String TAG_HomeOIRequired = "HomeOIRequired"; 68 public static final String TAG_HomeSP = "HomeSP"; 69 public static final String TAG_IconURL = "IconURL"; 70 public static final String TAG_IMSI = "IMSI"; 71 public static final String TAG_InnerEAPType = "InnerEAPType"; 72 public static final String TAG_InnerMethod = "InnerMethod"; 73 public static final String TAG_InnerVendorID = "InnerVendorID"; 74 public static final String TAG_InnerVendorType = "InnerVendorType"; 75 public static final String TAG_IPProtocol = "IPProtocol"; 76 public static final String TAG_MachineManaged = "MachineManaged"; 77 public static final String TAG_MaximumBSSLoadValue = "MaximumBSSLoadValue"; 78 public static final String TAG_MinBackhaulThreshold = "MinBackhaulThreshold"; 79 public static final String TAG_NetworkID = "NetworkID"; 80 public static final String TAG_NetworkType = "NetworkType"; 81 public static final String TAG_Other = "Other"; 82 public static final String TAG_OtherHomePartners = "OtherHomePartners"; 83 public static final String TAG_Password = "Password"; 84 public static final String TAG_PerProviderSubscription = "PerProviderSubscription"; 85 public static final String TAG_Policy = "Policy"; 86 public static final String TAG_PolicyUpdate = "PolicyUpdate"; 87 public static final String TAG_PortNumber = "PortNumber"; 88 public static final String TAG_PreferredRoamingPartnerList = "PreferredRoamingPartnerList"; 89 public static final String TAG_Priority = "Priority"; 90 public static final String TAG_Realm = "Realm"; 91 public static final String TAG_RequiredProtoPortTuple = "RequiredProtoPortTuple"; 92 public static final String TAG_Restriction = "Restriction"; 93 public static final String TAG_RoamingConsortiumOI = "RoamingConsortiumOI"; 94 public static final String TAG_SIM = "SIM"; 95 public static final String TAG_SoftTokenApp = "SoftTokenApp"; 96 public static final String TAG_SPExclusionList = "SPExclusionList"; 97 public static final String TAG_SSID = "SSID"; 98 public static final String TAG_StartDate = "StartDate"; 99 public static final String TAG_SubscriptionParameters = "SubscriptionParameters"; 100 public static final String TAG_SubscriptionUpdate = "SubscriptionUpdate"; 101 public static final String TAG_TimeLimit = "TimeLimit"; 102 public static final String TAG_TrustRoot = "TrustRoot"; 103 public static final String TAG_TypeOfSubscription = "TypeOfSubscription"; 104 public static final String TAG_ULBandwidth = "ULBandwidth"; 105 public static final String TAG_UpdateIdentifier = "UpdateIdentifier"; 106 public static final String TAG_UpdateInterval = "UpdateInterval"; 107 public static final String TAG_UpdateMethod = "UpdateMethod"; 108 public static final String TAG_URI = "URI"; 109 public static final String TAG_UsageLimits = "UsageLimits"; 110 public static final String TAG_UsageTimePeriod = "UsageTimePeriod"; 111 public static final String TAG_Username = "Username"; 112 public static final String TAG_UsernamePassword = "UsernamePassword"; 113 public static final String TAG_VendorId = "VendorId"; 114 public static final String TAG_VendorType = "VendorType"; 115 116 private static final DateFormat DTFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 117 118 static { 119 DTFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 120 } 121 122 private final File mPpsFile; 123 private final Map<String, HomeSP> mSPs; 124 125 public MOManager(File ppsFile) { 126 mPpsFile = ppsFile; 127 mSPs = new HashMap<>(); 128 } 129 130 public File getPpsFile() { 131 return mPpsFile; 132 } 133 134 public Map<String, HomeSP> getLoadedSPs() { 135 return mSPs; 136 } 137 138 public List<HomeSP> loadAllSPs() throws IOException { 139 140 if (!mPpsFile.exists()) { 141 return Collections.emptyList(); 142 } 143 144 try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) { 145 MOTree moTree = MOTree.unmarshal(in); 146 mSPs.clear(); 147 if (moTree == null) { 148 return Collections.emptyList(); // Empty file 149 } 150 151 List<HomeSP> sps = buildSPs(moTree); 152 if (sps != null) { 153 for (HomeSP sp : sps) { 154 if (mSPs.put(sp.getFQDN(), sp) != null) { 155 throw new OMAException("Multiple SPs for FQDN '" + sp.getFQDN() + "'"); 156 } else { 157 Log.d(Utils.HS20_TAG, "retrieved " + sp.getFQDN() + " from PPS"); 158 } 159 } 160 return sps; 161 162 } else { 163 throw new OMAException("Failed to build HomeSP"); 164 } 165 } 166 } 167 168 public static HomeSP buildSP(String xml) throws IOException, SAXException { 169 OMAParser omaParser = new OMAParser(); 170 MOTree tree = omaParser.parse(xml, OMAConstants.LOC_PPS + ":1.0"); 171 List<HomeSP> spList = buildSPs(tree); 172 if (spList.size() != 1) { 173 throw new OMAException("Expected exactly one HomeSP, got " + spList.size()); 174 } 175 return spList.iterator().next(); 176 } 177 178 public HomeSP addSP(String xml) throws IOException, SAXException { 179 OMAParser omaParser = new OMAParser(); 180 MOTree tree = omaParser.parse(xml, OMAConstants.LOC_PPS + ":1.0"); 181 List<HomeSP> spList = buildSPs(tree); 182 if (spList.size() != 1) { 183 throw new OMAException("Expected exactly one HomeSP, got " + spList.size()); 184 } 185 HomeSP sp = spList.iterator().next(); 186 String fqdn = sp.getFQDN(); 187 if (mSPs.put(fqdn, sp) != null) { 188 throw new OMAException("SP " + fqdn + " already exists"); 189 } 190 191 BufferedOutputStream out = null; 192 try { 193 out = new BufferedOutputStream(new FileOutputStream(mPpsFile, true)); 194 tree.marshal(out); 195 out.flush(); 196 } finally { 197 if (out != null) { 198 try { 199 out.close(); 200 } catch (IOException ioe) { 201 /**/ 202 } 203 } 204 } 205 206 return sp; 207 } 208 209 public void saveAllSps(Collection<HomeSP> homeSPs) throws IOException { 210 211 boolean dirty = false; 212 List<HomeSP> newSet = new ArrayList<>(homeSPs.size()); 213 214 Map<String, HomeSP> spClone = new HashMap<>(mSPs); 215 for (HomeSP homeSP : homeSPs) { 216 HomeSP existing = spClone.remove(homeSP.getFQDN()); 217 if (existing == null) { 218 dirty = true; 219 newSet.add(homeSP); 220 } 221 else if (!homeSP.deepEquals(existing)) { 222 dirty = true; 223 newSet.add(homeSP.getClone(existing.getCredential().getPassword())); 224 Log.d(Utils.HS20_TAG, "Non-equal HomeSP"); 225 } 226 else { 227 newSet.add(existing); 228 } 229 } 230 231 Log.d(Utils.HS20_TAG, String.format("Saving all SPs (%s): current %s (%d), new %s (%d)", 232 dirty ? "dirty" : "clean", 233 fqdnList(mSPs.values()), mSPs.size(), 234 fqdnList(homeSPs), homeSPs.size())); 235 236 if (!dirty && spClone.isEmpty()) { 237 return; 238 } 239 240 mSPs.clear(); 241 242 OMAConstructed ppsNode = new OMAConstructed(null, TAG_PerProviderSubscription, null); 243 int instance = 0; 244 for (HomeSP homeSP : newSet) { 245 buildHomeSPTree(homeSP, ppsNode, instance++); 246 mSPs.put(homeSP.getFQDN(), homeSP); 247 } 248 249 MOTree tree = new MOTree(OMAConstants.LOC_PPS + ":1.0", "1.2", ppsNode); 250 try (BufferedOutputStream out = 251 new BufferedOutputStream(new FileOutputStream(mPpsFile, true))) { 252 tree.marshal(out); 253 out.flush(); 254 } 255 } 256 257 private static String fqdnList(Collection<HomeSP> sps) { 258 StringBuilder sb = new StringBuilder(); 259 boolean first = true; 260 for (HomeSP sp : sps) { 261 if (first) { 262 first = false; 263 } 264 else { 265 sb.append(", "); 266 } 267 sb.append(sp.getFQDN()); 268 } 269 return sb.toString(); 270 } 271 272 private static void buildHomeSPTree(HomeSP homeSP, OMAConstructed root, int spInstance) 273 throws IOException { 274 OMANode providerSubNode = root.addChild(getInstanceString(spInstance), null, null, null); 275 276 // The HomeSP: 277 OMANode homeSpNode = providerSubNode.addChild(TAG_HomeSP, null, null, null); 278 if (!homeSP.getSSIDs().isEmpty()) { 279 OMAConstructed nwkIDNode = 280 (OMAConstructed) homeSpNode.addChild(TAG_NetworkID, null, null, null); 281 int instance = 0; 282 for (Map.Entry<String, Long> entry : homeSP.getSSIDs().entrySet()) { 283 OMAConstructed inode = 284 (OMAConstructed) nwkIDNode.addChild(getInstanceString(instance++), null, null, null); 285 inode.addChild(TAG_SSID, null, entry.getKey(), null); 286 if (entry.getValue() != null) { 287 inode.addChild(TAG_HESSID, null, String.format("%012x", entry.getValue()), null); 288 } 289 } 290 } 291 292 homeSpNode.addChild(TAG_FriendlyName, null, homeSP.getFriendlyName(), null); 293 294 if (homeSP.getIconURL() != null) { 295 homeSpNode.addChild(TAG_IconURL, null, homeSP.getIconURL(), null); 296 } 297 298 homeSpNode.addChild(TAG_FQDN, null, homeSP.getFQDN(), null); 299 300 if (!homeSP.getMatchAllOIs().isEmpty() || !homeSP.getMatchAnyOIs().isEmpty()) { 301 OMAConstructed homeOIList = 302 (OMAConstructed) homeSpNode.addChild(TAG_HomeOIList, null, null, null); 303 304 int instance = 0; 305 for (Long oi : homeSP.getMatchAllOIs()) { 306 OMAConstructed inode = 307 (OMAConstructed) homeOIList.addChild(getInstanceString(instance++), 308 null, null, null); 309 inode.addChild(TAG_HomeOI, null, String.format("%x", oi), null); 310 inode.addChild(TAG_HomeOIRequired, null, "TRUE", null); 311 } 312 for (Long oi : homeSP.getMatchAnyOIs()) { 313 OMAConstructed inode = 314 (OMAConstructed) homeOIList.addChild(getInstanceString(instance++), 315 null, null, null); 316 inode.addChild(TAG_HomeOI, null, String.format("%x", oi), null); 317 inode.addChild(TAG_HomeOIRequired, null, "FALSE", null); 318 } 319 } 320 321 if (!homeSP.getOtherHomePartners().isEmpty()) { 322 OMAConstructed otherPartners = 323 (OMAConstructed) homeSpNode.addChild(TAG_OtherHomePartners, null, null, null); 324 int instance = 0; 325 for (String fqdn : homeSP.getOtherHomePartners()) { 326 OMAConstructed inode = 327 (OMAConstructed) otherPartners.addChild(getInstanceString(instance++), 328 null, null, null); 329 inode.addChild(TAG_FQDN, null, fqdn, null); 330 } 331 } 332 333 if (!homeSP.getRoamingConsortiums().isEmpty()) { 334 homeSpNode.addChild(TAG_RoamingConsortiumOI, null, getRCList(homeSP.getRoamingConsortiums()), null); 335 } 336 337 // The Credential: 338 OMANode credentialNode = providerSubNode.addChild(TAG_Credential, null, null, null); 339 Credential cred = homeSP.getCredential(); 340 EAPMethod method = cred.getEAPMethod(); 341 342 if (cred.getCtime() > 0) { 343 credentialNode.addChild(TAG_CreationDate, 344 null, DTFormat.format(new Date(cred.getCtime())), null); 345 } 346 if (cred.getExpTime() > 0) { 347 credentialNode.addChild(TAG_ExpirationDate, 348 null, DTFormat.format(new Date(cred.getExpTime())), null); 349 } 350 351 if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_SIM 352 || method.getEAPMethodID() == EAP.EAPMethodID.EAP_AKA 353 || method.getEAPMethodID() == EAP.EAPMethodID.EAP_AKAPrim) { 354 355 OMANode simNode = credentialNode.addChild(TAG_SIM, null, null, null); 356 simNode.addChild(TAG_IMSI, null, cred.getImsi(), null); 357 simNode.addChild(TAG_EAPType, null, 358 Integer.toString(EAP.mapEAPMethod(method.getEAPMethodID())), null); 359 360 } else if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_TTLS) { 361 362 OMANode unpNode = credentialNode.addChild(TAG_UsernamePassword, null, null, null); 363 unpNode.addChild(TAG_Username, null, cred.getUserName(), null); 364 unpNode.addChild(TAG_Password, null, 365 Base64.encodeToString(cred.getPassword().getBytes(StandardCharsets.UTF_8), 366 Base64.DEFAULT), null); 367 OMANode eapNode = unpNode.addChild(TAG_EAPMethod, null, null, null); 368 eapNode.addChild(TAG_EAPType, null, 369 Integer.toString(EAP.mapEAPMethod(method.getEAPMethodID())), null); 370 eapNode.addChild(TAG_InnerMethod, null, 371 ((NonEAPInnerAuth) method.getAuthParam()).getOMAtype(), null); 372 373 } else if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_TLS) { 374 375 OMANode certNode = credentialNode.addChild(TAG_DigitalCertificate, null, null, null); 376 certNode.addChild(TAG_CertificateType, null, Credential.CertTypeX509, null); 377 certNode.addChild(TAG_CertSHA256Fingerprint, null, 378 Utils.toHex(cred.getFingerPrint()), null); 379 380 } else { 381 throw new OMAException("Invalid credential on " + homeSP.getFQDN()); 382 } 383 384 credentialNode.addChild(TAG_Realm, null, cred.getRealm(), null); 385 386 // !!! Note: This node defines CRL checking through OSCP, I suspect we won't be able 387 // to do that so it is commented out: 388 //credentialNode.addChild(TAG_CheckAAAServerCertStatus, null, "TRUE", null); 389 } 390 391 private static String getInstanceString(int instance) { 392 return "i" + instance; 393 } 394 395 private static String getRCList(Collection<Long> rcs) { 396 StringBuilder builder = new StringBuilder(); 397 boolean first = true; 398 for (Long roamingConsortium : rcs) { 399 if (first) { 400 first = false; 401 } 402 else { 403 builder.append(','); 404 } 405 builder.append(String.format("%x", roamingConsortium)); 406 } 407 return builder.toString(); 408 } 409 410 private static List<HomeSP> buildSPs(MOTree moTree) throws OMAException { 411 Log.d("HS2J", "MO root: " + moTree.getRoot().getName()); 412 OMAConstructed spList; 413 if (moTree.getRoot().getName().equals(TAG_PerProviderSubscription)) { 414 // The PPS file is rooted at PPS instead of MgmtTree to conserve space 415 spList = moTree.getRoot(); 416 } 417 else { 418 List<String> spPath = Arrays.asList(TAG_PerProviderSubscription); 419 spList = moTree.getRoot().getListValue(spPath.iterator()); 420 } 421 422 List<HomeSP> homeSPs = new ArrayList<>(); 423 424 if (spList == null) { 425 return homeSPs; 426 } 427 for (OMANode spRoot : spList.getChildren()) { 428 homeSPs.add(buildHomeSP(spRoot)); 429 } 430 431 return homeSPs; 432 } 433 434 private static HomeSP buildHomeSP(OMANode ppsRoot) throws OMAException { 435 OMANode spRoot = ppsRoot.getChild(TAG_HomeSP); 436 437 String fqdn = spRoot.getScalarValue(Arrays.asList(TAG_FQDN).iterator()); 438 String friendlyName = spRoot.getScalarValue(Arrays.asList(TAG_FriendlyName).iterator()); 439 String iconURL = spRoot.getScalarValue(Arrays.asList(TAG_IconURL).iterator()); 440 441 HashSet<Long> roamingConsortiums = new HashSet<>(); 442 String oiString = spRoot.getScalarValue(Arrays.asList(TAG_RoamingConsortiumOI).iterator()); 443 if (oiString != null) { 444 for (String oi : oiString.split(",")) { 445 roamingConsortiums.add(Long.parseLong(oi.trim(), 16)); 446 } 447 } 448 449 Map<String, Long> ssids = new HashMap<>(); 450 451 OMANode ssidListNode = spRoot.getListValue(Arrays.asList(TAG_NetworkID).iterator()); 452 if (ssidListNode != null) { 453 for (OMANode ssidRoot : ssidListNode.getChildren()) { 454 OMANode hessidNode = ssidRoot.getChild(TAG_HESSID); 455 ssids.put(ssidRoot.getChild(TAG_SSID).getValue(), getMac(hessidNode)); 456 } 457 } 458 459 Set<Long> matchAnyOIs = new HashSet<>(); 460 List<Long> matchAllOIs = new ArrayList<>(); 461 OMANode homeOIListNode = spRoot.getListValue(Arrays.asList(TAG_HomeOIList).iterator()); 462 if (homeOIListNode != null) { 463 for (OMANode homeOIRoot : homeOIListNode.getChildren()) { 464 String homeOI = homeOIRoot.getChild(TAG_HomeOI).getValue(); 465 if (Boolean.parseBoolean(homeOIRoot.getChild(TAG_HomeOIRequired).getValue())) { 466 matchAllOIs.add(Long.parseLong(homeOI, 16)); 467 } else { 468 matchAnyOIs.add(Long.parseLong(homeOI, 16)); 469 } 470 } 471 } 472 473 Set<String> otherHomePartners = new HashSet<>(); 474 OMANode otherListNode = 475 spRoot.getListValue(Arrays.asList(TAG_OtherHomePartners).iterator()); 476 if (otherListNode != null) { 477 for (OMANode fqdnNode : otherListNode.getChildren()) { 478 otherHomePartners.add(fqdnNode.getChild(TAG_FQDN).getValue()); 479 } 480 } 481 482 Credential credential = buildCredential(ppsRoot.getChild(TAG_Credential)); 483 484 return new HomeSP(ssids, fqdn, roamingConsortiums, otherHomePartners, 485 matchAnyOIs, matchAllOIs, friendlyName, iconURL, credential); 486 } 487 488 private static Credential buildCredential(OMANode credNode) throws OMAException { 489 long ctime = getTime(credNode.getChild(TAG_CreationDate)); 490 long expTime = getTime(credNode.getChild(TAG_ExpirationDate)); 491 String realm = getString(credNode.getChild(TAG_Realm)); 492 boolean checkAAACert = getBoolean(credNode.getChild(TAG_CheckAAAServerCertStatus)); 493 494 OMANode unNode = credNode.getChild(TAG_UsernamePassword); 495 OMANode certNode = credNode.getChild(TAG_DigitalCertificate); 496 OMANode simNode = credNode.getChild(TAG_SIM); 497 498 int alternatives = 0; 499 alternatives += unNode != null ? 1 : 0; 500 alternatives += certNode != null ? 1 : 0; 501 alternatives += simNode != null ? 1 : 0; 502 if (alternatives != 1) { 503 throw new OMAException("Expected exactly one credential type, got " + alternatives); 504 } 505 506 if (unNode != null) { 507 String userName = getString(unNode.getChild(TAG_Username)); 508 String password = getString(unNode.getChild(TAG_Password)); 509 boolean machineManaged = getBoolean(unNode.getChild(TAG_MachineManaged)); 510 String softTokenApp = getString(unNode.getChild(TAG_SoftTokenApp)); 511 boolean ableToShare = getBoolean(unNode.getChild(TAG_AbleToShare)); 512 513 OMANode eapMethodNode = unNode.getChild(TAG_EAPMethod); 514 int eapID = getInteger(eapMethodNode.getChild(TAG_EAPType)); 515 516 EAP.EAPMethodID eapMethodID = EAP.mapEAPMethod(eapID); 517 if (eapMethodID == null) { 518 throw new OMAException("Unknown EAP method: " + eapID); 519 } 520 521 Long vid = getOptionalInteger(eapMethodNode.getChild(TAG_VendorId)); 522 Long vtype = getOptionalInteger(eapMethodNode.getChild(TAG_VendorType)); 523 Long innerEAPType = getOptionalInteger(eapMethodNode.getChild(TAG_InnerEAPType)); 524 EAP.EAPMethodID innerEAPMethod = null; 525 if (innerEAPType != null) { 526 innerEAPMethod = EAP.mapEAPMethod(innerEAPType.intValue()); 527 if (innerEAPMethod == null) { 528 throw new OMAException("Bad inner EAP method: " + innerEAPType); 529 } 530 } 531 532 Long innerVid = getOptionalInteger(eapMethodNode.getChild(TAG_InnerVendorID)); 533 Long innerVtype = getOptionalInteger(eapMethodNode.getChild(TAG_InnerVendorType)); 534 String innerNonEAPMethod = getString(eapMethodNode.getChild(TAG_InnerMethod)); 535 536 EAPMethod eapMethod; 537 if (innerEAPMethod != null) { 538 eapMethod = new EAPMethod(eapMethodID, new InnerAuthEAP(innerEAPMethod)); 539 } else if (vid != null) { 540 eapMethod = new EAPMethod(eapMethodID, 541 new ExpandedEAPMethod(EAP.AuthInfoID.ExpandedEAPMethod, 542 vid.intValue(), vtype)); 543 } else if (innerVid != null) { 544 eapMethod = 545 new EAPMethod(eapMethodID, new ExpandedEAPMethod(EAP.AuthInfoID 546 .ExpandedInnerEAPMethod, innerVid.intValue(), innerVtype)); 547 } else if (innerNonEAPMethod != null) { 548 eapMethod = new EAPMethod(eapMethodID, new NonEAPInnerAuth(innerNonEAPMethod)); 549 } else { 550 throw new OMAException("Incomplete set of EAP parameters"); 551 } 552 553 return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, userName, 554 password, machineManaged, softTokenApp, ableToShare); 555 } 556 if (certNode != null) { 557 try { 558 String certTypeString = getString(certNode.getChild(TAG_CertificateType)); 559 byte[] fingerPrint = getOctets(certNode.getChild(TAG_CertSHA256Fingerprint)); 560 561 EAPMethod eapMethod = new EAPMethod(EAP.EAPMethodID.EAP_TLS, null); 562 563 return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, 564 Credential.mapCertType(certTypeString), fingerPrint); 565 } 566 catch (NumberFormatException nfe) { 567 throw new OMAException("Bad hex string: " + nfe.toString()); 568 } 569 } 570 if (simNode != null) { 571 572 String imsi = getString(simNode.getChild(TAG_IMSI)); 573 EAPMethod eapMethod = 574 new EAPMethod(EAP.mapEAPMethod(getInteger(simNode.getChild(TAG_EAPType))), 575 null); 576 577 return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, imsi); 578 } 579 throw new OMAException("Missing credential parameters"); 580 } 581 582 private static boolean getBoolean(OMANode boolNode) { 583 return boolNode != null && Boolean.parseBoolean(boolNode.getValue()); 584 } 585 586 private static String getString(OMANode stringNode) { 587 return stringNode != null ? stringNode.getValue() : null; 588 } 589 590 private static int getInteger(OMANode intNode) throws OMAException { 591 if (intNode == null) { 592 throw new OMAException("Missing integer value"); 593 } 594 try { 595 return Integer.parseInt(intNode.getValue()); 596 } catch (NumberFormatException nfe) { 597 throw new OMAException("Invalid integer: " + intNode.getValue()); 598 } 599 } 600 601 private static Long getMac(OMANode macNode) throws OMAException { 602 if (macNode == null) { 603 return null; 604 } 605 try { 606 return Long.parseLong(macNode.getValue(), 16); 607 } catch (NumberFormatException nfe) { 608 throw new OMAException("Invalid MAC: " + macNode.getValue()); 609 } 610 } 611 612 private static Long getOptionalInteger(OMANode intNode) throws OMAException { 613 if (intNode == null) { 614 return null; 615 } 616 try { 617 return Long.parseLong(intNode.getValue()); 618 } catch (NumberFormatException nfe) { 619 throw new OMAException("Invalid integer: " + intNode.getValue()); 620 } 621 } 622 623 private static long getTime(OMANode timeNode) throws OMAException { 624 if (timeNode == null) { 625 return -1; 626 } 627 String timeText = timeNode.getValue(); 628 try { 629 Date date = DTFormat.parse(timeText); 630 return date.getTime(); 631 } catch (ParseException pe) { 632 throw new OMAException("Badly formatted time: " + timeText); 633 } 634 } 635 636 private static byte[] getOctets(OMANode octetNode) throws OMAException { 637 if (octetNode == null) { 638 throw new OMAException("Missing byte value"); 639 } 640 return Utils.hexToBytes(octetNode.getValue()); 641 } 642} 643