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