Skip to content

Fix locale-dependent strftime breaking HMAC auth#372

Open
AaronAtDuo wants to merge 1 commit into
masterfrom
fix/strftime-locale-and-timezone
Open

Fix locale-dependent strftime breaking HMAC auth#372
AaronAtDuo wants to merge 1 commit into
masterfrom
fix/strftime-locale-and-timezone

Conversation

@AaronAtDuo

@AaronAtDuo AaronAtDuo commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace strftime(localtime()) with strftime_l(gmtime()) using an explicit C locale for the X-Duo-Date header
  • Hardcode +0000 UTC offset instead of relying on platform-specific %z behavior

Motivation

Three related bugs where strftime produces output that breaks HMAC signature verification:

Fix

// Before: locale-dependent, platform-specific %z
strftime(date, sizeof date, "%a, %d %b %Y %T %z", localtime(&t));

// After: explicit C locale, UTC with fixed offset
locale_t c_locale = newlocale(LC_TIME_MASK, "C", (locale_t)0);
strftime_l(date, sizeof date, "%a, %d %b %Y %T +0000", gmtime(&t), c_locale);
freelocale(c_locale);
  • strftime_l with C locale guarantees English day/month names regardless of process locale
  • gmtime() with +0000 sidesteps the AIX %z bug entirely
  • UTC matches the Python client's default sig_timezone behavior

Platform support

strftime_l (POSIX.1-2008) is available on Linux (glibc), macOS, FreeBSD, AIX 7.2+, Solaris 11.4+, and illumos. Not available on Solaris 11.3 and earlier (EOL for premier support: January 2024).

Test plan

  • Verified on Ubuntu 24.04 VM with LC_ALL=fr_FR.UTF-8
  • Unpatched: pam_duo produces French date header → Duo API returns 401
  • Patched: pam_duo produces English UTC date → auth succeeds
  • Tested using test_pam_locale.c harness that calls setlocale(LC_ALL, "") before PAM auth (simulates GDM/display manager behavior)
  • Existing test suite passes (make check)

Resolves #366, #355, #363

This analysis was generated with AI assistance (Claude).

Replace locale-dependent strftime(localtime()) with strftime_l(gmtime())
using an explicit C locale.  This fixes three issues:

- #366/#355: strftime %a and %b produce localized day/month names when
  the system locale is non-English, breaking HMAC signature verification
- #363: strftime %z on AIX produces a timezone name ("EST") instead of
  a numeric offset ("-0500"), also breaking signatures

The fix uses gmtime() with a hardcoded "+0000" UTC offset (matching the
Python client's default behavior) and strftime_l() with a C locale to
guarantee English day/month abbreviations regardless of environment.

Resolves #366, #355, #363

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pam_duo uses locale-dependent strftime for X-Duo-Date → breaks HMAC on non-C locales

1 participant