From: Michael R Sweet Date: Tue, 21 Oct 2025 23:23:00 +0000 (-0400) Subject: Sync up documentation and other changes from libcups. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96c8874a9ee7b7e8b45370a453015bc1d5d5d5b3;p=thirdparty%2Fcups.git Sync up documentation and other changes from libcups. --- diff --git a/cups/auth.c b/cups/auth.c index 040837ea16..fc52a0cba1 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -1,16 +1,16 @@ -/* - * Authentication functions for CUPS. - * - * Copyright © 2020-2025 by OpenPrinting. - * Copyright © 2007-2019 by Apple Inc. - * Copyright © 1997-2007 by Easy Software Products. - * - * This file contains Kerberos support code, copyright 2006 by - * Jelmer Vernooij. - * - * Licensed under Apache License v2.0. See the file "LICENSE" for more - * information. - */ +// +// Authentication functions for CUPS. +// +// Copyright © 2020-2025 by OpenPrinting. +// Copyright © 2007-2019 by Apple Inc. +// Copyright © 1997-2007 by Easy Software Products. +// +// This file contains Kerberos support code, copyright 2006 by +// Jelmer Vernooij. +// +// Licensed under Apache License v2.0. See the file "LICENSE" for more +// information. +// #include "cups-private.h" #include "debug-internal.h" @@ -20,36 +20,37 @@ # include #else # include -#endif /* _WIN32 || __EMX__ */ +#endif // _WIN32 || __EMX__ #if HAVE_AUTHORIZATION_H # include -#endif /* HAVE_AUTHORIZATION_H */ +#endif // HAVE_AUTHORIZATION_H #if defined(SO_PEERCRED) && defined(AF_LOCAL) # include -#endif /* SO_PEERCRED && AF_LOCAL */ +#endif // SO_PEERCRED && AF_LOCAL -/* - * Local functions... - */ +// +// Local functions... +// static const char *cups_auth_find(const char *www_authenticate, const char *scheme); static const char *cups_auth_param(const char *scheme, const char *name, char *value, size_t valsize); static const char *cups_auth_scheme(const char *www_authenticate, char *scheme, size_t schemesize); +static bool cups_do_local_auth(http_t *http); #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 */ +# 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 # else # define GSS_AUTH_IDENTITY_TYPE_1 1 # define gss_acquire_cred_ex_f __ApplePrivate_gss_acquire_cred_ex_f -typedef struct gss_auth_identity /* @private@ */ +typedef struct gss_auth_identity // @private@ { uint32_t type; uint32_t flags; @@ -66,58 +67,57 @@ extern OM_uint32 gss_acquire_cred_ex_f(gss_status_id_t, const gss_name_t, gss_cred_id_t, gss_OID_set, OM_uint32)); -# endif /* HAVE_GSS_GSSAPI_SPI_H */ +# endif // HAVE_GSS_GSSAPI_SPI_H # include -typedef struct _cups_gss_acquire_s /* Acquire callback data */ +typedef struct _cups_gss_acquire_s // Acquire callback data { - dispatch_semaphore_t sem; /* Synchronization semaphore */ - OM_uint32 major; /* Returned status code */ - gss_cred_id_t creds; /* Returned credentials */ + dispatch_semaphore_t sem; // Synchronization semaphore + OM_uint32 major; // Returned status code + gss_cred_id_t creds; // Returned credentials } _cups_gss_acquire_t; static void cups_gss_acquire(void *ctx, OM_uint32 major, gss_status_id_t status, gss_cred_id_t creds, gss_OID_set oids, OM_uint32 time_rec); -# endif /* HAVE_GSS_ACQUIRE_CRED_EX_F */ +# endif // HAVE_GSS_ACQUIRE_CRED_EX_F static gss_name_t cups_gss_getname(http_t *http, const char *service_name); # ifdef DEBUG static void cups_gss_printf(OM_uint32 major_status, OM_uint32 minor_status, const char *message); # else # 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); - - -/* - * 'cupsDoAuthentication()' - Authenticate a request. - * - * This function should be called in response to a @code HTTP_STATUS_UNAUTHORIZED@ - * status, prior to resubmitting your request. - * - * @since CUPS 1.1.20@ - */ - -int /* O - 0 on success, -1 on error */ +# endif // DEBUG +#endif // HAVE_GSSAPI + + +// +// 'cupsDoAuthentication()' - Authenticate a request. +// +// This function performs authentication for a request. It should be called in +// response to a `HTTP_STATUS_UNAUTHORIZED` status, prior to resubmitting your +// request. +// +// @since CUPS 1.1.20@ +// + +int // O - `0` on success, `-1` on error cupsDoAuthentication( - http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ - const char *method, /* I - Request method ("GET", "POST", "PUT") */ - const char *resource) /* I - Resource path */ + http_t *http, // I - Connection to server or `CUPS_HTTP_DEFAULT` + const char *method, // I - Request method ("GET", "POST", "PUT") + const char *resource) // I - Resource path { - const char *password, /* Password string */ - *www_auth, /* WWW-Authenticate header */ - *schemedata; /* Scheme-specific data */ - char scheme[256], /* Scheme name */ - prompt[1024]; /* Prompt for user */ - int localauth; /* Local authentication result */ - _cups_globals_t *cg = _cupsGlobals(); /* Global data */ + const char *password, // Password string + *www_auth, // WWW-Authenticate header + *schemedata; // Scheme-specific data + char scheme[256], // Scheme name + prompt[1024]; // Prompt for user + _cups_globals_t *cg = _cupsGlobals(); // Global data DEBUG_printf("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")", (void *)http, method, resource); + // Range check input... if (!http) http = _cupsConnect(); @@ -127,19 +127,13 @@ cupsDoAuthentication( DEBUG_printf("2cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"", http->digest_tries, http->userpass); DEBUG_printf("2cupsDoAuthentication: WWW-Authenticate=\"%s\"", httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE)); - /* - * Clear the current authentication string... - */ - + // Clear the current authentication string... httpSetAuthString(http, NULL, NULL); - /* - * See if we can do local authentication... - */ - + // See if we can do local authentication... if (http->digest_tries < 3) { - if ((localauth = cups_local_auth(http)) == 0) + if (cups_do_local_auth(http)) { DEBUG_printf("2cupsDoAuthentication: authstring=\"%s\"", http->authstring); @@ -148,35 +142,21 @@ cupsDoAuthentication( return (0); } - else if (localauth == -1) - { - http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; - return (-1); /* Error or canceled */ - } } - /* - * Nope, loop through the authentication schemes to find the first we support. - */ - + // Nope, loop through the authentication schemes to find the first we support. www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE); for (schemedata = cups_auth_scheme(www_auth, scheme, sizeof(scheme)); schemedata; schemedata = cups_auth_scheme(schemedata + strlen(scheme), scheme, sizeof(scheme))) { - /* - * Check the scheme name... - */ - + // Check the scheme name... DEBUG_printf("2cupsDoAuthentication: Trying scheme \"%s\"...", scheme); #ifdef HAVE_GSSAPI - if (!_cups_strcasecmp(scheme, "Negotiate") && !cups_is_local_connection(http)) + if (!_cups_strcasecmp(scheme, "Negotiate") && !httpAddrIsLocalhost(httpGetAddress(http))) { - /* - * Kerberos authentication to remote server... - */ - - int gss_status; /* Auth status */ + // Kerberos authentication to remote server... + int gss_status; // Auth status if ((gss_status = _cupsSetNegotiateAuthString(http, method, resource)) == CUPS_GSS_FAIL) { @@ -196,16 +176,16 @@ cupsDoAuthentication( } } else -#endif /* HAVE_GSSAPI */ +#endif // HAVE_GSSAPI if (!_cups_strcasecmp(scheme, "Bearer")) { // OAuth 2.0 (Bearer) authentication... - const char *bearer = NULL; /* Bearer token string, if any */ + const char *bearer = NULL; // Bearer token string, if any if (cg->oauth_cb) { // Try callback... - char scope[HTTP_MAX_VALUE]; /* scope="xyz" string */ + char scope[HTTP_MAX_VALUE]; // scope="xyz" string cups_auth_param(schemedata, "realm", http->realm, sizeof(http->realm)); @@ -230,26 +210,17 @@ cupsDoAuthentication( } else if (_cups_strcasecmp(scheme, "Basic") && _cups_strcasecmp(scheme, "Digest") && _cups_strcasecmp(scheme, "Negotiate")) { - /* - * Other schemes not yet supported... - */ - + // Other schemes not yet supported... DEBUG_printf("2cupsDoAuthentication: Scheme \"%s\" not yet supported.", scheme); continue; } - /* - * See if we should retry the current username:password... - */ - + // See if we should retry the current username:password... if (http->digest_tries > 1 || !http->userpass[0]) { - /* - * Nope - get a new password from the user... - */ - + // Nope - get a new password from the user... char default_username[HTTP_MAX_VALUE]; - /* Default username */ + // Default username if (!cg->lang_default) cg->lang_default = cupsLangDefault(); @@ -259,8 +230,8 @@ cupsDoAuthentication( snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsGetUser(), http->hostname[0] == '/' ? "localhost" : http->hostname); - http->digest_tries = _cups_strncasecmp(scheme, "Digest", 6) != 0; - http->userpass[0] = '\0'; + http->digest_tries = _cups_strncasecmp(scheme, "Digest", 6) != 0; + http->userpass[0] = '\0'; if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) { @@ -272,7 +243,9 @@ cupsDoAuthentication( snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsGetUser(), password); } else if (http->status == HTTP_STATUS_UNAUTHORIZED) + { http->digest_tries ++; + } if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3) { @@ -282,30 +255,21 @@ cupsDoAuthentication( return (-1); } - /* - * Got a password; encode it for the server... - */ - + // Got a password; encode it for the server... if (!_cups_strcasecmp(scheme, "Basic")) { - /* - * Basic authentication... - */ - - char encode[256]; /* Base64 buffer */ + // Basic authentication... + char encode[256]; // Base64 buffer DEBUG_puts("2cupsDoAuthentication: Using Basic."); - httpEncode64_2(encode, sizeof(encode), http->userpass, (int)strlen(http->userpass)); + httpEncode64_3(encode, sizeof(encode), http->userpass, strlen(http->userpass), false); httpSetAuthString(http, "Basic", encode); break; } else if (!_cups_strcasecmp(scheme, "Digest")) { - /* - * Digest authentication... - */ - - char nonce[HTTP_MAX_VALUE]; /* nonce="xyz" string */ + // Digest authentication... + char nonce[HTTP_MAX_VALUE]; // nonce="xyz" string cups_auth_param(schemedata, "algorithm", http->algorithm, sizeof(http->algorithm)); cups_auth_param(schemedata, "nonce", nonce, sizeof(nonce)); @@ -338,34 +302,31 @@ cupsDoAuthentication( #ifdef HAVE_GSSAPI -/* - * '_cupsSetNegotiateAuthString()' - Set the Kerberos authentication string. - */ +// +// '_cupsSetNegotiateAuthString()' - Set the Kerberos authentication string. +// -int /* O - 0 on success, negative 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") */ - const char *resource) /* I - Resource path */ + http_t *http, // I - Connection to server + const char *method, // I - Request method ("GET", "POST", "PUT") + const char *resource) // I - Resource path { - OM_uint32 minor_status, /* Minor status code */ - major_status; /* Major status code */ + OM_uint32 minor_status, // Minor status code + major_status; // Major status code gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - /* Output token */ + // Output token # ifdef __APPLE__ - /* - * If the weak-linked GSSAPI/Kerberos library is not present, don't try - * to use it... - */ - + // If the weak-linked GSSAPI/Kerberos library is not present, don't try + // to use it... if (&gss_init_sec_context == NULL) { DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos " "framework is not present"); return (CUPS_GSS_NONE); } -# endif /* __APPLE__ */ +# endif // __APPLE__ if (!strcmp(http->hostname, "localhost") || http->hostname[0] == '/' || isdigit(http->hostname[0] & 255) || !strchr(http->hostname, '.')) { @@ -396,18 +357,15 @@ _cupsSetNegotiateAuthString( # ifdef HAVE_GSS_ACQUIRE_CRED_EX_F if (major_status == GSS_S_NO_CRED) { - /* - * Ask the user for credentials... - */ - - char prompt[1024], /* Prompt for user */ - userbuf[256]; /* Kerberos username */ - const char *username, /* Username string */ - *password; /* Password string */ - _cups_gss_acquire_t data; /* Callback data */ - gss_auth_identity_desc identity; /* Kerberos user identity */ + // Ask the user for credentials... + char prompt[1024], // Prompt for user + userbuf[256]; // Kerberos username + const char *username, // Username string + *password; // Password string + _cups_gss_acquire_t data; // Callback data + gss_auth_identity_desc identity; // Kerberos user identity _cups_globals_t *cg = _cupsGlobals(); - /* Per-thread global data */ + // Per-thread global data if (!cg->lang_default) cg->lang_default = cupsLangDefault(); @@ -419,10 +377,7 @@ _cupsSetNegotiateAuthString( if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) return (CUPS_GSS_FAIL); - /* - * Try to acquire credentials... - */ - + // Try to acquire credentials... username = cupsGetUser(); if (!strchr(username, '@')) { @@ -455,7 +410,7 @@ _cupsSetNegotiateAuthString( if (major_status == GSS_S_COMPLETE) { - OM_uint32 release_minor; /* Minor status from releasing creds */ + OM_uint32 release_minor; // Minor status from releasing creds major_status = gss_init_sec_context(&minor_status, data.creds, &http->gssctx, @@ -472,7 +427,7 @@ _cupsSetNegotiateAuthString( # else (void)method; (void)resource; -# endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */ +# endif // HAVE_GSS_ACQUIRED_CRED_EX_F if (major_status == GSS_S_NO_CRED) { @@ -488,18 +443,15 @@ _cupsSetNegotiateAuthString( # ifdef DEBUG else if (major_status == GSS_S_CONTINUE_NEEDED) cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Continuation needed"); -# endif /* DEBUG */ +# endif // DEBUG if (output_token.length > 0 && output_token.length <= 65536) { - /* - * Allocate the authorization string since Windows KDCs can have - * arbitrarily large credentials... - */ - - int authsize = 10 + /* "Negotiate " */ + // Allocate the authorization string since Windows KDCs can have + // arbitrarily large credentials... + int authsize = 10 + // "Negotiate " (((int)output_token.length * 4 / 3 + 3) & ~3) + 1; - /* Base64 + nul */ + // Base64 + nul httpSetAuthString(http, NULL, NULL); @@ -510,8 +462,7 @@ _cupsSetNegotiateAuthString( } cupsCopyString(http->authstring, "Negotiate ", (size_t)authsize); - httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value, - (int)output_token.length); + httpEncode64_3(http->authstring + 10, authsize - 10, output_token.value, output_token.length, false); gss_release_buffer(&minor_status, &output_token); } @@ -525,64 +476,49 @@ _cupsSetNegotiateAuthString( return (CUPS_GSS_OK); } -#endif /* HAVE_GSSAPI */ +#endif // HAVE_GSSAPI -/* - * 'cups_auth_find()' - Find the named WWW-Authenticate scheme. - * - * The "www_authenticate" parameter points to the current position in the header. - * - * Returns @code NULL@ if the auth scheme is not present. - */ +// +// 'cups_auth_find()' - Find the named WWW-Authenticate scheme. +// +// The "www_authenticate" argument points to the current position in the header. +// +// Returns `NULL` if the auth scheme is not present. +// -static const char * /* O - Start of matching scheme or @code NULL@ if not found */ -cups_auth_find(const char *www_authenticate, /* I - Pointer into WWW-Authenticate header */ - const char *scheme) /* I - Authentication scheme */ +static const char * // O - Start of matching scheme or `NULL` if not found +cups_auth_find(const char *www_authenticate, // I - Pointer into WWW-Authenticate header + const char *scheme) // I - Authentication scheme { - size_t schemelen = strlen(scheme); /* Length of scheme */ + size_t schemelen = strlen(scheme); // Length of scheme DEBUG_printf("8cups_auth_find(www_authenticate=\"%s\", scheme=\"%s\"(%d))", www_authenticate, scheme, (int)schemelen); while (*www_authenticate) { - /* - * Skip leading whitespace and commas... - */ - + // Skip leading whitespace and commas... DEBUG_printf("9cups_auth_find: Before whitespace: \"%s\"", www_authenticate); while (isspace(*www_authenticate & 255) || *www_authenticate == ',') www_authenticate ++; DEBUG_printf("9cups_auth_find: After whitespace: \"%s\"", www_authenticate); - /* - * See if this is "Scheme" followed by whitespace or the end of the string. - */ - + // See if this is "Scheme" followed by whitespace or the end of the string. if (!strncmp(www_authenticate, scheme, schemelen) && (isspace(www_authenticate[schemelen] & 255) || www_authenticate[schemelen] == ',' || !www_authenticate[schemelen])) { - /* - * Yes, this is the start of the scheme-specific information... - */ - + // Yes, this is the start of the scheme-specific information... DEBUG_printf("9cups_auth_find: Returning \"%s\".", www_authenticate); return (www_authenticate); } - /* - * Skip the scheme name or param="value" string... - */ - + // Skip the scheme name or param="value" string... while (!isspace(*www_authenticate & 255) && *www_authenticate) { if (*www_authenticate == '\"') { - /* - * Skip quoted value... - */ - + // Skip quoted value... www_authenticate ++; while (*www_authenticate && *www_authenticate != '\"') www_authenticate ++; @@ -602,21 +538,21 @@ cups_auth_find(const char *www_authenticate, /* I - Pointer into WWW-Authenticat } -/* - * 'cups_auth_param()' - Copy the value for the named authentication parameter, - * if present. - */ +// +// 'cups_auth_param()' - Copy the value for the named authentication parameter, +// if present. +// -static const char * /* O - Parameter value or @code NULL@ if not present */ -cups_auth_param(const char *scheme, /* I - Pointer to auth data */ - const char *name, /* I - Name of parameter */ - char *value, /* I - Value buffer */ - size_t valsize) /* I - Size of value buffer */ +static const char * // O - Parameter value or `NULL` if not present +cups_auth_param(const char *scheme, // I - Pointer to auth data + const char *name, // I - Name of parameter + char *value, // I - Value buffer + size_t valsize) // I - Size of value buffer { - char *valptr = value, /* Pointer into value buffer */ - *valend = value + valsize - 1; /* Pointer to end of buffer */ - size_t namelen = strlen(name); /* Name length */ - int param; /* Is this a parameter? */ + char *valptr = value, // Pointer into value buffer + *valend = value + valsize - 1; // Pointer to end of buffer + size_t namelen = strlen(name); // Name length + bool param; // Is this a parameter? DEBUG_printf("8cups_auth_param(scheme=\"%s\", name=\"%s\", value=%p, valsize=%d)", scheme, name, (void *)value, (int)valsize); @@ -631,10 +567,7 @@ cups_auth_param(const char *scheme, /* I - Pointer to auth data */ if (!strncmp(scheme, name, namelen) && scheme[namelen] == '=') { - /* - * Found the parameter, copy the value... - */ - + // Found the parameter, copy the value... scheme += namelen + 1; if (*scheme == '\"') { @@ -666,22 +599,18 @@ cups_auth_param(const char *scheme, /* I - Pointer to auth data */ return (value); } - /* - * Skip the param=value string... - */ - - param = 0; + // Skip the param=value string... + param = false; while (!isspace(*scheme & 255) && *scheme) { if (*scheme == '=') - param = 1; + { + param = true; + } else if (*scheme == '\"') { - /* - * Skip quoted value... - */ - + // Skip quoted value... scheme ++; while (*scheme && *scheme != '\"') scheme ++; @@ -690,11 +619,8 @@ cups_auth_param(const char *scheme, /* I - Pointer to auth data */ scheme ++; } - /* - * If this wasn't a parameter, we are at the end of this scheme's - * parameters... - */ - + // If this wasn't a parameter, we are at the end of this scheme's + // parameters... if (!param) break; } @@ -707,55 +633,51 @@ cups_auth_param(const char *scheme, /* I - Pointer to auth data */ } -/* - * 'cups_auth_scheme()' - Get the (next) WWW-Authenticate scheme. - * - * The "www_authenticate" parameter points to the current position in the header. - * - * Returns @code NULL@ if there are no (more) auth schemes present. - */ +// +// 'cups_auth_scheme()' - Get the (next) WWW-Authenticate scheme. +// +// The "www_authenticate" argument points to the current position in the header. +// +// Returns `NULL` if there are no (more) auth schemes present. +// -static const char * /* O - Start of scheme or @code NULL@ if not found */ -cups_auth_scheme(const char *www_authenticate, /* I - Pointer into WWW-Authenticate header */ - char *scheme, /* I - Scheme name buffer */ - size_t schemesize) /* I - Size of buffer */ +static const char * // O - Start of scheme or `NULL` if not found +cups_auth_scheme(const char *www_authenticate, // I - Pointer into WWW-Authenticate header + char *scheme, // I - Scheme name buffer + size_t schemesize) // I - Size of buffer { - const char *start; /* Start of scheme data */ - char *sptr = scheme, /* Pointer into scheme buffer */ - *send = scheme + schemesize - 1;/* End of scheme buffer */ - int param; /* Is this a parameter? */ + const char *start; // Start of scheme data + char *sptr = scheme, // Pointer into scheme buffer + *send = scheme + schemesize - 1;// End of scheme buffer + bool param; // Is this a parameter? DEBUG_printf("8cups_auth_scheme(www_authenticate=\"%s\", scheme=%p, schemesize=%u)", www_authenticate, (void *)scheme, (unsigned)schemesize); while (*www_authenticate) { - /* - * Skip leading whitespace and commas... - */ - + // Skip leading whitespace and commas... while (isspace(*www_authenticate & 255) || *www_authenticate == ',') www_authenticate ++; - /* - * Parse the scheme name or param="value" string... - */ - - for (sptr = scheme, start = www_authenticate, param = 0; *www_authenticate && *www_authenticate != ',' && !isspace(*www_authenticate & 255); www_authenticate ++) + // Parse the scheme name or param="value" string... + for (sptr = scheme, start = www_authenticate, param = false; *www_authenticate && *www_authenticate != ',' && !isspace(*www_authenticate & 255); www_authenticate ++) { if (*www_authenticate == '=') - param = 1; + { + param = true; + } else if (!param && sptr < send) + { *sptr++ = *www_authenticate; + } else if (*www_authenticate == '\"') { - /* - * Skip quoted value... - */ - - + // Skip quoted value... do + { www_authenticate ++; + } while (*www_authenticate && *www_authenticate != '\"'); } } @@ -778,227 +700,45 @@ cups_auth_scheme(const char *www_authenticate, /* I - Pointer into WWW-Authentic } -#ifdef HAVE_GSSAPI -# ifdef HAVE_GSS_ACQUIRE_CRED_EX_F -/* - * 'cups_gss_acquire()' - Kerberos credentials callback. - */ -static void -cups_gss_acquire( - void *ctx, /* I - Caller context */ - OM_uint32 major, /* I - Major error code */ - gss_status_id_t status, /* I - Status (unused) */ - gss_cred_id_t creds, /* I - Credentials (if any) */ - gss_OID_set oids, /* I - Mechanism OIDs (unused) */ - OM_uint32 time_rec) /* I - Timestamp (unused) */ -{ - uint32_t min; /* Minor error code */ - _cups_gss_acquire_t *data; /* Callback data */ - - - (void)status; - (void)time_rec; - - data = (_cups_gss_acquire_t *)ctx; - data->major = major; - data->creds = creds; - - gss_release_oid_set(&min, &oids); - dispatch_semaphore_signal(data->sem); -} -# endif /* HAVE_GSS_ACQUIRE_CRED_EX_F */ - - -/* - * 'cups_gss_getname()' - Get CUPS service credentials for authentication. - */ - -static gss_name_t /* O - Server name */ -cups_gss_getname( - http_t *http, /* I - Connection to server */ - const char *service_name) /* I - Service name */ -{ - gss_buffer_desc token = GSS_C_EMPTY_BUFFER; - /* Service token */ - OM_uint32 major_status, /* Major status code */ - minor_status; /* Minor status code */ - gss_name_t server_name; /* Server name */ - char buf[1024]; /* Name buffer */ - - - DEBUG_printf("7cups_gss_getname(http=%p, service_name=\"%s\")", (void *)http, service_name); - - /* - * Get the hostname... - */ - - if (!http->gsshost[0]) - { - httpGetHostname(http, http->gsshost, sizeof(http->gsshost)); - - if (!strcmp(http->gsshost, "localhost")) - { - if (gethostname(http->gsshost, sizeof(http->gsshost)) < 0) - { - DEBUG_printf("1cups_gss_getname: gethostname() failed: %s", strerror(errno)); - http->gsshost[0] = '\0'; - return (NULL); - } - - if (!strchr(http->gsshost, '.')) - { - /* - * The hostname is not a FQDN, so look it up... - */ - - struct hostent *host; /* Host entry to get FQDN */ - - if ((host = gethostbyname(http->gsshost)) != NULL && host->h_name) - { - /* - * Use the resolved hostname... - */ - - cupsCopyString(http->gsshost, host->h_name, sizeof(http->gsshost)); - } - else - { - DEBUG_printf("1cups_gss_getname: gethostbyname(\"%s\") failed.", http->gsshost); - http->gsshost[0] = '\0'; - return (NULL); - } - } - } - } - - /* - * Get a service name we can use for authentication purposes... - */ - - snprintf(buf, sizeof(buf), "%s@%s", service_name, http->gsshost); - - DEBUG_printf("8cups_gss_getname: Looking up \"%s\".", buf); - - token.value = buf; - token.length = strlen(buf); - server_name = GSS_C_NO_NAME; - major_status = gss_import_name(&minor_status, &token, - GSS_C_NT_HOSTBASED_SERVICE, - &server_name); - - if (GSS_ERROR(major_status)) - { - cups_gss_printf(major_status, minor_status, - "cups_gss_getname: gss_import_name() failed"); - return (NULL); - } - - return (server_name); -} - - -# ifdef DEBUG -/* - * 'cups_gss_printf()' - Show debug error messages from GSSAPI. - */ - -static void -cups_gss_printf(OM_uint32 major_status,/* I - Major status code */ - OM_uint32 minor_status,/* I - Minor status code */ - const char *message) /* I - Prefix for error message */ -{ - OM_uint32 err_major_status, /* Major status code for display */ - err_minor_status; /* Minor status code for display */ - OM_uint32 msg_ctx; /* Message context */ - gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER, - /* Major status message */ - minor_status_string = GSS_C_EMPTY_BUFFER; - /* Minor status message */ - - - msg_ctx = 0; - err_major_status = gss_display_status(&err_minor_status, - major_status, - GSS_C_GSS_CODE, - GSS_C_NO_OID, - &msg_ctx, - &major_status_string); - - if (!GSS_ERROR(err_major_status)) - gss_display_status(&err_minor_status, minor_status, GSS_C_MECH_CODE, - GSS_C_NULL_OID, &msg_ctx, &minor_status_string); - - DEBUG_printf("1%s: %s, %s", message, (char *)major_status_string.value, (char *)minor_status_string.value); - - gss_release_buffer(&err_minor_status, &major_status_string); - gss_release_buffer(&err_minor_status, &minor_status_string); -} -# 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 - * available/applicable. - */ +// +// 'cups_do_local_auth()' - Use local credentials if available/applicable. +// -static int /* O - 0 if available */ - /* 1 if not available */ - /* -1 error */ -cups_local_auth(http_t *http) /* I - HTTP connection to server */ +static bool // O - `true` if authorized, `false` otherwise +cups_do_local_auth(http_t *http) // I - HTTP connection to server { -#if defined(_WIN32) || defined(__EMX__) - /* - * Currently _WIN32 and OS-2 do not support the CUPS server... - */ - - return (1); -#else - int pid; /* Current process ID */ - FILE *fp; /* Certificate file */ - char trc[16], /* Try Root Certificate parameter */ - filename[1024]; /* Certificate filename */ - const char *www_auth, /* WWW-Authenticate header */ - *schemedata; /* Data for the named auth scheme */ - _cups_globals_t *cg = _cupsGlobals(); /* Global data */ +#if !_WIN32 && !__EMX__ + int pid; // Current process ID + FILE *fp; // Certificate file + char trc[16], // Try Root Certificate parameter + filename[1024]; // Certificate filename + const char *www_auth, // WWW-Authenticate header + *schemedata; // Data for the named auth scheme + _cups_globals_t *cg = _cupsGlobals(); // Global data # if defined(HAVE_AUTHORIZATION_H) - OSStatus status; /* Status */ - AuthorizationItem auth_right; /* Authorization right */ - AuthorizationRights auth_rights; /* Authorization rights */ - AuthorizationFlags auth_flags; /* Authorization flags */ - AuthorizationExternalForm auth_extrn; /* Authorization ref external */ - char auth_key[1024]; /* Buffer */ - char buffer[1024]; /* Buffer */ -# endif /* HAVE_AUTHORIZATION_H */ + OSStatus status; // Status + AuthorizationItem auth_right; // Authorization right + AuthorizationRights auth_rights; // Authorization rights + AuthorizationFlags auth_flags; // Authorization flags + AuthorizationExternalForm auth_extrn; // Authorization ref external + char auth_key[1024]; // Buffer + char buffer[1024]; // Buffer +# endif // HAVE_AUTHORIZATION_H DEBUG_printf("7cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"", (void *)http, httpAddrString(http->hostaddr, filename, sizeof(filename)), http->hostname); - /* - * See if we are accessing localhost... - */ - - if (!cups_is_local_connection(http)) + // See if we are accessing localhost... + if (!httpAddrIsLocalhost(httpGetAddress(http))) { - DEBUG_puts("8cups_local_auth: Not a local connection!"); - return (1); + DEBUG_puts("8cups_local_auth: Not a local connection, returning false."); + return (false); } www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE); # if defined(HAVE_AUTHORIZATION_H) - /* - * Delete any previous authorization reference... - */ - + // Delete any previous authorization reference... if (http->auth_ref) { AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults); @@ -1010,8 +750,8 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &http->auth_ref); if (status != errAuthorizationSuccess) { - DEBUG_printf("8cups_local_auth: AuthorizationCreate() returned %d", (int)status); - return (-1); + DEBUG_printf("8cups_local_auth: AuthorizationCreate() returned %d, returning false.", (int)status); + return (false); } auth_right.name = auth_key; @@ -1035,47 +775,37 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ if (status == errAuthorizationSuccess) { - /* - * Set the authorization string and return... - */ - - httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn, - sizeof(auth_extrn)); + // Set the authorization string and return... + httpEncode64_3(buffer, sizeof(buffer), (void *)&auth_extrn, sizeof(auth_extrn), false); httpSetAuthString(http, "AuthRef", buffer); - DEBUG_printf("8cups_local_auth: Returning authstring=\"%s\"", http->authstring); - return (0); + DEBUG_printf("8cups_local_auth: Returning authstring=\"%s\", returning true.", http->authstring); + return (true); } else if (status == errAuthorizationCanceled) - return (-1); + { + return (false); + } - DEBUG_printf("9cups_local_auth: AuthorizationCopyRights() returned %d", (int)status); + DEBUG_printf("9cups_local_auth: AuthorizationCopyRights() returned %d.", (int)status); - /* - * Fall through to try certificates... - */ + // Fall through to try certificates... } -# endif /* HAVE_AUTHORIZATION_H */ +# endif // HAVE_AUTHORIZATION_H # if defined(SO_PEERCRED) && defined(AF_LOCAL) - /* - * See if we can authenticate using the peer credentials provided over a - * domain socket; if so, specify "PeerCred username" as the authentication - * information... - */ - + // See if we can authenticate using the peer credentials provided over a + // domain socket; if so, specify "PeerCred username" as the authentication + // information... if (http->hostaddr->addr.sa_family == AF_LOCAL && - !getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */ + !getenv("GATEWAY_INTERFACE") && // Not via CGI programs... cups_auth_find(www_auth, "PeerCred")) { - /* - * Verify that the current cupsGetUser() matches the current UID... - */ - - struct passwd pwd; /* Password information */ - struct passwd *result; /* Auxiliary pointer */ - const char *username; /* Current username */ + // Verify that the current cupsGetUser() matches the current UID... + struct passwd pwd; // Password information + struct passwd *result; // Auxiliary pointer + const char *username; // Current username username = cupsGetUser(); @@ -1084,38 +814,29 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ { httpSetAuthString(http, "PeerCred", username); - DEBUG_printf("8cups_local_auth: Returning authstring=\"%s\"", http->authstring); + DEBUG_printf("8cups_local_auth: Returning authstring=\"%s\", returning true.", http->authstring); - return (0); + return (true); } } -# endif /* SO_PEERCRED && AF_LOCAL */ +# endif // SO_PEERCRED && AF_LOCAL if ((schemedata = cups_auth_find(www_auth, "Local")) == NULL) - return (1); - - /* - * Try opening a certificate file for this PID. If that fails, - * try the root certificate... - */ + return (false); + // Try opening a certificate file for this PID. If that fails, + // try the root certificate... pid = getpid(); snprintf(filename, sizeof(filename), "%s/certs/%d", cg->cups_statedir, pid); if ((fp = fopen(filename, "r")) == NULL && pid > 0) { - /* - * No certificate for this PID; see if we can get the root certificate... - */ - + // No certificate for this PID; see if we can get the root certificate... DEBUG_printf("9cups_local_auth: Unable to open file \"%s\": %s", filename, strerror(errno)); if (!cups_auth_param(schemedata, "trc", trc, sizeof(trc))) { - /* - * Scheduler doesn't want us to use the root certificate... - */ - - return (1); + // Scheduler doesn't want us to use the root certificate... + return (false); } snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir); @@ -1125,30 +846,173 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ if (fp) { - /* - * Read the certificate from the file... - */ - - char certificate[33], /* Certificate string */ - *certptr; /* Pointer to certificate string */ + // Read the certificate from the file... + char certificate[33], // Certificate string + *certptr; // Pointer to certificate string certptr = fgets(certificate, sizeof(certificate), fp); fclose(fp); if (certptr) { - /* - * Set the authorization string and return... - */ - + // Set the authorization string and return... httpSetAuthString(http, "Local", certificate); - DEBUG_printf("8cups_local_auth: Returning authstring=\"%s\"", http->authstring); + DEBUG_printf("8cups_local_auth: Returning authstring=\"%s\", returning true.", http->authstring); - return (0); + return (true); + } + } +#endif // !_WIN32 && !__EMX__ + + DEBUG_puts("8cups_do_local_auth: Returning false."); + + return (false); +} + + +#ifdef HAVE_GSSAPI +# ifdef HAVE_GSS_ACQUIRE_CRED_EX_F +// +// 'cups_gss_acquire()' - Kerberos credentials callback. +// +static void +cups_gss_acquire( + void *ctx, // I - Caller context + OM_uint32 major, // I - Major error code + gss_status_id_t status, // I - Status (unused) + gss_cred_id_t creds, // I - Credentials (if any) + gss_OID_set oids, // I - Mechanism OIDs (unused) + OM_uint32 time_rec) // I - Timestamp (unused) +{ + uint32_t min; // Minor error code + _cups_gss_acquire_t *data; // Callback data + + + (void)status; + (void)time_rec; + + data = (_cups_gss_acquire_t *)ctx; + data->major = major; + data->creds = creds; + + gss_release_oid_set(&min, &oids); + dispatch_semaphore_signal(data->sem); +} +# endif // HAVE_GSS_ACQUIRE_CRED_EX_F + + +// +// 'cups_gss_getname()' - Get CUPS service credentials for authentication. +// + +static gss_name_t // O - Server name +cups_gss_getname( + http_t *http, // I - Connection to server + const char *service_name) // I - Service name +{ + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + // Service token + OM_uint32 major_status, // Major status code + minor_status; // Minor status code + gss_name_t server_name; // Server name + char buf[1024]; // Name buffer + + + DEBUG_printf("7cups_gss_getname(http=%p, service_name=\"%s\")", (void *)http, service_name); + + // Get the hostname... + if (!http->gsshost[0]) + { + httpGetHostname(http, http->gsshost, sizeof(http->gsshost)); + + if (!strcmp(http->gsshost, "localhost")) + { + if (gethostname(http->gsshost, sizeof(http->gsshost)) < 0) + { + DEBUG_printf("1cups_gss_getname: gethostname() failed: %s", strerror(errno)); + http->gsshost[0] = '\0'; + return (NULL); + } + + if (!strchr(http->gsshost, '.')) + { + // The hostname is not a FQDN, so look it up... + struct hostent *host; // Host entry to get FQDN + + if ((host = gethostbyname(http->gsshost)) != NULL && host->h_name) + { + // Use the resolved hostname... + cupsCopyString(http->gsshost, host->h_name, sizeof(http->gsshost)); + } + else + { + DEBUG_printf("1cups_gss_getname: gethostbyname(\"%s\") failed.", http->gsshost); + http->gsshost[0] = '\0'; + return (NULL); + } + } } } - return (1); -#endif /* _WIN32 || __EMX__ */ + // Get a service name we can use for authentication purposes... + snprintf(buf, sizeof(buf), "%s@%s", service_name, http->gsshost); + + DEBUG_printf("8cups_gss_getname: Looking up \"%s\".", buf); + + token.value = buf; + token.length = strlen(buf); + server_name = GSS_C_NO_NAME; + major_status = gss_import_name(&minor_status, &token, + GSS_C_NT_HOSTBASED_SERVICE, + &server_name); + + if (GSS_ERROR(major_status)) + { + cups_gss_printf(major_status, minor_status, + "cups_gss_getname: gss_import_name() failed"); + return (NULL); + } + + return (server_name); +} + + +# ifdef DEBUG +// +// 'cups_gss_printf()' - Show debug error messages from GSSAPI. +// + +static void +cups_gss_printf(OM_uint32 major_status,// I - Major status code + OM_uint32 minor_status,// I - Minor status code + const char *message) // I - Prefix for error message +{ + OM_uint32 err_major_status, // Major status code for display + err_minor_status; // Minor status code for display + OM_uint32 msg_ctx; // Message context + gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER, + // Major status message + minor_status_string = GSS_C_EMPTY_BUFFER; + // Minor status message + + + msg_ctx = 0; + err_major_status = gss_display_status(&err_minor_status, + major_status, + GSS_C_GSS_CODE, + GSS_C_NO_OID, + &msg_ctx, + &major_status_string); + + if (!GSS_ERROR(err_major_status)) + gss_display_status(&err_minor_status, minor_status, GSS_C_MECH_CODE, + GSS_C_NULL_OID, &msg_ctx, &minor_status_string); + + DEBUG_printf("1%s: %s, %s", message, (char *)major_status_string.value, (char *)minor_status_string.value); + + gss_release_buffer(&err_minor_status, &major_status_string); + gss_release_buffer(&err_minor_status, &minor_status_string); } +# endif // DEBUG +#endif // HAVE_GSSAPI diff --git a/cups/http.c b/cups/http.c index 5c0c6a04fa..a469fde2ba 100644 --- a/cups/http.c +++ b/cups/http.c @@ -30,7 +30,7 @@ // Local functions... // -static void http_add_field(http_t *http, http_field_t field, const char *value, int append); +static void http_add_field(http_t *http, http_field_t field, const char *value, bool append); static void http_content_coding_finish(http_t *http); static void http_content_coding_start(http_t *http, const char *value); static http_t *http_create(const char *host, int port, http_addrlist_t *addrlist, int family, http_encryption_t encryption, int blocking, _http_mode_t mode); @@ -2775,7 +2775,7 @@ httpSetField(http_t *http, // I - HTTP connection if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX || !value) return; - http_add_field(http, field, value, 0); + http_add_field(http, field, value, false); } @@ -3026,7 +3026,7 @@ _httpUpdate(http_t *http, // I - HTTP connection } else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN) { - http_add_field(http, field, value, 1); + http_add_field(http, field, value, true); if (field == HTTP_FIELD_AUTHENTICATION_INFO) httpGetSubField2(http, HTTP_FIELD_AUTHENTICATION_INFO, "nextnonce", http->nextnonce, (int)sizeof(http->nextnonce)); @@ -3589,7 +3589,7 @@ static void http_add_field(http_t *http, // I - HTTP connection http_field_t field, // I - HTTP field const char *value, // I - Value string - int append) // I - Append value? + bool append) // I - Append value? { char temp[1024], // Temporary value string combined[HTTP_MAX_VALUE]; diff --git a/cups/json.c b/cups/json.c index 4877ad865e..8452a335dd 100644 --- a/cups/json.c +++ b/cups/json.c @@ -1360,7 +1360,7 @@ cupsJSONNew(cups_json_t *parent, // I - Parent JSON node or `NULL` for a root n cups_json_t * // O - JSON node cupsJSONNewKey(cups_json_t *parent, // I - Parent JSON node or `NULL` for a root node - cups_json_t *after, // I - Previous sibling node or `NULL` to append to the end + cups_json_t *after, // I - Previous sibling node or `NULL` to append to the end const char *key) // I - Key string { cups_json_t *node; // JSON node diff --git a/cups/oauth.c b/cups/oauth.c index 7aa371ed49..de2c225c19 100644 --- a/cups/oauth.c +++ b/cups/oauth.c @@ -322,15 +322,15 @@ cupsOAuthCopyUserId( // This function performs a local/"native" OAuth authorization flow to obtain an // authorization code for use with the @link cupsOAuthGetTokens@ function. // -// The "auth_uri" parameter specifies the URI for the OAuth Authorization -// Server. The "metadata" parameter specifies the Authorization Server metadata +// The "auth_uri" argument specifies the URI for the OAuth Authorization +// Server. The "metadata" argument specifies the Authorization Server metadata // as obtained using @link cupsOAuthCopyMetadata@ and/or // @link cupsOAuthGetMetadata@. // -// The "resource_uri" parameter specifies the URI for a resource (printer, web +// The "resource_uri" argument specifies the URI for a resource (printer, web // file, etc.) that you which to access. // -// The "scopes" parameter specifies zero or more whitespace-delimited scope +// The "scopes" argument specifies zero or more whitespace-delimited scope // names to request during authorization. The list of supported scope names are // available from the Authorization Server metadata, for example: // @@ -339,7 +339,7 @@ cupsOAuthCopyUserId( // cups_json_t *scopes_supported = cupsJSONFind(metadata, "scopes_supported"); // ``` // -// The "redirect_uri" parameter specifies a 'http:' URL with a listen address, +// The "redirect_uri" argument specifies a 'http:' URL with a listen address, // port, and path to use. If `NULL`, 127.0.0.1 on a random port is used with a // path of "/". // @@ -712,8 +712,8 @@ cupsOAuthGetAuthorizationCode( // This function registers a client application with the specified OAuth // Authorization Server. // -// The "auth_uri" parameter specifies the URI for the OAuth Authorization -// Server. The "metadata" parameter specifies the Authorization Server metadata +// The "auth_uri" argument specifies the URI for the OAuth Authorization +// Server. The "metadata" argument specifies the Authorization Server metadata // as obtained using @link cupsOAuthCopyMetadata@ and/or // @link cupsOAuthGetMetadata@. // @@ -805,15 +805,15 @@ cupsOAuthGetClientId( // resource and scope(s). Device authorization grants allow a user to open a // web page on any device to authorize access to the resource. // -// The "auth_uri" parameter specifies the URI for the OAuth Authorization -// Server. The "metadata" parameter specifies the Authorization Server metadata +// The "auth_uri" argument specifies the URI for the OAuth Authorization +// Server. The "metadata" argument specifies the Authorization Server metadata // as obtained using @link cupsOAuthCopyMetadata@ and/or // @link cupsOAuthGetMetadata@. // -// The "resource_uri" parameter specifies the URI for a resource (printer, web +// The "resource_uri" argument specifies the URI for a resource (printer, web // file, etc.) that you which to access. // -// The "scopes" parameter specifies zero or more whitespace-delimited scope +// The "scopes" argument specifies zero or more whitespace-delimited scope // names to request during authorization. The list of supported scope names are // available from the Authorization Server metadata, for example: // @@ -1195,16 +1195,16 @@ cupsOAuthGetMetadata( // Server. OpenID Authorization Servers also provide user identification // information. // -// The "auth_uri" parameter specifies the URI for the OAuth Authorization -// Server. The "metadata" parameter specifies the Authorization Server metadata +// The "auth_uri" argument specifies the URI for the OAuth Authorization +// Server. The "metadata" argument specifies the Authorization Server metadata // as obtained using @link cupsOAuthCopyMetadata@ and/or // @link cupsOAuthGetMetadata@. // -// The "resource_uri" parameter specifies the URI for a resource (printer, web +// The "resource_uri" argument specifies the URI for a resource (printer, web // file, etc.) that you which to access. // -// The "grant_code" parameter specifies the code or token to use while the -// "grant_type" parameter specifies the type of code: +// The "grant_code" argument specifies the code or token to use while the +// "grant_type" argument specifies the type of code: // // - `CUPS_OGRANT_AUTHORIZATION_CODE`: A user authorization grant code. // - `CUPS_OGRANT_DEVICE_CODE`: A device authorization grant code. @@ -1539,15 +1539,15 @@ cupsOAuthGetUserId( // This function makes an authorization URL for the specified authorization // server and resource. // -// The "auth_uri" parameter specifies the URI for the OAuth Authorization -// Server. The "metadata" parameter specifies the Authorization Server metadata +// The "auth_uri" argument specifies the URI for the OAuth Authorization +// Server. The "metadata" argument specifies the Authorization Server metadata // as obtained using @link cupsOAuthCopyMetadata@ and/or // @link cupsOAuthGetMetadata@. // -// The "resource_uri" parameter specifies the URI for a resource (printer, web +// The "resource_uri" argument specifies the URI for a resource (printer, web // file, etc.) that you which to access. // -// The "scopes" parameter specifies zero or more whitespace-delimited scope +// The "scopes" argument specifies zero or more whitespace-delimited scope // names to request during authorization. The list of supported scope names are // available from the Authorization Server metadata, for example: // @@ -1556,25 +1556,25 @@ cupsOAuthGetUserId( // cups_json_t *scopes_supported = cupsJSONFind(metadata, "scopes_supported"); // ``` // -// The "client_id" parameter specifies the client identifier obtained using +// The "client_id" argument specifies the client identifier obtained using // @link cupsOAuthCopyClientId@ and/or @link cupsOAuthGetClientId@. // -// The "client_id" parameter is the string returned by +// The "client_id" argument is the string returned by // @link cupsOAuthCopyClientId@ or @link cupsOAuthGetClientId@. // -// The "code_verifier" parameter specifies a random Base64URL-encoded string +// The "code_verifier" argument specifies a random Base64URL-encoded string // that is used by the Proof Key for Code Exchange [RFC7636] extension to help // secure the authorization flow. The @link cupsOAuthMakeBase64Random@ function // can be used to generate this string. // -// The "nonce" parameter specifies a random Base64URL-encoded string that is +// The "nonce" argument specifies a random Base64URL-encoded string that is // used by OpenID to validate the ID token. The @link cupsOAuthMakeBase64Random@ // function can be used to generate this string. // -// The "redirect_uri" parameter specifies the URI that will receive the +// The "redirect_uri" argument specifies the URI that will receive the // authorization grant code. // -// The "state" parameter is a unique (random) identifier for the authorization +// The "state" argument is a unique (random) identifier for the authorization // request. It is provided to the redirection URI as a form parameter. // // @since CUPS 2.5@ diff --git a/cups/tls-gnutls.c b/cups/tls-gnutls.c index 718c023306..cbe4a3fdbe 100644 --- a/cups/tls-gnutls.c +++ b/cups/tls-gnutls.c @@ -1005,7 +1005,7 @@ cupsGetCredentialsTrust( time_t curtime; // Current date/time time(&curtime); - if (curtime < gnutls_x509_crt_get_activation_time(certs[0]) || curtime > gnutls_x509_crt_get_expiration_time(certs[0])) + if ((curtime + 86400) < gnutls_x509_crt_get_activation_time(certs[0]) || curtime > gnutls_x509_crt_get_expiration_time(certs[0])) { _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials have expired."), 1); trust = HTTP_TRUST_EXPIRED; @@ -1835,7 +1835,6 @@ _httpTLSStart(http_t *http) // I - Connection to server DEBUG_puts("4_httpTLSStart: cupsCreateCredentials failed."); http->error = errno = EINVAL; http->status = HTTP_STATUS_ERROR; - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1); cupsMutexUnlock(&tls_mutex); return (false); diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c index 128820b57d..593b2c2f1b 100644 --- a/cups/tls-openssl.c +++ b/cups/tls-openssl.c @@ -80,9 +80,94 @@ cupsAreCredentialsValidForName( bool result = false; // Result + DEBUG_printf("cupsAreCredentialsValidForName(common_name=\"%s\", credentials=\"%s\")", common_name, credentials); + + // Range check input... + if (!common_name || !credentials) + return (false); + + // Load the credentials... if ((certs = openssl_load_x509(credentials)) != NULL) { - result = X509_check_host(sk_X509_value(certs, 0), common_name, strlen(common_name), 0, NULL) != 0; + // Check the hostname against the primary certificate... + X509 *cert = sk_X509_value(certs, 0); + // Primary certificate + char subjectName[256]; // Common name from certificate + STACK_OF(GENERAL_NAME) *names = NULL; + // subjectAltName values + + DEBUG_printf("1cupsAreCredentialsValidForName: certs=%p(num=%d), cert=%p", certs, sk_X509_num(certs), cert); + + X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, subjectName, sizeof(subjectName)); + DEBUG_printf("1cupsAreCredentialsValidForName: subjectName=\"%s\"", subjectName); + + if (!_cups_strcasecmp(common_name, subjectName)) + { + DEBUG_puts("1cupsAreCredentialsValidForName: Match."); + result = true; + } + +#ifdef DEBUG + char issuerName[256]; + X509_NAME_get_text_by_NID(X509_get_issuer_name(cert), NID_commonName, issuerName, sizeof(issuerName)); + DEBUG_printf("1cupsAreCredentialsValidForName: issuerName=\"%s\"", issuerName); +#endif // DEBUG + + if (!result) + { + names = X509_get_ext_d2i(cert, NID_subject_alt_name, /*crit*/NULL, /*idx*/NULL); + DEBUG_printf("1cupsAreCredentialsValidForName: names=%p", names); + } + + if (names) + { + // Got subjectAltName values, look at them... + int i, // Looping var + count; // Number of values + + for (i = 0, count = sk_GENERAL_NAME_num(names); i < count && !result; i ++) + { + const GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i); + // subjectAltName value + + if (!name) + continue; + + DEBUG_printf("1cupsAreCredentialsValidForName: subjectAltName[%d/%d].type=%d", i + 1, count, name->type); + if (name->type == GEN_DNS) + { + // Match a DNS name... + char *dNSName; // DNS name value + + if (ASN1_STRING_to_UTF8((unsigned char **)&dNSName, name->d.dNSName) > 0) + { + DEBUG_printf("1cupsAreCredentialsValidForName: subjectAltName[%d/%d].dNSName=\"%s\"", i + 1, count, dNSName); + + if (!_cups_strcasecmp(common_name, dNSName)) + { + // Direct name match... + DEBUG_puts("1cupsAreCredentialsValidForName: Match."); + result = true; + } + else if (!strncmp(dNSName, "*.", 2)) + { + // Compare wildcard... + const char *domain_name = strchr(common_name, '.'); + // Domain name of common name + if (domain_name && !_cups_strcasecmp(domain_name, dNSName + 1)) + { + DEBUG_puts("1cupsAreCredentialsValidForName: Match."); + result = true; + } + } + + OPENSSL_free(dNSName); + } + } + } + + GENERAL_NAMES_free(names); + } sk_X509_free(certs); } @@ -820,6 +905,7 @@ cupsGetCredentialsTrust( if (!path || !credentials || !common_name) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), false); + DEBUG_printf("1cupsGetCredentialsTrust: Returning %d.", HTTP_TRUST_UNKNOWN); return (HTTP_TRUST_UNKNOWN); } @@ -827,6 +913,7 @@ cupsGetCredentialsTrust( if ((certs = openssl_load_x509(credentials)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Unable to import credentials."), true); + DEBUG_printf("1cupsGetCredentialsTrust: Returning %d.", HTTP_TRUST_UNKNOWN); return (HTTP_TRUST_UNKNOWN); } @@ -936,7 +1023,10 @@ cupsGetCredentialsTrust( time_t curtime; // Current date/time time(&curtime); - if (curtime < openssl_get_date(cert, 0) || curtime > openssl_get_date(cert, 1)) + + DEBUG_printf("1cupsGetCredentialsTrust: curtime=%ld, notBefore=%ld, notAfter=%ld", (long)curtime, (long)openssl_get_date(cert, 0), (long)openssl_get_date(cert, 1)); + + if ((curtime + 86400) < openssl_get_date(cert, 0) || curtime > openssl_get_date(cert, 1)) { _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials have expired."), 1); trust = HTTP_TRUST_EXPIRED; @@ -945,6 +1035,8 @@ cupsGetCredentialsTrust( sk_X509_free(certs); + DEBUG_printf("1cupsGetCredentialsTrust: Returning %d.", trust); + return (trust); } @@ -1811,7 +1903,6 @@ _httpTLSStart(http_t *http) // I - Connection to server DEBUG_puts("4_httpTLSStart: cupsCreateCredentials failed."); http->error = errno = EINVAL; http->status = HTTP_STATUS_ERROR; - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1); SSL_CTX_free(context); cupsMutexUnlock(&tls_mutex);