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

IAE "Illegal character(s) in message header value" from com.saucelabs.rest.Credential.call

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Major Major
    • sauce-ondemand-plugin
    • None
    • 1.14

      A user reports getting an error message when attempting to use the Test Connection button. The meat of the exception is

      java.lang.IllegalArgumentException: Illegal character(s) in message header value: Basic someLongBase64EncodedMessHereEtcEtcEtcEtcEtcEtcEtcEtcEtcEtcEtcEtcEtcAndAnEOL
      
      	sun.net.www.protocol.http.HttpURLConnection.checkMessageHeader(HttpURLConnection.java:428)
      	sun.net.www.protocol.http.HttpURLConnection.isExternalMessageHeaderAllowed(HttpURLConnection.java:394)
      	sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:2374)
      	sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:296)
      	com.saucelabs.rest.Credential.call(Credential.java:167)
      	com.saucelabs.rest.Credential.call(Credential.java:151)
      	com.saucelabs.rest.SauceTunnelFactory.list(SauceTunnelFactory.java:88)
      	hudson.plugins.sauce_ondemand.PluginImpl$DescriptorImpl.doValidate(PluginImpl.java:137)
      

      Note that HttpURLConnection is complaining rightly that the authentication string contains a newline. Credential.call has

      String userpassword = username + ":" + key;
      con.setRequestProperty("Authorization", "Basic " + new BASE64Encoder().encode(userpassword.getBytes()));
      

      You can see that this will fail in some cases:

      public class Demo {
          public static void main(String... args) {
              System.out.println("got: '" + new sun.misc.BASE64Encoder().encode(new String("someusername:apiKeyEtc01234567890123456789012345678901234").getBytes()) + "'");
          }
      }
      

      produces

      got: 'c29tZXVzZXJuYW1lOmFwaUtleUV0YzAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0
      '
      

      http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6947917 discusses a similar bug in the JRE, and suggests the workaround:

      public class Demo {
          public static void main(String... args) {
              System.out.println("got: '" + new sun.misc.BASE64Encoder() {
                  @Override protected int bytesPerLine() {
                      return 9999;
                  }
              }.encode(new String("someusername:apiKeyEtc01234567890123456789012345678901234").getBytes()) + "'");
          }
      }
      

      producing

      got: 'c29tZXVzZXJuYW1lOmFwaUtleUV0YzAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0'
      

      By the way https://github.com/infradna/saucerest-java/ seems to be the source of the REST API, but this appears long out of date whereas https://github.com/saucelabs/saucerest-java/ looks to be the authoritative library (which however still appears to suffer from this same bug, at least according to an inspection of sources).

            rossrowe Ross Rowe
            jglick Jesse Glick
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: