From: Amos Jeffries Date: Tue, 22 Dec 2015 10:57:16 +0000 (+1300) Subject: Add cache_peer auth-no-keytab option to use a credentials cache instead of keytab X-Git-Tag: SQUID_4_0_4~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9825b3982456021e6836e740d57e9295cd7b15c4;p=thirdparty%2Fsquid.git Add cache_peer auth-no-keytab option to use a credentials cache instead of keytab ... 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. --- diff --git a/doc/release-notes/release-4.sgml b/doc/release-notes/release-4.sgml index c8d69c8323..0d3c22ef94 100644 --- a/doc/release-notes/release-4.sgml +++ b/doc/release-notes/release-4.sgml @@ -169,6 +169,8 @@ This section gives a thorough account of those changes in three categories: of queued requests. cache_peer +

New option auth-no-keytab to let GSSAPI implementation determine + which Kerberos credentials to use, instead of specifying a keytab.

New option tls-min-version=1.N to set minimum TLS version allowed.

New option tls-no-default-ca replaces sslflags=NO_DEFAULT_CA

New option tls-no-npn to disable sending TLS NPN extension. diff --git a/src/CachePeer.h b/src/CachePeer.h index 20b8041022..925ff7526c 100644 --- a/src/CachePeer.h +++ b/src/CachePeer.h @@ -119,6 +119,7 @@ public: #if PEER_MULTICAST_SIBLINGS bool mcast_siblings; #endif + bool auth_no_keytab; } options; int weight; diff --git a/src/FwdState.cc b/src/FwdState.cc index 84ab620af8..05924fcf1a 100644 --- a/src/FwdState.cc +++ b/src/FwdState.cc @@ -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 diff --git a/src/RequestFlags.h b/src/RequestFlags.h index f9d411ef16..3d5efa3209 100644 --- a/src/RequestFlags.h +++ b/src/RequestFlags.h @@ -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 */ diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 3c6c03d4eb..7deb6d7bd4 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -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)) { diff --git a/src/cf.data.pre b/src/cf.data.pre index 5aef88209a..a204896cf2 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -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 ==== diff --git a/src/http.cc b/src/http.cc index 39d486a6cb..8be5f9c7ea 100644 --- a/src/http.cc +++ b/src/http.cc @@ -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); } diff --git a/src/peer_proxy_negotiate_auth.cc b/src/peer_proxy_negotiate_auth.cc index 64a7cb6359..82d6f6e1cd 100644 --- a/src/peer_proxy_negotiate_auth.cc +++ b/src/peer_proxy_negotiate_auth.cc @@ -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); diff --git a/src/peer_proxy_negotiate_auth.h b/src/peer_proxy_negotiate_auth.h index d1c81936b1..1816f4346c 100644 --- a/src/peer_proxy_negotiate_auth.h +++ b/src/peer_proxy_negotiate_auth.h @@ -10,8 +10,11 @@ #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_ */ diff --git a/src/tunnel.cc b/src/tunnel.cc index 828fbe2730..bf20e0ea42 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -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; }