1 package com.jsql.util;
2
3 import com.jsql.model.InjectionModel;
4 import com.jsql.model.bean.util.Header;
5 import com.jsql.model.bean.util.Interaction;
6 import com.jsql.model.bean.util.Request;
7 import com.jsql.model.exception.InjectionFailureException;
8 import com.jsql.model.exception.JSqlException;
9 import com.jsql.model.injection.method.AbstractMethodInjection;
10 import org.apache.commons.lang3.StringUtils;
11 import org.apache.logging.log4j.LogManager;
12 import org.apache.logging.log4j.Logger;
13
14 import java.io.IOException;
15 import java.net.Authenticator;
16 import java.net.CookieManager;
17 import java.net.PasswordAuthentication;
18 import java.net.URI;
19 import java.net.http.HttpClient;
20 import java.net.http.HttpClient.Version;
21 import java.net.http.HttpHeaders;
22 import java.net.http.HttpRequest;
23 import java.net.http.HttpRequest.BodyPublishers;
24 import java.net.http.HttpRequest.Builder;
25 import java.net.http.HttpResponse;
26 import java.net.http.HttpResponse.BodyHandlers;
27 import java.time.Duration;
28 import java.util.*;
29 import java.util.AbstractMap.SimpleEntry;
30 import java.util.Map.Entry;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33
34
35
36
37
38 public class ConnectionUtil {
39
40
41
42
43 private static final Logger LOGGER = LogManager.getRootLogger();
44
45
46
47
48 private String urlByUser;
49
50
51
52
53 private String urlBase;
54
55
56
57
58 private AbstractMethodInjection methodInjection;
59
60
61
62
63 private String typeRequest = "GET";
64
65 private final Random randomForUserAgent = new Random();
66
67 private final InjectionModel injectionModel;
68
69 private final CookieManager cookieManager = new CookieManager();
70
71 public ConnectionUtil(InjectionModel injectionModel) {
72 this.injectionModel = injectionModel;
73 }
74
75 public HttpClient getHttpClient() {
76
77 var httpClientBuilder = HttpClient.newBuilder()
78 .connectTimeout(Duration.ofSeconds(this.getTimeout()))
79 .sslContext(this.injectionModel.getMediatorUtils().getCertificateUtil().getSslContext())
80 .followRedirects(
81 this.injectionModel.getMediatorUtils().getPreferencesUtil().isFollowingRedirection()
82 ? HttpClient.Redirect.ALWAYS
83 : HttpClient.Redirect.NEVER
84 );
85
86 if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isHttp2Disabled()) {
87 httpClientBuilder.version(Version.HTTP_1_1);
88 }
89
90 if (!this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()) {
91 httpClientBuilder.cookieHandler(this.cookieManager);
92 }
93
94 if (this.injectionModel.getMediatorUtils().getAuthenticationUtil().isAuthentEnabled()) {
95 httpClientBuilder.authenticator(new Authenticator() {
96 @Override
97 protected PasswordAuthentication getPasswordAuthentication() {
98 return new PasswordAuthentication(
99 ConnectionUtil.this.injectionModel.getMediatorUtils().getAuthenticationUtil().getUsernameAuthentication(),
100 ConnectionUtil.this.injectionModel.getMediatorUtils().getAuthenticationUtil().getPasswordAuthentication().toCharArray()
101 );
102 }
103 });
104 }
105
106 return httpClientBuilder.build();
107 }
108
109
110 public static <T> Map<String, String> getHeadersMap(HttpResponse<T> httpResponse) {
111
112 Map<String, String> sortedMap = getHeadersMap(httpResponse.headers());
113
114 String responseCodeHttp = ""+ httpResponse.statusCode();
115 sortedMap.put(":status", responseCodeHttp);
116
117 return sortedMap;
118 }
119
120 public static Map<String, String> getHeadersMap(HttpHeaders httpHeaders) {
121
122 Map<String, String> unsortedMap = httpHeaders.map()
123 .entrySet()
124 .stream()
125 .sorted(Entry.comparingByKey())
126 .map(entrySet -> new AbstractMap.SimpleEntry<>(
127 entrySet.getKey(),
128 String.join(", ", entrySet.getValue())
129 ))
130 .collect(Collectors.toMap(
131 AbstractMap.SimpleEntry::getKey,
132 AbstractMap.SimpleEntry::getValue
133 ));
134
135 return new TreeMap<>(unsortedMap);
136 }
137
138
139
140
141
142
143
144
145
146 public HttpResponse<String> checkConnectionResponse() throws IOException, InterruptedException, JSqlException {
147
148 var queryString = this.injectionModel.getMediatorUtils().getParameterUtil().getQueryStringFromEntries();
149 var testUrl = this.getUrlBase().replaceAll("\\?$", "");
150
151 if (StringUtils.isNotEmpty(queryString)) {
152 testUrl += "?"+ queryString;
153 }
154
155 String contentTypeRequest = "text/plain";
156
157 var body = this.injectionModel.getMediatorUtils().getParameterUtil().getRawRequest();
158
159 if (this.injectionModel.getMediatorUtils().getParameterUtil().isMultipartRequest()) {
160 body = body.replaceAll("(?s)\\\\n", "\r\n");
161 } else if (this.injectionModel.getMediatorUtils().getParameterUtil().isRequestSoap()) {
162 contentTypeRequest = "text/xml";
163 } else if (!this.injectionModel.getMediatorUtils().getParameterUtil().getListRequest().isEmpty()) {
164 contentTypeRequest = "application/x-www-form-urlencoded";
165 }
166
167
168 Builder httpRequest = HttpRequest.newBuilder();
169 try {
170 httpRequest.uri(
171 URI.create(
172
173 testUrl
174
175 .replace(InjectionModel.STAR, StringUtils.EMPTY)
176 )
177 );
178 } catch (IllegalArgumentException e) {
179 throw new JSqlException(e);
180 }
181 httpRequest.setHeader(HeaderUtil.CONTENT_TYPE_REQUEST, contentTypeRequest)
182 .timeout(Duration.ofSeconds(this.getTimeout()));
183
184 this.injectionModel.getMediatorUtils().getCsrfUtil().addHeaderToken(httpRequest);
185 this.injectionModel.getMediatorUtils().getDigestUtil().addHeaderToken(httpRequest);
186
187 httpRequest.method(
188 this.typeRequest,
189 BodyPublishers.ofString(body)
190 );
191
192
193 for (SimpleEntry<String, String> header: this.injectionModel.getMediatorUtils().getParameterUtil().getListHeader()) {
194 HeaderUtil.sanitizeHeaders(httpRequest, header);
195 }
196
197 return this.injectionModel.getMediatorUtils().getHeaderUtil().checkResponseHeader(httpRequest, body);
198 }
199
200 public void testConnection() throws IOException, InterruptedException, JSqlException {
201
202
203 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, () -> I18nUtil.valueByKey("LOG_CONNECTION_TEST"));
204 this.getCookieManager().getCookieStore().removeAll();
205 HttpResponse<String> httpResponse = this.checkConnectionResponse();
206
207 if (
208 (httpResponse.statusCode() == 401 || httpResponse.statusCode() == 403)
209 && !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
210 && (
211 this.injectionModel.getMediatorUtils().getCsrfUtil().isCsrf()
212 || this.injectionModel.getMediatorUtils().getDigestUtil().isDigest()
213 )
214 ) {
215 if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isProcessingCsrf()) {
216 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, () -> "Testing CSRF handshake from previous connection...");
217 } else if (StringUtils.isNotEmpty(this.injectionModel.getMediatorUtils().getDigestUtil().getTokenDigest())) {
218 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, () -> "Testing Digest handshake from previous connection...");
219 }
220 httpResponse = this.checkConnectionResponse();
221 }
222
223 if (httpResponse.statusCode() >= 400 && !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotTestingConnection()) {
224 throw new InjectionFailureException(String.format("Connection failed: problem when calling %s", httpResponse.uri().toURL()));
225 }
226 }
227
228 public String getSource(String url, boolean lineFeed) {
229
230 Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
231 msgHeader.put(Header.URL, url);
232
233 String pageSource = StringUtils.EMPTY;
234
235 try {
236 var httpRequest = HttpRequest.newBuilder()
237 .uri(URI.create(url))
238 .timeout(Duration.ofSeconds(this.getTimeout()))
239 .build();
240
241 HttpHeaders httpHeaders;
242
243 if (lineFeed) {
244
245 HttpResponse<Stream<String>> response = this.getHttpClient().send(httpRequest, BodyHandlers.ofLines());
246 pageSource = response.body().collect(Collectors.joining("\n"));
247 httpHeaders = response.headers();
248
249 } else {
250
251 HttpResponse<String> response = this.getHttpClient().send(httpRequest, BodyHandlers.ofString());
252 pageSource = response.body();
253 httpHeaders = response.headers();
254 }
255
256 msgHeader.put(Header.RESPONSE, ConnectionUtil.getHeadersMap(httpHeaders));
257 msgHeader.put(Header.HEADER, ConnectionUtil.getHeadersMap(httpRequest.headers()));
258
259 } catch (IOException e) {
260 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
261 } catch (InterruptedException e) {
262
263 LOGGER.log(LogLevelUtil.IGNORE, e, e);
264 Thread.currentThread().interrupt();
265
266 } finally {
267
268 msgHeader.put(Header.SOURCE, pageSource);
269
270
271 var request = new Request();
272 request.setMessage(Interaction.MESSAGE_HEADER);
273 request.setParameters(msgHeader);
274 this.injectionModel.sendToViews(request);
275 }
276
277 return pageSource.trim();
278 }
279
280
281
282
283
284
285 public String getSourceLineFeed(String url) {
286 return this.getSource(url, true);
287 }
288
289 public String getSource(String url) {
290 return this.getSource(url, false);
291 }
292
293 public void setCustomUserAgent(Builder httpRequest) {
294 if (this.injectionModel.getMediatorUtils().getUserAgentUtil().isCustomUserAgent()) {
295
296 String agents = this.injectionModel.getMediatorUtils().getUserAgentUtil().getCustomUserAgent();
297 List<String> listAgents = Stream.of(agents.split("[\\r\\n]+"))
298 .filter(q -> !q.matches("^#.*"))
299 .collect(Collectors.toList());
300
301 String randomElement = listAgents.get(this.randomForUserAgent.nextInt(listAgents.size()));
302
303 httpRequest.setHeader("User-Agent", randomElement);
304 }
305 }
306
307
308
309
310 public ConnectionUtil withMethodInjection(AbstractMethodInjection methodInjection) {
311 this.methodInjection = methodInjection;
312 return this;
313 }
314
315 public ConnectionUtil withTypeRequest(String typeRequest) {
316 this.typeRequest = typeRequest;
317 return this;
318 }
319
320
321
322
323 public String getUrlByUser() {
324 return this.urlByUser;
325 }
326
327 public void setUrlByUser(String urlByUser) {
328 this.urlByUser = urlByUser;
329 }
330
331 public String getUrlBase() {
332 return this.urlBase;
333 }
334
335 public void setUrlBase(String urlBase) {
336 this.urlBase = urlBase;
337 }
338
339 public AbstractMethodInjection getMethodInjection() {
340 return this.methodInjection;
341 }
342
343 public void setMethodInjection(AbstractMethodInjection methodInjection) {
344 this.methodInjection = methodInjection;
345 }
346
347 public String getTypeRequest() {
348 return this.typeRequest;
349 }
350
351 public void setTypeRequest(String typeRequest) {
352 this.typeRequest = typeRequest;
353 }
354
355
356
357
358 public Integer getTimeout() {
359 return this.injectionModel.getMediatorUtils().getPreferencesUtil().countConnectionTimeout();
360 }
361
362 public CookieManager getCookieManager() {
363 return cookieManager;
364 }
365 }