Skip to content

Commit e052dc4

Browse files
committed
Don't allow local certificates over the loopback interface, drop support for writing to plain files.
1 parent 0ff8897 commit e052dc4

8 files changed

Lines changed: 52 additions & 62 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Changes in CUPS v2.4.17 (YYYY-MM-DD)
1313
values.
1414
- CVE-2026-NNNNN: The scheduler did not always allocate enough memory for a
1515
job's options string.
16+
- CVE-2026-NNNNN: The scheduler incorrectly allowed local certificates over the
17+
loopback interface.
1618
- The scheduler followed symbolic links when cleaning out its temporary
1719
directory (Issue #1448)
1820
- Updated `cupsFileGetConf` and `cupsFilePutConf` to escape more characters.

cups/auth.c

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Authentication functions for CUPS.
33
*
4-
* Copyright © 2020-2024 by OpenPrinting.
4+
* Copyright © 2020-2026 by OpenPrinting.
55
* Copyright © 2007-2019 by Apple Inc.
66
* Copyright © 1997-2007 by Easy Software Products.
77
*
@@ -92,7 +92,6 @@ static void cups_gss_printf(OM_uint32 major_status, OM_uint32 minor_status,
9292
# define cups_gss_printf(major, minor, message)
9393
# endif /* DEBUG */
9494
#endif /* HAVE_GSSAPI */
95-
static int cups_is_local_connection(http_t *http);
9695
static int cups_local_auth(http_t *http);
9796

9897

@@ -948,14 +947,6 @@ cups_gss_printf(OM_uint32 major_status,/* I - Major status code */
948947
# endif /* DEBUG */
949948
#endif /* HAVE_GSSAPI */
950949

951-
static int /* O - 0 if not a local connection */
952-
/* 1 if local connection */
953-
cups_is_local_connection(http_t *http) /* I - HTTP connection to server */
954-
{
955-
if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0)
956-
return 0;
957-
return 1;
958-
}
959950

960951
/*
961952
* 'cups_local_auth()' - Get the local authorization certificate if
@@ -967,13 +958,7 @@ static int /* O - 0 if available */
967958
/* -1 error */
968959
cups_local_auth(http_t *http) /* I - HTTP connection to server */
969960
{
970-
#if defined(_WIN32) || defined(__EMX__)
971-
/*
972-
* Currently _WIN32 and OS-2 do not support the CUPS server...
973-
*/
974-
975-
return (1);
976-
#else
961+
#if !_WIN32 && !__EMX__ && defined(AF_LOCAL)
977962
int pid; /* Current process ID */
978963
FILE *fp; /* Certificate file */
979964
char trc[16], /* Try Root Certificate parameter */
@@ -998,7 +983,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
998983
* See if we are accessing localhost...
999984
*/
1000985

1001-
if (!cups_is_local_connection(http))
986+
if (httpAddrFamily(httpGetAddress(http)) != AF_LOCAL)
1002987
{
1003988
DEBUG_puts("8cups_local_auth: Not a local connection!");
1004989
return (1);
@@ -1072,15 +1057,14 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
10721057
}
10731058
# endif /* HAVE_AUTHORIZATION_H */
10741059

1075-
# if defined(SO_PEERCRED) && defined(AF_LOCAL)
1060+
# ifdef SO_PEERCRED
10761061
/*
10771062
* See if we can authenticate using the peer credentials provided over a
10781063
* domain socket; if so, specify "PeerCred username" as the authentication
10791064
* information...
10801065
*/
10811066

1082-
if (http->hostaddr->addr.sa_family == AF_LOCAL &&
1083-
!getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */
1067+
if (!getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */
10841068
cups_auth_find(www_auth, "PeerCred"))
10851069
{
10861070
/*
@@ -1104,7 +1088,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
11041088
return (0);
11051089
}
11061090
}
1107-
# endif /* SO_PEERCRED && AF_LOCAL */
1091+
# endif /* SO_PEERCRED */
11081092

11091093
if ((schemedata = cups_auth_find(www_auth, "Local")) == NULL)
11101094
return (1);
@@ -1164,7 +1148,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */
11641148
return (0);
11651149
}
11661150
}
1151+
#endif /* !_WIN32 && !__EMX__ && AF_LOCAL */
11671152

11681153
return (1);
1169-
#endif /* _WIN32 || __EMX__ */
11701154
}

scheduler/auth.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
318318
}
319319
#ifdef HAVE_AUTHORIZATION_H
320320
else if (!strncmp(authorization, "AuthRef ", 8) &&
321-
httpAddrLocalhost(httpGetAddress(con->http)))
321+
httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
322322
{
323323
OSStatus status; /* Status */
324324
char authdata[HTTP_MAX_VALUE];
@@ -399,7 +399,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
399399
#endif /* HAVE_AUTHORIZATION_H */
400400
#if defined(SO_PEERCRED) && defined(AF_LOCAL)
401401
else if (PeerCred != CUPSD_PEERCRED_OFF && !strncmp(authorization, "PeerCred ", 9) &&
402-
con->http->hostaddr->addr.sa_family == AF_LOCAL && con->best)
402+
httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL && con->best)
403403
{
404404
/*
405405
* Use peer credentials from domain socket connection...
@@ -489,7 +489,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
489489
}
490490
#endif /* SO_PEERCRED && AF_LOCAL */
491491
else if (!strncmp(authorization, "Local", 5) &&
492-
httpAddrLocalhost(httpGetAddress(con->http)))
492+
httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
493493
{
494494
/*
495495
* Get Local certificate authentication data...

scheduler/client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,7 +2188,7 @@ cupsdSendHeader(
21882188
strlcpy(auth_str, "Negotiate", sizeof(auth_str));
21892189
}
21902190

2191-
if (con->best && !con->is_browser && !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost"))
2191+
if (con->best && !con->is_browser && httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
21922192
{
21932193
/*
21942194
* Add a "trc" (try root certification) parameter for local
@@ -2208,7 +2208,7 @@ cupsdSendHeader(
22082208
auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str);
22092209

22102210
#if defined(SO_PEERCRED) && defined(AF_LOCAL)
2211-
if (PeerCred != CUPSD_PEERCRED_OFF && httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
2211+
if (PeerCred != CUPSD_PEERCRED_OFF)
22122212
{
22132213
strlcpy(auth_key, ", PeerCred", auth_size);
22142214
auth_key += 10;

scheduler/ipp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5625,7 +5625,7 @@ create_local_printer(
56255625
* Require local access to create a local printer...
56265626
*/
56275627

5628-
if (!httpAddrLocalhost(httpGetAddress(con->http)))
5628+
if (httpAddrFamily(httpGetAddress(con->http)) != AF_LOCAL)
56295629
{
56305630
send_ipp_status(con, IPP_STATUS_ERROR_FORBIDDEN, _("Only local users can create a local printer."));
56315631
return;
@@ -5685,9 +5685,9 @@ create_local_printer(
56855685

56865686
ptr = ippGetString(device_uri, 0, NULL);
56875687

5688-
if (!ptr || !ptr[0])
5688+
if (!ptr || !ptr[0] || (strncmp(ptr, "ipp://", 6) && strncmp(ptr, "ipps://", 7)))
56895689
{
5690-
send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" has empty value."), "device-uri");
5690+
send_ipp_status(con, IPP_STATUS_ERROR_NOT_POSSIBLE, _("Bad device-uri \"%s\"."), ptr);
56915691

56925692
return;
56935693
}

scheduler/job.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,35 +1163,39 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */
11631163
}
11641164
else
11651165
{
1166+
char scheme[32], /* URI scheme */
1167+
userpass[32], /* URI username:password */
1168+
host[256], /* URI hostname */
1169+
resource[1024]; /* URI resource path (filename) */
1170+
int port; /* URI port number */
1171+
1172+
httpSeparateURI(HTTP_URI_CODING_ALL, job->printer->device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource));
1173+
11661174
job->print_pipes[0] = -1;
1167-
if (!strcmp(job->printer->device_uri, "file:/dev/null") ||
1168-
!strcmp(job->printer->device_uri, "file:///dev/null"))
1169-
job->print_pipes[1] = -1;
1170-
else
1175+
job->print_pipes[1] = -1;
1176+
1177+
if (strcmp(resource, "/dev/null"))
11711178
{
1172-
if (!strncmp(job->printer->device_uri, "file:/dev/", 10))
1173-
job->print_pipes[1] = open(job->printer->device_uri + 5,
1174-
O_WRONLY | O_EXCL);
1175-
else if (!strncmp(job->printer->device_uri, "file:///dev/", 12))
1176-
job->print_pipes[1] = open(job->printer->device_uri + 7,
1177-
O_WRONLY | O_EXCL);
1178-
else if (!strncmp(job->printer->device_uri, "file:///", 8))
1179-
job->print_pipes[1] = open(job->printer->device_uri + 7,
1180-
O_WRONLY | O_CREAT | O_TRUNC, 0600);
1181-
else
1182-
job->print_pipes[1] = open(job->printer->device_uri + 5,
1183-
O_WRONLY | O_CREAT | O_TRUNC, 0600);
1179+
if (!FileDevice)
1180+
{
1181+
abort_message = "Stopping job because file: output is disabled.";
11841182

1185-
if (job->print_pipes[1] < 0)
1183+
goto abort_job;
1184+
}
1185+
else if ((job->print_pipes[1] = open(resource, O_WRONLY | O_EXCL)) < 0)
11861186
{
1187-
abort_message = "Stopping job because the scheduler could not "
1188-
"open the output file.";
1187+
abort_message = "Stopping job because the scheduler could not open the output file.";
11891188

11901189
goto abort_job;
11911190
}
1191+
else
1192+
{
1193+
/*
1194+
* Close this file on execute...
1195+
*/
11921196

1193-
fcntl(job->print_pipes[1], F_SETFD,
1194-
fcntl(job->print_pipes[1], F_GETFD) | FD_CLOEXEC);
1197+
fcntl(job->print_pipes[1], F_SETFD, fcntl(job->print_pipes[1], F_GETFD) | FD_CLOEXEC);
1198+
}
11951199
}
11961200
}
11971201
}

test/4.2-cups-printer-ops.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# Verify that the CUPS printer operations work.
33
#
4-
# Copyright © 2020-2024 by OpenPrinting.
4+
# Copyright © 2020-2026 by OpenPrinting.
55
# Copyright © 2007-2019 by Apple Inc.
66
# Copyright © 2001-2006 by Easy Software Products. All rights reserved.
77
#
@@ -180,7 +180,7 @@
180180
ATTR uri printer-uri $method://$hostname:$port/printers/Test2
181181

182182
GROUP printer
183-
ATTR uri device-uri file:/tmp/Test2
183+
ATTR uri device-uri file:///dev/null
184184
ATTR enum printer-state 3
185185
ATTR boolean printer-is-accepting-jobs true
186186

@@ -206,7 +206,7 @@
206206
ATTR uri printer-uri $method://$hostname:$port/printers/Test1
207207

208208
GROUP printer
209-
ATTR uri device-uri file:/tmp/Test1
209+
ATTR uri device-uri file:///dev/null
210210
ATTR enum printer-state 3
211211
ATTR boolean printer-is-accepting-jobs true
212212
ATTR text printer-info "Test Printer 1"

test/5.1-lpadmin.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Test the lpadmin command.
44
#
5-
# Copyright © 2020-2024 by OpenPrinting.
5+
# Copyright © 2020-2026 by OpenPrinting.
66
# Copyright © 2007-2018 by Apple Inc.
77
# Copyright © 1997-2005 by Easy Software Products, all rights reserved.
88
#
@@ -12,8 +12,8 @@
1212

1313
echo "Add Printer Test"
1414
echo ""
15-
echo " lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd"
16-
$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd 2>&1
15+
echo " lpadmin -p Test3 -v file:///dev/null -E -m drv:///sample.drv/deskjet.ppd"
16+
$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:///dev/null -E -m drv:///sample.drv/deskjet.ppd 2>&1
1717
if test $? != 0; then
1818
echo " FAILED"
1919
exit 1
@@ -29,8 +29,8 @@ echo ""
2929

3030
echo "Modify Printer Test"
3131
echo ""
32-
echo " lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4"
33-
$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4 2>&1
32+
echo " lpadmin -p Test3 -v file:///dev/null -o PageSize=A4"
33+
$runcups $VALGRIND ../systemv/lpadmin -p Test3 -v file:///dev/null -o PageSize=A4 2>&1
3434
if test $? != 0; then
3535
echo " FAILED"
3636
exit 1
@@ -65,8 +65,8 @@ echo ""
6565

6666
echo "Add a printer for cupSNMP/IPPSupplies test"
6767
echo ""
68-
echo " lpadmin -p Test4 -E -v file:/dev/null -m drv:///sample.drv/zebra.ppd"
69-
$runcups $VALGRIND ../systemv/lpadmin -p Test4 -E -v file:/dev/null -m drv:///sample.drv/zebra.ppd 2>&1
68+
echo " lpadmin -p Test4 -E -v file:///dev/null -m drv:///sample.drv/zebra.ppd"
69+
$runcups $VALGRIND ../systemv/lpadmin -p Test4 -E -v file:///dev/null -m drv:///sample.drv/zebra.ppd 2>&1
7070
if test $? != 0; then
7171
echo " FAILED"
7272
exit 1

0 commit comments

Comments
 (0)