Skip to content

Commit

Permalink
Fix password hash comparisons (Issue #373)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Nov 13, 2024
1 parent 0e1c0a3 commit f4d0039
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changes in PAPPL
Changes in v1.4.8 (YYYY-MM-DD)
------------------------------

- SECURITY: The web interface password didn't work properly (Issue #373)
- Now use the "listen-hostname" hostname as system hostname if a name is
specified (Issue #369)

Expand Down
33 changes: 30 additions & 3 deletions pappl/client-webif.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// Core client web interface functions for the Printer Application Framework
//
// Copyright © 2019-2023 by Michael R Sweet.
// Copyright © 2019-2024 by Michael R Sweet.
// Copyright © 2010-2019 by Apple Inc.
//
// Licensed under Apache License v2.0. See the file "LICENSE" for more
Expand Down Expand Up @@ -451,34 +451,49 @@ papplClientHTMLAuthorize(

// Don't authorize if we have no auth service or we don't have a password set.
if (!client || (!client->system->auth_service && !client->system->auth_cb && !client->system->password_hash[0]))
{
_PAPPL_DEBUG("papplClientHTMLAuthorize: auth_service='%s', auth_cb=%s, password_hash=%s\n", client->system->auth_service, client->system->auth_cb != NULL ? "set" : "unset", client->system->password_hash[0] ? "set" : "unset");
_PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.");
return (true);
}

// When using an auth service, use HTTP Basic authentication...
if (client->system->auth_service || client->system->auth_cb)
{
http_status_t code = papplClientIsAuthorized(client);
// Authorization status code

_PAPPL_DEBUG("papplClientHTMLAuthorize: code=%d.\n", code);

if (code != HTTP_STATUS_CONTINUE)
{
_PAPPL_DEBUG("papplClientHTMLAuthorize: Returning false.\n");
papplClientRespond(client, code, NULL, NULL, 0, 0);
return (false);
}
else
{
_PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.\n");
return (true);
}
}

// Otherwise look for the authorization cookie...
if (papplClientGetCookie(client, "auth", auth_cookie, sizeof(auth_cookie)))
{
_PAPPL_DEBUG("papplClientHTMLAuthorize: Got auth cookie '%s'.\n", auth_cookie);
snprintf(auth_text, sizeof(auth_text), "%s:%s", papplSystemGetSessionKey(client->system, session_key, sizeof(session_key)), papplSystemGetPassword(client->system, password_hash, sizeof(password_hash)));
cupsHashData("sha2-256", (unsigned char *)auth_text, strlen(auth_text), auth_hash, sizeof(auth_hash));
cupsHashString(auth_hash, sizeof(auth_hash), auth_text, sizeof(auth_text));

_PAPPL_DEBUG("papplClientHTMLAuthorize: Expect auth cookie '%s'.\n", auth_text);

if (_papplIsEqual(auth_cookie, auth_text))
{
// Hashes match so we are authorized. Use "web-admin" as the username.
papplCopyString(client->username, "web-admin", sizeof(client->username));

_PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.\n");
return (true);
}
}
Expand All @@ -491,6 +506,8 @@ papplClientHTMLAuthorize(
cups_option_t *form = NULL; // Form variables
const char *password; // Password from user

_PAPPL_DEBUG("papplClientHTMLAuthorize: POST.\n");

if ((num_form = (cups_len_t)papplClientGetForm(client, &form)) == 0)
{
status = "Invalid form data.";
Expand All @@ -509,7 +526,10 @@ papplClientHTMLAuthorize(
papplSystemGetPassword(client->system, password_hash, sizeof(password_hash));
papplSystemHashPassword(client->system, password_hash, password, auth_text, sizeof(auth_text));

if (!strncmp(password_hash, auth_text, strlen(password_hash)))
_PAPPL_DEBUG("papplClientHTMLAuthorize: Saved password_hash is '%s'.\n", password_hash);
_PAPPL_DEBUG("papplClientHTMLAuthorize: Hashed form password is '%s'.\n", auth_text);

if (_papplIsEqual(password_hash, auth_text))
{
// Password hashes match, generate the cookie from the session key and
// password hash...
Expand All @@ -518,7 +538,8 @@ papplClientHTMLAuthorize(
cupsHashData("sha2-256", (unsigned char *)auth_text, strlen(auth_text), auth_hash, sizeof(auth_hash));
cupsHashString(auth_hash, sizeof(auth_hash), auth_text, sizeof(auth_text));

papplClientSetCookie(client, "auth", auth_text, 3600);
papplClientSetCookie(client, "auth", auth_text, 3600);
_PAPPL_DEBUG("papplClientHTMLAuthorize: Setting 'auth' cookie to '%s'.\n", auth_text);
}
else
{
Expand All @@ -531,16 +552,21 @@ papplClientHTMLAuthorize(
// Make the caller think this is a GET request...
client->operation = HTTP_STATE_GET;

_PAPPL_DEBUG("papplClientHTMLAuthorize: Status message is '%s'.\n", status);

if (!status)
{
// Hashes match so we are authorized. Use "web-admin" as the username.
papplCopyString(client->username, "web-admin", sizeof(client->username));

_PAPPL_DEBUG("papplClientHTMLAuthorize: Returning true.\n");
return (true);
}
}

// If we get this far, show the standard login form...
_PAPPL_DEBUG("papplClientHTMLAuthorize: Showing login form.\n");

papplClientRespond(client, HTTP_STATUS_OK, NULL, "text/html", 0, 0);
papplClientHTMLHeader(client, "Login", 0);
papplClientHTMLPuts(client,
Expand All @@ -560,6 +586,7 @@ papplClientHTMLAuthorize(
" </div>\n");
papplClientHTMLFooter(client);

_PAPPL_DEBUG("papplClientHTMLAuthorize: Returning false.\n");
return (false);
}

Expand Down
2 changes: 1 addition & 1 deletion pappl/system-accessors.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ papplSystemHashPassword(
{
// Copy existing nonce from the salt string...
papplCopyString(nonce, salt, sizeof(nonce));
if ((ptr = strchr(nonce, ':')) != NULL)
if ((ptr = strchr(nonce, '~')) != NULL)
*ptr = '\0';
}
else
Expand Down

0 comments on commit f4d0039

Please sign in to comment.