From dfa59762b50f26263716bae769bc4078d4059c37 Mon Sep 17 00:00:00 2001 From: David Mansfield Date: Fri, 4 Sep 2015 10:00:39 -0400 Subject: [PATCH] Implement optional hostname canonicalization for kerberos (SPNEGO) This commit implements an additional property, useCanonicalHostname, which is supported by the AbstractSpnegoAuthSupplier, and therefore available to SpnegoAuthSupplier and KerberosAuthOutInterceptor. The default behavior is not modified. If useCanonicalHostname is set, then the service principal will be created using the canonical name of the remote host. For example, if there is a CNAME DNS record for host.example.com which refers to an A record host-a-b-c.example.com, the default behavior would be to generate a service principal HTTP/host.example.com. When useCanonicalHostname is set to true, the service principal would be HTTP/ host-a-b-c.example.com. Most browsers and many other HTTP user agents perform this kind of canonicalization. --- .../http/auth/AbstractSpnegoAuthSupplier.java | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/AbstractSpnegoAuthSupplier.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/AbstractSpnegoAuthSupplier.java index 713b55ca272..dc28427da56 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/AbstractSpnegoAuthSupplier.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/AbstractSpnegoAuthSupplier.java @@ -18,6 +18,7 @@ */ package org.apache.cxf.transport.http.auth; +import java.net.InetAddress; import java.net.URI; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; @@ -62,6 +63,7 @@ public abstract class AbstractSpnegoAuthSupplier { private boolean credDelegation; private Configuration loginConfig; private Oid serviceNameType; + private boolean useCanonicalHostname; public String getAuthorization(AuthorizationPolicy authPolicy, URI currentURI, @@ -154,8 +156,17 @@ protected boolean isCredDelegationRequired(Message message) { } protected String getCompleteServicePrincipalName(URI currentURI) { - String name = servicePrincipalName == null - ? "HTTP/" + currentURI.getHost() : servicePrincipalName; + String name; + + if (servicePrincipalName == null) { + String host = currentURI.getHost(); + if (useCanonicalHostname) { + host = getCanonicalHostname(host); + } + name = "HTTP/" + host; + } else { + name = servicePrincipalName; + } if (realm != null) { name += "@" + realm; } @@ -163,10 +174,20 @@ protected String getCompleteServicePrincipalName(URI currentURI) { LOG.fine("Service Principal Name is " + name); } return name; - - } - + + private String getCanonicalHostname(String hostname) { + String canonicalHostname = hostname; + try { + InetAddress in = InetAddress.getByName(hostname); + canonicalHostname = in.getCanonicalHostName(); + LOG.fine("resolved hostname=" + hostname + " to canonicalHostname=" + canonicalHostname); + } catch (Exception e) { + LOG.log(Level.WARNING, "unable to resolve canonical hostname", e); + } + return canonicalHostname; + } + public void setServicePrincipalName(String servicePrincipalName) { this.servicePrincipalName = servicePrincipalName; } @@ -213,4 +234,12 @@ public void setServiceNameType(Oid serviceNameType) { this.serviceNameType = serviceNameType; } + public boolean isUseCanonicalHostname() { + return useCanonicalHostname; + } + + public void setUseCanonicalHostname(boolean useCanonicalHostname) { + this.useCanonicalHostname = useCanonicalHostname; + } + }