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