001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012:
013: package org.tmatesoft.svn.core.internal.util;
014:
015: import java.io.IOException;
016: import java.io.InterruptedIOException;
017: import java.net.InetAddress;
018: import java.net.InetSocketAddress;
019: import java.net.Socket;
020: import java.net.SocketTimeoutException;
021: import java.net.UnknownHostException;
022: import java.security.KeyManagementException;
023: import java.security.NoSuchAlgorithmException;
024: import java.security.cert.CertificateException;
025: import java.security.cert.X509Certificate;
026: import java.util.StringTokenizer;
027:
028: import javax.net.ssl.KeyManager;
029: import javax.net.ssl.SSLContext;
030: import javax.net.ssl.SSLSocket;
031: import javax.net.ssl.TrustManager;
032: import javax.net.ssl.X509TrustManager;
033:
034: import org.tmatesoft.svn.core.SVNErrorMessage;
035: import org.tmatesoft.svn.core.SVNException;
036: import org.tmatesoft.svn.core.auth.ISVNSSLManager;
037: import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
038:
039: /**
040: * <code>SVNSocketFactory</code> is a utility class that represents a custom
041: * socket factory which provides creating either a plain socket or a secure one
042: * to encrypt data transmitted over network.
043: *
044: * <p>
045: * The created socket then used by the inner engine of <b><i>SVNKit</i></b>
046: * library to communicate with a Subversion repository.
047: *
048: * @version 1.1.1
049: * @author TMate Software Ltd.
050: */
051: public class SVNSocketFactory {
052:
053: private static final int ourConnectTimeout;
054:
055: static {
056: String timeoutStr = System.getProperty(
057: "svnkit.tcp.connectTimeout", "0");
058: int timeout = 0;
059: try {
060: timeout = Integer.parseInt(timeoutStr);
061: if (timeout < 0) {
062: timeout = 0;
063: }
064: } catch (NumberFormatException nfe) {
065: timeout = 0;
066: }
067: ourConnectTimeout = timeout;
068: }
069:
070: public static Socket createPlainSocket(String host, int port)
071: throws IOException {
072: InetAddress address = createAddres(host);
073: Socket socket = new Socket();
074: socket.connect(new InetSocketAddress(address, port),
075: ourConnectTimeout);
076: socket.setReuseAddress(true);
077: socket.setTcpNoDelay(true);
078: socket.setKeepAlive(true);
079: socket.setSoLinger(true, 0);
080: return socket;
081: }
082:
083: public static Socket createSSLSocket(ISVNSSLManager manager,
084: String host, int port) throws IOException, SVNException {
085: InetSocketAddress address = new InetSocketAddress(
086: createAddres(host), port);
087:
088: manager = manager == null ? DEFAULT_SSL_MANAGER : manager;
089: Socket sslSocket = manager.getSSLContext().getSocketFactory()
090: .createSocket();
091: sslSocket.connect(address, ourConnectTimeout);
092: sslSocket.setReuseAddress(true);
093: sslSocket.setTcpNoDelay(true);
094: sslSocket.setKeepAlive(true);
095: sslSocket.setSoLinger(true, 0);
096: ((SSLSocket) sslSocket)
097: .setEnabledProtocols(new String[] { "SSLv3" });
098: return sslSocket;
099: }
100:
101: public static Socket createSSLSocket(ISVNSSLManager manager,
102: String host, int port, Socket socket) throws IOException,
103: SVNException {
104: manager = manager == null ? DEFAULT_SSL_MANAGER : manager;
105: Socket sslSocket = manager.getSSLContext().getSocketFactory()
106: .createSocket(socket, host, port, true);
107: sslSocket.setReuseAddress(true);
108: sslSocket.setTcpNoDelay(true);
109: sslSocket.setKeepAlive(true);
110: sslSocket.setSoLinger(true, 0);
111: ((SSLSocket) sslSocket)
112: .setEnabledProtocols(new String[] { "SSLv3" });
113: return sslSocket;
114: }
115:
116: private static InetAddress createAddres(String hostName)
117: throws UnknownHostException {
118: byte[] bytes = new byte[4];
119: int index = 0;
120: for (StringTokenizer tokens = new StringTokenizer(hostName, "."); tokens
121: .hasMoreTokens();) {
122: String token = tokens.nextToken();
123: try {
124: byte b = (byte) Integer.parseInt(token);
125: if (index < bytes.length) {
126: bytes[index] = b;
127: index++;
128: } else {
129: bytes = null;
130: break;
131: }
132: } catch (NumberFormatException e) {
133: bytes = null;
134: break;
135: }
136: }
137: if (bytes != null && index == 4) {
138: return InetAddress.getByAddress(hostName, bytes);
139: }
140: return InetAddress.getByName(hostName);
141: }
142:
143: private static final ISVNSSLManager DEFAULT_SSL_MANAGER = new ISVNSSLManager() {
144: public SSLContext getSSLContext() throws IOException {
145: SSLContext context = null;
146: try {
147: context = SSLContext.getInstance("SSL");
148: context.init(new KeyManager[] {},
149: new TrustManager[] { new X509TrustManager() {
150: public X509Certificate[] getAcceptedIssuers() {
151: return null;
152: }
153:
154: public void checkClientTrusted(
155: X509Certificate[] arg0, String arg1)
156: throws CertificateException {
157: }
158:
159: public void checkServerTrusted(
160: X509Certificate[] arg0, String arg1)
161: throws CertificateException {
162: }
163:
164: } }, null);
165: } catch (NoSuchAlgorithmException e) {
166: throw new IOException(e.getMessage());
167: } catch (KeyManagementException e) {
168: throw new IOException(e.getMessage());
169: }
170: return context;
171: }
172:
173: public void acknowledgeSSLContext(boolean accepted,
174: SVNErrorMessage errorMessage) {
175: }
176:
177: public boolean isClientCertPromptRequired() {
178: return false;
179: }
180:
181: public void setClientAuthentication(
182: SVNSSLAuthentication sslAuthentication) {
183: }
184:
185: public SVNSSLAuthentication getClientAuthentication() {
186: return null;
187: }
188:
189: public Throwable getClientCertLoadingError() {
190: return null;
191: }
192: };
193:
194: public static boolean isSocketStale(Socket socket)
195: throws IOException {
196: boolean isStale = true;
197: if (socket != null) {
198: isStale = false;
199: try {
200: if (socket.getInputStream().available() == 0) {
201: int timeout = socket.getSoTimeout();
202: try {
203: socket.setSoTimeout(1);
204: socket.getInputStream().mark(1);
205: int byteRead = socket.getInputStream().read();
206: if (byteRead == -1) {
207: isStale = true;
208: } else {
209: socket.getInputStream().reset();
210: }
211: } finally {
212: socket.setSoTimeout(timeout);
213: }
214: }
215: } catch (InterruptedIOException e) {
216: if (!SocketTimeoutException.class.isInstance(e)) {
217: throw e;
218: }
219: } catch (IOException e) {
220: isStale = true;
221: }
222: }
223: return isStale;
224: }
225: }
|