summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorDeepak Rathore <deeratho@cisco.com>2025-12-12 07:09:25 -0800
committerSteve Sakoman <steve@sakoman.com>2025-12-31 07:49:31 -0800
commit15a18fae405a4cb261401042bc513c0df9129205 (patch)
tree3a581b01b39213fc16e5e096ca7aafe2801394e1 /meta
parent553530a8acce3b078473c0fa512246a3e84d46bf (diff)
downloadpoky-15a18fae405a4cb261401042bc513c0df9129205.tar.gz
cups 2.4.11: Fix CVE-2025-58436
Upstream Repository: https://github.com/OpenPrinting/cups.git Bug Details: https://nvd.nist.gov/vuln/detail/CVE-2025-58436 Type: Security Fix CVE: CVE-2025-58436 Score: 5.5 Patch: https://github.com/OpenPrinting/cups/commit/5d414f1f91bd (From OE-Core rev: 6a721aad5f531ac74996386cbaaa0173c2c5001a) Signed-off-by: Deepak Rathore <deeratho@cisco.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-extended/cups/cups.inc1
-rw-r--r--meta/recipes-extended/cups/cups/CVE-2025-58436.patch635
2 files changed, 636 insertions, 0 deletions
diff --git a/meta/recipes-extended/cups/cups.inc b/meta/recipes-extended/cups/cups.inc
index 0a26a9b6de..cf3df32306 100644
--- a/meta/recipes-extended/cups/cups.inc
+++ b/meta/recipes-extended/cups/cups.inc
@@ -17,6 +17,7 @@ SRC_URI = "${GITHUB_BASE_URI}/download/v${PV}/cups-${PV}-source.tar.gz \
17 file://cups-volatiles.conf \ 17 file://cups-volatiles.conf \
18 file://CVE-2025-58060.patch \ 18 file://CVE-2025-58060.patch \
19 file://CVE-2025-58364.patch \ 19 file://CVE-2025-58364.patch \
20 file://CVE-2025-58436.patch \
20 " 21 "
21 22
22GITHUB_BASE_URI = "https://github.com/OpenPrinting/cups/releases" 23GITHUB_BASE_URI = "https://github.com/OpenPrinting/cups/releases"
diff --git a/meta/recipes-extended/cups/cups/CVE-2025-58436.patch b/meta/recipes-extended/cups/cups/CVE-2025-58436.patch
new file mode 100644
index 0000000000..5083d082dc
--- /dev/null
+++ b/meta/recipes-extended/cups/cups/CVE-2025-58436.patch
@@ -0,0 +1,635 @@
1From 7587d27139227397ab68cce554a112bb1190e6b6 Mon Sep 17 00:00:00 2001
2From: Zdenek Dohnal <zdohnal@redhat.com>
3Date: Mon, 13 Oct 2025 10:16:48 +0200
4Subject: [PATCH] Fix unresponsive cupsd process caused by a slow client
5
6If client is very slow, it will slow cupsd process for other clients.
7The fix is the best effort without turning scheduler cupsd into
8multithreaded process which would be too complex and error-prone when
9backporting to 2.4.x series.
10
11The fix for unencrypted communication is to follow up on communication
12only if there is the whole line on input, and the waiting time is
13guarded by timeout.
14
15Encrypted communication now starts after we have the whole client hello
16packet, which conflicts with optional upgrade support to HTTPS via
17methods other than method OPTIONS, so this optional support defined in
18RFC 2817, section 3.1 is removed. Too slow or incomplete requests are
19handled by connection timeout.
20
21Fixes CVE-2025-58436
22
23CVE: CVE-2025-58436
24Upstream-Status: Backport [https://github.com/OpenPrinting/cups/commit/5d414f1f91bd]
25
26(cherry picked from commit 5d414f1f91bdca118413301b148f0b188eb1cdc6)
27Signed-off-by: Deepak Rathore <deeratho@cisco.com>
28---
29 cups/http-private.h | 7 +-
30 cups/http.c | 80 +++++++++++++-------
31 cups/tls-openssl.c | 15 +++-
32 scheduler/client.c | 178 ++++++++++++++++++++++++++++----------------
33 scheduler/client.h | 3 +
34 scheduler/select.c | 12 +++
35 6 files changed, 198 insertions(+), 97 deletions(-)
36
37diff --git a/cups/http-private.h b/cups/http-private.h
38index 5f77b8ef0..b8e200bf6 100644
39--- a/cups/http-private.h
40+++ b/cups/http-private.h
41@@ -121,6 +121,7 @@ extern "C" {
42 * Constants...
43 */
44
45+# define _HTTP_MAX_BUFFER 32768 /* Size of read buffer */
46 # define _HTTP_MAX_SBUFFER 65536 /* Size of (de)compression buffer */
47 # define _HTTP_RESOLVE_DEFAULT 0 /* Just resolve with default options */
48 # define _HTTP_RESOLVE_STDERR 1 /* Log resolve progress to stderr */
49@@ -232,8 +233,8 @@ struct _http_s /**** HTTP connection structure ****/
50 http_encoding_t data_encoding; /* Chunked or not */
51 int _data_remaining;/* Number of bytes left (deprecated) */
52 int used; /* Number of bytes used in buffer */
53- char buffer[HTTP_MAX_BUFFER];
54- /* Buffer for incoming data */
55+ char _buffer[HTTP_MAX_BUFFER];
56+ /* Old read buffer (deprecated) */
57 int _auth_type; /* Authentication in use (deprecated) */
58 unsigned char _md5_state[88]; /* MD5 state (deprecated) */
59 char nonce[HTTP_MAX_VALUE];
60@@ -307,6 +308,8 @@ struct _http_s /**** HTTP connection structure ****/
61 /* Allocated field values */
62 *default_fields[HTTP_FIELD_MAX];
63 /* Default field values, if any */
64+ char buffer[_HTTP_MAX_BUFFER];
65+ /* Read buffer */
66 };
67 # endif /* !_HTTP_NO_PRIVATE */
68
69diff --git a/cups/http.c b/cups/http.c
70index 31a8be361..599703c7b 100644
71--- a/cups/http.c
72+++ b/cups/http.c
73@@ -53,7 +53,7 @@ static http_t *http_create(const char *host, int port,
74 static void http_debug_hex(const char *prefix, const char *buffer,
75 int bytes);
76 #endif /* DEBUG */
77-static ssize_t http_read(http_t *http, char *buffer, size_t length);
78+static ssize_t http_read(http_t *http, char *buffer, size_t length, int timeout);
79 static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length);
80 static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length);
81 static int http_send(http_t *http, http_state_t request,
82@@ -1200,7 +1200,7 @@ httpGets(char *line, /* I - Line to read into */
83 return (NULL);
84 }
85
86- bytes = http_read(http, http->buffer + http->used, (size_t)(HTTP_MAX_BUFFER - http->used));
87+ bytes = http_read(http, http->buffer + http->used, (size_t)(_HTTP_MAX_BUFFER - http->used), http->wait_value);
88
89 DEBUG_printf(("4httpGets: read " CUPS_LLFMT " bytes.", CUPS_LLCAST bytes));
90
91@@ -1720,24 +1720,13 @@ httpPeek(http_t *http, /* I - HTTP connection */
92
93 ssize_t buflen; /* Length of read for buffer */
94
95- if (!http->blocking)
96- {
97- while (!httpWait(http, http->wait_value))
98- {
99- if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
100- continue;
101-
102- return (0);
103- }
104- }
105-
106 if ((size_t)http->data_remaining > sizeof(http->buffer))
107 buflen = sizeof(http->buffer);
108 else
109 buflen = (ssize_t)http->data_remaining;
110
111 DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen));
112- bytes = http_read(http, http->buffer, (size_t)buflen);
113+ bytes = http_read(http, http->buffer, (size_t)buflen, http->wait_value);
114
115 DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.",
116 CUPS_LLCAST bytes));
117@@ -1758,9 +1747,9 @@ httpPeek(http_t *http, /* I - HTTP connection */
118 int zerr; /* Decompressor error */
119 z_stream stream; /* Copy of decompressor stream */
120
121- if (http->used > 0 && ((z_stream *)http->stream)->avail_in < HTTP_MAX_BUFFER)
122+ if (http->used > 0 && ((z_stream *)http->stream)->avail_in < _HTTP_MAX_BUFFER)
123 {
124- size_t buflen = HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in;
125+ size_t buflen = _HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in;
126 /* Number of bytes to copy */
127
128 if (((z_stream *)http->stream)->avail_in > 0 &&
129@@ -2018,7 +2007,7 @@ httpRead2(http_t *http, /* I - HTTP connection */
130
131 if (bytes == 0)
132 {
133- ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
134+ ssize_t buflen = _HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
135 /* Additional bytes for buffer */
136
137 if (buflen > 0)
138@@ -2768,7 +2757,7 @@ int /* O - 1 to continue, 0 to stop */
139 _httpUpdate(http_t *http, /* I - HTTP connection */
140 http_status_t *status) /* O - Current HTTP status */
141 {
142- char line[32768], /* Line from connection... */
143+ char line[_HTTP_MAX_BUFFER], /* Line from connection... */
144 *value; /* Pointer to value on line */
145 http_field_t field; /* Field index */
146 int major, minor; /* HTTP version numbers */
147@@ -2776,12 +2765,46 @@ _httpUpdate(http_t *http, /* I - HTTP connection */
148
149 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", (void *)http, (void *)status, httpStateString(http->state)));
150
151+ /* When doing non-blocking I/O, make sure we have a whole line... */
152+ if (!http->blocking)
153+ {
154+ ssize_t bytes; /* Bytes "peeked" from connection */
155+
156+ /* See whether our read buffer is full... */
157+ DEBUG_printf(("2_httpUpdate: used=%d", http->used));
158+
159+ if (http->used > 0 && !memchr(http->buffer, '\n', (size_t)http->used) && (size_t)http->used < sizeof(http->buffer))
160+ {
161+ /* No, try filling in more data... */
162+ if ((bytes = http_read(http, http->buffer + http->used, sizeof(http->buffer) - (size_t)http->used, /*timeout*/0)) > 0)
163+ {
164+ DEBUG_printf(("2_httpUpdate: Read %d bytes.", (int)bytes));
165+ http->used += (int)bytes;
166+ }
167+ }
168+
169+ /* Peek at the incoming data... */
170+ if (!http->used || !memchr(http->buffer, '\n', (size_t)http->used))
171+ {
172+ /* Don't have a full line, tell the reader to try again when there is more data... */
173+ DEBUG_puts("1_htttpUpdate: No newline in buffer yet.");
174+ if ((size_t)http->used == sizeof(http->buffer))
175+ *status = HTTP_STATUS_ERROR;
176+ else
177+ *status = HTTP_STATUS_CONTINUE;
178+ return (0);
179+ }
180+
181+ DEBUG_puts("2_httpUpdate: Found newline in buffer.");
182+ }
183+
184 /*
185 * Grab a single line from the connection...
186 */
187
188 if (!httpGets(line, sizeof(line), http))
189 {
190+ DEBUG_puts("1_httpUpdate: Error reading request line.");
191 *status = HTTP_STATUS_ERROR;
192 return (0);
193 }
194@@ -4134,7 +4157,8 @@ http_debug_hex(const char *prefix, /* I - Prefix for line */
195 static ssize_t /* O - Number of bytes read or -1 on error */
196 http_read(http_t *http, /* I - HTTP connection */
197 char *buffer, /* I - Buffer */
198- size_t length) /* I - Maximum bytes to read */
199+ size_t length, /* I - Maximum bytes to read */
200+ int timeout) /* I - Wait timeout */
201 {
202 ssize_t bytes; /* Bytes read */
203
204@@ -4143,7 +4167,7 @@ http_read(http_t *http, /* I - HTTP connection */
205
206 if (!http->blocking || http->timeout_value > 0.0)
207 {
208- while (!httpWait(http, http->wait_value))
209+ while (!_httpWait(http, timeout, 1))
210 {
211 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
212 continue;
213@@ -4246,7 +4270,7 @@ http_read_buffered(http_t *http, /* I - HTTP connection */
214 else
215 bytes = (ssize_t)length;
216
217- DEBUG_printf(("8http_read: Grabbing %d bytes from input buffer.",
218+ DEBUG_printf(("8http_read_buffered: Grabbing %d bytes from input buffer.",
219 (int)bytes));
220
221 memcpy(buffer, http->buffer, (size_t)bytes);
222@@ -4256,7 +4280,7 @@ http_read_buffered(http_t *http, /* I - HTTP connection */
223 memmove(http->buffer, http->buffer + bytes, (size_t)http->used);
224 }
225 else
226- bytes = http_read(http, buffer, length);
227+ bytes = http_read(http, buffer, length, http->wait_value);
228
229 return (bytes);
230 }
231@@ -4597,15 +4621,15 @@ http_set_timeout(int fd, /* I - File descriptor */
232 static void
233 http_set_wait(http_t *http) /* I - HTTP connection */
234 {
235- if (http->blocking)
236- {
237- http->wait_value = (int)(http->timeout_value * 1000);
238+ http->wait_value = (int)(http->timeout_value * 1000);
239
240- if (http->wait_value <= 0)
241+ if (http->wait_value <= 0)
242+ {
243+ if (http->blocking)
244 http->wait_value = 60000;
245+ else
246+ http->wait_value = 1000;
247 }
248- else
249- http->wait_value = 10000;
250 }
251
252
253diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c
254index 9fcbe0af3..f746f4cba 100644
255--- a/cups/tls-openssl.c
256+++ b/cups/tls-openssl.c
257@@ -215,12 +215,14 @@ cupsMakeServerCredentials(
258 // Save them...
259 if ((bio = BIO_new_file(keyfile, "wb")) == NULL)
260 {
261+ DEBUG_printf(("1cupsMakeServerCredentials: Unable to create private key file '%s': %s", keyfile, strerror(errno)));
262 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
263 goto done;
264 }
265
266 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL))
267 {
268+ DEBUG_puts("1cupsMakeServerCredentials: PEM_write_bio_PrivateKey failed.");
269 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write private key."), 1);
270 BIO_free(bio);
271 goto done;
272@@ -230,12 +232,14 @@ cupsMakeServerCredentials(
273
274 if ((bio = BIO_new_file(crtfile, "wb")) == NULL)
275 {
276+ DEBUG_printf(("1cupsMakeServerCredentials: Unable to create certificate file '%s': %s", crtfile, strerror(errno)));
277 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
278 goto done;
279 }
280
281 if (!PEM_write_bio_X509(bio, cert))
282 {
283+ DEBUG_puts("1cupsMakeServerCredentials: PEM_write_bio_X509 failed.");
284 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write X.509 certificate."), 1);
285 BIO_free(bio);
286 goto done;
287@@ -1082,10 +1086,10 @@ _httpTLSStart(http_t *http) // I - Connection to server
288
289 if (!cupsMakeServerCredentials(tls_keypath, cn, 0, NULL, time(NULL) + 3650 * 86400))
290 {
291- DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed.");
292+ DEBUG_printf(("4_httpTLSStart: cupsMakeServerCredentials failed: %s", cupsLastErrorString()));
293 http->error = errno = EINVAL;
294 http->status = HTTP_STATUS_ERROR;
295- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);
296+// _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);
297 SSL_CTX_free(context);
298 _cupsMutexUnlock(&tls_mutex);
299
300@@ -1346,14 +1350,17 @@ http_bio_read(BIO *h, // I - BIO data
301
302 http = (http_t *)BIO_get_data(h);
303
304- if (!http->blocking)
305+ if (!http->blocking || http->timeout_value > 0.0)
306 {
307 /*
308 * Make sure we have data before we read...
309 */
310
311- if (!_httpWait(http, 10000, 0))
312+ while (!_httpWait(http, http->wait_value, 0))
313 {
314+ if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
315+ continue;
316+
317 #ifdef WIN32
318 http->error = WSAETIMEDOUT;
319 #else
320diff --git a/scheduler/client.c b/scheduler/client.c
321index 233f9017d..d495d9a75 100644
322--- a/scheduler/client.c
323+++ b/scheduler/client.c
324@@ -34,11 +34,11 @@
325
326 static int check_if_modified(cupsd_client_t *con,
327 struct stat *filestats);
328-static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
329- void *data);
330 #ifdef HAVE_TLS
331-static int cupsd_start_tls(cupsd_client_t *con, http_encryption_t e);
332+static int check_start_tls(cupsd_client_t *con);
333 #endif /* HAVE_TLS */
334+static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
335+ void *data);
336 static char *get_file(cupsd_client_t *con, struct stat *filestats,
337 char *filename, size_t len);
338 static http_status_t install_cupsd_conf(cupsd_client_t *con);
339@@ -360,14 +360,20 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
340 if (lis->encryption == HTTP_ENCRYPTION_ALWAYS)
341 {
342 /*
343- * https connection; go secure...
344+ * HTTPS connection, force TLS negotiation...
345 */
346
347- if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS))
348- cupsdCloseClient(con);
349+ con->tls_start = time(NULL);
350+ con->encryption = HTTP_ENCRYPTION_ALWAYS;
351 }
352 else
353+ {
354+ /*
355+ * HTTP connection, but check for HTTPS negotiation on first data...
356+ */
357+
358 con->auto_ssl = 1;
359+ }
360 #endif /* HAVE_TLS */
361 }
362
363@@ -606,17 +612,46 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
364
365 con->auto_ssl = 0;
366
367- if (recv(httpGetFd(con->http), buf, 1, MSG_PEEK) == 1 &&
368- (!buf[0] || !strchr("DGHOPT", buf[0])))
369+ if (recv(httpGetFd(con->http), buf, 5, MSG_PEEK) == 5 && buf[0] == 0x16 && buf[1] == 3 && buf[2])
370 {
371 /*
372- * Encrypt this connection...
373+ * Client hello record, encrypt this connection...
374 */
375
376- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw first byte %02X, auto-negotiating SSL/TLS session.", buf[0] & 255);
377+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw client hello record, auto-negotiating TLS session.");
378+ con->tls_start = time(NULL);
379+ con->encryption = HTTP_ENCRYPTION_ALWAYS;
380+ }
381+ }
382
383- if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS))
384- cupsdCloseClient(con);
385+ if (con->tls_start)
386+ {
387+ /*
388+ * Try negotiating TLS...
389+ */
390+
391+ int tls_status = check_start_tls(con);
392+
393+ if (tls_status < 0)
394+ {
395+ /*
396+ * TLS negotiation failed, close the connection.
397+ */
398+
399+ cupsdCloseClient(con);
400+ return;
401+ }
402+ else if (tls_status == 0)
403+ {
404+ /*
405+ * Nothing to do yet...
406+ */
407+
408+ if ((time(NULL) - con->tls_start) > 5)
409+ {
410+ // Timeout, close the connection...
411+ cupsdCloseClient(con);
412+ }
413
414 return;
415 }
416@@ -780,9 +815,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
417 * Parse incoming parameters until the status changes...
418 */
419
420- while ((status = httpUpdate(con->http)) == HTTP_STATUS_CONTINUE)
421- if (!httpGetReady(con->http))
422- break;
423+ status = httpUpdate(con->http);
424
425 if (status != HTTP_STATUS_OK && status != HTTP_STATUS_CONTINUE)
426 {
427@@ -944,11 +977,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
428 return;
429 }
430
431- if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED))
432- {
433- cupsdCloseClient(con);
434- return;
435- }
436+ con->tls_start = time(NULL);
437+ con->tls_upgrade = 1;
438+ con->encryption = HTTP_ENCRYPTION_REQUIRED;
439+ return;
440 #else
441 if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE))
442 {
443@@ -987,32 +1019,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
444 if (!_cups_strcasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION),
445 "Upgrade") && !httpIsEncrypted(con->http))
446 {
447-#ifdef HAVE_TLS
448- /*
449- * Do encryption stuff...
450- */
451-
452- httpClearFields(con->http);
453-
454- if (!cupsdSendHeader(con, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL,
455- CUPSD_AUTH_NONE))
456- {
457- cupsdCloseClient(con);
458- return;
459- }
460-
461- if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED))
462- {
463- cupsdCloseClient(con);
464- return;
465- }
466-#else
467 if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE))
468 {
469 cupsdCloseClient(con);
470 return;
471 }
472-#endif /* HAVE_TLS */
473 }
474
475 if ((status = cupsdIsAuthorized(con, NULL)) != HTTP_STATUS_OK)
476@@ -2685,6 +2696,69 @@ check_if_modified(
477 }
478
479
480+#ifdef HAVE_TLS
481+/*
482+ * 'check_start_tls()' - Start encryption on a connection.
483+ */
484+
485+static int /* O - 0 to continue, 1 on success, -1 on error */
486+check_start_tls(cupsd_client_t *con) /* I - Client connection */
487+{
488+ unsigned char chello[4096]; /* Client hello record */
489+ ssize_t chello_bytes; /* Bytes read/peeked */
490+ int chello_len; /* Length of record */
491+
492+
493+ /*
494+ * See if we have a good and complete client hello record...
495+ */
496+
497+ if ((chello_bytes = recv(httpGetFd(con->http), (char *)chello, sizeof(chello), MSG_PEEK)) < 5)
498+ return (0); /* Not enough bytes (yet) */
499+
500+ if (chello[0] != 0x016 || chello[1] != 3 || chello[2] == 0)
501+ return (-1); /* Not a TLS Client Hello record */
502+
503+ chello_len = (chello[3] << 8) | chello[4];
504+
505+ if ((chello_len + 5) > chello_bytes)
506+ return (0); /* Not enough bytes yet */
507+
508+ /*
509+ * OK, we do, try negotiating...
510+ */
511+
512+ con->tls_start = 0;
513+
514+ if (httpEncryption(con->http, con->encryption))
515+ {
516+ cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s", cupsLastErrorString());
517+ return (-1);
518+ }
519+
520+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted.");
521+
522+ if (con->tls_upgrade)
523+ {
524+ // Respond to the original OPTIONS command...
525+ con->tls_upgrade = 0;
526+
527+ httpClearFields(con->http);
528+ httpClearCookie(con->http);
529+ httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0");
530+
531+ if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE))
532+ {
533+ cupsdCloseClient(con);
534+ return (-1);
535+ }
536+ }
537+
538+ return (1);
539+}
540+#endif /* HAVE_TLS */
541+
542+
543 /*
544 * 'compare_clients()' - Compare two client connections.
545 */
546@@ -2705,28 +2779,6 @@ compare_clients(cupsd_client_t *a, /* I - First client */
547 }
548
549
550-#ifdef HAVE_TLS
551-/*
552- * 'cupsd_start_tls()' - Start encryption on a connection.
553- */
554-
555-static int /* O - 0 on success, -1 on error */
556-cupsd_start_tls(cupsd_client_t *con, /* I - Client connection */
557- http_encryption_t e) /* I - Encryption mode */
558-{
559- if (httpEncryption(con->http, e))
560- {
561- cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s",
562- cupsLastErrorString());
563- return (-1);
564- }
565-
566- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted.");
567- return (0);
568-}
569-#endif /* HAVE_TLS */
570-
571-
572 /*
573 * 'get_file()' - Get a filename and state info.
574 */
575diff --git a/scheduler/client.h b/scheduler/client.h
576index 9fe4e2ea6..2939ce997 100644
577--- a/scheduler/client.h
578+++ b/scheduler/client.h
579@@ -53,6 +53,9 @@ struct cupsd_client_s
580 cups_lang_t *language; /* Language to use */
581 #ifdef HAVE_TLS
582 int auto_ssl; /* Automatic test for SSL/TLS */
583+ time_t tls_start; /* Do TLS negotiation? */
584+ int tls_upgrade; /* Doing TLS upgrade via OPTIONS? */
585+ http_encryption_t encryption; /* Type of TLS negotiation */
586 #endif /* HAVE_TLS */
587 http_addr_t clientaddr; /* Client's server address */
588 char clientname[256];/* Client's server name for connection */
589diff --git a/scheduler/select.c b/scheduler/select.c
590index 2e64f2a7e..ac6205c51 100644
591--- a/scheduler/select.c
592+++ b/scheduler/select.c
593@@ -408,6 +408,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
594
595 cupsd_in_select = 1;
596
597+ // Prevent 100% CPU by releasing control before the kevent call...
598+ usleep(1);
599+
600 if (timeout >= 0 && timeout < 86400)
601 {
602 ktimeout.tv_sec = timeout;
603@@ -452,6 +455,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
604 struct epoll_event *event; /* Current event */
605
606
607+ // Prevent 100% CPU by releasing control before the epoll_wait call...
608+ usleep(1);
609+
610 if (timeout >= 0 && timeout < 86400)
611 nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
612 timeout * 1000);
613@@ -544,6 +550,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
614 }
615 }
616
617+ // Prevent 100% CPU by releasing control before the poll call...
618+ usleep(1);
619+
620 if (timeout >= 0 && timeout < 86400)
621 nfds = poll(cupsd_pollfds, (nfds_t)count, timeout * 1000);
622 else
623@@ -597,6 +606,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
624 cupsd_current_input = cupsd_global_input;
625 cupsd_current_output = cupsd_global_output;
626
627+ // Prevent 100% CPU by releasing control before the select call...
628+ usleep(1);
629+
630 if (timeout >= 0 && timeout < 86400)
631 {
632 stimeout.tv_sec = timeout;
633--
6342.44.1
635