--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/gcfprotocols/secureconnection/javasrc/com/nokia/mj/impl/ssl/SecureConnectionImpl.java Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,588 @@
+/*
+* Copyright (c) 2003-2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+package com.nokia.mj.impl.ssl;
+
+import java.io.IOException;
+import javax.microedition.pki.CertificateException;
+import javax.microedition.io.*;
+import com.nokia.mj.impl.gcf.utils.UrlParser;
+import com.nokia.mj.impl.gcf.utils.StreamConnectionBase;
+import java.io.*;
+// import com.nokia.mj.impl.socket.*;
+import com.nokia.mj.impl.gcf.utils.DateUtil;
+import com.nokia.mj.impl.utils.Logger;
+import com.nokia.mj.impl.rt.support.Finalizer;
+import com.nokia.mj.impl.rt.support.ApplicationUtils;
+
+import com.nokia.mj.impl.rt.ui.RuntimeUiFactory;
+import com.nokia.mj.impl.rt.ui.RuntimeUi;
+import com.nokia.mj.impl.rt.ui.ConfirmData;
+import com.nokia.mj.impl.connectionmanager.ConnectionManager;
+import com.nokia.mj.impl.connectionmanager.AccessPoint;
+import com.nokia.mj.impl.utils.ResourceLoader;
+
+/**
+ * Secure Connection Implementation class.
+ */
+
+public class SecureConnectionImpl extends StreamConnectionBase implements
+ SecureConnection
+{
+ private UrlParser iUri; // the uri of the secure connection
+
+ private int iSocketDesc; // the tcp socket to be secured
+
+ private Finalizer iFinalizer;
+
+ private boolean iConnectionOpen = false;
+
+ private static final int X509_V_OK = 0;
+
+ private boolean iOutputStreamOpenedOnce = false;
+
+ private boolean iInputStreamOpenedOnce = false;
+
+ private boolean iDataOutputStreamOpenedOnce = false;
+
+ private boolean iDataInputStreamOpenedOnce = false;
+
+ private boolean iInput = false;
+
+ private int iChoice = -1;
+
+ private ConnectionManager iCmInstance = null;
+
+ private AccessPoint iApn = null;
+
+ private static final String SSL_RES_NAME = "javassl";
+
+ private static final String LOCALISED_STRING_ID = "qtn_ssl_prompt_";
+
+ private static final String UNTRUSTED_CERTIFICATE_WARNING = "untrusted_certificate";
+
+ /**
+ * Constructs the SecureConnectionImpl.
+ *
+ * @param aUri
+ * the uri to which secure connection is opened
+ * @param aMode
+ * the with which secure connection is opened
+ * @param aSock
+ * the tcp socket, which has to be made secure
+ * @throws IOException
+ * in case of any IO errors
+ */
+ public void showUI()
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo, "display ui called ");
+ RuntimeUi rui = RuntimeUiFactory.getRuntimeUi();
+ String[] ans = { "Yes", "No" };
+ String localisedWarning = ResourceLoader.getInstance(SSL_RES_NAME,
+ LOCALISED_STRING_ID).format(UNTRUSTED_CERTIFICATE_WARNING,
+ (Object[]) null);
+ ConfirmData conf = new ConfirmData(localisedWarning, ans, 0);
+ iInput = rui.confirm("SecureConnection", conf);
+ iChoice = conf.getAnswer();
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "confirmdata returned value : " + iInput + "selected button :"
+ + iChoice);
+ }
+
+ public SecureConnectionImpl(UrlParser aUri, int aMode, int aSock,
+ ConnectionManager cm, AccessPoint apnInfo) throws IOException
+ {
+
+ super(aUri.toString(), aMode, false);
+ int ret;
+ int[] retval = new int[2];
+ iCmInstance = cm;
+ iApn = apnInfo;
+
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::SecureConnectionImpl()");
+ iSocketDesc = aSock;
+ if (iApn != null)
+ {
+ ret = _doHandshake(iNativePeerHandle, iSocketDesc, iApn.getType(),
+ iApn.getNapId(), retval);
+ }
+ else
+ {
+ ret = _doHandshake(iNativePeerHandle, iSocketDesc, -1, -1, retval);
+ }
+
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "setting access point return value =" + retval[0]);
+ if (iCmInstance != null)
+ {
+ if (retval[0] < 0)
+ {
+ // reset connection manager
+ iCmInstance.reset();
+ }
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo, "ssl connect return value ="
+ + ret);
+ if (ret < 0)
+ {
+ throw new IOException(
+ "Unable to open a secure connection. Posix error code: " + ret);
+ }
+ if (retval[1] < 0)
+ {
+ // validation of certificate failed
+ iConnectionOpen = true;
+ SecurityInfo tmpSecurityInfo = getSecurityInfo();
+ throw new CertificateException(
+ "Invalid server certificate. Symbian OS error code: "
+ + retval[1],
+ tmpSecurityInfo.getServerCertificate(),
+ CertificateException.VERIFICATION_FAILED);
+ }
+ if (ret != X509_V_OK)
+ {
+ iConnectionOpen = true;
+ if (ret == 18) // open c error code for self signed certificate
+ {
+ showUI();
+ if (iInput == true)
+ {
+ if (iChoice == 0) // "Yes" option selected
+ {
+ Logger
+ .LOG(Logger.ESOCKET, Logger.EInfo,
+ "SecureConnectionImpl()- untrusted certificate accepted");
+ // Continue
+ }
+ else
+ {
+ // "No" option selected
+ SecurityInfo tmpSecurityInfo = getSecurityInfo();
+ if (tmpSecurityInfo.getServerCertificate() == null)
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "tmpSecurityInfo.getServerCertificate() is null");
+ else
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "tmpSecurityInfo.getServerCertificate() is not null");
+ throw new CertificateException(
+ "Untrusted server certificate", tmpSecurityInfo
+ .getServerCertificate(),
+ CertificateException.VERIFICATION_FAILED); // untrusted
+ // certificate
+ }
+ }
+ else
+ {
+ SecurityInfo tmpSecurityInfo = getSecurityInfo();
+ throw new CertificateException(
+ "Untrusted server certificate", tmpSecurityInfo
+ .getServerCertificate(),
+ CertificateException.VERIFICATION_FAILED); // untrusted
+ // certificate
+ }
+ }
+ else
+ {
+ SecurityInfo tmpSecurityInfo = getSecurityInfo();
+ throw new CertificateException("Untrusted server certificate",
+ tmpSecurityInfo.getServerCertificate(),
+ CertificateException.VERIFICATION_FAILED); // untrusted
+ // certificate
+ }
+ /*
+ * if(ret > 14) { ret = CertificateException.VERIFICATION_FAILED; }
+ */
+ }
+ else
+ {
+ iConnectionOpen = true;
+ }
+ iFinalizer = createFinalizer();
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "--SecureConnectionImpl(), socketdescrip = " + iSocketDesc);
+ }
+
+ /**
+ * Creatives the native side handle for this secure connection.
+ *
+ * @param aUri
+ * the uri to which secure connection is opened
+ * @param aMode
+ * the with which secure connection is opened
+ * @param aTimeOut
+ * the timeout value for this connection
+ * @return the native handle
+ */
+ public int createNativePeer(String aUri, int aMode, boolean aTimeOut)
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::createNativePeer()");
+ iUri = new UrlParser(aUri);
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "SecureConnectionImpl::createNativePeer() aUri = " + aUri
+ + "aMode = " + aMode + "iUri.host = " + iUri.host);
+ int ret = _createNativePeer(aUri, aMode, iUri.host, iUri.port);
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::createNativePeer()");
+ return ret;
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public String getAddress() throws IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::getAddress()");
+ String addr[] = new String[1];
+ if (iConnectionOpen == false)
+ {
+ throw new IOException(
+ "getAddress failed: connection is already closed");
+ }
+ int retValue = _getAddress(iNativePeerHandle, addr);
+ if (retValue < 0)
+ {
+ throw new IOException("getAddress failed. POSIX error code: "
+ + retValue);
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::getAddress()");
+ return addr[0];
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public String getLocalAddress() throws IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::getLocalAddress()");
+ String addr[] = new String[1];
+ if (iConnectionOpen == false)
+ {
+ throw new IOException(
+ "getLocalAddress failed: connection is already closed");
+ }
+ int retValue = _getLocalAddress(iNativePeerHandle, addr);
+ if (retValue < 0)
+ {
+ throw new IOException("getLocalAddress failed. POSIX error code: "
+ + retValue);
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::getLocalAddress()");
+ return addr[0];
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public int getLocalPort() throws IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::getLocalPort()");
+ if (iConnectionOpen == false)
+ {
+ throw new IOException(
+ "getLocalPort failed: connection is already closed");
+ }
+ int localPort = _getLocalPort(iNativePeerHandle);
+ if (localPort < 0)
+ {
+ throw new IOException("getLocalPort failed. POSIX error code: "
+ + localPort);
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::getLocalPort()");
+ return localPort;
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public int getPort() throws IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::getPort()");
+ if (iConnectionOpen == false)
+ {
+ throw new IOException("getPort failed: connection is already closed");
+ }
+ int result = _getport(iNativePeerHandle);
+ if (result < 0)
+ {
+ throw new IOException("getPort failed. POSIX error code: " + result);
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::getPort()");
+ return result;
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public int getSocketOption(byte aOption) throws IllegalArgumentException,
+ IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::getSocketOption()");
+ if (iConnectionOpen == false)
+ {
+ throw new IOException(
+ "getSocketOption failed: connection is already closed");
+ }
+ checkOption(aOption);
+ int retVal = _getSocketOption(iNativePeerHandle, aOption);
+ if (retVal < 0)
+ {
+ throw new IOException("getSocketOption failed. POSIX error code: "
+ + retVal);
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::getSocketOption()");
+
+ return retVal;
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public void setSocketOption(byte aOption, int aValue)
+ throws IllegalArgumentException, IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::setSocketOption()");
+ if (iConnectionOpen == false)
+ {
+ throw new IOException(
+ "setSocketOption failed: connection is already closed");
+ }
+ checkOption(aOption);
+
+ if (aValue < 0)
+ {
+ throw new IllegalArgumentException(
+ "Incorrect value for setSocketOption");
+ }
+ int retval = _setSocketOption(iNativePeerHandle, aOption, aValue);
+
+ if (retval < 0)
+ {
+ throw new IOException("setSocketOption failed. POSIX error code: "
+ + retval);
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::setSocketOption()");
+ }
+
+ private void checkOption(byte option) throws IllegalArgumentException
+ {
+ if ((option != DELAY) && (option != KEEPALIVE) && (option != LINGER)
+ && (option != RCVBUF) && (option != SNDBUF))
+ {
+ throw new IllegalArgumentException("Unsupported socket option");
+ }
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public SecurityInfo getSecurityInfo() throws IOException
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::getSecurityInfo()");
+ if (iConnectionOpen == false)
+ {
+ throw new IOException(
+ "getSecurityInfo failed: connection is already closed");
+ }
+ String[] iStringArray = new String[9];
+ long version = 0;
+ int res = _getSecurityInfo(iNativePeerHandle, iStringArray);
+ SecurityInfo securityInfo = new SecurityInfoImpl(iStringArray);
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::getSecurityInfo()");
+ return securityInfo;
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public OutputStream openOutputStream() throws IOException
+ {
+ if (iOutputStreamOpenedOnce == true)
+ {
+ throw new IOException(
+ "OutputStream cannot be opened multiple times");
+ }
+ else
+ {
+ iOutputStreamOpenedOnce = true;
+ return super.openOutputStream();
+ }
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public DataOutputStream openDataOutputStream() throws IOException
+ {
+ if (iDataOutputStreamOpenedOnce == true)
+ {
+ throw new IOException(
+ "DataOutputStream cannot be opened multiple times");
+ }
+ else
+ {
+ iDataOutputStreamOpenedOnce = true;
+ return super.openDataOutputStream();
+ }
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public InputStream openInputStream() throws IOException
+ {
+ if (iInputStreamOpenedOnce == true)
+ {
+ throw new IOException("InputStream cannot be opened multiple times");
+ }
+ else
+ {
+ iInputStreamOpenedOnce = true;
+ return super.openInputStream();
+ }
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+ public DataInputStream openDataInputStream() throws IOException
+ {
+ if (iDataInputStreamOpenedOnce == true)
+ {
+ throw new IOException(
+ "DataInputStream cannot be opened multiple times");
+ }
+ else
+ {
+ iDataInputStreamOpenedOnce = true;
+ return super.openDataInputStream();
+ }
+ }
+
+ /**
+ * Please refer to Jsr 118
+ */
+
+ public void close() throws IOException
+ {
+ Logger
+ .LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::close() open flag = "
+ + iConnectionOpen);
+ if (iConnectionOpen == true)
+ {
+ iConnectionOpen = false;
+ super.close(); // closes the input and outputstreams.
+
+ // If streams is closed only then the native is closed
+ if (isStreamsClosed() == true)
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "+SecureConnectionImpl::close() calling _close "
+ + iConnectionOpen);
+ int ret = _close(iNativePeerHandle);
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::close() = close returned "
+ + ret);
+ if (ret != 0)
+ {
+ throw new IOException("Posix error code : " + ret);
+ }
+ }
+ }
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "-SecureConnectionImpl::close()");
+ }
+
+ Finalizer createFinalizer()
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "creating a socket finalizer object ");
+ return new Finalizer()
+ {
+ public void finalizeImpl()
+ {
+ doFinalize();
+ }
+ };
+ }
+
+ public void doFinalize()
+ {
+ Logger.LOG(Logger.ESOCKET, Logger.EInfo,
+ "securesocket doFinalize() called :");
+ if (iConnectionOpen == true)
+ {
+ iConnectionOpen = false;
+ if (iNativePeerHandle != 0)
+ {
+ int ret = _close(iNativePeerHandle);
+ }
+ }
+ if (iNativePeerHandle != 0)
+ {
+ _dispose(iNativePeerHandle);
+ iNativePeerHandle = 0;
+ }
+ }
+
+ // Native calls
+
+ private native int _createNativePeer(String aUri, int aMode, String aHost,
+ int aPort);
+
+ private native int _doHandshake(int iNativePeerHandle, int iSocketDesc,
+ int type, int apn, int[] retval);
+
+ //private native int _addCertificate(int iNativePeerHandle);
+
+ private native int _getSecurityInfo(int iNativePeerHandle,
+ String[] aStringArray);
+
+ private native int _getAddress(int iNativePeerHandle, String[] aAddr);
+
+ private native int _getLocalAddress(int iNativePeerHandle, String[] aAddr);
+
+ private native int _getLocalPort(int iNativePeerHandle);
+
+ private native int _getport(int iNativePeerHandle);
+
+ private native int _setSocketOption(int iNativePeerHandle, int aOption,
+ int aValue);
+
+ private native int _getSocketOption(int iNativePeerHandle, int aOption);
+
+ private native int _close(int iNativePeerHandle);
+
+ private native void _dispose(int iNativePeerHandle);
+}