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