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