Skip to content

Commit

Permalink
add client certificate authentication support
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Veznaver committed Apr 29, 2015
1 parent 075f230 commit e6be858
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,18 @@ public class CifsConnectionBuilder implements OverthereConnectionBuilder {
*/
public static final String WINRM_LOCALE_DEFAULT = "en-US";

/**
* Set to true for mutual HTTPS authentication
*/

public static final String WINRM_CLIENT_CERTIFICATE = "winrmClientCertificate";

/**
* Default value for HTTPS mutual authentication
*/

public static final boolean WINRM_CLIENT_CERTIFICATE_DEFAULT = false;

/**
* See <a href="https://github.com/xebialabs/overthere/blob/master/README.md#cifs_winrmKerberosUseHttpSpn">the online documentation</a>
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_CONTEXT_DEFAULT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_ENABLE_HTTPS_DEFAULT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_ENVELOP_SIZE_DEFAULT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_CLIENT_CERTIFICATE;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_CLIENT_CERTIFICATE_DEFAULT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY_DEFAULT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY_DEFAULT;
import static com.xebialabs.overthere.cifs.CifsConnectionBuilder.WINRM_KERBEROS_ADD_PORT_TO_SPN_DEFAULT;
Expand Down Expand Up @@ -245,6 +247,7 @@ private WinRmClient createWinrmClient() {
client.setWinRmTimeout(options.get(WINRM_TIMEMOUT, DEFAULT_WINRM_TIMEOUT));
client.setWinRmEnvelopSize(options.get(WINRM_ENVELOP_SIZE, WINRM_ENVELOP_SIZE_DEFAULT));
client.setWinRmLocale(options.get(WINRM_LOCALE, WINRM_LOCALE_DEFAULT));
client.setClientCertificate(options.getBoolean(WINRM_CLIENT_CERTIFICATE, WINRM_CLIENT_CERTIFICATE_DEFAULT));
client.setHttpsCertTrustStrategy(options.getEnum(WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY, WinrmHttpsCertificateTrustStrategy.class, WINRM_HTTPS_CERTIFICATE_TRUST_STRATEGY_DEFAULT));
client.setHttpsHostnameVerifyStrategy(options.getEnum(WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY, WinrmHttpsHostnameVerificationStrategy.class, WINRM_HTTPS_HOSTNAME_VERIFICATION_STRATEGY_DEFAULT));
client.setKerberosUseHttpSpn(options.getBoolean(WINRM_KERBEROS_USE_HTTP_SPN, WINRM_KERBEROS_USE_HTTP_SPN_DEFAULT));
Expand Down
40 changes: 36 additions & 4 deletions src/main/java/com/xebialabs/overthere/cifs/winrm/WinRmClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
package com.xebialabs.overthere.cifs.winrm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
Expand All @@ -35,12 +38,14 @@
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -111,6 +116,7 @@ public class WinRmClient {
private String winRmTimeout;
private int winRmEnvelopSize;
private String winRmLocale;
private boolean clientCertificate;
private WinrmHttpsCertificateTrustStrategy httpsCertTrustStrategy;
private WinrmHttpsHostnameVerificationStrategy httpsHostnameVerifyStrategy;
private boolean kerberosUseHttpSpn;
Expand Down Expand Up @@ -408,6 +414,12 @@ private Document doSendRequest(final Document requestDocument, final SoapAction
final HttpContext context = new BasicHttpContext();
final HttpPost request = new HttpPost(targetURL.toURI());

/* http://www.dmtf.org/sites/default/files/standards/documents/DSP0226_1.0.0.pdf
* Web Services for Management (WS-Management) Specification, v1.0.0, page 119, section C.3.5 */
if (clientCertificate) {
request.setHeader("Authorization", "http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/https/mutual");
}

if (soapAction != null) {
request.setHeader("SOAPAction", soapAction.getValue());
}
Expand Down Expand Up @@ -442,10 +454,12 @@ private Document doSendRequest(final Document requestDocument, final SoapAction
}
}

private void configureHttpClient(final DefaultHttpClient httpclient) throws GeneralSecurityException {
private void configureHttpClient(final DefaultHttpClient httpclient) throws GeneralSecurityException, IOException {
configureTrust(httpclient);

configureAuthentication(httpclient, BASIC, new BasicUserPrincipal(username));
if (!clientCertificate) {
configureAuthentication(httpclient, BASIC, new BasicUserPrincipal(username));
}

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

private void configureTrust(final DefaultHttpClient httpclient) throws NoSuchAlgorithmException,
KeyManagementException, KeyStoreException, UnrecoverableKeyException {
KeyManagementException, KeyStoreException, UnrecoverableKeyException, CertificateException, IOException {

if (!"https".equalsIgnoreCase(targetURL.getProtocol())) {
return;
}

final TrustStrategy trustStrategy = httpsCertTrustStrategy.getStrategy();
final X509HostnameVerifier hostnameVerifier = httpsHostnameVerifyStrategy.getVerifier();
final SSLSocketFactory socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
final SSLSocketFactory socketFactory;

if (clientCertificate) {
KeyStore clientStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(username));
try {
clientStore.load(instream, password.toCharArray());
} finally {
instream.close();
}
socketFactory = new SSLSocketFactory(null, clientStore, password, null, null, trustStrategy, hostnameVerifier);
} else {
socketFactory = new SSLSocketFactory(trustStrategy, hostnameVerifier);
}

final Scheme sch = new Scheme("https", 443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
}
Expand Down Expand Up @@ -577,6 +605,10 @@ public void setWinRmLocale(String locale) {
this.winRmLocale = locale;
}

public void setClientCertificate(boolean WinrmClientCertificate) {
this.clientCertificate = WinrmClientCertificate;
}

public void setHttpsCertTrustStrategy(WinrmHttpsCertificateTrustStrategy httpsCertTrustStrategy) {
this.httpsCertTrustStrategy = httpsCertTrustStrategy;
}
Expand Down

0 comments on commit e6be858

Please sign in to comment.