1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package davmail;
20
21 import davmail.exception.DavMailException;
22 import davmail.ui.tray.DavGatewayTray;
23
24 import javax.net.ServerSocketFactory;
25 import javax.net.ssl.*;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.net.InetAddress;
29 import java.net.ServerSocket;
30 import java.net.Socket;
31 import java.security.*;
32 import java.security.cert.CertificateException;
33 import java.util.HashSet;
34
35
36
37
38 public abstract class AbstractServer extends Thread {
39 protected boolean nosslFlag;
40 private final int port;
41 private ServerSocket serverSocket;
42
43
44
45
46
47
48 public abstract String getProtocolName();
49
50
51
52
53
54
55 public int getPort() {
56 return port;
57 }
58
59
60
61
62
63
64
65
66
67 protected AbstractServer(String name, int port, int defaultPort) {
68 super(name);
69 setDaemon(true);
70 if (port == 0) {
71 this.port = defaultPort;
72 } else {
73 this.port = port;
74 }
75 }
76
77
78
79
80
81
82 public void bind() throws DavMailException {
83 String bindAddress = Settings.getProperty("davmail.bindAddress");
84 String keystoreFile = Settings.getProperty("davmail.ssl.keystoreFile");
85
86 ServerSocketFactory serverSocketFactory;
87 if (keystoreFile == null || keystoreFile.isEmpty() || nosslFlag) {
88 serverSocketFactory = ServerSocketFactory.getDefault();
89 } else {
90 try {
91
92
93
94 SSLContext sslContext = SSLContext.getInstance("TLS");
95
96
97 sslContext.init(getKeyManagers(), getTrustManagers(), null);
98
99
100 serverSocketFactory = sslContext.getServerSocketFactory();
101 } catch (IOException | GeneralSecurityException ex) {
102 throw new DavMailException("LOG_EXCEPTION_CREATING_SSL_SERVER_SOCKET", getProtocolName(), port, ex.getMessage() == null ? ex.toString() : ex.getMessage());
103 }
104 }
105 try {
106
107 if (bindAddress == null || bindAddress.isEmpty()) {
108 serverSocket = serverSocketFactory.createServerSocket(port);
109 } else {
110 serverSocket = serverSocketFactory.createServerSocket(port, 0, InetAddress.getByName(bindAddress));
111 }
112 if (serverSocket instanceof SSLServerSocket) {
113
114 HashSet<String> protocols = new HashSet<>();
115 for (String protocol : ((SSLServerSocket) serverSocket).getEnabledProtocols()) {
116 if (!protocol.startsWith("SSL")) {
117 protocols.add(protocol);
118 }
119 }
120 ((SSLServerSocket) serverSocket).setEnabledProtocols(protocols.toArray(new String[0]));
121 ((SSLServerSocket) serverSocket).setNeedClientAuth(Settings.getBooleanProperty("davmail.ssl.needClientAuth", false));
122 }
123
124 } catch (IOException e) {
125 throw new DavMailException("LOG_SOCKET_BIND_FAILED", getProtocolName(), port);
126 }
127 }
128
129
130
131
132
133
134
135
136
137
138 protected TrustManager[] getTrustManagers() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
139 String truststoreFile = Settings.getProperty("davmail.ssl.truststoreFile");
140 if (truststoreFile == null || truststoreFile.isEmpty()) {
141 return null;
142 }
143 try (FileInputStream trustStoreInputStream = new FileInputStream(truststoreFile)) {
144 KeyStore trustStore = KeyStore.getInstance(Settings.getProperty("davmail.ssl.truststoreType"));
145 trustStore.load(trustStoreInputStream, Settings.getCharArrayProperty("davmail.ssl.truststorePass"));
146
147 TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
148 tmf.init(trustStore);
149 return tmf.getTrustManagers();
150 }
151 }
152
153
154
155
156
157
158
159
160
161
162 protected KeyManager[] getKeyManagers() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException, UnrecoverableKeyException {
163 String keystoreFile = Settings.getProperty("davmail.ssl.keystoreFile");
164 if (keystoreFile == null || keystoreFile.isEmpty()) {
165 return null;
166 }
167 try (FileInputStream keyStoreInputStream = new FileInputStream(keystoreFile)) {
168 KeyStore keystore = KeyStore.getInstance(Settings.getProperty("davmail.ssl.keystoreType"));
169 keystore.load(keyStoreInputStream, Settings.getCharArrayProperty("davmail.ssl.keystorePass"));
170
171 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
172 kmf.init(keystore, Settings.getCharArrayProperty("davmail.ssl.keyPass"));
173 return kmf.getKeyManagers();
174 }
175 }
176
177
178
179
180
181
182
183 @Override
184 public void run() {
185 AbstractConnection connection = null;
186 Socket clientSocket = null;
187 try {
188 while (!serverSocket.isClosed()) {
189 clientSocket = serverSocket.accept();
190
191 clientSocket.setSoTimeout(Settings.getIntProperty("davmail.clientSoTimeout", 300) * 1000);
192 DavGatewayTray.debug(new BundleMessage("LOG_CONNECTION_FROM", clientSocket.getInetAddress(), port));
193
194 if (Settings.getBooleanProperty("davmail.allowRemote") ||
195 clientSocket.getInetAddress().isLoopbackAddress() ||
196
197 clientSocket.getInetAddress().equals(InetAddress.getByAddress(new byte[]{(byte) 0xfe, (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
198 )) {
199 connection = createConnectionHandler(clientSocket);
200 connection.start();
201
202 } else {
203 DavGatewayTray.warn(new BundleMessage("LOG_EXTERNAL_CONNECTION_REFUSED"));
204 }
205 }
206
207 } catch (IOException e) {
208
209 if (!serverSocket.isClosed()) {
210 DavGatewayTray.warn(new BundleMessage("LOG_EXCEPTION_LISTENING_FOR_CONNECTIONS"), e);
211 }
212 } finally {
213 try {
214 if (clientSocket != null) {
215 clientSocket.close();
216 }
217 } catch (IOException e) {
218 DavGatewayTray.warn(new BundleMessage("LOG_EXCEPTION_CLOSING_CLIENT_SOCKET"), e);
219 }
220 if (connection != null) {
221 connection.close();
222 }
223 }
224
225 }
226
227
228
229
230
231
232
233 public abstract AbstractConnection createConnectionHandler(Socket clientSocket);
234
235
236
237
238 public void close() {
239 try {
240 if (serverSocket != null) {
241 serverSocket.close();
242 }
243 } catch (IOException e) {
244 DavGatewayTray.warn(new BundleMessage("LOG_EXCEPTION_CLOSING_SERVER_SOCKET"), e);
245 }
246 }
247 }