Xpoint
   [напомнить пароль]

Как отключить SSL в созданном SSLSocket

Метки: [без меток]
2007-07-04 19:19:36 [обр] Vicul[досье]

Проблема следующая, на сервере создается серверный сокет для обмена с клиентами. Вначале обмен с клиентами должен идти без шифрования, но после сервер может потребовать перейти на шифрование по TLS на созданном соединении. Создание сокета на сервере я начинаю так,

 String[] cipherSuite = {
                "TLS_RSA_WITH_AES_128_CBC_SHA",
                "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
                "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
                "TLS_DH_anon_WITH_AES_128_CBC_SHA"
               };

SSLServerSocketFactory sslSrvFact =
            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket m_listenSocket = (SSLServerSocket)sslSrvFact.createServerSocket(m_serverPort, m_backlog);
 m_listenSocket.setEnabledCipherSuites(cipherSuite);

Серверный сокет создан и запускаю его на прослушку:

SSLSocket clientSocket =(SSLSocket) m_startServ.m_listenSocket.accept();

Далее созданный клиентский сокет я передаю на обработку другой нити программы. Так вот, этот сокет уже идет как SSL и после приема данных от клиента выдает ошибку, что данные не закодированы. Я понимаю, что создания этого сокета идет по дефаулту с максимальной защитой. Но мне бы хотелось в этом клиентском сокете отключить SSL на время, ну как это сделать не знаю.

В принципе есть вариант использовать обычные сокеты ServerSocket и Socket. Но тогда я получаю обратную проблему, как созданный Socket потом преобазовать в SSLSocket со всеми нужными свойствами?

Заранее благодаю за любые идеи.

ЗЫ. Все это должно работать на Java 1.4.2.

спустя 1 день [обр] Vicul[досье]
Проблема решена.
спустя 19 часов [обр] GRAy(14/259)[досье]
Vicul[досье] А если не сложно - расскажите как? ;) Просто я размышлял над вашим вопросом и мне кажется что использование SSL сокета с нешифрованными данными невозможно по самой его природе, т.к. он суть абстракция совершенно другого сетевого протокола - отличного от стандартного TCP.
спустя 9 дней [обр] Vicul[досье]

Нужно изменить подход, к этой теме.

Вначале создаем обычный серверный сокет:

ServerSocket listenSocket = new ServerSocket(serverPort, backlog);
Socket clientSocket = listenSocket.accept();

и ждем клиента. После получения клинтского запроса, получем клиентский сокет clientSocket и уходим на его обработку, работаем, как с обычным клиентом. Теперь, клиент хочет шифроваться, в программе-обработчике создаем шифрованный сокет и начинаем создавать его фабрику:

        KeyStore ks;
        String KSType = "JKS";
        String KSProvider = "SUN";
        String KSFileName = "KSFileName";
        String KMFAlgorithm = "SunX509";
        String KMFProvider = "SunJSSE";
        String TMFAlgorithm = "SunX509";
        String TMFProvider = "SunJSSE";
        String SSLCProtocol = "TLSv1";
        String SSLCProvider = "SunJSSE";
        String ksPassword = "ksPassword";
        String keyPassword = "keyPassword";

//parameters for keystores
                ks=KeyStore.getInstance(KSType, KSProvider);
                ks.load(new BufferedInputStream(new FileInputStream(KSFileName)),
                        ksPassword.toCharArray());
                //key and trust managers
                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KMFAlgorithm, KMFProvider);
                kmf.init(ks, keyPassword.toCharArray());
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TMFAlgorithm, TMFProvider);
                tmf.init(ks);
                //create random data
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
                //create SSL context
                SSLContext sslc = SSLContext.getInstance(SSLCProtocol, SSLCProvider);
                sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), secureRandom);

                SSLSocketFactory factory = sslc.getSocketFactory();

Теперь через фабрику создаем сам секретный сокет на основе старого обыкновенного сокета:

                SSLSocket clientSocketTLS =
                        (SSLSocket)factory.createSocket(clientSocket, HostName,
                                PortName, true);

Здесь необходимо отметить, что созданный сокет является логическим продолжением старого сокета. Это я к тому, что если вы надумаете свернуть старый сокет или заблокировать один из его потоков, то автоматом свернется и новый сокет!
Переводим сокет в серверный режим

clientSocketTLS.setUseClientMode(false);

Это значит, что клиент уже в курсе, что надо начинать handshake (обмен ключами и сертификатами). Этот процесс делается автоматом, то есть если в буфер сокета поступят даннай, начинается этот
самый handshake. Но можно его активизировать самим,

clientSocketTLS.startHandshake();

В этом случае этод метод начинает работать как accept(), то есть висим, пока не поступят данные.
Далее работаем с clientSocketTLS, как с обычным сокетом.

Здесь необходимо отменить, что процесс перехода на шифровальный канал должен быть строго регламентирован с клиентом, т.е. клиент и сервер должны знать, когда надо начинать Handshake. Например, если клиент захотел зашифроваться и послал запрос к серверу по незашифрованному каналу. Теперь серверу нужно время перестроить сокет, а клиент уже шлет первый пакет Handshake (clientHello), и тут начинаются траблы с синхронизацией сокетных потоков. В Виндах я это решил с установкой разных приоритетов на процессы-обработчики. В других ОС, н-р НетВарь, это уже не катит. Пока, что эту проблему я не решил.

Powered by POEM™ Engine Copyright © 2002-2005