package ch.elexis.docbox.ws.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.Service;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.docbox.ws.cdachservicesv2.CDACHServicesV2;
public class WsClientUtil {
private static Logger logger = LoggerFactory.getLogger(WsClientUtil.class);
private static char[] hex = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
public final static String toHex(byte[] v){
String out = "";
for (int i = 0; i < v.length; i++)
out = out + hex[(v[i] >> 4) & 0xF] + hex[v[i] & 0xF];
return (out);
}
public static String getSHA1(String password){
if (password == null || "".equals(password)) {
return "";
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA");
md.update(password.getBytes("UTF-8"));
byte[] digest = md.digest();
return toHex(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
logger.error("Error", e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
logger.error("Error", e);
}
return "";
}
public static boolean checkAccess(CDACHServicesV2 port){
{
javax.xml.ws.Holder<java.lang.Boolean> _checkAccess_success =
new javax.xml.ws.Holder<java.lang.Boolean>();
javax.xml.ws.Holder<java.lang.String> _checkAccess_message =
new javax.xml.ws.Holder<java.lang.String>();
port.checkAccess(_checkAccess_success, _checkAccess_message);
logger.debug("checkAccess._checkAccess_success=" + _checkAccess_success.value);
logger.debug("checkAccess._checkAccess_message=" + _checkAccess_message.value);
return _checkAccess_success.value;
}
}
public static void addWsSecurityAndHttpConfigWithClientCert(Service ss, final String username,
final String password, final String p12, final String jks, final String passwordP12,
final String passwordJks){
String url = WsClientConfig.getDocboxServiceUrl();
final boolean clientcert = url.contains("ihe");
ss.setHandlerResolver(new HandlerResolver() {
@SuppressWarnings("rawtypes")
public List<Handler> getHandlerChain(PortInfo portInfo){
List<Handler> handlerList = new ArrayList<Handler>();
handlerList.add(new SecurityHandler(username, password, clientcert, p12, jks,
passwordP12, passwordJks));
return handlerList;
}
});
}
public static boolean isMedelexisCertAvailable(){
InputStream keyInputStream = null;
InputStream certInputStream = null;
try {
certInputStream =
WsClientUtil.class.getResourceAsStream("/cert/MedElexis_MedElexis.p12");
keyInputStream = WsClientUtil.class.getResourceAsStream("/cert/cert.key");
return certInputStream != null && keyInputStream != null;
} finally {
if (keyInputStream != null) {
try {
keyInputStream.close();
} catch (IOException e) {
// ignore
}
}
if (certInputStream != null) {
try {
certInputStream.close();
} catch (IOException e) {
// ignore
}
}
}
}
public static class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
private String username;
private String password;
private boolean clientcert;
private String p12;
private String jks;
private String passwordP12;
private String passwordJks;
public SecurityHandler(String username, String password, boolean clientcert, String p12,
String jks, String passwordP12, String passwordJks){
this.username = username;
this.password = password;
this.clientcert = clientcert;
this.p12 = p12;
this.jks = jks;
this.passwordP12 = passwordP12;
this.passwordJks = passwordJks;
}
public Set<QName> getHeaders(){
return new TreeSet<QName>();
}
public boolean handleMessage(SOAPMessageContext context){
Boolean outboundProperty =
(Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
if (clientcert) {
InputStream certInput = null;
try {
String trustpass = passwordJks;
TrustManager[] tm = null;
if (jks != null) {
KeyStore keyTrustStore = KeyStore.getInstance("JKS");
File truststore = new File(jks);
keyTrustStore.load(new FileInputStream(truststore),
trustpass.toCharArray());
TrustManagerFactory trustFactory =
TrustManagerFactory.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
trustFactory.init(keyTrustStore);
tm = trustFactory.getTrustManagers();
}
KeyStore keyStore = KeyStore.getInstance("PKCS12");
char[] certPass = getCertPass();
certInput = getCertInputStream();
keyStore.load(certInput, certPass);
KeyManagerFactory keyFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, certPass);
KeyManager[] km = keyFactory.getKeyManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(km, tm, null);
HttpsURLConnection
.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
} catch (KeyStoreException kse) {
logger.error("Security configuration failed with the following: "
+ kse.getCause());
} catch (KeyManagementException kse) {
logger.error("Security configuration failed with the following: "
+ kse.getCause());
} catch (NoSuchAlgorithmException nsa) {
logger.error("Security configuration failed with the following: "
+ nsa.getCause());
} catch (FileNotFoundException fnfe) {
logger.error("Security configuration failed with the following: "
+ fnfe.getCause());
} catch (UnrecoverableKeyException uke) {
logger.error("Security configuration failed with the following: "
+ uke.getCause());
} catch (CertificateException ce) {
logger.error("Security configuration failed with the following: "
+ ce.getCause());
} catch (IOException ioe) {
logger.error("Security configuration failed with the following: "
+ ioe.getCause());
} finally {
if (certInput != null) {
try {
certInput.close();
} catch (IOException e) {
// ignore
}
}
}
}
try {
SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
SOAPFactory factory = SOAPFactory.newInstance();
String prefix = "wsse";
String uri =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
SOAPElement securityElem = factory.createElement("Security", prefix, uri);
SOAPElement usernameTokenEl =
factory.createElement("UsernameToken", prefix, uri);
SOAPElement usernameEl = factory.createElement("Username", prefix, uri);
SOAPElement passwordEl = factory.createElement("Password", prefix, uri);
usernameEl.setTextContent(username);
passwordEl.setTextContent(password);
usernameTokenEl.addChildElement(usernameEl);
usernameTokenEl.addChildElement(passwordEl);
securityElem.addChildElement(usernameTokenEl);
SOAPHeader header = envelope.getHeader();
if (header == null) {
header = envelope.addHeader();
}
header.addChildElement(securityElem);
} catch (Exception e) {
logger.error("Exception in handler: " + e);
}
} else {
// inbound
}
return true;
}
private InputStream getCertInputStream(){
// look for cert from fragment
InputStream certInputStream =
WsClientUtil.class.getResourceAsStream("/cert/MedElexis_MedElexis.p12");
if (certInputStream != null) {
logger.info("Using fragment Cert.");
return certInputStream;
}
// look for configured cert
try {
File keystore = new File(p12);
logger.info("Using configured Cert.");
return new FileInputStream(keystore);
} catch (FileNotFoundException e) {
logger.warn("Could not load cert." + e);
}
return null;
}
private char[] getCertPass(){
// look for pass from fragment
InputStream keyInputStream = WsClientUtil.class.getResourceAsStream("/cert/cert.key");
if (keyInputStream != null) {
char[] chars = new char[1024];
InputStreamReader reader = new InputStreamReader(keyInputStream);
try {
int len = reader.read(chars);
byte[] decoded = Base64.decodeBase64(new String(chars, 0, len));
return new String(decoded, "UTF-8").toCharArray();
} catch (IOException e) {
logger.warn("Could not load cert." + e);
} finally {
try {
if (reader != null) {
reader.close();
}
if (keyInputStream != null) {
keyInputStream.close();
}
} catch (IOException e) {
// ignore
}
}
}
return passwordP12.toCharArray();
}
public boolean handleFault(SOAPMessageContext context){
return true;
}
public void close(MessageContext context){
//
}
}
}