use of com.android.hotspot2.osu.commands.MOData in project android_frameworks_base by DirtyUnicorns.
the class MOManager method modifySP.
public HomeSP modifySP(HomeSP homeSP, Collection<MOData> mods, OSUManager osuManager) throws IOException {
Log.d(OSUManager.TAG, "modifying SP: " + mods);
MOTree moTree;
int ppsMods = 0;
int updateIdentifier = 0;
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
moTree = MOTree.unmarshal(in);
// moTree is PPS/?/provider-data
OMAConstructed targetTree = findTargetTree(moTree, homeSP.getFQDN());
if (targetTree == null) {
throw new IOException("Failed to find PPS tree for " + homeSP.getFQDN());
}
OMAConstructed instance = getInstanceNode(targetTree);
for (MOData mod : mods) {
LinkedList<String> tailPath = getTailPath(mod.getBaseURI(), TAG_PerProviderSubscription);
OMAConstructed modRoot = mod.getMOTree().getRoot();
if (tailPath.getFirst().equals(TAG_UpdateIdentifier)) {
updateIdentifier = getInteger(modRoot.getChildren().iterator().next());
OMANode oldUdi = targetTree.getChild(TAG_UpdateIdentifier);
if (getInteger(oldUdi) != updateIdentifier) {
ppsMods++;
}
if (oldUdi != null) {
targetTree.replaceNode(oldUdi, modRoot.getChild(TAG_UpdateIdentifier));
} else {
targetTree.addChild(modRoot.getChild(TAG_UpdateIdentifier));
}
} else {
// Drop the instance
tailPath.removeFirst();
OMANode current = instance.getListValue(tailPath.iterator());
if (current == null) {
throw new IOException("No previous node for " + tailPath + " in " + homeSP.getFQDN());
}
for (OMANode newNode : modRoot.getChildren()) {
// newNode is something like Credential
// current is the same existing node
OMANode old = current.getParent().replaceNode(current, newNode);
ppsMods++;
}
}
}
}
writeMO(moTree, mPpsFile, osuManager);
if (ppsMods == 0) {
// HomeSP not modified.
return null;
}
// Return a new rebuilt HomeSP
List<HomeSP> sps = buildSPs(moTree);
if (sps != null) {
for (HomeSP sp : sps) {
if (sp.getFQDN().equals(homeSP.getFQDN())) {
return sp;
}
}
} else {
throw new OMAException("Failed to build HomeSP");
}
return null;
}
use of com.android.hotspot2.osu.commands.MOData in project android_frameworks_base by AOSPA.
the class OSUClient method provision.
public void provision(OSUManager osuManager, Network network, KeyManager km) throws IOException, GeneralSecurityException {
try (HTTPHandler httpHandler = new HTTPHandler(StandardCharsets.UTF_8, OSUSocketFactory.getSocketFactory(mKeyStore, null, OSUManager.FLOW_PROVISIONING, network, mURL, km, true))) {
SPVerifier spVerifier = new SPVerifier(mOSUInfo);
spVerifier.verify(httpHandler.getOSUCertificate(mURL));
URL redirectURL = osuManager.prepareUserInput(mOSUInfo.getName(Locale.getDefault()));
OMADMAdapter omadmAdapter = osuManager.getOMADMAdapter();
String regRequest = SOAPBuilder.buildPostDevDataResponse(RequestReason.SubRegistration, null, redirectURL.toString(), omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
Log.d(TAG, "Registration request: " + regRequest);
OSUResponse osuResponse = httpHandler.exchangeSOAP(mURL, regRequest);
Log.d(TAG, "Response: " + osuResponse);
if (osuResponse.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Expected a PostDevDataResponse");
}
PostDevDataResponse regResponse = (PostDevDataResponse) osuResponse;
String sessionID = regResponse.getSessionID();
if (regResponse.getExecCommand() == ExecCommand.UseClientCertTLS) {
ClientCertInfo ccInfo = (ClientCertInfo) regResponse.getCommandData();
if (ccInfo.doesAcceptMfgCerts()) {
throw new IOException("Mfg certs are not supported in Android");
} else if (ccInfo.doesAcceptProviderCerts()) {
((WiFiKeyManager) km).enableClientAuth(ccInfo.getIssuerNames());
httpHandler.renegotiate(null, null);
} else {
throw new IOException("Neither manufacturer nor provider cert specified");
}
regRequest = SOAPBuilder.buildPostDevDataResponse(RequestReason.SubRegistration, sessionID, redirectURL.toString(), omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
osuResponse = httpHandler.exchangeSOAP(mURL, regRequest);
if (osuResponse.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Expected a PostDevDataResponse");
}
regResponse = (PostDevDataResponse) osuResponse;
}
if (regResponse.getExecCommand() != ExecCommand.Browser) {
throw new IOException("Expected a launchBrowser command");
}
Log.d(TAG, "Exec: " + regResponse.getExecCommand() + ", for '" + regResponse.getCommandData() + "'");
if (!osuResponse.getSessionID().equals(sessionID)) {
throw new IOException("Mismatching session IDs");
}
String webURL = ((BrowserURI) regResponse.getCommandData()).getURI();
if (webURL == null) {
throw new IOException("No web-url");
} else if (!webURL.contains(sessionID)) {
throw new IOException("Bad or missing session ID in webURL");
}
if (!osuManager.startUserInput(new URL(webURL), network)) {
throw new IOException("User session failed");
}
Log.d(TAG, " -- Sending user input complete:");
String userComplete = SOAPBuilder.buildPostDevDataResponse(RequestReason.InputComplete, sessionID, null, omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
OSUResponse moResponse1 = httpHandler.exchangeSOAP(mURL, userComplete);
if (moResponse1.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Bad user input complete response: " + moResponse1);
}
PostDevDataResponse provResponse = (PostDevDataResponse) moResponse1;
GetCertData estData = checkResponse(provResponse);
Map<OSUCertType, List<X509Certificate>> certs = new HashMap<>();
PrivateKey clientKey = null;
MOData moData;
if (estData == null) {
moData = (MOData) provResponse.getCommandData();
} else {
try (ESTHandler estHandler = new ESTHandler((GetCertData) provResponse.getCommandData(), network, osuManager.getOMADMAdapter(), km, mKeyStore, null, OSUManager.FLOW_PROVISIONING)) {
estHandler.execute(false);
certs.put(OSUCertType.CA, estHandler.getCACerts());
certs.put(OSUCertType.Client, estHandler.getClientCerts());
clientKey = estHandler.getClientKey();
}
Log.d(TAG, " -- Sending provisioning cert enrollment complete:");
String certComplete = SOAPBuilder.buildPostDevDataResponse(RequestReason.CertEnrollmentComplete, sessionID, null, omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
OSUResponse moResponse2 = httpHandler.exchangeSOAP(mURL, certComplete);
if (moResponse2.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Bad cert enrollment complete response: " + moResponse2);
}
PostDevDataResponse provComplete = (PostDevDataResponse) moResponse2;
if (provComplete.getStatus() != OSUStatus.ProvComplete || provComplete.getOSUCommand() != OSUCommandID.AddMO) {
throw new IOException("Expected addMO: " + provComplete);
}
moData = (MOData) provComplete.getCommandData();
}
// !!! How can an ExchangeComplete be sent w/o knowing the fate of the certs???
String updateResponse = SOAPBuilder.buildUpdateResponse(sessionID, null);
Log.d(TAG, " -- Sending updateResponse:");
OSUResponse exComplete = httpHandler.exchangeSOAP(mURL, updateResponse);
Log.d(TAG, "exComplete response: " + exComplete);
if (exComplete.getMessageType() != OSUMessageType.ExchangeComplete) {
throw new IOException("Expected ExchangeComplete: " + exComplete);
} else if (exComplete.getStatus() != OSUStatus.ExchangeComplete) {
throw new IOException("Bad ExchangeComplete status: " + exComplete);
}
retrieveCerts(moData.getMOTree().getRoot(), certs, network, km, mKeyStore);
osuManager.provisioningComplete(mOSUInfo, moData, certs, clientKey, network);
}
}
use of com.android.hotspot2.osu.commands.MOData in project android_frameworks_base by AOSPA.
the class OSUClient method remediate.
public void remediate(OSUManager osuManager, Network network, KeyManager km, HomeSP homeSP, int flowType) throws IOException, GeneralSecurityException {
try (HTTPHandler httpHandler = createHandler(network, homeSP, km, flowType)) {
URL redirectURL = osuManager.prepareUserInput(homeSP.getFriendlyName());
OMADMAdapter omadmAdapter = osuManager.getOMADMAdapter();
String regRequest = SOAPBuilder.buildPostDevDataResponse(RequestReason.SubRemediation, null, redirectURL.toString(), omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
OSUResponse serverResponse = httpHandler.exchangeSOAP(mURL, regRequest);
if (serverResponse.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Expected a PostDevDataResponse");
}
String sessionID = serverResponse.getSessionID();
PostDevDataResponse pddResponse = (PostDevDataResponse) serverResponse;
Log.d(TAG, "Remediation response: " + pddResponse);
Map<OSUCertType, List<X509Certificate>> certs = null;
PrivateKey clientKey = null;
if (pddResponse.getStatus() != OSUStatus.RemediationComplete) {
if (pddResponse.getExecCommand() == ExecCommand.UploadMO) {
String ulMessage = SOAPBuilder.buildPostDevDataResponse(RequestReason.MOUpload, null, redirectURL.toString(), omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN), osuManager.getMOTree(homeSP));
Log.d(TAG, "Upload MO: " + ulMessage);
OSUResponse ulResponse = httpHandler.exchangeSOAP(mURL, ulMessage);
if (ulResponse.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Expected a PostDevDataResponse to MOUpload");
}
pddResponse = (PostDevDataResponse) ulResponse;
}
if (pddResponse.getExecCommand() == ExecCommand.Browser) {
if (flowType == OSUManager.FLOW_POLICY) {
throw new IOException("Browser launch requested in policy flow");
}
String webURL = ((BrowserURI) pddResponse.getCommandData()).getURI();
if (webURL == null) {
throw new IOException("No web-url");
} else if (!webURL.contains(sessionID)) {
throw new IOException("Bad or missing session ID in webURL");
}
if (!osuManager.startUserInput(new URL(webURL), network)) {
throw new IOException("User session failed");
}
Log.d(TAG, " -- Sending user input complete:");
String userComplete = SOAPBuilder.buildPostDevDataResponse(RequestReason.InputComplete, sessionID, null, omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
OSUResponse udResponse = httpHandler.exchangeSOAP(mURL, userComplete);
if (udResponse.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Bad user input complete response: " + udResponse);
}
pddResponse = (PostDevDataResponse) udResponse;
} else if (pddResponse.getExecCommand() == ExecCommand.GetCert) {
certs = new HashMap<>();
try (ESTHandler estHandler = new ESTHandler((GetCertData) pddResponse.getCommandData(), network, osuManager.getOMADMAdapter(), km, mKeyStore, homeSP, flowType)) {
estHandler.execute(true);
certs.put(OSUCertType.CA, estHandler.getCACerts());
certs.put(OSUCertType.Client, estHandler.getClientCerts());
clientKey = estHandler.getClientKey();
}
if (httpHandler.isHTTPAuthPerformed()) {
// 8.4.3.6
httpHandler.renegotiate(certs, clientKey);
}
Log.d(TAG, " -- Sending remediation cert enrollment complete:");
// 8.4.3.5 in the spec actually prescribes that an update URI is sent here,
// but there is no remediation flow that defines user interaction after EST
// so for now a null is passed.
String certComplete = SOAPBuilder.buildPostDevDataResponse(RequestReason.CertEnrollmentComplete, sessionID, null, omadmAdapter.getMO(OMAConstants.DevInfoURN), omadmAdapter.getMO(OMAConstants.DevDetailURN));
OSUResponse ceResponse = httpHandler.exchangeSOAP(mURL, certComplete);
if (ceResponse.getMessageType() != OSUMessageType.PostDevData) {
throw new IOException("Bad cert enrollment complete response: " + ceResponse);
}
pddResponse = (PostDevDataResponse) ceResponse;
} else {
throw new IOException("Unexpected command: " + pddResponse.getExecCommand());
}
}
if (pddResponse.getStatus() != OSUStatus.RemediationComplete) {
throw new IOException("Expected a PostDevDataResponse to MOUpload");
}
Log.d(TAG, "Remediation response: " + pddResponse);
List<MOData> mods = new ArrayList<>();
for (OSUCommand command : pddResponse.getCommands()) {
if (command.getOSUCommand() == OSUCommandID.UpdateNode) {
mods.add((MOData) command.getCommandData());
} else if (command.getOSUCommand() != OSUCommandID.NoMOUpdate) {
throw new IOException("Unexpected OSU response: " + command);
}
}
// 1. Machine remediation: Remediation complete + replace node
// 2a. User remediation with upload: ExecCommand.UploadMO
// 2b. User remediation without upload: ExecCommand.Browser
// 3. User remediation only: -> sppPostDevData user input complete
//
// 4. Update node
// 5. -> Update response
// 6. Exchange complete
OSUError error = null;
String updateResponse = SOAPBuilder.buildUpdateResponse(sessionID, error);
Log.d(TAG, " -- Sending updateResponse:");
OSUResponse exComplete = httpHandler.exchangeSOAP(mURL, updateResponse);
Log.d(TAG, "exComplete response: " + exComplete);
if (exComplete.getMessageType() != OSUMessageType.ExchangeComplete) {
throw new IOException("Expected ExchangeComplete: " + exComplete);
} else if (exComplete.getStatus() != OSUStatus.ExchangeComplete) {
throw new IOException("Bad ExchangeComplete status: " + exComplete);
}
// the network is lost and the remediation flow fails.
try {
osuManager.remediationComplete(homeSP, mods, certs, clientKey);
} catch (IOException | GeneralSecurityException e) {
osuManager.provisioningFailed(homeSP.getFriendlyName(), e.getMessage(), homeSP, OSUManager.FLOW_REMEDIATION);
error = OSUError.CommandFailed;
}
}
}
use of com.android.hotspot2.osu.commands.MOData in project android_frameworks_base by AOSPA.
the class MOManager method modifySP.
public HomeSP modifySP(HomeSP homeSP, Collection<MOData> mods, OSUManager osuManager) throws IOException {
Log.d(OSUManager.TAG, "modifying SP: " + mods);
MOTree moTree;
int ppsMods = 0;
int updateIdentifier = 0;
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
moTree = MOTree.unmarshal(in);
// moTree is PPS/?/provider-data
OMAConstructed targetTree = findTargetTree(moTree, homeSP.getFQDN());
if (targetTree == null) {
throw new IOException("Failed to find PPS tree for " + homeSP.getFQDN());
}
OMAConstructed instance = getInstanceNode(targetTree);
for (MOData mod : mods) {
LinkedList<String> tailPath = getTailPath(mod.getBaseURI(), TAG_PerProviderSubscription);
OMAConstructed modRoot = mod.getMOTree().getRoot();
if (tailPath.getFirst().equals(TAG_UpdateIdentifier)) {
updateIdentifier = getInteger(modRoot.getChildren().iterator().next());
OMANode oldUdi = targetTree.getChild(TAG_UpdateIdentifier);
if (getInteger(oldUdi) != updateIdentifier) {
ppsMods++;
}
if (oldUdi != null) {
targetTree.replaceNode(oldUdi, modRoot.getChild(TAG_UpdateIdentifier));
} else {
targetTree.addChild(modRoot.getChild(TAG_UpdateIdentifier));
}
} else {
// Drop the instance
tailPath.removeFirst();
OMANode current = instance.getListValue(tailPath.iterator());
if (current == null) {
throw new IOException("No previous node for " + tailPath + " in " + homeSP.getFQDN());
}
for (OMANode newNode : modRoot.getChildren()) {
// newNode is something like Credential
// current is the same existing node
OMANode old = current.getParent().replaceNode(current, newNode);
ppsMods++;
}
}
}
}
writeMO(moTree, mPpsFile, osuManager);
if (ppsMods == 0) {
// HomeSP not modified.
return null;
}
// Return a new rebuilt HomeSP
List<HomeSP> sps = buildSPs(moTree);
if (sps != null) {
for (HomeSP sp : sps) {
if (sp.getFQDN().equals(homeSP.getFQDN())) {
return sp;
}
}
} else {
throw new OMAException("Failed to build HomeSP");
}
return null;
}
use of com.android.hotspot2.osu.commands.MOData in project android_frameworks_base by AOSPA.
the class OSUManager method remediationComplete.
public void remediationComplete(HomeSP homeSP, Collection<MOData> mods, Map<OSUCertType, List<X509Certificate>> certs, PrivateKey privateKey) throws IOException, GeneralSecurityException {
HomeSP altSP = mWifiNetworkAdapter.modifySP(homeSP, mods);
X509Certificate caCert = null;
List<X509Certificate> clientCerts = null;
if (certs != null) {
List<X509Certificate> certList = certs.get(OSUCertType.AAA);
caCert = certList != null && !certList.isEmpty() ? certList.iterator().next() : null;
clientCerts = certs.get(OSUCertType.Client);
}
if (altSP != null || certs != null) {
if (altSP == null) {
// No MO mods, only certs and key
altSP = homeSP;
}
mWifiNetworkAdapter.updateNetwork(altSP, caCert, clientCerts, privateKey);
}
notifyUser(OSUOperationStatus.ProvisioningSuccess, null, homeSP.getFriendlyName());
}
Aggregations