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