1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.metricshub.wbem.sblim.cimclient.internal.http;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.io.OutputStream;
55 import java.net.InetAddress;
56 import java.net.Socket;
57 import java.net.SocketTimeoutException;
58 import java.util.HashMap;
59 import java.util.Map;
60 import java.util.logging.Level;
61 import javax.net.ssl.SSLSocket;
62 import org.metricshub.wbem.sblim.cimclient.internal.http.io.ASCIIPrintStream;
63 import org.metricshub.wbem.sblim.cimclient.internal.logging.LogAndTraceBroker;
64 import org.metricshub.wbem.sblim.cimclient.internal.util.WBEMConfiguration;
65 import org.metricshub.wbem.sblim.cimclient.internal.util.WBEMConstants;
66
67
68
69
70
71
72 public class HttpConnectionHandler {
73
74
75
76 public static final int MAJOR_VERSION = 1;
77
78
79
80
81 public static final int MINOR_VERSION = 1;
82
83 HttpContentHandler iHandler;
84
85 private int iHeaderTimeout;
86
87 private int iMaxAllowedTimeouts;
88
89 private Map<String, Integer> iSuspectIPs = new HashMap<String, Integer>();
90
91 private StringBuilder iBlockedIPs = null;
92
93
94
95
96
97
98
99
100
101 public HttpConnectionHandler(HttpContentHandler pHandler, WBEMConfiguration pProperties) {
102 this.iHandler = pHandler;
103 this.iHeaderTimeout = pProperties.getListenerHttpHeaderTimeout();
104 this.iMaxAllowedTimeouts = pProperties.getListenerMaxAllowedTimeouts();
105 }
106
107 private synchronized void addSuspectIP(String pSuspectIP) {
108 if (this.iMaxAllowedTimeouts == 0) return;
109
110 Integer times = this.iSuspectIPs.get(pSuspectIP);
111 if (times == null) {
112 this.iSuspectIPs.put(pSuspectIP, Integer.valueOf(1));
113 } else {
114 int timesVal = times.intValue() + 1;
115 this.iSuspectIPs.put(pSuspectIP, Integer.valueOf(timesVal));
116 if (timesVal >= this.iMaxAllowedTimeouts) {
117 boolean newIP = false;
118 if (this.iBlockedIPs == null) {
119 this.iBlockedIPs = new StringBuilder(pSuspectIP);
120 newIP = true;
121 } else if (this.iBlockedIPs.indexOf(pSuspectIP) == -1) {
122 this.iBlockedIPs.append(',');
123 this.iBlockedIPs.append(pSuspectIP);
124 newIP = true;
125 }
126 if (newIP) LogAndTraceBroker
127 .getBroker()
128 .trace(
129 Level.WARNING,
130 "Maximum allowable timeouts exceeded, all future connections ignored from " + pSuspectIP
131 );
132 }
133 }
134 }
135
136 private synchronized boolean isBlockedIP(Socket socket) {
137 return (this.iBlockedIPs != null && this.iBlockedIPs.indexOf(socket.getInetAddress().getHostAddress()) != -1);
138 }
139
140
141
142
143
144
145
146 public void handleConnection(Socket socket) {
147 InputStream is = null;
148 OutputStream os = null;
149 if (isBlockedIP(socket)) {
150 LogAndTraceBroker
151 .getBroker()
152 .trace(Level.FINEST, "Incoming connection ignored from blocked IP " + socket.getInetAddress().getHostAddress());
153 } else try {
154 is = socket.getInputStream();
155 os = socket.getOutputStream();
156 do {
157 MessageReader reader = new MessageReader(is, this.iHeaderTimeout);
158 boolean persistent = reader.isPersistentConnectionSupported();
159 persistent = false;
160 boolean chunk = reader.isChunkSupported();
161
162 HttpServerMethod readerMethod = reader.getMethod();
163 if (readerMethod.getMethodName().equals("POST") || readerMethod.getMethodName().equals("M-POST")) {
164
165
166 MessageWriter writer = new MessageWriter(os, persistent, chunk);
167 try {
168 StringBuilder localURL = new StringBuilder(socket instanceof SSLSocket ? "https://" : "http://");
169 InetAddress localAddress = socket.getLocalAddress();
170 if (localAddress != null) {
171 localURL.append(localAddress.getHostAddress());
172 int port = socket.getLocalPort();
173 if (port > 0) {
174 localURL.append(":");
175 localURL.append(port);
176 }
177 }
178
179
180 this.iHandler.handleContent(reader, writer, socket.getInetAddress(), localURL.toString());
181 writer.setMethod(
182 new HttpServerMethod(readerMethod.getMajorVersion(), readerMethod.getMinorVersion(), 200, "OK")
183 );
184 } catch (HttpException e) {
185 writer.setMethod(
186 new HttpServerMethod(
187 readerMethod.getMajorVersion(),
188 readerMethod.getMinorVersion(),
189 e.getStatus(),
190 e.getMessage()
191 )
192 );
193 } catch (Throwable t) {
194 writer.setMethod(
195 new HttpServerMethod(
196 readerMethod.getMajorVersion(),
197 readerMethod.getMinorVersion(),
198 501,
199 "Not Implemented"
200 )
201 );
202
203 writer.reset();
204
205 writeError(writer.getOutputStream(), "error", "error");
206 } finally {
207 try {
208 writer.close();
209 } catch (IOException e) {
210 LogAndTraceBroker
211 .getBroker()
212 .trace(Level.FINER, "Exception while closing output stream from server socket", e);
213 }
214 }
215 } else {
216 persistent = false;
217 MessageWriter writer = new MessageWriter(os, false, false);
218 HttpHeader header = new HttpHeader();
219 writer.setHeader(header);
220
221
222 writer.setMethod(
223 new HttpServerMethod(readerMethod.getMajorVersion(), readerMethod.getMinorVersion(), 501, "Not Implemented")
224 );
225 writeError(writer.getOutputStream(), "", "");
226 try {
227 writer.close();
228 } catch (IOException e) {
229 LogAndTraceBroker
230 .getBroker()
231 .trace(Level.FINER, "Exception while closing output stream from server socket", e);
232 }
233 }
234
235 if (!persistent) break;
236 try {
237 reader.close();
238 } catch (IOException e) {
239 LogAndTraceBroker
240 .getBroker()
241 .trace(Level.FINER, "Exception while closing input stream from server socket", e);
242 }
243 } while (true);
244 } catch (IOException e) {
245 LogAndTraceBroker.getBroker().trace(Level.FINER, "Exception while reading from server socket", e);
246
247 if (
248 e instanceof SocketTimeoutException ||
249 WBEMConstants.INDICATION_DOS_EXCEPTION_MESSAGE.equalsIgnoreCase(e.getMessage())
250 ) {
251 addSuspectIP(socket.getInetAddress().getHostAddress());
252 }
253 }
254 try {
255 socket.close();
256 } catch (IOException e) {
257 LogAndTraceBroker.getBroker().trace(Level.FINER, "Exception while closing server socket", e);
258 }
259 }
260
261
262
263
264 public void close() {
265 this.iHandler.close();
266 }
267
268 private void writeError(ASCIIPrintStream dos, String title, String body) {
269 dos.print("<HTML> <HEAD> <TITLE>" + title + "</TITLE></HEAD><BODY>" + body + "</BODY></HTML>");
270 }
271
272
273
274
275
276
277 public synchronized String getBlockedIPs() {
278 return (this.iBlockedIPs == null) ? null : this.iBlockedIPs.toString();
279 }
280
281
282
283
284
285
286
287
288 public synchronized void setBlockedIPs(String pIPs) {
289 this.iBlockedIPs = (pIPs == null || pIPs.trim().length() == 0) ? null : new StringBuilder(pIPs);
290 }
291 }