From d4521ed0df7e625ccf2bc079bab6f48c46ef9bf9 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Mon, 26 Oct 2020 17:35:22 +0100 Subject: [PATCH 1/4] Avoid infinite loop in admin.cgi when negotiate is used SetAuthorizationString with NULL argument sets an empty string. Related: #5596 Signed-off-by: Samuel Cabrero --- cups/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cups/auth.c b/cups/auth.c index db45bbba68..f2409350aa 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -295,7 +295,7 @@ cupsDoAuthentication( } } - if (http->authstring) + if (http->authstring && http->authstring[0]) { DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\".", http->authstring)); From 61ad7780bc7d0593e3225d088ac6dff31badf801 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Tue, 27 Oct 2020 16:11:41 +0100 Subject: [PATCH 2/4] Add cups_is_local_connection() to check if connection is to localhost Related: #5596 Signed-off-by: Samuel Cabrero --- cups/auth.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cups/auth.c b/cups/auth.c index f2409350aa..d2956438de 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -90,6 +90,7 @@ static void cups_gss_printf(OM_uint32 major_status, OM_uint32 minor_status, # define cups_gss_printf(major, minor, message) # endif /* DEBUG */ #endif /* HAVE_GSSAPI */ +static int cups_is_local_connection(http_t *http); static int cups_local_auth(http_t *http); @@ -916,6 +917,14 @@ cups_gss_printf(OM_uint32 major_status,/* I - Major status code */ # endif /* DEBUG */ #endif /* HAVE_GSSAPI */ +static int /* O - 0 if not a local connection */ + /* 1 if local connection */ +cups_is_local_connection(http_t *http) /* I - HTTP connection to server */ +{ + if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0) + return 0; + return 1; +} /* * 'cups_local_auth()' - Get the local authorization certificate if @@ -958,7 +967,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * See if we are accessing localhost... */ - if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0) + if (!cups_is_local_connection(http)) { DEBUG_puts("8cups_local_auth: Not a local connection!"); return (1); From f629d079750a86b1b605c285f99c0dea3933ca50 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Tue, 27 Oct 2020 16:23:30 +0100 Subject: [PATCH 3/4] Try local kerberos ccache credentials only for remote servers If connecting to localhost then proceed to ask the client for the authorization using cupsGetPassword2. The get password callback will return 401 to the client with WWW-Authenticate: Negotiate. Fixes: #5596 Signed-off-by: Samuel Cabrero --- cups/auth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cups/auth.c b/cups/auth.c index d2956438de..9661657fc7 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -175,10 +175,10 @@ cupsDoAuthentication( DEBUG_printf(("2cupsDoAuthentication: Trying scheme \"%s\"...", scheme)); #ifdef HAVE_GSSAPI - if (!_cups_strcasecmp(scheme, "Negotiate")) + if (!_cups_strcasecmp(scheme, "Negotiate") && !cups_is_local_connection(http)) { /* - * Kerberos authentication... + * Kerberos authentication to remote server... */ int gss_status; /* Auth status */ @@ -202,7 +202,9 @@ cupsDoAuthentication( } else #endif /* HAVE_GSSAPI */ - if (_cups_strcasecmp(scheme, "Basic") && _cups_strcasecmp(scheme, "Digest")) + if (_cups_strcasecmp(scheme, "Basic") && + _cups_strcasecmp(scheme, "Digest") && + _cups_strcasecmp(scheme, "Negotiate")) { /* * Other schemes not yet supported... @@ -216,7 +218,7 @@ cupsDoAuthentication( * See if we should retry the current username:password... */ - if ((http->digest_tries > 1 || !http->userpass[0]) && (!_cups_strcasecmp(scheme, "Basic") || (!_cups_strcasecmp(scheme, "Digest")))) + if (http->digest_tries > 1 || !http->userpass[0]) { /* * Nope - get a new password from the user... From 0563a28b18b21d5574a5e0e38b74246146074bbf Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Tue, 27 Oct 2020 16:18:03 +0100 Subject: [PATCH 4/4] Allow Local authentication for Negotiate PeerCred is also possible if address family is AF_LOCAL. This will allow the CGI programs to generate the authorization from the local certificates based on PID also when Negotiate is used for local connections: Client CGI Browser <- Remote conn -> admin.cgi <--- Localhost conn ---> Scheduler | | | + --- HTTP/POST /admin/ --> | | | + --- CUPS-Get-Devices ------------> | | | | | | <-- 401 Unauthorized --------------+ | | WWW-Authenticate: | | | Negotiate, (PeerCred,) Local | | | | | <-- 401 Unauthorized -----+ | | WWW-Authenticate: | | | Negotiate | | | | | | --- HTTP/POST /admin/ --> | | | Authorization: + --- IPP CUPS-GetDevices ---------> | | Negotiate | Authorization: Local | | | | Fixes: #5596 Signed-off-by: Samuel Cabrero --- cups/auth.c | 5 ----- scheduler/client.c | 9 ++------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/cups/auth.c b/cups/auth.c index 9661657fc7..b6fec6b983 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -1043,11 +1043,6 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ } # endif /* HAVE_AUTHORIZATION_H */ -# ifdef HAVE_GSSAPI - if (cups_auth_find(www_auth, "Negotiate")) - return (1); -# endif /* HAVE_GSSAPI */ - # if defined(SO_PEERCRED) && defined(AF_LOCAL) /* * See if we can authenticate using the peer credentials provided over a diff --git a/scheduler/client.c b/scheduler/client.c index c2ee8f12a6..56797d58d7 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -2109,18 +2109,13 @@ cupsdSendHeader( } else if (auth_type == CUPSD_AUTH_NEGOTIATE) { -#if defined(SO_PEERCRED) && defined(AF_LOCAL) - if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL) - strlcpy(auth_str, "PeerCred", sizeof(auth_str)); - else -#endif /* SO_PEERCRED && AF_LOCAL */ strlcpy(auth_str, "Negotiate", sizeof(auth_str)); } - if (con->best && auth_type != CUPSD_AUTH_NEGOTIATE && !con->is_browser && !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost")) + if (con->best && !con->is_browser && !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost")) { /* - * Add a "trc" (try root certification) parameter for local non-Kerberos + * Add a "trc" (try root certification) parameter for local * requests when the request requires system group membership - then the * client knows the root certificate can/should be used. *