Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP Authorization Manager/ Kerberos Authentication: add port to SPN when server port is neither 80 nor 443 #3394

Closed
asfimport opened this issue Jul 7, 2014 · 11 comments

Comments

@asfimport
Copy link
Collaborator

dan.haughey (Bug 56701):
We are load testing a server using Kerberos authentication, but the server principal name is not being generated in the format that the server expects. JMeter appears to use this format:

HTTP/example-server.com

but our server expects:

HTTP/example-server.com:12345

(where 12345 is the port number of the site being tested).

Chrome has a command-line switch '--enable-auth-negotiate-port' (disabled by default) that adds this port number to the SPN for sites that are on a port other than 80 or 443. (This is documented at http://dev.chromium.org/developers/design-documents/http-authentication) - using this switch allows the site to be browsed in Chrome.

Could a similar option be added to JMeter? At the moment I've hacked a solution in src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java that adds the port number on if it is a non-standard port to mimic Chrome's behaviour with the switch enabled. This obviously needs putting behind some sort of option but I haven't had time to code this properly. My diff is attached in case this is useful to anyone.

Created attachment add-port-to-spn.diff: Patch to alter SPN generation behaviour in AuthManager.java

add-port-to-spn.diff
--- AuthManager (2).java	Mon Jul  7 15:39:30 2014
+++ AuthManager.java	Mon Jul  7 15:15:36 2014
@@ -392,7 +392,9 @@
                 log.debug(username + " > D="+domain+" R="+realm + " M="+auth.getMechanism());
             }
             if (Mechanism.KERBEROS.equals(auth.getMechanism())) {
-                ((AbstractHttpClient) client).getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory(true));
+                Boolean stripPort = (url.getPort() == HTTPConstants.DEFAULT_HTTP_PORT || url.getPort() == HTTPConstants.DEFAULT_HTTPS_PORT);
+
+                ((AbstractHttpClient) client).getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory(stripPort));
                 credentialsProvider.setCredentials(new AuthScope(null, -1, null), USE_JAAS_CREDENTIALS);
             } else {
                 credentialsProvider.setCredentials(

OS: All

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Hello,
Thanks for patch.
I commited it to trunk nearly as is without adding option as it does not seem necessary to me.
But it would be great if you could test toward your initial site and a site with regular port (80 or 443).

Version should be available in nightly build:
http://jmeter.apache.org/nightly.html

Installing JMeter runtime
Download the _bin and _lib files
Unpack the archives into the same directory structure
The other archives are not needed to run JMeter.

Philippe M.
@philmdot

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Date: Wed Jul 16 14:42:17 2014
New Revision: 1611028

URL: http://svn.apache.org/r1611028
Log:
#3394 - HTTP Authorization Manager/ Kerberos Authentication: add port to SPN when server port is neither 80 nor 443
#3394

Modified:
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java
jmeter/trunk/xdocs/changes.xml

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Hello Felix,
AS you are the Kerberos expert of JMeter, it would be nice to have your opinion on this issue and fix in nightly build.

Thanks for your help in advance
Regards
Philippe

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
I don't think that it is a good idea to make a non default option, that is available in only one major browser, to be the default for jmeter.

As written in the chrome url given in an cited by Dan only chrome supports the port embedded in the spn. IE and firefox will not embed ports into the spn. As SPNEGO is essential a child of microsoft, I would opt to be compatible with IE as the default. (I have done my tests only with firefox, though)

The easiest solution would be to introduce a system property to decide which algortihm should be used. But it might be, that someone would like to test two different systems, which behave different in respect to port embedded into spn. (We could wait for that to happen :)

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Hello Felix,
Thanks for feedback.
Currently what will happen is the following:

  • If port if 443 or 80 then it will not be appended.
  • If port is none of the above , then :<port> will be appended.

With this behaviour , is your note still valid ? If yes I will introduce a system property.
Thanks

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
Yes, that is exactly what I meant. Firefox and IE will produce a SPN HTTP/hostname for every given port. Chrome will do that as default. Chrome will construct a HTTP/hostname:port SPN only if you start it with --enable-auth-negotiate-port.

So I would opt for generating HTTP/hostname as default for every given port.

If someone really wants HTTP/hostname:port for non standard ports (80 and 443) we should give him a chance by setting a system property (something like -Dorg.apache.jmeter.enable-auth-negotiate-port=true)

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Thanks a lot for feedback Felix.
You think System property is better of jmeter property ?
Feel free to contribute a patch, otherwise I should be handling this in the upcoming days.
Regards

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
Haven't tested it yet against my kerberos setup. But you can review it anyway, since the changes seems to be trivial enough.

Will add a comment, as soon as I tested it against my previous setup (using a tomcat listening on port 8080)

Created attachment spnego-strip-ports-option.diff: Add an option to enable the chrome optional behavior

spnego-strip-ports-option.diff
diff --git bin/jmeter.properties bin/jmeter.properties
index 4b58e11..862882e 100644
--- bin/jmeter.properties
+++ bin/jmeter.properties
@@ -339,6 +339,10 @@ log_level.jorphan=INFO
 # Name of application module used in jaas.conf
 #kerberos_jaas_application=JMeter
 
+# Should ports be stripped from urls before constructing SPNs
+# for spnego authentication
+#spnego.strip_port=true
+
 #         Sample logging levels for Commons HttpClient
 #
 # Commons HttpClient Logging information can be found at:
diff --git src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java
index 625ce23..3775b08 100644
--- src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java
+++ src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java
@@ -96,6 +96,9 @@ public class AuthManager extends ConfigTestElement implements TestStateListener,
 
     private static final boolean DEFAULT_CLEAR_VALUE = false;
 
+    /** Decides whether port should be omitted from SPN for kerberos spnego authentication */
+    private static final boolean STRIP_PORT = JMeterUtils.getPropDefault("spnego.strip_port", true);
+
     public enum Mechanism {
         BASIC_DIGEST, KERBEROS;
     }
@@ -392,8 +395,7 @@ public class AuthManager extends ConfigTestElement implements TestStateListener,
                 log.debug(username + " > D="+domain+" R="+realm + " M="+auth.getMechanism());
             }
             if (Mechanism.KERBEROS.equals(auth.getMechanism())) {
-                boolean stripPort = (url.getPort() == HTTPConstants.DEFAULT_HTTP_PORT || url.getPort() == HTTPConstants.DEFAULT_HTTPS_PORT);
-                ((AbstractHttpClient) client).getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory(stripPort));
+                ((AbstractHttpClient) client).getAuthSchemes().register(AuthPolicy.SPNEGO, new SPNegoSchemeFactory(isStripPort(url)));
                 credentialsProvider.setCredentials(new AuthScope(null, -1, null), USE_JAAS_CREDENTIALS);
             } else {
                 credentialsProvider.setCredentials(
@@ -403,6 +405,24 @@ public class AuthManager extends ConfigTestElement implements TestStateListener,
         }
     }
 
+    /**
+     * IE and Firefox will always strip port from the url before constructing
+     * the SPN. Chrome has an option (<code>--enable-auth-negotiate-port</code>)
+     * to include the port if it differs from <code>80</code> or
+     * <code>443</code>. That behavior can be changed by setting the jmeter
+     * property <code>spnego.stripPort</code>.
+     *
+     * @param url
+     *            to be checked
+     * @return <code>true</code> when port should omitted in SPN
+     */
+    private boolean isStripPort(URL url) {
+        if (STRIP_PORT)
+            return true;
+        return url.getPort() == HTTPConstants.DEFAULT_HTTP_PORT
+                || url.getPort() == HTTPConstants.DEFAULT_HTTPS_PORT;
+    }
+
     /** {@inheritDoc} */
     @Override
     public void testStarted() {
diff --git xdocs/usermanual/component_reference.xml xdocs/usermanual/component_reference.xml
index fca72e5..72a7327 100644
--- xdocs/usermanual/component_reference.xml
+++ xdocs/usermanual/component_reference.xml
@@ -3537,6 +3537,17 @@ Look at the two sample configuration files (krb5.conf and jaas.conf) located in
 your Kerberos configuration.
 </p>
 <br></br>
+<p>
+When generating a SPN for Kerberos SPNEGO authentication IE and Firefox will omit the port number
+from the url. Chrome has an option (<code>--enable-auth-negotiate-port</code>) to include the port
+number if it differs from the standard ones (<code>80</code> and <code>443</code>). That behavior
+can be emulated by setting the following jmeter property as below.
+<pre>
+jmeter.properties:
+spnego.strip_port=false
+</pre> 
+</p>
+<br></br>
 <b>Controls:</b>
 <ul>
   <li>Add Button - Add an entry to the authorization table.</li>

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Date: Fri Jul 18 20:05:59 2014
New Revision: 1611785

URL: http://svn.apache.org/r1611785
Log:
#3394 - HTTP Authorization Manager/ Kerberos Authentication: add port to SPN when server port is neither 80 nor 443
Add a jmeter property to control behaviour.
By default strip port.
#3394

Modified:
jmeter/trunk/bin/jmeter.properties
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/control/AuthManager.java
jmeter/trunk/xdocs/changes.xml
jmeter/trunk/xdocs/usermanual/component_reference.xml

@asfimport
Copy link
Collaborator Author

@pmouawad (migrated from Bugzilla):
Thanks a lot Felix, I updated the name of property to relate it to kerberos.

@asfimport
Copy link
Collaborator Author

@FSchumacher (migrated from Bugzilla):
I have tested the current trunk against my test setup, which uses HTTP/www.example.com@EXAMPLE.COM as SPN for a tomcat service which runs on port 8080. That setup works.

I have tried to change my SPN to HTTP/www.example.com:8080@EXAMPLE.COM. Generated a new ktab for tomcat, changed kerberos.spnego.strip_port to "false". And tried again. It seems to use the correct SPN, but tomcat can't authenticate that SPN with its keytab against apacheds. That might be a setup problem though.

So all in all. I think the feature will do, what the original requestor wants.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant