]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Mirror changes from trunk.
[thirdparty/cups.git] / cups / http.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
71e16022 4 * HTTP routines for CUPS.
ef416fc2 5 *
db8b865d 6 * Copyright 2007-2013 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
f7deaa1a 9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
11 *
ef416fc2 12 * These coded instructions, statements, and computer programs are the
bc44d920 13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
18 * This file is subject to the Apple OS-Developed Software exception.
19 *
20 * Contents:
21 *
a469f8a5
MS
22 * httpAcceptConnection() - Accept a new HTTP client connection from
23 * the specified listening socket.
24 * httpAddCredential() - Allocates and adds a single credential to
25 * an array.
26 * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP
27 * connections.
28 * httpBlocking() - Set blocking/non-blocking behavior on a
29 * connection.
30 * httpCheck() - Check to see if there is a pending response
31 * from the server.
32 * httpClearCookie() - Clear the cookie value(s).
33 * httpClearFields() - Clear HTTP request fields.
34 * httpClose() - Close an HTTP connection.
35 * httpConnect() - Connect to a HTTP server.
36 * httpConnect2() - Connect to a HTTP server.
37 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
38 * httpCopyCredentials() - Copy the credentials associated with an
39 * encrypted connection.
a469f8a5
MS
40 * _httpCreateCredentials() - Create credentials in the internal format.
41 * httpDelete() - Send a DELETE request to the server.
42 * _httpDisconnect() - Disconnect a HTTP connection.
43 * httpEncryption() - Set the required encryption on the link.
44 * httpError() - Get the last error on a connection.
45 * httpFlush() - Flush data from a HTTP connection.
46 * httpFlushWrite() - Flush data in write buffer.
47 * _httpFreeCredentials() - Free internal credentials.
48 * httpFreeCredentials() - Free an array of credentials.
49 * httpGet() - Send a GET request to the server.
a469f8a5
MS
50 * httpGetAuthString() - Get the current authorization string.
51 * httpGetBlocking() - Get the blocking/non-block state of a
52 * connection.
6961465f
MS
53 * httpGetContentEncoding() - Get a common content encoding, if any,
54 * between the client and server.
a469f8a5 55 * httpGetCookie() - Get any cookie data from the response.
0fa6c7fa 56 * httpGetExpect() - Get the value of the Expect header, if any.
a469f8a5
MS
57 * httpGetFd() - Get the file descriptor associated with a
58 * connection.
59 * httpGetField() - Get a field value from a request/response.
60 * httpGetLength() - Get the amount of data remaining from the
61 * content-length or transfer-encoding fields.
62 * httpGetLength2() - Get the amount of data remaining from the
63 * content-length or transfer-encoding fields.
64 * httpGets() - Get a line of text from a HTTP connection.
65 * httpGetState() - Get the current state of the HTTP request.
66 * httpGetStatus() - Get the status of the last HTTP request.
67 * httpGetSubField() - Get a sub-field value.
68 * httpGetSubField2() - Get a sub-field value.
69 * httpGetVersion() - Get the HTTP version at the other end.
70 * httpHead() - Send a HEAD request to the server.
71 * httpInitialize() - Initialize the HTTP interface library and
72 * set the default HTTP proxy (if any).
73 * httpOptions() - Send an OPTIONS request to the server.
74 * httpPeek() - Peek at data from a HTTP connection.
75 * httpPost() - Send a POST request to the server.
76 * httpPrintf() - Print a formatted string to a HTTP
77 * connection.
78 * httpPut() - Send a PUT request to the server.
79 * httpRead() - Read data from a HTTP connection.
80 * httpRead2() - Read data from a HTTP connection.
81 * _httpReadCDSA() - Read function for the CDSA library.
82 * _httpReadGNUTLS() - Read function for the GNU TLS library.
83 * httpReadRequest() - Read a HTTP request from a connection.
84 * httpReconnect() - Reconnect to a HTTP server.
85 * httpReconnect2() - Reconnect to a HTTP server with timeout and
86 * optional cancel.
87 * httpSetAuthString() - Set the current authorization string.
88 * httpSetCredentials() - Set the credentials associated with an
89 * encrypted connection.
90 * httpSetCookie() - Set the cookie value(s).
0fa6c7fa 91 * httpSetDefaultField() - Set the default value of an HTTP header.
a469f8a5
MS
92 * httpSetExpect() - Set the Expect: header in a request.
93 * httpSetField() - Set the value of an HTTP header.
94 * httpSetLength() - Set the content-length and
95 * content-encoding.
96 * httpSetTimeout() - Set read/write timeouts and an optional
97 * callback.
98 * httpTrace() - Send an TRACE request to the server.
99 * _httpUpdate() - Update the current HTTP status for incoming
100 * data.
101 * httpUpdate() - Update the current HTTP state for incoming
102 * data.
103 * _httpWait() - Wait for data available on a connection (no
104 * flush).
105 * httpWait() - Wait for data available on a connection.
106 * httpWrite() - Write data to a HTTP connection.
107 * httpWrite2() - Write data to a HTTP connection.
108 * _httpWriteCDSA() - Write function for the CDSA library.
109 * _httpWriteGNUTLS() - Write function for the GNU TLS library.
110 * httpWriteResponse() - Write a HTTP response to a client
111 * connection.
112 * http_bio_ctrl() - Control the HTTP connection.
113 * http_bio_free() - Free OpenSSL data.
114 * http_bio_new() - Initialize an OpenSSL BIO structure.
115 * http_bio_puts() - Send a string for OpenSSL.
116 * http_bio_read() - Read data for OpenSSL.
117 * http_bio_write() - Write data for OpenSSL.
118 * http_content_coding_finish() - Finish doing any content encoding.
119 * http_content_coding_start() - Start doing content encoding.
db8b865d 120 * http_create() - Create an unconnected HTTP connection.
a469f8a5
MS
121 * http_debug_hex() - Do a hex dump of a buffer.
122 * http_field() - Return the field index for a field name.
0fa6c7fa
MS
123 * http_read() - Read a buffer from a HTTP connection.
124 * http_read_buffered() - Do a buffered read from a HTTP connection.
125 * http_read_chunk() - Read a chunk from a HTTP connection.
a469f8a5
MS
126 * http_read_ssl() - Read from a SSL/TLS connection.
127 * http_send() - Send a request with all fields and the
128 * trailing blank line.
129 * http_set_credentials() - Set the SSL/TLS credentials.
0fa6c7fa
MS
130 * http_set_length() - Set the data_encoding and data_remaining
131 * values.
a469f8a5
MS
132 * http_set_timeout() - Set the socket timeout values.
133 * http_set_wait() - Set the default wait value for reads.
134 * http_setup_ssl() - Set up SSL/TLS support on a connection.
135 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
cb7f98ee
MS
136 * http_state_string() - Return the string associated with a given
137 * HTTP state.
a469f8a5
MS
138 * http_upgrade() - Force upgrade to TLS encryption.
139 * http_write() - Write a buffer to a HTTP connection.
140 * http_write_chunk() - Write a chunked buffer.
141 * http_write_ssl() - Write to a SSL/TLS connection.
ef416fc2 142 */
143
144/*
145 * Include necessary headers...
146 */
147
71e16022 148#include "cups-private.h"
ef416fc2 149#include <fcntl.h>
83e08001 150#include <math.h>
cc754834
MS
151#ifdef WIN32
152# include <tchar.h>
153#else
ef416fc2 154# include <signal.h>
155# include <sys/time.h>
156# include <sys/resource.h>
cc754834 157#endif /* WIN32 */
f7deaa1a 158#ifdef HAVE_POLL
dcb445bc 159# include <poll.h>
f7deaa1a 160#endif /* HAVE_POLL */
ef416fc2 161
162
ef416fc2 163/*
164 * Local functions...
165 */
166
a469f8a5
MS
167#ifdef HAVE_LIBZ
168static void http_content_coding_finish(http_t *http);
169static void http_content_coding_start(http_t *http,
170 const char *value);
171#endif /* HAVE_LIBZ */
db8b865d
MS
172static http_t *http_create(const char *host, int port,
173 http_addrlist_t *addrlist, int family,
174 http_encryption_t encryption,
175 int blocking, _http_mode_t mode);
ae71f5de
MS
176#ifdef DEBUG
177static void http_debug_hex(const char *prefix, const char *buffer,
178 int bytes);
179#endif /* DEBUG */
ef416fc2 180static http_field_t http_field(const char *name);
0fa6c7fa
MS
181static ssize_t http_read(http_t *http, char *buffer, size_t length);
182static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length);
183static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length);
ef416fc2 184static int http_send(http_t *http, http_state_t request,
185 const char *uri);
0fa6c7fa
MS
186static ssize_t http_write(http_t *http, const char *buffer,
187 size_t length);
188static ssize_t http_write_chunk(http_t *http, const char *buffer,
189 size_t length);
ef416fc2 190#ifdef HAVE_SSL
191static int http_read_ssl(http_t *http, char *buf, int len);
c1420c87 192# ifdef HAVE_CDSASSL
7cf5915e 193static int http_set_credentials(http_t *http);
c1420c87 194# endif /* HAVE_CDSASSL */
d7225fc2 195#endif /* HAVE_SSL */
a469f8a5 196static off_t http_set_length(http_t *http);
85dda01c
MS
197static void http_set_timeout(int fd, double timeout);
198static void http_set_wait(http_t *http);
cb7f98ee
MS
199#ifdef DEBUG
200static const char *http_state_string(http_state_t state);
201#endif /* DEBUG */
d7225fc2 202#ifdef HAVE_SSL
ef416fc2 203static int http_setup_ssl(http_t *http);
204static void http_shutdown_ssl(http_t *http);
205static int http_upgrade(http_t *http);
206static int http_write_ssl(http_t *http, const char *buf, int len);
207#endif /* HAVE_SSL */
208
209
210/*
211 * Local globals...
212 */
213
214static const char * const http_fields[] =
215 {
216 "Accept-Language",
217 "Accept-Ranges",
218 "Authorization",
219 "Connection",
220 "Content-Encoding",
221 "Content-Language",
222 "Content-Length",
223 "Content-Location",
224 "Content-MD5",
225 "Content-Range",
226 "Content-Type",
227 "Content-Version",
228 "Date",
229 "Host",
230 "If-Modified-Since",
231 "If-Unmodified-since",
232 "Keep-Alive",
233 "Last-Modified",
234 "Link",
235 "Location",
236 "Range",
237 "Referer",
238 "Retry-After",
239 "Transfer-Encoding",
240 "Upgrade",
241 "User-Agent",
a469f8a5
MS
242 "WWW-Authenticate",
243 "Accept-Encoding",
244 "Allow",
245 "Server"
ef416fc2 246 };
247
248
411affcf 249#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
250/*
251 * BIO methods for OpenSSL...
252 */
253
254static int http_bio_write(BIO *h, const char *buf, int num);
255static int http_bio_read(BIO *h, char *buf, int size);
256static int http_bio_puts(BIO *h, const char *str);
257static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
258static int http_bio_new(BIO *h);
259static int http_bio_free(BIO *data);
260
261static BIO_METHOD http_bio_methods =
262 {
263 BIO_TYPE_SOCKET,
264 "http",
265 http_bio_write,
266 http_bio_read,
267 http_bio_puts,
268 NULL, /* http_bio_gets, */
269 http_bio_ctrl,
270 http_bio_new,
271 http_bio_free,
272 NULL,
273 };
7cf5915e 274#endif /* HAVE_SSL && HAVE_LIBSSL */
411affcf 275
276
a469f8a5
MS
277/*
278 * 'httpAcceptConnection()' - Accept a new HTTP client connection from the
279 * specified listening socket.
280 *
9c0e8e5d 281 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
282 */
283
284http_t * /* O - HTTP connection or @code NULL@ */
285httpAcceptConnection(int fd, /* I - Listen socket file descriptor */
286 int blocking) /* I - 1 if the connection should be
287 blocking, 0 otherwise */
288{
289 http_t *http; /* HTTP connection */
290 http_addrlist_t addrlist; /* Dummy address list */
291 socklen_t addrlen; /* Length of address */
292 int val; /* Socket option value */
293
294
295 /*
296 * Range check input...
297 */
298
299 if (fd < 0)
300 return (NULL);
301
302 /*
303 * Create the client connection...
304 */
305
306 memset(&addrlist, 0, sizeof(addrlist));
307
db8b865d 308 if ((http = http_create(NULL, 0, &addrlist, AF_UNSPEC,
a469f8a5
MS
309 HTTP_ENCRYPTION_IF_REQUESTED, blocking,
310 _HTTP_MODE_SERVER)) == NULL)
311 return (NULL);
312
313 /*
314 * Accept the client and get the remote address...
315 */
316
317 addrlen = sizeof(http_addr_t);
318
319 if ((http->fd = accept(fd, (struct sockaddr *)&(http->addrlist->addr),
320 &addrlen)) < 0)
321 {
322 _cupsSetHTTPError(HTTP_STATUS_ERROR);
323 httpClose(http);
324
325 return (NULL);
326 }
327
328 httpAddrString(&(http->addrlist->addr), http->hostname,
329 sizeof(http->hostname));
330
331#ifdef SO_NOSIGPIPE
332 /*
333 * Disable SIGPIPE for this socket.
334 */
335
336 val = 1;
db8b865d 337 setsockopt(http->fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
a469f8a5
MS
338#endif /* SO_NOSIGPIPE */
339
340 /*
341 * Using TCP_NODELAY improves responsiveness, especially on systems
342 * with a slow loopback interface. Since we write large buffers
343 * when sending print files and requests, there shouldn't be any
344 * performance penalty for this...
345 */
346
347 val = 1;
db8b865d 348 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
a469f8a5
MS
349
350#ifdef FD_CLOEXEC
351 /*
352 * Close this socket when starting another process...
353 */
354
355 fcntl(http->fd, F_SETFD, FD_CLOEXEC);
356#endif /* FD_CLOEXEC */
357
358 return (http);
359}
360
361
7cf5915e
MS
362/*
363 * 'httpAddCredential()' - Allocates and adds a single credential to an array.
364 *
365 * Use @code cupsArrayNew(NULL, NULL)@ to create a credentials array.
366 *
f3c17241 367 * @since CUPS 1.5/OS X 10.7@
7cf5915e
MS
368 */
369
370int /* O - 0 on success, -1 on error */
371httpAddCredential(
372 cups_array_t *credentials, /* I - Credentials array */
373 const void *data, /* I - PEM-encoded X.509 data */
374 size_t datalen) /* I - Length of data */
375{
376 http_credential_t *credential; /* Credential data */
377
378
379 if ((credential = malloc(sizeof(http_credential_t))) != NULL)
380 {
381 credential->datalen = datalen;
382
383 if ((credential->data = malloc(datalen)) != NULL)
384 {
385 memcpy(credential->data, data, datalen);
386 cupsArrayAdd(credentials, credential);
387 return (0);
388 }
389
390 free(credential);
391 }
392
393 return (-1);
394}
395
396
397#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
411affcf 398/*
399 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
400 */
401
402BIO_METHOD * /* O - BIO methods for OpenSSL */
403_httpBIOMethods(void)
404{
405 return (&http_bio_methods);
406}
407#endif /* HAVE_SSL && HAVE_LIBSSL */
408
409
ecdc0628 410/*
411 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
412 */
413
414void
568fa3fa 415httpBlocking(http_t *http, /* I - Connection to server */
ecdc0628 416 int b) /* I - 1 = blocking, 0 = non-blocking */
417{
418 if (http)
85dda01c 419 {
ecdc0628 420 http->blocking = b;
85dda01c
MS
421 http_set_wait(http);
422 }
ecdc0628 423}
424
425
ef416fc2 426/*
427 * 'httpCheck()' - Check to see if there is a pending response from the server.
428 */
429
ecdc0628 430int /* O - 0 = no data, 1 = data available */
568fa3fa 431httpCheck(http_t *http) /* I - Connection to server */
ef416fc2 432{
433 return (httpWait(http, 0));
434}
435
436
437/*
438 * 'httpClearCookie()' - Clear the cookie value(s).
439 *
f3c17241 440 * @since CUPS 1.1.19/OS X 10.3@
ef416fc2 441 */
442
443void
568fa3fa 444httpClearCookie(http_t *http) /* I - Connection to server */
ef416fc2 445{
446 if (!http)
447 return;
448
449 if (http->cookie)
450 {
451 free(http->cookie);
452 http->cookie = NULL;
453 }
454}
455
456
ecdc0628 457/*
458 * 'httpClearFields()' - Clear HTTP request fields.
459 */
460
461void
568fa3fa 462httpClearFields(http_t *http) /* I - Connection to server */
ecdc0628 463{
a469f8a5
MS
464 DEBUG_printf(("httpClearFields(http=%p)", http));
465
ecdc0628 466 if (http)
467 {
468 memset(http->fields, 0, sizeof(http->fields));
a469f8a5
MS
469
470 if (http->mode == _HTTP_MODE_CLIENT)
471 {
472 if (http->hostname[0] == '/')
473 httpSetField(http, HTTP_FIELD_HOST, "localhost");
474 else
475 httpSetField(http, HTTP_FIELD_HOST, http->hostname);
476 }
b423cd4c 477
f7deaa1a 478 if (http->field_authorization)
479 {
480 free(http->field_authorization);
481 http->field_authorization = NULL;
482 }
483
a469f8a5
MS
484 if (http->accept_encoding)
485 {
486 _cupsStrFree(http->accept_encoding);
487 http->accept_encoding = NULL;
488 }
489
490 if (http->allow)
491 {
492 _cupsStrFree(http->allow);
493 http->allow = NULL;
494 }
495
496 if (http->server)
497 {
498 _cupsStrFree(http->server);
499 http->server = NULL;
500 }
501
b423cd4c 502 http->expect = (http_status_t)0;
ecdc0628 503 }
504}
505
506
ef416fc2 507/*
6d2f911b 508 * 'httpClose()' - Close an HTTP connection.
ef416fc2 509 */
510
511void
568fa3fa 512httpClose(http_t *http) /* I - Connection to server */
ef416fc2 513{
f7deaa1a 514#ifdef HAVE_GSSAPI
1f0275e3 515 OM_uint32 minor_status; /* Minor status code */
f7deaa1a 516#endif /* HAVE_GSSAPI */
517
518
e07d4801 519 DEBUG_printf(("httpClose(http=%p)", http));
ef416fc2 520
6d2f911b
MS
521 /*
522 * Range check input...
523 */
524
ef416fc2 525 if (!http)
526 return;
527
6d2f911b
MS
528 /*
529 * Close any open connection...
530 */
531
532 _httpDisconnect(http);
533
534 /*
535 * Free memory used...
536 */
537
ef416fc2 538 httpAddrFreeList(http->addrlist);
539
ef416fc2 540 if (http->cookie)
541 free(http->cookie);
542
f7deaa1a 543#ifdef HAVE_GSSAPI
544 if (http->gssctx != GSS_C_NO_CONTEXT)
1f0275e3 545 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
f7deaa1a 546
547 if (http->gssname != GSS_C_NO_NAME)
1f0275e3 548 gss_release_name(&minor_status, &http->gssname);
f7deaa1a 549#endif /* HAVE_GSSAPI */
550
b94498cf 551#ifdef HAVE_AUTHORIZATION_H
552 if (http->auth_ref)
553 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
554#endif /* HAVE_AUTHORIZATION_H */
555
f7deaa1a 556 httpClearFields(http);
557
558 if (http->authstring && http->authstring != http->_authstring)
559 free(http->authstring);
560
ef416fc2 561 free(http);
562}
563
564
565/*
566 * 'httpConnect()' - Connect to a HTTP server.
1ff0402e 567 *
a469f8a5 568 * This function is deprecated - use @link httpConnect2@ instead.
1ff0402e
MS
569 *
570 * @deprecated@
ef416fc2 571 */
572
573http_t * /* O - New HTTP connection */
574httpConnect(const char *host, /* I - Host to connect to */
575 int port) /* I - Port number */
576{
cb7f98ee 577 return (httpConnect2(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED,
a469f8a5 578 1, 30000, NULL));
1ff0402e
MS
579}
580
581
582/*
a469f8a5
MS
583 * 'httpConnect2()' - Connect to a HTTP server.
584 *
9c0e8e5d 585 * @since CUPS 1.7/OS X 10.9@
1ff0402e
MS
586 */
587
588http_t * /* O - New HTTP connection */
a469f8a5 589httpConnect2(
1ff0402e
MS
590 const char *host, /* I - Host to connect to */
591 int port, /* I - Port number */
a469f8a5
MS
592 http_addrlist_t *addrlist, /* I - List of addresses or NULL to lookup */
593 int family, /* I - Address family to use or @code AF_UNSPEC@ for any */
594 http_encryption_t encryption, /* I - Type of encryption to use */
595 int blocking, /* I - 1 for blocking connection, 0 for non-blocking */
db8b865d 596 int msec, /* I - Connection timeout in milliseconds, 0 means don't connect */
a469f8a5 597 int *cancel) /* I - Pointer to "cancel" variable */
1ff0402e
MS
598{
599 http_t *http; /* New HTTP connection */
ef416fc2 600
601
a469f8a5
MS
602 DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, "
603 "encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port,
604 addrlist, family, encryption, blocking, msec, cancel));
1ff0402e 605
ef416fc2 606 /*
1ff0402e 607 * Create the HTTP structure...
ef416fc2 608 */
609
db8b865d 610 if ((http = http_create(host, port, addrlist, family, encryption, blocking,
a469f8a5 611 _HTTP_MODE_CLIENT)) == NULL)
1ff0402e 612 return (NULL);
ef416fc2 613
1ff0402e 614 /*
db8b865d 615 * Optionally connect to the remote system...
1ff0402e
MS
616 */
617
db8b865d 618 if (msec == 0 || !httpReconnect2(http, msec, cancel))
1ff0402e
MS
619 return (http);
620
621 /*
622 * Could not connect to any known address - bail out!
623 */
624
a469f8a5 625 httpClose(http);
1ff0402e
MS
626
627 return (NULL);
ef416fc2 628}
629
630
a469f8a5
MS
631/*
632 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
633 *
634 * This function is now deprecated. Please use the @link httpConnect2@ function
635 * instead.
636 *
637 * @deprecated@
638 */
639
640http_t * /* O - New HTTP connection */
641httpConnectEncrypt(
642 const char *host, /* I - Host to connect to */
643 int port, /* I - Port number */
644 http_encryption_t encryption) /* I - Type of encryption to use */
645{
646 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
647 host, port, encryption));
648
649 return (httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000,
650 NULL));
651}
652
653
7cf5915e
MS
654/*
655 * 'httpCopyCredentials()' - Copy the credentials associated with an encrypted
656 * connection.
657 *
f3c17241 658 * @since CUPS 1.5/OS X 10.7@
7cf5915e
MS
659 */
660
661int /* O - Status of call (0 = success) */
662httpCopyCredentials(
663 http_t *http, /* I - Connection to server */
664 cups_array_t **credentials) /* O - Array of credentials */
665{
666# ifdef HAVE_LIBSSL
667# elif defined(HAVE_GNUTLS)
c1420c87 668# elif defined(HAVE_CDSASSL)
7cf5915e 669 OSStatus error; /* Error code */
c1420c87 670 SecTrustRef peerTrust; /* Peer trust reference */
7cf5915e 671 CFIndex count; /* Number of credentials */
7cf5915e
MS
672 SecCertificateRef secCert; /* Certificate reference */
673 CFDataRef data; /* Certificate data */
674 int i; /* Looping var */
675# elif defined(HAVE_SSPISSL)
676# endif /* HAVE_LIBSSL */
677
678
679 if (credentials)
680 *credentials = NULL;
681
682 if (!http || !http->tls || !credentials)
683 return (-1);
684
685# ifdef HAVE_LIBSSL
686 return (-1);
687
688# elif defined(HAVE_GNUTLS)
689 return (-1);
690
c1420c87
MS
691# elif defined(HAVE_CDSASSL)
692 if (!(error = SSLCopyPeerTrust(http->tls, &peerTrust)) && peerTrust)
7cf5915e
MS
693 {
694 if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL)
695 {
c1420c87
MS
696 count = SecTrustGetCertificateCount(peerTrust);
697
698 for (i = 0; i < count; i ++)
7cf5915e 699 {
c1420c87 700 secCert = SecTrustGetCertificateAtIndex(peerTrust, i);
7cf5915e
MS
701 if ((data = SecCertificateCopyData(secCert)))
702 {
703 httpAddCredential(*credentials, CFDataGetBytePtr(data),
704 CFDataGetLength(data));
705 CFRelease(data);
706 }
707 }
708 }
709
c1420c87 710 CFRelease(peerTrust);
7cf5915e
MS
711 }
712
713 return (error);
714
715# elif defined(HAVE_SSPISSL)
716 return (-1);
82f97232
MS
717
718# else
719 return (-1);
7cf5915e
MS
720# endif /* HAVE_LIBSSL */
721}
722
723
85dda01c
MS
724/*
725 * '_httpCreateCredentials()' - Create credentials in the internal format.
726 */
727
728http_tls_credentials_t /* O - Internal credentials */
729_httpCreateCredentials(
730 cups_array_t *credentials) /* I - Array of credentials */
731{
732 if (!credentials)
733 return (NULL);
734
735# ifdef HAVE_LIBSSL
736 return (NULL);
737
738# elif defined(HAVE_GNUTLS)
739 return (NULL);
740
c1420c87 741# elif defined(HAVE_CDSASSL)
85dda01c
MS
742 CFMutableArrayRef peerCerts; /* Peer credentials reference */
743 SecCertificateRef secCert; /* Certificate reference */
744 CFDataRef data; /* Credential data reference */
745 http_credential_t *credential; /* Credential data */
746
747
748 if ((peerCerts = CFArrayCreateMutable(kCFAllocatorDefault,
749 cupsArrayCount(credentials),
750 &kCFTypeArrayCallBacks)) == NULL)
751 return (NULL);
752
753 for (credential = (http_credential_t *)cupsArrayFirst(credentials);
754 credential;
755 credential = (http_credential_t *)cupsArrayNext(credentials))
756 {
757 if ((data = CFDataCreate(kCFAllocatorDefault, credential->data,
758 credential->datalen)))
759 {
760 if ((secCert = SecCertificateCreateWithData(kCFAllocatorDefault, data))
761 != NULL)
762 {
763 CFArrayAppendValue(peerCerts, secCert);
764 CFRelease(secCert);
765 }
766
767 CFRelease(data);
768 }
769 }
770
771 return (peerCerts);
772
773# elif defined(HAVE_SSPISSL)
774 return (NULL);
775
776# else
777 return (NULL);
778# endif /* HAVE_LIBSSL */
779}
780
781
ef416fc2 782/*
783 * 'httpDelete()' - Send a DELETE request to the server.
784 */
785
786int /* O - Status of call (0 = success) */
568fa3fa 787httpDelete(http_t *http, /* I - Connection to server */
ef416fc2 788 const char *uri) /* I - URI to delete */
789{
cb7f98ee 790 return (http_send(http, HTTP_STATE_DELETE, uri));
ef416fc2 791}
792
793
6d2f911b
MS
794/*
795 * '_httpDisconnect()' - Disconnect a HTTP connection.
796 */
797
798void
799_httpDisconnect(http_t *http) /* I - Connection to server */
800{
801#ifdef HAVE_SSL
802 if (http->tls)
803 http_shutdown_ssl(http);
804#endif /* HAVE_SSL */
805
806#ifdef WIN32
807 closesocket(http->fd);
808#else
809 close(http->fd);
810#endif /* WIN32 */
811
812 http->fd = -1;
813}
814
815
ef416fc2 816/*
817 * 'httpEncryption()' - Set the required encryption on the link.
818 */
819
820int /* O - -1 on error, 0 on success */
568fa3fa 821httpEncryption(http_t *http, /* I - Connection to server */
ef416fc2 822 http_encryption_t e) /* I - New encryption preference */
823{
e07d4801 824 DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
ef416fc2 825
826#ifdef HAVE_SSL
827 if (!http)
828 return (0);
829
830 http->encryption = e;
831
cb7f98ee
MS
832 if ((http->encryption == HTTP_ENCRYPTION_ALWAYS && !http->tls) ||
833 (http->encryption == HTTP_ENCRYPTION_NEVER && http->tls))
834 return (httpReconnect2(http, 30000, NULL));
835 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
ef416fc2 836 return (http_upgrade(http));
837 else
838 return (0);
839#else
cb7f98ee 840 if (e == HTTP_ENCRYPTION_ALWAYS || e == HTTP_ENCRYPTION_REQUIRED)
ef416fc2 841 return (-1);
842 else
843 return (0);
844#endif /* HAVE_SSL */
845}
846
847
ecdc0628 848/*
849 * 'httpError()' - Get the last error on a connection.
850 */
851
852int /* O - Error code (errno) value */
568fa3fa 853httpError(http_t *http) /* I - Connection to server */
ecdc0628 854{
855 if (http)
856 return (http->error);
857 else
858 return (EINVAL);
859}
860
861
ef416fc2 862/*
863 * 'httpFlush()' - Flush data from a HTTP connection.
864 */
865
866void
568fa3fa 867httpFlush(http_t *http) /* I - Connection to server */
ef416fc2 868{
f8b3a85b
MS
869 char buffer[8192]; /* Junk buffer */
870 int blocking; /* To block or not to block */
871 http_state_t oldstate; /* Old state */
ef416fc2 872
873
f11a948a 874 DEBUG_printf(("httpFlush(http=%p), state=%s", http,
cb7f98ee 875 http_state_string(http->state)));
ef416fc2 876
c1420c87
MS
877 /*
878 * Nothing to do if we are in the "waiting" state...
879 */
880
881 if (http->state == HTTP_STATE_WAITING)
882 return;
883
fa73b229 884 /*
885 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
886 */
887
888 blocking = http->blocking;
889 http->blocking = 0;
890
891 /*
892 * Read any data we can...
893 */
894
f8b3a85b 895 oldstate = http->state;
a4d04587 896 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 897
898 /*
899 * Restore blocking and reset the connection if we didn't get all of
900 * the remaining data...
901 */
902
903 http->blocking = blocking;
904
a469f8a5
MS
905 if (http->state == oldstate && http->state != HTTP_STATE_WAITING &&
906 http->fd >= 0)
fa73b229 907 {
908 /*
909 * Didn't get the data back, so close the current connection.
910 */
911
c41769ff
MS
912#ifdef HAVE_LIBZ
913 if (http->coding)
914 http_content_coding_finish(http);
915#endif /* HAVE_LIBZ */
916
a469f8a5
MS
917 DEBUG_puts("1httpFlush: Setting state to HTTP_STATE_WAITING and closing.");
918
919 http->state = HTTP_STATE_WAITING;
fa73b229 920
921#ifdef HAVE_SSL
922 if (http->tls)
923 http_shutdown_ssl(http);
924#endif /* HAVE_SSL */
925
926#ifdef WIN32
927 closesocket(http->fd);
928#else
929 close(http->fd);
930#endif /* WIN32 */
931
932 http->fd = -1;
933 }
ef416fc2 934}
935
936
937/*
938 * 'httpFlushWrite()' - Flush data in write buffer.
939 *
f3c17241 940 * @since CUPS 1.2/OS X 10.5@
ef416fc2 941 */
942
943int /* O - Bytes written or -1 on error */
568fa3fa 944httpFlushWrite(http_t *http) /* I - Connection to server */
ef416fc2 945{
946 int bytes; /* Bytes written */
947
948
a469f8a5
MS
949 DEBUG_printf(("httpFlushWrite(http=%p) data_encoding=%d", http,
950 http ? http->data_encoding : -1));
ef416fc2 951
952 if (!http || !http->wused)
f8b3a85b
MS
953 {
954 DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." :
955 "1httpFlushWrite: No connection.");
ef416fc2 956 return (0);
f8b3a85b 957 }
ef416fc2 958
a469f8a5 959 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
ef416fc2 960 bytes = http_write_chunk(http, http->wbuffer, http->wused);
961 else
962 bytes = http_write(http, http->wbuffer, http->wused);
963
964 http->wused = 0;
965
22c9029b 966 DEBUG_printf(("1httpFlushWrite: Returning %d, errno=%d.", bytes, errno));
f8b3a85b 967
ef416fc2 968 return (bytes);
969}
970
971
7cf5915e
MS
972/*
973 * '_httpFreeCredentials()' - Free internal credentials.
974 */
975
976void
977_httpFreeCredentials(
978 http_tls_credentials_t credentials) /* I - Internal credentials */
979{
980 if (!credentials)
981 return;
982
983#ifdef HAVE_LIBSSL
984 (void)credentials;
985
986#elif defined(HAVE_GNUTLS)
987 (void)credentials;
988
989#elif defined(HAVE_CDSASSL)
990 CFRelease(credentials);
991
992#elif defined(HAVE_SSPISSL)
993 (void)credentials;
994
995#endif /* HAVE_LIBSSL */
996}
997
998
999/*
1000 * 'httpFreeCredentials()' - Free an array of credentials.
1001 */
1002
1003void
1004httpFreeCredentials(
1005 cups_array_t *credentials) /* I - Array of credentials */
1006{
1007 http_credential_t *credential; /* Credential */
1008
1009
1010 for (credential = (http_credential_t *)cupsArrayFirst(credentials);
1011 credential;
1012 credential = (http_credential_t *)cupsArrayNext(credentials))
1013 {
1014 cupsArrayRemove(credentials, credential);
1015 free((void *)credential->data);
1016 free(credential);
1017 }
1018
1019 cupsArrayDelete(credentials);
1020}
1021
1022
ef416fc2 1023/*
1024 * 'httpGet()' - Send a GET request to the server.
1025 */
1026
1027int /* O - Status of call (0 = success) */
568fa3fa 1028httpGet(http_t *http, /* I - Connection to server */
ef416fc2 1029 const char *uri) /* I - URI to get */
1030{
cb7f98ee 1031 return (http_send(http, HTTP_STATE_GET, uri));
ef416fc2 1032}
1033
1034
6961465f
MS
1035/*
1036 * 'httpGetAuthString()' - Get the current authorization string.
1037 *
1038 * The authorization string is set by cupsDoAuthentication() and
1039 * httpSetAuthString(). Use httpGetAuthString() to retrieve the
1040 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
1041 * value.
1042 *
1043 * @since CUPS 1.3/OS X 10.5@
1044 */
1045
1046char * /* O - Authorization string */
1047httpGetAuthString(http_t *http) /* I - Connection to server */
1048{
1049 if (http)
1050 return (http->authstring);
1051 else
1052 return (NULL);
1053}
1054
1055
1056/*
1057 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
1058 *
1059 * @since CUPS 1.2/OS X 10.5@
1060 */
1061
1062int /* O - 1 if blocking, 0 if non-blocking */
1063httpGetBlocking(http_t *http) /* I - Connection to server */
1064{
1065 return (http ? http->blocking : 0);
1066}
1067
1068
a469f8a5
MS
1069/*
1070 * 'httpGetContentEncoding()' - Get a common content encoding, if any, between
1071 * the client and server.
1072 *
1073 * This function uses the value of the Accepts-Encoding HTTP header and must be
1074 * called after receiving a response from the server or a request from the
1075 * client. The value returned can be use in subsequent requests (for clients)
1076 * or in the response (for servers) in order to compress the content stream.
1077 *
9c0e8e5d 1078 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
1079 */
1080
1081const char * /* O - Content-Coding value or
1082 @code NULL@ for the identity
1083 coding. */
1084httpGetContentEncoding(http_t *http) /* I - Connection to client/server */
1085{
1086#ifdef HAVE_LIBZ
1087 if (http && http->accept_encoding)
1088 {
1089 int i; /* Looping var */
1090 char temp[HTTP_MAX_VALUE], /* Copy of Accepts-Encoding value */
1091 *start, /* Start of coding value */
1092 *end; /* End of coding value */
1093 double qvalue; /* "qvalue" for coding */
1094 struct lconv *loc = localeconv(); /* Locale data */
1095 static const char * const codings[] =
1096 { /* Supported content codings */
1097 "deflate",
1098 "gzip",
1099 "x-deflate",
1100 "x-gzip"
1101 };
1102
1103 strlcpy(temp, http->accept_encoding, sizeof(temp));
1104
1105 for (start = temp; *start; start = end)
1106 {
1107 /*
1108 * Find the end of the coding name...
1109 */
1110
1111 qvalue = 1.0;
1112 end = start;
1113 while (*end && *end != ';' && *end != ',' && !isspace(*end & 255))
1114 end ++;
1115
1116 if (*end == ';')
1117 {
1118 /*
1119 * Grab the qvalue as needed...
1120 */
1121
1122 if (!strncmp(end, ";q=", 3))
1123 qvalue = _cupsStrScand(end + 3, NULL, loc);
1124
1125 /*
1126 * Skip past all attributes...
1127 */
1128
1129 *end++ = '\0';
1130 while (*end && *end != ',' && !isspace(*end & 255))
1131 end ++;
1132 }
1133 else if (*end)
1134 *end++ = '\0';
1135
1136 while (*end && isspace(*end & 255))
1137 end ++;
1138
1139 /*
1140 * Check value if it matches something we support...
1141 */
1142
1143 if (qvalue <= 0.0)
1144 continue;
1145
1146 for (i = 0; i < (int)(sizeof(codings) / sizeof(codings[0])); i ++)
1147 if (!strcmp(start, codings[i]))
1148 return (codings[i]);
1149 }
1150 }
1151#endif /* HAVE_LIBZ */
1152
1153 return (NULL);
1154}
1155
1156
ecdc0628 1157/*
1158 * 'httpGetCookie()' - Get any cookie data from the response.
757d2cad 1159 *
f3c17241 1160 * @since CUPS 1.1.19/OS X 10.3@
ecdc0628 1161 */
1162
1163const char * /* O - Cookie data or NULL */
1164httpGetCookie(http_t *http) /* I - HTTP connecion */
1165{
1166 return (http ? http->cookie : NULL);
1167}
1168
1169
a469f8a5
MS
1170/*
1171 * 'httpGetExpect()' - Get the value of the Expect header, if any.
1172 *
1173 * Returns @code HTTP_STATUS_NONE@ if there is no Expect header, otherwise
1174 * returns the expected HTTP status code, typically @code HTTP_STATUS_CONTINUE@.
1175 *
9c0e8e5d 1176 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
1177 */
1178
1179http_status_t /* O - Expect: status, if any */
1180httpGetExpect(http_t *http) /* I - Connection to client */
1181{
1182 if (!http)
1183 return (HTTP_STATUS_ERROR);
1184 else
1185 return (http->expect);
1186}
1187
1188
ecdc0628 1189/*
1190 * 'httpGetFd()' - Get the file descriptor associated with a connection.
1191 *
f3c17241 1192 * @since CUPS 1.2/OS X 10.5@
ecdc0628 1193 */
1194
1195int /* O - File descriptor or -1 if none */
568fa3fa 1196httpGetFd(http_t *http) /* I - Connection to server */
ecdc0628 1197{
1198 return (http ? http->fd : -1);
1199}
1200
1201
1202/*
1203 * 'httpGetField()' - Get a field value from a request/response.
1204 */
1205
1206const char * /* O - Field value */
568fa3fa 1207httpGetField(http_t *http, /* I - Connection to server */
ecdc0628 1208 http_field_t field) /* I - Field to get */
1209{
1210 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
1211 return (NULL);
a469f8a5
MS
1212
1213 switch (field)
f7deaa1a 1214 {
a469f8a5
MS
1215 case HTTP_FIELD_ACCEPT_ENCODING :
1216 return (http->accept_encoding);
f7deaa1a 1217
a469f8a5
MS
1218 case HTTP_FIELD_ALLOW :
1219 return (http->allow);
1220
1221 case HTTP_FIELD_SERVER :
1222 return (http->server);
1223
1224 case HTTP_FIELD_AUTHORIZATION :
1225 if (http->field_authorization)
1226 {
1227 /*
1228 * Special case for WWW-Authenticate: as its contents can be
1229 * longer than HTTP_MAX_VALUE...
1230 */
1231
1232 return (http->field_authorization);
1233 }
1234
1235 default :
1236 return (http->fields[field]);
f7deaa1a 1237 }
ecdc0628 1238}
1239
1240
1241/*
1242 * 'httpGetLength()' - Get the amount of data remaining from the
1243 * content-length or transfer-encoding fields.
1244 *
1245 * This function is deprecated and will not return lengths larger than
1246 * 2^31 - 1; use httpGetLength2() instead.
1247 *
1248 * @deprecated@
1249 */
1250
1251int /* O - Content length */
568fa3fa 1252httpGetLength(http_t *http) /* I - Connection to server */
ecdc0628 1253{
1254 /*
1255 * Get the read content length and return the 32-bit value.
1256 */
1257
1258 if (http)
1259 {
1260 httpGetLength2(http);
1261
1262 return (http->_data_remaining);
1263 }
1264 else
1265 return (-1);
1266}
1267
1268
1269/*
1270 * 'httpGetLength2()' - Get the amount of data remaining from the
1271 * content-length or transfer-encoding fields.
1272 *
1273 * This function returns the complete content length, even for
1274 * content larger than 2^31 - 1.
1275 *
f3c17241 1276 * @since CUPS 1.2/OS X 10.5@
ecdc0628 1277 */
1278
1279off_t /* O - Content length */
568fa3fa 1280httpGetLength2(http_t *http) /* I - Connection to server */
ecdc0628 1281{
a469f8a5
MS
1282 off_t remaining; /* Remaining length */
1283
1284
f11a948a 1285 DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
cb7f98ee 1286 http_state_string(http->state)));
ecdc0628 1287
1288 if (!http)
1289 return (-1);
1290
88f9aafc 1291 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
ecdc0628 1292 {
e07d4801 1293 DEBUG_puts("4httpGetLength2: chunked request!");
a469f8a5 1294 remaining = 0;
ecdc0628 1295 }
1296 else
1297 {
ecdc0628 1298 /*
1299 * The following is a hack for HTTP servers that don't send a
a469f8a5 1300 * Content-Length or Transfer-Encoding field...
ecdc0628 1301 *
a469f8a5 1302 * If there is no Content-Length then the connection must close
ecdc0628 1303 * after the transfer is complete...
1304 */
1305
b86bc4cf 1306 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
1307 {
1308 /*
a469f8a5
MS
1309 * Default content length is 0 for errors and certain types of operations,
1310 * and 2^31-1 for other successful requests...
b86bc4cf 1311 */
1312
cb7f98ee 1313 if (http->status >= HTTP_STATUS_MULTIPLE_CHOICES ||
a469f8a5
MS
1314 http->state == HTTP_STATE_OPTIONS ||
1315 (http->state == HTTP_STATE_GET && http->mode == _HTTP_MODE_SERVER) ||
1316 http->state == HTTP_STATE_HEAD ||
1317 (http->state == HTTP_STATE_PUT && http->mode == _HTTP_MODE_CLIENT) ||
1318 http->state == HTTP_STATE_DELETE ||
1319 http->state == HTTP_STATE_TRACE ||
1320 http->state == HTTP_STATE_CONNECT)
1321 remaining = 0;
b86bc4cf 1322 else
a469f8a5 1323 remaining = 2147483647;
b86bc4cf 1324 }
a469f8a5
MS
1325 else if ((remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
1326 NULL, 10)) < 0)
1327 remaining = -1;
ecdc0628 1328
e07d4801 1329 DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
a469f8a5 1330 CUPS_LLCAST remaining));
ecdc0628 1331 }
1332
a469f8a5 1333 return (remaining);
ecdc0628 1334}
1335
1336
ef416fc2 1337/*
1338 * 'httpGets()' - Get a line of text from a HTTP connection.
1339 */
1340
1341char * /* O - Line or NULL */
1342httpGets(char *line, /* I - Line to read into */
1343 int length, /* I - Max length of buffer */
568fa3fa 1344 http_t *http) /* I - Connection to server */
ef416fc2 1345{
1346 char *lineptr, /* Pointer into line */
1347 *lineend, /* End of line */
1348 *bufptr, /* Pointer into input buffer */
1349 *bufend; /* Pointer to end of buffer */
1350 int bytes, /* Number of bytes read */
1351 eol; /* End-of-line? */
1352
1353
e07d4801 1354 DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
ef416fc2 1355
0fa6c7fa 1356 if (!http || !line || length <= 1)
ef416fc2 1357 return (NULL);
1358
1359 /*
1360 * Read a line from the buffer...
1361 */
f11a948a
MS
1362
1363 http->error = 0;
1364 lineptr = line;
1365 lineend = line + length - 1;
1366 eol = 0;
ef416fc2 1367
1368 while (lineptr < lineend)
1369 {
1370 /*
1371 * Pre-load the buffer as needed...
1372 */
1373
1374#ifdef WIN32
1375 WSASetLastError(0);
1376#else
1377 errno = 0;
1378#endif /* WIN32 */
1379
1380 while (http->used == 0)
1381 {
1382 /*
1383 * No newline; see if there is more data to be read...
1384 */
1385
85dda01c 1386 while (!_httpWait(http, http->wait_value, 1))
89d46774 1387 {
f228370c
MS
1388 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1389 continue;
1390
e07d4801 1391 DEBUG_puts("3httpGets: Timed out!");
b86bc4cf 1392#ifdef WIN32
1393 http->error = WSAETIMEDOUT;
1394#else
89d46774 1395 http->error = ETIMEDOUT;
b86bc4cf 1396#endif /* WIN32 */
ef416fc2 1397 return (NULL);
89d46774 1398 }
ef416fc2 1399
0fa6c7fa
MS
1400 bytes = http_read(http, http->buffer + http->used,
1401 HTTP_MAX_BUFFER - http->used);
ef416fc2 1402
0fa6c7fa 1403 DEBUG_printf(("4httpGets: read %d bytes.", bytes));
12f89d24 1404
ef416fc2 1405 if (bytes < 0)
1406 {
1407 /*
1408 * Nope, can't get a line this time...
1409 */
1410
1411#ifdef WIN32
cc754834
MS
1412 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
1413
10d09e33 1414 if (WSAGetLastError() == WSAEINTR)
cc754834 1415 continue;
10d09e33
MS
1416 else if (WSAGetLastError() == WSAEWOULDBLOCK)
1417 {
1418 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1419 continue;
1420
1421 http->error = WSAGetLastError();
1422 }
cc754834 1423 else if (WSAGetLastError() != http->error)
ef416fc2 1424 {
1425 http->error = WSAGetLastError();
1426 continue;
1427 }
1428
ef416fc2 1429#else
e07d4801 1430 DEBUG_printf(("3httpGets: recv() error %d!", errno));
ef416fc2 1431
10d09e33 1432 if (errno == EINTR)
ef416fc2 1433 continue;
10d09e33
MS
1434 else if (errno == EWOULDBLOCK || errno == EAGAIN)
1435 {
1436 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1437 continue;
1438 else if (!http->timeout_cb && errno == EAGAIN)
1439 continue;
1440
1441 http->error = errno;
1442 }
ef416fc2 1443 else if (errno != http->error)
1444 {
1445 http->error = errno;
1446 continue;
1447 }
1448#endif /* WIN32 */
1449
1450 return (NULL);
1451 }
1452 else if (bytes == 0)
1453 {
1454 http->error = EPIPE;
1455
1456 return (NULL);
1457 }
1458
1459 /*
1460 * Yup, update the amount used...
1461 */
1462
1463 http->used += bytes;
1464 }
1465
1466 /*
1467 * Now copy as much of the current line as possible...
1468 */
1469
1470 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1471 lineptr < lineend && bufptr < bufend;)
1472 {
1473 if (*bufptr == 0x0a)
1474 {
1475 eol = 1;
1476 bufptr ++;
1477 break;
1478 }
1479 else if (*bufptr == 0x0d)
1480 bufptr ++;
1481 else
1482 *lineptr++ = *bufptr++;
1483 }
1484
b86bc4cf 1485 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1486 if (http->used > 0)
1487 memmove(http->buffer, bufptr, http->used);
1488
1489 if (eol)
1490 {
1491 /*
1492 * End of line...
1493 */
1494
1495 http->activity = time(NULL);
1496
1497 *lineptr = '\0';
ef55b745 1498
e07d4801 1499 DEBUG_printf(("3httpGets: Returning \"%s\"", line));
ef416fc2 1500
1501 return (line);
1502 }
1503 }
1504
e07d4801 1505 DEBUG_puts("3httpGets: No new line available!");
ef416fc2 1506
1507 return (NULL);
1508}
1509
1510
a2326b5b
MS
1511/*
1512 * 'httpGetState()' - Get the current state of the HTTP request.
1513 */
1514
1515http_state_t /* O - HTTP state */
1516httpGetState(http_t *http) /* I - Connection to server */
1517{
a469f8a5 1518 return (http ? http->state : HTTP_STATE_ERROR);
a2326b5b
MS
1519}
1520
1521
1522/*
1523 * 'httpGetStatus()' - Get the status of the last HTTP request.
1524 *
f3c17241 1525 * @since CUPS 1.2/OS X 10.5@
a2326b5b
MS
1526 */
1527
1528http_status_t /* O - HTTP status */
1529httpGetStatus(http_t *http) /* I - Connection to server */
1530{
cb7f98ee 1531 return (http ? http->status : HTTP_STATUS_ERROR);
a2326b5b
MS
1532}
1533
1534
1535/*
1536 * 'httpGetSubField()' - Get a sub-field value.
1537 *
1538 * @deprecated@
1539 */
1540
1541char * /* O - Value or NULL */
1542httpGetSubField(http_t *http, /* I - Connection to server */
1543 http_field_t field, /* I - Field index */
1544 const char *name, /* I - Name of sub-field */
1545 char *value) /* O - Value string */
1546{
1547 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
1548}
1549
1550
1551/*
1552 * 'httpGetSubField2()' - Get a sub-field value.
1553 *
f3c17241 1554 * @since CUPS 1.2/OS X 10.5@
a2326b5b
MS
1555 */
1556
1557char * /* O - Value or NULL */
1558httpGetSubField2(http_t *http, /* I - Connection to server */
1559 http_field_t field, /* I - Field index */
1560 const char *name, /* I - Name of sub-field */
1561 char *value, /* O - Value string */
1562 int valuelen) /* I - Size of value buffer */
1563{
1564 const char *fptr; /* Pointer into field */
1565 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
1566 *ptr, /* Pointer into string buffer */
1567 *end; /* End of value buffer */
1568
1569 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
1570 "valuelen=%d)", http, field, name, value, valuelen));
1571
1572 if (!http || !name || !value || valuelen < 2 ||
1573 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
1574 return (NULL);
1575
1576 end = value + valuelen - 1;
1577
1578 for (fptr = http->fields[field]; *fptr;)
1579 {
1580 /*
1581 * Skip leading whitespace...
1582 */
1583
1584 while (_cups_isspace(*fptr))
1585 fptr ++;
1586
1587 if (*fptr == ',')
1588 {
1589 fptr ++;
1590 continue;
1591 }
1592
1593 /*
1594 * Get the sub-field name...
1595 */
1596
1597 for (ptr = temp;
1598 *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
1599 ptr < (temp + sizeof(temp) - 1);
1600 *ptr++ = *fptr++);
1601
1602 *ptr = '\0';
1603
1604 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
1605
1606 /*
1607 * Skip trailing chars up to the '='...
1608 */
1609
1610 while (_cups_isspace(*fptr))
1611 fptr ++;
1612
1613 if (!*fptr)
1614 break;
1615
1616 if (*fptr != '=')
1617 continue;
1618
1619 /*
1620 * Skip = and leading whitespace...
1621 */
1622
1623 fptr ++;
1624
1625 while (_cups_isspace(*fptr))
1626 fptr ++;
1627
1628 if (*fptr == '\"')
1629 {
1630 /*
1631 * Read quoted string...
1632 */
1633
1634 for (ptr = value, fptr ++;
1635 *fptr && *fptr != '\"' && ptr < end;
1636 *ptr++ = *fptr++);
1637
1638 *ptr = '\0';
1639
1640 while (*fptr && *fptr != '\"')
1641 fptr ++;
1642
1643 if (*fptr)
1644 fptr ++;
1645 }
1646 else
1647 {
1648 /*
1649 * Read unquoted string...
1650 */
1651
1652 for (ptr = value;
1653 *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
1654 *ptr++ = *fptr++);
1655
1656 *ptr = '\0';
1657
1658 while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
1659 fptr ++;
1660 }
1661
1662 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
1663
1664 /*
1665 * See if this is the one...
1666 */
1667
1668 if (!strcmp(name, temp))
1669 {
1670 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
1671 return (value);
1672 }
1673 }
1674
1675 value[0] = '\0';
1676
1677 DEBUG_puts("3httpGetSubField2: Returning NULL");
1678
1679 return (NULL);
1680}
1681
1682
1683/*
1684 * 'httpGetVersion()' - Get the HTTP version at the other end.
1685 */
1686
1687http_version_t /* O - Version number */
1688httpGetVersion(http_t *http) /* I - Connection to server */
1689{
a469f8a5 1690 return (http ? http->version : HTTP_VERSION_1_0);
a2326b5b
MS
1691}
1692
1693
ef416fc2 1694/*
1695 * 'httpHead()' - Send a HEAD request to the server.
1696 */
1697
1698int /* O - Status of call (0 = success) */
568fa3fa 1699httpHead(http_t *http, /* I - Connection to server */
ef416fc2 1700 const char *uri) /* I - URI for head */
1701{
e07d4801 1702 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
cb7f98ee 1703 return (http_send(http, HTTP_STATE_HEAD, uri));
ef416fc2 1704}
1705
1706
1707/*
1708 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1709 * default HTTP proxy (if any).
1710 */
1711
1712void
1713httpInitialize(void)
1714{
6d2f911b
MS
1715 static int initialized = 0; /* Have we been called before? */
1716#ifdef WIN32
1717 WSADATA winsockdata; /* WinSock data */
1718#endif /* WIN32 */
ef416fc2 1719#ifdef HAVE_LIBSSL
6d2f911b
MS
1720 int i; /* Looping var */
1721 unsigned char data[1024]; /* Seed data */
ef416fc2 1722#endif /* HAVE_LIBSSL */
1723
ef416fc2 1724
6d2f911b
MS
1725 _cupsGlobalLock();
1726 if (initialized)
1727 {
1728 _cupsGlobalUnlock();
1729 return;
1730 }
1731
1732#ifdef WIN32
c7017ecc 1733 WSAStartup(MAKEWORD(2,2), &winsockdata);
ef416fc2 1734
fa73b229 1735#elif !defined(SO_NOSIGPIPE)
ef416fc2 1736 /*
1737 * Ignore SIGPIPE signals...
1738 */
1739
fa73b229 1740# ifdef HAVE_SIGSET
1741 sigset(SIGPIPE, SIG_IGN);
6d2f911b 1742
fa73b229 1743# elif defined(HAVE_SIGACTION)
1744 struct sigaction action; /* POSIX sigaction data */
1745
1746
ef416fc2 1747 memset(&action, 0, sizeof(action));
1748 action.sa_handler = SIG_IGN;
1749 sigaction(SIGPIPE, &action, NULL);
6d2f911b 1750
fa73b229 1751# else
ef416fc2 1752 signal(SIGPIPE, SIG_IGN);
fa73b229 1753# endif /* !SO_NOSIGPIPE */
ef416fc2 1754#endif /* WIN32 */
1755
1756#ifdef HAVE_GNUTLS
6d2f911b
MS
1757 /*
1758 * Initialize GNU TLS...
1759 */
1760
ef416fc2 1761 gnutls_global_init();
ef416fc2 1762
6d2f911b
MS
1763#elif defined(HAVE_LIBSSL)
1764 /*
1765 * Initialize OpenSSL...
1766 */
1767
ef416fc2 1768 SSL_load_error_strings();
1769 SSL_library_init();
1770
1771 /*
1772 * Using the current time is a dubious random seed, but on some systems
1773 * it is the best we can do (on others, this seed isn't even used...)
1774 */
1775
6d2f911b 1776 CUPS_SRAND(time(NULL));
ef416fc2 1777
1778 for (i = 0; i < sizeof(data); i ++)
6d2f911b 1779 data[i] = CUPS_RAND();
ef416fc2 1780
dfd5680b 1781 RAND_seed(data, sizeof(data));
6d2f911b
MS
1782#endif /* HAVE_GNUTLS */
1783
1784 initialized = 1;
1785 _cupsGlobalUnlock();
ef416fc2 1786}
1787
1788
1789/*
1790 * 'httpOptions()' - Send an OPTIONS request to the server.
1791 */
1792
1793int /* O - Status of call (0 = success) */
568fa3fa 1794httpOptions(http_t *http, /* I - Connection to server */
ef416fc2 1795 const char *uri) /* I - URI for options */
1796{
cb7f98ee 1797 return (http_send(http, HTTP_STATE_OPTIONS, uri));
ef416fc2 1798}
1799
1800
6d2f911b 1801/*
a469f8a5 1802 * 'httpPeek()' - Peek at data from a HTTP connection.
6d2f911b
MS
1803 *
1804 * This function copies available data from the given HTTP connection, reading
1805 * a buffer as needed. The data is still available for reading using
1806 * @link httpRead@ or @link httpRead2@.
1807 *
1808 * For non-blocking connections the usual timeouts apply.
a469f8a5 1809 *
9c0e8e5d 1810 * @since CUPS 1.7/OS X 10.9@
6d2f911b
MS
1811 */
1812
1813ssize_t /* O - Number of bytes copied */
a469f8a5 1814httpPeek(http_t *http, /* I - Connection to server */
0fa6c7fa
MS
1815 char *buffer, /* I - Buffer for data */
1816 size_t length) /* I - Maximum number of bytes */
6d2f911b
MS
1817{
1818 ssize_t bytes; /* Bytes read */
1819 char len[32]; /* Length string */
1820
1821
a469f8a5 1822 DEBUG_printf(("httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
6d2f911b
MS
1823 http, buffer, CUPS_LLCAST length));
1824
1825 if (http == NULL || buffer == NULL)
1826 return (-1);
1827
1828 http->activity = time(NULL);
1829 http->error = 0;
1830
1831 if (length <= 0)
1832 return (0);
1833
a469f8a5 1834 if (http->data_encoding == HTTP_ENCODING_CHUNKED &&
6d2f911b
MS
1835 http->data_remaining <= 0)
1836 {
a469f8a5 1837 DEBUG_puts("2httpPeek: Getting chunk length...");
6d2f911b
MS
1838
1839 if (httpGets(len, sizeof(len), http) == NULL)
1840 {
a469f8a5 1841 DEBUG_puts("1httpPeek: Could not get length!");
6d2f911b
MS
1842 return (0);
1843 }
1844
db8b865d
MS
1845 if (!len[0])
1846 {
1847 DEBUG_puts("1httpPeek: Blank chunk length, trying again...");
1848 if (!httpGets(len, sizeof(len), http))
1849 {
1850 DEBUG_puts("1httpPeek: Could not get chunk length.");
1851 return (0);
1852 }
1853 }
1854
6d2f911b 1855 http->data_remaining = strtoll(len, NULL, 16);
db8b865d 1856
6d2f911b
MS
1857 if (http->data_remaining < 0)
1858 {
a469f8a5 1859 DEBUG_puts("1httpPeek: Negative chunk length!");
6d2f911b
MS
1860 return (0);
1861 }
1862 }
1863
a469f8a5 1864 DEBUG_printf(("2httpPeek: data_remaining=" CUPS_LLFMT,
6d2f911b
MS
1865 CUPS_LLCAST http->data_remaining));
1866
0fa6c7fa 1867 if (http->data_remaining <= 0 && http->data_encoding != HTTP_ENCODING_FIELDS)
6d2f911b
MS
1868 {
1869 /*
1870 * A zero-length chunk ends a transfer; unless we are reading POST
1871 * data, go idle...
1872 */
1873
c41769ff
MS
1874#ifdef HAVE_LIBZ
1875 if (http->coding)
1876 http_content_coding_finish(http);
1877#endif /* HAVE_LIBZ */
1878
0fa6c7fa
MS
1879 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
1880 httpGets(len, sizeof(len), http);
1881
a469f8a5 1882 if (http->state == HTTP_STATE_POST_RECV)
6d2f911b
MS
1883 http->state ++;
1884 else
cb7f98ee 1885 http->state = HTTP_STATE_STATUS;
a469f8a5
MS
1886
1887 DEBUG_printf(("1httpPeek: 0-length chunk, set state to %s.",
cb7f98ee 1888 http_state_string(http->state)));
6d2f911b
MS
1889
1890 /*
1891 * Prevent future reads for this request...
1892 */
1893
a469f8a5 1894 http->data_encoding = HTTP_ENCODING_FIELDS;
6d2f911b
MS
1895
1896 return (0);
1897 }
0fa6c7fa 1898 else if (length > (size_t)http->data_remaining)
6d2f911b
MS
1899 length = (size_t)http->data_remaining;
1900
0fa6c7fa
MS
1901#ifdef HAVE_LIBZ
1902 if (http->used == 0 &&
1903 (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0))
1904#else
6d2f911b 1905 if (http->used == 0)
0fa6c7fa 1906#endif /* HAVE_LIBZ */
6d2f911b
MS
1907 {
1908 /*
1909 * Buffer small reads for better performance...
1910 */
1911
3e7fe0ca
MS
1912 ssize_t buflen; /* Length of read for buffer */
1913
f228370c
MS
1914 if (!http->blocking)
1915 {
85dda01c 1916 while (!httpWait(http, http->wait_value))
f228370c
MS
1917 {
1918 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1919 continue;
1920
1921 return (0);
1922 }
1923 }
6d2f911b
MS
1924
1925 if (http->data_remaining > sizeof(http->buffer))
3e7fe0ca 1926 buflen = sizeof(http->buffer);
6d2f911b 1927 else
3e7fe0ca
MS
1928 buflen = http->data_remaining;
1929
a469f8a5 1930 DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen));
db8b865d 1931 bytes = http_read(http, http->buffer, buflen);
3e7fe0ca 1932
a469f8a5 1933 DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.",
3e7fe0ca 1934 CUPS_LLCAST bytes));
db8b865d
MS
1935 if (bytes > 0)
1936 {
3e7fe0ca 1937#ifdef DEBUG
db8b865d 1938 http_debug_hex("httpPeek", http->buffer, (int)bytes);
3e7fe0ca
MS
1939#endif /* DEBUG */
1940
db8b865d
MS
1941 http->used = bytes;
1942 }
6d2f911b
MS
1943 }
1944
c1420c87
MS
1945#ifdef HAVE_LIBZ
1946 if (http->coding)
1947 {
db8b865d 1948# ifdef HAVE_INFLATECOPY
c1420c87 1949 int zerr; /* Decompressor error */
c1420c87
MS
1950 z_stream stream; /* Copy of decompressor stream */
1951
0fa6c7fa
MS
1952 if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER)
1953 {
1954 size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
1955 /* Number of bytes to copy */
1956
1957 if (http->stream.avail_in > 0 &&
1958 http->stream.next_in > http->dbuffer)
1959 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
1960
1961 http->stream.next_in = http->dbuffer;
1962
1963 if (buflen > http->data_remaining)
1964 buflen = http->data_remaining;
1965
1966 if (buflen > http->used)
1967 buflen = http->used;
1968
1969 DEBUG_printf(("1httpPeek: Copying %d more bytes of data into "
1970 "decompression buffer.", (int)buflen));
1971
1972 memcpy(http->dbuffer + http->stream.avail_in, http->buffer, buflen);
1973 http->stream.avail_in += buflen;
1974 http->used -= buflen;
1975 http->data_remaining -= buflen;
1976
1977 if (http->used > 0)
1978 memmove(http->buffer, http->buffer + buflen, http->used);
1979 }
c1420c87
MS
1980
1981 DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length,
0fa6c7fa 1982 (int)http->stream.avail_in));
c1420c87
MS
1983
1984 if (inflateCopy(&stream, &(http->stream)) != Z_OK)
1985 {
1986 DEBUG_puts("2httpPeek: Unable to copy decompressor stream.");
1987 http->error = ENOMEM;
1988 return (-1);
1989 }
1990
c1420c87
MS
1991 stream.next_out = (Bytef *)buffer;
1992 stream.avail_out = length;
1993
1994 zerr = inflate(&stream, Z_SYNC_FLUSH);
1995 inflateEnd(&stream);
1996
1997 if (zerr < Z_OK)
1998 {
1999 DEBUG_printf(("2httpPeek: zerr=%d", zerr));
0fa6c7fa
MS
2000#ifdef DEBUG
2001 http_debug_hex("2httpPeek", (char *)http->dbuffer,
2002 http->stream.avail_in);
2003#endif /* DEBUG */
2004
c1420c87
MS
2005 http->error = EIO;
2006 return (-1);
2007 }
2008
2009 bytes = length - http->stream.avail_out;
db8b865d
MS
2010
2011# else
2012 DEBUG_puts("2httpPeek: No inflateCopy on this platform, httpPeek does not "
2013 "work with compressed streams.");
2014 return (-1);
2015# endif /* HAVE_INFLATECOPY */
c1420c87
MS
2016 }
2017 else
2018#endif /* HAVE_LIBZ */
6d2f911b
MS
2019 if (http->used > 0)
2020 {
2021 if (length > (size_t)http->used)
2022 length = (size_t)http->used;
2023
2024 bytes = (ssize_t)length;
2025
a469f8a5 2026 DEBUG_printf(("2httpPeek: grabbing %d bytes from input buffer...",
6d2f911b
MS
2027 (int)bytes));
2028
2029 memcpy(buffer, http->buffer, length);
2030 }
2031 else
2032 bytes = 0;
2033
2034 if (bytes < 0)
2035 {
2036#ifdef WIN32
cc754834
MS
2037 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)
2038 bytes = 0;
2039 else
2040 http->error = WSAGetLastError();
6d2f911b
MS
2041#else
2042 if (errno == EINTR || errno == EAGAIN)
2043 bytes = 0;
2044 else
2045 http->error = errno;
2046#endif /* WIN32 */
2047 }
2048 else if (bytes == 0)
2049 {
2050 http->error = EPIPE;
2051 return (0);
2052 }
2053
6d2f911b
MS
2054 return (bytes);
2055}
2056
c1420c87
MS
2057/* For OS X 10.8 and earlier */
2058ssize_t _httpPeek(http_t *http, char *buffer, size_t length)
2059{ return (httpPeek(http, buffer, length)); }
2060
6d2f911b 2061
ef416fc2 2062/*
2063 * 'httpPost()' - Send a POST request to the server.
2064 */
2065
2066int /* O - Status of call (0 = success) */
568fa3fa 2067httpPost(http_t *http, /* I - Connection to server */
ef416fc2 2068 const char *uri) /* I - URI for post */
2069{
cb7f98ee 2070 return (http_send(http, HTTP_STATE_POST, uri));
ef416fc2 2071}
2072
2073
2074/*
2075 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 2076 *
2077 * @private@
ef416fc2 2078 */
2079
2080int /* O - Number of bytes written */
568fa3fa 2081httpPrintf(http_t *http, /* I - Connection to server */
ef416fc2 2082 const char *format, /* I - printf-style format string */
2083 ...) /* I - Additional args as needed */
2084{
2085 int bytes; /* Number of bytes to write */
2086 char buf[16384]; /* Buffer for formatted string */
2087 va_list ap; /* Variable argument pointer */
2088
2089
e07d4801 2090 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
ef416fc2 2091
2092 va_start(ap, format);
2093 bytes = vsnprintf(buf, sizeof(buf), format, ap);
2094 va_end(ap);
2095
a469f8a5 2096 DEBUG_printf(("3httpPrintf: (%d bytes) %s", bytes, buf));
ef416fc2 2097
a469f8a5 2098 if (http->data_encoding == HTTP_ENCODING_FIELDS)
d09495fa 2099 return (httpWrite2(http, buf, bytes));
2100 else
ef416fc2 2101 {
d09495fa 2102 if (http->wused)
2103 {
e07d4801 2104 DEBUG_puts("4httpPrintf: flushing existing data...");
ef416fc2 2105
d09495fa 2106 if (httpFlushWrite(http) < 0)
2107 return (-1);
2108 }
ef416fc2 2109
d09495fa 2110 return (http_write(http, buf, bytes));
2111 }
ef416fc2 2112}
2113
2114
2115/*
2116 * 'httpPut()' - Send a PUT request to the server.
2117 */
2118
2119int /* O - Status of call (0 = success) */
568fa3fa 2120httpPut(http_t *http, /* I - Connection to server */
ef416fc2 2121 const char *uri) /* I - URI to put */
2122{
e07d4801 2123 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
cb7f98ee 2124 return (http_send(http, HTTP_STATE_PUT, uri));
ef416fc2 2125}
2126
2127
2128/*
2129 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 2130 *
2131 * This function is deprecated. Use the httpRead2() function which can
2132 * read more than 2GB of data.
2133 *
2134 * @deprecated@
ef416fc2 2135 */
2136
2137int /* O - Number of bytes read */
568fa3fa 2138httpRead(http_t *http, /* I - Connection to server */
ef416fc2 2139 char *buffer, /* I - Buffer for data */
2140 int length) /* I - Maximum number of bytes */
2141{
a4d04587 2142 return ((int)httpRead2(http, buffer, length));
2143}
2144
2145
2146/*
2147 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 2148 *
f3c17241 2149 * @since CUPS 1.2/OS X 10.5@
a4d04587 2150 */
2151
2152ssize_t /* O - Number of bytes read */
568fa3fa 2153httpRead2(http_t *http, /* I - Connection to server */
a4d04587 2154 char *buffer, /* I - Buffer for data */
2155 size_t length) /* I - Maximum number of bytes */
2156{
2157 ssize_t bytes; /* Bytes read */
ef416fc2 2158
2159
db8b865d 2160#ifdef HAVE_LIBZ
a469f8a5 2161 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
0fa6c7fa 2162 ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT,
db8b865d
MS
2163 http, buffer, CUPS_LLCAST length,
2164 http->coding,
0fa6c7fa 2165 http->data_encoding, CUPS_LLCAST http->data_remaining));
db8b865d
MS
2166#else
2167 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
2168 ") data_encoding=%d data_remaining=" CUPS_LLFMT,
2169 http, buffer, CUPS_LLCAST length,
2170 http->data_encoding, CUPS_LLCAST http->data_remaining));
2171#endif /* HAVE_LIBZ */
ef416fc2 2172
2173 if (http == NULL || buffer == NULL)
2174 return (-1);
2175
2176 http->activity = time(NULL);
f11a948a 2177 http->error = 0;
ef416fc2 2178
2179 if (length <= 0)
2180 return (0);
2181
a469f8a5 2182#ifdef HAVE_LIBZ
0fa6c7fa 2183 if (http->coding)
ef416fc2 2184 {
0fa6c7fa 2185 do
f228370c 2186 {
0fa6c7fa 2187 if (http->stream.avail_in > 0)
f228370c 2188 {
0fa6c7fa 2189 int zerr; /* Decompressor error */
f228370c 2190
0fa6c7fa
MS
2191 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d",
2192 (int)http->stream.avail_in, (int)length));
ef416fc2 2193
0fa6c7fa
MS
2194 http->stream.next_out = (Bytef *)buffer;
2195 http->stream.avail_out = length;
83e08001 2196
0fa6c7fa 2197 if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK)
83e08001 2198 {
0fa6c7fa 2199 DEBUG_printf(("2httpRead2: zerr=%d", zerr));
12f89d24 2200#ifdef DEBUG
0fa6c7fa
MS
2201 http_debug_hex("2httpRead2", (char *)http->dbuffer,
2202 http->stream.avail_in);
12f89d24 2203#endif /* DEBUG */
83e08001 2204
0fa6c7fa
MS
2205 http->error = EIO;
2206 return (-1);
2207 }
a469f8a5 2208
0fa6c7fa 2209 bytes = length - http->stream.avail_out;
a469f8a5 2210
0fa6c7fa
MS
2211 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d",
2212 http->stream.avail_in, http->stream.avail_out,
2213 (int)bytes));
2214 }
2215 else
2216 bytes = 0;
a469f8a5 2217
0fa6c7fa
MS
2218 if (bytes == 0)
2219 {
2220 ssize_t buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
2221 /* Additional bytes for buffer */
a469f8a5 2222
0fa6c7fa
MS
2223 if (buflen > 0)
2224 {
2225 if (http->stream.avail_in > 0 &&
2226 http->stream.next_in > http->dbuffer)
2227 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
2228
2229 http->stream.next_in = http->dbuffer;
2230
2231 DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into "
2232 "decompression buffer.", (int)buflen));
2233
2234 if (http->data_remaining > 0)
2235 {
2236 if (buflen > http->data_remaining)
2237 buflen = http->data_remaining;
2238
2239 bytes = http_read_buffered(http,
2240 (char *)http->dbuffer +
2241 http->stream.avail_in, buflen);
2242 }
2243 else if (http->data_encoding == HTTP_ENCODING_CHUNKED)
2244 bytes = http_read_chunk(http,
2245 (char *)http->dbuffer +
2246 http->stream.avail_in, buflen);
2247 else
2248 bytes = 0;
2249
2250 if (bytes < 0)
2251 return (bytes);
2252 else if (bytes == 0)
2253 break;
2254
db8b865d
MS
2255 DEBUG_printf(("1httpRead2: Adding " CUPS_LLFMT " bytes to "
2256 "decompression buffer.", CUPS_LLCAST bytes));
2257
0fa6c7fa
MS
2258 http->data_remaining -= bytes;
2259 http->stream.avail_in += bytes;
db8b865d 2260
cb7f98ee
MS
2261 if (http->data_remaining <= 0 &&
2262 http->data_encoding == HTTP_ENCODING_CHUNKED)
2263 {
2264 /*
2265 * Read the trailing blank line now...
2266 */
2267
2268 char len[32]; /* Length string */
2269
2270 httpGets(len, sizeof(len), http);
2271 }
2272
db8b865d 2273 bytes = 0;
0fa6c7fa
MS
2274 }
2275 else
2276 return (0);
2277 }
a469f8a5 2278 }
0fa6c7fa 2279 while (bytes == 0);
a469f8a5
MS
2280 }
2281 else
2282#endif /* HAVE_LIBZ */
0fa6c7fa 2283 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
ef416fc2 2284 {
0fa6c7fa 2285 if ((bytes = http_read_chunk(http, buffer, length)) > 0)
cb7f98ee 2286 {
0fa6c7fa 2287 http->data_remaining -= bytes;
cb7f98ee
MS
2288
2289 if (http->data_remaining <= 0)
2290 {
2291 /*
2292 * Read the trailing blank line now...
2293 */
2294
2295 char len[32]; /* Length string */
2296
2297 httpGets(len, sizeof(len), http);
2298 }
2299 }
ef416fc2 2300 }
0fa6c7fa 2301 else if (http->data_remaining <= 0)
ef416fc2 2302 {
0fa6c7fa
MS
2303 /*
2304 * No more data to read...
2305 */
ef416fc2 2306
0fa6c7fa 2307 return (0);
ef416fc2 2308 }
ef416fc2 2309 else
2310 {
0fa6c7fa
MS
2311 DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.",
2312 (int)length));
ef416fc2 2313
db8b865d
MS
2314 if (length > (size_t)http->data_remaining)
2315 length = (size_t)http->data_remaining;
ef416fc2 2316
0fa6c7fa 2317 if ((bytes = http_read_buffered(http, buffer, length)) > 0)
cb7f98ee 2318 {
0fa6c7fa 2319 http->data_remaining -= bytes;
cb7f98ee
MS
2320
2321 if (http->data_remaining <= 0 &&
2322 http->data_encoding == HTTP_ENCODING_CHUNKED)
2323 {
2324 /*
2325 * Read the trailing blank line now...
2326 */
2327
2328 char len[32]; /* Length string */
2329
2330 httpGets(len, sizeof(len), http);
2331 }
2332 }
ef416fc2 2333 }
2334
0fa6c7fa
MS
2335 if (
2336#ifdef HAVE_LIBZ
2337 (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0) &&
2338#endif /* HAVE_LIBZ */
2339 ((http->data_remaining <= 0 &&
2340 http->data_encoding == HTTP_ENCODING_LENGTH) ||
2341 (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0)))
ef416fc2 2342 {
a469f8a5 2343#ifdef HAVE_LIBZ
0fa6c7fa
MS
2344 if (http->coding)
2345 http_content_coding_finish(http);
a469f8a5
MS
2346#endif /* HAVE_LIBZ */
2347
0fa6c7fa
MS
2348 if (http->state == HTTP_STATE_POST_RECV)
2349 http->state ++;
6961465f
MS
2350 else if (http->state == HTTP_STATE_GET_SEND ||
2351 http->state == HTTP_STATE_POST_SEND)
2352 http->state = HTTP_STATE_WAITING;
0fa6c7fa 2353 else
cb7f98ee 2354 http->state = HTTP_STATE_STATUS;
a469f8a5 2355
0fa6c7fa 2356 DEBUG_printf(("1httpRead2: End of content, set state to %s.",
cb7f98ee 2357 http_state_string(http->state)));
ef416fc2 2358 }
2359
ef416fc2 2360 return (bytes);
2361}
2362
2363
2364#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2365/*
411affcf 2366 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 2367 */
2368
2369OSStatus /* O - -1 on error, 0 on success */
2370_httpReadCDSA(
2371 SSLConnectionRef connection, /* I - SSL/TLS connection */
2372 void *data, /* I - Data buffer */
2373 size_t *dataLength) /* IO - Number of bytes */
2374{
411affcf 2375 OSStatus result; /* Return value */
2376 ssize_t bytes; /* Number of bytes read */
2377 http_t *http; /* HTTP connection */
2378
2379
2380 http = (http_t *)connection;
e53920b9 2381
411affcf 2382 if (!http->blocking)
2383 {
2384 /*
2385 * Make sure we have data before we read...
2386 */
e53920b9 2387
85dda01c 2388 while (!_httpWait(http, http->wait_value, 0))
411affcf 2389 {
f228370c
MS
2390 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2391 continue;
2392
411affcf 2393 http->error = ETIMEDOUT;
2394 return (-1);
2395 }
2396 }
ef416fc2 2397
b423cd4c 2398 do
411affcf 2399 {
2400 bytes = recv(http->fd, data, *dataLength, 0);
2401 }
e07d4801 2402 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2403
b423cd4c 2404 if (bytes == *dataLength)
411affcf 2405 {
b423cd4c 2406 result = 0;
411affcf 2407 }
b423cd4c 2408 else if (bytes > 0)
2409 {
2410 *dataLength = bytes;
2411 result = errSSLWouldBlock;
2412 }
2413 else
2414 {
2415 *dataLength = 0;
fa73b229 2416
2417 if (bytes == 0)
ed486911 2418 result = errSSLClosedGraceful;
b423cd4c 2419 else if (errno == EAGAIN)
2420 result = errSSLWouldBlock;
b423cd4c 2421 else
ed486911 2422 result = errSSLClosedAbort;
ef416fc2 2423 }
b423cd4c 2424
411affcf 2425 return (result);
ef416fc2 2426}
2427#endif /* HAVE_SSL && HAVE_CDSASSL */
2428
2429
411affcf 2430#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2431/*
2432 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
2433 */
2434
2435ssize_t /* O - Number of bytes read or -1 on error */
2436_httpReadGNUTLS(
568fa3fa 2437 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2438 void *data, /* I - Buffer */
2439 size_t length) /* I - Number of bytes to read */
2440{
2441 http_t *http; /* HTTP connection */
a4845881
MS
2442 ssize_t bytes; /* Bytes read */
2443
411affcf 2444
a4845881 2445 DEBUG_printf(("6_httpReadGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data, (int)length));
411affcf 2446
2447 http = (http_t *)ptr;
2448
2449 if (!http->blocking)
2450 {
2451 /*
2452 * Make sure we have data before we read...
2453 */
2454
85dda01c 2455 while (!_httpWait(http, http->wait_value, 0))
411affcf 2456 {
f228370c
MS
2457 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2458 continue;
2459
411affcf 2460 http->error = ETIMEDOUT;
2461 return (-1);
2462 }
2463 }
2464
a4845881
MS
2465 bytes = recv(http->fd, data, length, 0);
2466 DEBUG_printf(("6_httpReadGNUTLS: bytes=%d", (int)bytes));
2467 return (bytes);
411affcf 2468}
2469#endif /* HAVE_SSL && HAVE_GNUTLS */
2470
2471
ef416fc2 2472/*
a469f8a5
MS
2473 * 'httpReadRequest()' - Read a HTTP request from a connection.
2474 *
9c0e8e5d 2475 * @since CUPS 1.7/OS X 10.9@
ef416fc2 2476 */
2477
a469f8a5
MS
2478http_state_t /* O - New state of connection */
2479httpReadRequest(http_t *http, /* I - HTTP connection */
2480 char *uri, /* I - URI buffer */
2481 size_t urilen) /* I - Size of URI buffer */
dcb445bc 2482{
a469f8a5
MS
2483 char line[4096], /* HTTP request line */
2484 *req_method, /* HTTP request method */
2485 *req_uri, /* HTTP request URI */
2486 *req_version; /* HTTP request version number string */
dcb445bc
MS
2487
2488
a469f8a5
MS
2489 /*
2490 * Range check input...
2491 */
ef416fc2 2492
a469f8a5
MS
2493 DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")",
2494 http, uri, CUPS_LLCAST urilen));
ef416fc2 2495
a469f8a5
MS
2496 if (uri)
2497 *uri = '\0';
ef416fc2 2498
a469f8a5 2499 if (!http || !uri || urilen < 1)
dcb445bc 2500 {
a469f8a5
MS
2501 DEBUG_puts("1httpReadRequest: Bad arguments, returning HTTP_STATE_ERROR.");
2502 return (HTTP_STATE_ERROR);
dcb445bc 2503 }
a469f8a5 2504 else if (http->state != HTTP_STATE_WAITING)
1ff0402e 2505 {
a469f8a5 2506 DEBUG_printf(("1httpReadRequest: Bad state %s, returning HTTP_STATE_ERROR.",
cb7f98ee 2507 http_state_string(http->state)));
a469f8a5 2508 return (HTTP_STATE_ERROR);
1ff0402e 2509 }
ef416fc2 2510
2511 /*
a469f8a5 2512 * Reset state...
ef416fc2 2513 */
2514
a469f8a5 2515 httpClearFields(http);
ef416fc2 2516
a469f8a5
MS
2517 http->activity = time(NULL);
2518 http->data_encoding = HTTP_ENCODING_FIELDS;
2519 http->data_remaining = 0;
2520 http->keep_alive = HTTP_KEEPALIVE_OFF;
2521 http->status = HTTP_STATUS_OK;
2522 http->version = HTTP_VERSION_1_1;
bd7854cb 2523
a29fd7dd 2524 /*
a469f8a5 2525 * Read a line from the socket...
a29fd7dd
MS
2526 */
2527
a469f8a5
MS
2528 if (!httpGets(line, sizeof(line), http))
2529 {
2530 DEBUG_puts("1httpReadRequest: Unable to read, returning HTTP_STATE_ERROR");
2531 return (HTTP_STATE_ERROR);
2532 }
2533
2534 if (!line[0])
2535 {
2536 DEBUG_puts("1httpReadRequest: Blank line, returning HTTP_STATE_WAITING");
2537 return (HTTP_STATE_WAITING);
2538 }
2539
2540 DEBUG_printf(("1httpReadRequest: %s", line));
2541
2542 /*
2543 * Parse it...
2544 */
2545
2546 req_method = line;
2547 req_uri = line;
2548
2549 while (*req_uri && !isspace(*req_uri & 255))
2550 req_uri ++;
2551
2552 if (!*req_uri)
2553 {
2554 DEBUG_puts("1httpReadRequest: No request URI.");
2555 return (HTTP_STATE_ERROR);
2556 }
2557
2558 *req_uri++ = '\0';
2559
2560 while (*req_uri && isspace(*req_uri & 255))
2561 req_uri ++;
2562
2563 req_version = req_uri;
2564
2565 while (*req_version && !isspace(*req_version & 255))
2566 req_version ++;
2567
2568 if (!*req_version)
2569 {
2570 DEBUG_puts("1httpReadRequest: No request protocol version.");
2571 return (HTTP_STATE_ERROR);
2572 }
2573
2574 *req_version++ = '\0';
2575
2576 while (*req_version && isspace(*req_version & 255))
2577 req_version ++;
2578
2579 /*
2580 * Validate...
2581 */
2582
2583 if (!strcmp(req_method, "OPTIONS"))
2584 http->state = HTTP_STATE_OPTIONS;
2585 else if (!strcmp(req_method, "GET"))
2586 http->state = HTTP_STATE_GET;
2587 else if (!strcmp(req_method, "HEAD"))
2588 http->state = HTTP_STATE_HEAD;
2589 else if (!strcmp(req_method, "POST"))
2590 http->state = HTTP_STATE_POST;
2591 else if (!strcmp(req_method, "PUT"))
2592 http->state = HTTP_STATE_PUT;
2593 else if (!strcmp(req_method, "DELETE"))
2594 http->state = HTTP_STATE_DELETE;
2595 else if (!strcmp(req_method, "TRACE"))
2596 http->state = HTTP_STATE_TRACE;
2597 else if (!strcmp(req_method, "CONNECT"))
2598 http->state = HTTP_STATE_CONNECT;
2599 else
2600 {
2601 DEBUG_printf(("1httpReadRequest: Unknown method \"%s\".", req_method));
2602 return (HTTP_STATE_UNKNOWN_METHOD);
2603 }
2604
2605 DEBUG_printf(("1httpReadRequest: Set state to %s.",
cb7f98ee 2606 http_state_string(http->state)));
a469f8a5
MS
2607
2608 if (!strcmp(req_version, "HTTP/1.0"))
2609 {
2610 http->version = HTTP_VERSION_1_0;
2611 http->keep_alive = HTTP_KEEPALIVE_OFF;
2612 }
2613 else if (!strcmp(req_version, "HTTP/1.1"))
2614 {
2615 http->version = HTTP_VERSION_1_1;
2616 http->keep_alive = HTTP_KEEPALIVE_ON;
2617 }
2618 else
2619 {
2620 DEBUG_printf(("1httpReadRequest: Unknown version \"%s\".", req_version));
2621 return (HTTP_STATE_UNKNOWN_VERSION);
2622 }
2623
2624 DEBUG_printf(("1httpReadRequest: URI is \"%s\".", req_uri));
2625 strlcpy(uri, req_uri, urilen);
2626
2627 return (http->state);
2628}
2629
2630
2631/*
2632 * 'httpReconnect()' - Reconnect to a HTTP server.
2633 *
2634 * This function is deprecated. Please use the @link httpReconnect2@ function
2635 * instead.
2636 *
2637 * @deprecated@
2638 */
2639
2640int /* O - 0 on success, non-zero on failure */
2641httpReconnect(http_t *http) /* I - Connection to server */
2642{
2643 DEBUG_printf(("httpReconnect(http=%p)", http));
2644
2645 return (httpReconnect2(http, 30000, NULL));
2646}
2647
2648
2649/*
2650 * 'httpReconnect2()' - Reconnect to a HTTP server with timeout and optional
2651 * cancel.
2652 */
2653
2654int /* O - 0 on success, non-zero on failure */
2655httpReconnect2(http_t *http, /* I - Connection to server */
2656 int msec, /* I - Timeout in milliseconds */
2657 int *cancel) /* I - Pointer to "cancel" variable */
2658{
2659 http_addrlist_t *addr; /* Connected address */
2660#ifdef DEBUG
2661 http_addrlist_t *current; /* Current address */
2662 char temp[256]; /* Temporary address string */
2663#endif /* DEBUG */
2664
2665
2666 DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", http, msec,
2667 cancel));
2668
2669 if (!http)
2670 {
cb7f98ee 2671 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
a469f8a5
MS
2672 return (-1);
2673 }
2674
2675#ifdef HAVE_SSL
2676 if (http->tls)
2677 {
2678 DEBUG_puts("2httpReconnect2: Shutting down SSL/TLS...");
2679 http_shutdown_ssl(http);
2680 }
2681#endif /* HAVE_SSL */
2682
2683 /*
2684 * Close any previously open socket...
2685 */
2686
2687 if (http->fd >= 0)
2688 {
2689 DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd));
2690
2691#ifdef WIN32
2692 closesocket(http->fd);
2693#else
2694 close(http->fd);
2695#endif /* WIN32 */
2696
2697 http->fd = -1;
2698 }
2699
2700 /*
2701 * Reset all state (except fields, which may be reused)...
2702 */
2703
2704 http->state = HTTP_STATE_WAITING;
a469f8a5
MS
2705 http->version = HTTP_VERSION_1_1;
2706 http->keep_alive = HTTP_KEEPALIVE_OFF;
a29fd7dd 2707 memset(&http->_hostaddr, 0, sizeof(http->_hostaddr));
a469f8a5 2708 http->data_encoding = HTTP_ENCODING_FIELDS;
a29fd7dd
MS
2709 http->_data_remaining = 0;
2710 http->used = 0;
a29fd7dd
MS
2711 http->data_remaining = 0;
2712 http->hostaddr = NULL;
2713 http->wused = 0;
2714
ef416fc2 2715 /*
2716 * Connect to the server...
2717 */
2718
1ff0402e
MS
2719#ifdef DEBUG
2720 for (current = http->addrlist; current; current = current->next)
12f89d24 2721 DEBUG_printf(("2httpReconnect2: Address %s:%d",
1ff0402e 2722 httpAddrString(&(current->addr), temp, sizeof(temp)),
a469f8a5 2723 httpAddrPort(&(current->addr))));
1ff0402e
MS
2724#endif /* DEBUG */
2725
dcb445bc
MS
2726 if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec,
2727 cancel)) == NULL)
ef416fc2 2728 {
2729 /*
2730 * Unable to connect...
2731 */
2732
2733#ifdef WIN32
2734 http->error = WSAGetLastError();
2735#else
2736 http->error = errno;
2737#endif /* WIN32 */
cb7f98ee 2738 http->status = HTTP_STATUS_ERROR;
ef416fc2 2739
12f89d24 2740 DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s",
1ff0402e
MS
2741 strerror(http->error)));
2742
ef416fc2 2743 return (-1);
2744 }
2745
12f89d24 2746 DEBUG_printf(("2httpReconnect2: New socket=%d", http->fd));
1ff0402e 2747
85dda01c
MS
2748 if (http->timeout_value > 0)
2749 http_set_timeout(http->fd, http->timeout_value);
10d09e33 2750
ef416fc2 2751 http->hostaddr = &(addr->addr);
2752 http->error = 0;
ef416fc2 2753
2754#ifdef HAVE_SSL
cb7f98ee 2755 if (http->encryption == HTTP_ENCRYPTION_ALWAYS)
ef416fc2 2756 {
2757 /*
2758 * Always do encryption via SSL.
2759 */
2760
2761 if (http_setup_ssl(http) != 0)
2762 {
f7deaa1a 2763# ifdef WIN32
ef416fc2 2764 closesocket(http->fd);
f7deaa1a 2765# else
ef416fc2 2766 close(http->fd);
f7deaa1a 2767# endif /* WIN32 */
ef416fc2 2768
2769 return (-1);
2770 }
2771 }
cb7f98ee 2772 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls_upgrade)
ef416fc2 2773 return (http_upgrade(http));
2774#endif /* HAVE_SSL */
2775
12f89d24 2776 DEBUG_printf(("1httpReconnect2: Connected to %s:%d...",
1ff0402e 2777 httpAddrString(http->hostaddr, temp, sizeof(temp)),
a469f8a5 2778 httpAddrPort(http->hostaddr)));
1ff0402e 2779
ef416fc2 2780 return (0);
2781}
2782
2783
355e94dc
MS
2784/*
2785 * 'httpSetAuthString()' - Set the current authorization string.
2786 *
2787 * This function just stores a copy of the current authorization string in
2788 * the HTTP connection object. You must still call httpSetField() to set
2789 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
2790 * httpHead(), httpOptions(), httpPost, or httpPut().
2791 *
f3c17241 2792 * @since CUPS 1.3/OS X 10.5@
355e94dc
MS
2793 */
2794
2795void
568fa3fa 2796httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
2797 const char *scheme, /* I - Auth scheme (NULL to clear it) */
2798 const char *data) /* I - Auth data (NULL for none) */
2799{
2800 /*
2801 * Range check input...
2802 */
2803
2804 if (!http)
2805 return;
2806
2807 if (http->authstring && http->authstring != http->_authstring)
2808 free(http->authstring);
2809
2810 http->authstring = http->_authstring;
2811
2812 if (scheme)
2813 {
2814 /*
2815 * Set the current authorization string...
2816 */
2817
2818 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 2819 char *temp;
355e94dc
MS
2820
2821 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
2822 {
2823 if ((temp = malloc(len)) == NULL)
2824 len = sizeof(http->_authstring);
2825 else
2826 http->authstring = temp;
2827 }
355e94dc
MS
2828
2829 if (data)
2830 snprintf(http->authstring, len, "%s %s", scheme, data);
2831 else
2832 strlcpy(http->authstring, scheme, len);
2833 }
2834 else
2835 {
2836 /*
2837 * Clear the current authorization string...
2838 */
2839
2840 http->_authstring[0] = '\0';
2841 }
2842}
2843
2844
7cf5915e
MS
2845/*
2846 * 'httpSetCredentials()' - Set the credentials associated with an encrypted
2847 * connection.
2848 *
f3c17241 2849 * @since CUPS 1.5/OS X 10.7@
7cf5915e
MS
2850 */
2851
2852int /* O - Status of call (0 = success) */
2853httpSetCredentials(http_t *http, /* I - Connection to server */
2854 cups_array_t *credentials) /* I - Array of credentials */
2855{
2856 if (!http || cupsArrayCount(credentials) < 1)
2857 return (-1);
2858
2859 _httpFreeCredentials(http->tls_credentials);
2860
85dda01c 2861 http->tls_credentials = _httpCreateCredentials(credentials);
7cf5915e
MS
2862
2863 return (http->tls_credentials ? 0 : -1);
2864}
2865
2866
ef416fc2 2867/*
6d2f911b 2868 * 'httpSetCookie()' - Set the cookie value(s).
ef416fc2 2869 *
f3c17241 2870 * @since CUPS 1.1.19/OS X 10.3@
ef416fc2 2871 */
2872
2873void
2874httpSetCookie(http_t *http, /* I - Connection */
2875 const char *cookie) /* I - Cookie string */
2876{
2877 if (!http)
2878 return;
2879
2880 if (http->cookie)
2881 free(http->cookie);
2882
2883 if (cookie)
2884 http->cookie = strdup(cookie);
2885 else
2886 http->cookie = NULL;
2887}
2888
2889
c1420c87
MS
2890/*
2891 * 'httpSetDefaultField()' - Set the default value of an HTTP header.
2892 *
6961465f
MS
2893 * Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@,
2894 * and @code HTTP_FIELD_USER_AGENT@ can be set.
c1420c87 2895 *
9c0e8e5d 2896 * @since CUPS 1.7/OS X 10.9@
c1420c87
MS
2897 */
2898
2899void
2900httpSetDefaultField(http_t *http, /* I - Connection to server */
2901 http_field_t field, /* I - Field index */
2902 const char *value)/* I - Value */
2903{
2904 DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")",
2905 http, field, http_fields[field], value));
2906
2907 if (!http)
2908 return;
2909
2910 switch (field)
2911 {
2912 case HTTP_FIELD_ACCEPT_ENCODING :
2913 if (http->default_accept_encoding)
2914 _cupsStrFree(http->default_accept_encoding);
2915
2916 http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
2917 break;
2918
2919 case HTTP_FIELD_SERVER :
2920 if (http->default_server)
2921 _cupsStrFree(http->default_server);
2922
2923 http->default_server = value ? _cupsStrAlloc(value) : NULL;
2924 break;
2925
2926 case HTTP_FIELD_USER_AGENT :
2927 if (http->default_user_agent)
2928 _cupsStrFree(http->default_user_agent);
2929
2930 http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
2931 break;
2932
2933 default :
2934 DEBUG_puts("1httpSetDefaultField: Ignored.");
2935 break;
2936 }
2937}
2938
2939
b423cd4c 2940/*
2941 * 'httpSetExpect()' - Set the Expect: header in a request.
2942 *
a469f8a5
MS
2943 * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
2944 * argument.
b423cd4c 2945 *
f3c17241 2946 * @since CUPS 1.2/OS X 10.5@
b423cd4c 2947 */
2948
2949void
568fa3fa 2950httpSetExpect(http_t *http, /* I - Connection to server */
a469f8a5 2951 http_status_t expect) /* I - HTTP status to expect
cb7f98ee 2952 (@code HTTP_STATUS_CONTINUE@) */
b423cd4c 2953{
cb7f98ee
MS
2954 DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", http, expect));
2955
b423cd4c 2956 if (http)
2957 http->expect = expect;
2958}
2959
2960
ef416fc2 2961/*
2962 * 'httpSetField()' - Set the value of an HTTP header.
2963 */
2964
2965void
568fa3fa 2966httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 2967 http_field_t field, /* I - Field index */
2968 const char *value) /* I - Value */
2969{
a469f8a5
MS
2970 DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", http,
2971 field, http_fields[field], value));
2972
ef416fc2 2973 if (http == NULL ||
2974 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
a469f8a5 2975 field >= HTTP_FIELD_MAX ||
ef416fc2 2976 value == NULL)
2977 return;
2978
a469f8a5
MS
2979 switch (field)
2980 {
2981 case HTTP_FIELD_ACCEPT_ENCODING :
2982 if (http->accept_encoding)
2983 _cupsStrFree(http->accept_encoding);
2984
2985 http->accept_encoding = _cupsStrAlloc(value);
2986 break;
2987
2988 case HTTP_FIELD_ALLOW :
2989 if (http->allow)
2990 _cupsStrFree(http->allow);
2991
2992 http->allow = _cupsStrAlloc(value);
2993 break;
2994
2995 case HTTP_FIELD_SERVER :
2996 if (http->server)
2997 _cupsStrFree(http->server);
2998
2999 http->server = _cupsStrAlloc(value);
3000 break;
3001
3002 default :
3003 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
3004 break;
3005 }
f7deaa1a 3006
f7deaa1a 3007 if (field == HTTP_FIELD_AUTHORIZATION)
3008 {
e07d4801
MS
3009 /*
3010 * Special case for Authorization: as its contents can be
3011 * longer than HTTP_MAX_VALUE
3012 */
3013
f7deaa1a 3014 if (http->field_authorization)
3015 free(http->field_authorization);
3016
3017 http->field_authorization = strdup(value);
3018 }
e07d4801
MS
3019 else if (field == HTTP_FIELD_HOST)
3020 {
3021 /*
f11a948a
MS
3022 * Special-case for Host: as we don't want a trailing "." on the hostname and
3023 * need to bracket IPv6 numeric addresses.
e07d4801
MS
3024 */
3025
178cb736
MS
3026 char *ptr = strchr(value, ':');
3027
3028 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
3029 {
3030 /*
3031 * Bracket IPv6 numeric addresses...
3032 *
3033 * This is slightly inefficient (basically copying twice), but is an edge
3034 * case and not worth optimizing...
3035 */
e07d4801 3036
f11a948a
MS
3037 snprintf(http->fields[HTTP_FIELD_HOST],
3038 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
3039 }
3040 else
e07d4801 3041 {
f11a948a
MS
3042 /*
3043 * Check for a trailing dot on the hostname...
3044 */
3045
178cb736 3046 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
3047
3048 if (*ptr)
3049 {
3050 ptr += strlen(ptr) - 1;
e07d4801 3051
f11a948a
MS
3052 if (*ptr == '.')
3053 *ptr = '\0';
3054 }
e07d4801
MS
3055 }
3056 }
a469f8a5
MS
3057#ifdef HAVE_LIBZ
3058 else if (field == HTTP_FIELD_CONTENT_ENCODING &&
3059 http->data_encoding != HTTP_ENCODING_FIELDS)
3060 {
3061 DEBUG_puts("1httpSetField: Calling http_content_coding_start.");
3062 http_content_coding_start(http, value);
3063 }
3064#endif /* HAVE_LIBZ */
ef416fc2 3065}
3066
3067
3068/*
3069 * 'httpSetLength()' - Set the content-length and content-encoding.
3070 *
f3c17241 3071 * @since CUPS 1.2/OS X 10.5@
ef416fc2 3072 */
3073
3074void
568fa3fa 3075httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 3076 size_t length) /* I - Length (0 for chunked) */
3077{
a469f8a5
MS
3078 DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", http,
3079 CUPS_LLCAST length));
3080
ef416fc2 3081 if (!http)
3082 return;
3083
3084 if (!length)
3085 {
5a9febac
MS
3086 strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked",
3087 HTTP_MAX_VALUE);
ef416fc2 3088 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
3089 }
3090 else
3091 {
3092 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
3093 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
3094 CUPS_LLFMT, CUPS_LLCAST length);
3095 }
3096}
3097
3098
10d09e33 3099/*
f228370c 3100 * 'httpSetTimeout()' - Set read/write timeouts and an optional callback.
10d09e33
MS
3101 *
3102 * The optional timeout callback receives both the HTTP connection and a user
f228370c
MS
3103 * data pointer and must return 1 to continue or 0 to error (time) out.
3104 *
f3c17241 3105 * @since CUPS 1.5/OS X 10.7@
10d09e33
MS
3106 */
3107
3108void
f228370c
MS
3109httpSetTimeout(
3110 http_t *http, /* I - Connection to server */
3111 double timeout, /* I - Number of seconds for timeout,
10d09e33 3112 must be greater than 0 */
f228370c
MS
3113 http_timeout_cb_t cb, /* I - Callback function or NULL */
3114 void *user_data) /* I - User data pointer */
10d09e33
MS
3115{
3116 if (!http || timeout <= 0.0)
3117 return;
3118
85dda01c
MS
3119 http->timeout_cb = cb;
3120 http->timeout_data = user_data;
3121 http->timeout_value = timeout;
10d09e33
MS
3122
3123 if (http->fd >= 0)
85dda01c 3124 http_set_timeout(http->fd, timeout);
c8fef167 3125
85dda01c 3126 http_set_wait(http);
10d09e33
MS
3127}
3128
3129
ef416fc2 3130/*
3131 * 'httpTrace()' - Send an TRACE request to the server.
3132 */
3133
3134int /* O - Status of call (0 = success) */
568fa3fa 3135httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 3136 const char *uri) /* I - URI for trace */
3137{
cb7f98ee 3138 return (http_send(http, HTTP_STATE_TRACE, uri));
ef416fc2 3139}
3140
3141
3142/*
e60ec91f
MS
3143 * '_httpUpdate()' - Update the current HTTP status for incoming data.
3144 *
3145 * Note: Unlike httpUpdate(), this function does not flush pending write data
3146 * and only retrieves a single status line from the HTTP connection.
ef416fc2 3147 */
3148
e60ec91f
MS
3149int /* O - 1 to continue, 0 to stop */
3150_httpUpdate(http_t *http, /* I - Connection to server */
3151 http_status_t *status) /* O - Current HTTP status */
ef416fc2 3152{
3153 char line[32768], /* Line from connection... */
3154 *value; /* Pointer to value on line */
3155 http_field_t field; /* Field index */
e60ec91f 3156 int major, minor; /* HTTP version numbers */
ef416fc2 3157
3158
e60ec91f 3159 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status,
cb7f98ee 3160 http_state_string(http->state)));
ef416fc2 3161
3162 /*
e60ec91f 3163 * Grab a single line from the connection...
ef416fc2 3164 */
3165
e60ec91f 3166 if (!httpGets(line, sizeof(line), http))
ef416fc2 3167 {
cb7f98ee 3168 *status = HTTP_STATUS_ERROR;
e60ec91f 3169 return (0);
ef416fc2 3170 }
3171
e60ec91f 3172 DEBUG_printf(("2_httpUpdate: Got \"%s\"", line));
ef416fc2 3173
e60ec91f 3174 if (line[0] == '\0')
ef416fc2 3175 {
e60ec91f
MS
3176 /*
3177 * Blank line means the start of the data section (if any). Return
3178 * the result code, too...
3179 *
a469f8a5
MS
3180 * If we get status 100 (HTTP_STATUS_CONTINUE), then we *don't* change
3181 * states. Instead, we just return HTTP_STATUS_CONTINUE to the caller and
3182 * keep on tryin'...
e60ec91f 3183 */
ef416fc2 3184
a469f8a5 3185 if (http->status == HTTP_STATUS_CONTINUE)
ef416fc2 3186 {
e60ec91f
MS
3187 *status = http->status;
3188 return (0);
3189 }
ef416fc2 3190
cb7f98ee 3191 if (http->status < HTTP_STATUS_BAD_REQUEST)
e60ec91f 3192 http->digest_tries = 0;
ef416fc2 3193
3194#ifdef HAVE_SSL
cb7f98ee 3195 if (http->status == HTTP_STATUS_SWITCHING_PROTOCOLS && !http->tls)
e60ec91f
MS
3196 {
3197 if (http_setup_ssl(http) != 0)
ef416fc2 3198 {
ef416fc2 3199# ifdef WIN32
e60ec91f 3200 closesocket(http->fd);
ef416fc2 3201# else
e60ec91f 3202 close(http->fd);
ef416fc2 3203# endif /* WIN32 */
3204
cb7f98ee 3205 *status = http->status = HTTP_STATUS_ERROR;
e60ec91f 3206 return (0);
ef416fc2 3207 }
e60ec91f 3208
a469f8a5 3209 *status = HTTP_STATUS_CONTINUE;
e60ec91f
MS
3210 return (0);
3211 }
ef416fc2 3212#endif /* HAVE_SSL */
3213
a469f8a5
MS
3214 if (http_set_length(http) < 0)
3215 {
3216 DEBUG_puts("1_httpUpdate: Bad Content-Length.");
3217 http->error = EINVAL;
cb7f98ee 3218 http->status = *status = HTTP_STATUS_ERROR;
a469f8a5
MS
3219 return (0);
3220 }
ef416fc2 3221
e60ec91f
MS
3222 switch (http->state)
3223 {
c41769ff
MS
3224 case HTTP_STATE_GET :
3225 case HTTP_STATE_POST :
a469f8a5 3226 case HTTP_STATE_POST_RECV :
c41769ff 3227 case HTTP_STATE_PUT :
e60ec91f 3228 http->state ++;
a469f8a5
MS
3229
3230 DEBUG_printf(("1_httpUpdate: Set state to %s.",
cb7f98ee 3231 http_state_string(http->state)));
a469f8a5 3232
c41769ff
MS
3233 case HTTP_STATE_POST_SEND :
3234 case HTTP_STATE_HEAD :
e60ec91f 3235 break;
ef416fc2 3236
e60ec91f 3237 default :
a469f8a5
MS
3238 http->state = HTTP_STATE_WAITING;
3239
cb7f98ee 3240 DEBUG_puts("1_httpUpdate: Reset state to HTTP_STATE_WAITING.");
e60ec91f 3241 break;
ef416fc2 3242 }
e60ec91f 3243
a469f8a5
MS
3244#ifdef HAVE_LIBZ
3245 DEBUG_puts("1_httpUpdate: Calling http_content_coding_start.");
3246 http_content_coding_start(http,
3247 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
3248#endif /* HAVE_LIBZ */
3249
e60ec91f
MS
3250 *status = http->status;
3251 return (0);
3252 }
3253 else if (!strncmp(line, "HTTP/", 5))
3254 {
3255 /*
3256 * Got the beginning of a response...
3257 */
3258
3259 int intstatus; /* Status value as an integer */
3260
3261 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3)
3262 {
cb7f98ee 3263 *status = http->status = HTTP_STATUS_ERROR;
e60ec91f
MS
3264 return (0);
3265 }
3266
a469f8a5
MS
3267 httpClearFields(http);
3268
e60ec91f
MS
3269 http->version = (http_version_t)(major * 100 + minor);
3270 *status = http->status = (http_status_t)intstatus;
3271 }
3272 else if ((value = strchr(line, ':')) != NULL)
3273 {
3274 /*
3275 * Got a value...
3276 */
3277
3278 *value++ = '\0';
3279 while (_cups_isspace(*value))
3280 value ++;
3281
a469f8a5
MS
3282 DEBUG_printf(("1_httpUpdate: Header %s: %s", line, value));
3283
e60ec91f
MS
3284 /*
3285 * Be tolerants of servers that send unknown attribute fields...
3286 */
3287
88f9aafc 3288 if (!_cups_strcasecmp(line, "expect"))
ef416fc2 3289 {
3290 /*
e60ec91f 3291 * "Expect: 100-continue" or similar...
ef416fc2 3292 */
3293
e60ec91f 3294 http->expect = (http_status_t)atoi(value);
ef416fc2 3295 }
88f9aafc 3296 else if (!_cups_strcasecmp(line, "cookie"))
ef416fc2 3297 {
3298 /*
e60ec91f 3299 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
ef416fc2 3300 */
3301
e60ec91f
MS
3302 httpSetCookie(http, value);
3303 }
3304 else if ((field = http_field(line)) != HTTP_FIELD_UNKNOWN)
3305 httpSetField(http, field, value);
3306#ifdef DEBUG
3307 else
3308 DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
3309#endif /* DEBUG */
3310 }
3311 else
3312 {
3313 DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line));
a469f8a5 3314 http->error = EINVAL;
cb7f98ee 3315 http->status = *status = HTTP_STATUS_ERROR;
e60ec91f
MS
3316 return (0);
3317 }
ef416fc2 3318
e60ec91f
MS
3319 return (1);
3320}
ef416fc2 3321
ef416fc2 3322
e60ec91f
MS
3323/*
3324 * 'httpUpdate()' - Update the current HTTP state for incoming data.
3325 */
ef416fc2 3326
e60ec91f
MS
3327http_status_t /* O - HTTP status */
3328httpUpdate(http_t *http) /* I - Connection to server */
3329{
3330 http_status_t status; /* Request status */
3331
3332
3333 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
cb7f98ee 3334 http_state_string(http->state)));
e60ec91f
MS
3335
3336 /*
3337 * Flush pending data, if any...
3338 */
3339
3340 if (http->wused)
3341 {
3342 DEBUG_puts("2httpUpdate: flushing buffer...");
3343
3344 if (httpFlushWrite(http) < 0)
cb7f98ee 3345 return (HTTP_STATUS_ERROR);
ef416fc2 3346 }
3347
e60ec91f
MS
3348 /*
3349 * If we haven't issued any commands, then there is nothing to "update"...
3350 */
3351
a469f8a5 3352 if (http->state == HTTP_STATE_WAITING)
cb7f98ee 3353 return (HTTP_STATUS_CONTINUE);
e60ec91f
MS
3354
3355 /*
3356 * Grab all of the lines we can from the connection...
3357 */
3358
3359 while (_httpUpdate(http, &status));
3360
ef416fc2 3361 /*
3362 * See if there was an error...
3363 */
3364
cb7f98ee 3365 if (http->error == EPIPE && http->status > HTTP_STATUS_CONTINUE)
e07d4801
MS
3366 {
3367 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 3368 return (http->status);
e07d4801 3369 }
ef416fc2 3370
3371 if (http->error)
3372 {
e07d4801 3373 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 3374 strerror(http->error)));
cb7f98ee
MS
3375 http->status = HTTP_STATUS_ERROR;
3376 return (HTTP_STATUS_ERROR);
ef416fc2 3377 }
3378
3379 /*
e60ec91f 3380 * Return the current status...
ef416fc2 3381 */
3382
e60ec91f 3383 return (status);
ef416fc2 3384}
3385
3386
38e73f87
MS
3387/*
3388 * '_httpWait()' - Wait for data available on a connection (no flush).
3389 */
3390
3391int /* O - 1 if data is available, 0 otherwise */
3392_httpWait(http_t *http, /* I - Connection to server */
3393 int msec, /* I - Milliseconds to wait */
3394 int usessl) /* I - Use SSL context? */
3395{
3396#ifdef HAVE_POLL
3397 struct pollfd pfd; /* Polled file descriptor */
3398#else
3399 fd_set input_set; /* select() input set */
3400 struct timeval timeout; /* Timeout */
3401#endif /* HAVE_POLL */
3402 int nfds; /* Result from select()/poll() */
3403
3404
e07d4801 3405 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
3406
3407 if (http->fd < 0)
f8b3a85b
MS
3408 {
3409 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
38e73f87 3410 return (0);
f8b3a85b 3411 }
38e73f87
MS
3412
3413 /*
3414 * Check the SSL/TLS buffers for data first...
3415 */
3416
3417#ifdef HAVE_SSL
3418 if (http->tls && usessl)
3419 {
3420# ifdef HAVE_LIBSSL
7cf5915e 3421 if (SSL_pending(http->tls))
f8b3a85b
MS
3422 {
3423 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 3424 return (1);
f8b3a85b
MS
3425 }
3426
38e73f87 3427# elif defined(HAVE_GNUTLS)
7cf5915e 3428 if (gnutls_record_check_pending(http->tls))
f8b3a85b
MS
3429 {
3430 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 3431 return (1);
f8b3a85b
MS
3432 }
3433
38e73f87
MS
3434# elif defined(HAVE_CDSASSL)
3435 size_t bytes; /* Bytes that are available */
3436
7cf5915e 3437 if (!SSLGetBufferedReadSize(http->tls, &bytes) &&
38e73f87 3438 bytes > 0)
f8b3a85b
MS
3439 {
3440 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 3441 return (1);
f8b3a85b 3442 }
38e73f87
MS
3443# endif /* HAVE_LIBSSL */
3444 }
3445#endif /* HAVE_SSL */
3446
3447 /*
3448 * Then try doing a select() or poll() to poll the socket...
3449 */
3450
3451#ifdef HAVE_POLL
3452 pfd.fd = http->fd;
3453 pfd.events = POLLIN;
3454
5a9febac
MS
3455 do
3456 {
3457 nfds = poll(&pfd, 1, msec);
3458 }
3459 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
3460
3461#else
3462 do
3463 {
3464 FD_ZERO(&input_set);
3465 FD_SET(http->fd, &input_set);
3466
e07d4801 3467 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
3468
3469 if (msec >= 0)
3470 {
3471 timeout.tv_sec = msec / 1000;
3472 timeout.tv_usec = (msec % 1000) * 1000;
3473
3474 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
3475 }
3476 else
3477 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
3478
e07d4801 3479 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
3480 }
3481# ifdef WIN32
cc754834
MS
3482 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
3483 WSAGetLastError() == WSAEWOULDBLOCK));
38e73f87 3484# else
e07d4801 3485 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
3486# endif /* WIN32 */
3487#endif /* HAVE_POLL */
3488
f8b3a85b
MS
3489 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
3490 errno));
38e73f87
MS
3491
3492 return (nfds > 0);
3493}
3494
3495
ef416fc2 3496/*
3497 * 'httpWait()' - Wait for data available on a connection.
3498 *
f3c17241 3499 * @since CUPS 1.1.19/OS X 10.3@
ef416fc2 3500 */
3501
3502int /* O - 1 if data is available, 0 otherwise */
568fa3fa 3503httpWait(http_t *http, /* I - Connection to server */
ef416fc2 3504 int msec) /* I - Milliseconds to wait */
3505{
3506 /*
3507 * First see if there is data in the buffer...
3508 */
3509
22c9029b
MS
3510 DEBUG_printf(("2httpWait(http=%p, msec=%d)", http, msec));
3511
ef416fc2 3512 if (http == NULL)
3513 return (0);
3514
3515 if (http->used)
22c9029b
MS
3516 {
3517 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
ef416fc2 3518 return (1);
22c9029b 3519 }
ef416fc2 3520
0fa6c7fa
MS
3521#ifdef HAVE_LIBZ
3522 if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0)
3523 {
3524 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
3525 return (1);
3526 }
3527#endif /* HAVE_LIBZ */
3528
8ca02f3c 3529 /*
3530 * Flush pending data, if any...
3531 */
3532
3533 if (http->wused)
3534 {
22c9029b
MS
3535 DEBUG_puts("3httpWait: Flushing write buffer.");
3536
8ca02f3c 3537 if (httpFlushWrite(http) < 0)
3538 return (0);
3539 }
3540
ef416fc2 3541 /*
3542 * If not, check the SSL/TLS buffers and do a select() on the connection...
3543 */
3544
38e73f87 3545 return (_httpWait(http, msec, 1));
ef416fc2 3546}
3547
3548
3549/*
3550 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 3551 *
3552 * This function is deprecated. Use the httpWrite2() function which can
3553 * write more than 2GB of data.
3554 *
3555 * @deprecated@
ef416fc2 3556 */
ef55b745 3557
ef416fc2 3558int /* O - Number of bytes written */
568fa3fa 3559httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 3560 const char *buffer, /* I - Buffer for data */
3561 int length) /* I - Number of bytes to write */
3562{
a4d04587 3563 return ((int)httpWrite2(http, buffer, length));
3564}
3565
3566
3567/*
3568 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 3569 *
f3c17241 3570 * @since CUPS 1.2/OS X 10.5@
a4d04587 3571 */
ef55b745 3572
a4d04587 3573ssize_t /* O - Number of bytes written */
568fa3fa 3574httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 3575 const char *buffer, /* I - Buffer for data */
3576 size_t length) /* I - Number of bytes to write */
3577{
3578 ssize_t bytes; /* Bytes written */
ef416fc2 3579
3580
e07d4801 3581 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 3582 buffer, CUPS_LLCAST length));
ef416fc2 3583
3584 /*
3585 * Range check input...
3586 */
3587
a469f8a5
MS
3588 if (!http || !buffer)
3589 {
3590 DEBUG_puts("1httpWrite2: Returning -1 due to bad input.");
ef416fc2 3591 return (-1);
a469f8a5 3592 }
ef416fc2 3593
3594 /*
3595 * Mark activity on the connection...
3596 */
3597
3598 http->activity = time(NULL);
3599
3600 /*
3601 * Buffer small writes for better performance...
3602 */
3603
a469f8a5
MS
3604#ifdef HAVE_LIBZ
3605 if (http->coding)
3606 {
3607 DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding));
3608
3609 if (length == 0)
3610 {
3611 http_content_coding_finish(http);
3612 bytes = 0;
3613 }
3614 else
3615 {
3616 http->stream.next_in = (Bytef *)buffer;
3617 http->stream.avail_in = length;
3618 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
3619 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
3620
3621 while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK)
3622 {
3623 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3624
3625 if (http->stream.avail_out == 0)
3626 {
3627 if (httpFlushWrite(http) < 0)
3628 {
3629 DEBUG_puts("1httpWrite2: Unable to flush, returning -1.");
3630 return (-1);
3631 }
3632
3633 http->stream.next_out = (Bytef *)http->wbuffer;
3634 http->stream.avail_out = sizeof(http->wbuffer);
3635 }
3636 }
3637
3638 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3639 bytes = length;
3640 }
3641 }
3642 else
3643#endif /* HAVE_LIBZ */
ef416fc2 3644 if (length > 0)
3645 {
3646 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
3647 {
e07d4801
MS
3648 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
3649 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 3650
3651 httpFlushWrite(http);
3652 }
3653
38e73f87
MS
3654 if ((length + http->wused) <= sizeof(http->wbuffer) &&
3655 length < sizeof(http->wbuffer))
ef416fc2 3656 {
3657 /*
3658 * Write to buffer...
3659 */
3660
e07d4801 3661 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 3662 CUPS_LLCAST length));
ef416fc2 3663
3664 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 3665 http->wused += (int)length;
3666 bytes = (ssize_t)length;
ef416fc2 3667 }
3668 else
3669 {
3670 /*
3671 * Otherwise write the data directly...
3672 */
3673
e07d4801 3674 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 3675 CUPS_LLCAST length));
ef416fc2 3676
a469f8a5 3677 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
b86bc4cf 3678 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 3679 else
b86bc4cf 3680 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 3681
e07d4801 3682 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 3683 CUPS_LLCAST bytes));
ef416fc2 3684 }
3685
a469f8a5 3686 if (http->data_encoding == HTTP_ENCODING_LENGTH)
ef416fc2 3687 http->data_remaining -= bytes;
3688 }
3689 else
3690 bytes = 0;
3691
3692 /*
3693 * Handle end-of-request processing...
3694 */
3695
a469f8a5
MS
3696 if ((http->data_encoding == HTTP_ENCODING_CHUNKED && length == 0) ||
3697 (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0))
ef416fc2 3698 {
3699 /*
3700 * Finished with the transfer; unless we are sending POST or PUT
3701 * data, go idle...
3702 */
3703
db8b865d
MS
3704#ifdef HAVE_LIBZ
3705 if (http->coding)
3706 http_content_coding_finish(http);
3707#endif /* HAVE_LIBZ */
3708
ef416fc2 3709 if (http->wused)
a469f8a5
MS
3710 {
3711 if (httpFlushWrite(http) < 0)
3712 return (-1);
3713 }
ef416fc2 3714
a469f8a5 3715 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
ef416fc2 3716 {
3717 /*
3718 * Send a 0-length chunk at the end of the request...
3719 */
3720
3721 http_write(http, "0\r\n\r\n", 5);
3722
3723 /*
3724 * Reset the data state...
3725 */
3726
a469f8a5 3727 http->data_encoding = HTTP_ENCODING_FIELDS;
ef416fc2 3728 http->data_remaining = 0;
3729 }
a469f8a5
MS
3730
3731 if (http->state == HTTP_STATE_POST_RECV)
3732 http->state ++;
ad29aeab
MS
3733 else if (http->state == HTTP_STATE_POST_SEND)
3734 http->state = HTTP_STATE_WAITING;
db8b865d 3735 else
cb7f98ee 3736 http->state = HTTP_STATE_STATUS;
a469f8a5 3737
db8b865d 3738 DEBUG_printf(("2httpWrite2: Changed state to %s.",
cb7f98ee 3739 http_state_string(http->state)));
ef416fc2 3740 }
3741
a469f8a5
MS
3742 DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes));
3743
ef416fc2 3744 return (bytes);
3745}
3746
3747
3748#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
3749/*
411affcf 3750 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 3751 */
3752
3753OSStatus /* O - -1 on error, 0 on success */
3754_httpWriteCDSA(
3755 SSLConnectionRef connection, /* I - SSL/TLS connection */
3756 const void *data, /* I - Data buffer */
3757 size_t *dataLength) /* IO - Number of bytes */
3758{
411affcf 3759 OSStatus result; /* Return value */
3760 ssize_t bytes; /* Number of bytes read */
3761 http_t *http; /* HTTP connection */
e53920b9 3762
3763
411affcf 3764 http = (http_t *)connection;
ef416fc2 3765
b423cd4c 3766 do
411affcf 3767 {
3768 bytes = write(http->fd, data, *dataLength);
3769 }
e07d4801 3770 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 3771
b423cd4c 3772 if (bytes == *dataLength)
411affcf 3773 {
b423cd4c 3774 result = 0;
411affcf 3775 }
b423cd4c 3776 else if (bytes >= 0)
3777 {
3778 *dataLength = bytes;
3779 result = errSSLWouldBlock;
3780 }
3781 else
3782 {
3783 *dataLength = 0;
ef55b745 3784
fa73b229 3785 if (errno == EAGAIN)
b423cd4c 3786 result = errSSLWouldBlock;
b423cd4c 3787 else
ed486911 3788 result = errSSLClosedAbort;
ef416fc2 3789 }
b423cd4c 3790
411affcf 3791 return (result);
ef416fc2 3792}
3793#endif /* HAVE_SSL && HAVE_CDSASSL */
3794
3795
411affcf 3796#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
3797/*
3798 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
3799 */
3800
3801ssize_t /* O - Number of bytes written or -1 on error */
3802_httpWriteGNUTLS(
568fa3fa 3803 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 3804 const void *data, /* I - Data buffer */
3805 size_t length) /* I - Number of bytes to write */
3806{
a4845881
MS
3807 ssize_t bytes; /* Bytes written */
3808
3809
3810 DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data,
3811 (int)length));
a2326b5b 3812#ifdef DEBUG
a4845881 3813 http_debug_hex("_httpWriteGNUTLS", data, (int)length);
a2326b5b 3814#endif /* DEBUG */
a4845881
MS
3815
3816 bytes = send(((http_t *)ptr)->fd, data, length, 0);
3817 DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes));
a2326b5b 3818
a4845881 3819 return (bytes);
411affcf 3820}
3821#endif /* HAVE_SSL && HAVE_GNUTLS */
3822
3823
a469f8a5
MS
3824/*
3825 * 'httpWriteResponse()' - Write a HTTP response to a client connection.
3826 *
9c0e8e5d 3827 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
3828 */
3829
3830int /* O - 0 on success, -1 on error */
3831httpWriteResponse(http_t *http, /* I - HTTP connection */
3832 http_status_t status) /* I - Status code */
3833{
3834 http_encoding_t old_encoding; /* Old data_encoding value */
3835 off_t old_remaining; /* Old data_remaining value */
3836
3837
3838 /*
3839 * Range check input...
3840 */
3841
3842 DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", http, status));
3843
3844 if (!http || status < HTTP_STATUS_CONTINUE)
3845 {
3846 DEBUG_puts("1httpWriteResponse: Bad input.");
3847 return (-1);
3848 }
3849
3850 /*
3851 * Set the various standard fields if they aren't already...
3852 */
3853
3854 if (!http->fields[HTTP_FIELD_DATE][0])
3855 httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL)));
3856
cb7f98ee 3857 if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive)
a469f8a5
MS
3858 {
3859 http->keep_alive = 0;
3860 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "");
3861 }
3862
3863 if (http->version == HTTP_VERSION_1_1)
3864 {
3865 if (!http->fields[HTTP_FIELD_CONNECTION][0])
3866 {
3867 if (http->keep_alive)
3868 httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
3869 else
3870 httpSetField(http, HTTP_FIELD_CONNECTION, "close");
3871 }
3872
3873 if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0])
3874 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10");
3875 }
3876
3877#ifdef HAVE_SSL
3878 if (status == HTTP_STATUS_UPGRADE_REQUIRED)
3879 {
3880 if (!http->fields[HTTP_FIELD_CONNECTION][0])
3881 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
3882
3883 if (!http->fields[HTTP_FIELD_UPGRADE][0])
3884 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
3885 }
3886#endif /* HAVE_SSL */
3887
3888 if (!http->server)
c1420c87
MS
3889 httpSetField(http, HTTP_FIELD_SERVER,
3890 http->default_server ? http->default_server : CUPS_MINIMAL);
a469f8a5 3891
a469f8a5
MS
3892 /*
3893 * Set the Accept-Encoding field if it isn't already...
3894 */
3895
3896 if (!http->accept_encoding)
c1420c87
MS
3897 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
3898 http->default_accept_encoding ? http->default_accept_encoding :
3899#ifdef HAVE_LIBZ
3900 "gzip, deflate, identity");
3901#else
3902 "identity");
a469f8a5
MS
3903#endif /* HAVE_LIBZ */
3904
3905 /*
3906 * Send the response header...
3907 */
3908
3909 old_encoding = http->data_encoding;
3910 old_remaining = http->data_remaining;
3911 http->data_encoding = HTTP_ENCODING_FIELDS;
3912
3913 if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100,
3914 http->version % 100, (int)status, httpStatus(status)) < 0)
3915 {
3916 http->status = HTTP_STATUS_ERROR;
3917 return (-1);
3918 }
3919
3920 if (status != HTTP_STATUS_CONTINUE)
3921 {
3922 /*
3923 * 100 Continue doesn't have the rest of the response headers...
3924 */
3925
3926 int i; /* Looping var */
3927 const char *value; /* Field value */
3928
3929 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3930 {
3931 if ((value = httpGetField(http, i)) != NULL && *value)
3932 {
3933 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
3934 {
3935 http->status = HTTP_STATUS_ERROR;
3936 return (-1);
3937 }
3938 }
3939 }
3940
3941 if (http->cookie)
3942 {
3943 if (httpPrintf(http, "Set-Cookie: %s path=/%s\r\n", http->cookie,
3944 http->tls ? " secure" : "") < 1)
3945 {
cb7f98ee 3946 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
3947 return (-1);
3948 }
3949 }
3950 }
3951
3952 if (httpWrite2(http, "\r\n", 2) < 2)
3953 {
cb7f98ee 3954 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
3955 return (-1);
3956 }
3957
3958 if (httpFlushWrite(http) < 0)
3959 {
cb7f98ee 3960 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
3961 return (-1);
3962 }
3963
3964 if (status == HTTP_STATUS_CONTINUE)
3965 {
3966 /*
3967 * Restore the old data_encoding and data_length values...
3968 */
3969
3970 http->data_encoding = old_encoding;
3971 http->data_remaining = old_remaining;
3972
3973 if (old_remaining <= INT_MAX)
3974 http->_data_remaining = (int)old_remaining;
3975 else
3976 http->_data_remaining = INT_MAX;
3977 }
3978 else if (http->state == HTTP_STATE_OPTIONS ||
3979 http->state == HTTP_STATE_HEAD ||
3980 http->state == HTTP_STATE_PUT ||
3981 http->state == HTTP_STATE_TRACE ||
cb7f98ee
MS
3982 http->state == HTTP_STATE_CONNECT ||
3983 http->state == HTTP_STATE_STATUS)
a469f8a5
MS
3984 {
3985 DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
cb7f98ee 3986 "was %s.", http_state_string(http->state)));
a469f8a5
MS
3987 http->state = HTTP_STATE_WAITING;
3988 }
3989 else
3990 {
3991 /*
3992 * Force data_encoding and data_length to be set according to the response
3993 * headers...
3994 */
3995
3996 http_set_length(http);
3997
db8b865d 3998#ifdef HAVE_LIBZ
a469f8a5
MS
3999 /*
4000 * Then start any content encoding...
4001 */
4002
4003 DEBUG_puts("1httpWriteResponse: Calling http_content_coding_start.");
4004 http_content_coding_start(http,
4005 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
db8b865d 4006#endif /* HAVE_LIBZ */
a469f8a5
MS
4007 }
4008
4009 return (0);
4010}
4011
4012
411affcf 4013#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
4014/*
4015 * 'http_bio_ctrl()' - Control the HTTP connection.
4016 */
4017
4018static long /* O - Result/data */
4019http_bio_ctrl(BIO *h, /* I - BIO data */
4020 int cmd, /* I - Control command */
4021 long arg1, /* I - First argument */
4022 void *arg2) /* I - Second argument */
4023{
4024 switch (cmd)
4025 {
4026 default :
4027 return (0);
4028
4029 case BIO_CTRL_RESET :
4030 h->ptr = NULL;
4031 return (0);
4032
4033 case BIO_C_SET_FILE_PTR :
4034 h->ptr = arg2;
4035 h->init = 1;
4036 return (1);
4037
4038 case BIO_C_GET_FILE_PTR :
4039 if (arg2)
4040 {
4041 *((void **)arg2) = h->ptr;
4042 return (1);
4043 }
4044 else
4045 return (0);
ef55b745 4046
411affcf 4047 case BIO_CTRL_DUP :
4048 case BIO_CTRL_FLUSH :
4049 return (1);
4050 }
4051}
4052
4053
4054/*
4055 * 'http_bio_free()' - Free OpenSSL data.
4056 */
4057
4058static int /* O - 1 on success, 0 on failure */
4059http_bio_free(BIO *h) /* I - BIO data */
4060{
4061 if (!h)
4062 return (0);
4063
4064 if (h->shutdown)
4065 {
4066 h->init = 0;
4067 h->flags = 0;
4068 }
4069
4070 return (1);
4071}
4072
4073
4074/*
4075 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
4076 */
4077
4078static int /* O - 1 on success, 0 on failure */
4079http_bio_new(BIO *h) /* I - BIO data */
4080{
4081 if (!h)
4082 return (0);
4083
4084 h->init = 0;
4085 h->num = 0;
4086 h->ptr = NULL;
4087 h->flags = 0;
4088
4089 return (1);
4090}
4091
4092
4093/*
4094 * 'http_bio_puts()' - Send a string for OpenSSL.
4095 */
4096
4097static int /* O - Bytes written */
4098http_bio_puts(BIO *h, /* I - BIO data */
4099 const char *str) /* I - String to write */
4100{
b86bc4cf 4101#ifdef WIN32
4102 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
4103#else
411affcf 4104 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 4105#endif /* WIN32 */
411affcf 4106}
4107
4108
4109/*
4110 * 'http_bio_read()' - Read data for OpenSSL.
4111 */
4112
4113static int /* O - Bytes read */
4114http_bio_read(BIO *h, /* I - BIO data */
4115 char *buf, /* I - Buffer */
4116 int size) /* I - Number of bytes to read */
4117{
4118 http_t *http; /* HTTP connection */
4119
4120
4121 http = (http_t *)h->ptr;
4122
4123 if (!http->blocking)
4124 {
4125 /*
4126 * Make sure we have data before we read...
4127 */
4128
85dda01c 4129 while (!_httpWait(http, http->wait_value, 0))
411affcf 4130 {
f228370c
MS
4131 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4132 continue;
4133
b86bc4cf 4134#ifdef WIN32
4135 http->error = WSAETIMEDOUT;
4136#else
411affcf 4137 http->error = ETIMEDOUT;
b86bc4cf 4138#endif /* WIN32 */
4139
411affcf 4140 return (-1);
4141 }
4142 }
4143
4144 return (recv(http->fd, buf, size, 0));
4145}
4146
4147
4148/*
4149 * 'http_bio_write()' - Write data for OpenSSL.
4150 */
4151
4152static int /* O - Bytes written */
4153http_bio_write(BIO *h, /* I - BIO data */
4154 const char *buf, /* I - Buffer to write */
4155 int num) /* I - Number of bytes to write */
4156{
4157 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
4158}
4159#endif /* HAVE_SSL && HAVE_LIBSSL */
4160
4161
a469f8a5
MS
4162#ifdef HAVE_LIBZ
4163/*
4164 * 'http_content_coding_finish()' - Finish doing any content encoding.
4165 */
4166
4167static void
4168http_content_coding_finish(
4169 http_t *http) /* I - HTTP connection */
4170{
4171 int zerr; /* Compression status */
06cefec3 4172 Byte dummy[1]; /* Dummy read buffer */
a469f8a5
MS
4173
4174
4175 switch (http->coding)
4176 {
4177 case _HTTP_CODING_DEFLATE :
4178 case _HTTP_CODING_GZIP :
06cefec3
MS
4179 http->stream.next_in = dummy;
4180 http->stream.avail_in = 0;
4181
a469f8a5
MS
4182 do
4183 {
4184 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
4185 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
4186
4187 zerr = deflate(&(http->stream), Z_FINISH);
4188
4189 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
4190 if (http->wused == sizeof(http->wbuffer))
4191 httpFlushWrite(http);
4192 }
4193 while (zerr == Z_OK);
4194
4195 deflateEnd(&(http->stream));
4196
4197 if (http->wused)
4198 httpFlushWrite(http);
4199 break;
4200
4201 case _HTTP_CODING_INFLATE :
4202 case _HTTP_CODING_GUNZIP :
4203 inflateEnd(&(http->stream));
0fa6c7fa
MS
4204 free(http->dbuffer);
4205 http->dbuffer = NULL;
a469f8a5
MS
4206 break;
4207
4208 default :
4209 break;
4210 }
4211
4212 http->coding = _HTTP_CODING_IDENTITY;
4213}
4214
4215
4216/*
4217 * 'http_content_coding_start()' - Start doing content encoding.
4218 */
4219
4220static void
4221http_content_coding_start(
4222 http_t *http, /* I - HTTP connection */
4223 const char *value) /* I - Value of Content-Encoding */
4224{
4225 int zerr; /* Error/status */
4226 _http_coding_t coding; /* Content coding value */
4227
4228
4229 DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http,
4230 value));
4231
4232 if (http->coding != _HTTP_CODING_IDENTITY)
4233 {
4234 DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
4235 http->coding));
4236 return;
4237 }
4238 else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
4239 {
cb7f98ee
MS
4240 if (http->state == HTTP_STATE_GET_SEND ||
4241 http->state == HTTP_STATE_POST_SEND)
a469f8a5
MS
4242 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP :
4243 _HTTP_CODING_GUNZIP;
cb7f98ee
MS
4244 else if (http->state == HTTP_STATE_POST_RECV ||
4245 http->state == HTTP_STATE_PUT_RECV)
a469f8a5
MS
4246 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
4247 _HTTP_CODING_GUNZIP;
4248 else
4249 {
4250 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4251 return;
4252 }
4253 }
4254 else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
4255 {
cb7f98ee
MS
4256 if (http->state == HTTP_STATE_GET_SEND ||
4257 http->state == HTTP_STATE_POST_SEND)
a469f8a5
MS
4258 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
4259 _HTTP_CODING_INFLATE;
cb7f98ee
MS
4260 else if (http->state == HTTP_STATE_POST_RECV ||
4261 http->state == HTTP_STATE_PUT_RECV)
a469f8a5
MS
4262 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
4263 _HTTP_CODING_INFLATE;
4264 else
4265 {
4266 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4267 return;
4268 }
4269 }
4270 else
4271 {
4272 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4273 return;
4274 }
4275
4276 memset(&(http->stream), 0, sizeof(http->stream));
4277
4278 switch (coding)
4279 {
4280 case _HTTP_CODING_DEFLATE :
4281 case _HTTP_CODING_GZIP :
4282 if (http->wused)
4283 httpFlushWrite(http);
4284
db8b865d
MS
4285 /*
4286 * Window size for compression is 11 bits - optimal based on PWG Raster
4287 * sample files on pwg.org. -11 is raw deflate, 27 is gzip, per ZLIB
4288 * documentation.
4289 */
4290
a469f8a5
MS
4291 if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION,
4292 Z_DEFLATED,
db8b865d 4293 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7,
a469f8a5
MS
4294 Z_DEFAULT_STRATEGY)) < Z_OK)
4295 {
cb7f98ee 4296 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
4297 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
4298 return;
4299 }
4300 break;
4301
4302 case _HTTP_CODING_INFLATE :
4303 case _HTTP_CODING_GUNZIP :
0fa6c7fa 4304 if ((http->dbuffer = malloc(HTTP_MAX_BUFFER)) == NULL)
a469f8a5 4305 {
cb7f98ee 4306 http->status = HTTP_STATUS_ERROR;
0fa6c7fa 4307 http->error = errno;
a469f8a5
MS
4308 return;
4309 }
0fa6c7fa 4310
db8b865d
MS
4311 /*
4312 * Window size for decompression is up to 15 bits (maximum supported).
4313 * -15 is raw inflate, 31 is gunzip, per ZLIB documentation.
4314 */
4315
0fa6c7fa 4316 if ((zerr = inflateInit2(&(http->stream),
db8b865d 4317 coding == _HTTP_CODING_INFLATE ? -15 : 31))
0fa6c7fa
MS
4318 < Z_OK)
4319 {
4320 free(http->dbuffer);
4321 http->dbuffer = NULL;
cb7f98ee 4322 http->status = HTTP_STATUS_ERROR;
0fa6c7fa
MS
4323 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
4324 return;
4325 }
4326
4327 http->stream.avail_in = 0;
4328 http->stream.next_in = http->dbuffer;
a469f8a5
MS
4329 break;
4330
4331 default :
4332 break;
4333 }
4334
4335 http->coding = coding;
4336
4337 DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
4338 http->coding));
4339}
4340#endif /* HAVE_LIBZ */
4341
4342
db8b865d
MS
4343/*
4344 * 'http_create()' - Create an unconnected HTTP connection.
4345 */
4346
4347static http_t * /* O - HTTP connection */
4348http_create(
4349 const char *host, /* I - Hostname */
4350 int port, /* I - Port number */
4351 http_addrlist_t *addrlist, /* I - Address list or NULL */
4352 int family, /* I - Address family or AF_UNSPEC */
4353 http_encryption_t encryption, /* I - Encryption to use */
4354 int blocking, /* I - 1 for blocking mode */
4355 _http_mode_t mode) /* I - _HTTP_MODE_CLIENT or _SERVER */
4356{
4357 http_t *http; /* New HTTP connection */
4358 char service[255]; /* Service name */
4359 http_addrlist_t *myaddrlist = NULL; /* My address list */
4360
4361
4362 DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, "
4363 "encryption=%d, blocking=%d, mode=%d)", host, port, addrlist,
4364 family, encryption, blocking, mode));
4365
4366 if (!host && mode == _HTTP_MODE_CLIENT)
4367 return (NULL);
4368
4369 httpInitialize();
4370
4371 /*
4372 * Lookup the host...
4373 */
4374
4375 if (addrlist)
4376 {
4377 myaddrlist = httpAddrCopyList(addrlist);
4378 }
4379 else
4380 {
4381 snprintf(service, sizeof(service), "%d", port);
4382
4383 myaddrlist = httpAddrGetList(host, family, service);
4384 }
4385
4386 if (!myaddrlist)
4387 return (NULL);
4388
4389 /*
4390 * Allocate memory for the structure...
4391 */
4392
4393 if ((http = calloc(sizeof(http_t), 1)) == NULL)
4394 {
cb7f98ee 4395 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
db8b865d
MS
4396 httpAddrFreeList(addrlist);
4397 return (NULL);
4398 }
4399
4400 /*
4401 * Initialize the HTTP data...
4402 */
4403
4404 http->mode = mode;
4405 http->activity = time(NULL);
4406 http->addrlist = myaddrlist;
4407 http->blocking = blocking;
4408 http->fd = -1;
4409#ifdef HAVE_GSSAPI
4410 http->gssctx = GSS_C_NO_CONTEXT;
4411 http->gssname = GSS_C_NO_NAME;
4412#endif /* HAVE_GSSAPI */
cb7f98ee 4413 http->status = HTTP_STATUS_CONTINUE;
db8b865d
MS
4414 http->version = HTTP_VERSION_1_1;
4415
4416 if (host)
4417 strlcpy(http->hostname, host, sizeof(http->hostname));
4418
4419 if (port == 443) /* Always use encryption for https */
4420 http->encryption = HTTP_ENCRYPTION_ALWAYS;
4421 else
4422 http->encryption = encryption;
4423
4424 http_set_wait(http);
4425
4426 /*
4427 * Return the new structure...
4428 */
4429
4430 return (http);
4431}
4432
4433/* For OS X 10.8 and earlier */
4434http_t *_httpCreate(const char *host, int port, http_addrlist_t *addrlist,
4435 http_encryption_t encryption, int family)
4436{ return (http_create(host, port, addrlist, family, encryption, 1,
4437 _HTTP_MODE_CLIENT)); }
4438
4439
ae71f5de
MS
4440#ifdef DEBUG
4441/*
4442 * 'http_debug_hex()' - Do a hex dump of a buffer.
4443 */
4444
4445static void
4446http_debug_hex(const char *prefix, /* I - Prefix for line */
4447 const char *buffer, /* I - Buffer to dump */
4448 int bytes) /* I - Bytes to dump */
4449{
4450 int i, j, /* Looping vars */
4451 ch; /* Current character */
4452 char line[255], /* Line buffer */
4453 *start, /* Start of line after prefix */
4454 *ptr; /* Pointer into line */
4455
4456
f11a948a 4457 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
4458 return;
4459
83e08001 4460 DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
ae71f5de 4461
f11a948a 4462 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
4463 start = line + strlen(line);
4464
4465 for (i = 0; i < bytes; i += 16)
4466 {
4467 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
4468 sprintf(ptr, "%02X", buffer[i + j] & 255);
4469
4470 while (j < 16)
4471 {
5a9febac 4472 memcpy(ptr, " ", 3);
ae71f5de
MS
4473 ptr += 2;
4474 j ++;
4475 }
4476
5a9febac 4477 memcpy(ptr, " ", 3);
ae71f5de
MS
4478 ptr += 2;
4479
4480 for (j = 0; j < 16 && (i + j) < bytes; j ++)
4481 {
4482 ch = buffer[i + j] & 255;
4483
4484 if (ch < ' ' || ch >= 127)
4485 ch = '.';
4486
4487 *ptr++ = ch;
4488 }
4489
4490 *ptr = '\0';
4491 DEBUG_puts(line);
4492 }
4493}
4494#endif /* DEBUG */
4495
4496
ef416fc2 4497/*
4498 * 'http_field()' - Return the field index for a field name.
4499 */
4500
ae71f5de
MS
4501static http_field_t /* O - Field index */
4502http_field(const char *name) /* I - String name */
ef416fc2 4503{
ae71f5de 4504 int i; /* Looping var */
ef416fc2 4505
4506
4507 for (i = 0; i < HTTP_FIELD_MAX; i ++)
88f9aafc 4508 if (_cups_strcasecmp(name, http_fields[i]) == 0)
ef416fc2 4509 return ((http_field_t)i);
4510
4511 return (HTTP_FIELD_UNKNOWN);
4512}
4513
4514
0fa6c7fa
MS
4515/*
4516 * 'http_read()' - Read a buffer from a HTTP connection.
4517 *
4518 * This function does the low-level read from the socket, retrying and timing
4519 * out as needed.
4520 */
4521
4522static ssize_t /* O - Number of bytes read or -1 on error */
4523http_read(http_t *http, /* I - Connection to server */
4524 char *buffer, /* I - Buffer */
4525 size_t length) /* I - Maximum bytes to read */
4526{
4527 ssize_t bytes; /* Bytes read */
4528
4529
4530 DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
4531 buffer, CUPS_LLCAST length));
4532
4533 if (!http->blocking)
4534 {
4535 while (!httpWait(http, http->wait_value))
4536 {
4537 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4538 continue;
4539
4540 DEBUG_puts("2http_read: Timeout.");
4541 return (0);
4542 }
4543 }
4544
4545 DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
4546
4547 do
4548 {
4549#ifdef HAVE_SSL
4550 if (http->tls)
4551 bytes = http_read_ssl(http, buffer, length);
4552 else
4553#endif /* HAVE_SSL */
4554 bytes = recv(http->fd, buffer, length, 0);
4555
4556 if (bytes < 0)
4557 {
4558#ifdef WIN32
4559 if (WSAGetLastError() != WSAEINTR)
4560 {
4561 http->error = WSAGetLastError();
4562 return (-1);
4563 }
4564 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4565 {
4566 if (!http->timeout_cb ||
4567 !(*http->timeout_cb)(http, http->timeout_data))
4568 {
4569 http->error = WSAEWOULDBLOCK;
4570 return (-1);
4571 }
4572 }
4573#else
4574 DEBUG_printf(("2http_read: %s", strerror(errno)));
4575
4576 if (errno == EWOULDBLOCK || errno == EAGAIN)
4577 {
4578 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
4579 {
4580 http->error = errno;
4581 return (-1);
4582 }
4583 else if (!http->timeout_cb && errno != EAGAIN)
4584 {
4585 http->error = errno;
4586 return (-1);
4587 }
4588 }
4589 else if (errno != EINTR)
4590 {
4591 http->error = errno;
4592 return (-1);
4593 }
4594#endif /* WIN32 */
4595 }
4596 }
4597 while (bytes < 0);
4598
4599 DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
4600 CUPS_LLCAST bytes));
4601#ifdef DEBUG
4602 if (bytes > 0)
6961465f 4603 http_debug_hex("http_read", buffer, (int)bytes);
0fa6c7fa
MS
4604#endif /* DEBUG */
4605
4606 if (bytes < 0)
4607 {
4608#ifdef WIN32
4609 if (WSAGetLastError() == WSAEINTR)
4610 bytes = 0;
4611 else
4612 http->error = WSAGetLastError();
4613#else
4614 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
4615 bytes = 0;
4616 else
4617 http->error = errno;
4618#endif /* WIN32 */
4619 }
4620 else if (bytes == 0)
4621 {
4622 http->error = EPIPE;
4623 return (0);
4624 }
4625
4626 return (bytes);
4627}
4628
4629
4630/*
4631 * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
4632 *
4633 * This function reads data from the HTTP buffer or from the socket, as needed.
4634 */
4635
4636static ssize_t /* O - Number of bytes read or -1 on error */
4637http_read_buffered(http_t *http, /* I - Connection to server */
4638 char *buffer, /* I - Buffer */
4639 size_t length) /* I - Maximum bytes to read */
4640{
4641 ssize_t bytes; /* Bytes read */
4642
4643
4644 DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT
4645 ") used=%d",
4646 http, buffer, CUPS_LLCAST length, http->used));
4647
4648 if (http->used > 0)
4649 {
4650 if (length > (size_t)http->used)
4651 bytes = (size_t)http->used;
4652 else
4653 bytes = length;
4654
4655 DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
4656 (int)bytes));
4657
4658 memcpy(buffer, http->buffer, bytes);
4659 http->used -= (int)bytes;
4660
4661 if (http->used > 0)
4662 memmove(http->buffer, http->buffer + bytes, http->used);
4663 }
4664 else
4665 bytes = http_read(http, buffer, length);
4666
4667 return (bytes);
4668}
4669
4670
4671/*
4672 * 'http_read_chunk()' - Read a chunk from a HTTP connection.
4673 *
4674 * This function reads and validates the chunk length, then does a buffered read
4675 * returning the number of bytes placed in the buffer.
4676 */
4677
4678static ssize_t /* O - Number of bytes read or -1 on error */
4679http_read_chunk(http_t *http, /* I - Connection to server */
4680 char *buffer, /* I - Buffer */
4681 size_t length) /* I - Maximum bytes to read */
4682{
4683 DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
4684 http, buffer, CUPS_LLCAST length));
4685
4686 if (http->data_remaining <= 0)
4687 {
4688 char len[32]; /* Length string */
4689
4690 if (!httpGets(len, sizeof(len), http))
4691 {
4692 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4693 return (0);
4694 }
4695
4696 if (!len[0])
4697 {
4698 DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
4699 if (!httpGets(len, sizeof(len), http))
4700 {
4701 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4702 return (0);
4703 }
4704 }
4705
4706 http->data_remaining = strtoll(len, NULL, 16);
4707
4708 if (http->data_remaining < 0)
4709 {
4710 DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
4711 CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
4712 return (0);
4713 }
4714
4715 DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
4716 len, CUPS_LLCAST http->data_remaining));
4717
4718 if (http->data_remaining == 0)
4719 {
4720 /*
4721 * 0-length chunk, grab trailing blank line...
4722 */
4723
4724 httpGets(len, sizeof(len), http);
4725 }
4726 }
4727
4728 DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
4729 CUPS_LLCAST http->data_remaining));
4730
4731 if (http->data_remaining <= 0)
4732 return (0);
4733 else if (length > (size_t)http->data_remaining)
4734 length = (size_t)http->data_remaining;
4735
4736 return (http_read_buffered(http, buffer, length));
4737}
4738
4739
ef416fc2 4740#ifdef HAVE_SSL
4741/*
4742 * 'http_read_ssl()' - Read from a SSL/TLS connection.
4743 */
4744
4745static int /* O - Bytes read */
568fa3fa 4746http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 4747 char *buf, /* I - Buffer to store data */
4748 int len) /* I - Length of buffer */
4749{
4750# if defined(HAVE_LIBSSL)
4751 return (SSL_read((SSL *)(http->tls), buf, len));
4752
4753# elif defined(HAVE_GNUTLS)
ef55b745
MS
4754 ssize_t result; /* Return value */
4755
4756
7cf5915e 4757 result = gnutls_record_recv(http->tls, buf, len);
ef55b745
MS
4758
4759 if (result < 0 && !errno)
4760 {
4761 /*
4762 * Convert GNU TLS error to errno value...
4763 */
4764
4765 switch (result)
4766 {
4767 case GNUTLS_E_INTERRUPTED :
4768 errno = EINTR;
4769 break;
4770
4771 case GNUTLS_E_AGAIN :
4772 errno = EAGAIN;
4773 break;
4774
4775 default :
4776 errno = EPIPE;
4777 break;
4778 }
4779
4780 result = -1;
4781 }
4782
4783 return ((int)result);
ef416fc2 4784
4785# elif defined(HAVE_CDSASSL)
fa73b229 4786 int result; /* Return value */
ef416fc2 4787 OSStatus error; /* Error info */
4788 size_t processed; /* Number of bytes processed */
4789
4790
7cf5915e 4791 error = SSLRead(http->tls, buf, len, &processed);
83e08001
MS
4792 DEBUG_printf(("6http_read_ssl: error=%d, processed=%d", (int)error,
4793 (int)processed));
fa73b229 4794 switch (error)
ef416fc2 4795 {
fa73b229 4796 case 0 :
4797 result = (int)processed;
4798 break;
84315f46 4799
fa73b229 4800 case errSSLWouldBlock :
b423cd4c 4801 if (processed)
4802 result = (int)processed;
4803 else
4804 {
4805 result = -1;
83e08001 4806 errno = EINTR;
b423cd4c 4807 }
fa73b229 4808 break;
84315f46
MS
4809
4810 case errSSLClosedGraceful :
fa73b229 4811 default :
84315f46
MS
4812 if (processed)
4813 result = (int)processed;
4814 else
4815 {
4816 result = -1;
83e08001 4817 errno = EPIPE;
84315f46 4818 }
fa73b229 4819 break;
ef416fc2 4820 }
fa73b229 4821
4822 return (result);
83e08001 4823
cc754834
MS
4824# elif defined(HAVE_SSPISSL)
4825 return _sspiRead((_sspi_struct_t*) http->tls, buf, len);
ef416fc2 4826# endif /* HAVE_LIBSSL */
4827}
4828#endif /* HAVE_SSL */
4829
4830
4831/*
4832 * 'http_send()' - Send a request with all fields and the trailing blank line.
4833 */
4834
a469f8a5
MS
4835static int /* O - 0 on success, non-zero on error */
4836http_send(http_t *http, /* I - Connection to server */
4837 http_state_t request, /* I - Request code */
4838 const char *uri) /* I - URI */
ef416fc2 4839{
a469f8a5
MS
4840 int i; /* Looping var */
4841 char buf[1024]; /* Encoded URI buffer */
4842 const char *value; /* Field value */
4843 static const char * const codes[] = /* Request code strings */
4844 {
ef416fc2 4845 NULL,
4846 "OPTIONS",
4847 "GET",
4848 NULL,
4849 "HEAD",
4850 "POST",
4851 NULL,
4852 NULL,
4853 "PUT",
4854 NULL,
4855 "DELETE",
4856 "TRACE",
a469f8a5
MS
4857 "CLOSE",
4858 NULL,
4859 NULL
ef416fc2 4860 };
ef416fc2 4861
4862
cb7f98ee 4863 DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 4864 http, codes[request], uri));
4865
4866 if (http == NULL || uri == NULL)
4867 return (-1);
4868
4869 /*
4870 * Set the User-Agent field if it isn't already...
4871 */
4872
4873 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
db8b865d
MS
4874 {
4875 if (http->default_user_agent)
4876 httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent);
4877 else
4878 httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent());
4879 }
ef416fc2 4880
a469f8a5
MS
4881 /*
4882 * Set the Accept-Encoding field if it isn't already...
4883 */
4884
c1420c87
MS
4885 if (!http->accept_encoding && http->default_accept_encoding)
4886 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
4887 http->default_accept_encoding);
a469f8a5 4888
ef416fc2 4889 /*
4890 * Encode the URI as needed...
4891 */
4892
839a51c8 4893 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 4894
4895 /*
4896 * See if we had an error the last time around; if so, reconnect...
4897 */
4898
cb7f98ee
MS
4899 if (http->fd < 0 || http->status == HTTP_STATUS_ERROR ||
4900 http->status >= HTTP_STATUS_BAD_REQUEST)
4901 {
4902 DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d",
4903 http->fd, http->status, http->tls_upgrade));
4904
4905 if (httpReconnect2(http, 30000, NULL))
fa73b229 4906 return (-1);
cb7f98ee 4907 }
ef416fc2 4908
d09495fa 4909 /*
4910 * Flush any written data that is pending...
4911 */
4912
4913 if (http->wused)
536bc2c6
MS
4914 {
4915 if (httpFlushWrite(http) < 0)
cb7f98ee 4916 if (httpReconnect2(http, 30000, NULL))
536bc2c6
MS
4917 return (-1);
4918 }
d09495fa 4919
ef416fc2 4920 /*
4921 * Send the request header...
4922 */
4923
d09495fa 4924 http->state = request;
a469f8a5 4925 http->data_encoding = HTTP_ENCODING_FIELDS;
d09495fa 4926
cb7f98ee 4927 if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT)
ef416fc2 4928 http->state ++;
4929
cb7f98ee 4930 http->status = HTTP_STATUS_CONTINUE;
ef416fc2 4931
4932#ifdef HAVE_SSL
cb7f98ee 4933 if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
ef416fc2 4934 {
4935 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
a469f8a5 4936 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
ef416fc2 4937 }
4938#endif /* HAVE_SSL */
4939
4940 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
4941 {
cb7f98ee 4942 http->status = HTTP_STATUS_ERROR;
ef416fc2 4943 return (-1);
4944 }
4945
4946 for (i = 0; i < HTTP_FIELD_MAX; i ++)
a469f8a5 4947 if ((value = httpGetField(http, i)) != NULL && *value)
ef416fc2 4948 {
cb7f98ee 4949 DEBUG_printf(("5http_send: %s: %s", http_fields[i], value));
ef416fc2 4950
37e7e6e0
MS
4951 if (i == HTTP_FIELD_HOST)
4952 {
a469f8a5
MS
4953 if (httpPrintf(http, "Host: %s:%d\r\n", value,
4954 httpAddrPort(http->hostaddr)) < 1)
37e7e6e0 4955 {
cb7f98ee 4956 http->status = HTTP_STATUS_ERROR;
37e7e6e0
MS
4957 return (-1);
4958 }
4959 }
a469f8a5 4960 else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
ef416fc2 4961 {
cb7f98ee 4962 http->status = HTTP_STATUS_ERROR;
ef416fc2 4963 return (-1);
4964 }
4965 }
4966
4967 if (http->cookie)
4968 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
4969 {
cb7f98ee 4970 http->status = HTTP_STATUS_ERROR;
ef416fc2 4971 return (-1);
4972 }
4973
cb7f98ee
MS
4974 DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect,
4975 http->mode, http->state));
4976
4977 if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT &&
4978 (http->state == HTTP_STATE_POST_RECV ||
4979 http->state == HTTP_STATE_PUT_RECV))
b423cd4c 4980 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
4981 {
cb7f98ee 4982 http->status = HTTP_STATUS_ERROR;
b423cd4c 4983 return (-1);
4984 }
4985
ef416fc2 4986 if (httpPrintf(http, "\r\n") < 1)
4987 {
cb7f98ee 4988 http->status = HTTP_STATUS_ERROR;
ef416fc2 4989 return (-1);
4990 }
4991
536bc2c6
MS
4992 if (httpFlushWrite(http) < 0)
4993 return (-1);
4994
a469f8a5 4995 http_set_length(http);
ef416fc2 4996 httpClearFields(http);
4997
f7deaa1a 4998 /*
b94498cf 4999 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 5000 */
5001
ef55b745
MS
5002 if (http->field_authorization && http->authstring &&
5003 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 5004 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 5005 {
5006 http->_authstring[0] = '\0';
5007
5008 if (http->authstring != http->_authstring)
5009 free(http->authstring);
ef55b745 5010
f7deaa1a 5011 http->authstring = http->_authstring;
5012 }
5013
ef416fc2 5014 return (0);
5015}
5016
5017
5018#ifdef HAVE_SSL
c1420c87 5019# if defined(HAVE_CDSASSL)
7cf5915e
MS
5020/*
5021 * 'http_set_credentials()' - Set the SSL/TLS credentials.
5022 */
5023
5024static int /* O - Status of connection */
5025http_set_credentials(http_t *http) /* I - Connection to server */
5026{
5027 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
7cf5915e
MS
5028 OSStatus error = 0; /* Error code */
5029 http_tls_credentials_t credentials = NULL;
5030 /* TLS credentials */
7cf5915e
MS
5031
5032
5033 DEBUG_printf(("7http_set_credentials(%p)", http));
5034
7cf5915e
MS
5035 /*
5036 * Prefer connection specific credentials...
5037 */
5038
5039 if ((credentials = http->tls_credentials) == NULL)
5040 credentials = cg->tls_credentials;
5041
7cf5915e
MS
5042 if (credentials)
5043 {
5044 error = SSLSetCertificate(http->tls, credentials);
5045 DEBUG_printf(("4http_set_credentials: SSLSetCertificate, error=%d",
5046 (int)error));
5047 }
5048 else
5049 DEBUG_puts("4http_set_credentials: No credentials to set.");
5050
5051 return (error);
7cf5915e 5052}
c1420c87 5053# endif /* HAVE_CDSASSL */
9b66acc5 5054#endif /* HAVE_SSL */
7cf5915e
MS
5055
5056
a469f8a5
MS
5057/*
5058 * 'http_set_length()' - Set the data_encoding and data_remaining values.
5059 */
5060
5061static off_t /* O - Remainder or -1 on error */
5062http_set_length(http_t *http) /* I - Connection */
5063{
5064 off_t remaining; /* Remainder */
5065
5066
5067 DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", http, http->mode,
cb7f98ee 5068 http_state_string(http->state)));
a469f8a5
MS
5069
5070 if ((remaining = httpGetLength2(http)) >= 0)
5071 {
5072 if (http->mode == _HTTP_MODE_SERVER &&
5073 http->state != HTTP_STATE_GET_SEND &&
c41769ff 5074 http->state != HTTP_STATE_PUT &&
a469f8a5
MS
5075 http->state != HTTP_STATE_POST &&
5076 http->state != HTTP_STATE_POST_SEND)
5077 {
5078 DEBUG_puts("1http_set_length: Not setting data_encoding/remaining.");
5079 return (remaining);
5080 }
5081
5082 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING],
5083 "chunked"))
5084 {
5085 DEBUG_puts("1http_set_length: Setting data_encoding to "
5086 "HTTP_ENCODING_CHUNKED.");
5087 http->data_encoding = HTTP_ENCODING_CHUNKED;
5088 }
5089 else
5090 {
5091 DEBUG_puts("1http_set_length: Setting data_encoding to "
5092 "HTTP_ENCODING_LENGTH.");
5093 http->data_encoding = HTTP_ENCODING_LENGTH;
5094 }
5095
5096 DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".",
5097 CUPS_LLCAST remaining));
5098 http->data_remaining = remaining;
5099
5100 if (remaining <= INT_MAX)
5101 http->_data_remaining = remaining;
5102 else
5103 http->_data_remaining = INT_MAX;
5104 }
5105
5106 return (remaining);
5107}
5108
85dda01c
MS
5109/*
5110 * 'http_set_timeout()' - Set the socket timeout values.
5111 */
5112
5113static void
5114http_set_timeout(int fd, /* I - File descriptor */
5115 double timeout) /* I - Timeout in seconds */
5116{
5117#ifdef WIN32
5118 DWORD tv = (DWORD)(timeout * 1000);
5119 /* Timeout in milliseconds */
5120
db8b865d
MS
5121 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
5122 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
85dda01c
MS
5123
5124#else
5125 struct timeval tv; /* Timeout in secs and usecs */
5126
5127 tv.tv_sec = (int)timeout;
5128 tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
5129
db8b865d
MS
5130 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
5131 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
85dda01c
MS
5132#endif /* WIN32 */
5133}
5134
5135
5136/*
5137 * 'http_set_wait()' - Set the default wait value for reads.
5138 */
5139
5140static void
5141http_set_wait(http_t *http) /* I - Connection to server */
5142{
5143 if (http->blocking)
5144 {
5145 http->wait_value = (int)(http->timeout_value * 1000);
5146
5147 if (http->wait_value <= 0)
5148 http->wait_value = 60000;
5149 }
5150 else
5151 http->wait_value = 10000;
5152}
5153
5154
9b66acc5 5155#ifdef HAVE_SSL
ef416fc2 5156/*
5157 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
5158 */
5159
a4845881 5160static int /* O - 0 on success, -1 on failure */
568fa3fa 5161http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 5162{
12f89d24
MS
5163 char hostname[256], /* Hostname */
5164 *hostptr; /* Pointer into hostname */
7cf5915e 5165
ef416fc2 5166# ifdef HAVE_LIBSSL
a4845881
MS
5167 SSL_CTX *context; /* Context for encryption */
5168 BIO *bio; /* BIO data */
5169 const char *message = NULL;/* Error message */
ef416fc2 5170# elif defined(HAVE_GNUTLS)
a4845881 5171 int status; /* Status of handshake */
ef416fc2 5172 gnutls_certificate_client_credentials *credentials;
89d46774 5173 /* TLS credentials */
ef416fc2 5174# elif defined(HAVE_CDSASSL)
0fa6c7fa
MS
5175 _cups_globals_t *cg = _cupsGlobals();
5176 /* Pointer to library globals */
a4845881 5177 OSStatus error; /* Error code */
a4845881 5178 const char *message = NULL;/* Error message */
a4845881
MS
5179 cups_array_t *credentials; /* Credentials array */
5180 cups_array_t *names; /* CUPS distinguished names */
5181 CFArrayRef dn_array; /* CF distinguished names array */
5182 CFIndex count; /* Number of credentials */
5183 CFDataRef data; /* Certificate data */
5184 int i; /* Looping var */
5185 http_credential_t *credential; /* Credential data */
cc754834 5186# elif defined(HAVE_SSPISSL)
a4845881
MS
5187 TCHAR username[256]; /* Username returned from GetUserName() */
5188 TCHAR commonName[256];/* Common name for certificate */
5189 DWORD dwSize; /* 32 bit size */
ef416fc2 5190# endif /* HAVE_LIBSSL */
5191
5192
e07d4801 5193 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 5194
7cf5915e 5195 /*
c1420c87 5196 * Get the hostname to use for SSL...
7cf5915e
MS
5197 */
5198
5199 if (httpAddrLocalhost(http->hostaddr))
12f89d24 5200 {
12f89d24
MS
5201 strlcpy(hostname, "localhost", sizeof(hostname));
5202 }
7cf5915e 5203 else
12f89d24
MS
5204 {
5205 /*
c1420c87 5206 * Otherwise make sure the hostname we have does not end in a trailing dot.
12f89d24
MS
5207 */
5208
12f89d24
MS
5209 strlcpy(hostname, http->hostname, sizeof(hostname));
5210 if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
5211 *hostptr == '.')
5212 *hostptr = '\0';
5213 }
dcb445bc 5214
ef416fc2 5215# ifdef HAVE_LIBSSL
5216 context = SSL_CTX_new(SSLv23_client_method());
5217
5218 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
5219
411affcf 5220 bio = BIO_new(_httpBIOMethods());
5221 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
5222
7cf5915e 5223 http->tls = SSL_new(context);
a4845881 5224 SSL_set_bio(http->tls, bio, bio);
ef416fc2 5225
a29fd7dd 5226# ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
dcb445bc 5227 SSL_set_tlsext_host_name(http->tls, hostname);
a29fd7dd 5228# endif /* HAVE_SSL_SET_TLSEXT_HOST_NAME */
dcb445bc 5229
7cf5915e 5230 if (SSL_connect(http->tls) != 1)
ef416fc2 5231 {
ef416fc2 5232 unsigned long error; /* Error code */
5233
5234 while ((error = ERR_get_error()) != 0)
a4845881
MS
5235 {
5236 message = ERR_error_string(error, NULL);
5237 DEBUG_printf(("8http_setup_ssl: %s", message));
5238 }
ef416fc2 5239
5240 SSL_CTX_free(context);
7cf5915e
MS
5241 SSL_free(http->tls);
5242 http->tls = NULL;
ef416fc2 5243
5244# ifdef WIN32
5245 http->error = WSAGetLastError();
5246# else
5247 http->error = errno;
5248# endif /* WIN32 */
cb7f98ee 5249 http->status = HTTP_STATUS_ERROR;
ef416fc2 5250
a4845881
MS
5251 if (!message)
5252 message = _("Unable to establish a secure connection to host.");
5253
e924ce80 5254 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
a4845881
MS
5255
5256 return (-1);
ef416fc2 5257 }
5258
5259# elif defined(HAVE_GNUTLS)
ef416fc2 5260 credentials = (gnutls_certificate_client_credentials *)
5261 malloc(sizeof(gnutls_certificate_client_credentials));
5262 if (credentials == NULL)
5263 {
a4845881
MS
5264 DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s",
5265 strerror(errno)));
5266 http->error = errno;
cb7f98ee
MS
5267 http->status = HTTP_STATUS_ERROR;
5268 _cupsSetHTTPError(HTTP_STATUS_ERROR);
ef416fc2 5269
5270 return (-1);
5271 }
5272
5273 gnutls_certificate_allocate_credentials(credentials);
5274
7cf5915e
MS
5275 gnutls_init(&http->tls, GNUTLS_CLIENT);
5276 gnutls_set_default_priority(http->tls);
dcb445bc
MS
5277 gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname,
5278 strlen(hostname));
7cf5915e
MS
5279 gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);
5280 gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr)http);
5281 gnutls_transport_set_pull_function(http->tls, _httpReadGNUTLS);
5282 gnutls_transport_set_push_function(http->tls, _httpWriteGNUTLS);
ef416fc2 5283
a4845881 5284 while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
ef416fc2 5285 {
a4845881
MS
5286 DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)",
5287 status, gnutls_strerror(status)));
ef416fc2 5288
a4845881
MS
5289 if (gnutls_error_is_fatal(status))
5290 {
5291 http->error = EIO;
cb7f98ee 5292 http->status = HTTP_STATUS_ERROR;
85b5d1df 5293
6961465f 5294 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);
a4845881
MS
5295
5296 gnutls_deinit(http->tls);
5297 gnutls_certificate_free_credentials(*credentials);
5298 free(credentials);
5299 http->tls = NULL;
5300
5301 return (-1);
5302 }
ef416fc2 5303 }
5304
7cf5915e 5305 http->tls_credentials = credentials;
ef416fc2 5306
5307# elif defined(HAVE_CDSASSL)
c1420c87
MS
5308 if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
5309 kSSLStreamType)) == NULL)
e53920b9 5310 {
c1420c87
MS
5311 DEBUG_puts("4http_setup_ssl: SSLCreateContext failed.");
5312 http->error = errno = ENOMEM;
cb7f98ee
MS
5313 http->status = HTTP_STATUS_ERROR;
5314 _cupsSetHTTPError(HTTP_STATUS_ERROR);
e53920b9 5315
89d46774 5316 return (-1);
e53920b9 5317 }
ef416fc2 5318
7cf5915e
MS
5319 error = SSLSetConnection(http->tls, http);
5320 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error));
5321
5322 if (!error)
5323 {
5324 error = SSLSetIOFuncs(http->tls, _httpReadCDSA, _httpWriteCDSA);
5325 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error));
5326 }
5327
7cf5915e
MS
5328 if (!error)
5329 {
c1420c87
MS
5330 error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth,
5331 true);
5332 DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d",
10ddcf65
MS
5333 (int)error));
5334 }
5335
ef416fc2 5336 if (!error)
7cf5915e
MS
5337 {
5338 if (cg->client_cert_cb)
5339 {
5340 error = SSLSetSessionOption(http->tls,
5341 kSSLSessionOptionBreakOnCertRequested, true);
5342 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, "
5343 "error=%d", (int)error));
5344 }
5345 else
5346 {
5347 error = http_set_credentials(http);
5348 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d",
5349 (int)error));
5350 }
5351 }
5352
10ddcf65
MS
5353 /*
5354 * Let the server know which hostname/domain we are trying to connect to
5355 * in case it wants to serve up a certificate with a matching common name.
5356 */
5357
ed486911 5358 if (!error)
7cf5915e 5359 {
dcb445bc 5360 error = SSLSetPeerDomainName(http->tls, hostname, strlen(hostname));
7cf5915e
MS
5361
5362 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d",
5363 (int)error));
5364 }
ed486911 5365
ef416fc2 5366 if (!error)
b423cd4c 5367 {
7cf5915e
MS
5368 int done = 0; /* Are we done yet? */
5369
5370 while (!error && !done)
5371 {
5372 error = SSLHandshake(http->tls);
5373
85dda01c 5374 DEBUG_printf(("4http_setup_ssl: SSLHandshake returned %d.", (int)error));
7cf5915e
MS
5375
5376 switch (error)
5377 {
5378 case noErr :
5379 done = 1;
5380 break;
5381
5382 case errSSLWouldBlock :
82cc1f9a
MS
5383 error = noErr; /* Force a retry */
5384 usleep(1000); /* in 1 millisecond */
7cf5915e
MS
5385 break;
5386
5387 case errSSLServerAuthCompleted :
5388 error = 0;
5389 if (cg->server_cert_cb)
5390 {
5391 error = httpCopyCredentials(http, &credentials);
5392 if (!error)
5393 {
5394 error = (cg->server_cert_cb)(http, http->tls, credentials,
5395 cg->server_cert_data);
5396 httpFreeCredentials(credentials);
5397 }
5398
10ddcf65
MS
5399 DEBUG_printf(("4http_setup_ssl: Server certificate callback "
5400 "returned %d.", (int)error));
7cf5915e
MS
5401 }
5402 break;
5403
5404 case errSSLClientCertRequested :
5405 error = 0;
5406
5407 if (cg->client_cert_cb)
5408 {
5409 names = NULL;
82f97232 5410 if (!(error = SSLCopyDistinguishedNames(http->tls, &dn_array)) &&
7cf5915e
MS
5411 dn_array)
5412 {
5413 if ((names = cupsArrayNew(NULL, NULL)) != NULL)
5414 {
5415 for (i = 0, count = CFArrayGetCount(dn_array); i < count; i++)
5416 {
5417 data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i);
5418
82cc1f9a 5419 if ((credential = malloc(sizeof(*credential))) != NULL)
7cf5915e
MS
5420 {
5421 credential->datalen = CFDataGetLength(data);
5422 if ((credential->data = malloc(credential->datalen)))
5423 {
82f97232 5424 memcpy((void *)credential->data, CFDataGetBytePtr(data),
7cf5915e
MS
5425 credential->datalen);
5426 cupsArrayAdd(names, credential);
5427 }
5a9febac
MS
5428 else
5429 free(credential);
7cf5915e
MS
5430 }
5431 }
5432 }
5433
5434 CFRelease(dn_array);
5435 }
5436
5437 if (!error)
5438 {
82f97232 5439 error = (cg->client_cert_cb)(http, http->tls, names,
7cf5915e
MS
5440 cg->client_cert_data);
5441
85dda01c 5442 DEBUG_printf(("4http_setup_ssl: Client certificate callback "
7cf5915e
MS
5443 "returned %d.", (int)error));
5444 }
5445
5446 httpFreeCredentials(names);
5447 }
5448 break;
5449
5450 case errSSLUnknownRootCert :
5451 message = _("Unable to establish a secure connection to host "
5452 "(untrusted certificate).");
5453 break;
5454
5455 case errSSLNoRootCert :
5456 message = _("Unable to establish a secure connection to host "
5457 "(self-signed certificate).");
5458 break;
5459
5460 case errSSLCertExpired :
5461 message = _("Unable to establish a secure connection to host "
5462 "(expired certificate).");
5463 break;
5464
5465 case errSSLCertNotYetValid :
5466 message = _("Unable to establish a secure connection to host "
5467 "(certificate not yet valid).");
5468 break;
5469
5470 case errSSLHostNameMismatch :
5471 message = _("Unable to establish a secure connection to host "
5472 "(host name mismatch).");
5473 break;
5474
5475 case errSSLXCertChainInvalid :
5476 message = _("Unable to establish a secure connection to host "
5477 "(certificate chain invalid).");
5478 break;
5479
5480 case errSSLConnectionRefused :
5481 message = _("Unable to establish a secure connection to host "
5482 "(peer dropped connection before responding).");
5483 break;
5484
5485 default :
5486 break;
5487 }
5488 }
b423cd4c 5489 }
ef416fc2 5490
89d46774 5491 if (error)
ef416fc2 5492 {
5493 http->error = error;
cb7f98ee 5494 http->status = HTTP_STATUS_ERROR;
7cf5915e
MS
5495 errno = ECONNREFUSED;
5496
c1420c87 5497 CFRelease(http->tls);
7cf5915e 5498 http->tls = NULL;
ef416fc2 5499
7cf5915e
MS
5500 /*
5501 * If an error string wasn't set by the callbacks use a generic one...
5502 */
5503
5504 if (!message)
5505#ifdef HAVE_CSSMERRORSTRING
5506 message = cssmErrorString(error);
5507#else
5508 message = _("Unable to establish a secure connection to host.");
5509#endif /* HAVE_CSSMERRORSTRING */
ef416fc2 5510
cb7f98ee 5511 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
ef416fc2 5512
cc754834
MS
5513 return (-1);
5514 }
7cf5915e 5515
cc754834 5516# elif defined(HAVE_SSPISSL)
7cf5915e 5517 http->tls = _sspiAlloc();
cc754834 5518
7cf5915e 5519 if (!http->tls)
a4845881 5520 {
cb7f98ee 5521 _cupsSetHTTPError(HTTP_STATUS_ERROR);
cc754834 5522 return (-1);
83e08001 5523 }
cc754834 5524
7cf5915e
MS
5525 http->tls->sock = http->fd;
5526 dwSize = sizeof(username) / sizeof(TCHAR);
cc754834
MS
5527 GetUserName(username, &dwSize);
5528 _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
5529 sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
5530
7cf5915e
MS
5531 if (!_sspiGetCredentials(http->tls_credentials, L"ClientContainer",
5532 commonName, FALSE))
cc754834 5533 {
7cf5915e
MS
5534 _sspiFree(http->tls_credentials);
5535 http->tls_credentials = NULL;
a4845881
MS
5536
5537 http->error = EIO;
cb7f98ee 5538 http->status = HTTP_STATUS_ERROR;
a4845881 5539
e924ce80 5540 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
a4845881
MS
5541 _("Unable to establish a secure connection to host."), 1);
5542
cc754834
MS
5543 return (-1);
5544 }
5545
c1420c87 5546 _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE);
7cf5915e 5547 _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
cc754834 5548
dcb445bc 5549 if (!_sspiConnect(http->tls_credentials, hostname))
cc754834 5550 {
7cf5915e
MS
5551 _sspiFree(http->tls_credentials);
5552 http->tls_credentials = NULL;
a4845881
MS
5553
5554 http->error = EIO;
cb7f98ee 5555 http->status = HTTP_STATUS_ERROR;
a4845881 5556
e924ce80 5557 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
a4845881
MS
5558 _("Unable to establish a secure connection to host."), 1);
5559
ef416fc2 5560 return (-1);
5561 }
5562# endif /* HAVE_CDSASSL */
5563
ef416fc2 5564 return (0);
5565}
ef416fc2 5566
5567
ef416fc2 5568/*
5569 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
5570 */
5571
5572static void
568fa3fa 5573http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 5574{
5575# ifdef HAVE_LIBSSL
89d46774 5576 SSL_CTX *context; /* Context for encryption */
ef416fc2 5577
a4845881 5578 context = SSL_get_SSL_CTX(http->tls);
ef416fc2 5579
a4845881 5580 SSL_shutdown(http->tls);
ef416fc2 5581 SSL_CTX_free(context);
a4845881 5582 SSL_free(http->tls);
ef416fc2 5583
5584# elif defined(HAVE_GNUTLS)
ef416fc2 5585 gnutls_certificate_client_credentials *credentials;
89d46774 5586 /* TLS credentials */
ef416fc2 5587
7cf5915e 5588 credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials);
ef416fc2 5589
7cf5915e
MS
5590 gnutls_bye(http->tls, GNUTLS_SHUT_RDWR);
5591 gnutls_deinit(http->tls);
ef416fc2 5592 gnutls_certificate_free_credentials(*credentials);
5593 free(credentials);
ef416fc2 5594
5595# elif defined(HAVE_CDSASSL)
7cf5915e 5596 while (SSLClose(http->tls) == errSSLWouldBlock)
b423cd4c 5597 usleep(1000);
5598
c1420c87 5599 CFRelease(http->tls);
89d46774 5600
7cf5915e
MS
5601 if (http->tls_credentials)
5602 CFRelease(http->tls_credentials);
89d46774 5603
cc754834 5604# elif defined(HAVE_SSPISSL)
7cf5915e 5605 _sspiFree(http->tls_credentials);
ef416fc2 5606# endif /* HAVE_LIBSSL */
5607
7cf5915e
MS
5608 http->tls = NULL;
5609 http->tls_credentials = NULL;
ef416fc2 5610}
5611#endif /* HAVE_SSL */
5612
5613
cb7f98ee
MS
5614#ifdef DEBUG
5615/*
5616 * 'http_state_string()' - Return the string associated with a given HTTP state.
5617 */
5618
5619static const char * /* O - State string */
5620http_state_string(http_state_t state) /* I - HTTP state */
5621{
5622 static char buffer[255]; /* Unknown value buffer */
5623 static const char * const states[] = /* State strings */
5624 {
5625 "HTTP_STATE_ERROR",
5626 "HTTP_STATE_WAITING",
5627 "HTTP_STATE_OPTIONS",
5628 "HTTP_STATE_GET",
5629 "HTTP_STATE_GET_SEND",
5630 "HTTP_STATE_HEAD",
5631 "HTTP_STATE_POST",
5632 "HTTP_STATE_POST_RECV",
5633 "HTTP_STATE_POST_SEND",
5634 "HTTP_STATE_PUT",
5635 "HTTP_STATE_PUT_RECV",
5636 "HTTP_STATE_DELETE",
5637 "HTTP_STATE_TRACE",
5638 "HTTP_STATE_CONNECT",
5639 "HTTP_STATE_STATUS",
5640 "HTTP_STATE_UNKNOWN_METHOD",
5641 "HTTP_STATE_UNKNOWN_VERSION"
5642 };
5643
5644 if (state >= HTTP_STATE_ERROR && state <= HTTP_STATE_UNKNOWN_VERSION)
5645 return (states[state - HTTP_STATE_ERROR]);
5646
5647 snprintf(buffer, sizeof(buffer), "??? %d ???", (int)state);
5648 return (buffer);
5649}
5650#endif /* DEBUG */
5651
5652
ef416fc2 5653#ifdef HAVE_SSL
5654/*
5655 * 'http_upgrade()' - Force upgrade to TLS encryption.
5656 */
5657
89d46774 5658static int /* O - Status of connection */
568fa3fa 5659http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 5660{
89d46774 5661 int ret; /* Return value */
5662 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 5663
5664
e07d4801 5665 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 5666
85b5d1df
MS
5667 /*
5668 * Flush the connection to make sure any previous "Upgrade" message
5669 * has been read.
5670 */
5671
5672 httpFlush(http);
5673
ef416fc2 5674 /*
5675 * Copy the HTTP data to a local variable so we can do the OPTIONS
5676 * request without interfering with the existing request data...
5677 */
5678
5679 memcpy(&myhttp, http, sizeof(myhttp));
5680
5681 /*
5682 * Send an OPTIONS request to the server, requiring SSL or TLS
5683 * encryption on the link...
5684 */
5685
cb7f98ee 5686 http->tls_upgrade = 1;
f7deaa1a 5687 http->field_authorization = NULL; /* Don't free the auth string */
5688
b86bc4cf 5689 httpClearFields(http);
5690 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
a469f8a5 5691 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
ef416fc2 5692
b86bc4cf 5693 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 5694 {
5695 /*
5696 * Wait for the secure connection...
5697 */
5698
cb7f98ee 5699 while (httpUpdate(http) == HTTP_STATUS_CONTINUE);
ef416fc2 5700 }
5701
ef416fc2 5702 /*
b86bc4cf 5703 * Restore the HTTP request data...
ef416fc2 5704 */
5705
b86bc4cf 5706 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 5707 http->data_encoding = myhttp.data_encoding;
5708 http->data_remaining = myhttp.data_remaining;
5709 http->_data_remaining = myhttp._data_remaining;
5710 http->expect = myhttp.expect;
5711 http->field_authorization = myhttp.field_authorization;
bc44d920 5712 http->digest_tries = myhttp.digest_tries;
cb7f98ee 5713 http->tls_upgrade = 0;
ef416fc2 5714
5715 /*
5716 * See if we actually went secure...
5717 */
5718
5719 if (!http->tls)
5720 {
5721 /*
5722 * Server does not support HTTP upgrade...
5723 */
5724
e07d4801 5725 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 5726
5727# ifdef WIN32
5728 closesocket(http->fd);
5729# else
5730 close(http->fd);
5731# endif
5732
5733 http->fd = -1;
5734
5735 return (-1);
5736 }
5737 else
5738 return (ret);
5739}
5740#endif /* HAVE_SSL */
5741
5742
ef416fc2 5743/*
5744 * 'http_write()' - Write a buffer to a HTTP connection.
5745 */
ef55b745 5746
0fa6c7fa 5747static ssize_t /* O - Number of bytes written */
568fa3fa 5748http_write(http_t *http, /* I - Connection to server */
f11a948a 5749 const char *buffer, /* I - Buffer for data */
0fa6c7fa 5750 size_t length) /* I - Number of bytes to write */
ef416fc2 5751{
0fa6c7fa
MS
5752 ssize_t tbytes, /* Total bytes sent */
5753 bytes; /* Bytes sent */
ef416fc2 5754
5755
0fa6c7fa
MS
5756 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
5757 buffer, CUPS_LLCAST length));
f11a948a
MS
5758 http->error = 0;
5759 tbytes = 0;
ef416fc2 5760
5761 while (length > 0)
5762 {
12f89d24
MS
5763 DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
5764
85dda01c
MS
5765 if (http->timeout_cb)
5766 {
5767#ifdef HAVE_POLL
5768 struct pollfd pfd; /* Polled file descriptor */
5769#else
5770 fd_set output_set; /* Output ready for write? */
5771 struct timeval timeout; /* Timeout value */
5772#endif /* HAVE_POLL */
5773 int nfds; /* Result from select()/poll() */
5774
5775 do
5776 {
5777#ifdef HAVE_POLL
5778 pfd.fd = http->fd;
5779 pfd.events = POLLOUT;
5780
5781 while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
82cc1f9a
MS
5782 (errno == EINTR || errno == EAGAIN))
5783 /* do nothing */;
85dda01c
MS
5784
5785#else
5786 do
5787 {
5788 FD_ZERO(&output_set);
5789 FD_SET(http->fd, &output_set);
5790
5791 timeout.tv_sec = http->wait_value / 1000;
5792 timeout.tv_usec = 1000 * (http->wait_value % 1000);
5793
5794 nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
5795 }
5796# ifdef WIN32
5797 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
5798 WSAGetLastError() == WSAEWOULDBLOCK));
5799# else
5800 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
5801# endif /* WIN32 */
5802#endif /* HAVE_POLL */
5803
5804 if (nfds < 0)
5805 {
5806 http->error = errno;
5807 return (-1);
5808 }
5809 else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
5810 {
5811#ifdef WIN32
83e08001 5812 http->error = WSAEWOULDBLOCK;
85dda01c
MS
5813#else
5814 http->error = EWOULDBLOCK;
5815#endif /* WIN32 */
5816 return (-1);
5817 }
5818 }
5819 while (nfds <= 0);
5820 }
5821
ef416fc2 5822#ifdef HAVE_SSL
5823 if (http->tls)
5824 bytes = http_write_ssl(http, buffer, length);
5825 else
5826#endif /* HAVE_SSL */
5827 bytes = send(http->fd, buffer, length, 0);
5828
0fa6c7fa
MS
5829 DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
5830 CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
12f89d24 5831
ef416fc2 5832 if (bytes < 0)
5833 {
5834#ifdef WIN32
10d09e33 5835 if (WSAGetLastError() == WSAEINTR)
cc754834 5836 continue;
10d09e33
MS
5837 else if (WSAGetLastError() == WSAEWOULDBLOCK)
5838 {
5839 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
5840 continue;
5841
5842 http->error = WSAGetLastError();
5843 }
5844 else if (WSAGetLastError() != http->error &&
5845 WSAGetLastError() != WSAECONNRESET)
ef416fc2 5846 {
5847 http->error = WSAGetLastError();
5848 continue;
5849 }
10d09e33 5850
ef416fc2 5851#else
10d09e33 5852 if (errno == EINTR)
ef416fc2 5853 continue;
10d09e33
MS
5854 else if (errno == EWOULDBLOCK || errno == EAGAIN)
5855 {
5856 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
5857 continue;
5858 else if (!http->timeout_cb && errno == EAGAIN)
5859 continue;
5860
5861 http->error = errno;
5862 }
ef416fc2 5863 else if (errno != http->error && errno != ECONNRESET)
5864 {
5865 http->error = errno;
5866 continue;
5867 }
5868#endif /* WIN32 */
5869
f8b3a85b
MS
5870 DEBUG_printf(("3http_write: error writing data (%s).",
5871 strerror(http->error)));
ef416fc2 5872
5873 return (-1);
5874 }
5875
5876 buffer += bytes;
5877 tbytes += bytes;
5878 length -= bytes;
5879 }
5880
5881#ifdef DEBUG
ae71f5de 5882 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 5883#endif /* DEBUG */
5884
0fa6c7fa 5885 DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
f8b3a85b 5886
ef416fc2 5887 return (tbytes);
5888}
5889
5890
5891/*
5892 * 'http_write_chunk()' - Write a chunked buffer.
5893 */
5894
0fa6c7fa 5895static ssize_t /* O - Number bytes written */
568fa3fa 5896http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 5897 const char *buffer, /* I - Buffer to write */
0fa6c7fa 5898 size_t length) /* I - Length of buffer */
ef416fc2 5899{
0fa6c7fa
MS
5900 char header[16]; /* Chunk header */
5901 ssize_t bytes; /* Bytes written */
ef416fc2 5902
f11a948a 5903
0fa6c7fa
MS
5904 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
5905 http, buffer, CUPS_LLCAST length));
ef416fc2 5906
5907 /*
5908 * Write the chunk header, data, and trailer.
5909 */
5910
0fa6c7fa
MS
5911 snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
5912 if (http_write(http, header, strlen(header)) < 0)
ef416fc2 5913 {
0fa6c7fa 5914 DEBUG_puts("8http_write_chunk: http_write of length failed.");
ef416fc2 5915 return (-1);
5916 }
5917
5918 if ((bytes = http_write(http, buffer, length)) < 0)
5919 {
0fa6c7fa 5920 DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
ef416fc2 5921 return (-1);
5922 }
5923
5924 if (http_write(http, "\r\n", 2) < 0)
5925 {
0fa6c7fa 5926 DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
ef416fc2 5927 return (-1);
5928 }
5929
5930 return (bytes);
5931}
5932
5933
5934#ifdef HAVE_SSL
5935/*
5936 * 'http_write_ssl()' - Write to a SSL/TLS connection.
5937 */
5938
5939static int /* O - Bytes written */
568fa3fa 5940http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 5941 const char *buf, /* I - Buffer holding data */
5942 int len) /* I - Length of buffer */
5943{
f8b3a85b
MS
5944 ssize_t result; /* Return value */
5945
5946
5947 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
5948
ef416fc2 5949# if defined(HAVE_LIBSSL)
f8b3a85b 5950 result = SSL_write((SSL *)(http->tls), buf, len);
ef416fc2 5951
5952# elif defined(HAVE_GNUTLS)
7cf5915e 5953 result = gnutls_record_send(http->tls, buf, len);
ef55b745
MS
5954
5955 if (result < 0 && !errno)
5956 {
5957 /*
5958 * Convert GNU TLS error to errno value...
5959 */
5960
5961 switch (result)
5962 {
5963 case GNUTLS_E_INTERRUPTED :
5964 errno = EINTR;
5965 break;
5966
5967 case GNUTLS_E_AGAIN :
5968 errno = EAGAIN;
5969 break;
5970
5971 default :
5972 errno = EPIPE;
5973 break;
5974 }
5975
5976 result = -1;
5977 }
5978
ef416fc2 5979# elif defined(HAVE_CDSASSL)
5980 OSStatus error; /* Error info */
5981 size_t processed; /* Number of bytes processed */
5982
5983
7cf5915e 5984 error = SSLWrite(http->tls, buf, len, &processed);
ef416fc2 5985
fa73b229 5986 switch (error)
ef416fc2 5987 {
fa73b229 5988 case 0 :
5989 result = (int)processed;
5990 break;
84315f46 5991
fa73b229 5992 case errSSLWouldBlock :
b423cd4c 5993 if (processed)
5994 result = (int)processed;
5995 else
5996 {
5997 result = -1;
ef55b745 5998 errno = EINTR;
b423cd4c 5999 }
fa73b229 6000 break;
84315f46
MS
6001
6002 case errSSLClosedGraceful :
fa73b229 6003 default :
84315f46
MS
6004 if (processed)
6005 result = (int)processed;
6006 else
6007 {
6008 result = -1;
6009 errno = EPIPE;
6010 }
fa73b229 6011 break;
ef416fc2 6012 }
cc754834 6013# elif defined(HAVE_SSPISSL)
84315f46 6014 return _sspiWrite((_sspi_struct_t *)http->tls, (void *)buf, len);
ef416fc2 6015# endif /* HAVE_LIBSSL */
f8b3a85b
MS
6016
6017 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
6018
6019 return ((int)result);
ef416fc2 6020}
6021#endif /* HAVE_SSL */
6022
6023
6024/*
f2d18633 6025 * End of "$Id$".
ef416fc2 6026 */