1/*
2* Conditions Of Use
3*
4* This software was developed by employees of the National Institute of
5* Standards and Technology (NIST), an agency of the Federal Government.
6* Pursuant to title 15 Untied States Code Section 105, works of NIST
7* employees are not subject to copyright protection in the United States
8* and are considered to be in the public domain.  As a result, a formal
9* license is not needed to use the software.
10*
11* This software is provided by NIST as a service and is expressly
12* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15* AND DATA ACCURACY.  NIST does not warrant or make any representations
16* regarding the use of the software or the results thereof, including but
17* not limited to the correctness, accuracy, reliability or usefulness of
18* the software.
19*
20* Permission to use this software is contingent upon your acceptance
21* of the terms of this agreement
22*
23* .
24*
25*/
26package gov.nist.core.net;
27
28import java.io.FileInputStream;
29import java.io.FileNotFoundException;
30import java.io.IOException;
31import java.net.DatagramSocket;
32import java.net.InetAddress;
33import java.net.InetSocketAddress;
34import java.net.ServerSocket;
35import java.net.Socket;
36import java.net.SocketException;
37import java.security.GeneralSecurityException;
38import java.security.KeyStore;
39import java.security.SecureRandom;
40
41import javax.net.ssl.KeyManagerFactory;
42import javax.net.ssl.SSLContext;
43import javax.net.ssl.SSLServerSocket;
44import javax.net.ssl.SSLServerSocketFactory;
45import javax.net.ssl.SSLSocket;
46import javax.net.ssl.SSLSocketFactory;
47import javax.net.ssl.TrustManagerFactory;
48
49/**
50 * extended implementation of a network layer that allows to define a private java
51 * keystores/truststores
52 *
53 * @author f.reif
54 * @version 1.2
55 * @since 1.2
56 *
57 */
58public class SslNetworkLayer implements NetworkLayer {
59
60    private SSLSocketFactory sslSocketFactory;
61
62    private SSLServerSocketFactory sslServerSocketFactory;
63
64    public SslNetworkLayer(
65            String trustStoreFile,
66            String keyStoreFile,
67            char[] keyStorePassword,
68            String keyStoreType) throws GeneralSecurityException, FileNotFoundException, IOException
69    {
70        SSLContext sslContext;
71        sslContext = SSLContext.getInstance("TLS");
72        String algorithm = KeyManagerFactory.getDefaultAlgorithm();
73        TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(algorithm);
74        KeyManagerFactory kmFactory = KeyManagerFactory.getInstance(algorithm);
75        SecureRandom secureRandom   = new SecureRandom();
76        secureRandom.nextInt();
77        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
78        KeyStore trustStore = KeyStore.getInstance(keyStoreType);
79        keyStore.load(new FileInputStream(keyStoreFile), keyStorePassword);
80        trustStore.load(new FileInputStream(trustStoreFile), keyStorePassword);
81        tmFactory.init(trustStore);
82        kmFactory.init(keyStore, keyStorePassword);
83        sslContext.init(kmFactory.getKeyManagers(), tmFactory.getTrustManagers(), secureRandom);
84        sslServerSocketFactory = sslContext.getServerSocketFactory();
85        sslSocketFactory = sslContext.getSocketFactory();
86    }
87
88    public ServerSocket createServerSocket(int port, int backlog,
89            InetAddress bindAddress) throws IOException {
90        return new ServerSocket(port, backlog, bindAddress);
91    }
92
93    public Socket createSocket(InetAddress address, int port)
94            throws IOException {
95        return new Socket(address, port);
96    }
97
98    public DatagramSocket createDatagramSocket() throws SocketException {
99        return new DatagramSocket();
100    }
101
102    public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
103            throws SocketException {
104        return new DatagramSocket(port, laddr);
105    }
106
107    /* Added by Daniel J. Martinez Manzano <dani@dif.um.es> */
108    public SSLServerSocket createSSLServerSocket(int port, int backlog,
109            InetAddress bindAddress) throws IOException {
110        return (SSLServerSocket) sslServerSocketFactory.createServerSocket(
111                port, backlog, bindAddress);
112    }
113
114    /* Added by Daniel J. Martinez Manzano <dani@dif.um.es> */
115    public SSLSocket createSSLSocket(InetAddress address, int port)
116            throws IOException {
117        return (SSLSocket) sslSocketFactory.createSocket(address, port);
118    }
119
120    /* Added by Daniel J. Martinez Manzano <dani@dif.um.es> */
121    public SSLSocket createSSLSocket(InetAddress address, int port,
122            InetAddress myAddress) throws IOException {
123        return (SSLSocket) sslSocketFactory.createSocket(address, port,
124                myAddress, 0);
125    }
126
127    public Socket createSocket(InetAddress address, int port,
128            InetAddress myAddress) throws IOException {
129        if (myAddress != null)
130            return new Socket(address, port, myAddress, 0);
131        else
132            return new Socket(address, port);
133    }
134
135    /**
136     * Creates a new Socket, binds it to myAddress:myPort and connects it to
137     * address:port.
138     *
139     * @param address the InetAddress that we'd like to connect to.
140     * @param port the port that we'd like to connect to
141     * @param myAddress the address that we are supposed to bind on or null
142     *        for the "any" address.
143     * @param myPort the port that we are supposed to bind on or 0 for a random
144     * one.
145     *
146     * @return a new Socket, bound on myAddress:myPort and connected to
147     * address:port.
148     * @throws IOException if binding or connecting the socket fail for a reason
149     * (exception relayed from the correspoonding Socket methods)
150     */
151    public Socket createSocket(InetAddress address, int port,
152                    InetAddress myAddress, int myPort)
153        throws IOException
154    {
155        if (myAddress != null)
156            return new Socket(address, port, myAddress, myPort);
157        else if (port != 0)
158        {
159            //myAddress is null (i.e. any)  but we have a port number
160            Socket sock = new Socket();
161            sock.bind(new InetSocketAddress(port));
162            sock.connect(new InetSocketAddress(address, port));
163            return sock;
164        }
165        else
166            return new Socket(address, port);
167    }
168}
169