]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Add cache_peer auth-no-keytab option to use a credentials cache instead of keytab
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 22 Dec 2015 10:57:16 +0000 (23:57 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 22 Dec 2015 10:57:16 +0000 (23:57 +1300)
... when using login=NEGOTIATE to authenticate via kerberos to a peer.

When specified, this option prevents Squid from crafting a kerberos
credentials cache from a keytab, but instead lets GSSAPI use an existing
credentials cache.

doc/release-notes/release-4.sgml
src/CachePeer.h
src/FwdState.cc
src/RequestFlags.h
src/cache_cf.cc
src/cf.data.pre
src/http.cc
src/peer_proxy_negotiate_auth.cc
src/peer_proxy_negotiate_auth.h
src/tunnel.cc

index c8d69c83236b61c747bc0f37f773e3e948ce6c36..0d3c22ef940c97596e03d55f36b4f08fd77d8aab 100644 (file)
@@ -169,6 +169,8 @@ This section gives a thorough account of those changes in three categories:
           of queued requests.
 
        <tag>cache_peer</tag>
+       <p>New option <em>auth-no-keytab</em> to let GSSAPI implementation determine
+          which Kerberos credentials to use, instead of specifying a keytab.
        <p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
        <p>New option <em>tls-no-default-ca</em> replaces <em>sslflags=NO_DEFAULT_CA</em>
        <p>New option <em>tls-no-npn</em> to disable sending TLS NPN extension.
index 20b804102273136320fd88eabbcaa0bbd1cd4adb..925ff7526c535128bda32b19517f8affc49f5885 100644 (file)
@@ -119,6 +119,7 @@ public:
 #if PEER_MULTICAST_SIBLINGS
         bool mcast_siblings;
 #endif
+        bool auth_no_keytab;
     } options;
 
     int weight;
index 84ab620af86595ec91194c0761b68af387b6a93a..05924fcf1af9d2b0ce8a9baa93256b01fe9737ab 100644 (file)
@@ -968,11 +968,13 @@ FwdState::dispatch()
         ++ serverConnection()->getPeer()->stats.fetches;
         request->peer_login = serverConnection()->getPeer()->login;
         request->peer_domain = serverConnection()->getPeer()->domain;
+        request->flags.auth_no_keytab = serverConnection()->getPeer()->options.auth_no_keytab;
         httpStart(this);
     } else {
         assert(!request->flags.sslPeek);
         request->peer_login = NULL;
         request->peer_domain = NULL;
+        request->flags.auth_no_keytab = 0;
 
         switch (request->url.getScheme()) {
 #if USE_OPENSSL
index f9d411ef1666d588ab6e22474c50a585b6336650..3d5efa3209ab4353f7e32054b1f69707b6e57627 100644 (file)
@@ -30,6 +30,8 @@ public:
     bool ims :1;
     /** request is authenticated */
     bool auth :1;
+    /** do not use keytabs for peer Kerberos authentication */
+    bool auth_no_keytab :1;
     /** he response to the request may be stored in the cache */
     bool cachable :1;
     /** the request can be forwarded through the hierarchy */
index 3c6c03d4eb3d1d38783fddda81aea22f215b42f7..7deb6d7bd49993c3390b7b7ea52a61101aa74b5d 100644 (file)
@@ -2167,6 +2167,8 @@ parse_peer(CachePeer ** head)
         } else if (!strncmp(token, "login=", 6)) {
             p->login = xstrdup(token + 6);
             rfc1738_unescape(p->login);
+        } else if (!strcmp(token, "auth-no-keytab")) {
+            p->options.auth_no_keytab = 1;
         } else if (!strncmp(token, "connect-timeout=", 16)) {
             p->connect_timeout = xatoi(token + 16);
         } else if (!strncmp(token, "connect-fail-limit=", 19)) {
index 5aef88209a8c00b68d806d199a5c376b333a1554..a204896cf210ddfa9c944103c429cc22673b21f2 100644 (file)
@@ -3199,6 +3199,12 @@ DOC_START
                        Default is auto to automatically determine the status
                        of the peer.
        
+       auth-no-keytab
+                       Do not use a keytab to authenticate to a peer when
+                       login=NEGOTIATE is specified. Let the GSSAPI
+                       implementation determine which already existing
+                       credentials cache to use instead.
+       
        
        ==== SSL / HTTPS / TLS OPTIONS ====
        
index 39d486a6cbf75e0aecfe2e89f62a14ba87afd9d2..8be5f9c7ea470e786e9ef18db0da68f24f8c3f8a 100644 (file)
@@ -1722,10 +1722,15 @@ httpFixupAuthentication(HttpRequest * request, const HttpHeader * hdr_in, HttpHe
     if (strncmp(request->peer_login, "NEGOTIATE",strlen("NEGOTIATE")) == 0) {
         char *Token=NULL;
         char *PrincipalName=NULL,*p;
+        int negotiate_flags = 0;
+
         if ((p=strchr(request->peer_login,':')) != NULL ) {
             PrincipalName=++p;
         }
-        Token = peer_proxy_negotiate_auth(PrincipalName, request->peer_host);
+        if (request->flags.auth_no_keytab) {
+            negotiate_flags |= PEER_PROXY_NEGOTIATE_NOKEYTAB;
+        }
+        Token = peer_proxy_negotiate_auth(PrincipalName, request->peer_host, negotiate_flags);
         if (Token) {
             httpHeaderPutStrf(hdr_out, header, "Negotiate %s",Token);
         }
index 64a7cb6359406948403cdbf96b7e23b25bbe9d0f..82d6f6e1cd74dc399a3f71c91676016798fccfa8 100644 (file)
@@ -499,7 +499,7 @@ restart:
  * peer_proxy_negotiate_auth gets a GSSAPI token for principal_name
  * and base64 encodes it.
  */
-char *peer_proxy_negotiate_auth(char *principal_name, char *proxy) {
+char *peer_proxy_negotiate_auth(char *principal_name, char *proxy, int flags) {
     int rc = 0;
     OM_uint32 major_status, minor_status;
     gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
@@ -517,16 +517,18 @@ char *peer_proxy_negotiate_auth(char *principal_name, char *proxy) {
         return NULL;
     }
 
-    if (principal_name)
-        debugs(11, 5,
-               HERE << "Creating credential cache for " << principal_name);
-    else
-        debugs(11, 5, HERE << "Creating credential cache");
-    rc = krb5_create_cache(NULL, principal_name);
-    if (rc) {
-        debugs(11, 5, HERE << "Error : Failed to create Kerberos cache");
-        krb5_cleanup();
-        return NULL;
+    if (!(flags & PEER_PROXY_NEGOTIATE_NOKEYTAB)) {
+        if (principal_name)
+            debugs(11, 5,
+                   HERE << "Creating credential cache for " << principal_name);
+        else
+            debugs(11, 5, HERE << "Creating credential cache");
+        rc = krb5_create_cache(NULL, principal_name);
+        if (rc) {
+            debugs(11, 5, HERE << "Error : Failed to create Kerberos cache");
+            krb5_cleanup();
+            return NULL;
+        }
     }
 
     service.value = (void *) xmalloc(strlen("HTTP") + strlen(proxy) + 2);
index d1c81936b1e4898e0a6bd07b2c938c45905f2c12..1816f4346ceab0bf20739d747f641e1e3092dd89 100644 (file)
 #define SQUID_PEER_PROXY_NEGOTIATE_AUTH_H_
 
 #if HAVE_AUTH_MODULE_NEGOTIATE && HAVE_KRB5 && HAVE_GSSAPI
+
+#define PEER_PROXY_NEGOTIATE_NOKEYTAB  1
+
 /* upstream proxy authentication */
-SQUIDCEXTERN char *peer_proxy_negotiate_auth(char *principal_name, char *proxy);
+SQUIDCEXTERN char *peer_proxy_negotiate_auth(char *principal_name, char *proxy, int flags);
 #endif
 
 #endif /* SQUID_PEER_PROXY_NEGOTIATE_AUTH_H_ */
index 828fbe2730f0e0ebab9bb10d2e6aceac9f4e3df0..bf20e0ea424b147934aeabab3d94b94f84024bd5 100644 (file)
@@ -1007,10 +1007,12 @@ tunnelConnectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, int xe
     if (conn->getPeer()) {
         tunnelState->request->peer_login = conn->getPeer()->login;
         tunnelState->request->peer_domain = conn->getPeer()->domain;
+        tunnelState->request->flags.auth_no_keytab = conn->getPeer()->options.auth_no_keytab;
         tunnelState->request->flags.proxying = !(conn->getPeer()->options.originserver);
     } else {
         tunnelState->request->peer_login = NULL;
         tunnelState->request->peer_domain = NULL;
+        tunnelState->request->flags.auth_no_keytab = false;
         tunnelState->request->flags.proxying = false;
     }
 
@@ -1280,10 +1282,12 @@ switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::
     if (srvConn->getPeer()) {
         tunnelState->request->peer_login = srvConn->getPeer()->login;
         tunnelState->request->peer_domain = srvConn->getPeer()->domain;
+        tunnelState->request->flags.auth_no_keytab = srvConn->getPeer()->options.auth_no_keytab;
         tunnelState->request->flags.proxying = !(srvConn->getPeer()->options.originserver);
     } else {
         tunnelState->request->peer_login = NULL;
         tunnelState->request->peer_domain = NULL;
+        tunnelState->request->flags.auth_no_keytab = false;
         tunnelState->request->flags.proxying = false;
     }