У меня есть 2 Apache контейнера Karaf на одной машине Windows 10, которые должны иметь возможность общаться друг с другом через защищенное соединение через Apache XMLRP C 3.1.3. Мне уже удалось заставить это работать, используя незащищенное соединение, но в тот момент, когда я устанавливаю конфигурацию, связанную с TLS, происходит сбой со следующей ошибкой:
jar: beginEntry com/sun/crypto/provider/TlsMasterSecretGenerator.class
jar: Manifest Entry: com/sun/crypto/provider/TlsMasterSecretGenerator.class digest=SHA1
jar: manifest c81ee6f125affccd17cafa2072a3d60eb0933480
jar: computed c81ee6f125affccd17cafa2072a3d60eb0933480
jar:
Provider: KeyGenerator.SunTlsExtendedMasterSecret algorithm from: SunJCE
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
pool-92-thread-1, setSoTimeout(0) called
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1581323916 bytes = { 112, 252, 233, 36, 94, 119, 141, 89, 13, 246, 13, 115, 127, 90, 1, 124, 209, 37, 192, 7, 65, 154, 121, 224, 20, 87, 93, 30 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension extended_master_secret
***
[write] MD5 and SHA1 hashes: len = 193
0000: 01 00 00 BD 03 03 5E 41 17 8C 70 FC E9 24 5E 77 ......^A..p..$^w
0010: 8D 59 0D F6 0D 73 7F 5A 01 7C D1 25 C0 07 41 9A .Y...s.Z...%..A.
0020: 79 E0 14 57 5D 1E 00 00 56 C0 24 C0 28 00 3D C0 y..W]...V.$.(.=.
0030: 26 C0 2A 00 6B 00 6A C0 0A C0 14 00 35 C0 05 C0 &.*.k.j.....5...
0040: 0F 00 39 00 38 C0 23 C0 27 00 3C C0 25 C0 29 00 ..9.8.#.'.<.%.).
0050: 67 00 40 C0 09 C0 13 00 2F C0 04 C0 0E 00 33 00 g.@...../.....3.
0060: 32 C0 2C C0 2B C0 30 00 9D C0 2E C0 32 00 9F 00 2.,.+.0.....2...
0070: A3 C0 2F 00 9C C0 2D C0 31 00 9E 00 A2 00 FF 01 ../...-.1.......
0080: 00 00 3E 00 0A 00 16 00 14 00 17 00 18 00 19 00 ..>.............
0090: 09 00 0A 00 0B 00 0C 00 0D 00 0E 00 16 00 0B 00 ................
00A0: 02 01 00 00 0D 00 16 00 14 06 03 06 01 05 03 05 ................
00B0: 01 04 03 04 01 04 02 02 03 02 01 02 02 00 17 00 ................
00C0: 00 .
pool-92-thread-1, WRITE: TLSv1.2 Handshake, length = 193
[Raw write]: length = 198
0000: 16 03 03 00 C1 01 00 00 BD 03 03 5E 41 17 8C 70 ...........^A..p
0010: FC E9 24 5E 77 8D 59 0D F6 0D 73 7F 5A 01 7C D1 ..$^w.Y...s.Z...
0020: 25 C0 07 41 9A 79 E0 14 57 5D 1E 00 00 56 C0 24 %..A.y..W]...V.$
0030: C0 28 00 3D C0 26 C0 2A 00 6B 00 6A C0 0A C0 14 .(.=.&.*.k.j....
0040: 00 35 C0 05 C0 0F 00 39 00 38 C0 23 C0 27 00 3C .5.....9.8.#.'.<
0050: C0 25 C0 29 00 67 00 40 C0 09 C0 13 00 2F C0 04 .%.).g.@...../..
0060: C0 0E 00 33 00 32 C0 2C C0 2B C0 30 00 9D C0 2E ...3.2.,.+.0....
0070: C0 32 00 9F 00 A3 C0 2F 00 9C C0 2D C0 31 00 9E .2...../...-.1..
0080: 00 A2 00 FF 01 00 00 3E 00 0A 00 16 00 14 00 17 .......>........
0090: 00 18 00 19 00 09 00 0A 00 0B 00 0C 00 0D 00 0E ................
00A0: 00 16 00 0B 00 02 01 00 00 0D 00 16 00 14 06 03 ................
00B0: 06 01 05 03 05 01 04 03 04 01 04 02 02 03 02 01 ................
00C0: 02 02 00 17 00 00 ......
pool-92-thread-1, received EOFException: error
pool-92-thread-1, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
pool-92-thread-1, SEND TLSv1.2 ALERT: fatal, description = handshake_failure
pool-92-thread-1, WRITE: TLSv1.2 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 03 00 02 02 28 ......(
pool-92-thread-1, called closeSocket()
pool-92-thread-1, called close()
pool-92-thread-1, called closeInternal(true)
И клиент, и сервер используют та же самая Java 1.8.0.171 установка с разными JVM. Я создал самозаверяющий сертификат из отдельного хранилища ключей и настроил это хранилище ключей, используя следующие свойства, и добавил сертификат в файл Java cacerts:
java .protocol.handler.pkgs = javax . net .ssl security.provider = com.sun. net .ssl.internal.ssl.Provider
вариант протокола SSL (например, TLS, SSL v3 и др. c.)
security.protocol = TLSv1, TLSv1.1, TLSv1.2 javax. net .ssl.keyStore = E: / alm / ALM_HEAD / dev / system / ssl / server_keystore javax. net .ssl.keyStoreType = JKS javax. net .ssl.keyStorePassword = ********* javax. net .ssl.trustStore = E: / alm / ALM_HEAD / dev / system / ssl / server_keystore javax. net .ssl.trustStoreType = JKS javax. net .ssl.trustStorePassword = ********* sun.ssl.keymanager.type = SunX509 sun.ssl.trust.manager.type = SunX509
javax. net .debug = нет
javax. net .debug = все
java .security.debug = нет
java. security.debug = все
Когда я тогда go в Wireshark для анализа запроса и ответа от порта сервера, я получаю это:
запрос
Frame 14: 242 bytes on wire (1936 bits), 242 bytes captured (1936 bits) on interface \Device\NPF_Loopback, id 5
Null/Loopback
Internet Protocol Version 4, Src: 192.168.253.26, Dst: 192.168.253.26
Transmission Control Protocol, Src Port: 1092, Dst Port: 20021, Seq: 1, Ack: 1, Len: 198
Transport Layer Security
TLSv1.2 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.2 (0x0303)
Length: 193
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 189
Version: TLS 1.2 (0x0303)
Random: 5e4119ed69069f93d32c6efb00f8911dca14d37e4a20740b…
Session ID Length: 0
Cipher Suites Length: 86
Cipher Suites (43 suites)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 (0xc026)
Cipher Suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 (0xc02a)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 (0x006a)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA (0xc005)
Cipher Suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA (0xc00f)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 (0xc025)
Cipher Suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 (0xc029)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 (0x0040)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA (0xc004)
Cipher Suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA (0xc00e)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02e)
Cipher Suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 (0xc032)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
Cipher Suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 (0x00a3)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02d)
Cipher Suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 (0xc031)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
Cipher Suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 (0x00a2)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Compression Methods Length: 1
Compression Methods (1 method)
Compression Method: null (0)
Extensions Length: 62
Extension: supported_groups (len=22)
Type: supported_groups (10)
Length: 22
Supported Groups List Length: 20
Supported Groups (10 groups)
Supported Group: secp256r1 (0x0017)
Supported Group: secp384r1 (0x0018)
Supported Group: secp521r1 (0x0019)
Supported Group: sect283k1 (0x0009)
Supported Group: sect283r1 (0x000a)
Supported Group: sect409k1 (0x000b)
Supported Group: sect409r1 (0x000c)
Supported Group: sect571k1 (0x000d)
Supported Group: sect571r1 (0x000e)
Supported Group: secp256k1 (0x0016)
Extension: ec_point_formats (len=2)
Type: ec_point_formats (11)
Length: 2
EC point formats Length: 1
Elliptic curves point formats (1)
EC point format: uncompressed (0)
Extension: signature_algorithms (len=22)
Type: signature_algorithms (13)
Length: 22
Signature Hash Algorithms Length: 20
Signature Hash Algorithms (10 algorithms)
Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
Signature Algorithm: SHA256 DSA (0x0402)
Signature Algorithm: ecdsa_sha1 (0x0203)
Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
Signature Algorithm: SHA1 DSA (0x0202)
Extension: extended_master_secret (len=0)
Type: extended_master_secret (23)
Length: 0
ответ
Frame 18: 51 bytes on wire (408 bits), 51 bytes captured (408 bits) on interface \Device\NPF_Loopback, id 5
Null/Loopback
Internet Protocol Version 4, Src: 192.168.253.26, Dst: 192.168.253.26
Transmission Control Protocol, Src Port: 1092, Dst Port: 20021, Seq: 199, Ack: 2, Len: 7
Transport Layer Security
TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
Content Type: Alert (21)
Version: TLS 1.2 (0x0303)
Length: 2
Alert Message
Level: Fatal (2)
Description: Handshake Failure (40)
Я не уверен, что это идет не так здесь. Я не думаю, что это проблема с сертификатом, потому что у меня уже были разные ошибки, связанные с сертификатом TLS, когда я приводил его в порядок. И было бы странно, если бы 2 установки XMLRP C с использованием JVM, запущенных с той же версии Java, не имели бы алгоритмов общей подписи или наборов шифров.
В случае, если это уместно, это мой исходный код для сервер:
/**
* Creates a XML-RPC web server at the specified port number.
*
* @param port
* the port number
* @param securityHandler
* a optional security handler, which allows to check whether a
* user is authorized to call a service method
* @param secure
* should the server use the secure https protocol for
* communications
*/
public XmlRpcWebServer(int port, SecurityHandler securityHandler, boolean secure) {
this.securityHandler = securityHandler;
if (secure) {
InputStream inputStream = null;
try {
// if secure: load poperties and set as a system property.
Properties props = new Properties();
String xmlRpcPropertyFile = System.getProperty(XML_RPC_PROPERTIES_PATH);
if (xmlRpcPropertyFile==null) {
//com.ikanalm.xmlrpc.secure.cfg property not set, load the xml_rpc.properties from classpath
xmlRpcPropertyFile=XML_RPC_PROPERTY_FILE;
inputStream = Loader.getResourceAsStream(xmlRpcPropertyFile, this.getClass());
} else {
//com.ikanalm.xmlrpc.secure.cfg property set, load the xml_rpc.properties from absolute path
String xmlRpcPropertiesPath = new File(".").getCanonicalPath()+File.separator+ xmlRpcPropertyFile;
//System.out.println("Trying to load database configuration from : "+xmlRpcPropertiesPath);
inputStream = FileUtils.openInputStream(new File(xmlRpcPropertiesPath));
}
// Load the properties
props.load(inputStream);
// Set system properties:
System.setProperty("javax.net.debug", props.getProperty("javax.net.debug"));
System.setProperty("java.security.debug", props.getProperty("java.security.debug"));
System.setProperty("jsse.enableSNIExtension", "true");
} catch (IOException ioe) {
throw new InvocatorException("Xml-rpc.properties file for secure xml-rpc communication can not be found.", ioe);
} catch (MissingResourceException mre) {
throw new InvocatorException("Xml-rpc.properties file for secure xml-rpc communication can not be found.", mre);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (final IOException ioe) {
// ignore
}
}
}
try {
LIB4JHandlerMapping lib4jhm = new LIB4JHandlerMapping();
lib4jhm.setVoidMethodEnabled(true);
lib4jhm.setTypeConverterFactory(new LIB4JTypeConverterFactoryImpl());
servlet = new XmlRpcServlet() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException {
LIB4JHandlerMapping lib4jhm = new LIB4JHandlerMapping();
lib4jhm.setVoidMethodEnabled(true);
lib4jhm.setTypeConverterFactory(new LIB4JTypeConverterFactoryImpl());
return lib4jhm;
}
};
webServer = new WebServer(servlet, port); // WebServer is just an extends org.apache.xmlrpc.webserver.ServletWebServer
webServer.setParanoid(false);
XmlRpcServerConfigImpl pConfig = new XmlRpcServerConfigImpl();
pConfig.setEnabledForExtensions(true);
servlet.getXmlRpcServletServer().setConfig(pConfig );
} catch (ServletException e) {
// TODO Auto-generated catch block
throw new InvocatorException("Exception while setting up XmlRpcWebServer.", e);
}
}
/**
* Registers a service. Methods of this object will be callable
* over XML-RPC as "interfaceName.method".
*
* @param ifType the interface type of the service
* @param impl instance of a class which implements the specified service interface
* @throws XmlRpcException
*/
public void registerService(Class<?> ifType, Object impl) {
registerHandlerTypes(ifType);
try {
((LIB4JHandlerMapping)servlet.getXmlRpcServletServer().getHandlerMapping()).addHandler(ifType.getName(), ifType, new Handler(ifType, impl, securityHandler));
} catch (XmlRpcException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Register handler types for the method.
* @param ifType
*/
private void registerHandlerTypes(Class<?> ifType) {
Method[] typeMethods = ifType.getMethods();
for (Method method : typeMethods) {
for (Class<?> clazz : method.getParameterTypes()) {
LIB4JTypeConverterFactoryImpl.registerType(clazz);
}
}
}
и для клиента:
/**
* Constructor.
*
* @param host the host name
* @param port the port number
* @param user the user id
* @param password the password
* @param secure should the client use the secure https protocol for communications
* @param ifType the interface type of the service
**/
private Invocator(String host, int port, String user, String password, boolean secured, Class<?> ifType) {
// Set instance variables
this.ifType = ifType;
// Get a reference to a xml-rpc client
InputStream inputStream = null;
try {
if (secured) {
// if secure: load poperties and set as a system property.
Properties props = new Properties();
String xmlRpcPropertyFile = System.getProperty(XmlRpcWebServer.XML_RPC_PROPERTIES_PATH);
if (xmlRpcPropertyFile == null) {
//com.ikanalm.xmlrpc.secure.cfg property not set, load the xml_rpc.properties from classpath
xmlRpcPropertyFile = XmlRpcWebServer.XML_RPC_PROPERTY_FILE;
inputStream = Loader.getResourceAsStream(xmlRpcPropertyFile, this.getClass());
} else {
//com.ikanalm.xmlrpc.secure.cfg property set, load the xml_rpc.properties from absolute path
String xmlRpcPropertiesPath = new File(".").getCanonicalPath() +File.separator + xmlRpcPropertyFile;
//System.out.println("Trying to load database configuration from : "+ xmlRpcPropertiesPath);
inputStream = FileUtils.openInputStream(new File(xmlRpcPropertiesPath));
}
// Load the properties
props.load(inputStream);
// set hostNameVerifier (otherwise error "HTTPS hostname wrong:...")
setHostNameVerifier();
}
XmlRpcClientConfigImpl clientConfig = new XmlRpcClientConfigImpl();
clientConfig.setBasicUserName(user);
clientConfig.setBasicPassword(password);
clientConfig.setServerURL(new URL(secured? "https": "http", host, port, ""));
clientConfig.setEnabledForExtensions(true); // needed to allow more serialization
client = new XmlRpcClient();
client.setConfig(clientConfig);
} catch (MalformedURLException murle) {
throw new InvocatorException(murle);
} catch (IOException ioe) {
throw new InvocatorException("Xml-rpc.properties file for secure xml-rpc communication can not be found.", ioe);
} catch (MissingResourceException mre) {
throw new InvocatorException("Xml-rpc.properties file for secure xml-rpc communication can not be found.", mre);
}catch(Exception e) {
throw new InvocatorException("Error while starting the client", e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (final IOException ioe) {
// ignore
}
}
}
/**
* Returns a proxy which will use this invocationhandler to call a remote
* XML-RPC service, which implements the specified service interface.
*
* @param host the host name
* @param port the port number
* @param user the user id
* @param password the password
* @param secure value true if the server has to use the secure https protocol for communications
* @param ifType the interface type of the service
* @return a Proxy which implements the specified service interface
*/
public static Object getServiceProxy(String host, int port, String user, String password, boolean secured, Class<?> ifType) {
return Proxy.newProxyInstance(Invocator.class.getClassLoader(), new Class[] { ifType }, new Invocator(host, port, user, password, secured, ifType));
}
/**
* @see java.lang.reflect.InvocationHandler#invoke
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Convert the arguments from Java type to XML-RPC type
Vector<Object> params = null;
if (args != null) {
params = new Vector<Object>();
for (int i = 0; i < args.length; i++) {
params.add(ValueConverter.convertFromJavaType(args[i]));
}
}
// The vector holding the parameters must not be null
else {
params = new Vector<Object>();
}
try {
// Execute method
Object ret = client.execute(ifType.getName() + '.' + method.getName(), params);
// Convert the returnValue from XML-RPC type to Java type
Class<?> retType = method.getReturnType();
return ValueConverter.convertToJavaType(ret, retType);
}
catch (XmlRpcException xre) {
handleXmlRpcException(xre);
return null;
}
}
/**
* Utility method which tries to convert the XmlRpcExcepion to the
* exception which caused the XmlRpcException.
*
* @throws Throwable the cause exception or a InvocatorException if the conversion did not succeed
*/
private void handleXmlRpcException(XmlRpcException xre) throws Throwable {
// The cause of the XmlRpcException
Throwable cause;
try {
// The message contains the cause of the exception and the related message
// Ex. message = 'Cause Exception : Cause message'
String xreMessage = xre.getMessage();
String[] tmp = xre.getMessage().split(":");
String causeException = tmp[0];
String causeMessage = xreMessage.substring(xreMessage.indexOf(":") + 1).trim();
// Re-construct the exception which caused the XmlRpcException
Class<?> causeExceptionClazz = this.getClass().getClassLoader().loadClass(causeException);
Constructor<?> constructor = causeExceptionClazz.getConstructor(new Class[] { String.class });
cause = (Throwable) constructor.newInstance(new Object[] { causeMessage });
}
// Wrap the XmlRpcException in a InvocatorException if the original exception can't be re-constructed
catch (Throwable t) {
throw new InvocatorException(xre);
}
// Throw the cause of the XmlRpcException
throw cause;
}
/**
* Sets the hostname verifier.
* (ommit a bug...)
*/
private static void setHostNameVerifier() {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
//System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}