package com.android.hotspot2.osu; import com.android.hotspot2.omadm.OMAException; import com.android.hotspot2.omadm.XMLNode; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.ParserConfigurationException; public class SOAPParser { private static final String EnvelopeTag = "envelope"; private static final String BodyTag = "body"; private static final Map sResponseMap = new HashMap<>(); static { sResponseMap.put("spppostdevdataresponse", new ResponseFactory() { @Override public OSUResponse buildResponse(XMLNode root) throws OMAException { return new PostDevDataResponse(root); } }); sResponseMap.put("sppexchangecomplete", new ResponseFactory() { @Override public OSUResponse buildResponse(XMLNode root) throws OMAException { return new ExchangeCompleteResponse(root); } }); sResponseMap.put("getcertificate", new ResponseFactory() { @Override public OSUResponse buildResponse(XMLNode root) { return null; } }); sResponseMap.put("spperror", new ResponseFactory() { @Override public OSUResponse buildResponse(XMLNode root) { return null; } }); } private final XMLNode mResponseNode; public SOAPParser(InputStream in) throws ParserConfigurationException, SAXException, IOException { XMLNode root; try { XMLParser parser = new XMLParser(in); root = parser.getRoot(); } finally { in.close(); } String[] nsn = root.getTag().split(":"); if (nsn.length > 2) { throw new OMAException("Bad root tag syntax: '" + root.getTag() + "'"); } else if (!EnvelopeTag.equalsIgnoreCase(nsn[nsn.length - 1])) { throw new OMAException("Expected envelope: '" + root.getTag() + "'"); } String bodyTag = nsn.length > 1 ? (nsn[0] + ":" + BodyTag) : BodyTag; XMLNode body = null; for (XMLNode child : root.getChildren()) { if (bodyTag.equalsIgnoreCase(child.getTag())) { body = child; break; } } if (body == null || body.getChildren().isEmpty()) { throw new OMAException("Missing SOAP body"); } mResponseNode = body.getSoleChild(); } public OSUResponse getResponse() throws OMAException { ResponseFactory responseFactory = sResponseMap.get(mResponseNode.getStrippedTag()); if (responseFactory == null) { throw new OMAException("Unknown response type: '" + mResponseNode.getStrippedTag() + "'"); } return responseFactory.buildResponse(mResponseNode); } public XMLNode getResponseNode() { return mResponseNode; } /* SOAP method response from SPP server. Receipt of this element by a mobile device causes the following command to be executed. When the mobile device receives this command, it launches its default browser to the URI contained in this element. The URI must use HTTPS as the protocol and must contain an FQDN. Command to mobile to re-negotiate the TLS connection using a client certificate of the accepted type or Issuer to authenticate with the Subscription server. The issuer name of an acceptable provider-issued certificate. The text of this element is formatted in accordance with the Issuer Name field in RFC-3280. This element is present only when acceptProviderCerts is true. When this boolean is true, IEEE 802.1ar manufacturing certificates are acceptable for mobile device authentication. When this boolean is true, X509v3 certificates issued by providers identified in the providerIssuerName child element(s) are acceptable for mobile device authentication. Command to mobile to upload the MO named in the moURN attribute to the SPP server. Element to allow the addition of new commands in the future. This command causes an management object in the mobile devices management tree at the specified location to be added. If there is already a management object at that location, the object is replaced. This command causes the update of an interior node and its child nodes (if any) at the location specified in the management tree URI attribute. The content of this element is the MO node XML. This response is used when there is no command to be executed nor update of any MO required. For vendor-specific extensions or future needs. SOAP method used by SPP client to confirm installation of MO addition or update. SOAP method used by SPP server to end session. Command to mobile to initiate certificate enrollment or re-enrollment and is a container for metadata to enable enrollment. HTTPS URI of the server to be contacted to initiate certificate enrollment. The URI must contain an FQDN. Temporary userid used by an EST client to authenticate to the EST server using HTTP Digest authentication. This element must be used for initial certificate enrollment; its use is optional for certificate re-enrollment. Temporary password used by an EST client to authenticate to the EST server using HTTP Digest authentication. This element must be used for initial certificate enrollment; its use is optional for certificate re-enrollment. For vendor-specific extensions or future needs. Error response. */ }