Protocolpublic class Protocol extends com.sun.midp.io.j2me.http.Protocol implements HttpsConnectionThis class implements the necessary functionality
for an HTTPS connection. With support for HTTPS tunneling.
Handshake error codes at the beginning of IOException messages:
(1) certificate is expired
(2) certificate is not yet valid
(3) certificate failed signature verification
(4) certificate was signed using an unsupported algorithm
(5) certificate was issued by an unrecognized certificate authority
(6) certificate does not contain the correct site name
(7) certificate chain exceeds the length allowed
(8) certificate does not contain a signature
(9) version 3 certificate has unrecognized critical extensions
(10) version 3 certificate has an inappropriate keyUsage or
extendedKeyUsage extension
(11) certificate in the a chain was not issued by the next
authority in the chain
(12) trusted certificate authority's public key is expired
|
Fields Summary |
---|
private static final String | COMMON_NAME_LABELCommon name label. | private static final int | COMMON_NAME_LABEL_LENGTHCommon name label length. | private static SecurityToken | classSecurityTokenThis class has a different security domain than the MIDlet suite | private Properties | proxyHeaderscollection of "Proxy-" headers as name/value pairs | private SSLStreamConnection | sslConnectionUnderlying SSL connection. |
Constructors Summary |
---|
public Protocol()Create a new instance of this class. Override the some of the values
in our super class.
protocol = "https";
default_port = 443; // 443 is the default port for HTTPS
requiredPermission = Permissions.HTTPS;
|
Methods Summary |
---|
private static boolean | checkSiteName(java.lang.String siteName, java.lang.String certName)Check to see if the site name given by the user matches the site
name of subject in the certificate. The method supports the wild card
character for the machine name if a domain name is included after it.
int startOfDomain;
int domainLength;
if (certName == null) {
return false;
}
// try the easy way first, ignoring case
if ((siteName.length() == certName.length()) &&
siteName.regionMatches(true, 0, certName, 0,
certName.length())) {
return true;
}
if (!certName.startsWith("*.")) {
// not a wild card, done
return false;
}
startOfDomain = siteName.indexOf('.");
if (startOfDomain == -1) {
// no domain name
return false;
}
// skip past the '.'
startOfDomain++;
domainLength = siteName.length() - startOfDomain;
if ((certName.length() - 2) != domainLength) {
return false;
}
// compare the just the domain names, ignoring case
if (siteName.regionMatches(true, startOfDomain, certName, 2,
domainLength)) {
return true;
}
return false;
| protected StreamConnection | connect()Connect to the underlying secure socket transport.
Perform the SSL handshake and then proceded to the underlying
HTTP protocol connect semantics.
String httpsTunnel;
com.sun.midp.io.j2me.socket.Protocol tcpConnection;
OutputStream tcpOutputStream;
InputStream tcpInputStream;
X509Certificate serverCert;
verifyPermissionCheck();
/*
* To save memory for applications the do not use HTTPS,
* the public keys of the certificate authorities may not
* have been loaded yet.
*/
WebPublicKeyStore.loadCertificateAuthorities();
// Open socket connection
tcpConnection =
new com.sun.midp.io.j2me.socket.Protocol();
// check to see if a protocol is specified for the tunnel
httpsTunnel = Configuration.getProperty("com.sun.midp.io.http.proxy");
if (httpsTunnel != null) {
// Make the connection to the ssl tunnel
tcpConnection.openPrim(classSecurityToken, "//" + httpsTunnel);
// Do not delay request since this delays the response.
tcpConnection.setSocketOption(SocketConnection.DELAY, 0);
tcpOutputStream = tcpConnection.openOutputStream();
tcpInputStream = tcpConnection.openInputStream();
// Do the handshake with the ssl tunnel
try {
doTunnelHandshake(tcpOutputStream, tcpInputStream);
} catch (IOException ioe) {
String temp = ioe.getMessage();
tcpConnection.close();
tcpOutputStream.close();
tcpInputStream.close();
if (temp.indexOf(" 500 ") > -1) {
throw new ConnectionNotFoundException(temp);
}
throw ioe;
}
} else {
tcpConnection.openPrim(classSecurityToken, "//" + hostAndPort);
// Do not delay request since this delays the response.
tcpConnection.setSocketOption(SocketConnection.DELAY, 0);
tcpOutputStream = tcpConnection.openOutputStream();
tcpInputStream = tcpConnection.openInputStream();
}
tcpConnection.close();
try {
// Get the SSLStreamConnection
sslConnection = new SSLStreamConnection(url.host, url.port,
tcpInputStream, tcpOutputStream);
} catch (Exception e) {
try {
tcpInputStream.close();
} finally {
try {
tcpOutputStream.close();
} finally {
if (e instanceof IOException) {
throw (IOException)e;
} else {
throw (RuntimeException)e;
}
}
}
}
try {
serverCert = sslConnection.getServerCertificate();
/*
* if the subject alternate name is a DNS name,
* then use that instead of the common name for a
* site name match
*/
if (serverCert.getSubjectAltNameType() ==
X509Certificate.TYPE_DNS_NAME) {
if (!checkSiteName(url.host,
(String)serverCert.getSubjectAltName())) {
throw new CertificateException(
"Subject alternative name did not match site name",
serverCert, CertificateException.SITENAME_MISMATCH);
}
} else {
String cname = getCommonName(serverCert.getSubject());
if (cname == null) {
throw new CertificateException(
"Common name missing from subject name",
serverCert, CertificateException.SITENAME_MISMATCH);
}
if (!checkSiteName(url.host, cname)) {
throw new CertificateException(serverCert,
CertificateException.SITENAME_MISMATCH);
}
}
return sslConnection;
} catch (Exception e) {
try {
sslConnection.close();
} finally {
if (e instanceof IOException) {
throw (IOException)e;
} else {
throw (RuntimeException)e;
}
}
}
| protected void | disconnect(StreamConnection connection, java.io.InputStream inputStream, java.io.OutputStream outputStream)disconnect the current connection.
try {
try {
inputStream.close();
} finally {
try {
outputStream.close();
} finally {
connection.close();
}
}
} catch (IOException e) {
} catch (NullPointerException e) {
}
| private static java.lang.String | getCommonName(java.lang.String name)Parse the common name out of a distinguished name.
int start;
int end;
if (name == null) {
return null;
}
/* The common name starts with "CN=" label */
start = name.indexOf(COMMON_NAME_LABEL);
if (start < 0) {
return null;
}
start += COMMON_NAME_LABEL_LENGTH;
end = name.indexOf(';", start);
if (end < 0) {
end = name.length();
}
return name.substring(start, end);
| public java.lang.String | getRequestProperty(java.lang.String key)Get the request header value for the named property.
/* https handles the proxy fields in a different way */
if (key.startsWith("Proxy-")) {
return proxyHeaders.getProperty(key);
}
return super.getRequestProperty(key);
| public SecurityInfo | getSecurityInfo()Return the security information associated with this connection.
If the connection is still in Setup state then
the connection is initiated to establish the secure connection
to the server. The method returns when the connection is
established and the Certificate supplied by the
server has been validated.
The SecurityInfo is only returned if the
connection has been successfully made to the server.
ensureOpen();
sendRequest();
if (sslConnection == null) {
/*
* This is a persistent connection so the connect method did
* not get called, so the stream connection of HTTP class
* will be a SSL connection. Get the info from that.
*/
StreamConnection sc =
((StreamConnectionElement)getStreamConnection()).
getBaseConnection();
return ((SSLStreamConnection)sc).getSecurityInfo();
}
return sslConnection.getSecurityInfo();
| public static void | initSecurityToken(SecurityToken token)Initializes the security token for this class, so it can
perform actions that a normal MIDlet Suite cannot.
if (classSecurityToken != null) {
return;
}
classSecurityToken = token;
| protected void | setRequestField(java.lang.String key, java.lang.String value)Add the named field to the list of request fields.
/* https handles the proxy fields in a different way */
if (key.startsWith("Proxy-")) {
proxyHeaders.setProperty(key, value);
return;
}
super.setRequestField(key, value);
|
|