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