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