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 = StringUtil.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.Builder getHttpClient() {
76 var httpClientBuilder = HttpClient.newBuilder()
77 .connectTimeout(Duration.ofSeconds(this.getTimeout()))
78 .sslContext(this.injectionModel.getMediatorUtils().getCertificateUtil().getSslContext())
79 .followRedirects(
80 this.injectionModel.getMediatorUtils().getPreferencesUtil().isFollowingRedirection()
81 ? HttpClient.Redirect.ALWAYS
82 : HttpClient.Redirect.NEVER
83 );
84 if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isHttp2Disabled()) {
85 httpClientBuilder.version(Version.HTTP_1_1);
86 }
87 if (!this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()) {
88 httpClientBuilder.cookieHandler(this.cookieManager);
89 }
90 if (this.injectionModel.getMediatorUtils().getAuthenticationUtil().isAuthentEnabled()) {
91 httpClientBuilder.authenticator(new Authenticator() {
92 @Override
93 protected PasswordAuthentication getPasswordAuthentication() {
94 return new PasswordAuthentication(
95 ConnectionUtil.this.injectionModel.getMediatorUtils().getAuthenticationUtil().getUsernameAuthentication(),
96 ConnectionUtil.this.injectionModel.getMediatorUtils().getAuthenticationUtil().getPasswordAuthentication().toCharArray()
97 );
98 }
99 });
100 }
101 return httpClientBuilder;
102 }
103
104 public static <T> Map<String, String> getHeadersMap(HttpResponse<T> httpResponse) {
105 Map<String, String> sortedMap = ConnectionUtil.getHeadersMap(httpResponse.headers());
106 String responseCodeHttp = String.valueOf(httpResponse.statusCode());
107 sortedMap.put(":status", responseCodeHttp);
108 return sortedMap;
109 }
110
111 public static Map<String, String> getHeadersMap(HttpHeaders httpHeaders) {
112 Map<String, String> unsortedMap = httpHeaders.map()
113 .entrySet()
114 .stream()
115 .sorted(Entry.comparingByKey())
116 .map(entrySet -> new AbstractMap.SimpleEntry<>(
117 entrySet.getKey(),
118 String.join(", ", entrySet.getValue())
119 ))
120 .collect(Collectors.toMap(
121 AbstractMap.SimpleEntry::getKey,
122 AbstractMap.SimpleEntry::getValue
123 ));
124 return new TreeMap<>(unsortedMap);
125 }
126
127
128
129
130
131
132 public HttpResponse<String> checkConnectionResponse() throws IOException, InterruptedException, JSqlException {
133 var queryString = this.injectionModel.getMediatorUtils().getParameterUtil().getQueryStringFromEntries();
134 var testUrl = this.getUrlBase().replaceAll("\\?$", StringUtils.EMPTY);
135
136 if (StringUtils.isNotEmpty(queryString)) {
137 testUrl += "?"+ queryString;
138 }
139
140 String contentTypeRequest = "text/plain";
141
142 var body = this.injectionModel.getMediatorUtils().getParameterUtil().getRawRequest();
143
144 if (this.injectionModel.getMediatorUtils().getParameterUtil().isMultipartRequest()) {
145 body = body.replaceAll("(?s)\\\\n", "\r\n");
146 } else if (this.injectionModel.getMediatorUtils().getParameterUtil().isRequestSoap()) {
147 contentTypeRequest = "text/xml";
148 } else if (!this.injectionModel.getMediatorUtils().getParameterUtil().getListRequest().isEmpty()) {
149 contentTypeRequest = "application/x-www-form-urlencoded";
150 }
151
152
153 Builder httpRequest = HttpRequest.newBuilder();
154 try {
155 httpRequest.uri(
156 URI.create(
157 testUrl
158 .replace(InjectionModel.STAR, StringUtils.EMPTY)
159 )
160 );
161 } catch (IllegalArgumentException e) {
162 throw new JSqlException(e);
163 }
164 httpRequest.setHeader(HeaderUtil.CONTENT_TYPE_REQUEST, contentTypeRequest)
165 .timeout(Duration.ofSeconds(this.getTimeout()));
166
167 this.injectionModel.getMediatorUtils().getCsrfUtil().addHeaderToken(httpRequest);
168 this.injectionModel.getMediatorUtils().getDigestUtil().addHeaderToken(httpRequest);
169
170 httpRequest.method(this.typeRequest, BodyPublishers.ofString(body));
171
172
173 for (SimpleEntry<String, String> header: this.injectionModel.getMediatorUtils().getParameterUtil().getListHeader()) {
174 HeaderUtil.sanitizeHeaders(httpRequest, header);
175 }
176
177 return this.injectionModel.getMediatorUtils().getHeaderUtil().checkResponseHeader(httpRequest, body);
178 }
179
180 public void testConnection() throws IOException, InterruptedException, JSqlException {
181
182 LOGGER.log(LogLevelUtil.CONSOLE_DEFAULT, () -> I18nUtil.valueByKey("LOG_CONNECTION_TEST"));
183 this.getCookieManager().getCookieStore().removeAll();
184 HttpResponse<String> httpResponse = this.checkConnectionResponse();
185
186 if (
187 (httpResponse.statusCode() == 401 || httpResponse.statusCode() == 403)
188 && !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotProcessingCookies()
189 && (
190 this.injectionModel.getMediatorUtils().getCsrfUtil().isCsrf()
191 || this.injectionModel.getMediatorUtils().getDigestUtil().isDigest()
192 )
193 ) {
194 if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isProcessingCsrf()) {
195 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, () -> "Testing CSRF handshake from previous connection...");
196 } else if (StringUtils.isNotEmpty(this.injectionModel.getMediatorUtils().getDigestUtil().getTokenDigest())) {
197 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, () -> "Testing Digest handshake from previous connection...");
198 }
199 httpResponse = this.checkConnectionResponse();
200 }
201
202 if (httpResponse.statusCode() >= 400 && !this.injectionModel.getMediatorUtils().getPreferencesUtil().isNotTestingConnection()) {
203 throw new InjectionFailureException(String.format("Connection failed: problem when calling %s", httpResponse.uri().toURL()));
204 }
205 }
206
207
208
209
210
211
212 public String getSourceLineFeed(String url) {
213 return this.getSource(url, true, false);
214 }
215
216 public String getSource(String url) {
217 return this.getSource(url, false, false);
218 }
219
220 public String getSource(String url, boolean isConnectIssueIgnored) {
221 return this.getSource(url, false, isConnectIssueIgnored);
222 }
223
224 public String getSource(String url, boolean lineFeed, boolean isConnectIssueIgnored) {
225 Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
226 msgHeader.put(Header.URL, url);
227
228 String pageSource = StringUtils.EMPTY;
229
230 try {
231 var httpRequest = HttpRequest.newBuilder()
232 .uri(URI.create(url))
233 .timeout(Duration.ofSeconds(this.getTimeout()))
234 .build();
235
236 HttpHeaders httpHeaders;
237 if (lineFeed) {
238 HttpResponse<Stream<String>> response = this.getHttpClient().build().send(httpRequest, BodyHandlers.ofLines());
239 pageSource = response.body().collect(Collectors.joining("\n"));
240 httpHeaders = response.headers();
241 } else {
242 HttpResponse<String> response = this.getHttpClient().build().send(httpRequest, BodyHandlers.ofString());
243 pageSource = response.body();
244 httpHeaders = response.headers();
245 }
246
247 msgHeader.put(Header.RESPONSE, ConnectionUtil.getHeadersMap(httpHeaders));
248 msgHeader.put(Header.HEADER, ConnectionUtil.getHeadersMap(httpRequest.headers()));
249
250 } catch (IOException e) {
251 if (!isConnectIssueIgnored) {
252 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
253 }
254 } catch (InterruptedException e) {
255 LOGGER.log(LogLevelUtil.IGNORE, e, e);
256 Thread.currentThread().interrupt();
257 } finally {
258 msgHeader.put(Header.SOURCE, pageSource);
259
260 var request = new Request();
261 request.setMessage(Interaction.MESSAGE_HEADER);
262 request.setParameters(msgHeader);
263 this.injectionModel.sendToViews(request);
264 }
265
266 return pageSource.trim();
267 }
268
269 public void setCustomUserAgent(Builder httpRequest) {
270 if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isUserAgentRandom()) {
271 String agents = this.injectionModel.getMediatorUtils().getUserAgentUtil().getCustomUserAgent();
272 List<String> listAgents = Stream.of(agents.split("[\\r\\n]+"))
273 .filter(q -> !q.matches("^#.*"))
274 .collect(Collectors.toList());
275 String randomElement = listAgents.get(this.randomForUserAgent.nextInt(listAgents.size()));
276 httpRequest.setHeader("User-Agent", randomElement);
277 }
278 }
279
280
281
282
283 public ConnectionUtil withMethodInjection(AbstractMethodInjection methodInjection) {
284 this.methodInjection = methodInjection;
285 return this;
286 }
287
288 public ConnectionUtil withTypeRequest(String typeRequest) {
289 this.typeRequest = typeRequest;
290 return this;
291 }
292
293
294
295
296 public String getUrlByUser() {
297 return this.urlByUser;
298 }
299
300 public void setUrlByUser(String urlByUser) {
301 this.urlByUser = urlByUser;
302 }
303
304 public String getUrlBase() {
305 return this.urlBase;
306 }
307
308 public void setUrlBase(String urlBase) {
309 this.urlBase = urlBase;
310 }
311
312 public AbstractMethodInjection getMethodInjection() {
313 return this.methodInjection;
314 }
315
316 public void setMethodInjection(AbstractMethodInjection methodInjection) {
317 this.methodInjection = methodInjection;
318 }
319
320 public String getTypeRequest() {
321 return this.typeRequest;
322 }
323
324 public void setTypeRequest(String typeRequest) {
325 this.typeRequest = typeRequest;
326 }
327
328
329
330
331 public Integer getTimeout() {
332 return this.injectionModel.getMediatorUtils().getPreferencesUtil().countConnectionTimeout();
333 }
334
335 public CookieManager getCookieManager() {
336 return this.cookieManager;
337 }
338 }