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