bug : cupsd crashes / misbehaves on malformed Authorization: Negotiate header (unchecked malloc + decode in GSSAPI path)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 70/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- c
- Domain
- authentication, backend, security
Research direction
Read the Negotiate handling around scheduler/auth.c:847-851 and the decoder behavior in cups/http-support.c:463-464, :509. Build cupsd with HAVE_GSSAPI and AuthType Negotiate, then try the malformed Authorization token described in the issue. Done means invalid input is rejected before it reaches gss_accept_sec_context, with no daemon crash or misbehavior.
Written by the indexing model from the issue text.
Description
Before you write the report
I read REPORTING_ISSUES.md before filing this. This is a code defect in the daemon's auth path, so no printer was needed — I verified the logic locally with a small repro mirroring the exact calls.
I searched open + closed issues and PRs for GSSAPI, Negotiate, gss_accept_sec_context, httpDecode64_2, Kerberos to avoid a duplicate. The closest I found were #1609 (OAuth/OIDC token-validation gaps) and #1766 (ipp backend musl stack crash) — both are different subsystems and neither touches this Negotiate decode path. So I believe this is fresh.
Describe the bug
Hey, while looking at the Kerberos / Negotiate handling in scheduler/auth.c I noticed the input token setup does not check for failures at all.
On current master (b37c10e8, v2.5b1), scheduler/auth.c:847-851:
len = (int)strlen(authorization) + 0;
input_token.value = malloc((size_t)len);
input_token.value = httpDecode64_2(input_token.value, &len,
authorization);
input_token.length = (size_t)len;
Two problems stacked on top of each other:
malloc()at:848is never NULL-checked.authorizationhere is the remainder of the client-sentAuthorization: Negotiate ...header, so a remote client controls its length.httpDecode64_2()at:849can returnNULL(seecups/http-support.c:463-464— it returnsNULLwhen!outlen || *outlen < 1, andhttpDecode64_3underneath returnsNULLon bad input at:509). ThatNULLis assigned straight back overinput_token.valuewith no check.
Right after that, the token goes directly into:
major_status = gss_accept_sec_context(&minor_status,
&context,
ServerCreds,
&input_token, // <- possibly NULL .value here
...);
So a malformed (or huge, OOM-inducing) Negotiate header can push a NULL / garbage token buffer into gss_accept_sec_context() inside cupsd itself, which runs as root and pre-auth. At best the daemon logs a confusing GSS error, at worst it trips over the bad buffer in the GSS library.
What made me look twice is that the Basic path just above (:600-602) decodes into a fixed stack buffer username[] safely, while this path uses a heap allocation with no checks. Felt like an oversight worth flagging.
To Reproduce
I could not spin up a Kerberos KDC here, so I extracted the exact 3-line sequence into a tiny repro that mirrors the real httpDecode64_2 NULL contract:
char *v = malloc((size_t)len); // mirrors :848, no check
v = fake_httpDecode64_2(v, &len, "!!!not-base64!!!");
// mirrors :849, returns NULL on bad input
printf("after decode: value=%p len=%d\n", (void*)v, len);
Steps:
- Save as
repro_gss.cand build:
cc -O0 repro_gss.c -o repro_gss && ./repro_gss
- You will see:
after decode: value=0x0 len=16
REPRODUCED: input_token.value==NULL fed to gss_accept_sec_context -> root cupsd robustness bug
Matches scheduler/auth.c:847-851: malloc unchecked + httpDecode64_2 NULL unchecked
- Full daemon path: send
Authorization: Negotiate !!!not-base64!!!(or a very long token to pressuremalloc) to acupsdbuilt withHAVE_GSSAPIandAuthType Negotiate— theNULLtoken reachesgss_accept_sec_context()instead of being rejected cleanly.
Honestly the malloc-OOM half needs memory pressure to trigger, but the malformed-base64 NULL half triggers on demand — that is the part I actually reproduced above.
Expected behavior
Reject the bad token cleanly before touching GSS, something like:
len = (int)strlen(authorization);
input_token.value = malloc((size_t)len);
if (!input_token.value)
return;
if (!httpDecode64_2(input_token.value, &len, authorization))
{
free(input_token.value);
return;
}
input_token.length = (size_t)len;
Even better long term would be moving this to httpDecode64_3 like the rest of the tree, since httpDecode64_2 is already marked deprecated. But the NULL checks alone fix the crash path with no behavior change.
Screenshots
N/A — daemon auth path, repro output pasted above.
System Information:
- OS and its version: macOS arm64 (clang 17) for the logic repro — affects any Linux cupsd built with GSSAPI/Kerberos
- Application:
cupsd(scheduler/auth.c),AuthType Negotiate - CUPS version: master 2.5b1 @
b37c10e8
Additional context
A couple of notes from my digging:
- Impact is daemon robustness — pre-auth remote header reaches root
cupsd. Not claiming RCE, just a genuine NULL-into-GSS path that should be a clean reject. - I checked the sibling decode sites:
:404and:602use stack buffers with size init, only this:848-849site uses unchecked heap allocation. So this looks like a one-off miss, not a pattern.
- Dominant language
- C
- Stars
- 1.8k
- Forks
- 349
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 12
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenPrinting/cups
-
Potential integer overflow when using atoi() In cgi-bin/var.cPossibly taken @lynayur claimed this 9 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
OpenPrinting/cups#1748 ·
Maintainers usually reply within 1 day
-
investigating
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
OpenPrinting/cups#1721 · 4 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
Bug : rastertoepson crashes with SIGFPE (divide-by-zero) on crafted raster with HWResolution 0Possibly taken @michaelrsweet claimed this today. Openinvestigating
OpenPrinting/cups#1771 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 15/100
OpenPrinting/cups#1763 ·
Maintainers usually reply within 1 day
-
investigating platform issue printer specific issue
Difficulty 3/5 1-2 days Newbie friendliness 65/100
OpenPrinting/cups#1727 · 4 comments ·
Maintainers usually reply within 1 day
All issues in OpenPrinting/cups
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
snowballstem/snowball#311 ·
-
tech-debt
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
antoxa2584x/nfsu2-sw#44 · 1 reaction ·
Maintainers usually reply within 1 day