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]