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