Skip to content

Commit e6be858

Browse files
author
Robert Veznaver
committed
add client certificate authentication support
1 parent 075f230 commit e6be858

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

src/main/java/com/xebialabs/overthere/cifs/CifsConnectionBuilder.java

+12
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,18 @@ public class CifsConnectionBuilder implements OverthereConnectionBuilder {
170170
*/
171171
public static final String WINRM_LOCALE_DEFAULT = "en-US";
172172

173+
/**
174+
* Set to true for mutual HTTPS authentication
175+
*/
176+
177+
public static final String WINRM_CLIENT_CERTIFICATE = "winrmClientCertificate";
178+
179+
/**
180+
* Default value for HTTPS mutual authentication
181+
*/
182+
183+
public static final boolean WINRM_CLIENT_CERTIFICATE_DEFAULT = false;
184+
173185
/**
174186
* See <a href="https://github.com/xebialabs/overthere/blob/master/README.md#cifs_winrmKerberosUseHttpSpn">the online documentation</a>
175187
*/

src/main/java/com/xebialabs/overthere/cifs/winrm/CifsWinRmConnection.java

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_CONTEXT_DEFAULT;
5151
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_ENABLE_HTTPS_DEFAULT;
5252
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_ENVELOP_SIZE_DEFAULT;
53+
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_CLIENT_CERTIFICATE;
54+
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_CLIENT_CERTIFICATE_DEFAULT;
5355
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY_DEFAULT;
5456
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY_DEFAULT;
5557
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_KERBEROS_ADD_PORT_TO_SPN_DEFAULT;
@@ -245,6 +247,7 @@ private WinRmClient createWinrmClient() {
245247
client.setWinRmTimeout(options.get(WINRM_TIMEMOUT, DEFAULT_WINRM_TIMEOUT));
246248
client.setWinRmEnvelopSize(options.get(WINRM_ENVELOP_SIZE, WINRM_ENVELOP_SIZE_DEFAULT));
247249
client.setWinRmLocale(options.get(WINRM_LOCALE, WINRM_LOCALE_DEFAULT));
250+
client.setClientCertificate(options.getBoolean(WINRM_CLIENT_CERTIFICATE, WINRM_CLIENT_CERTIFICATE_DEFAULT));
248251
client.setHttpsCertTrustStrategy(options.getEnum(WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY, WinrmHttpsCertificateTrustStrategy.class, WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY_DEFAULT));
249252
client.setHttpsHostnameVerifyStrategy(options.getEnum(WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY, WinrmHttpsHostnameVerificationStrategy.class, WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY_DEFAULT));
250253
client.setKerberosUseHttpSpn(options.getBoolean(WINRM_KERBEROS_USE_HTTP_SPN, WINRM_KERBEROS_USE_HTTP_SPN_DEFAULT));

src/main/java/com/xebialabs/overthere/cifs/winrm/WinRmClient.java

+36-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
package com.xebialabs.overthere.cifs.winrm;
2424

2525
import java.io.BufferedReader;
26+
import java.io.File;
27+
import java.io.FileInputStream;
28+
import java.io.FileNotFoundException;
2629
import java.io.IOException;
2730
import java.io.InputStream;
2831
import java.io.InputStreamReader;
@@ -35,12 +38,14 @@
3538
import java.net.URL;
3639
import java.security.GeneralSecurityException;
3740
import java.security.KeyManagementException;
41+
import java.security.KeyStore;
3842
import java.security.KeyStoreException;
3943
import java.security.NoSuchAlgorithmException;
4044
import java.security.Principal;
4145
import java.security.PrivilegedActionException;
4246
import java.security.PrivilegedExceptionAction;
4347
import java.security.UnrecoverableKeyException;
48+
import java.security.cert.CertificateException;
4449
import java.util.Iterator;
4550
import java.util.List;
4651
import java.util.UUID;
@@ -111,6 +116,7 @@ public class WinRmClient {
111116
private String winRmTimeout;
112117
private int winRmEnvelopSize;
113118
private String winRmLocale;
119+
private boolean clientCertificate;
114120
private WinrmHttpsCertificateTrustStrategy httpsCertTrustStrategy;
115121
private WinrmHttpsHostnameVerificationStrategy httpsHostnameVerifyStrategy;
116122
private boolean kerberosUseHttpSpn;
@@ -408,6 +414,12 @@ private Document doSendRequest(final Document requestDocument, final SoapAction
408414
final HttpContext context = new BasicHttpContext();
409415
final HttpPost request = new HttpPost(targetURL.toURI());
410416

417+
/* http://www.dmtf.org/sites/default/files/standards/documents/DSP0226_1.0.0.pdf
418+
* Web Services for Management (WS-Management) Specification, v1.0.0, page 119, section C.3.5 */
419+
if (clientCertificate) {
420+
request.setHeader("Authorization", "http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/https/mutual");
421+
}
422+
411423
if (soapAction != null) {
412424
request.setHeader("SOAPAction", soapAction.getValue());
413425
}
@@ -442,10 +454,12 @@ private Document doSendRequest(final Document requestDocument, final SoapAction
442454
}
443455
}
444456

445-
private void configureHttpClient(final DefaultHttpClient httpclient) throws GeneralSecurityException {
457+
private void configureHttpClient(final DefaultHttpClient httpclient) throws GeneralSecurityException, IOException {
446458
configureTrust(httpclient);
447459

448-
configureAuthentication(httpclient, BASIC, new BasicUserPrincipal(username));
460+
if (!clientCertificate) {
461+
configureAuthentication(httpclient, BASIC, new BasicUserPrincipal(username));
462+
}
449463

450464
if (enableKerberos) {
451465
String spnServiceClass = kerberosUseHttpSpn ? "HTTP" : "WSMAN";
@@ -463,15 +477,29 @@ private void configureHttpClient(final DefaultHttpClient httpclient) throws Gene
463477
}
464478

465479
private void configureTrust(final DefaultHttpClient httpclient) throws NoSuchAlgorithmException,
466-
KeyManagementException, KeyStoreException, UnrecoverableKeyException {
480+
KeyManagementException, KeyStoreException, UnrecoverableKeyException, CertificateException, IOException {
467481

468482
if (!"https".equalsIgnoreCase(targetURL.getProtocol())) {
469483
return;
470484
}
471485

472486
final TrustStrategy trustStrategy = httpsCertTrustStrategy.getStrategy();
473487
final X509HostnameVerifier hostnameVerifier = httpsHostnameVerifyStrategy.getVerifier();
474-
final SSLSocketFactory socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
488+
final SSLSocketFactory socketFactory;
489+
490+
if (clientCertificate) {
491+
KeyStore clientStore = KeyStore.getInstance("PKCS12");
492+
FileInputStream instream = new FileInputStream(new File(username));
493+
try {
494+
clientStore.load(instream, password.toCharArray());
495+
} finally {
496+
instream.close();
497+
}
498+
socketFactory = new SSLSocketFactory(null, clientStore, password, null, null, trustStrategy, hostnameVerifier);
499+
} else {
500+
socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
501+
}
502+
475503
final Scheme sch = new Scheme("https", 443, socketFactory);
476504
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
477505
}
@@ -577,6 +605,10 @@ public void setWinRmLocale(String locale) {
577605
this.winRmLocale = locale;
578606
}
579607

608+
public void setClientCertificate(boolean WinrmClientCertificate) {
609+
this.clientCertificate = WinrmClientCertificate;
610+
}
611+
580612
public void setHttpsCertTrustStrategy(WinrmHttpsCertificateTrustStrategy httpsCertTrustStrategy) {
581613
this.httpsCertTrustStrategy = httpsCertTrustStrategy;
582614
}

0 commit comments

Comments
 (0)