[jboss-user] [Remoting] - Re: Problem using JaxWS over HTTPS connection from within a

ron.sigal@jboss.com do-not-reply at jboss.com
Wed Feb 4 23:25:11 EST 2009


Hi Andrew,

Well, here's a paragraph from the class javadoc for sun.net.www.protocol.https.HttpsClient:


  |  *      <LI>It does basic server authentication, to protect
  |  *      against "URL spoofing" attacks.  This involves deciding
  |  *      whether the X.509 certificate chain identifying the server
  |  *      is trusted, and verifying that the name of the server is
  |  *      found in the certificate.  (The application may enable an
  |  *      anonymous SSL cipher suite, and such checks are not done
  |  *      for anonymous ciphers.)
  | 

and here's the code for sun.net.www.protocol.https.HttpsClient.checkURLSpoofing() from openjdk:


  |     // Server identity checking is done according to RFC 2818: HTTP over TLS
  |     // Section 3.1 Server Identity
  |     private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
  |             throws IOException
  |     {
  |         //
  |         // Get authenticated server name, if any
  |         //
  |         boolean done = false;
  |         String host = url.getHost();
  | 
  |         // if IPv6 strip off the "[]"
  |         if (host != null && host.startsWith("[") && host.endsWith("]")) {
  |             host = host.substring(1, host.length()-1);
  |         }
  | 
  |         Certificate[] peerCerts = null;
  |         try {
  |             HostnameChecker checker = HostnameChecker.getInstance(
  |                                                 HostnameChecker.TYPE_TLS);
  | 
  |             Principal principal = getPeerPrincipal();
  |             if (principal instanceof KerberosPrincipal) {
  |                 if (!checker.match(host, (KerberosPrincipal)principal)) {
  |                     throw new SSLPeerUnverifiedException("Hostname checker" +
  |                                 " failed for Kerberos");
  |                 }
  |             } else {
  |                 // get the subject's certificate
  |                 peerCerts = session.getPeerCertificates();
  | 
  |                 X509Certificate peerCert;
  |                 if (peerCerts[0] instanceof
  |                         java.security.cert.X509Certificate) {
  |                     peerCert = (java.security.cert.X509Certificate)peerCerts[0];
  |                 } else {
  |                     throw new SSLPeerUnverifiedException("");
  |                 }
  |                 checker.match(host, peerCert);
  |             }
  | 
  |             // if it doesn't throw an exception, we passed. Return.
  |             return;
  | 
  |         } catch (SSLPeerUnverifiedException e) {
  | 
  |             //
  |             // client explicitly changed default policy and enabled
  |             // anonymous ciphers; we can't check the standard policy
  |             //
  |             // ignore
  |         } catch (java.security.cert.CertificateException cpe) {
  |             // ignore
  |         }
  | 
  |         String cipher = session.getCipherSuite();
  |         if ((cipher != null) && (cipher.indexOf("_anon_") != -1)) {
  |             return;
  |         } else if ((hostnameVerifier != null) &&
  |                    (hostnameVerifier.verify(host, session))) {
  |             return;
  |         }
  | 
  |         serverSocket.close();
  |         session.invalidate();
  | 
  |         throw new IOException("HTTPS hostname wrong:  should be <"
  |                               + url.getHost() + ">");
  |     }
  | 

So it looks like the call to sun.security.util.HostnameChecker.match(host, peerCert) is failing, and there's no HostnameVerifier to save the day.  The javadoc for HostnameVerifier.matchIP(), which is called when the host name looks like an IP address, says


  |     /**
  |      * Check if the certificate allows use of the given IP address.
  |      *
  |      * From RFC2818:
  |      * In some cases, the URI is specified as an IP address rather than a
  |      * hostname. In this case, the iPAddress subjectAltName must be present
  |      * in the certificate and must exactly match the IP in the URI.
  |      */
  | 

On the other hand, when the host name doesn't look like an IP address, the method HostnameChecker.matchDNS() is called, the javadoc for which says


  |     /**
  |      * Check if the certificate allows use of the given DNS name.
  |      *
  |      * From RFC2818:
  |      * If a subjectAltName extension of type dNSName is present, that MUST
  |      * be used as the identity. Otherwise, the (most specific) Common Name
  |      * field in the Subject field of the certificate MUST be used. Although
  |      * the use of the Common Name is existing practice, it is deprecated and
  |      * Certification Authorities are encouraged to use the dNSName instead.
  |      *
  |      * Matching is performed using the matching rules specified by
  |      * [RFC2459].  If more than one identity of a given type is present in
  |      * the certificate (e.g., more than one dNSName name, a match in any one
  |      * of the set is considered acceptable.)
  |      */
  | 

Well, here's a guess.  If the host name looks like an IP address, the certificate must have that address in a subjAltNames extension.  It looks like you can do that with openssl but not keytool.  That might be one solution.

Or, alternatively, try "localhost" instead of 127.0.0.1.

Or, for a nasty workaround, you can tell HTTPSClientInvoker to use a HostnameVerifier that accepts any name.  To do that, add the parameter "org.jboss.security.ignoreHttpsHost", set to "true", when you set up the Remoting client.  I'm not sure how you're doing that, but if you're creating an org.jboss.remoting.Client, you can pass a configuration map to the constructor.

Making it up as I go,
Ron

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4207200#4207200

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4207200



More information about the jboss-user mailing list