1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.utils;
19
20 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21 import org.apache.commons.lang3.StringUtils;
22
23 import java.io.IOException;
24 import java.net.Authenticator;
25 import java.net.HttpURLConnection;
26 import java.net.InetSocketAddress;
27 import java.net.PasswordAuthentication;
28 import java.net.Proxy;
29 import java.net.SocketAddress;
30 import java.net.URL;
31 import java.util.Base64;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import static java.nio.charset.StandardCharsets.UTF_8;
35
36
37
38
39
40
41
42
43 public final class URLConnectionFactory {
44
45
46
47
48 private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
49
50
51
52 private final Settings settings;
53
54
55
56
57
58
59 public URLConnectionFactory(Settings settings) {
60 this.settings = settings;
61 }
62
63
64
65
66
67
68
69
70
71
72
73 @SuppressWarnings("squid:S2583")
74 @SuppressFBWarnings(justification = "yes, there is a redundant null check in the catch - to suppress warnings we are leaving the null check",
75 value = {"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
76 public HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
77 HttpURLConnection conn = null;
78 final String proxyHost = settings.getString(Settings.KEYS.PROXY_SERVER);
79
80 try {
81 if (proxyHost != null && !matchNonProxy(url)) {
82 final int proxyPort = settings.getInt(Settings.KEYS.PROXY_PORT);
83 final SocketAddress address = new InetSocketAddress(proxyHost, proxyPort);
84
85 final String username = settings.getString(Settings.KEYS.PROXY_USERNAME);
86 final String password = settings.getString(Settings.KEYS.PROXY_PASSWORD);
87
88 if (username != null && password != null) {
89 final Authenticator auth = new Authenticator() {
90 @Override
91 public PasswordAuthentication getPasswordAuthentication() {
92 if (proxyHost.equals(getRequestingHost()) || getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
93 LOGGER.debug("Using the configured proxy username and password");
94 if (settings.getBoolean(Settings.KEYS.PROXY_DISABLE_SCHEMAS, true)) {
95 System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
96 }
97 return new PasswordAuthentication(username, password.toCharArray());
98 }
99 return super.getPasswordAuthentication();
100 }
101 };
102 Authenticator.setDefault(auth);
103 }
104
105 final Proxy proxy = new Proxy(Proxy.Type.HTTP, address);
106 conn = (HttpURLConnection) url.openConnection(proxy);
107 } else {
108 conn = (HttpURLConnection) url.openConnection();
109 }
110 final int connectionTimeout = settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
111
112
113 final int readTimeout = settings.getInt(Settings.KEYS.CONNECTION_READ_TIMEOUT, 60_000);
114 conn.setConnectTimeout(connectionTimeout);
115 conn.setReadTimeout(readTimeout);
116 conn.setInstanceFollowRedirects(true);
117 } catch (IOException ex) {
118 if (conn != null) {
119 try {
120 conn.disconnect();
121 } finally {
122 conn = null;
123 }
124 }
125 throw new URLConnectionFailureException("Error getting connection.", ex);
126 }
127 addAuthenticationIfPresent(conn);
128 return conn;
129 }
130
131
132
133
134
135
136
137
138
139 private void addAuthenticationIfPresent(HttpURLConnection conn) {
140 final String userInfo = conn.getURL().getUserInfo();
141 if (userInfo != null) {
142 final String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userInfo.getBytes(UTF_8));
143 if (LOGGER.isDebugEnabled()) {
144 LOGGER.debug("Adding user info as basic authorization");
145 }
146 conn.addRequestProperty("Authorization", basicAuth);
147 }
148 }
149
150
151
152
153
154
155
156
157
158 public void addBasicAuthentication(HttpURLConnection conn, String userKey, String passwordKey) {
159 if (StringUtils.isNotEmpty(settings.getString(userKey))
160 && StringUtils.isNotEmpty(settings.getString(passwordKey))) {
161 final String user = settings.getString(userKey);
162 final String password = settings.getString(passwordKey);
163
164 if (user.isEmpty() || password.isEmpty()) {
165 if (LOGGER.isDebugEnabled()) {
166 LOGGER.debug("Skip authentication as user and/or password is empty");
167 }
168 } else {
169 final String userColonPassword = user + ":" + password;
170 final String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userColonPassword.getBytes(UTF_8));
171 if (LOGGER.isDebugEnabled()) {
172 LOGGER.debug("Adding user/password from settings.xml as basic authorization");
173 }
174 conn.addRequestProperty("Authorization", basicAuth);
175 }
176 }
177 }
178
179
180
181
182
183
184
185 @SuppressWarnings("StringSplitter")
186 private boolean matchNonProxy(final URL url) {
187 final String host = url.getHost();
188
189
190 final String nonProxyHosts = settings.getString(Settings.KEYS.PROXY_NON_PROXY_HOSTS);
191 if (null != nonProxyHosts) {
192 final String[] nonProxies = nonProxyHosts.split("(,)|(;)|(\\|)");
193 for (final String nonProxyHost : nonProxies) {
194
195 if (null != nonProxyHost && nonProxyHost.contains("*")) {
196
197 final int pos = nonProxyHost.indexOf('*');
198 final String nonProxyHostPrefix = nonProxyHost.substring(0, pos);
199 final String nonProxyHostSuffix = nonProxyHost.substring(pos + 1);
200
201 if (!StringUtils.isBlank(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && StringUtils.isBlank(nonProxyHostSuffix)) {
202 return true;
203 }
204
205 if (StringUtils.isBlank(nonProxyHostPrefix) && !StringUtils.isBlank(nonProxyHostSuffix) && host.endsWith(nonProxyHostSuffix)) {
206 return true;
207 }
208
209 if (!StringUtils.isBlank(nonProxyHostPrefix) && host.startsWith(nonProxyHostPrefix) && !StringUtils.isBlank(nonProxyHostSuffix)
210 && host.endsWith(nonProxyHostSuffix)) {
211 return true;
212 }
213 } else if (host.equals(nonProxyHost)) {
214 return true;
215 }
216 }
217 }
218 return false;
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233 public HttpURLConnection createHttpURLConnection(URL url, boolean proxy) throws URLConnectionFailureException {
234 if (proxy) {
235 return createHttpURLConnection(url);
236 }
237 final HttpURLConnection conn;
238 try {
239 conn = (HttpURLConnection) url.openConnection();
240 final int timeout = settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 10000);
241 conn.setConnectTimeout(timeout);
242 conn.setInstanceFollowRedirects(true);
243 } catch (IOException ioe) {
244 throw new URLConnectionFailureException("Error getting connection.", ioe);
245 }
246 addAuthenticationIfPresent(conn);
247 return conn;
248 }
249
250 }