From 227516085da476f4422276bb4a61b4f2d8924a40 Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Tue, 19 Mar 2024 17:19:38 +0100 Subject: [PATCH] Handle cases when auth groups are unset Currently, pappl based applications require authentication every time for any request if authentication module is set, even if authentication group(s) is set to `None`. With this PR, admin can set admin and print group to `None`. Every admin action is allowed if admin group is `None`. If the connection is local, no group is set and we are missing authentication field, use `requesting-user-name`. This allows smooth printing to the printer application via CUPS when printer application uses PAM module to protect against simple attacks. --- pappl/client-accessors.c | 14 ++++++++++++++ pappl/client-auth.c | 6 ++++++ pappl/client-private.h | 1 + pappl/printer-ipp.c | 14 +++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pappl/client-accessors.c b/pappl/client-accessors.c index a1c5d1f3..11ee058b 100644 --- a/pappl/client-accessors.c +++ b/pappl/client-accessors.c @@ -334,3 +334,17 @@ papplClientSetUsername( client->username[0] = '\0'; } } + + +// +// '_papplClientGroupIsEmpty()' - Check if group is empty +// + +bool // O - `true` if empty, `false` if set +_papplClientGroupIsEmpty(const char *group) // I - Group name +{ + if (!group || !group[0]) + return (true); + + return (false); +} diff --git a/pappl/client-auth.c b/pappl/client-auth.c index c92b47ee..052ea198 100644 --- a/pappl/client-auth.c +++ b/pappl/client-auth.c @@ -216,6 +216,12 @@ _papplClientIsAuthorizedForGroup( return (HTTP_STATUS_BAD_REQUEST); } } + else + { + // If there is no Authorization field, no group and we are on localhost - continue + if (_papplClientGroupIsEmpty(group) && httpAddrIsLocalhost(httpGetAddress(client->http))) + return (HTTP_STATUS_CONTINUE); + } // If we get there then we don't have any authorization value we can use... return (HTTP_STATUS_UNAUTHORIZED); diff --git a/pappl/client-private.h b/pappl/client-private.h index fb95e963..09a1c560 100644 --- a/pappl/client-private.h +++ b/pappl/client-private.h @@ -57,6 +57,7 @@ extern char *_papplClientCreateTempFile(pappl_client_t *client, const void *dat extern void _papplClientDelete(pappl_client_t *client) _PAPPL_PRIVATE; extern void _papplClientFlushDocumentData(pappl_client_t *client) _PAPPL_PRIVATE; extern const char *_papplClientGetAuthWebScheme(pappl_client_t *client) _PAPPL_PRIVATE; +extern bool _papplClientGroupIsEmpty(const char *group) _PAPPL_PRIVATE; extern bool _papplClientHaveDocumentData(pappl_client_t *client) _PAPPL_PRIVATE; extern http_status_t _papplClientIsAuthorizedForGroup(pappl_client_t *client, bool allow_remote, const char *group, gid_t groupid) _PAPPL_PUBLIC; extern bool _papplClientProcessHTTP(pappl_client_t *client) _PAPPL_PRIVATE; diff --git a/pappl/printer-ipp.c b/pappl/printer-ipp.c index 340cb595..6eaa96ab 100644 --- a/pappl/printer-ipp.c +++ b/pappl/printer-ipp.c @@ -785,9 +785,21 @@ bool // O - `true` on success, `false` on failure _papplPrinterIsAuthorized( pappl_client_t *client) // I - Client { + const char *username; // Current username + ipp_attribute_t *attr; // requesting-user-name attribute + http_status_t code = _papplClientIsAuthorizedForGroup(client, true, client->printer->print_group, client->printer->print_gid); - if (code == HTTP_STATUS_CONTINUE && client->job && client->job->username && strcmp(client->username, client->job->username)) + // In case of local connections, use requesting-user-name attribute as username later if client username is missing + if (code == HTTP_STATUS_CONTINUE) + { + if (!client->username[0] && (attr = ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME)) != NULL) + username = ippGetString(attr, 0, NULL); + else + username = client->username; + } + + if (code == HTTP_STATUS_CONTINUE && client->job && client->job->username && strcmp(username, client->job->username)) { // Not the owner, try authorizing with admin group... code = _papplClientIsAuthorizedForGroup(client, true, client->system->admin_group, client->system->admin_gid);