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 public String getSource(String url, boolean lineFeed) {
208 Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
209 msgHeader.put(Header.URL, url);
210
211 String pageSource = StringUtils.EMPTY;
212
213 try {
214 var httpRequest = HttpRequest.newBuilder()
215 .uri(URI.create(url))
216 .timeout(Duration.ofSeconds(this.getTimeout()))
217 .build();
218
219 HttpHeaders httpHeaders;
220 if (lineFeed) {
221 HttpResponse<Stream<String>> response = this.getHttpClient().build().send(httpRequest, BodyHandlers.ofLines());
222 pageSource = response.body().collect(Collectors.joining("\n"));
223 httpHeaders = response.headers();
224 } else {
225 HttpResponse<String> response = this.getHttpClient().build().send(httpRequest, BodyHandlers.ofString());
226 pageSource = response.body();
227 httpHeaders = response.headers();
228 }
229
230 msgHeader.put(Header.RESPONSE, ConnectionUtil.getHeadersMap(httpHeaders));
231 msgHeader.put(Header.HEADER, ConnectionUtil.getHeadersMap(httpRequest.headers()));
232
233 } catch (IOException e) {
234 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
235 } catch (InterruptedException e) {
236 LOGGER.log(LogLevelUtil.IGNORE, e, e);
237 Thread.currentThread().interrupt();
238 } finally {
239 msgHeader.put(Header.SOURCE, pageSource);
240
241 var request = new Request();
242 request.setMessage(Interaction.MESSAGE_HEADER);
243 request.setParameters(msgHeader);
244 this.injectionModel.sendToViews(request);
245 }
246
247 return pageSource.trim();
248 }
249
250
251
252
253
254
255 public String getSourceLineFeed(String url) {
256 return this.getSource(url, true);
257 }
258
259 public String getSource(String url) {
260 return this.getSource(url, false);
261 }
262
263 public void setCustomUserAgent(Builder httpRequest) {
264 if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isUserAgentRandom()) {
265 String agents = this.injectionModel.getMediatorUtils().getUserAgentUtil().getCustomUserAgent();
266 List<String> listAgents = Stream.of(agents.split("[\\r\\n]+"))
267 .filter(q -> !q.matches("^#.*"))
268 .collect(Collectors.toList());
269 String randomElement = listAgents.get(this.randomForUserAgent.nextInt(listAgents.size()));
270 httpRequest.setHeader("User-Agent", randomElement);
271 }
272 }
273
274
275
276
277 public ConnectionUtil withMethodInjection(AbstractMethodInjection methodInjection) {
278 this.methodInjection = methodInjection;
279 return this;
280 }
281
282 public ConnectionUtil withTypeRequest(String typeRequest) {
283 this.typeRequest = typeRequest;
284 return this;
285 }
286
287
288
289
290 public String getUrlByUser() {
291 return this.urlByUser;
292 }
293
294 public void setUrlByUser(String urlByUser) {
295 this.urlByUser = urlByUser;
296 }
297
298 public String getUrlBase() {
299 return this.urlBase;
300 }
301
302 public void setUrlBase(String urlBase) {
303 this.urlBase = urlBase;
304 }
305
306 public AbstractMethodInjection getMethodInjection() {
307 return this.methodInjection;
308 }
309
310 public void setMethodInjection(AbstractMethodInjection methodInjection) {
311 this.methodInjection = methodInjection;
312 }
313
314 public String getTypeRequest() {
315 return this.typeRequest;
316 }
317
318 public void setTypeRequest(String typeRequest) {
319 this.typeRequest = typeRequest;
320 }
321
322
323
324
325 public Integer getTimeout() {
326 return this.injectionModel.getMediatorUtils().getPreferencesUtil().countConnectionTimeout();
327 }
328
329 public CookieManager getCookieManager() {
330 return this.cookieManager;
331 }
332 }