Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-5230

Unable to use SSL Auth because certFile is not passed to svnkit

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Major Major
    • subversion-plugin
    • None
    • Running Hudson 1.334, and occurs when built from HEAD revision 25498. Running on an EC2 VM, Linux.

      Description of the problem:
      We're unable to use SSL authentication to check out a project from our repository. Accessing this repository from this machine using SSL auth with this same certificate is not a problem - svn checkout of a project from this repository works from the command-line.

      Steps to reproduce:
      Create a job that has an SVN URL to a repository which requires SSL certificate authentication
      2. View the error that shows up beneath the "Repository URL" field: "Unable to access [svn repository] : svn: Received fatal alert: handshake_failure"
      3. Go to the "enter credential" page
      4. Select HTTPS client certificate, browse to your certificate file (.pfx) on your local disk, and enter its password
      5. View the Error page which shows the java stack trace for the error (full stack trace pasted at the bottom of this message)
      Attempting an SSL client certificate authentcation
      Failed to authenticate: svn: SSL handshake failed: 'Received fatal alert: handshake_failure'
      javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

      Possible cause of the problem:
      In the Hudson source code, in the class SubversionSCM.java ( https://hudson.dev.java.net/svn/hudson/trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionSCM.java, revision 25498), we see that the private inner class SslClientCertificateCredential has only one member variable: String password. Its constructor takes two parameters, File certificate and String password, and then it only stores the password.
      After an object of type SslClientCertificateCredential is created (in method public void postCredential()), you call cred.createSVNAuthentication(kind), which goes to the following code:

      public SVNAuthentication createSVNAuthentication(String kind)

      { if(kind.equals(ISVNAuthenticationManager.SSL)) return new SVNSSLAuthentication(null,Scrambler.descramble(password),false); else return null; // unexpected authentication type }

      Here is the constructor signature for SVNSSLAuthentication:
      public SVNSSLAuthentication(File certFile, String password, boolean storageAllowed)

      As you can see, when you are calling the constructor of SVNSSLAuthentication, you are passing null as the first parameter instead of passing a File certFile. This is because you aren't storing the File certificate in the constructor for this class, so you have nothing to pass for that parameter.

      Because you aren't passing in a certFile, when the SVNSSLAuthentication tries to make its request to the SVN server, it doesn't have a certFile to give it, so it causes a handshake_failure when it gets the response from the SVN server.

      Attached is a patch file that I believe will fix this problem.

      _______________________________________________

      The java stack trace for the error incurred in step 5 of the repro steps:

      javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
      at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
      at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
      at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1657)
      at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:932)
      at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
      at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
      at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
      at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
      at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
      at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.sendData(HTTPConnection.java:226)
      at org.tmatesoft.svn.core.internal.io.dav.http.HTTPRequest.dispatch(HTTPRequest.java:166)
      at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.request(HTTPConnection.java:345)
      at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.request(HTTPConnection.java:273)
      at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.request(HTTPConnection.java:261)
      at org.tmatesoft.svn.core.internal.io.dav.DAVConnection.exchangeCapabilities(DAVConnection.java:516)
      at org.tmatesoft.svn.core.internal.io.dav.DAVConnection.open(DAVConnection.java:98)
      at org.tmatesoft.svn.core.internal.io.dav.DAVRepository.openConnection(DAVRepository.java:1001)
      at org.tmatesoft.svn.core.internal.io.dav.DAVRepository.testConnection(DAVRepository.java:97)
      at hudson.scm.SubversionSCM$DescriptorImpl.postCredential(SubversionSCM.java:1701)
      at hudson.scm.SubversionSCM$DescriptorImpl.doPostCredential(SubversionSCM.java:1601)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.kohsuke.stapler.Function$InstanceFunction.invoke(Function.java:185)
      at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:101)
      at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:54)
      at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:74)
      at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:30)
      at org.kohsuke.stapler.Stapler.invoke(Stapler.java:500)
      at org.kohsuke.stapler.MetaClass$6.doDispatch(MetaClass.java:180)
      at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:30)
      at org.kohsuke.stapler.Stapler.invoke(Stapler.java:500)
      at org.kohsuke.stapler.Stapler.invoke(Stapler.java:416)
      at org.kohsuke.stapler.Stapler.service(Stapler.java:122)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:45)
      at winstone.ServletConfiguration.execute(ServletConfiguration.java:249)
      at winstone.RequestDispatcher.forward(RequestDispatcher.java:335)
      at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:378)
      at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:94)
      at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:86)
      at winstone.FilterConfiguration.execute(FilterConfiguration.java:195)
      at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:368)
      at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:47)
      at winstone.FilterConfiguration.execute(FilterConfiguration.java:195)
      at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:368)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
      at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:166)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at org.acegisecurity.ui.basicauth.BasicProcessingFilter.doFilter(BasicProcessingFilter.java:173)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
      at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:66)
      at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
      at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:76)
      at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:164)
      at winstone.FilterConfiguration.execute(FilterConfiguration.java:195)
      at winstone.RequestDispatcher.doFilter(RequestDispatcher.java:368)
      at winstone.RequestDispatcher.forward(RequestDispatcher.java:333)
      at winstone.RequestHandlerThread.processRequest(RequestHandlerThread.java:244)
      at winstone.RequestHandlerThread.run(RequestHandlerThread.java:150)
      at java.lang.Thread.run(Thread.java:619)
      FAILED: svn: Received fatal alert: handshake_failure

            Unassigned Unassigned
            awixted awixted
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: