From 9756c004cdf4881b0d0660fe9533a6734f850cab Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Mon, 5 May 2025 08:07:52 -0400 Subject: [PATCH] Move CUPS_SID to cgi.h and use it as the state string for OAuth. Increase buffer sizes to allow for very large JWTs. --- cgi-bin/cgi.h | 10 +++++++++- cgi-bin/home.c | 42 +++++++++++++++++++++++------------------- cgi-bin/var.c | 15 ++++++--------- scheduler/auth.c | 6 ++++-- scheduler/client.h | 2 +- scheduler/statbuf.h | 11 ++++++----- 6 files changed, 49 insertions(+), 37 deletions(-) diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h index 0f97727789..534131fe22 100644 --- a/cgi-bin/cgi.h +++ b/cgi-bin/cgi.h @@ -1,7 +1,7 @@ /* * CGI support library definitions for CUPS. * - * Copyright © 2020-2024 by OpenPrinting. + * Copyright © 2020-2025 by OpenPrinting. * Copyright © 2007-2019 by Apple Inc. * Copyright © 1997-2006 by Easy Software Products. * @@ -37,6 +37,14 @@ extern "C" { # endif /* __cplusplus */ + +/* + * Constants... + */ + +# define CUPS_SID "org.cups.sid" /* Session ID cookie/variable */ + + /* * Types... */ diff --git a/cgi-bin/home.c b/cgi-bin/home.c index d4b781d64f..22e8819f85 100644 --- a/cgi-bin/home.c +++ b/cgi-bin/home.c @@ -98,13 +98,13 @@ do_login(void) // OAuth authorization server URL *server_name = getenv("SERVER_NAME"), // SERVER_NAME value - *server_port = getenv("SERVER_PORT"); + *server_port = getenv("SERVER_PORT"), // SERVER_PORT value + *state = NULL; // State string char *client_id = NULL, // Client ID value *code_verifier = NULL, // Code verifier string *nonce = NULL, // Nonce string redirect_uri[1024], // redirect_uri value - *state = NULL, // State string *url = NULL; // Authorization URL cups_json_t *metadata = NULL; // OAuth metadata @@ -144,7 +144,7 @@ do_login(void) // Make state and code verification strings... code_verifier = cupsOAuthMakeBase64Random(128); nonce = cupsOAuthMakeBase64Random(16); - state = cupsOAuthMakeBase64Random(16); + state = cgiGetCookie(CUPS_SID); // Get the authorization URL if ((url = cupsOAuthMakeAuthorizationURL(oauth_uri, metadata, /*resource_uri*/NULL, getenv("CUPS_OAUTH_SCOPES"), client_id, code_verifier, nonce, redirect_uri, state)) == NULL) @@ -166,7 +166,6 @@ do_login(void) free(code_verifier); cupsJSONDelete(metadata); free(nonce); - free(state); free(url); } @@ -196,12 +195,23 @@ do_redirect(const char *url) // URL or NULL for home page fprintf(stderr, "DEBUG2: do_redirect(url=\"%s\")\n", url); if (url && (!strncmp(url, "http://", 7) || !strncmp(url, "https://", 8))) - printf("Location: %s\n\n", url); + printf("Location: %s\n", url); else - printf("Location: %s://%s:%s%s\n\n", getenv("HTTPS") ? "https" : "http", getenv("SERVER_NAME"), getenv("SERVER_PORT"), url ? url : "/"); + printf("Location: %s://%s:%s%s\n", getenv("HTTPS") ? "https" : "http", getenv("SERVER_NAME"), getenv("SERVER_PORT"), url ? url : "/"); puts("Content-Type: text/plain\n"); puts("Redirecting..."); + fflush(stdout); + + + if (url && (!strncmp(url, "http://", 7) || !strncmp(url, "https://", 8))) + fprintf(stderr, "DEBUG2: do_redirect: Location: %s\n", url); + else + fprintf(stderr, "DEBUG2: do_redirect: Location: %s://%s:%s%s\n", getenv("HTTPS") ? "https" : "http", getenv("SERVER_NAME"), getenv("SERVER_PORT"), url ? url : "/"); + + fputs("DEBUG2: do_redirect: Content-Type: text/plain\n", stderr); + fputs("DEBUG2: do_redirect:\n", stderr); + fputs("DEBUG2: do_redirect: Redirecting...", stderr); } @@ -233,9 +243,7 @@ finish_login(void) *client_id = NULL, // Client ID value *error, // Error string redirect_uri[1024]; // redirect_uri value - const char *code, // Authorization code - *state_cookie, // State cookie - *state_var; // State variable + const char *code; // Authorization code cups_json_t *metadata = NULL; // OAuth metadata time_t access_expires; // When the bearer token expires @@ -276,16 +284,8 @@ finish_login(void) fprintf(stderr, "DEBUG2: finish_login: client_id=\"%s\"\n", client_id); - // Get the state and code strings... - code = cgiGetVariable("code"); - state_cookie = cgiGetCookie("CUPS_OAUTH_STATE"); - state_var = cgiGetVariable("state"); - - if (!state_cookie || !state_var || strcmp(state_cookie, state_var)) - { - show_error(cgiText(_("OAuth Login")), cgiText(_("Unable to authorize access")), cgiText(_("Bad client state value in response."))); - goto done; - } + // Get the code string... + code = cgiGetVariable("code"); // Get the access token... if ((bearer = cupsOAuthGetTokens(oauth_uri, metadata, /*resource_uri*/NULL, code, CUPS_OGRANT_AUTHORIZATION_CODE, redirect_uri, &access_expires)) == NULL) @@ -294,12 +294,16 @@ finish_login(void) goto done; } + fprintf(stderr, "DEBUG2: finish_login: access_token=\"%s\", access_expires=%ld\n", bearer, (long)access_expires); + // Save it as a cookie... cgiSetCookie("CUPS_BEARER", bearer, /*path*/NULL, /*domain*/NULL, access_expires, /*secure*/0); // Redirect... do_redirect(cgiGetCookie("CUPS_REFERRER")); + fputs("DEBUG2: finish_login: After redirect.\n", stderr); + done: // Free memory... diff --git a/cgi-bin/var.c b/cgi-bin/var.c index 66a5a8e70b..e5443499d5 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -18,13 +18,6 @@ #include -/* - * Session ID name - */ - -#define CUPS_SID "org.cups.sid" - - /* * Data structure to hold all the CGI form variables and arrays... */ @@ -394,8 +387,10 @@ cgiInitialize(void) else if (!cgi_initialize_post()) return (0); - if ((cups_sid_form = cgiGetVariable(CUPS_SID)) == NULL || - strcmp(cups_sid_cookie, cups_sid_form)) + if ((cups_sid_form = cgiGetVariable(CUPS_SID)) == NULL) + cups_sid_form = cgiGetVariable("state"); + + if (!cups_sid_form || strcmp(cups_sid_cookie, cups_sid_form)) { if (cups_sid_form) fprintf(stderr, "DEBUG: " CUPS_SID " form variable is \"%s\"\n", @@ -505,6 +500,8 @@ cgiSetCookie(const char *name, /* I - Name */ time_t expires, /* I - Expiration date (0 for session) */ int secure) /* I - Require SSL */ { + fprintf(stderr, "DEBUG2: cgiSetCookie(name=\"%s\", value=\"%s\", path=\"%s\", domain=\"%s\", expires=%ld, secure=%d)\n", name, value, path, domain, (long)expires, secure); + num_cookies = cupsAddOption(name, value, num_cookies, &cookies); printf("Set-Cookie: %s=%s;", name, value); diff --git a/scheduler/auth.c b/scheduler/auth.c index 1702d1f8c8..08252844c1 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -317,7 +317,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ int type; /* Authentication type */ const char *authorization; /* Pointer into Authorization string */ char *ptr, /* Pointer into string */ - bearer[2048], /* CUPS_BEARER cookie string */ + bearer[4096], /* CUPS_BEARER cookie string */ username[HTTP_MAX_VALUE], /* Username string */ password[HTTP_MAX_VALUE]; @@ -351,7 +351,9 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ authorization = httpGetField(con->http, HTTP_FIELD_AUTHORIZATION); - if (!*authorization && type == CUPSD_AUTH_BEARER && httpGetCookieValue(con->http, "CUPS_BEARER", bearer, sizeof(bearer)) && bearer[0]) + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cookie=\"%s\"", httpGetCookie(con->http)); + + if (!*authorization && httpGetCookieValue(con->http, "CUPS_BEARER", bearer, sizeof(bearer)) && bearer[0]) authorization = "Bearer COOKIE"; username[0] = '\0'; diff --git a/scheduler/client.h b/scheduler/client.h index 33b2f6ec96..0db5e8f497 100644 --- a/scheduler/client.h +++ b/scheduler/client.h @@ -54,7 +54,7 @@ struct cupsd_client_s int sent_header, /* Non-zero if sent HTTP header */ got_fields, /* Non-zero if all fields seen */ header_used; /* Number of header bytes used */ - char header[2048]; /* Header from CGI program */ + char header[4096]; /* Header from CGI program */ cups_lang_t *language; /* Language to use */ int auto_ssl; /* Automatic test for SSL/TLS */ http_addr_t clientaddr; /* Client's server address */ diff --git a/scheduler/statbuf.h b/scheduler/statbuf.h index 45fa904b8f..d0f7f67ae4 100644 --- a/scheduler/statbuf.h +++ b/scheduler/statbuf.h @@ -1,11 +1,12 @@ /* * Status buffer definitions for the CUPS scheduler. * - * Copyright © 2020-2024 by OpenPrinting. - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2005 by Easy Software Products, all rights reserved. + * Copyright © 2020-2025 by OpenPrinting. + * Copyright © 2007-2010 by Apple Inc. + * Copyright © 1997-2005 by Easy Software Products, all rights reserved. * - * Licensed under Apache License v2.0. See the file "LICENSE" for more information. + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ @@ -13,7 +14,7 @@ * Constants... */ -#define CUPSD_SB_BUFFER_SIZE 2048 /* Bytes for job status buffer */ +#define CUPSD_SB_BUFFER_SIZE 4096 /* Bytes for job status buffer */ /* -- 2.47.2