📄 protocol.java
字号:
/* * @(#)Protocol.java 1.11 01/08/22 * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. */ package com.sun.midp.io.j2me.https;import java.util.Hashtable;import java.util.Enumeration;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.microedition.io.Connector;import javax.microedition.io.StreamConnection;import javax.microedition.io.ConnectionNotFoundException;import com.sun.kssl.*;import com.sun.midp.Configuration;import com.sun.midp.io.InternalConnector;import com.sun.midp.io.Properties;import com.sun.midp.io.j2me.http.*;import com.sun.midp.io.j2me.storage.File;import com.sun.midp.io.j2me.storage.RandomAccessStream;import com.sun.midp.publickeystore.WebPublicKeyStore;import com.sun.midp.security.ImplicitlyTrustedClass;import com.sun.midp.security.SecurityDomain;/** * This class implements the necessary functionality * for an HTTPS connection. With support for HTTPS tunneling. * <p> * Handshake error codes at the beginning of IOException messages:</p> * <blockquote><p> * (1) certificate is expired * </p><p> * (2) certificate is not yet valid * </p><p> * (3) certificate failed signature verification * </p><p> * (4) certificate was signed using an unsupported algorithm * </p><p> * (5) certificate was issued by an unrecognized certificate authority * </p><p> * (6) certificate does not contain the correct site name * </p><p> * (7) certificate chain exceeds the length allowed * </p><p> * (8) certificate does not contain a signature * </p><p> * (9) version 3 certificate has unrecognized critical extensions * </p><p> * (10) version 3 certificate has an inappropriate keyUsage or * extendedKeyUsage extension * </p><p> * (11) certificate in the a chain was not issued by the next * authority in the chain * </p><p> * (12) trusted certificate authority's public key is expired * </p></blockquote> */public class Protocol extends com.sun.midp.io.j2me.http.Protocol implements ImplicitlyTrustedClass, HandshakeListener { /** This class has a different security domain than the MIDlet suite */ private static SecurityDomain classSecurityDomain; /** We do not want to load CA's more than once */ private static boolean caLoaded; /** * Load the certificate authorities for the MIDP RI from storage * into the SSL keystore. */ private static void loadCertificateAuthorities() { RandomAccessStream storage; InputStream tks; WebPublicKeyStore ks; try { storage = new RandomAccessStream(classSecurityDomain); storage.connect(File.getStorageRoot() + "_main.ks", Connector.READ); tks = storage.openInputStream(); } catch (Exception e) { System.out.println("Could not open the trusted key store, " + "cannot authenticate HTTPS servers"); return; } try { ks = new com.sun.midp.publickeystore.WebPublicKeyStore(tks); } catch (Exception e) { System.out.println("Corrupt key store file, " + "cannot authenticate HTTPS servers"); e.printStackTrace(); return; } finally { try { storage.disconnect(); } catch (Exception e) { // nothing we can do. } } WebPublicKeyStore.setTrustedKeyStore(ks); } /** collection of "Proxy-" headers as name/value pairs */ private Properties proxyHeaders = new Properties(); /** last handshake error */ private byte handshakeError; /** bad cert that caused the last handshake error */ private X509Certificate badCert; /** * Create a new instance of this class. Override the some of the values * in our super class. */ public Protocol() { protocol = "https"; default_port = 443; // 443 is the default port for HTTPS } /** * Initializes the security domain for this class, so it can * perform actions that a normal MIDlet Suite cannot. * * @param domain <code>SecurityDomain</code> for this class. */ public void initSecurityDomain(SecurityDomain domain) { if (classSecurityDomain == null) { classSecurityDomain = domain; } } /** * Get the request header value for the named property. * @param key property name of specific HTTP 1.1 header field * @return value of the named property, if found, null otherwise. */ public String getRequestProperty(String key) { /* https handles the proxy fields in a different way */ if (key.startsWith("Proxy-")) { return proxyHeaders.getProperty(key); } return super.getRequestProperty(key); } /** * Add the named field to the list of request fields. * * @param key key for the request header field. * @param value the value for the request header field. */ protected void setRequestField(String key, String value) { /* https handles the proxy fields in a different way */ if (key.startsWith("Proxy-")) { proxyHeaders.setProperty(key, value); return; } super.setRequestField(key, value); } /** * Connect to the underlying secure socket transport. * Perform the SSL handshake and then proceded to the underlying * HTTP protocol connect semantics. * * @return SSL/TCP stream connection * @exception IOException is thrown if the connection cannot be opened */ protected StreamConnection connect() throws IOException { String httpsTunnel; StreamConnection tcpConnection; OutputStream tcpOutputStream; InputStream tcpInputStream; /* * To save memory for applications the do not use HTTPS, * the public keys of the certificate authorities may not * have been loaded yet. */ if (!caLoaded) { caLoaded = true; loadCertificateAuthorities(); } /* * check to see if a protocol is specified for the tunnel * If not default to socket:// */ httpsTunnel = Configuration.getProperty("com.sun.midp.io.http.proxy"); if ((httpsTunnel != null) && (httpsTunnel.indexOf("://") == -1)) { httpsTunnel = "socket://"+ httpsTunnel; } // Open socket connection if (httpsTunnel != null) { // Make the connection to the ssl tunnel tcpConnection = (StreamConnection)InternalConnector.openInternal(httpsTunnel, Connector.READ_WRITE, false); 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 = (StreamConnection)InternalConnector.openInternal("socket://" + hostAndPort, Connector.READ_WRITE, false); tcpOutputStream = tcpConnection.openOutputStream(); tcpInputStream = tcpConnection.openInputStream(); } tcpConnection.close(); // Get the SSLStreamConnection try { return new SSLStreamConnection(url.host, url.port, tcpInputStream, tcpOutputStream, this); } catch (IOException ioe) { // SSLStreamConnection will close the TCP streams if (handshakeError == 0) { throw ioe; } throw new IOException("(" + handshakeError + ") " + ioe.getMessage() + " " + badCert); } } /** * disconnect the current connection. * * @param connection connection return from {@link #connect()} * @param inputStream input stream opened from <code>connection</code> * @param outputStream output stream opened from <code>connection</code> * @exception IOException if an I/O error occurs while * the connection is terminated. */ protected void disconnect(StreamConnection connection, InputStream inputStream, OutputStream outputStream) throws IOException { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } if (connection != null) { connection.close(); } } /** * This method is called periodically by the SSL client code * as the handshake progresses. This method is a placeholder * it does nothing. * * @param status indicates the current state of the handshake * protocol */ public void SSLHandshakeUpdate(String status) { } /** * This method is called by the SSL client code when it * encounters an error while parsing/verifying the server's * certificate chain. This method saves the error code and * returns false. * * @param c the problematic certificate * @param error a byte-code indicating the problem (these error * codes are defined in the X509Certificate class) * @return false so the SSL handshake will be aborted */ public boolean SSLCertificateOk(X509Certificate c, byte error) { handshakeError = error; badCert = c; // just say no to bad certificates return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -