Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

bug : cupsd crashes / misbehaves on malformed Authorization: Negotiate header (unchecked malloc + decode in GSSAPI path)

Cerrado Apto para principiantes
#1,772 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@michaelrsweet ya está trabajando en esto.

Desde el 18/10/2026.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
70/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
c

Línea de trabajo

Lee el manejo de Negotiate en scheduler/auth.c:847-851 y el comportamiento del decodificador en cups/http-support.c:463-464, :509. Compila cupsd con HAVE_GSSAPI y AuthType Negotiate y luego prueba el token Authorization malformado descrito en el issue. Se considera terminado cuando las entradas no válidas se rechazan antes de llegar a gss_accept_sec_context, sin que el daemon se bloquee ni se comporte de forma incorrecta.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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:

  1. malloc() at :848 is never NULL-checked. authorization here is the remainder of the client-sent Authorization: Negotiate ... header, so a remote client controls its length.
  2. httpDecode64_2() at :849 can return NULL (see cups/http-support.c:463-464 — it returns NULL when !outlen || *outlen < 1, and httpDecode64_3 underneath returns NULL on bad input at :509). That NULL is assigned straight back over input_token.value with 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:

  1. Save as repro_gss.c and build:
cc -O0 repro_gss.c -o repro_gss && ./repro_gss
  1. 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
  1. Full daemon path: send Authorization: Negotiate !!!not-base64!!! (or a very long token to pressure malloc) to a cupsd built with HAVE_GSSAPI and AuthType Negotiate — the NULL token reaches gss_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: :404 and :602 use stack buffers with size init, only this :848-849 site uses unchecked heap allocation. So this looks like a one-off miss, not a pattern.
Lenguaje dominante
C
Estrellas
1.8k
Forks
352
Merge medio
2 d 5 h
PR fusionados (30 d)
14

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de OpenPrinting/cups

Todos los issues de OpenPrinting/cups

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.