001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.jndi.provider.ldap.ext;
019:
020: import java.io.IOException;
021: import java.net.Socket;
022:
023: import javax.naming.ldap.StartTlsResponse;
024: import javax.net.ssl.HandshakeCompletedEvent;
025: import javax.net.ssl.HandshakeCompletedListener;
026: import javax.net.ssl.HostnameVerifier;
027: import javax.net.ssl.SSLSession;
028: import javax.net.ssl.SSLSocket;
029: import javax.net.ssl.SSLSocketFactory;
030:
031: public class StartTlsResponseImpl extends StartTlsResponse {
032:
033: /**
034: *
035: */
036: private static final long serialVersionUID = -1199041712215453042L;
037:
038: private String[] suites;
039:
040: private HostnameVerifier verifier;
041:
042: private Socket socket; // existing uderlying socket
043:
044: private boolean isHandshaked = false; // is handshake finished
045:
046: private SSLSocket negotiatedSslSocket = null; // negotiated ssl socket
047:
048: @Override
049: public void close() throws IOException {
050: /*
051: * TODO Spec requires close the TLS connection gracefully and reverts
052: * back to the underlying connection. RI close the ssl socket but
053: * dosen't reverts to former socket when invoke this method. We follow
054: * RI here.
055: */
056: if (negotiatedSslSocket != null) {
057: negotiatedSslSocket.close();
058: }
059: }
060:
061: @Override
062: public SSLSession negotiate() throws IOException {
063: return negotiate(null);
064: }
065:
066: @Override
067: public SSLSession negotiate(SSLSocketFactory factory)
068: throws IOException {
069:
070: if (socket == null) {
071: // must set socket before negotiate
072: return null;
073: }
074:
075: if (factory == null) {
076: factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
077: }
078:
079: SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,
080: socket.getInetAddress().getHostName(),
081: socket.getPort(), false);
082:
083: if (suites != null) {
084: sslSocket.setEnabledCipherSuites(suites);
085: }
086:
087: sslSocket
088: .addHandshakeCompletedListener(new HandshakeCompletedListener() {
089: public void handshakeCompleted(
090: HandshakeCompletedEvent event) {
091: isHandshaked = true;
092: }
093: });
094:
095: sslSocket.startHandshake();
096:
097: while (!isHandshaked) {
098: // Wait for handshake finish.
099: }
100:
101: HostnameVerifier defaultVerifier = new HostnameVerifier() {
102:
103: public boolean verify(String hostname, SSLSession session) {
104: // TODO: add verify logic here
105: return false;
106: }
107:
108: };
109:
110: /*
111: * TODO: the spec requires to verify server's hostname by default
112: * hostname verifier first, if failed, use the callback verifier. RI use
113: * callback verifier first then the dafault one. We follow the spec
114: * here.
115: */
116: if (defaultVerifier.verify(sslSocket.getInetAddress()
117: .getHostName(), sslSocket.getSession())) {
118: this .negotiatedSslSocket = sslSocket;
119: return sslSocket.getSession();
120: } else if (verifier != null
121: && verifier.verify(sslSocket.getInetAddress()
122: .getHostName(), sslSocket.getSession())) {
123: this .negotiatedSslSocket = sslSocket;
124: return sslSocket.getSession();
125: }
126:
127: // negotiation fails
128: /*
129: * TODO: What to do if hostname verification failed? RI throws exception
130: * of hostname verification.
131: */
132: return null;
133: }
134:
135: @Override
136: public void setEnabledCipherSuites(String[] suites) {
137: this .suites = suites;
138: }
139:
140: @Override
141: public void setHostnameVerifier(HostnameVerifier verifier) {
142: this .verifier = verifier;
143: }
144:
145: public void setSocket(Socket socket) {
146: this .socket = socket;
147: }
148:
149: public SSLSocket getSSLSocket() {
150: return this.negotiatedSslSocket;
151: }
152: }
|