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