Hi, The problem I reached is quite specific. I've searched Internet for any hint but without success. So I would like to ask you for any pointers.
I have two tomcat servers "A" and "B": A - tomcat 7.0.41 (local machine Linux Mint 15) B - tomcat 7.0.42 (Ubuntu 12.04.2 on AWS EC2) ************************************************************************************************************************ In B I have defined REST service: web.xml: ... <servlet> <servlet-name>service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.systemincloud.machine.connector.service.cmd</param-value> </init-param> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.systemincloud.machine.connector.service.Service</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>service</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping> server.xml: <Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" ciphers="SSL_RSA_WITH_RC4_128_SHA" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" keystorePass="******" truststoreFile="../.truststore" truststorePass="******"/> The first REST request to B is coming from server A. I am using jersey-client-2.0.jar: public String newInstance(String dns, String fileName, InputStream file, Map<String, String> parameters) { WebTarget service = getService(dns); FormDataMultiPart multiPart = new FormDataMultiPart(); multiPart.field("fileName", fileName); multiPart.bodyPart(new FormDataBodyPart("model", file, MediaType.APPLICATION_OCTET_STREAM_TYPE)); Form f = new Form(new MultivaluedHashMap<String, String>(parameters)); multiPart.field("parameters", f, MediaType.APPLICATION_FORM_URLENCODED_TYPE); NewInstanceResponse response = service.path(PATH).path("newInstance").request(MediaType.APPLICATION_JSON).post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE), NewInstanceResponse.class); return response.getSystemInstanceId(); } In InputStream I have a file (jar) from local hardrive. And I have no problems with such a configuration and application work as expected. In wireshark I get: After a lot of: 5173 77.673830000 192.168.30.144 54.229.*.* TCP 1514 [TCP segment of a reassembled PDU] I get (however only this POST wireshark is not decrypting): 52215 110.765747000 54.229.*.* 192.168.30.144 HTTP 312 HTTP/1.1 200 OK (application/json) **************************************************************************************************************************** Problem starts when I configure ssl client authentication for REST service: web.xml ... <security-constraint> <web-resource-collection> <web-resource-name>Service Api</web-resource-name> <url-pattern>/service/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>sic-service</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>CLIENT-CERT</auth-method> <realm-name>Service Api</realm-name> </login-config> <security-role> <role-name>sic-service</role-name> </security-role> ... tomcat-users.xml: ... <role rolename="sic-service"/> <role rolename="manager-script"/> <user username="CN=*.*.*.*, OU=System in Cloud, O=System in Cloud, L=Cracow, ST=Malopolskie, C=PL" password="null" roles="sic-service"/> ... In server A I have: X509KeyManager dkms = null; try { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream(new File(keystore_path)), keystore_password.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE"); kmf.init(ks, keystore_password.toCharArray()); KeyManager kms[] = kmf.getKeyManagers(); for (int i = 0; i < kms.length; i++) { if (kms[i] instanceof X509KeyManager) dkms = (X509KeyManager) kms[i]; } } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException| IOException | NoSuchProviderException | UnrecoverableKeyException e1) { e1.printStackTrace(); } KeyManager defaultKms[] = new KeyManager[] { dkms }; TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers(){return null;} public void checkClientTrusted(X509Certificate[] certs, String authType){} public void checkServerTrusted(X509Certificate[] certs, String authType){} }}; SSLContext sc = null; try { sc = SSLContext.getInstance("TLS"); sc.init(defaultKms, trustAllCerts, new SecureRandom()); } catch (Exception e) { e.printStackTrace(); } client = ClientBuilder.newBuilder() .withConfig(config) .hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }) .sslContext(sc) .build(); I tested authetication with WizTools REST Client 3.2. however with REST requests without multipart form. Now. When I run above application on server A In wireshark I have: around only 40 439 15.718628000 192.168.30.144 54.229.101.121 TCP 1514 [TCP segment of a reassembled PDU] then 7 times 475 15.808478000 192.168.30.144 54.229.101.121 TLSv1 1514 Ignored Unknown Record then 486 15.835327000 54.229.101.121 192.168.30.144 HTTP 1282 HTTP/1.1 401 Unauthorized (text/html) 487 15.851888000 54.229.101.121 192.168.30.144 HTTP 235 HTTP/1.1 400 Bad Request And there is one re-transmission of whole communication (with Key Exchange) with the same result. In server A, I have error: SEVERE: Servlet.service() for servlet [API] in context with path [] threw exception [javax.ws.rs.ProcessingException: java.io.IOException: Error writing to server] with root cause java.io.IOException: Error writing to server at sun.net.www.protocol.http.HttpURLConnection.writeRequests(HttpURLConnection.java:625) at sun.net.www.protocol.http.HttpURLConnection.writeRequests(HttpURLConnection.java:637) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1320) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338) at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:293) at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:200) at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:215) at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:650) at org.glassfish.jersey.internal.Errors.process(Errors.java:315) at org.glassfish.jersey.internal.Errors.process(Errors.java:297) at org.glassfish.jersey.internal.Errors.process(Errors.java:228) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:421) at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:646) at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:402) at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:305) at com.systemincloud.service.cmd.MachineClient.newInstance(MachineClient.java:117) at com.systemincloud.service.cmd.NewInstanceExecutor.execute(NewInstanceExecutor.java:28) at com.systemincloud.service.connector.cmd.NewInstanceCmd.post(NewInstanceCmd.java:25) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ... In server B I have: catalina.out: ... Aug 21, 2013 1:28:37 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 10522 ms Aug 21, 2013 1:29:38 PM org.apache.coyote.http11.AbstractHttp11Processor process INFO: Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. localhost.2013-08-21.log Aug 21, 2013 1:28:34 PM org.apache.catalina.core.StandardContext listenerStart FINE: Sending application start events Aug 21, 2013 1:28:34 PM org.apache.catalina.core.StandardContext filterStart FINE: Starting filters Aug 21, 2013 1:29:38 PM org.apache.catalina.authenticator.SSLAuthenticator authenticate FINE: Looking up certificates Aug 21, 2013 1:29:38 PM org.apache.catalina.authenticator.SSLAuthenticator authenticate FINE: Looking up certificates localhost_access_log.2013-08-21.txt: 91.198.177.112 - - [21/Aug/2013:13:29:38 +0000] "POST /service/newInstance HTTP/1.1" 401 1037 91.198.177.112 - - [21/Aug/2013:13:29:38 +0000] "?? )????>H??^Tj??)c??^S??\%^R?????*??;,? ^D0(? ^DsE??+?^NlZF2^L?Bk?" 400 - 91.198.177.112 - - [21/Aug/2013:13:29:38 +0000] "POST /service/newInstance HTTP/1.1" 401 1037 91.198.177.112 - - [21/Aug/2013:13:29:38 +0000] "?? )????>H??^Tj??)c??^S??\%^R?????*??;,? ^D0(? ^DsE??+?^NlZF2^L?Bk?" 400 - ********************************************************************************** Other observations: + Non multipart requests work with no problems. + problems do not depend on type of file content (tried txt, jar), name or size (tried from 800kB to 50 MB); + If just before multipart request I do simple request: WebTarget service = getService(dns); service.path(PATH).path("newToken").request(MediaType.APPLICATION_JSON) .post(Entity.entity(new NewTokenRequest(token), MediaType.APPLICATION_JSON), NewTokenResponse.class); the next multipart request is correctly received on server B. And this is for me a workaround for today. My knowledge of SSL is basic so I still haven't done deeper analyse in protocol. Can you give me some directions what can I try to solve my problem. Thank you, Marek -- Marek Jagielski +48 513 402 596