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