Hi,

here are two patches to support canonical address resolution to support
Kerberos Authentication against HTTP Server which are addressed by DNS
CNAME.
I have also changed the behavior to strip ports in GSS and Kerberos
Setups. So it looks more compatible to the widely used browser behavior.

I hope, this is the right place to submit this patches. :-)


With kind regards

Sebastian
Index: httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java	(Revision 1602556)
+++ httpclient/src/main/java/org/apache/http/impl/auth/GGSSchemeBase.java	(Arbeitskopie)
@@ -67,6 +67,7 @@
 
     private final Base64 base64codec;
     private final boolean stripPort;
+    private final boolean useCanonicalHostname;
 
     /** Authentication process state */
     private State state;
@@ -74,15 +75,20 @@
     /** base64 decoded challenge **/
     private byte[] token;
 
-    GGSSchemeBase(final boolean stripPort) {
+    GGSSchemeBase(final boolean stripPort, final boolean useCanonicalHostname) {
         super();
         this.base64codec = new Base64(0);
         this.stripPort = stripPort;
+        this.useCanonicalHostname = useCanonicalHostname;
         this.state = State.UNINITIATED;
     }
 
+    GGSSchemeBase(final boolean stripPort) {
+        this(stripPort, true);
+    }
+
     GGSSchemeBase() {
-        this(false);
+        this(true,true);
     }
 
     protected GSSManager getManager() {
@@ -149,12 +155,22 @@
                     host = route.getTargetHost();
                 }
                 final String authServer;
-                if (!this.stripPort && host.getPort() > 0) {
-                    authServer = host.toHostString();
-                } else {
-                    authServer = host.getHostName();
+                String tmpServerName=null;
+
+                if (this.useCanonicalHostname){
+                    tmpServerName = host.getCanonicalHostName();
                 }
 
+                if (tmpServerName==null){
+                    tmpServerName = host.getHostName();
+                }
+
+                if (this.stripPort || host.getPort()==80 || host.getPort()==443) {
+                    authServer=tmpServerName;
+                }else{
+                    authServer=tmpServerName+":"+host.getPort();
+                }
+
                 if (log.isDebugEnabled()) {
                     log.debug("init " + authServer);
                 }
Index: httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java	(Revision 1602556)
+++ httpclient/src/main/java/org/apache/http/impl/auth/KerberosScheme.java	(Arbeitskopie)
@@ -46,12 +46,16 @@
 
     private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
 
+    public KerberosScheme(final boolean stripPort, final boolean useCanonicalHostname) {
+        super(stripPort, useCanonicalHostname);
+    }
+
     public KerberosScheme(final boolean stripPort) {
         super(stripPort);
     }
 
     public KerberosScheme() {
-        super(false);
+        super();
     }
 
     public String getSchemeName() {
Index: httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java	(Revision 1602556)
+++ httpclient/src/main/java/org/apache/http/impl/auth/KerberosSchemeFactory.java	(Arbeitskopie)
@@ -44,14 +44,22 @@
 public class KerberosSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
 
     private final boolean stripPort;
+    private final boolean useCanonicalHostname;
 
+    public KerberosSchemeFactory(final boolean stripPort, final boolean useCanonicalHostname) {
+        super();
+        this.stripPort = stripPort;
+        this.useCanonicalHostname = useCanonicalHostname;
+    }
+
     public KerberosSchemeFactory(final boolean stripPort) {
         super();
         this.stripPort = stripPort;
+        this.useCanonicalHostname = true;
     }
 
     public KerberosSchemeFactory() {
-        this(false);
+        this(true, true);
     }
 
     public boolean isStripPort() {
@@ -58,12 +66,16 @@
         return stripPort;
     }
 
+    public boolean isUseCanonicalHostname() {
+        return useCanonicalHostname;
+    }
+
     public AuthScheme newInstance(final HttpParams params) {
-        return new KerberosScheme(this.stripPort);
+        return new KerberosScheme(this.stripPort, this.useCanonicalHostname);
     }
 
     public AuthScheme create(final HttpContext context) {
-        return new KerberosScheme(this.stripPort);
+        return new KerberosScheme(this.stripPort, this.useCanonicalHostname);
     }
 
 }
Index: httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java	(Revision 1602556)
+++ httpclient/src/main/java/org/apache/http/impl/auth/SPNegoScheme.java	(Arbeitskopie)
@@ -47,12 +47,16 @@
 
     private static final String SPNEGO_OID = "1.3.6.1.5.5.2";
 
+    public SPNegoScheme(final boolean stripPort, final boolean useCanonicalHostname) {
+        super(stripPort, useCanonicalHostname);
+    }
+
     public SPNegoScheme(final boolean stripPort) {
         super(stripPort);
     }
 
     public SPNegoScheme() {
-        super(false);
+        super();
     }
 
     public String getSchemeName() {
Index: httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java	(Revision 1602556)
+++ httpclient/src/main/java/org/apache/http/impl/auth/SPNegoSchemeFactory.java	(Arbeitskopie)
@@ -44,14 +44,22 @@
 public class SPNegoSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
 
     private final boolean stripPort;
+    private final boolean useCanonicalHostname;
 
+    public SPNegoSchemeFactory(final boolean stripPort, final boolean useCanonicalHostname) {
+        super();
+        this.stripPort = stripPort;
+        this.useCanonicalHostname = useCanonicalHostname;
+    }
+
     public SPNegoSchemeFactory(final boolean stripPort) {
         super();
         this.stripPort = stripPort;
+        this.useCanonicalHostname = true;
     }
 
     public SPNegoSchemeFactory() {
-        this(false);
+        this(true, true);
     }
 
     public boolean isStripPort() {
@@ -58,12 +66,16 @@
         return stripPort;
     }
 
+    public boolean isUseCanonicalHostname() {
+        return useCanonicalHostname;
+    }
+
     public AuthScheme newInstance(final HttpParams params) {
-        return new SPNegoScheme(this.stripPort);
+        return new SPNegoScheme(this.stripPort, this.useCanonicalHostname);
     }
 
     public AuthScheme create(final HttpContext context) {
-        return new SPNegoScheme(this.stripPort);
+        return new SPNegoScheme(this.stripPort, this.useCanonicalHostname);
     }
 
 }

Index: httpcore/src/main/java/org/apache/http/HttpHost.java
===================================================================
--- httpcore/src/main/java/org/apache/http/HttpHost.java	(Revision 1601778)
+++ httpcore/src/main/java/org/apache/http/HttpHost.java	(Arbeitskopie)
@@ -29,6 +29,7 @@
 
 import java.io.Serializable;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.Locale;
 
 import org.apache.http.annotation.Immutable;
@@ -56,6 +57,8 @@
     /** The lowercase host, for {@link #equals} and {@link #hashCode}. */
     protected final String lcHostname;
 
+    /** The canonical host, for {@link #equals} and {@link #hashCode}. */
+    protected final String canonicalHostname;
 
     /** The port to use, defaults to -1 if not set. */
     protected final int port;
@@ -80,6 +83,7 @@
         super();
         this.hostname   = Args.notBlank(hostname, "Host name");
         this.lcHostname = hostname.toLowerCase(Locale.ENGLISH);
+        this.canonicalHostname = resolveCanonicalHostname (hostname);
         if (scheme != null) {
             this.schemeName = scheme.toLowerCase(Locale.ENGLISH);
         } else {
@@ -127,6 +131,7 @@
         this.address = Args.notNull(address, "Inet address");
         this.hostname = address.getHostAddress();
         this.lcHostname = this.hostname.toLowerCase(Locale.ENGLISH);
+        this.canonicalHostname = resolveCanonicalHostname (hostname);
         if (scheme != null) {
             this.schemeName = scheme.toLowerCase(Locale.ENGLISH);
         } else {
@@ -169,6 +174,7 @@
         Args.notNull(httphost, "HTTP host");
         this.hostname   = httphost.hostname;
         this.lcHostname = httphost.lcHostname;
+        this.canonicalHostname = resolveCanonicalHostname (hostname);
         this.schemeName = httphost.schemeName;
         this.port = httphost.port;
         this.address = httphost.address;
@@ -184,6 +190,38 @@
     }
 
     /**
+     * resolves the a canonical host name.
+     *
+     * @return resolves the canonical host name (DNS name)
+     */
+    private String resolveCanonicalHostname (final String hostname){
+        //should we only return a real canonical name or should we instead return the ip or the hostname, if something has failed?
+        InetAddress in;
+        try {
+                in = InetAddress.getByName(hostname);
+        } catch (UnknownHostException e) {
+                //return hostname;
+                return null;
+        }
+
+        final String canonicalServer = in.getCanonicalHostName();
+        if (in.getHostAddress().contentEquals(canonicalServer)){
+                return hostname;
+        }
+        return canonicalServer;
+    }
+
+    /**
+     * Returns the canonical host name.
+     *
+     * @return the canonical host name (IP or DNS name)
+     */
+    public String getCanonicalHostName() {
+        return this.canonicalHostname;
+    }
+
+
+    /**
      * Returns the port.
      *
      * @return the host port, or <code>-1</code> if not set


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to