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