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