001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.vfs;
030:
031: import com.caucho.log.Log;
032: import com.caucho.util.IntMap;
033:
034: import javax.net.ssl.SSLPeerUnverifiedException;
035: import javax.net.ssl.SSLSession;
036: import javax.net.ssl.SSLSocket;
037: import java.io.IOException;
038: import java.io.InputStream;
039: import java.io.OutputStream;
040: import java.net.InetAddress;
041: import java.net.Socket;
042: import java.nio.channels.SelectableChannel;
043: import java.security.cert.CertificateException;
044: import java.security.cert.X509Certificate;
045: import java.util.logging.Level;
046: import java.util.logging.Logger;
047:
048: /**
049: * Abstract socket to handle both normal sockets and bin/resin sockets.
050: */
051: public class QSocketWrapper extends QSocket {
052: private static final Logger log = Log.open(QSocketWrapper.class);
053: private static Class sslSocketClass;
054: private static IntMap sslKeySizes;
055:
056: private Socket _s;
057: private InputStream _is;
058: private OutputStream _os;
059: private SocketStream _streamImpl;
060:
061: public QSocketWrapper() {
062: }
063:
064: public QSocketWrapper(Socket s) {
065: init(s);
066: }
067:
068: public void init(Socket s) {
069: _s = s;
070: _is = null;
071: _os = null;
072: }
073:
074: public Socket getSocket() {
075: return _s;
076: }
077:
078: /**
079: * Sets the socket timeout.
080: */
081: public void setReadTimeout(int ms) throws IOException {
082: _s.setSoTimeout(ms);
083: }
084:
085: /**
086: * Returns the server inet address that accepted the request.
087: */
088: public InetAddress getLocalAddress() {
089: return _s.getLocalAddress();
090: }
091:
092: /**
093: * Returns the server port that accepted the request.
094: */
095: public int getLocalPort() {
096: return _s.getLocalPort();
097: }
098:
099: /**
100: * Returns the remote client's inet address.
101: */
102: public InetAddress getRemoteAddress() {
103: if (_s != null)
104: return _s.getInetAddress();
105: else
106: return null;
107: }
108:
109: /**
110: * Returns the remote client's port.
111: */
112: public int getRemotePort() {
113: if (_s != null)
114: return _s.getPort();
115: else
116: return 0;
117: }
118:
119: /**
120: * Returns true if the connection is secure.
121: */
122: public boolean isSecure() {
123: if (_s == null || sslSocketClass == null)
124: return false;
125: else
126: return sslSocketClass.isAssignableFrom(_s.getClass());
127: }
128:
129: /**
130: * Returns the secure cipher algorithm.
131: */
132: public String getCipherSuite() {
133: if (!(_s instanceof SSLSocket))
134: return super .getCipherSuite();
135:
136: SSLSocket sslSocket = (SSLSocket) _s;
137:
138: SSLSession sslSession = sslSocket.getSession();
139:
140: if (sslSession != null)
141: return sslSession.getCipherSuite();
142: else
143: return null;
144: }
145:
146: /**
147: * Returns the bits in the socket.
148: */
149: public int getCipherBits() {
150: if (!(_s instanceof SSLSocket))
151: return super .getCipherBits();
152:
153: SSLSocket sslSocket = (SSLSocket) _s;
154:
155: SSLSession sslSession = sslSocket.getSession();
156:
157: if (sslSession != null)
158: return sslKeySizes.get(sslSession.getCipherSuite());
159: else
160: return 0;
161: }
162:
163: /**
164: * Returns the client certificate.
165: */
166: public X509Certificate getClientCertificate()
167: throws CertificateException {
168: X509Certificate[] certs = getClientCertificates();
169:
170: if (certs == null || certs.length == 0)
171: return null;
172: else
173: return certs[0];
174: }
175:
176: /**
177: * Returns the client certificate.
178: */
179: public X509Certificate[] getClientCertificates()
180: throws CertificateException {
181: if (sslSocketClass == null)
182: return null;
183: else
184: return getClientCertificatesImpl();
185: }
186:
187: /**
188: * Returns the client certificate.
189: */
190: private X509Certificate[] getClientCertificatesImpl()
191: throws CertificateException {
192: if (!(_s instanceof SSLSocket))
193: return null;
194:
195: SSLSocket sslSocket = (SSLSocket) _s;
196:
197: SSLSession sslSession = sslSocket.getSession();
198: if (sslSession == null)
199: return null;
200:
201: String cipherSuite = sslSession.getCipherSuite();
202:
203: try {
204: return (X509Certificate[]) sslSession.getPeerCertificates();
205: } catch (SSLPeerUnverifiedException e) {
206: if (log.isLoggable(Level.FINEST))
207: log.log(Level.FINEST, e.toString(), e);
208:
209: return null;
210: } catch (Throwable e) {
211: log.log(Level.FINER, e.toString(), e);
212: }
213:
214: return null;
215: }
216:
217: /**
218: * Returns the selectable channel.
219: */
220: public SelectableChannel getSelectableChannel() {
221: if (_s != null)
222: return _s.getChannel();
223: else
224: return null;
225: }
226:
227: /**
228: * Returns the socket's input stream.
229: */
230: public StreamImpl getStream() throws IOException {
231: if (_streamImpl == null)
232: _streamImpl = new SocketStream();
233:
234: _streamImpl.init(getInputStream(), getOutputStream());
235:
236: return _streamImpl;
237: }
238:
239: /**
240: * Returns the socket's input stream.
241: */
242: private InputStream getInputStream() throws IOException {
243: if (_is == null)
244: _is = _s.getInputStream();
245:
246: return _is;
247: }
248:
249: /**
250: * Returns the socket's output stream.
251: */
252: private OutputStream getOutputStream() throws IOException {
253: if (_os == null)
254: _os = _s.getOutputStream();
255:
256: return _os;
257: }
258:
259: public void resetTotalBytes() {
260: if (_streamImpl != null)
261: _streamImpl.resetTotalBytes();
262: }
263:
264: public long getTotalReadBytes() {
265: return (_streamImpl == null) ? 0 : _streamImpl
266: .getTotalReadBytes();
267: }
268:
269: public long getTotalWriteBytes() {
270: return (_streamImpl == null) ? 0 : _streamImpl
271: .getTotalWriteBytes();
272: }
273:
274: /**
275: * Returns true for closes.
276: */
277: public boolean isClosed() {
278: return _s == null;
279: }
280:
281: /**
282: * Closes the underlying socket.
283: */
284: public void close() throws IOException {
285: Socket s = _s;
286: _s = null;
287:
288: InputStream is = _is;
289: _is = null;
290:
291: OutputStream os = _os;
292: _os = null;
293:
294: if (os != null) {
295: try {
296: os.close();
297: } catch (Exception e) {
298: }
299: }
300:
301: if (is != null) {
302: try {
303: is.close();
304: } catch (Exception e) {
305: }
306: }
307:
308: if (s != null) {
309: try {
310: s.close();
311: } catch (Exception e) {
312: }
313: }
314: }
315:
316: public String toString() {
317: return "QSocketWrapper[" + _s + "]";
318: }
319:
320: static {
321: try {
322: sslSocketClass = Class.forName("javax.net.ssl.SSLSocket");
323: } catch (Throwable e) {
324: }
325:
326: sslKeySizes = new IntMap();
327: sslKeySizes.put("SSL_DH_anon_WITH_DES_CBC_SHA", 56);
328: sslKeySizes.put("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", 168);
329: sslKeySizes.put("SSL_DH_anon_WITH_RC4_128_MD5", 128);
330: sslKeySizes.put("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 40);
331: sslKeySizes.put("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", 40);
332: sslKeySizes.put("SSL_DHE_DSS_WITH_DES_CBC_SHA", 56);
333: sslKeySizes.put("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 40);
334: sslKeySizes.put("SSL_RSA_WITH_RC4_128_MD5", 128);
335: sslKeySizes.put("SSL_RSA_WITH_RC4_128_SHA", 128);
336: sslKeySizes.put("SSL_RSA_WITH_DES_CBC_SHA", 56);
337: sslKeySizes.put("SSL_RSA_WITH_3DES_EDE_CBC_SHA", 168);
338: sslKeySizes.put("SSL_RSA_EXPORT_WITH_RC4_40_MD5", 40);
339: sslKeySizes.put("SSL_RSA_WITH_NULL_MD5", 0);
340: sslKeySizes.put("SSL_RSA_WITH_NULL_SHA", 0);
341: sslKeySizes.put("SSL_DSA_WITH_RC4_128_MD5", 128);
342: sslKeySizes.put("SSL_DSA_WITH_RC4_128_SHA", 128);
343: sslKeySizes.put("SSL_DSA_WITH_DES_CBC_SHA", 56);
344: sslKeySizes.put("SSL_DSA_WITH_3DES_EDE_CBC_SHA", 168);
345: sslKeySizes.put("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 168);
346: sslKeySizes.put("SSL_DSA_EXPORT_WITH_RC4_40_MD5", 40);
347: sslKeySizes.put("SSL_DSA_WITH_NULL_MD5", 0);
348: sslKeySizes.put("SSL_DSA_WITH_NULL_SHA", 0);
349: }
350: }
|