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