]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Changelog.
[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 */
4172
4173
4174 switch (http->coding)
4175 {
4176 case _HTTP_CODING_DEFLATE :
4177 case _HTTP_CODING_GZIP :
4178 do
4179 {
4180 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
4181 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
4182
4183 zerr = deflate(&(http->stream), Z_FINISH);
4184
4185 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
4186 if (http->wused == sizeof(http->wbuffer))
4187 httpFlushWrite(http);
4188 }
4189 while (zerr == Z_OK);
4190
4191 deflateEnd(&(http->stream));
4192
4193 if (http->wused)
4194 httpFlushWrite(http);
4195 break;
4196
4197 case _HTTP_CODING_INFLATE :
4198 case _HTTP_CODING_GUNZIP :
4199 inflateEnd(&(http->stream));
0fa6c7fa
MS
4200 free(http->dbuffer);
4201 http->dbuffer = NULL;
a469f8a5
MS
4202 break;
4203
4204 default :
4205 break;
4206 }
4207
4208 http->coding = _HTTP_CODING_IDENTITY;
4209}
4210
4211
4212/*
4213 * 'http_content_coding_start()' - Start doing content encoding.
4214 */
4215
4216static void
4217http_content_coding_start(
4218 http_t *http, /* I - HTTP connection */
4219 const char *value) /* I - Value of Content-Encoding */
4220{
4221 int zerr; /* Error/status */
4222 _http_coding_t coding; /* Content coding value */
4223
4224
4225 DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http,
4226 value));
4227
4228 if (http->coding != _HTTP_CODING_IDENTITY)
4229 {
4230 DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
4231 http->coding));
4232 return;
4233 }
4234 else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
4235 {
cb7f98ee
MS
4236 if (http->state == HTTP_STATE_GET_SEND ||
4237 http->state == HTTP_STATE_POST_SEND)
a469f8a5
MS
4238 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP :
4239 _HTTP_CODING_GUNZIP;
cb7f98ee
MS
4240 else if (http->state == HTTP_STATE_POST_RECV ||
4241 http->state == HTTP_STATE_PUT_RECV)
a469f8a5
MS
4242 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
4243 _HTTP_CODING_GUNZIP;
4244 else
4245 {
4246 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4247 return;
4248 }
4249 }
4250 else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
4251 {
cb7f98ee
MS
4252 if (http->state == HTTP_STATE_GET_SEND ||
4253 http->state == HTTP_STATE_POST_SEND)
a469f8a5
MS
4254 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
4255 _HTTP_CODING_INFLATE;
cb7f98ee
MS
4256 else if (http->state == HTTP_STATE_POST_RECV ||
4257 http->state == HTTP_STATE_PUT_RECV)
a469f8a5
MS
4258 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
4259 _HTTP_CODING_INFLATE;
4260 else
4261 {
4262 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4263 return;
4264 }
4265 }
4266 else
4267 {
4268 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4269 return;
4270 }
4271
4272 memset(&(http->stream), 0, sizeof(http->stream));
4273
4274 switch (coding)
4275 {
4276 case _HTTP_CODING_DEFLATE :
4277 case _HTTP_CODING_GZIP :
4278 if (http->wused)
4279 httpFlushWrite(http);
4280
db8b865d
MS
4281 /*
4282 * Window size for compression is 11 bits - optimal based on PWG Raster
4283 * sample files on pwg.org. -11 is raw deflate, 27 is gzip, per ZLIB
4284 * documentation.
4285 */
4286
a469f8a5
MS
4287 if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION,
4288 Z_DEFLATED,
db8b865d 4289 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7,
a469f8a5
MS
4290 Z_DEFAULT_STRATEGY)) < Z_OK)
4291 {
cb7f98ee 4292 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
4293 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
4294 return;
4295 }
4296 break;
4297
4298 case _HTTP_CODING_INFLATE :
4299 case _HTTP_CODING_GUNZIP :
0fa6c7fa 4300 if ((http->dbuffer = malloc(HTTP_MAX_BUFFER)) == NULL)
a469f8a5 4301 {
cb7f98ee 4302 http->status = HTTP_STATUS_ERROR;
0fa6c7fa 4303 http->error = errno;
a469f8a5
MS
4304 return;
4305 }
0fa6c7fa 4306
db8b865d
MS
4307 /*
4308 * Window size for decompression is up to 15 bits (maximum supported).
4309 * -15 is raw inflate, 31 is gunzip, per ZLIB documentation.
4310 */
4311
0fa6c7fa 4312 if ((zerr = inflateInit2(&(http->stream),
db8b865d 4313 coding == _HTTP_CODING_INFLATE ? -15 : 31))
0fa6c7fa
MS
4314 < Z_OK)
4315 {
4316 free(http->dbuffer);
4317 http->dbuffer = NULL;
cb7f98ee 4318 http->status = HTTP_STATUS_ERROR;
0fa6c7fa
MS
4319 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
4320 return;
4321 }
4322
4323 http->stream.avail_in = 0;
4324 http->stream.next_in = http->dbuffer;
a469f8a5
MS
4325 break;
4326
4327 default :
4328 break;
4329 }
4330
4331 http->coding = coding;
4332
4333 DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
4334 http->coding));
4335}
4336#endif /* HAVE_LIBZ */
4337
4338
db8b865d
MS
4339/*
4340 * 'http_create()' - Create an unconnected HTTP connection.
4341 */
4342
4343static http_t * /* O - HTTP connection */
4344http_create(
4345 const char *host, /* I - Hostname */
4346 int port, /* I - Port number */
4347 http_addrlist_t *addrlist, /* I - Address list or NULL */
4348 int family, /* I - Address family or AF_UNSPEC */
4349 http_encryption_t encryption, /* I - Encryption to use */
4350 int blocking, /* I - 1 for blocking mode */
4351 _http_mode_t mode) /* I - _HTTP_MODE_CLIENT or _SERVER */
4352{
4353 http_t *http; /* New HTTP connection */
4354 char service[255]; /* Service name */
4355 http_addrlist_t *myaddrlist = NULL; /* My address list */
4356
4357
4358 DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, "
4359 "encryption=%d, blocking=%d, mode=%d)", host, port, addrlist,
4360 family, encryption, blocking, mode));
4361
4362 if (!host && mode == _HTTP_MODE_CLIENT)
4363 return (NULL);
4364
4365 httpInitialize();
4366
4367 /*
4368 * Lookup the host...
4369 */
4370
4371 if (addrlist)
4372 {
4373 myaddrlist = httpAddrCopyList(addrlist);
4374 }
4375 else
4376 {
4377 snprintf(service, sizeof(service), "%d", port);
4378
4379 myaddrlist = httpAddrGetList(host, family, service);
4380 }
4381
4382 if (!myaddrlist)
4383 return (NULL);
4384
4385 /*
4386 * Allocate memory for the structure...
4387 */
4388
4389 if ((http = calloc(sizeof(http_t), 1)) == NULL)
4390 {
cb7f98ee 4391 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
db8b865d
MS
4392 httpAddrFreeList(addrlist);
4393 return (NULL);
4394 }
4395
4396 /*
4397 * Initialize the HTTP data...
4398 */
4399
4400 http->mode = mode;
4401 http->activity = time(NULL);
4402 http->addrlist = myaddrlist;
4403 http->blocking = blocking;
4404 http->fd = -1;
4405#ifdef HAVE_GSSAPI
4406 http->gssctx = GSS_C_NO_CONTEXT;
4407 http->gssname = GSS_C_NO_NAME;
4408#endif /* HAVE_GSSAPI */
cb7f98ee 4409 http->status = HTTP_STATUS_CONTINUE;
db8b865d
MS
4410 http->version = HTTP_VERSION_1_1;
4411
4412 if (host)
4413 strlcpy(http->hostname, host, sizeof(http->hostname));
4414
4415 if (port == 443) /* Always use encryption for https */
4416 http->encryption = HTTP_ENCRYPTION_ALWAYS;
4417 else
4418 http->encryption = encryption;
4419
4420 http_set_wait(http);
4421
4422 /*
4423 * Return the new structure...
4424 */
4425
4426 return (http);
4427}
4428
4429/* For OS X 10.8 and earlier */
4430http_t *_httpCreate(const char *host, int port, http_addrlist_t *addrlist,
4431 http_encryption_t encryption, int family)
4432{ return (http_create(host, port, addrlist, family, encryption, 1,
4433 _HTTP_MODE_CLIENT)); }
4434
4435
ae71f5de
MS
4436#ifdef DEBUG
4437/*
4438 * 'http_debug_hex()' - Do a hex dump of a buffer.
4439 */
4440
4441static void
4442http_debug_hex(const char *prefix, /* I - Prefix for line */
4443 const char *buffer, /* I - Buffer to dump */
4444 int bytes) /* I - Bytes to dump */
4445{
4446 int i, j, /* Looping vars */
4447 ch; /* Current character */
4448 char line[255], /* Line buffer */
4449 *start, /* Start of line after prefix */
4450 *ptr; /* Pointer into line */
4451
4452
f11a948a 4453 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
4454 return;
4455
83e08001 4456 DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
ae71f5de 4457
f11a948a 4458 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
4459 start = line + strlen(line);
4460
4461 for (i = 0; i < bytes; i += 16)
4462 {
4463 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
4464 sprintf(ptr, "%02X", buffer[i + j] & 255);
4465
4466 while (j < 16)
4467 {
5a9febac 4468 memcpy(ptr, " ", 3);
ae71f5de
MS
4469 ptr += 2;
4470 j ++;
4471 }
4472
5a9febac 4473 memcpy(ptr, " ", 3);
ae71f5de
MS
4474 ptr += 2;
4475
4476 for (j = 0; j < 16 && (i + j) < bytes; j ++)
4477 {
4478 ch = buffer[i + j] & 255;
4479
4480 if (ch < ' ' || ch >= 127)
4481 ch = '.';
4482
4483 *ptr++ = ch;
4484 }
4485
4486 *ptr = '\0';
4487 DEBUG_puts(line);
4488 }
4489}
4490#endif /* DEBUG */
4491
4492
ef416fc2 4493/*
4494 * 'http_field()' - Return the field index for a field name.
4495 */
4496
ae71f5de
MS
4497static http_field_t /* O - Field index */
4498http_field(const char *name) /* I - String name */
ef416fc2 4499{
ae71f5de 4500 int i; /* Looping var */
ef416fc2 4501
4502
4503 for (i = 0; i < HTTP_FIELD_MAX; i ++)
88f9aafc 4504 if (_cups_strcasecmp(name, http_fields[i]) == 0)
ef416fc2 4505 return ((http_field_t)i);
4506
4507 return (HTTP_FIELD_UNKNOWN);
4508}
4509
4510
0fa6c7fa
MS
4511/*
4512 * 'http_read()' - Read a buffer from a HTTP connection.
4513 *
4514 * This function does the low-level read from the socket, retrying and timing
4515 * out as needed.
4516 */
4517
4518static ssize_t /* O - Number of bytes read or -1 on error */
4519http_read(http_t *http, /* I - Connection to server */
4520 char *buffer, /* I - Buffer */
4521 size_t length) /* I - Maximum bytes to read */
4522{
4523 ssize_t bytes; /* Bytes read */
4524
4525
4526 DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
4527 buffer, CUPS_LLCAST length));
4528
4529 if (!http->blocking)
4530 {
4531 while (!httpWait(http, http->wait_value))
4532 {
4533 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4534 continue;
4535
4536 DEBUG_puts("2http_read: Timeout.");
4537 return (0);
4538 }
4539 }
4540
4541 DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
4542
4543 do
4544 {
4545#ifdef HAVE_SSL
4546 if (http->tls)
4547 bytes = http_read_ssl(http, buffer, length);
4548 else
4549#endif /* HAVE_SSL */
4550 bytes = recv(http->fd, buffer, length, 0);
4551
4552 if (bytes < 0)
4553 {
4554#ifdef WIN32
4555 if (WSAGetLastError() != WSAEINTR)
4556 {
4557 http->error = WSAGetLastError();
4558 return (-1);
4559 }
4560 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4561 {
4562 if (!http->timeout_cb ||
4563 !(*http->timeout_cb)(http, http->timeout_data))
4564 {
4565 http->error = WSAEWOULDBLOCK;
4566 return (-1);
4567 }
4568 }
4569#else
4570 DEBUG_printf(("2http_read: %s", strerror(errno)));
4571
4572 if (errno == EWOULDBLOCK || errno == EAGAIN)
4573 {
4574 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
4575 {
4576 http->error = errno;
4577 return (-1);
4578 }
4579 else if (!http->timeout_cb && errno != EAGAIN)
4580 {
4581 http->error = errno;
4582 return (-1);
4583 }
4584 }
4585 else if (errno != EINTR)
4586 {
4587 http->error = errno;
4588 return (-1);
4589 }
4590#endif /* WIN32 */
4591 }
4592 }
4593 while (bytes < 0);
4594
4595 DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
4596 CUPS_LLCAST bytes));
4597#ifdef DEBUG
4598 if (bytes > 0)
6961465f 4599 http_debug_hex("http_read", buffer, (int)bytes);
0fa6c7fa
MS
4600#endif /* DEBUG */
4601
4602 if (bytes < 0)
4603 {
4604#ifdef WIN32
4605 if (WSAGetLastError() == WSAEINTR)
4606 bytes = 0;
4607 else
4608 http->error = WSAGetLastError();
4609#else
4610 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
4611 bytes = 0;
4612 else
4613 http->error = errno;
4614#endif /* WIN32 */
4615 }
4616 else if (bytes == 0)
4617 {
4618 http->error = EPIPE;
4619 return (0);
4620 }
4621
4622 return (bytes);
4623}
4624
4625
4626/*
4627 * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
4628 *
4629 * This function reads data from the HTTP buffer or from the socket, as needed.
4630 */
4631
4632static ssize_t /* O - Number of bytes read or -1 on error */
4633http_read_buffered(http_t *http, /* I - Connection to server */
4634 char *buffer, /* I - Buffer */
4635 size_t length) /* I - Maximum bytes to read */
4636{
4637 ssize_t bytes; /* Bytes read */
4638
4639
4640 DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT
4641 ") used=%d",
4642 http, buffer, CUPS_LLCAST length, http->used));
4643
4644 if (http->used > 0)
4645 {
4646 if (length > (size_t)http->used)
4647 bytes = (size_t)http->used;
4648 else
4649 bytes = length;
4650
4651 DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
4652 (int)bytes));
4653
4654 memcpy(buffer, http->buffer, bytes);
4655 http->used -= (int)bytes;
4656
4657 if (http->used > 0)
4658 memmove(http->buffer, http->buffer + bytes, http->used);
4659 }
4660 else
4661 bytes = http_read(http, buffer, length);
4662
4663 return (bytes);
4664}
4665
4666
4667/*
4668 * 'http_read_chunk()' - Read a chunk from a HTTP connection.
4669 *
4670 * This function reads and validates the chunk length, then does a buffered read
4671 * returning the number of bytes placed in the buffer.
4672 */
4673
4674static ssize_t /* O - Number of bytes read or -1 on error */
4675http_read_chunk(http_t *http, /* I - Connection to server */
4676 char *buffer, /* I - Buffer */
4677 size_t length) /* I - Maximum bytes to read */
4678{
4679 DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
4680 http, buffer, CUPS_LLCAST length));
4681
4682 if (http->data_remaining <= 0)
4683 {
4684 char len[32]; /* Length string */
4685
4686 if (!httpGets(len, sizeof(len), http))
4687 {
4688 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4689 return (0);
4690 }
4691
4692 if (!len[0])
4693 {
4694 DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
4695 if (!httpGets(len, sizeof(len), http))
4696 {
4697 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4698 return (0);
4699 }
4700 }
4701
4702 http->data_remaining = strtoll(len, NULL, 16);
4703
4704 if (http->data_remaining < 0)
4705 {
4706 DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
4707 CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
4708 return (0);
4709 }
4710
4711 DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
4712 len, CUPS_LLCAST http->data_remaining));
4713
4714 if (http->data_remaining == 0)
4715 {
4716 /*
4717 * 0-length chunk, grab trailing blank line...
4718 */
4719
4720 httpGets(len, sizeof(len), http);
4721 }
4722 }
4723
4724 DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
4725 CUPS_LLCAST http->data_remaining));
4726
4727 if (http->data_remaining <= 0)
4728 return (0);
4729 else if (length > (size_t)http->data_remaining)
4730 length = (size_t)http->data_remaining;
4731
4732 return (http_read_buffered(http, buffer, length));
4733}
4734
4735
ef416fc2 4736#ifdef HAVE_SSL
4737/*
4738 * 'http_read_ssl()' - Read from a SSL/TLS connection.
4739 */
4740
4741static int /* O - Bytes read */
568fa3fa 4742http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 4743 char *buf, /* I - Buffer to store data */
4744 int len) /* I - Length of buffer */
4745{
4746# if defined(HAVE_LIBSSL)
4747 return (SSL_read((SSL *)(http->tls), buf, len));
4748
4749# elif defined(HAVE_GNUTLS)
ef55b745
MS
4750 ssize_t result; /* Return value */
4751
4752
7cf5915e 4753 result = gnutls_record_recv(http->tls, buf, len);
ef55b745
MS
4754
4755 if (result < 0 && !errno)
4756 {
4757 /*
4758 * Convert GNU TLS error to errno value...
4759 */
4760
4761 switch (result)
4762 {
4763 case GNUTLS_E_INTERRUPTED :
4764 errno = EINTR;
4765 break;
4766
4767 case GNUTLS_E_AGAIN :
4768 errno = EAGAIN;
4769 break;
4770
4771 default :
4772 errno = EPIPE;
4773 break;
4774 }
4775
4776 result = -1;
4777 }
4778
4779 return ((int)result);
ef416fc2 4780
4781# elif defined(HAVE_CDSASSL)
fa73b229 4782 int result; /* Return value */
ef416fc2 4783 OSStatus error; /* Error info */
4784 size_t processed; /* Number of bytes processed */
4785
4786
7cf5915e 4787 error = SSLRead(http->tls, buf, len, &processed);
83e08001
MS
4788 DEBUG_printf(("6http_read_ssl: error=%d, processed=%d", (int)error,
4789 (int)processed));
fa73b229 4790 switch (error)
ef416fc2 4791 {
fa73b229 4792 case 0 :
4793 result = (int)processed;
4794 break;
84315f46 4795
fa73b229 4796 case errSSLWouldBlock :
b423cd4c 4797 if (processed)
4798 result = (int)processed;
4799 else
4800 {
4801 result = -1;
83e08001 4802 errno = EINTR;
b423cd4c 4803 }
fa73b229 4804 break;
84315f46
MS
4805
4806 case errSSLClosedGraceful :
fa73b229 4807 default :
84315f46
MS
4808 if (processed)
4809 result = (int)processed;
4810 else
4811 {
4812 result = -1;
83e08001 4813 errno = EPIPE;
84315f46 4814 }
fa73b229 4815 break;
ef416fc2 4816 }
fa73b229 4817
4818 return (result);
83e08001 4819
cc754834
MS
4820# elif defined(HAVE_SSPISSL)
4821 return _sspiRead((_sspi_struct_t*) http->tls, buf, len);
ef416fc2 4822# endif /* HAVE_LIBSSL */
4823}
4824#endif /* HAVE_SSL */
4825
4826
4827/*
4828 * 'http_send()' - Send a request with all fields and the trailing blank line.
4829 */
4830
a469f8a5
MS
4831static int /* O - 0 on success, non-zero on error */
4832http_send(http_t *http, /* I - Connection to server */
4833 http_state_t request, /* I - Request code */
4834 const char *uri) /* I - URI */
ef416fc2 4835{
a469f8a5
MS
4836 int i; /* Looping var */
4837 char buf[1024]; /* Encoded URI buffer */
4838 const char *value; /* Field value */
4839 static const char * const codes[] = /* Request code strings */
4840 {
ef416fc2 4841 NULL,
4842 "OPTIONS",
4843 "GET",
4844 NULL,
4845 "HEAD",
4846 "POST",
4847 NULL,
4848 NULL,
4849 "PUT",
4850 NULL,
4851 "DELETE",
4852 "TRACE",
a469f8a5
MS
4853 "CLOSE",
4854 NULL,
4855 NULL
ef416fc2 4856 };
ef416fc2 4857
4858
cb7f98ee 4859 DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 4860 http, codes[request], uri));
4861
4862 if (http == NULL || uri == NULL)
4863 return (-1);
4864
4865 /*
4866 * Set the User-Agent field if it isn't already...
4867 */
4868
4869 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
db8b865d
MS
4870 {
4871 if (http->default_user_agent)
4872 httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent);
4873 else
4874 httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent());
4875 }
ef416fc2 4876
a469f8a5
MS
4877 /*
4878 * Set the Accept-Encoding field if it isn't already...
4879 */
4880
c1420c87
MS
4881 if (!http->accept_encoding && http->default_accept_encoding)
4882 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
4883 http->default_accept_encoding);
a469f8a5 4884
ef416fc2 4885 /*
4886 * Encode the URI as needed...
4887 */
4888
839a51c8 4889 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 4890
4891 /*
4892 * See if we had an error the last time around; if so, reconnect...
4893 */
4894
cb7f98ee
MS
4895 if (http->fd < 0 || http->status == HTTP_STATUS_ERROR ||
4896 http->status >= HTTP_STATUS_BAD_REQUEST)
4897 {
4898 DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d",
4899 http->fd, http->status, http->tls_upgrade));
4900
4901 if (httpReconnect2(http, 30000, NULL))
fa73b229 4902 return (-1);
cb7f98ee 4903 }
ef416fc2 4904
d09495fa 4905 /*
4906 * Flush any written data that is pending...
4907 */
4908
4909 if (http->wused)
536bc2c6
MS
4910 {
4911 if (httpFlushWrite(http) < 0)
cb7f98ee 4912 if (httpReconnect2(http, 30000, NULL))
536bc2c6
MS
4913 return (-1);
4914 }
d09495fa 4915
ef416fc2 4916 /*
4917 * Send the request header...
4918 */
4919
d09495fa 4920 http->state = request;
a469f8a5 4921 http->data_encoding = HTTP_ENCODING_FIELDS;
d09495fa 4922
cb7f98ee 4923 if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT)
ef416fc2 4924 http->state ++;
4925
cb7f98ee 4926 http->status = HTTP_STATUS_CONTINUE;
ef416fc2 4927
4928#ifdef HAVE_SSL
cb7f98ee 4929 if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
ef416fc2 4930 {
4931 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
a469f8a5 4932 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
ef416fc2 4933 }
4934#endif /* HAVE_SSL */
4935
4936 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
4937 {
cb7f98ee 4938 http->status = HTTP_STATUS_ERROR;
ef416fc2 4939 return (-1);
4940 }
4941
4942 for (i = 0; i < HTTP_FIELD_MAX; i ++)
a469f8a5 4943 if ((value = httpGetField(http, i)) != NULL && *value)
ef416fc2 4944 {
cb7f98ee 4945 DEBUG_printf(("5http_send: %s: %s", http_fields[i], value));
ef416fc2 4946
37e7e6e0
MS
4947 if (i == HTTP_FIELD_HOST)
4948 {
a469f8a5
MS
4949 if (httpPrintf(http, "Host: %s:%d\r\n", value,
4950 httpAddrPort(http->hostaddr)) < 1)
37e7e6e0 4951 {
cb7f98ee 4952 http->status = HTTP_STATUS_ERROR;
37e7e6e0
MS
4953 return (-1);
4954 }
4955 }
a469f8a5 4956 else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
ef416fc2 4957 {
cb7f98ee 4958 http->status = HTTP_STATUS_ERROR;
ef416fc2 4959 return (-1);
4960 }
4961 }
4962
4963 if (http->cookie)
4964 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
4965 {
cb7f98ee 4966 http->status = HTTP_STATUS_ERROR;
ef416fc2 4967 return (-1);
4968 }
4969
cb7f98ee
MS
4970 DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect,
4971 http->mode, http->state));
4972
4973 if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT &&
4974 (http->state == HTTP_STATE_POST_RECV ||
4975 http->state == HTTP_STATE_PUT_RECV))
b423cd4c 4976 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
4977 {
cb7f98ee 4978 http->status = HTTP_STATUS_ERROR;
b423cd4c 4979 return (-1);
4980 }
4981
ef416fc2 4982 if (httpPrintf(http, "\r\n") < 1)
4983 {
cb7f98ee 4984 http->status = HTTP_STATUS_ERROR;
ef416fc2 4985 return (-1);
4986 }
4987
536bc2c6
MS
4988 if (httpFlushWrite(http) < 0)
4989 return (-1);
4990
a469f8a5 4991 http_set_length(http);
ef416fc2 4992 httpClearFields(http);
4993
f7deaa1a 4994 /*
b94498cf 4995 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 4996 */
4997
ef55b745
MS
4998 if (http->field_authorization && http->authstring &&
4999 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 5000 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 5001 {
5002 http->_authstring[0] = '\0';
5003
5004 if (http->authstring != http->_authstring)
5005 free(http->authstring);
ef55b745 5006
f7deaa1a 5007 http->authstring = http->_authstring;
5008 }
5009
ef416fc2 5010 return (0);
5011}
5012
5013
5014#ifdef HAVE_SSL
c1420c87 5015# if defined(HAVE_CDSASSL)
7cf5915e
MS
5016/*
5017 * 'http_set_credentials()' - Set the SSL/TLS credentials.
5018 */
5019
5020static int /* O - Status of connection */
5021http_set_credentials(http_t *http) /* I - Connection to server */
5022{
5023 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
7cf5915e
MS
5024 OSStatus error = 0; /* Error code */
5025 http_tls_credentials_t credentials = NULL;
5026 /* TLS credentials */
7cf5915e
MS
5027
5028
5029 DEBUG_printf(("7http_set_credentials(%p)", http));
5030
7cf5915e
MS
5031 /*
5032 * Prefer connection specific credentials...
5033 */
5034
5035 if ((credentials = http->tls_credentials) == NULL)
5036 credentials = cg->tls_credentials;
5037
7cf5915e
MS
5038 if (credentials)
5039 {
5040 error = SSLSetCertificate(http->tls, credentials);
5041 DEBUG_printf(("4http_set_credentials: SSLSetCertificate, error=%d",
5042 (int)error));
5043 }
5044 else
5045 DEBUG_puts("4http_set_credentials: No credentials to set.");
5046
5047 return (error);
7cf5915e 5048}
c1420c87 5049# endif /* HAVE_CDSASSL */
9b66acc5 5050#endif /* HAVE_SSL */
7cf5915e
MS
5051
5052
a469f8a5
MS
5053/*
5054 * 'http_set_length()' - Set the data_encoding and data_remaining values.
5055 */
5056
5057static off_t /* O - Remainder or -1 on error */
5058http_set_length(http_t *http) /* I - Connection */
5059{
5060 off_t remaining; /* Remainder */
5061
5062
5063 DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", http, http->mode,
cb7f98ee 5064 http_state_string(http->state)));
a469f8a5
MS
5065
5066 if ((remaining = httpGetLength2(http)) >= 0)
5067 {
5068 if (http->mode == _HTTP_MODE_SERVER &&
5069 http->state != HTTP_STATE_GET_SEND &&
c41769ff 5070 http->state != HTTP_STATE_PUT &&
a469f8a5
MS
5071 http->state != HTTP_STATE_POST &&
5072 http->state != HTTP_STATE_POST_SEND)
5073 {
5074 DEBUG_puts("1http_set_length: Not setting data_encoding/remaining.");
5075 return (remaining);
5076 }
5077
5078 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING],
5079 "chunked"))
5080 {
5081 DEBUG_puts("1http_set_length: Setting data_encoding to "
5082 "HTTP_ENCODING_CHUNKED.");
5083 http->data_encoding = HTTP_ENCODING_CHUNKED;
5084 }
5085 else
5086 {
5087 DEBUG_puts("1http_set_length: Setting data_encoding to "
5088 "HTTP_ENCODING_LENGTH.");
5089 http->data_encoding = HTTP_ENCODING_LENGTH;
5090 }
5091
5092 DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".",
5093 CUPS_LLCAST remaining));
5094 http->data_remaining = remaining;
5095
5096 if (remaining <= INT_MAX)
5097 http->_data_remaining = remaining;
5098 else
5099 http->_data_remaining = INT_MAX;
5100 }
5101
5102 return (remaining);
5103}
5104
85dda01c
MS
5105/*
5106 * 'http_set_timeout()' - Set the socket timeout values.
5107 */
5108
5109static void
5110http_set_timeout(int fd, /* I - File descriptor */
5111 double timeout) /* I - Timeout in seconds */
5112{
5113#ifdef WIN32
5114 DWORD tv = (DWORD)(timeout * 1000);
5115 /* Timeout in milliseconds */
5116
db8b865d
MS
5117 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
5118 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
85dda01c
MS
5119
5120#else
5121 struct timeval tv; /* Timeout in secs and usecs */
5122
5123 tv.tv_sec = (int)timeout;
5124 tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
5125
db8b865d
MS
5126 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
5127 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
85dda01c
MS
5128#endif /* WIN32 */
5129}
5130
5131
5132/*
5133 * 'http_set_wait()' - Set the default wait value for reads.
5134 */
5135
5136static void
5137http_set_wait(http_t *http) /* I - Connection to server */
5138{
5139 if (http->blocking)
5140 {
5141 http->wait_value = (int)(http->timeout_value * 1000);
5142
5143 if (http->wait_value <= 0)
5144 http->wait_value = 60000;
5145 }
5146 else
5147 http->wait_value = 10000;
5148}
5149
5150
9b66acc5 5151#ifdef HAVE_SSL
ef416fc2 5152/*
5153 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
5154 */
5155
a4845881 5156static int /* O - 0 on success, -1 on failure */
568fa3fa 5157http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 5158{
12f89d24
MS
5159 char hostname[256], /* Hostname */
5160 *hostptr; /* Pointer into hostname */
7cf5915e 5161
ef416fc2 5162# ifdef HAVE_LIBSSL
a4845881
MS
5163 SSL_CTX *context; /* Context for encryption */
5164 BIO *bio; /* BIO data */
5165 const char *message = NULL;/* Error message */
ef416fc2 5166# elif defined(HAVE_GNUTLS)
a4845881 5167 int status; /* Status of handshake */
ef416fc2 5168 gnutls_certificate_client_credentials *credentials;
89d46774 5169 /* TLS credentials */
ef416fc2 5170# elif defined(HAVE_CDSASSL)
0fa6c7fa
MS
5171 _cups_globals_t *cg = _cupsGlobals();
5172 /* Pointer to library globals */
a4845881 5173 OSStatus error; /* Error code */
a4845881 5174 const char *message = NULL;/* Error message */
a4845881
MS
5175 cups_array_t *credentials; /* Credentials array */
5176 cups_array_t *names; /* CUPS distinguished names */
5177 CFArrayRef dn_array; /* CF distinguished names array */
5178 CFIndex count; /* Number of credentials */
5179 CFDataRef data; /* Certificate data */
5180 int i; /* Looping var */
5181 http_credential_t *credential; /* Credential data */
cc754834 5182# elif defined(HAVE_SSPISSL)
a4845881
MS
5183 TCHAR username[256]; /* Username returned from GetUserName() */
5184 TCHAR commonName[256];/* Common name for certificate */
5185 DWORD dwSize; /* 32 bit size */
ef416fc2 5186# endif /* HAVE_LIBSSL */
5187
5188
e07d4801 5189 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 5190
7cf5915e 5191 /*
c1420c87 5192 * Get the hostname to use for SSL...
7cf5915e
MS
5193 */
5194
5195 if (httpAddrLocalhost(http->hostaddr))
12f89d24 5196 {
12f89d24
MS
5197 strlcpy(hostname, "localhost", sizeof(hostname));
5198 }
7cf5915e 5199 else
12f89d24
MS
5200 {
5201 /*
c1420c87 5202 * Otherwise make sure the hostname we have does not end in a trailing dot.
12f89d24
MS
5203 */
5204
12f89d24
MS
5205 strlcpy(hostname, http->hostname, sizeof(hostname));
5206 if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
5207 *hostptr == '.')
5208 *hostptr = '\0';
5209 }
dcb445bc 5210
ef416fc2 5211# ifdef HAVE_LIBSSL
5212 context = SSL_CTX_new(SSLv23_client_method());
5213
5214 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
5215
411affcf 5216 bio = BIO_new(_httpBIOMethods());
5217 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
5218
7cf5915e 5219 http->tls = SSL_new(context);
a4845881 5220 SSL_set_bio(http->tls, bio, bio);
ef416fc2 5221
a29fd7dd 5222# ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
dcb445bc 5223 SSL_set_tlsext_host_name(http->tls, hostname);
a29fd7dd 5224# endif /* HAVE_SSL_SET_TLSEXT_HOST_NAME */
dcb445bc 5225
7cf5915e 5226 if (SSL_connect(http->tls) != 1)
ef416fc2 5227 {
ef416fc2 5228 unsigned long error; /* Error code */
5229
5230 while ((error = ERR_get_error()) != 0)
a4845881
MS
5231 {
5232 message = ERR_error_string(error, NULL);
5233 DEBUG_printf(("8http_setup_ssl: %s", message));
5234 }
ef416fc2 5235
5236 SSL_CTX_free(context);
7cf5915e
MS
5237 SSL_free(http->tls);
5238 http->tls = NULL;
ef416fc2 5239
5240# ifdef WIN32
5241 http->error = WSAGetLastError();
5242# else
5243 http->error = errno;
5244# endif /* WIN32 */
cb7f98ee 5245 http->status = HTTP_STATUS_ERROR;
ef416fc2 5246
a4845881
MS
5247 if (!message)
5248 message = _("Unable to establish a secure connection to host.");
5249
e924ce80 5250 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
a4845881
MS
5251
5252 return (-1);
ef416fc2 5253 }
5254
5255# elif defined(HAVE_GNUTLS)
ef416fc2 5256 credentials = (gnutls_certificate_client_credentials *)
5257 malloc(sizeof(gnutls_certificate_client_credentials));
5258 if (credentials == NULL)
5259 {
a4845881
MS
5260 DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s",
5261 strerror(errno)));
5262 http->error = errno;
cb7f98ee
MS
5263 http->status = HTTP_STATUS_ERROR;
5264 _cupsSetHTTPError(HTTP_STATUS_ERROR);
ef416fc2 5265
5266 return (-1);
5267 }
5268
5269 gnutls_certificate_allocate_credentials(credentials);
5270
7cf5915e
MS
5271 gnutls_init(&http->tls, GNUTLS_CLIENT);
5272 gnutls_set_default_priority(http->tls);
dcb445bc
MS
5273 gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname,
5274 strlen(hostname));
7cf5915e
MS
5275 gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);
5276 gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr)http);
5277 gnutls_transport_set_pull_function(http->tls, _httpReadGNUTLS);
5278 gnutls_transport_set_push_function(http->tls, _httpWriteGNUTLS);
ef416fc2 5279
a4845881 5280 while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
ef416fc2 5281 {
a4845881
MS
5282 DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)",
5283 status, gnutls_strerror(status)));
ef416fc2 5284
a4845881
MS
5285 if (gnutls_error_is_fatal(status))
5286 {
5287 http->error = EIO;
cb7f98ee 5288 http->status = HTTP_STATUS_ERROR;
85b5d1df 5289
6961465f 5290 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);
a4845881
MS
5291
5292 gnutls_deinit(http->tls);
5293 gnutls_certificate_free_credentials(*credentials);
5294 free(credentials);
5295 http->tls = NULL;
5296
5297 return (-1);
5298 }
ef416fc2 5299 }
5300
7cf5915e 5301 http->tls_credentials = credentials;
ef416fc2 5302
5303# elif defined(HAVE_CDSASSL)
c1420c87
MS
5304 if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
5305 kSSLStreamType)) == NULL)
e53920b9 5306 {
c1420c87
MS
5307 DEBUG_puts("4http_setup_ssl: SSLCreateContext failed.");
5308 http->error = errno = ENOMEM;
cb7f98ee
MS
5309 http->status = HTTP_STATUS_ERROR;
5310 _cupsSetHTTPError(HTTP_STATUS_ERROR);
e53920b9 5311
89d46774 5312 return (-1);
e53920b9 5313 }
ef416fc2 5314
7cf5915e
MS
5315 error = SSLSetConnection(http->tls, http);
5316 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error));
5317
5318 if (!error)
5319 {
5320 error = SSLSetIOFuncs(http->tls, _httpReadCDSA, _httpWriteCDSA);
5321 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error));
5322 }
5323
7cf5915e
MS
5324 if (!error)
5325 {
c1420c87
MS
5326 error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth,
5327 true);
5328 DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d",
10ddcf65
MS
5329 (int)error));
5330 }
5331
ef416fc2 5332 if (!error)
7cf5915e
MS
5333 {
5334 if (cg->client_cert_cb)
5335 {
5336 error = SSLSetSessionOption(http->tls,
5337 kSSLSessionOptionBreakOnCertRequested, true);
5338 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, "
5339 "error=%d", (int)error));
5340 }
5341 else
5342 {
5343 error = http_set_credentials(http);
5344 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d",
5345 (int)error));
5346 }
5347 }
5348
10ddcf65
MS
5349 /*
5350 * Let the server know which hostname/domain we are trying to connect to
5351 * in case it wants to serve up a certificate with a matching common name.
5352 */
5353
ed486911 5354 if (!error)
7cf5915e 5355 {
dcb445bc 5356 error = SSLSetPeerDomainName(http->tls, hostname, strlen(hostname));
7cf5915e
MS
5357
5358 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d",
5359 (int)error));
5360 }
ed486911 5361
ef416fc2 5362 if (!error)
b423cd4c 5363 {
7cf5915e
MS
5364 int done = 0; /* Are we done yet? */
5365
5366 while (!error && !done)
5367 {
5368 error = SSLHandshake(http->tls);
5369
85dda01c 5370 DEBUG_printf(("4http_setup_ssl: SSLHandshake returned %d.", (int)error));
7cf5915e
MS
5371
5372 switch (error)
5373 {
5374 case noErr :
5375 done = 1;
5376 break;
5377
5378 case errSSLWouldBlock :
82cc1f9a
MS
5379 error = noErr; /* Force a retry */
5380 usleep(1000); /* in 1 millisecond */
7cf5915e
MS
5381 break;
5382
5383 case errSSLServerAuthCompleted :
5384 error = 0;
5385 if (cg->server_cert_cb)
5386 {
5387 error = httpCopyCredentials(http, &credentials);
5388 if (!error)
5389 {
5390 error = (cg->server_cert_cb)(http, http->tls, credentials,
5391 cg->server_cert_data);
5392 httpFreeCredentials(credentials);
5393 }
5394
10ddcf65
MS
5395 DEBUG_printf(("4http_setup_ssl: Server certificate callback "
5396 "returned %d.", (int)error));
7cf5915e
MS
5397 }
5398 break;
5399
5400 case errSSLClientCertRequested :
5401 error = 0;
5402
5403 if (cg->client_cert_cb)
5404 {
5405 names = NULL;
82f97232 5406 if (!(error = SSLCopyDistinguishedNames(http->tls, &dn_array)) &&
7cf5915e
MS
5407 dn_array)
5408 {
5409 if ((names = cupsArrayNew(NULL, NULL)) != NULL)
5410 {
5411 for (i = 0, count = CFArrayGetCount(dn_array); i < count; i++)
5412 {
5413 data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i);
5414
82cc1f9a 5415 if ((credential = malloc(sizeof(*credential))) != NULL)
7cf5915e
MS
5416 {
5417 credential->datalen = CFDataGetLength(data);
5418 if ((credential->data = malloc(credential->datalen)))
5419 {
82f97232 5420 memcpy((void *)credential->data, CFDataGetBytePtr(data),
7cf5915e
MS
5421 credential->datalen);
5422 cupsArrayAdd(names, credential);
5423 }
5a9febac
MS
5424 else
5425 free(credential);
7cf5915e
MS
5426 }
5427 }
5428 }
5429
5430 CFRelease(dn_array);
5431 }
5432
5433 if (!error)
5434 {
82f97232 5435 error = (cg->client_cert_cb)(http, http->tls, names,
7cf5915e
MS
5436 cg->client_cert_data);
5437
85dda01c 5438 DEBUG_printf(("4http_setup_ssl: Client certificate callback "
7cf5915e
MS
5439 "returned %d.", (int)error));
5440 }
5441
5442 httpFreeCredentials(names);
5443 }
5444 break;
5445
5446 case errSSLUnknownRootCert :
5447 message = _("Unable to establish a secure connection to host "
5448 "(untrusted certificate).");
5449 break;
5450
5451 case errSSLNoRootCert :
5452 message = _("Unable to establish a secure connection to host "
5453 "(self-signed certificate).");
5454 break;
5455
5456 case errSSLCertExpired :
5457 message = _("Unable to establish a secure connection to host "
5458 "(expired certificate).");
5459 break;
5460
5461 case errSSLCertNotYetValid :
5462 message = _("Unable to establish a secure connection to host "
5463 "(certificate not yet valid).");
5464 break;
5465
5466 case errSSLHostNameMismatch :
5467 message = _("Unable to establish a secure connection to host "
5468 "(host name mismatch).");
5469 break;
5470
5471 case errSSLXCertChainInvalid :
5472 message = _("Unable to establish a secure connection to host "
5473 "(certificate chain invalid).");
5474 break;
5475
5476 case errSSLConnectionRefused :
5477 message = _("Unable to establish a secure connection to host "
5478 "(peer dropped connection before responding).");
5479 break;
5480
5481 default :
5482 break;
5483 }
5484 }
b423cd4c 5485 }
ef416fc2 5486
89d46774 5487 if (error)
ef416fc2 5488 {
5489 http->error = error;
cb7f98ee 5490 http->status = HTTP_STATUS_ERROR;
7cf5915e
MS
5491 errno = ECONNREFUSED;
5492
c1420c87 5493 CFRelease(http->tls);
7cf5915e 5494 http->tls = NULL;
ef416fc2 5495
7cf5915e
MS
5496 /*
5497 * If an error string wasn't set by the callbacks use a generic one...
5498 */
5499
5500 if (!message)
5501#ifdef HAVE_CSSMERRORSTRING
5502 message = cssmErrorString(error);
5503#else
5504 message = _("Unable to establish a secure connection to host.");
5505#endif /* HAVE_CSSMERRORSTRING */
ef416fc2 5506
cb7f98ee 5507 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
ef416fc2 5508
cc754834
MS
5509 return (-1);
5510 }
7cf5915e 5511
cc754834 5512# elif defined(HAVE_SSPISSL)
7cf5915e 5513 http->tls = _sspiAlloc();
cc754834 5514
7cf5915e 5515 if (!http->tls)
a4845881 5516 {
cb7f98ee 5517 _cupsSetHTTPError(HTTP_STATUS_ERROR);
cc754834 5518 return (-1);
83e08001 5519 }
cc754834 5520
7cf5915e
MS
5521 http->tls->sock = http->fd;
5522 dwSize = sizeof(username) / sizeof(TCHAR);
cc754834
MS
5523 GetUserName(username, &dwSize);
5524 _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
5525 sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
5526
7cf5915e
MS
5527 if (!_sspiGetCredentials(http->tls_credentials, L"ClientContainer",
5528 commonName, FALSE))
cc754834 5529 {
7cf5915e
MS
5530 _sspiFree(http->tls_credentials);
5531 http->tls_credentials = NULL;
a4845881
MS
5532
5533 http->error = EIO;
cb7f98ee 5534 http->status = HTTP_STATUS_ERROR;
a4845881 5535
e924ce80 5536 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
a4845881
MS
5537 _("Unable to establish a secure connection to host."), 1);
5538
cc754834
MS
5539 return (-1);
5540 }
5541
c1420c87 5542 _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE);
7cf5915e 5543 _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
cc754834 5544
dcb445bc 5545 if (!_sspiConnect(http->tls_credentials, hostname))
cc754834 5546 {
7cf5915e
MS
5547 _sspiFree(http->tls_credentials);
5548 http->tls_credentials = NULL;
a4845881
MS
5549
5550 http->error = EIO;
cb7f98ee 5551 http->status = HTTP_STATUS_ERROR;
a4845881 5552
e924ce80 5553 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
a4845881
MS
5554 _("Unable to establish a secure connection to host."), 1);
5555
ef416fc2 5556 return (-1);
5557 }
5558# endif /* HAVE_CDSASSL */
5559
ef416fc2 5560 return (0);
5561}
ef416fc2 5562
5563
ef416fc2 5564/*
5565 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
5566 */
5567
5568static void
568fa3fa 5569http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 5570{
5571# ifdef HAVE_LIBSSL
89d46774 5572 SSL_CTX *context; /* Context for encryption */
ef416fc2 5573
a4845881 5574 context = SSL_get_SSL_CTX(http->tls);
ef416fc2 5575
a4845881 5576 SSL_shutdown(http->tls);
ef416fc2 5577 SSL_CTX_free(context);
a4845881 5578 SSL_free(http->tls);
ef416fc2 5579
5580# elif defined(HAVE_GNUTLS)
ef416fc2 5581 gnutls_certificate_client_credentials *credentials;
89d46774 5582 /* TLS credentials */
ef416fc2 5583
7cf5915e 5584 credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials);
ef416fc2 5585
7cf5915e
MS
5586 gnutls_bye(http->tls, GNUTLS_SHUT_RDWR);
5587 gnutls_deinit(http->tls);
ef416fc2 5588 gnutls_certificate_free_credentials(*credentials);
5589 free(credentials);
ef416fc2 5590
5591# elif defined(HAVE_CDSASSL)
7cf5915e 5592 while (SSLClose(http->tls) == errSSLWouldBlock)
b423cd4c 5593 usleep(1000);
5594
c1420c87 5595 CFRelease(http->tls);
89d46774 5596
7cf5915e
MS
5597 if (http->tls_credentials)
5598 CFRelease(http->tls_credentials);
89d46774 5599
cc754834 5600# elif defined(HAVE_SSPISSL)
7cf5915e 5601 _sspiFree(http->tls_credentials);
ef416fc2 5602# endif /* HAVE_LIBSSL */
5603
7cf5915e
MS
5604 http->tls = NULL;
5605 http->tls_credentials = NULL;
ef416fc2 5606}
5607#endif /* HAVE_SSL */
5608
5609
cb7f98ee
MS
5610#ifdef DEBUG
5611/*
5612 * 'http_state_string()' - Return the string associated with a given HTTP state.
5613 */
5614
5615static const char * /* O - State string */
5616http_state_string(http_state_t state) /* I - HTTP state */
5617{
5618 static char buffer[255]; /* Unknown value buffer */
5619 static const char * const states[] = /* State strings */
5620 {
5621 "HTTP_STATE_ERROR",
5622 "HTTP_STATE_WAITING",
5623 "HTTP_STATE_OPTIONS",
5624 "HTTP_STATE_GET",
5625 "HTTP_STATE_GET_SEND",
5626 "HTTP_STATE_HEAD",
5627 "HTTP_STATE_POST",
5628 "HTTP_STATE_POST_RECV",
5629 "HTTP_STATE_POST_SEND",
5630 "HTTP_STATE_PUT",
5631 "HTTP_STATE_PUT_RECV",
5632 "HTTP_STATE_DELETE",
5633 "HTTP_STATE_TRACE",
5634 "HTTP_STATE_CONNECT",
5635 "HTTP_STATE_STATUS",
5636 "HTTP_STATE_UNKNOWN_METHOD",
5637 "HTTP_STATE_UNKNOWN_VERSION"
5638 };
5639
5640 if (state >= HTTP_STATE_ERROR && state <= HTTP_STATE_UNKNOWN_VERSION)
5641 return (states[state - HTTP_STATE_ERROR]);
5642
5643 snprintf(buffer, sizeof(buffer), "??? %d ???", (int)state);
5644 return (buffer);
5645}
5646#endif /* DEBUG */
5647
5648
ef416fc2 5649#ifdef HAVE_SSL
5650/*
5651 * 'http_upgrade()' - Force upgrade to TLS encryption.
5652 */
5653
89d46774 5654static int /* O - Status of connection */
568fa3fa 5655http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 5656{
89d46774 5657 int ret; /* Return value */
5658 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 5659
5660
e07d4801 5661 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 5662
85b5d1df
MS
5663 /*
5664 * Flush the connection to make sure any previous "Upgrade" message
5665 * has been read.
5666 */
5667
5668 httpFlush(http);
5669
ef416fc2 5670 /*
5671 * Copy the HTTP data to a local variable so we can do the OPTIONS
5672 * request without interfering with the existing request data...
5673 */
5674
5675 memcpy(&myhttp, http, sizeof(myhttp));
5676
5677 /*
5678 * Send an OPTIONS request to the server, requiring SSL or TLS
5679 * encryption on the link...
5680 */
5681
cb7f98ee 5682 http->tls_upgrade = 1;
f7deaa1a 5683 http->field_authorization = NULL; /* Don't free the auth string */
5684
b86bc4cf 5685 httpClearFields(http);
5686 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
a469f8a5 5687 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
ef416fc2 5688
b86bc4cf 5689 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 5690 {
5691 /*
5692 * Wait for the secure connection...
5693 */
5694
cb7f98ee 5695 while (httpUpdate(http) == HTTP_STATUS_CONTINUE);
ef416fc2 5696 }
5697
ef416fc2 5698 /*
b86bc4cf 5699 * Restore the HTTP request data...
ef416fc2 5700 */
5701
b86bc4cf 5702 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 5703 http->data_encoding = myhttp.data_encoding;
5704 http->data_remaining = myhttp.data_remaining;
5705 http->_data_remaining = myhttp._data_remaining;
5706 http->expect = myhttp.expect;
5707 http->field_authorization = myhttp.field_authorization;
bc44d920 5708 http->digest_tries = myhttp.digest_tries;
cb7f98ee 5709 http->tls_upgrade = 0;
ef416fc2 5710
5711 /*
5712 * See if we actually went secure...
5713 */
5714
5715 if (!http->tls)
5716 {
5717 /*
5718 * Server does not support HTTP upgrade...
5719 */
5720
e07d4801 5721 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 5722
5723# ifdef WIN32
5724 closesocket(http->fd);
5725# else
5726 close(http->fd);
5727# endif
5728
5729 http->fd = -1;
5730
5731 return (-1);
5732 }
5733 else
5734 return (ret);
5735}
5736#endif /* HAVE_SSL */
5737
5738
ef416fc2 5739/*
5740 * 'http_write()' - Write a buffer to a HTTP connection.
5741 */
ef55b745 5742
0fa6c7fa 5743static ssize_t /* O - Number of bytes written */
568fa3fa 5744http_write(http_t *http, /* I - Connection to server */
f11a948a 5745 const char *buffer, /* I - Buffer for data */
0fa6c7fa 5746 size_t length) /* I - Number of bytes to write */
ef416fc2 5747{
0fa6c7fa
MS
5748 ssize_t tbytes, /* Total bytes sent */
5749 bytes; /* Bytes sent */
ef416fc2 5750
5751
0fa6c7fa
MS
5752 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
5753 buffer, CUPS_LLCAST length));
f11a948a
MS
5754 http->error = 0;
5755 tbytes = 0;
ef416fc2 5756
5757 while (length > 0)
5758 {
12f89d24
MS
5759 DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
5760
85dda01c
MS
5761 if (http->timeout_cb)
5762 {
5763#ifdef HAVE_POLL
5764 struct pollfd pfd; /* Polled file descriptor */
5765#else
5766 fd_set output_set; /* Output ready for write? */
5767 struct timeval timeout; /* Timeout value */
5768#endif /* HAVE_POLL */
5769 int nfds; /* Result from select()/poll() */
5770
5771 do
5772 {
5773#ifdef HAVE_POLL
5774 pfd.fd = http->fd;
5775 pfd.events = POLLOUT;
5776
5777 while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
82cc1f9a
MS
5778 (errno == EINTR || errno == EAGAIN))
5779 /* do nothing */;
85dda01c
MS
5780
5781#else
5782 do
5783 {
5784 FD_ZERO(&output_set);
5785 FD_SET(http->fd, &output_set);
5786
5787 timeout.tv_sec = http->wait_value / 1000;
5788 timeout.tv_usec = 1000 * (http->wait_value % 1000);
5789
5790 nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
5791 }
5792# ifdef WIN32
5793 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
5794 WSAGetLastError() == WSAEWOULDBLOCK));
5795# else
5796 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
5797# endif /* WIN32 */
5798#endif /* HAVE_POLL */
5799
5800 if (nfds < 0)
5801 {
5802 http->error = errno;
5803 return (-1);
5804 }
5805 else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
5806 {
5807#ifdef WIN32
83e08001 5808 http->error = WSAEWOULDBLOCK;
85dda01c
MS
5809#else
5810 http->error = EWOULDBLOCK;
5811#endif /* WIN32 */
5812 return (-1);
5813 }
5814 }
5815 while (nfds <= 0);
5816 }
5817
ef416fc2 5818#ifdef HAVE_SSL
5819 if (http->tls)
5820 bytes = http_write_ssl(http, buffer, length);
5821 else
5822#endif /* HAVE_SSL */
5823 bytes = send(http->fd, buffer, length, 0);
5824
0fa6c7fa
MS
5825 DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
5826 CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
12f89d24 5827
ef416fc2 5828 if (bytes < 0)
5829 {
5830#ifdef WIN32
10d09e33 5831 if (WSAGetLastError() == WSAEINTR)
cc754834 5832 continue;
10d09e33
MS
5833 else if (WSAGetLastError() == WSAEWOULDBLOCK)
5834 {
5835 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
5836 continue;
5837
5838 http->error = WSAGetLastError();
5839 }
5840 else if (WSAGetLastError() != http->error &&
5841 WSAGetLastError() != WSAECONNRESET)
ef416fc2 5842 {
5843 http->error = WSAGetLastError();
5844 continue;
5845 }
10d09e33 5846
ef416fc2 5847#else
10d09e33 5848 if (errno == EINTR)
ef416fc2 5849 continue;
10d09e33
MS
5850 else if (errno == EWOULDBLOCK || errno == EAGAIN)
5851 {
5852 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
5853 continue;
5854 else if (!http->timeout_cb && errno == EAGAIN)
5855 continue;
5856
5857 http->error = errno;
5858 }
ef416fc2 5859 else if (errno != http->error && errno != ECONNRESET)
5860 {
5861 http->error = errno;
5862 continue;
5863 }
5864#endif /* WIN32 */
5865
f8b3a85b
MS
5866 DEBUG_printf(("3http_write: error writing data (%s).",
5867 strerror(http->error)));
ef416fc2 5868
5869 return (-1);
5870 }
5871
5872 buffer += bytes;
5873 tbytes += bytes;
5874 length -= bytes;
5875 }
5876
5877#ifdef DEBUG
ae71f5de 5878 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 5879#endif /* DEBUG */
5880
0fa6c7fa 5881 DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
f8b3a85b 5882
ef416fc2 5883 return (tbytes);
5884}
5885
5886
5887/*
5888 * 'http_write_chunk()' - Write a chunked buffer.
5889 */
5890
0fa6c7fa 5891static ssize_t /* O - Number bytes written */
568fa3fa 5892http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 5893 const char *buffer, /* I - Buffer to write */
0fa6c7fa 5894 size_t length) /* I - Length of buffer */
ef416fc2 5895{
0fa6c7fa
MS
5896 char header[16]; /* Chunk header */
5897 ssize_t bytes; /* Bytes written */
ef416fc2 5898
f11a948a 5899
0fa6c7fa
MS
5900 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
5901 http, buffer, CUPS_LLCAST length));
ef416fc2 5902
5903 /*
5904 * Write the chunk header, data, and trailer.
5905 */
5906
0fa6c7fa
MS
5907 snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
5908 if (http_write(http, header, strlen(header)) < 0)
ef416fc2 5909 {
0fa6c7fa 5910 DEBUG_puts("8http_write_chunk: http_write of length failed.");
ef416fc2 5911 return (-1);
5912 }
5913
5914 if ((bytes = http_write(http, buffer, length)) < 0)
5915 {
0fa6c7fa 5916 DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
ef416fc2 5917 return (-1);
5918 }
5919
5920 if (http_write(http, "\r\n", 2) < 0)
5921 {
0fa6c7fa 5922 DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
ef416fc2 5923 return (-1);
5924 }
5925
5926 return (bytes);
5927}
5928
5929
5930#ifdef HAVE_SSL
5931/*
5932 * 'http_write_ssl()' - Write to a SSL/TLS connection.
5933 */
5934
5935static int /* O - Bytes written */
568fa3fa 5936http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 5937 const char *buf, /* I - Buffer holding data */
5938 int len) /* I - Length of buffer */
5939{
f8b3a85b
MS
5940 ssize_t result; /* Return value */
5941
5942
5943 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
5944
ef416fc2 5945# if defined(HAVE_LIBSSL)
f8b3a85b 5946 result = SSL_write((SSL *)(http->tls), buf, len);
ef416fc2 5947
5948# elif defined(HAVE_GNUTLS)
7cf5915e 5949 result = gnutls_record_send(http->tls, buf, len);
ef55b745
MS
5950
5951 if (result < 0 && !errno)
5952 {
5953 /*
5954 * Convert GNU TLS error to errno value...
5955 */
5956
5957 switch (result)
5958 {
5959 case GNUTLS_E_INTERRUPTED :
5960 errno = EINTR;
5961 break;
5962
5963 case GNUTLS_E_AGAIN :
5964 errno = EAGAIN;
5965 break;
5966
5967 default :
5968 errno = EPIPE;
5969 break;
5970 }
5971
5972 result = -1;
5973 }
5974
ef416fc2 5975# elif defined(HAVE_CDSASSL)
5976 OSStatus error; /* Error info */
5977 size_t processed; /* Number of bytes processed */
5978
5979
7cf5915e 5980 error = SSLWrite(http->tls, buf, len, &processed);
ef416fc2 5981
fa73b229 5982 switch (error)
ef416fc2 5983 {
fa73b229 5984 case 0 :
5985 result = (int)processed;
5986 break;
84315f46 5987
fa73b229 5988 case errSSLWouldBlock :
b423cd4c 5989 if (processed)
5990 result = (int)processed;
5991 else
5992 {
5993 result = -1;
ef55b745 5994 errno = EINTR;
b423cd4c 5995 }
fa73b229 5996 break;
84315f46
MS
5997
5998 case errSSLClosedGraceful :
fa73b229 5999 default :
84315f46
MS
6000 if (processed)
6001 result = (int)processed;
6002 else
6003 {
6004 result = -1;
6005 errno = EPIPE;
6006 }
fa73b229 6007 break;
ef416fc2 6008 }
cc754834 6009# elif defined(HAVE_SSPISSL)
84315f46 6010 return _sspiWrite((_sspi_struct_t *)http->tls, (void *)buf, len);
ef416fc2 6011# endif /* HAVE_LIBSSL */
f8b3a85b
MS
6012
6013 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
6014
6015 return ((int)result);
ef416fc2 6016}
6017#endif /* HAVE_SSL */
6018
6019
6020/*
f2d18633 6021 * End of "$Id$".
ef416fc2 6022 */