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