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