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