8 Replies Latest reply on Jun 6, 2006 8:49 AM by nuno oliveira

    clientAuth=true disables BASIC AUTH

    nuno oliveira Newbie

      I configured the server.xml file in tomcat inside jboss4.0.3sp1 with both keystore and truststore, respective pswds, and clientAuth="true". This enables dual ssl. However, it disables basic auth from any clients towards other web apps that don't require cert based auth. I was expecting that different webapps, running in different security domains, with diferent <auth-method>values (BASIC versus CLIENT-CERT) would be enough for the app server to know when to negociate client cert or not. Apparently it doesn't work like that.

      I'm already used to not get many answers from this forum. Never know if my questions are to basic or to complex. Even so, I believe that this scenario should be common enough to work. However, if it's not supposed to work like that after all, I need to setup my different web apps in different tomcat connectors with different ssl cfgs. This step I don't know how to do, so if someone has any hints on any of these topics I would as always welcome them. Sincerely hope anyone can help me with this. No point in redirecting me to http://www.jboss.org/wiki/Wiki.jsp?page=SSLSetup either. Been there, done that :)

      Thanks

        • 1. Re: clientAuth=true disables BASIC AUTH
          chris griffith Expert

          I may be way off base here, but I am not seeing the connection. I was under the impression (as having never had to configure this myself), that enabling the SSL/TSL connector in Tomcat does not have anything to do with the authentication method used by an web application. And that such configuration is only used to allow the container to provide a encrypted (i.e. SSL) transport for the data being sent.

          Are you expecting otherwise? Do you agree with this, but are seeing unexpected behavior? I hope to dispell your notion of never getting any usefull help on this forum.

          cgriffith

          • 2. Re: clientAuth=true disables BASIC AUTH
            nuno oliveira Newbie

            Thank you very much for your answer :)

            You are correct, but the connector not only allows you to enable server side auth via ssl negotiation, it also allows you to enable client side auth. In fact, there's no point in setting your web app auth-method to CLIENT-CERT unless the connector is enabled for that via clientAuth="true". My point is that once you set this up, all the other webapps that were getting by with BASIC AUTH thru an encrypted , server-only authenticated channel stop working, which seems weird. That's why I mentioned probably having to attach these different web apps to different connectors, so that I could configure one with clientAuth="true" and another with clientAuth="false". Seems a litle far-fetched but if it works it will be better than what I have now which is nothing :(.
            My second problem is I don't know if it is even possible to set this up either.

            Once again, thank you very much for your help. Even though my problem remains, your answer gives me hope that there's more people out there also willing to share their experience on this issue.

            • 3. Re: clientAuth=true disables BASIC AUTH
              chris griffith Expert

              Again, I am going to have to disagree with you. I am no expert so I am just putting this out there for discussion. Your statement...

              but the connector not only allows you to enable server side auth via ssl negotiation, it also allows you to enable client side auth.


              confuses a client with a user of an application. SSL is a transport layer protocol. SSL configured to check certificates (on one side or both) is just a way to provide trust. Trust that your server knows the client and trust that the client knows the server. Not that the server knows the user using the client.

              However, this does not deal with your original problem of

              This enables dual ssl. However, it disables basic auth from any clients towards other web apps that don't require cert based auth.


              So what happens with an application that is configured to use BASIC authentication?
              Also, if you have evidence to show my arguments are incorrect, please let me know.

              later, cgriffith

              • 4. Re: clientAuth=true disables BASIC AUTH
                nuno oliveira Newbie

                Hello, thanks for you feedback.

                Regarding your argument, if I'm not mistaken, there is no distintion bewteen user and client in the servlet spec, so the fact that one web app requiring client certificates forces other clients from other web apps running in completely diferent security domains to also present certificates seems to be non-compliant with the spec.
                A litle more pragramtically, despite the validity of the theoretic argument, I would like to know if it is so by design in JBoss or due to some misconfiguration on my part.

                My original problem happened with webservices, but I setup a small servlet app to ilustrate it. Here is what it looks like:

                the servlet
                ------------------------------------------------

                package sslservlet;

                import java.io.IOException;
                import java.io.PrintWriter;

                import javax.servlet.ServletException;
                import javax.servlet.http.HttpServlet;
                import javax.servlet.http.HttpServletRequest;
                import javax.servlet.http.HttpServletResponse;

                public class MyServlet extends HttpServlet
                {
                public void doPost(HttpServletRequest request,
                HttpServletResponse response)
                throws ServletException, IOException
                {
                this.doGet(request, response);
                }

                public void doGet(HttpServletRequest request,
                HttpServletResponse response)
                throws ServletException, IOException
                {
                PrintWriter out = response.getWriter();

                try{
                out.println("ola");

                }catch(Throwable e)
                {
                e.printStackTrace();
                }
                }
                }


                web.xml
                ------------------------------------------------

                <?xml version="1.0" encoding="UTF-8"?>
                <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
                version="2.4">


                <servlet-name>MyServlet</servlet-name>
                <servlet-class>sslservlet.MyServlet</servlet-class>


                <servlet-mapping>
                <servlet-name>MyServlet</servlet-name>
                <url-pattern>/myservlet</url-pattern>
                </servlet-mapping>

                <security-constraint>
                <web-resource-collection>
                <web-resource-name>MyServlet</web-resource-name>
                <url-pattern>/*</url-pattern>
                </web-resource-collection>
                <auth-constraint>
                <role-name>*</role-name>
                </auth-constraint>
                <user-data-constraint>
                <transport-guarantee>CONFIDENTIAL</transport-guarantee>
                </user-data-constraint>
                </security-constraint>

                <login-config>
                <auth-method>BASIC</auth-method>
                </login-config>

                </web-app>


                the excerpt of the server.xml file
                ------------------------------------------------



                the keystore (localhost.ks)
                ------------------------------------------------

                Keystore type: jks
                Keystore provider: SUN

                Your keystore contains 2 entries

                Alias name: trut
                Creation date: 6/Jun/2006
                Entry type: trustedCertEntry

                Owner: CN=localhost
                Issuer: CN=localhost
                Serial number: 4485527a
                Valid from: Tue Jun 06 11:01:30 BST 2006 until: Mon Sep 04 11:01:30 BST 2006
                Certificate fingerprints:
                MD5: 99:B2:EF:4D:F0:1C:5F:22:4B:0B:2B:82:33:6A:AF:BA
                SHA1: 7B:24:F3:83:4F:08:0A:1B:FC:97:1E:8B:F9:8D:D1:82:00:CF:D7:B6


                *******************************************
                *******************************************


                Alias name: mykey
                Creation date: 6/Jun/2006
                Entry type: keyEntry
                Certificate chain length: 1
                Certificate[1]:
                Owner: CN=localhost
                Issuer: CN=localhost
                Serial number: 4485527a
                Valid from: Tue Jun 06 11:01:30 BST 2006 until: Mon Sep 04 11:01:30 BST 2006
                Certificate fingerprints:
                MD5: 99:B2:EF:4D:F0:1C:5F:22:4B:0B:2B:82:33:6A:AF:BA
                SHA1: 7B:24:F3:83:4F:08:0A:1B:FC:97:1E:8B:F9:8D:D1:82:00:CF:D7:B6


                *******************************************
                *******************************************


                the client
                ------------------------------------------------

                package sslservlet;

                import java.io.InputStream;
                import java.net.URL;

                import javax.net.ssl.HostnameVerifier;
                import javax.net.ssl.HttpsURLConnection;
                import javax.net.ssl.SSLSession;

                public class Client {

                private static class _HostNameVerifier implements HostnameVerifier
                {
                public boolean verify(String arg0, SSLSession arg1){
                return true;
                }
                }

                public static void main(String[] args)
                {
                try{

                URL url = new URL("https://localhost:8443/sslservlet/myservlet");
                HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
                conn.setHostnameVerifier(new _HostNameVerifier());

                String msg = "";

                InputStream istream = conn.getInputStream();
                int i = 0;
                while((i = istream.read()) != -1)
                msg+=(char)i;

                System.out.print(msg);

                }
                catch(Throwable e){
                e.printStackTrace();
                }
                }
                }


                the client is called with the following property set
                -Djavax.net.ssl.trustStore=conf/localhost.ks


                the response:
                -----------------------------------------------------------

                java.io.IOException: Server returned HTTP response code: 401 for URL: https://localhost:8443/sslservlet/myservlet
                at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1149)
                at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
                at sslservlet.Client.main(Client.java:29)



                This is expected since I'm not providing any username + password. This is not a problem since the reality I'm trying to replicate happens before this step.



                So now, after changing the clientAuth to "true" the answer becomes
                --------------------------------------------------------------------------------

                java.net.SocketException: Software caused connection abort: recv failed
                at java.net.SocketInputStream.socketRead0(Native Method)
                at java.net.SocketInputStream.read(SocketInputStream.java:129)
                at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:284)
                at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:319)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:720)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1345)
                at com.sun.net.ssl.internal.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:103)
                at com.sun.net.ssl.internal.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:590)
                at com.sun.net.ssl.internal.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:697)
                at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:623)
                at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:160)
                at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
                at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:815)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1025)
                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1038)
                at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
                at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
                at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:913)
                at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
                at sslservlet.Client.main(Client.java:29)


                If I setup the client side keystore definition properties, the problem disapears. That is, adding to the jvm startup

                -Djavax.net.ssl.keyStore=conf/localhost.ks
                -Djavax.net.ssl.keyStorePassword=123456

                the response is again

                java.io.IOException: Server returned HTTP response code: 401 for URL: https://localhost:8443/sslservlet/myservlet
                at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1149)
                at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
                at sslservlet.Client.main(Client.java:29)


                Again, thanks for your valid argumentation and general help.

                • 5. Re: clientAuth=true disables BASIC AUTH
                  nuno oliveira Newbie

                  sorry forgot to include the part about the server.xml file. here it goes.



                  Cheers

                  • 6. Re: clientAuth=true disables BASIC AUTH
                    nuno oliveira Newbie

                    Had to format it as code to finally show up :( sorry about that.

                    <Connector port="8443" address="${jboss.bind.address}"
                     maxThreads="100" strategy="ms" maxHttpHeaderSize="8192"
                     emptySessionPath="true"
                     scheme="https" secure="true" clientAuth="true"
                     keystoreFile="${jboss.server.home.dir}/conf/localhost.ks"
                     keystorePass="123456"
                     truststoreFile="${jboss.server.home.dir}/conf/localhost.ks"
                     truststorePass="123456"
                     sslProtocol="TLS" />


                    • 7. Re: clientAuth=true disables BASIC AUTH
                      chris griffith Expert

                      Thank you for the details provided. However, I think this just re-inforces my argument.
                      In your example, your servlet is configured to use BASIC authentication, as well as requires a transport of CONFIDENTIAL (i.e. SSL.)

                      In your first attempt to use your client, your ssl is not configured to require the client to authenticate using certificate. In this case, the server accepts the client when creating an SSL session. However, the servlet still requires authentication. Since this has not been provided, 401 error is returned.

                      Next, you set SSL connector to require the client to prove its identity via a certificate. At first this does not work because you have to tell the JVM of client to provide the certificate. After doing that, you end up is same situation as above. The client attempts to communicate with the server. The server requires SSL connection and requests from the client a certificate. The client provides the certificate. The server accepts the certificate and the SSL handshake proceeds. The result is a mutually trusted encrypted connection. Then the original request made by client starts to be processed by servlet container. The container determines that the request requires BASIC authentication. However, you have not provided this. So the container returns the 401 error.

                      So, set up a client to negotiate BASIC authentication as well as providing certificates for SSL encryption and see what happens. If you still do not agree with me, then I am not sure what other arguments I can provide. In any case, thanks for the thoughtful discussion.

                      later, cgriffith

                      • 8. Re: clientAuth=true disables BASIC AUTH
                        nuno oliveira Newbie

                        Hi, thanks for your anser.

                        I perfectly understand what's going on in my example. It's not that I don't agree with your general way of reasoning. I just feel it's missplaced in the context of servlet apps. I feel that there's no point in being able to specify CLIENT-CERT instead of BASIC AUTH, once you make that dependent on a transport layer concept (the connector) instead of an applicational one (the deployment descriptor). The confusion between client (transport) and user (applicational) was not my idea. It's in the spec, or at least in my reading of the spec. That's my point.
                        However, it seems that I'm going to have to live with this so am going forward in the direction of separate connectors. Hope I'm able to make that work somehow. Will scan these forums for a similar attempt. Thank you very much for your time and good will.