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