Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
Autopsy
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
IRT
Autopsy
Commits
5f35af22
Commit
5f35af22
authored
1 year ago
by
Greg DiCristofaro
Browse files
Options
Downloads
Patches
Plain Diff
use Nb classes for auth and proxy selection
parent
8ed27b93
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java
+79
-188
79 additions, 188 deletions
...stech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java
with
79 additions
and
188 deletions
Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java
+
79
−
188
View file @
5f35af22
...
...
@@ -22,12 +22,11 @@
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.net.
Authenticator
;
import
java.net.
InetAddress
;
import
java.net.
PasswordAuthentication
;
import
java.net.
Proxy
;
import
java.net.
ProxySelector
;
import
java.net.
SocketAddress
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
java.net.UnknownHostException
;
import
java.security.KeyManagementException
;
import
java.security.KeyStore
;
import
java.security.KeyStoreException
;
...
...
@@ -35,14 +34,13 @@
import
java.security.SecureRandom
;
import
java.security.UnrecoverableKeyException
;
import
java.text.MessageFormat
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Objects
;
import
java.util.logging.Level
;
import
java.util.stream.Stream
;
import
javax.net.ssl.KeyManager
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
...
...
@@ -50,14 +48,10 @@
import
javax.net.ssl.TrustManagerFactory
;
import
javax.net.ssl.X509TrustManager
;
import
org.apache.commons.collections4.MapUtils
;
import
org.apache.commons.lang.ArrayUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.http.HttpEntity
;
import
org.apache.http.HttpHost
;
import
org.apache.http.HttpStatus
;
import
org.apache.http.auth.AuthScope
;
import
org.apache.http.auth.NTCredentials
;
import
org.apache.http.client.CredentialsProvider
;
import
org.apache.http.client.config.AuthSchemes
;
import
org.apache.http.client.config.RequestConfig
;
import
org.apache.http.client.methods.CloseableHttpResponse
;
import
org.apache.http.client.methods.HttpPost
;
...
...
@@ -71,29 +65,27 @@
import
org.sleuthkit.autopsy.coreutils.Logger
;
import
org.apache.http.impl.client.HttpClientBuilder
;
import
org.apache.http.impl.client.HttpClients
;
import
org.apache.http.impl.client.SystemDefaultCredentialsProvider
;
import
org.apache.http.impl.client.WinHttpClients
;
import
org.apache.http.impl.conn.SystemDefaultRoutePlanner
;
import
org.apache.http.ssl.SSLInitializationException
;
import
org.netbeans.core.ProxySettings
;
import
org.openide.util.
NetworkSettings
;
import
org.openide.util.
Lookup
;
import
org.sleuthkit.autopsy.coreutils.Version
;
/**
* Makes the http requests to CT cloud.
*
* NOTE: regarding proxy settings, the host and port are handled by the
* NbProxySelector. Any proxy authentication is handled by NbAuthenticator which
* is installed at startup (i.e. NbAuthenticator.install). See
* GeneralOptionsModel.testHttpConnection to see how the general options panel
* tests the connection.
*/
class
CTCloudHttpClient
{
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
CTCloudHttpClient
.
class
.
getName
());
private
static
final
String
HOST_URL
=
Version
.
getBuildType
()
==
Version
.
Type
.
RELEASE
?
Constants
.
CT_CLOUD_SERVER
:
Constants
.
CT_CLOUD_DEV_SERVER
;
private
static
final
List
<
String
>
DEFAULT_SCHEME_PRIORITY
=
new
ArrayList
<>(
Arrays
.
asList
(
AuthSchemes
.
SPNEGO
,
AuthSchemes
.
KERBEROS
,
AuthSchemes
.
NTLM
,
AuthSchemes
.
CREDSSP
,
AuthSchemes
.
DIGEST
,
AuthSchemes
.
BASIC
));
private
static
final
String
NB_PROXY_SELECTOR_NAME
=
"org.netbeans.core.NbProxySelector"
;
private
static
final
int
CONNECTION_TIMEOUT_MS
=
58
*
1000
;
// milli sec
...
...
@@ -105,48 +97,12 @@ public static CTCloudHttpClient getInstance() {
private
final
ObjectMapper
mapper
=
ObjectMapperUtil
.
getInstance
().
getDefaultObjectMapper
();
private
final
SSLContext
sslContext
;
private
String
hostName
=
null
;
private
final
ProxySelector
proxySelector
;
private
CTCloudHttpClient
()
{
// leave as null for now unless we want to customize this at a later date
this
.
sslContext
=
createSSLContext
();
}
private
ProxySettingArgs
getProxySettings
(
URI
uri
)
{
if
(
StringUtils
.
isBlank
(
hostName
))
{
try
{
hostName
=
InetAddress
.
getLocalHost
().
getCanonicalHostName
();
}
catch
(
UnknownHostException
ex
)
{
LOGGER
.
log
(
Level
.
WARNING
,
"An error occurred while fetching the hostname"
,
ex
);
}
}
String
proxyPortStr
=
uri
!=
null
?
NetworkSettings
.
getProxyPort
(
uri
)
:
ProxySettings
.
getHttpPort
();
int
proxyPort
=
0
;
if
(
StringUtils
.
isNotBlank
(
proxyPortStr
))
{
try
{
proxyPort
=
Integer
.
parseInt
(
proxyPortStr
);
}
catch
(
NumberFormatException
ex
)
{
LOGGER
.
log
(
Level
.
WARNING
,
"Unable to convert port to integer"
);
}
}
String
proxyHost
=
uri
!=
null
?
NetworkSettings
.
getProxyHost
(
uri
)
:
ProxySettings
.
getHttpHost
();
ProxySettingArgs
proxySettings
=
new
ProxySettingArgs
(
ProxySettings
.
getProxyType
()
!=
ProxySettings
.
DIRECT_CONNECTION
,
hostName
,
proxyHost
,
proxyPort
,
ProxySettings
.
getAuthenticationUsername
(),
ProxySettings
.
getAuthenticationPassword
(),
null
);
// TODO comment out later
LOGGER
.
log
(
Level
.
INFO
,
MessageFormat
.
format
(
"Proxy settings to be used with {0} are {1}."
,
uri
,
proxySettings
));
return
proxySettings
;
this
.
proxySelector
=
getProxySelector
();
}
private
static
URI
getUri
(
String
host
,
String
path
,
Map
<
String
,
String
>
urlReqParams
)
throws
URISyntaxException
{
...
...
@@ -171,12 +127,12 @@ public <O> O doPost(String urlPath, Object jsonBody, Class<O> classType) throws
}
public
<
O
>
O
doPost
(
String
urlPath
,
Map
<
String
,
String
>
urlReqParams
,
Object
jsonBody
,
Class
<
O
>
classType
)
throws
CTCloudException
{
URI
postURI
=
null
;
try
{
postURI
=
getUri
(
HOST_URL
,
urlPath
,
urlReqParams
);
LOGGER
.
log
(
Level
.
INFO
,
"initiating http connection to ctcloud server"
);
try
(
CloseableHttpClient
httpclient
=
createConnection
(
getP
roxySe
ttings
(
postURI
)
,
sslContext
))
{
try
(
CloseableHttpClient
httpclient
=
createConnection
(
p
roxySe
lector
,
sslContext
))
{
HttpPost
postRequest
=
new
HttpPost
(
postURI
);
...
...
@@ -237,7 +193,7 @@ public void doFileUploadPost(String fullUrlPath, String fileName, InputStream fi
throw
new
CTCloudException
(
CTCloudException
.
ErrorCode
.
UNKNOWN
,
ex
);
}
try
(
CloseableHttpClient
httpclient
=
createConnection
(
getP
roxySe
ttings
(
postUri
)
,
sslContext
))
{
try
(
CloseableHttpClient
httpclient
=
createConnection
(
p
roxySe
lector
,
sslContext
))
{
LOGGER
.
log
(
Level
.
INFO
,
"initiating http post request to ctcloud server "
+
fullUrlPath
);
HttpPost
post
=
new
HttpPost
(
postUri
);
configureRequestTimeout
(
post
);
...
...
@@ -335,19 +291,30 @@ private void configureRequestTimeout(HttpRequestBase request) {
}
/**
*
Creates a connection to CT Cloud with the given argum
ent
s
.
*
Get ProxySelector present (favoring NbProxySelector if pres
ent
)
.
*
* @param proxySettings The network proxy settings.
* @param sslContext The ssl context or null.
* @return The connection to CT Cloud.
* @return The found ProxySelector or null.
*/
private
static
CloseableHttpClient
createConnection
(
ProxySettingArgs
proxySettings
,
SSLContext
sslContext
)
throws
SSLInitializationException
{
HttpClientBuilder
builder
=
getHttpClientBuilder
(
proxySettings
);
if
(
sslContext
!=
null
)
{
builder
.
setSSLContext
(
sslContext
);
}
return
builder
.
build
();
private
static
ProxySelector
getProxySelector
()
{
Collection
<?
extends
ProxySelector
>
selectors
=
Lookup
.
getDefault
().
lookupAll
(
ProxySelector
.
class
);
return
(
selectors
!=
null
?
selectors
.
stream
()
:
Stream
.
empty
())
.
filter
(
s
->
s
!=
null
)
.
map
(
s
->
(
ProxySelector
)
s
)
.
sorted
((
a
,
b
)
->
{
String
aName
=
a
.
getClass
().
getCanonicalName
();
String
bName
=
b
.
getClass
().
getCanonicalName
();
boolean
aIsNb
=
aName
.
equalsIgnoreCase
(
NB_PROXY_SELECTOR_NAME
);
boolean
bIsNb
=
bName
.
equalsIgnoreCase
(
NB_PROXY_SELECTOR_NAME
);
if
(
aIsNb
==
bIsNb
)
{
return
StringUtils
.
compareIgnoreCase
(
aName
,
bName
);
}
else
{
return
aIsNb
?
-
1
:
1
;
}
})
.
findFirst
()
// TODO take this out to remove proxy selector logging
.
map
(
s
->
new
LoggingProxySelector
(
s
))
.
orElse
(
null
);
}
/**
...
...
@@ -371,6 +338,7 @@ private static SSLContext createSSLContext() {
}
}
// jvm default key manager
// based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909
private
static
KeyManager
[]
getKeyManagers
()
{
LOGGER
.
log
(
Level
.
INFO
,
"Using default algorithm to create trust store: "
+
KeyManagerFactory
.
getDefaultAlgorithm
());
...
...
@@ -385,6 +353,7 @@ private static KeyManager[] getKeyManagers() {
}
// jvm default trust store
// based in part on this: https://stackoverflow.com/questions/1793979/registering-multiple-keystores-in-jvm/16229909
private
static
TrustManager
[]
getTrustManagers
()
{
try
{
...
...
@@ -401,138 +370,60 @@ private static TrustManager[] getTrustManagers() {
}
}
private
static
HttpClientBuilder
getHttpClientBuilder
(
ProxySettingArgs
proxySettings
)
{
if
(
proxySettings
.
isSystemOrManualProxy
())
{
Authenticator
.
setDefault
(
new
Authenticator
()
{
@Override
protected
PasswordAuthentication
getPasswordAuthentication
()
{
LOGGER
.
info
(
"Requesting Password Authentication..."
);
return
super
.
getPasswordAuthentication
();
}
});
HttpClientBuilder
builder
=
null
;
HttpHost
proxyHost
=
null
;
CredentialsProvider
proxyCredsProvider
=
null
;
RequestConfig
config
=
null
;
if
(
Objects
.
nonNull
(
proxySettings
.
getProxyHostname
())
&&
proxySettings
.
getProxyPort
()
>
0
)
{
proxyHost
=
new
HttpHost
(
proxySettings
.
getProxyHostname
(),
proxySettings
.
getProxyPort
());
proxyCredsProvider
=
getProxyCredentialsProvider
(
proxySettings
);
if
(
StringUtils
.
isNotBlank
(
proxySettings
.
getAuthScheme
()))
{
if
(!
DEFAULT_SCHEME_PRIORITY
.
get
(
0
).
equalsIgnoreCase
(
proxySettings
.
getAuthScheme
()))
{
DEFAULT_SCHEME_PRIORITY
.
removeIf
(
s
->
s
.
equalsIgnoreCase
(
proxySettings
.
getAuthScheme
()));
DEFAULT_SCHEME_PRIORITY
.
add
(
0
,
proxySettings
.
getAuthScheme
());
}
}
config
=
RequestConfig
.
custom
().
setProxyPreferredAuthSchemes
(
DEFAULT_SCHEME_PRIORITY
).
build
();
}
if
(
Objects
.
isNull
(
proxyCredsProvider
)
&&
WinHttpClients
.
isWinAuthAvailable
())
{
builder
=
WinHttpClients
.
custom
();
builder
.
useSystemProperties
();
LOGGER
.
log
(
Level
.
WARNING
,
"Using Win HTTP Client"
);
}
else
{
builder
=
HttpClients
.
custom
();
builder
.
setDefaultRequestConfig
(
config
);
if
(
Objects
.
nonNull
(
proxyCredsProvider
))
{
// make sure non null proxycreds before setting it
builder
.
setDefaultCredentialsProvider
(
proxyCredsProvider
);
}
LOGGER
.
log
(
Level
.
WARNING
,
"Using default http client"
);
}
if
(
Objects
.
nonNull
(
proxyHost
))
{
builder
.
setProxy
(
proxyHost
);
LOGGER
.
log
(
Level
.
WARNING
,
MessageFormat
.
format
(
"Using proxy {0}"
,
proxyHost
));
}
return
builder
;
}
else
{
return
HttpClients
.
custom
();
}
}
/**
*
Returns a CredentialsProvider for proxy, if one is configured
.
*
Creates a connection to CT Cloud with the given arguments
.
*
* @return CredentialsProvider, if a proxy is configured with credentials,
* null otherwise
* @param proxySelector The proxy selector.
* @param sslContext The ssl context or null.
* @return The connection to CT Cloud.
*/
private
static
CredentialsProvider
getProxyCredentialsProvider
(
ProxySettingArgs
proxySettings
)
{
CredentialsProvider
proxyCredsProvider
=
null
;
if
(
proxySettings
.
isSystemOrManualProxy
())
{
if
(
StringUtils
.
isNotBlank
(
proxySettings
.
getProxyUserId
()))
{
if
(
null
!=
proxySettings
.
getProxyPassword
()
&&
proxySettings
.
getProxyPassword
().
length
>
0
)
{
// Password will be blank for KERBEROS / NEGOTIATE schemes.
proxyCredsProvider
=
new
SystemDefaultCredentialsProvider
();
String
userId
=
proxySettings
.
getProxyUserId
();
String
domain
=
null
;
if
(
userId
.
contains
(
"\\"
))
{
domain
=
userId
.
split
(
"\\\\"
)[
0
];
userId
=
userId
.
split
(
"\\\\"
)[
1
];
}
String
workStation
=
proxySettings
.
getHostName
();
proxyCredsProvider
.
setCredentials
(
new
AuthScope
(
proxySettings
.
getProxyHostname
(),
proxySettings
.
getProxyPort
()),
new
NTCredentials
(
userId
,
new
String
(
proxySettings
.
getProxyPassword
()),
workStation
,
domain
));
}
}
}
private
static
CloseableHttpClient
createConnection
(
ProxySelector
proxySelector
,
SSLContext
sslContext
)
throws
SSLInitializationException
{
HttpClientBuilder
builder
;
return
proxyCredsProvider
;
}
if
(
ProxySettings
.
getProxyType
()
!=
ProxySettings
.
DIRECT_CONNECTION
&&
StringUtils
.
isBlank
(
ProxySettings
.
getAuthenticationUsername
())
&&
ArrayUtils
.
isEmpty
(
ProxySettings
.
getAuthenticationPassword
())
&&
WinHttpClients
.
isWinAuthAvailable
())
{
private
static
class
ProxySettingArgs
{
private
final
boolean
systemOrManualProxy
;
private
final
String
hostName
;
private
final
String
proxyHostname
;
private
final
int
proxyPort
;
private
final
String
proxyUserId
;
private
final
char
[]
proxyPassword
;
private
final
String
authScheme
;
ProxySettingArgs
(
boolean
systemOrManualProxy
,
String
hostName
,
String
proxyHostname
,
int
proxyPort
,
String
proxyUserId
,
char
[]
proxyPassword
,
String
authScheme
)
{
this
.
systemOrManualProxy
=
systemOrManualProxy
;
this
.
hostName
=
hostName
;
this
.
proxyHostname
=
proxyHostname
;
this
.
proxyPort
=
proxyPort
;
this
.
proxyUserId
=
proxyUserId
;
this
.
proxyPassword
=
proxyPassword
;
this
.
authScheme
=
authScheme
;
builder
=
WinHttpClients
.
custom
();
builder
.
useSystemProperties
();
LOGGER
.
log
(
Level
.
WARNING
,
"Using Win HTTP Client"
);
}
else
{
builder
=
HttpClients
.
custom
();
// builder.setDefaultRequestConfig(config);
LOGGER
.
log
(
Level
.
WARNING
,
"Using default http client"
);
}
boolean
isSystemOrManualProxy
(
)
{
return
systemOrManualProxy
;
if
(
sslContext
!=
null
)
{
builder
.
setSSLContext
(
sslContext
)
;
}
String
getHostName
(
)
{
return
hostName
;
if
(
proxySelector
!=
null
)
{
builder
.
setRoutePlanner
(
new
SystemDefaultRoutePlanner
(
proxySelector
))
;
}
String
getProxyHostname
()
{
return
proxyHostname
;
}
return
builder
.
build
();
}
int
getProxyPort
()
{
return
proxyPort
;
}
private
static
class
LoggingProxySelector
extends
ProxySelector
{
String
getProxyUserId
()
{
return
proxyUserId
;
}
private
final
ProxySelector
delegate
;
char
[]
getProxyPassword
(
)
{
return
proxyPassword
;
public
LoggingProxySelector
(
ProxySelector
delegate
)
{
this
.
delegate
=
delegate
;
}
public
String
getAuthScheme
()
{
return
authScheme
;
@Override
public
List
<
Proxy
>
select
(
URI
uri
)
{
List
<
Proxy
>
selectedProxies
=
delegate
.
select
(
uri
);
LOGGER
.
log
(
Level
.
FINE
,
MessageFormat
.
format
(
"Proxy selected for {0} are {1}"
,
uri
,
selectedProxies
));
return
selectedProxies
;
}
@Override
public
String
toString
()
{
return
"ProxySettingArgs{"
+
"systemOrManualProxy="
+
systemOrManualProxy
+
", hostName="
+
hostName
+
", proxyHostname="
+
proxyHostname
+
", proxyPort="
+
proxyPort
+
", proxyUserId="
+
proxyUserId
+
", proxyPassword set="
+
(
proxyPassword
!=
null
&&
proxyPassword
.
length
>
0
)
+
", authScheme="
+
authScheme
+
'}'
;
public
void
connectFailed
(
URI
uri
,
SocketAddress
sa
,
IOException
ioe
)
{
LOGGER
.
log
(
Level
.
WARNING
,
MessageFormat
.
format
(
"Connection failed connecting to {0} socket address {1}"
,
uri
,
sa
),
ioe
);
delegate
.
connectFailed
(
uri
,
sa
,
ioe
);
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment