From 1ce6909d23aed05c3e24d2631a5468f09a0c486b Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Fri, 15 Feb 2019 17:06:35 -0500 Subject: [PATCH] Non-Kerberized IPP printing to Windows was broken (Issue #5515) --- CHANGES.md | 3 ++- cups/auth.c | 72 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index cc4369c525..c74c9d2577 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -CHANGES - 2.3b8 - 2019-02-14 +CHANGES - 2.3b8 - 2019-02-15 ============================ @@ -21,6 +21,7 @@ Changes in CUPS v2.3b8 Everywhere printer differently, resulting in different PPDs for the same printer (Issue #5484) - The web interface no longer provides access to the log files (Issue #5513) +- Non-Kerberized printing to Windows via IPP was broken (Issue #5515) - Eliminated use of private headers and some deprecated macOS APIs (Issue #5516) - Localization updates (Issue #5461, Issues #5471, Issue #5481, Issue #5486, Issue #5489, Issue #5491, Issue #5492, Issue #5493, Issue #5494, Issue #5495, diff --git a/cups/auth.c b/cups/auth.c index 0f7fd523a9..634ed1fba2 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -42,6 +42,9 @@ static const char *cups_auth_param(const char *scheme, const char *name, char *v static const char *cups_auth_scheme(const char *www_authenticate, char *scheme, size_t schemesize); #ifdef HAVE_GSSAPI +# define CUPS_GSS_OK 0 /* Successfully set credentials */ +# define CUPS_GSS_NONE -1 /* No credentials */ +# define CUPS_GSS_FAIL -2 /* Failed credentials/authentication */ # ifdef HAVE_GSS_ACQUIRE_CRED_EX_F # ifdef HAVE_GSS_GSSAPI_SPI_H # include @@ -168,6 +171,8 @@ cupsDoAuthentication( * Check the scheme name... */ + DEBUG_printf(("2cupsDoAuthentication: Trying scheme \"%s\"...", scheme)); + #ifdef HAVE_GSSAPI if (!_cups_strcasecmp(scheme, "Negotiate")) { @@ -175,18 +180,36 @@ cupsDoAuthentication( * Kerberos authentication... */ - if (_cupsSetNegotiateAuthString(http, method, resource)) + int gss_status; /* Auth status */ + + if ((gss_status = _cupsSetNegotiateAuthString(http, method, resource)) == CUPS_GSS_FAIL) { + DEBUG_puts("1cupsDoAuthentication: Negotiate failed."); http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } - - break; + else if (gss_status == CUPS_GSS_NONE) + { + DEBUG_puts("2cupsDoAuthentication: No credentials for Negotiate."); + continue; + } + else + { + DEBUG_puts("2cupsDoAuthentication: Using Negotiate."); + break; + } } else #endif /* HAVE_GSSAPI */ if (_cups_strcasecmp(scheme, "Basic") && _cups_strcasecmp(scheme, "Digest")) - continue; /* Not supported (yet) */ + { + /* + * Other schemes not yet supported... + */ + + DEBUG_printf(("2cupsDoAuthentication: Scheme \"%s\" not yet supported.", scheme)); + continue; + } /* * See if we should retry the current username:password... @@ -216,6 +239,7 @@ cupsDoAuthentication( if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) { + DEBUG_puts("1cupsDoAuthentication: User canceled password request."); http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } @@ -245,6 +269,7 @@ cupsDoAuthentication( char encode[256]; /* Base64 buffer */ + DEBUG_puts("2cupsDoAuthentication: Using Basic."); httpEncode64_2(encode, sizeof(encode), http->userpass, (int)strlen(http->userpass)); httpSetAuthString(http, "Basic", encode); break; @@ -263,19 +288,22 @@ cupsDoAuthentication( cups_auth_param(schemedata, "realm", http->realm, sizeof(http->realm)); if (_httpSetDigestAuthString(http, nonce, method, resource)) + { + DEBUG_puts("2cupsDoAuthentication: Using Basic."); break; + } } } if (http->authstring) { - DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring)); + DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\".", http->authstring)); return (0); } else { - DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"", www_auth)); + DEBUG_puts("1cupsDoAuthentication: No supported schemes."); http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); @@ -288,7 +316,7 @@ cupsDoAuthentication( * '_cupsSetNegotiateAuthString()' - Set the Kerberos authentication string. */ -int /* O - 0 on success, -1 on error */ +int /* O - 0 on success, negative on error */ _cupsSetNegotiateAuthString( http_t *http, /* I - Connection to server */ const char *method, /* I - Request method ("GET", "POST", "PUT") */ @@ -313,10 +341,16 @@ _cupsSetNegotiateAuthString( { DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos " "framework is not present"); - return (-1); + return (CUPS_GSS_NONE); } # endif /* __APPLE__ */ + if (!strcmp(http->hostname, "localhost") || http->hostname[0] == '/' || isdigit(http->hostname[0] & 255) || !strchr(http->hostname, '.')) + { + DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos not available for host \"%s\".", http->hostname)); + return (CUPS_GSS_NONE); + } + if (http->gssname == GSS_C_NO_NAME) { http->gssname = cups_gss_getname(http, _cupsGSSServiceName()); @@ -361,7 +395,7 @@ _cupsSetNegotiateAuthString( cupsUser(), http->gsshost); if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) - return (-1); + return (CUPS_GSS_FAIL); /* * Try to acquire credentials... @@ -415,18 +449,20 @@ _cupsSetNegotiateAuthString( } # endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */ - if (GSS_ERROR(major_status)) + if (major_status == GSS_S_NO_CRED) { - cups_gss_printf(major_status, minor_status, - "_cupsSetNegotiateAuthString: Unable to initialize " - "security context"); - return (-1); + cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: No credentials"); + return (CUPS_GSS_NONE); + } + else if (GSS_ERROR(major_status)) + { + cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Unable to initialize security context"); + return (CUPS_GSS_FAIL); } # ifdef DEBUG else if (major_status == GSS_S_CONTINUE_NEEDED) - cups_gss_printf(major_status, minor_status, - "_cupsSetNegotiateAuthString: Continuation needed!"); + cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Continuation needed"); # endif /* DEBUG */ if (output_token.length > 0 && output_token.length <= 65536) @@ -460,10 +496,10 @@ _cupsSetNegotiateAuthString( "large - %d bytes!", (int)output_token.length)); gss_release_buffer(&minor_status, &output_token); - return (-1); + return (CUPS_GSS_FAIL); } - return (0); + return (CUPS_GSS_OK); } #endif /* HAVE_GSSAPI */