]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.6svn-r10188, including changes for <rdar://problem/10127258...
[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
1186 if (bytes < 0)
1187 {
1188 /*
1189 * Nope, can't get a line this time...
1190 */
1191
1192#ifdef WIN32
cc754834
MS
1193 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
1194
10d09e33 1195 if (WSAGetLastError() == WSAEINTR)
cc754834 1196 continue;
10d09e33
MS
1197 else if (WSAGetLastError() == WSAEWOULDBLOCK)
1198 {
1199 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1200 continue;
1201
1202 http->error = WSAGetLastError();
1203 }
cc754834 1204 else if (WSAGetLastError() != http->error)
ef416fc2 1205 {
1206 http->error = WSAGetLastError();
1207 continue;
1208 }
1209
ef416fc2 1210#else
e07d4801 1211 DEBUG_printf(("3httpGets: recv() error %d!", errno));
ef416fc2 1212
10d09e33 1213 if (errno == EINTR)
ef416fc2 1214 continue;
10d09e33
MS
1215 else if (errno == EWOULDBLOCK || errno == EAGAIN)
1216 {
1217 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1218 continue;
1219 else if (!http->timeout_cb && errno == EAGAIN)
1220 continue;
1221
1222 http->error = errno;
1223 }
ef416fc2 1224 else if (errno != http->error)
1225 {
1226 http->error = errno;
1227 continue;
1228 }
1229#endif /* WIN32 */
1230
1231 return (NULL);
1232 }
1233 else if (bytes == 0)
1234 {
1235 http->error = EPIPE;
1236
1237 return (NULL);
1238 }
1239
1240 /*
1241 * Yup, update the amount used...
1242 */
1243
1244 http->used += bytes;
1245 }
1246
1247 /*
1248 * Now copy as much of the current line as possible...
1249 */
1250
1251 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1252 lineptr < lineend && bufptr < bufend;)
1253 {
1254 if (*bufptr == 0x0a)
1255 {
1256 eol = 1;
1257 bufptr ++;
1258 break;
1259 }
1260 else if (*bufptr == 0x0d)
1261 bufptr ++;
1262 else
1263 *lineptr++ = *bufptr++;
1264 }
1265
b86bc4cf 1266 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1267 if (http->used > 0)
1268 memmove(http->buffer, bufptr, http->used);
1269
1270 if (eol)
1271 {
1272 /*
1273 * End of line...
1274 */
1275
1276 http->activity = time(NULL);
1277
1278 *lineptr = '\0';
ef55b745 1279
e07d4801 1280 DEBUG_printf(("3httpGets: Returning \"%s\"", line));
ef416fc2 1281
1282 return (line);
1283 }
1284 }
1285
e07d4801 1286 DEBUG_puts("3httpGets: No new line available!");
ef416fc2 1287
1288 return (NULL);
1289}
1290
1291
a2326b5b
MS
1292/*
1293 * 'httpGetState()' - Get the current state of the HTTP request.
1294 */
1295
1296http_state_t /* O - HTTP state */
1297httpGetState(http_t *http) /* I - Connection to server */
1298{
1299 return (http ? http->state : HTTP_ERROR);
1300}
1301
1302
1303/*
1304 * 'httpGetStatus()' - Get the status of the last HTTP request.
1305 *
1306 * @since CUPS 1.2/Mac OS X 10.5@
1307 */
1308
1309http_status_t /* O - HTTP status */
1310httpGetStatus(http_t *http) /* I - Connection to server */
1311{
1312 return (http ? http->status : HTTP_ERROR);
1313}
1314
1315
1316/*
1317 * 'httpGetSubField()' - Get a sub-field value.
1318 *
1319 * @deprecated@
1320 */
1321
1322char * /* O - Value or NULL */
1323httpGetSubField(http_t *http, /* I - Connection to server */
1324 http_field_t field, /* I - Field index */
1325 const char *name, /* I - Name of sub-field */
1326 char *value) /* O - Value string */
1327{
1328 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
1329}
1330
1331
1332/*
1333 * 'httpGetSubField2()' - Get a sub-field value.
1334 *
1335 * @since CUPS 1.2/Mac OS X 10.5@
1336 */
1337
1338char * /* O - Value or NULL */
1339httpGetSubField2(http_t *http, /* I - Connection to server */
1340 http_field_t field, /* I - Field index */
1341 const char *name, /* I - Name of sub-field */
1342 char *value, /* O - Value string */
1343 int valuelen) /* I - Size of value buffer */
1344{
1345 const char *fptr; /* Pointer into field */
1346 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
1347 *ptr, /* Pointer into string buffer */
1348 *end; /* End of value buffer */
1349
1350 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
1351 "valuelen=%d)", http, field, name, value, valuelen));
1352
1353 if (!http || !name || !value || valuelen < 2 ||
1354 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
1355 return (NULL);
1356
1357 end = value + valuelen - 1;
1358
1359 for (fptr = http->fields[field]; *fptr;)
1360 {
1361 /*
1362 * Skip leading whitespace...
1363 */
1364
1365 while (_cups_isspace(*fptr))
1366 fptr ++;
1367
1368 if (*fptr == ',')
1369 {
1370 fptr ++;
1371 continue;
1372 }
1373
1374 /*
1375 * Get the sub-field name...
1376 */
1377
1378 for (ptr = temp;
1379 *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
1380 ptr < (temp + sizeof(temp) - 1);
1381 *ptr++ = *fptr++);
1382
1383 *ptr = '\0';
1384
1385 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
1386
1387 /*
1388 * Skip trailing chars up to the '='...
1389 */
1390
1391 while (_cups_isspace(*fptr))
1392 fptr ++;
1393
1394 if (!*fptr)
1395 break;
1396
1397 if (*fptr != '=')
1398 continue;
1399
1400 /*
1401 * Skip = and leading whitespace...
1402 */
1403
1404 fptr ++;
1405
1406 while (_cups_isspace(*fptr))
1407 fptr ++;
1408
1409 if (*fptr == '\"')
1410 {
1411 /*
1412 * Read quoted string...
1413 */
1414
1415 for (ptr = value, fptr ++;
1416 *fptr && *fptr != '\"' && ptr < end;
1417 *ptr++ = *fptr++);
1418
1419 *ptr = '\0';
1420
1421 while (*fptr && *fptr != '\"')
1422 fptr ++;
1423
1424 if (*fptr)
1425 fptr ++;
1426 }
1427 else
1428 {
1429 /*
1430 * Read unquoted string...
1431 */
1432
1433 for (ptr = value;
1434 *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
1435 *ptr++ = *fptr++);
1436
1437 *ptr = '\0';
1438
1439 while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
1440 fptr ++;
1441 }
1442
1443 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
1444
1445 /*
1446 * See if this is the one...
1447 */
1448
1449 if (!strcmp(name, temp))
1450 {
1451 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
1452 return (value);
1453 }
1454 }
1455
1456 value[0] = '\0';
1457
1458 DEBUG_puts("3httpGetSubField2: Returning NULL");
1459
1460 return (NULL);
1461}
1462
1463
1464/*
1465 * 'httpGetVersion()' - Get the HTTP version at the other end.
1466 */
1467
1468http_version_t /* O - Version number */
1469httpGetVersion(http_t *http) /* I - Connection to server */
1470{
1471 return (http ? http->version : HTTP_1_0);
1472}
1473
1474
ef416fc2 1475/*
1476 * 'httpHead()' - Send a HEAD request to the server.
1477 */
1478
1479int /* O - Status of call (0 = success) */
568fa3fa 1480httpHead(http_t *http, /* I - Connection to server */
ef416fc2 1481 const char *uri) /* I - URI for head */
1482{
e07d4801 1483 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1484 return (http_send(http, HTTP_HEAD, uri));
1485}
1486
1487
1488/*
1489 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1490 * default HTTP proxy (if any).
1491 */
1492
1493void
1494httpInitialize(void)
1495{
6d2f911b
MS
1496 static int initialized = 0; /* Have we been called before? */
1497#ifdef WIN32
1498 WSADATA winsockdata; /* WinSock data */
1499#endif /* WIN32 */
ef416fc2 1500#ifdef HAVE_LIBSSL
6d2f911b
MS
1501 int i; /* Looping var */
1502 unsigned char data[1024]; /* Seed data */
ef416fc2 1503#endif /* HAVE_LIBSSL */
1504
ef416fc2 1505
6d2f911b
MS
1506 _cupsGlobalLock();
1507 if (initialized)
1508 {
1509 _cupsGlobalUnlock();
1510 return;
1511 }
1512
1513#ifdef WIN32
c7017ecc 1514 WSAStartup(MAKEWORD(2,2), &winsockdata);
ef416fc2 1515
fa73b229 1516#elif !defined(SO_NOSIGPIPE)
ef416fc2 1517 /*
1518 * Ignore SIGPIPE signals...
1519 */
1520
fa73b229 1521# ifdef HAVE_SIGSET
1522 sigset(SIGPIPE, SIG_IGN);
6d2f911b 1523
fa73b229 1524# elif defined(HAVE_SIGACTION)
1525 struct sigaction action; /* POSIX sigaction data */
1526
1527
ef416fc2 1528 memset(&action, 0, sizeof(action));
1529 action.sa_handler = SIG_IGN;
1530 sigaction(SIGPIPE, &action, NULL);
6d2f911b 1531
fa73b229 1532# else
ef416fc2 1533 signal(SIGPIPE, SIG_IGN);
fa73b229 1534# endif /* !SO_NOSIGPIPE */
ef416fc2 1535#endif /* WIN32 */
1536
1537#ifdef HAVE_GNUTLS
6d2f911b
MS
1538 /*
1539 * Initialize GNU TLS...
1540 */
1541
ef416fc2 1542 gnutls_global_init();
ef416fc2 1543
6d2f911b
MS
1544#elif defined(HAVE_LIBSSL)
1545 /*
1546 * Initialize OpenSSL...
1547 */
1548
ef416fc2 1549 SSL_load_error_strings();
1550 SSL_library_init();
1551
1552 /*
1553 * Using the current time is a dubious random seed, but on some systems
1554 * it is the best we can do (on others, this seed isn't even used...)
1555 */
1556
6d2f911b 1557 CUPS_SRAND(time(NULL));
ef416fc2 1558
1559 for (i = 0; i < sizeof(data); i ++)
6d2f911b 1560 data[i] = CUPS_RAND();
ef416fc2 1561
dfd5680b 1562 RAND_seed(data, sizeof(data));
6d2f911b
MS
1563#endif /* HAVE_GNUTLS */
1564
1565 initialized = 1;
1566 _cupsGlobalUnlock();
ef416fc2 1567}
1568
1569
1570/*
1571 * 'httpOptions()' - Send an OPTIONS request to the server.
1572 */
1573
1574int /* O - Status of call (0 = success) */
568fa3fa 1575httpOptions(http_t *http, /* I - Connection to server */
ef416fc2 1576 const char *uri) /* I - URI for options */
1577{
1578 return (http_send(http, HTTP_OPTIONS, uri));
1579}
1580
1581
6d2f911b
MS
1582/*
1583 * '_httpPeek()' - Peek at data from a HTTP connection.
1584 *
1585 * This function copies available data from the given HTTP connection, reading
1586 * a buffer as needed. The data is still available for reading using
1587 * @link httpRead@ or @link httpRead2@.
1588 *
1589 * For non-blocking connections the usual timeouts apply.
1590 */
1591
1592ssize_t /* O - Number of bytes copied */
1593_httpPeek(http_t *http, /* I - Connection to server */
1594 char *buffer, /* I - Buffer for data */
1595 size_t length) /* I - Maximum number of bytes */
1596{
1597 ssize_t bytes; /* Bytes read */
1598 char len[32]; /* Length string */
1599
1600
1601 DEBUG_printf(("_httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
1602 http, buffer, CUPS_LLCAST length));
1603
1604 if (http == NULL || buffer == NULL)
1605 return (-1);
1606
1607 http->activity = time(NULL);
1608 http->error = 0;
1609
1610 if (length <= 0)
1611 return (0);
1612
1613 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1614 http->data_remaining <= 0)
1615 {
1616 DEBUG_puts("2_httpPeek: Getting chunk length...");
1617
1618 if (httpGets(len, sizeof(len), http) == NULL)
1619 {
1620 DEBUG_puts("1_httpPeek: Could not get length!");
1621 return (0);
1622 }
1623
1624 http->data_remaining = strtoll(len, NULL, 16);
1625 if (http->data_remaining < 0)
1626 {
1627 DEBUG_puts("1_httpPeek: Negative chunk length!");
1628 return (0);
1629 }
1630 }
1631
1632 DEBUG_printf(("2_httpPeek: data_remaining=" CUPS_LLFMT,
1633 CUPS_LLCAST http->data_remaining));
1634
1635 if (http->data_remaining <= 0)
1636 {
1637 /*
1638 * A zero-length chunk ends a transfer; unless we are reading POST
1639 * data, go idle...
1640 */
1641
1642 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1643 httpGets(len, sizeof(len), http);
1644
1645 if (http->state == HTTP_POST_RECV)
1646 http->state ++;
1647 else
1648 http->state = HTTP_WAITING;
1649
1650 /*
1651 * Prevent future reads for this request...
1652 */
1653
1654 http->data_encoding = HTTP_ENCODE_LENGTH;
1655
1656 return (0);
1657 }
1658 else if (length > (size_t)http->data_remaining)
1659 length = (size_t)http->data_remaining;
1660
1661 if (http->used == 0)
1662 {
1663 /*
1664 * Buffer small reads for better performance...
1665 */
1666
f228370c
MS
1667 if (!http->blocking)
1668 {
85dda01c 1669 while (!httpWait(http, http->wait_value))
f228370c
MS
1670 {
1671 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1672 continue;
1673
1674 return (0);
1675 }
1676 }
6d2f911b
MS
1677
1678 if (http->data_remaining > sizeof(http->buffer))
1679 bytes = sizeof(http->buffer);
1680 else
1681 bytes = http->data_remaining;
1682
1683#ifdef HAVE_SSL
1684 if (http->tls)
1685 bytes = http_read_ssl(http, http->buffer, bytes);
1686 else
1687#endif /* HAVE_SSL */
1688 {
1689 DEBUG_printf(("2_httpPeek: reading %d bytes from socket into buffer...",
1690 (int)bytes));
1691
1692 bytes = recv(http->fd, http->buffer, bytes, 0);
1693
1694 DEBUG_printf(("2_httpPeek: read %d bytes from socket into buffer...",
1695 (int)bytes));
1696 }
1697
1698 if (bytes > 0)
1699 http->used = bytes;
1700 else if (bytes < 0)
1701 {
1702#ifdef WIN32
cc754834
MS
1703 if (WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK)
1704 {
1705 http->error = WSAGetLastError();
1706 return (-1);
1707 }
6d2f911b
MS
1708#else
1709 if (errno != EINTR && errno != EAGAIN)
1710 {
1711 http->error = errno;
1712 return (-1);
1713 }
1714#endif /* WIN32 */
1715 }
1716 else
1717 {
1718 http->error = EPIPE;
1719 return (0);
1720 }
1721 }
1722
1723 if (http->used > 0)
1724 {
1725 if (length > (size_t)http->used)
1726 length = (size_t)http->used;
1727
1728 bytes = (ssize_t)length;
1729
1730 DEBUG_printf(("2_httpPeek: grabbing %d bytes from input buffer...",
1731 (int)bytes));
1732
1733 memcpy(buffer, http->buffer, length);
1734 }
1735 else
1736 bytes = 0;
1737
1738 if (bytes < 0)
1739 {
1740#ifdef WIN32
cc754834
MS
1741 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)
1742 bytes = 0;
1743 else
1744 http->error = WSAGetLastError();
6d2f911b
MS
1745#else
1746 if (errno == EINTR || errno == EAGAIN)
1747 bytes = 0;
1748 else
1749 http->error = errno;
1750#endif /* WIN32 */
1751 }
1752 else if (bytes == 0)
1753 {
1754 http->error = EPIPE;
1755 return (0);
1756 }
1757
1758#ifdef DEBUG
1759 http_debug_hex("_httpPeek", buffer, (int)bytes);
1760#endif /* DEBUG */
1761
1762 return (bytes);
1763}
1764
1765
ef416fc2 1766/*
1767 * 'httpPost()' - Send a POST request to the server.
1768 */
1769
1770int /* O - Status of call (0 = success) */
568fa3fa 1771httpPost(http_t *http, /* I - Connection to server */
ef416fc2 1772 const char *uri) /* I - URI for post */
1773{
1774 return (http_send(http, HTTP_POST, uri));
1775}
1776
1777
1778/*
1779 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 1780 *
1781 * @private@
ef416fc2 1782 */
1783
1784int /* O - Number of bytes written */
568fa3fa 1785httpPrintf(http_t *http, /* I - Connection to server */
ef416fc2 1786 const char *format, /* I - printf-style format string */
1787 ...) /* I - Additional args as needed */
1788{
1789 int bytes; /* Number of bytes to write */
1790 char buf[16384]; /* Buffer for formatted string */
1791 va_list ap; /* Variable argument pointer */
1792
1793
e07d4801 1794 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
ef416fc2 1795
1796 va_start(ap, format);
1797 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1798 va_end(ap);
1799
e07d4801 1800 DEBUG_printf(("3httpPrintf: %s", buf));
ef416fc2 1801
d09495fa 1802 if (http->data_encoding == HTTP_ENCODE_FIELDS)
1803 return (httpWrite2(http, buf, bytes));
1804 else
ef416fc2 1805 {
d09495fa 1806 if (http->wused)
1807 {
e07d4801 1808 DEBUG_puts("4httpPrintf: flushing existing data...");
ef416fc2 1809
d09495fa 1810 if (httpFlushWrite(http) < 0)
1811 return (-1);
1812 }
ef416fc2 1813
d09495fa 1814 return (http_write(http, buf, bytes));
1815 }
ef416fc2 1816}
1817
1818
1819/*
1820 * 'httpPut()' - Send a PUT request to the server.
1821 */
1822
1823int /* O - Status of call (0 = success) */
568fa3fa 1824httpPut(http_t *http, /* I - Connection to server */
ef416fc2 1825 const char *uri) /* I - URI to put */
1826{
e07d4801 1827 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1828 return (http_send(http, HTTP_PUT, uri));
1829}
1830
1831
1832/*
1833 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 1834 *
1835 * This function is deprecated. Use the httpRead2() function which can
1836 * read more than 2GB of data.
1837 *
1838 * @deprecated@
ef416fc2 1839 */
1840
1841int /* O - Number of bytes read */
568fa3fa 1842httpRead(http_t *http, /* I - Connection to server */
ef416fc2 1843 char *buffer, /* I - Buffer for data */
1844 int length) /* I - Maximum number of bytes */
1845{
a4d04587 1846 return ((int)httpRead2(http, buffer, length));
1847}
1848
1849
1850/*
1851 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 1852 *
426c6a59 1853 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 1854 */
1855
1856ssize_t /* O - Number of bytes read */
568fa3fa 1857httpRead2(http_t *http, /* I - Connection to server */
a4d04587 1858 char *buffer, /* I - Buffer for data */
1859 size_t length) /* I - Maximum number of bytes */
1860{
1861 ssize_t bytes; /* Bytes read */
ef416fc2 1862 char len[32]; /* Length string */
1863
1864
e07d4801 1865 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
a603edef 1866 http, buffer, CUPS_LLCAST length));
ef416fc2 1867
1868 if (http == NULL || buffer == NULL)
1869 return (-1);
1870
1871 http->activity = time(NULL);
f11a948a 1872 http->error = 0;
ef416fc2 1873
1874 if (length <= 0)
1875 return (0);
1876
1877 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1878 http->data_remaining <= 0)
1879 {
e07d4801 1880 DEBUG_puts("2httpRead2: Getting chunk length...");
ef416fc2 1881
1882 if (httpGets(len, sizeof(len), http) == NULL)
1883 {
e07d4801 1884 DEBUG_puts("1httpRead2: Could not get length!");
ef416fc2 1885 return (0);
1886 }
1887
1888 http->data_remaining = strtoll(len, NULL, 16);
1889 if (http->data_remaining < 0)
1890 {
e07d4801 1891 DEBUG_puts("1httpRead2: Negative chunk length!");
ef416fc2 1892 return (0);
1893 }
1894 }
1895
e07d4801 1896 DEBUG_printf(("2httpRead2: data_remaining=" CUPS_LLFMT,
ef416fc2 1897 CUPS_LLCAST http->data_remaining));
1898
1899 if (http->data_remaining <= 0)
1900 {
1901 /*
1902 * A zero-length chunk ends a transfer; unless we are reading POST
1903 * data, go idle...
1904 */
1905
1906 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1907 httpGets(len, sizeof(len), http);
1908
1909 if (http->state == HTTP_POST_RECV)
1910 http->state ++;
1911 else
1912 http->state = HTTP_WAITING;
1913
1914 /*
1915 * Prevent future reads for this request...
1916 */
1917
1918 http->data_encoding = HTTP_ENCODE_LENGTH;
1919
1920 return (0);
1921 }
b86bc4cf 1922 else if (length > (size_t)http->data_remaining)
1923 length = (size_t)http->data_remaining;
ef416fc2 1924
1925 if (http->used == 0 && length <= 256)
1926 {
1927 /*
1928 * Buffer small reads for better performance...
1929 */
1930
83e08001
MS
1931 ssize_t buflen; /* Length of read for buffer */
1932
f228370c
MS
1933 if (!http->blocking)
1934 {
85dda01c 1935 while (!httpWait(http, http->wait_value))
f228370c
MS
1936 {
1937 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1938 continue;
1939
1940 return (0);
1941 }
1942 }
ef416fc2 1943
1944 if (http->data_remaining > sizeof(http->buffer))
83e08001 1945 buflen = sizeof(http->buffer);
ef416fc2 1946 else
83e08001 1947 buflen = http->data_remaining;
ef416fc2 1948
83e08001
MS
1949 DEBUG_printf(("2httpRead2: Reading %d bytes into buffer.", (int)buflen));
1950
1951 do
1952 {
ef416fc2 1953#ifdef HAVE_SSL
83e08001
MS
1954 if (http->tls)
1955 bytes = http_read_ssl(http, http->buffer, buflen);
1956 else
ef416fc2 1957#endif /* HAVE_SSL */
83e08001 1958 bytes = recv(http->fd, http->buffer, buflen, 0);
ef416fc2 1959
83e08001 1960 if (bytes < 0)
10d09e33 1961 {
83e08001
MS
1962#ifdef WIN32
1963 if (WSAGetLastError() != WSAEINTR)
10d09e33 1964 {
83e08001 1965 http->error = WSAGetLastError();
10d09e33
MS
1966 return (-1);
1967 }
83e08001
MS
1968 else if (WSAGetLastError() == WSAEWOULDBLOCK)
1969 {
1970 if (!http->timeout_cb ||
1971 !(*http->timeout_cb)(http, http->timeout_data))
1972 {
1973 http->error = WSAEWOULDBLOCK;
1974 return (-1);
1975 }
1976 }
ef416fc2 1977#else
83e08001 1978 if (errno == EWOULDBLOCK || errno == EAGAIN)
10d09e33 1979 {
83e08001
MS
1980 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
1981 {
1982 http->error = errno;
1983 return (-1);
1984 }
1985 else if (!http->timeout_cb && errno != EAGAIN)
1986 {
1987 http->error = errno;
1988 return (-1);
1989 }
10d09e33 1990 }
83e08001 1991 else if (errno != EINTR)
10d09e33
MS
1992 {
1993 http->error = errno;
1994 return (-1);
1995 }
ef416fc2 1996#endif /* WIN32 */
83e08001 1997 }
ef416fc2 1998 }
83e08001
MS
1999 while (bytes < 0);
2000
2001 DEBUG_printf(("2httpRead2: Read %d bytes into buffer.", (int)bytes));
2002
2003 http->used = bytes;
ef416fc2 2004 }
2005
2006 if (http->used > 0)
2007 {
b86bc4cf 2008 if (length > (size_t)http->used)
2009 length = (size_t)http->used;
ef416fc2 2010
b86bc4cf 2011 bytes = (ssize_t)length;
ef416fc2 2012
e07d4801 2013 DEBUG_printf(("2httpRead2: grabbing %d bytes from input buffer...",
a603edef 2014 (int)bytes));
ef416fc2 2015
2016 memcpy(buffer, http->buffer, length);
b86bc4cf 2017 http->used -= (int)length;
ef416fc2 2018
2019 if (http->used > 0)
2020 memmove(http->buffer, http->buffer + length, http->used);
2021 }
2022#ifdef HAVE_SSL
2023 else if (http->tls)
2024 {
f228370c
MS
2025 if (!http->blocking)
2026 {
85dda01c 2027 while (!httpWait(http, http->wait_value))
f228370c
MS
2028 {
2029 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2030 continue;
2031
2032 return (0);
2033 }
2034 }
ef416fc2 2035
83e08001
MS
2036 while ((bytes = (ssize_t)http_read_ssl(http, buffer, (int)length)) < 0)
2037 {
2038#ifdef WIN32
2039 if (WSAGetLastError() == WSAEWOULDBLOCK)
2040 {
2041 if (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))
2042 break;
2043 }
2044 else if (WSAGetLastError() != WSAEINTR)
2045 break;
2046#else
2047 if (errno == EWOULDBLOCK || errno == EAGAIN)
2048 {
2049 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
2050 break;
2051 else if (!http->timeout_cb && errno != EAGAIN)
2052 break;
2053 }
2054 else if (errno != EINTR)
2055 break;
2056#endif /* WIN32 */
2057 }
ef416fc2 2058 }
2059#endif /* HAVE_SSL */
2060 else
2061 {
f228370c
MS
2062 if (!http->blocking)
2063 {
85dda01c 2064 while (!httpWait(http, http->wait_value))
f228370c
MS
2065 {
2066 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2067 continue;
2068
2069 return (0);
2070 }
2071 }
ef416fc2 2072
e07d4801 2073 DEBUG_printf(("2httpRead2: reading " CUPS_LLFMT " bytes from socket...",
a603edef 2074 CUPS_LLCAST length));
ef416fc2 2075
b86bc4cf 2076#ifdef WIN32
10d09e33
MS
2077 while ((bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0)) < 0)
2078 {
2079 if (WSAGetLastError() == WSAEWOULDBLOCK)
2080 {
2081 if (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))
2082 break;
2083 }
2084 else if (WSAGetLastError() != WSAEINTR)
cc754834 2085 break;
10d09e33 2086 }
b86bc4cf 2087#else
ef416fc2 2088 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
10d09e33
MS
2089 {
2090 if (errno == EWOULDBLOCK || errno == EAGAIN)
2091 {
2092 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
2093 break;
2094 else if (!http->timeout_cb && errno != EAGAIN)
2095 break;
2096 }
2097 else if (errno != EINTR)
ef416fc2 2098 break;
10d09e33 2099 }
b86bc4cf 2100#endif /* WIN32 */
ef416fc2 2101
e07d4801 2102 DEBUG_printf(("2httpRead2: read " CUPS_LLFMT " bytes from socket...",
a603edef 2103 CUPS_LLCAST bytes));
ef416fc2 2104 }
2105
2106 if (bytes > 0)
2107 {
2108 http->data_remaining -= bytes;
2109
2110 if (http->data_remaining <= INT_MAX)
2111 http->_data_remaining = (int)http->data_remaining;
2112 else
2113 http->_data_remaining = INT_MAX;
2114 }
2115 else if (bytes < 0)
2116 {
2117#ifdef WIN32
10d09e33 2118 if (WSAGetLastError() == WSAEINTR)
cc754834
MS
2119 bytes = 0;
2120 else
2121 http->error = WSAGetLastError();
ef416fc2 2122#else
10d09e33 2123 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
ef416fc2 2124 bytes = 0;
2125 else
2126 http->error = errno;
2127#endif /* WIN32 */
2128 }
2129 else
2130 {
2131 http->error = EPIPE;
2132 return (0);
2133 }
2134
2135 if (http->data_remaining == 0)
2136 {
2137 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2138 httpGets(len, sizeof(len), http);
2139
2140 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
2141 {
2142 if (http->state == HTTP_POST_RECV)
2143 http->state ++;
2144 else
2145 http->state = HTTP_WAITING;
2146 }
2147 }
2148
2149#ifdef DEBUG
ae71f5de 2150 http_debug_hex("httpRead2", buffer, (int)bytes);
ef416fc2 2151#endif /* DEBUG */
2152
2153 return (bytes);
2154}
2155
2156
2157#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2158/*
411affcf 2159 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 2160 */
2161
2162OSStatus /* O - -1 on error, 0 on success */
2163_httpReadCDSA(
2164 SSLConnectionRef connection, /* I - SSL/TLS connection */
2165 void *data, /* I - Data buffer */
2166 size_t *dataLength) /* IO - Number of bytes */
2167{
411affcf 2168 OSStatus result; /* Return value */
2169 ssize_t bytes; /* Number of bytes read */
2170 http_t *http; /* HTTP connection */
2171
2172
2173 http = (http_t *)connection;
e53920b9 2174
411affcf 2175 if (!http->blocking)
2176 {
2177 /*
2178 * Make sure we have data before we read...
2179 */
e53920b9 2180
85dda01c 2181 while (!_httpWait(http, http->wait_value, 0))
411affcf 2182 {
f228370c
MS
2183 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2184 continue;
2185
411affcf 2186 http->error = ETIMEDOUT;
2187 return (-1);
2188 }
2189 }
ef416fc2 2190
b423cd4c 2191 do
411affcf 2192 {
2193 bytes = recv(http->fd, data, *dataLength, 0);
2194 }
e07d4801 2195 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2196
b423cd4c 2197 if (bytes == *dataLength)
411affcf 2198 {
b423cd4c 2199 result = 0;
411affcf 2200 }
b423cd4c 2201 else if (bytes > 0)
2202 {
2203 *dataLength = bytes;
2204 result = errSSLWouldBlock;
2205 }
2206 else
2207 {
2208 *dataLength = 0;
fa73b229 2209
2210 if (bytes == 0)
ed486911 2211 result = errSSLClosedGraceful;
b423cd4c 2212 else if (errno == EAGAIN)
2213 result = errSSLWouldBlock;
b423cd4c 2214 else
ed486911 2215 result = errSSLClosedAbort;
ef416fc2 2216 }
b423cd4c 2217
411affcf 2218 return (result);
ef416fc2 2219}
2220#endif /* HAVE_SSL && HAVE_CDSASSL */
2221
2222
411affcf 2223#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2224/*
2225 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
2226 */
2227
2228ssize_t /* O - Number of bytes read or -1 on error */
2229_httpReadGNUTLS(
568fa3fa 2230 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2231 void *data, /* I - Buffer */
2232 size_t length) /* I - Number of bytes to read */
2233{
2234 http_t *http; /* HTTP connection */
a4845881
MS
2235 ssize_t bytes; /* Bytes read */
2236
411affcf 2237
a4845881 2238 DEBUG_printf(("6_httpReadGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data, (int)length));
411affcf 2239
2240 http = (http_t *)ptr;
2241
2242 if (!http->blocking)
2243 {
2244 /*
2245 * Make sure we have data before we read...
2246 */
2247
85dda01c 2248 while (!_httpWait(http, http->wait_value, 0))
411affcf 2249 {
f228370c
MS
2250 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2251 continue;
2252
411affcf 2253 http->error = ETIMEDOUT;
2254 return (-1);
2255 }
2256 }
2257
a4845881
MS
2258 bytes = recv(http->fd, data, length, 0);
2259 DEBUG_printf(("6_httpReadGNUTLS: bytes=%d", (int)bytes));
2260 return (bytes);
411affcf 2261}
2262#endif /* HAVE_SSL && HAVE_GNUTLS */
2263
2264
ef416fc2 2265/*
ecdc0628 2266 * 'httpReconnect()' - Reconnect to a HTTP server.
ef416fc2 2267 */
2268
2269int /* O - 0 on success, non-zero on failure */
568fa3fa 2270httpReconnect(http_t *http) /* I - Connection to server */
dcb445bc
MS
2271{
2272 DEBUG_printf(("httpReconnect(http=%p)", http));
2273
2274 return (httpReconnect2(http, 30, NULL));
2275}
2276
2277
2278/*
2279 * 'httpReconnect2()' - Reconnect to a HTTP server with timeout and optional
2280 * cancel.
2281 */
2282
2283int /* O - 0 on success, non-zero on failure */
2284httpReconnect2(http_t *http, /* I - Connection to server */
2285 int msec, /* I - Timeout in milliseconds */
2286 int *cancel) /* I - Pointer to "cancel" variable */
ef416fc2 2287{
2288 http_addrlist_t *addr; /* Connected address */
1ff0402e
MS
2289#ifdef DEBUG
2290 http_addrlist_t *current; /* Current address */
2291 char temp[256]; /* Temporary address string */
2292#endif /* DEBUG */
ef416fc2 2293
2294
dcb445bc
MS
2295 DEBUG_printf(("httpReconnect(http=%p, msec=%d, cancel=%p)", http, msec,
2296 cancel));
ef416fc2 2297
2298 if (!http)
dcb445bc
MS
2299 {
2300 _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
ef416fc2 2301 return (-1);
dcb445bc 2302 }
ef416fc2 2303
2304#ifdef HAVE_SSL
2305 if (http->tls)
1ff0402e 2306 {
e07d4801 2307 DEBUG_puts("2httpReconnect: Shutting down SSL/TLS...");
ef416fc2 2308 http_shutdown_ssl(http);
1ff0402e 2309 }
ef416fc2 2310#endif /* HAVE_SSL */
2311
2312 /*
2313 * Close any previously open socket...
2314 */
2315
2316 if (http->fd >= 0)
bd7854cb 2317 {
e07d4801 2318 DEBUG_printf(("2httpReconnect: Closing socket %d...", http->fd));
1ff0402e 2319
ef416fc2 2320#ifdef WIN32
2321 closesocket(http->fd);
2322#else
2323 close(http->fd);
2324#endif /* WIN32 */
2325
bd7854cb 2326 http->fd = -1;
2327 }
2328
ef416fc2 2329 /*
2330 * Connect to the server...
2331 */
2332
1ff0402e
MS
2333#ifdef DEBUG
2334 for (current = http->addrlist; current; current = current->next)
e07d4801 2335 DEBUG_printf(("2httpReconnect: Address %s:%d",
1ff0402e
MS
2336 httpAddrString(&(current->addr), temp, sizeof(temp)),
2337 _httpAddrPort(&(current->addr))));
2338#endif /* DEBUG */
2339
dcb445bc
MS
2340 if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec,
2341 cancel)) == NULL)
ef416fc2 2342 {
2343 /*
2344 * Unable to connect...
2345 */
2346
2347#ifdef WIN32
2348 http->error = WSAGetLastError();
2349#else
2350 http->error = errno;
2351#endif /* WIN32 */
2352 http->status = HTTP_ERROR;
2353
e07d4801 2354 DEBUG_printf(("1httpReconnect: httpAddrConnect failed: %s",
1ff0402e
MS
2355 strerror(http->error)));
2356
ef416fc2 2357 return (-1);
2358 }
2359
e07d4801 2360 DEBUG_printf(("2httpReconnect: New socket=%d", http->fd));
1ff0402e 2361
85dda01c
MS
2362 if (http->timeout_value > 0)
2363 http_set_timeout(http->fd, http->timeout_value);
10d09e33 2364
ef416fc2 2365 http->hostaddr = &(addr->addr);
2366 http->error = 0;
2367 http->status = HTTP_CONTINUE;
10ddcf65 2368 http->state = HTTP_WAITING;
ef416fc2 2369
2370#ifdef HAVE_SSL
2371 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
2372 {
2373 /*
2374 * Always do encryption via SSL.
2375 */
2376
2377 if (http_setup_ssl(http) != 0)
2378 {
f7deaa1a 2379# ifdef WIN32
ef416fc2 2380 closesocket(http->fd);
f7deaa1a 2381# else
ef416fc2 2382 close(http->fd);
f7deaa1a 2383# endif /* WIN32 */
ef416fc2 2384
2385 return (-1);
2386 }
2387 }
2388 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
2389 return (http_upgrade(http));
2390#endif /* HAVE_SSL */
2391
e07d4801 2392 DEBUG_printf(("1httpReconnect: Connected to %s:%d...",
1ff0402e
MS
2393 httpAddrString(http->hostaddr, temp, sizeof(temp)),
2394 _httpAddrPort(http->hostaddr)));
2395
ef416fc2 2396 return (0);
2397}
2398
2399
355e94dc
MS
2400/*
2401 * 'httpSetAuthString()' - Set the current authorization string.
2402 *
2403 * This function just stores a copy of the current authorization string in
2404 * the HTTP connection object. You must still call httpSetField() to set
2405 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
2406 * httpHead(), httpOptions(), httpPost, or httpPut().
2407 *
426c6a59 2408 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
2409 */
2410
2411void
568fa3fa 2412httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
2413 const char *scheme, /* I - Auth scheme (NULL to clear it) */
2414 const char *data) /* I - Auth data (NULL for none) */
2415{
2416 /*
2417 * Range check input...
2418 */
2419
2420 if (!http)
2421 return;
2422
2423 if (http->authstring && http->authstring != http->_authstring)
2424 free(http->authstring);
2425
2426 http->authstring = http->_authstring;
2427
2428 if (scheme)
2429 {
2430 /*
2431 * Set the current authorization string...
2432 */
2433
2434 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 2435 char *temp;
355e94dc
MS
2436
2437 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
2438 {
2439 if ((temp = malloc(len)) == NULL)
2440 len = sizeof(http->_authstring);
2441 else
2442 http->authstring = temp;
2443 }
355e94dc
MS
2444
2445 if (data)
2446 snprintf(http->authstring, len, "%s %s", scheme, data);
2447 else
2448 strlcpy(http->authstring, scheme, len);
2449 }
2450 else
2451 {
2452 /*
2453 * Clear the current authorization string...
2454 */
2455
2456 http->_authstring[0] = '\0';
2457 }
2458}
2459
2460
7cf5915e
MS
2461/*
2462 * 'httpSetCredentials()' - Set the credentials associated with an encrypted
2463 * connection.
2464 *
321d8d57 2465 * @since CUPS 1.5/Mac OS X 10.7@
7cf5915e
MS
2466 */
2467
2468int /* O - Status of call (0 = success) */
2469httpSetCredentials(http_t *http, /* I - Connection to server */
2470 cups_array_t *credentials) /* I - Array of credentials */
2471{
2472 if (!http || cupsArrayCount(credentials) < 1)
2473 return (-1);
2474
2475 _httpFreeCredentials(http->tls_credentials);
2476
85dda01c 2477 http->tls_credentials = _httpCreateCredentials(credentials);
7cf5915e
MS
2478
2479 return (http->tls_credentials ? 0 : -1);
2480}
2481
2482
ef416fc2 2483/*
6d2f911b 2484 * 'httpSetCookie()' - Set the cookie value(s).
ef416fc2 2485 *
426c6a59 2486 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2487 */
2488
2489void
2490httpSetCookie(http_t *http, /* I - Connection */
2491 const char *cookie) /* I - Cookie string */
2492{
2493 if (!http)
2494 return;
2495
2496 if (http->cookie)
2497 free(http->cookie);
2498
2499 if (cookie)
2500 http->cookie = strdup(cookie);
2501 else
2502 http->cookie = NULL;
2503}
2504
2505
b423cd4c 2506/*
2507 * 'httpSetExpect()' - Set the Expect: header in a request.
2508 *
2509 * Currently only HTTP_CONTINUE is supported for the "expect" argument.
2510 *
426c6a59 2511 * @since CUPS 1.2/Mac OS X 10.5@
b423cd4c 2512 */
2513
2514void
568fa3fa 2515httpSetExpect(http_t *http, /* I - Connection to server */
b423cd4c 2516 http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
2517{
2518 if (http)
2519 http->expect = expect;
2520}
2521
2522
ef416fc2 2523/*
2524 * 'httpSetField()' - Set the value of an HTTP header.
2525 */
2526
2527void
568fa3fa 2528httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 2529 http_field_t field, /* I - Field index */
2530 const char *value) /* I - Value */
2531{
2532 if (http == NULL ||
2533 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
2534 field > HTTP_FIELD_WWW_AUTHENTICATE ||
2535 value == NULL)
2536 return;
2537
2538 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
f7deaa1a 2539
f7deaa1a 2540 if (field == HTTP_FIELD_AUTHORIZATION)
2541 {
e07d4801
MS
2542 /*
2543 * Special case for Authorization: as its contents can be
2544 * longer than HTTP_MAX_VALUE
2545 */
2546
f7deaa1a 2547 if (http->field_authorization)
2548 free(http->field_authorization);
2549
2550 http->field_authorization = strdup(value);
2551 }
e07d4801
MS
2552 else if (field == HTTP_FIELD_HOST)
2553 {
2554 /*
f11a948a
MS
2555 * Special-case for Host: as we don't want a trailing "." on the hostname and
2556 * need to bracket IPv6 numeric addresses.
e07d4801
MS
2557 */
2558
178cb736
MS
2559 char *ptr = strchr(value, ':');
2560
2561 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
2562 {
2563 /*
2564 * Bracket IPv6 numeric addresses...
2565 *
2566 * This is slightly inefficient (basically copying twice), but is an edge
2567 * case and not worth optimizing...
2568 */
e07d4801 2569
f11a948a
MS
2570 snprintf(http->fields[HTTP_FIELD_HOST],
2571 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
2572 }
2573 else
e07d4801 2574 {
f11a948a
MS
2575 /*
2576 * Check for a trailing dot on the hostname...
2577 */
2578
178cb736 2579 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
2580
2581 if (*ptr)
2582 {
2583 ptr += strlen(ptr) - 1;
e07d4801 2584
f11a948a
MS
2585 if (*ptr == '.')
2586 *ptr = '\0';
2587 }
e07d4801
MS
2588 }
2589 }
ef416fc2 2590}
2591
2592
2593/*
2594 * 'httpSetLength()' - Set the content-length and content-encoding.
2595 *
426c6a59 2596 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 2597 */
2598
2599void
568fa3fa 2600httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 2601 size_t length) /* I - Length (0 for chunked) */
2602{
2603 if (!http)
2604 return;
2605
2606 if (!length)
2607 {
2608 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
2609 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
2610 }
2611 else
2612 {
2613 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
2614 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
2615 CUPS_LLFMT, CUPS_LLCAST length);
2616 }
2617}
2618
2619
10d09e33 2620/*
f228370c 2621 * 'httpSetTimeout()' - Set read/write timeouts and an optional callback.
10d09e33
MS
2622 *
2623 * The optional timeout callback receives both the HTTP connection and a user
f228370c
MS
2624 * data pointer and must return 1 to continue or 0 to error (time) out.
2625 *
2626 * @since CUPS 1.5/Mac OS X 10.7@
10d09e33
MS
2627 */
2628
2629void
f228370c
MS
2630httpSetTimeout(
2631 http_t *http, /* I - Connection to server */
2632 double timeout, /* I - Number of seconds for timeout,
10d09e33 2633 must be greater than 0 */
f228370c
MS
2634 http_timeout_cb_t cb, /* I - Callback function or NULL */
2635 void *user_data) /* I - User data pointer */
10d09e33
MS
2636{
2637 if (!http || timeout <= 0.0)
2638 return;
2639
85dda01c
MS
2640 http->timeout_cb = cb;
2641 http->timeout_data = user_data;
2642 http->timeout_value = timeout;
10d09e33
MS
2643
2644 if (http->fd >= 0)
85dda01c 2645 http_set_timeout(http->fd, timeout);
c8fef167 2646
85dda01c 2647 http_set_wait(http);
10d09e33
MS
2648}
2649
2650
ef416fc2 2651/*
2652 * 'httpTrace()' - Send an TRACE request to the server.
2653 */
2654
2655int /* O - Status of call (0 = success) */
568fa3fa 2656httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 2657 const char *uri) /* I - URI for trace */
2658{
2659 return (http_send(http, HTTP_TRACE, uri));
2660}
2661
2662
2663/*
e60ec91f
MS
2664 * '_httpUpdate()' - Update the current HTTP status for incoming data.
2665 *
2666 * Note: Unlike httpUpdate(), this function does not flush pending write data
2667 * and only retrieves a single status line from the HTTP connection.
ef416fc2 2668 */
2669
e60ec91f
MS
2670int /* O - 1 to continue, 0 to stop */
2671_httpUpdate(http_t *http, /* I - Connection to server */
2672 http_status_t *status) /* O - Current HTTP status */
ef416fc2 2673{
2674 char line[32768], /* Line from connection... */
2675 *value; /* Pointer to value on line */
2676 http_field_t field; /* Field index */
e60ec91f 2677 int major, minor; /* HTTP version numbers */
ef416fc2 2678
2679
e60ec91f 2680 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status,
f11a948a 2681 http_states[http->state]));
ef416fc2 2682
2683 /*
e60ec91f 2684 * Grab a single line from the connection...
ef416fc2 2685 */
2686
e60ec91f 2687 if (!httpGets(line, sizeof(line), http))
ef416fc2 2688 {
e60ec91f
MS
2689 *status = HTTP_ERROR;
2690 return (0);
ef416fc2 2691 }
2692
e60ec91f 2693 DEBUG_printf(("2_httpUpdate: Got \"%s\"", line));
ef416fc2 2694
e60ec91f 2695 if (line[0] == '\0')
ef416fc2 2696 {
e60ec91f
MS
2697 /*
2698 * Blank line means the start of the data section (if any). Return
2699 * the result code, too...
2700 *
2701 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
2702 * Instead, we just return HTTP_CONTINUE to the caller and keep on
2703 * tryin'...
2704 */
ef416fc2 2705
e60ec91f 2706 if (http->status == HTTP_CONTINUE)
ef416fc2 2707 {
e60ec91f
MS
2708 *status = http->status;
2709 return (0);
2710 }
ef416fc2 2711
e60ec91f
MS
2712 if (http->status < HTTP_BAD_REQUEST)
2713 http->digest_tries = 0;
ef416fc2 2714
2715#ifdef HAVE_SSL
e60ec91f
MS
2716 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
2717 {
2718 if (http_setup_ssl(http) != 0)
ef416fc2 2719 {
ef416fc2 2720# ifdef WIN32
e60ec91f 2721 closesocket(http->fd);
ef416fc2 2722# else
e60ec91f 2723 close(http->fd);
ef416fc2 2724# endif /* WIN32 */
2725
e60ec91f
MS
2726 *status = http->status = HTTP_ERROR;
2727 return (0);
ef416fc2 2728 }
e60ec91f
MS
2729
2730 *status = HTTP_CONTINUE;
2731 return (0);
2732 }
ef416fc2 2733#endif /* HAVE_SSL */
2734
e60ec91f 2735 httpGetLength2(http);
ef416fc2 2736
e60ec91f
MS
2737 switch (http->state)
2738 {
2739 case HTTP_GET :
2740 case HTTP_POST :
2741 case HTTP_POST_RECV :
2742 case HTTP_PUT :
2743 http->state ++;
2744 case HTTP_POST_SEND :
2745 case HTTP_HEAD :
2746 break;
ef416fc2 2747
e60ec91f
MS
2748 default :
2749 http->state = HTTP_WAITING;
2750 break;
ef416fc2 2751 }
e60ec91f
MS
2752
2753 *status = http->status;
2754 return (0);
2755 }
2756 else if (!strncmp(line, "HTTP/", 5))
2757 {
2758 /*
2759 * Got the beginning of a response...
2760 */
2761
2762 int intstatus; /* Status value as an integer */
2763
2764 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3)
2765 {
2766 *status = http->status = HTTP_ERROR;
2767 return (0);
2768 }
2769
2770 http->version = (http_version_t)(major * 100 + minor);
2771 *status = http->status = (http_status_t)intstatus;
2772 }
2773 else if ((value = strchr(line, ':')) != NULL)
2774 {
2775 /*
2776 * Got a value...
2777 */
2778
2779 *value++ = '\0';
2780 while (_cups_isspace(*value))
2781 value ++;
2782
2783 /*
2784 * Be tolerants of servers that send unknown attribute fields...
2785 */
2786
88f9aafc 2787 if (!_cups_strcasecmp(line, "expect"))
ef416fc2 2788 {
2789 /*
e60ec91f 2790 * "Expect: 100-continue" or similar...
ef416fc2 2791 */
2792
e60ec91f 2793 http->expect = (http_status_t)atoi(value);
ef416fc2 2794 }
88f9aafc 2795 else if (!_cups_strcasecmp(line, "cookie"))
ef416fc2 2796 {
2797 /*
e60ec91f 2798 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
ef416fc2 2799 */
2800
e60ec91f
MS
2801 httpSetCookie(http, value);
2802 }
2803 else if ((field = http_field(line)) != HTTP_FIELD_UNKNOWN)
2804 httpSetField(http, field, value);
2805#ifdef DEBUG
2806 else
2807 DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
2808#endif /* DEBUG */
2809 }
2810 else
2811 {
2812 DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line));
2813 *status = http->status = HTTP_ERROR;
2814 return (0);
2815 }
ef416fc2 2816
e60ec91f
MS
2817 return (1);
2818}
ef416fc2 2819
ef416fc2 2820
e60ec91f
MS
2821/*
2822 * 'httpUpdate()' - Update the current HTTP state for incoming data.
2823 */
ef416fc2 2824
e60ec91f
MS
2825http_status_t /* O - HTTP status */
2826httpUpdate(http_t *http) /* I - Connection to server */
2827{
2828 http_status_t status; /* Request status */
2829
2830
2831 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
2832 http_states[http->state]));
2833
2834 /*
2835 * Flush pending data, if any...
2836 */
2837
2838 if (http->wused)
2839 {
2840 DEBUG_puts("2httpUpdate: flushing buffer...");
2841
2842 if (httpFlushWrite(http) < 0)
ef416fc2 2843 return (HTTP_ERROR);
ef416fc2 2844 }
2845
e60ec91f
MS
2846 /*
2847 * If we haven't issued any commands, then there is nothing to "update"...
2848 */
2849
2850 if (http->state == HTTP_WAITING)
2851 return (HTTP_CONTINUE);
2852
2853 /*
2854 * Grab all of the lines we can from the connection...
2855 */
2856
2857 while (_httpUpdate(http, &status));
2858
ef416fc2 2859 /*
2860 * See if there was an error...
2861 */
2862
2863 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
e07d4801
MS
2864 {
2865 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 2866 return (http->status);
e07d4801 2867 }
ef416fc2 2868
2869 if (http->error)
2870 {
e07d4801 2871 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 2872 strerror(http->error)));
2873 http->status = HTTP_ERROR;
2874 return (HTTP_ERROR);
2875 }
2876
2877 /*
e60ec91f 2878 * Return the current status...
ef416fc2 2879 */
2880
e60ec91f 2881 return (status);
ef416fc2 2882}
2883
2884
38e73f87
MS
2885/*
2886 * '_httpWait()' - Wait for data available on a connection (no flush).
2887 */
2888
2889int /* O - 1 if data is available, 0 otherwise */
2890_httpWait(http_t *http, /* I - Connection to server */
2891 int msec, /* I - Milliseconds to wait */
2892 int usessl) /* I - Use SSL context? */
2893{
2894#ifdef HAVE_POLL
2895 struct pollfd pfd; /* Polled file descriptor */
2896#else
2897 fd_set input_set; /* select() input set */
2898 struct timeval timeout; /* Timeout */
2899#endif /* HAVE_POLL */
2900 int nfds; /* Result from select()/poll() */
2901
2902
e07d4801 2903 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
2904
2905 if (http->fd < 0)
f8b3a85b
MS
2906 {
2907 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
38e73f87 2908 return (0);
f8b3a85b 2909 }
38e73f87
MS
2910
2911 /*
2912 * Check the SSL/TLS buffers for data first...
2913 */
2914
2915#ifdef HAVE_SSL
2916 if (http->tls && usessl)
2917 {
2918# ifdef HAVE_LIBSSL
7cf5915e 2919 if (SSL_pending(http->tls))
f8b3a85b
MS
2920 {
2921 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2922 return (1);
f8b3a85b
MS
2923 }
2924
38e73f87 2925# elif defined(HAVE_GNUTLS)
7cf5915e 2926 if (gnutls_record_check_pending(http->tls))
f8b3a85b
MS
2927 {
2928 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2929 return (1);
f8b3a85b
MS
2930 }
2931
38e73f87
MS
2932# elif defined(HAVE_CDSASSL)
2933 size_t bytes; /* Bytes that are available */
2934
7cf5915e 2935 if (!SSLGetBufferedReadSize(http->tls, &bytes) &&
38e73f87 2936 bytes > 0)
f8b3a85b
MS
2937 {
2938 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2939 return (1);
f8b3a85b 2940 }
38e73f87
MS
2941# endif /* HAVE_LIBSSL */
2942 }
2943#endif /* HAVE_SSL */
2944
2945 /*
2946 * Then try doing a select() or poll() to poll the socket...
2947 */
2948
2949#ifdef HAVE_POLL
2950 pfd.fd = http->fd;
2951 pfd.events = POLLIN;
2952
e07d4801
MS
2953 while ((nfds = poll(&pfd, 1, msec)) < 0 &&
2954 (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2955
2956#else
2957 do
2958 {
2959 FD_ZERO(&input_set);
2960 FD_SET(http->fd, &input_set);
2961
e07d4801 2962 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
2963
2964 if (msec >= 0)
2965 {
2966 timeout.tv_sec = msec / 1000;
2967 timeout.tv_usec = (msec % 1000) * 1000;
2968
2969 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
2970 }
2971 else
2972 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
2973
e07d4801 2974 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
2975 }
2976# ifdef WIN32
cc754834
MS
2977 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
2978 WSAGetLastError() == WSAEWOULDBLOCK));
38e73f87 2979# else
e07d4801 2980 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2981# endif /* WIN32 */
2982#endif /* HAVE_POLL */
2983
f8b3a85b
MS
2984 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
2985 errno));
38e73f87
MS
2986
2987 return (nfds > 0);
2988}
2989
2990
ef416fc2 2991/*
2992 * 'httpWait()' - Wait for data available on a connection.
2993 *
426c6a59 2994 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2995 */
2996
2997int /* O - 1 if data is available, 0 otherwise */
568fa3fa 2998httpWait(http_t *http, /* I - Connection to server */
ef416fc2 2999 int msec) /* I - Milliseconds to wait */
3000{
3001 /*
3002 * First see if there is data in the buffer...
3003 */
3004
22c9029b
MS
3005 DEBUG_printf(("2httpWait(http=%p, msec=%d)", http, msec));
3006
ef416fc2 3007 if (http == NULL)
3008 return (0);
3009
3010 if (http->used)
22c9029b
MS
3011 {
3012 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
ef416fc2 3013 return (1);
22c9029b 3014 }
ef416fc2 3015
8ca02f3c 3016 /*
3017 * Flush pending data, if any...
3018 */
3019
3020 if (http->wused)
3021 {
22c9029b
MS
3022 DEBUG_puts("3httpWait: Flushing write buffer.");
3023
8ca02f3c 3024 if (httpFlushWrite(http) < 0)
3025 return (0);
3026 }
3027
ef416fc2 3028 /*
3029 * If not, check the SSL/TLS buffers and do a select() on the connection...
3030 */
3031
38e73f87 3032 return (_httpWait(http, msec, 1));
ef416fc2 3033}
3034
3035
3036/*
3037 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 3038 *
3039 * This function is deprecated. Use the httpWrite2() function which can
3040 * write more than 2GB of data.
3041 *
3042 * @deprecated@
ef416fc2 3043 */
ef55b745 3044
ef416fc2 3045int /* O - Number of bytes written */
568fa3fa 3046httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 3047 const char *buffer, /* I - Buffer for data */
3048 int length) /* I - Number of bytes to write */
3049{
a4d04587 3050 return ((int)httpWrite2(http, buffer, length));
3051}
3052
3053
3054/*
3055 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 3056 *
426c6a59 3057 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 3058 */
ef55b745 3059
a4d04587 3060ssize_t /* O - Number of bytes written */
568fa3fa 3061httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 3062 const char *buffer, /* I - Buffer for data */
3063 size_t length) /* I - Number of bytes to write */
3064{
3065 ssize_t bytes; /* Bytes written */
ef416fc2 3066
3067
e07d4801 3068 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 3069 buffer, CUPS_LLCAST length));
ef416fc2 3070
3071 /*
3072 * Range check input...
3073 */
3074
3075 if (http == NULL || buffer == NULL)
3076 return (-1);
3077
3078 /*
3079 * Mark activity on the connection...
3080 */
3081
3082 http->activity = time(NULL);
3083
3084 /*
3085 * Buffer small writes for better performance...
3086 */
3087
3088 if (length > 0)
3089 {
3090 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
3091 {
e07d4801
MS
3092 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
3093 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 3094
3095 httpFlushWrite(http);
3096 }
3097
38e73f87
MS
3098 if ((length + http->wused) <= sizeof(http->wbuffer) &&
3099 length < sizeof(http->wbuffer))
ef416fc2 3100 {
3101 /*
3102 * Write to buffer...
3103 */
3104
e07d4801 3105 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 3106 CUPS_LLCAST length));
ef416fc2 3107
3108 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 3109 http->wused += (int)length;
3110 bytes = (ssize_t)length;
ef416fc2 3111 }
3112 else
3113 {
3114 /*
3115 * Otherwise write the data directly...
3116 */
3117
e07d4801 3118 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 3119 CUPS_LLCAST length));
ef416fc2 3120
3121 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
b86bc4cf 3122 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 3123 else
b86bc4cf 3124 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 3125
e07d4801 3126 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 3127 CUPS_LLCAST bytes));
ef416fc2 3128 }
3129
3130 if (http->data_encoding == HTTP_ENCODE_LENGTH)
3131 http->data_remaining -= bytes;
3132 }
3133 else
3134 bytes = 0;
3135
3136 /*
3137 * Handle end-of-request processing...
3138 */
3139
3140 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
3141 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
3142 {
3143 /*
3144 * Finished with the transfer; unless we are sending POST or PUT
3145 * data, go idle...
3146 */
3147
e07d4801 3148 DEBUG_puts("2httpWrite: changing states...");
ef416fc2 3149
3150 if (http->wused)
3151 httpFlushWrite(http);
3152
3153 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
3154 {
3155 /*
3156 * Send a 0-length chunk at the end of the request...
3157 */
3158
3159 http_write(http, "0\r\n\r\n", 5);
3160
3161 /*
3162 * Reset the data state...
3163 */
3164
3165 http->data_encoding = HTTP_ENCODE_LENGTH;
3166 http->data_remaining = 0;
3167 }
ef416fc2 3168 }
3169
3170 return (bytes);
3171}
3172
3173
3174#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
3175/*
411affcf 3176 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 3177 */
3178
3179OSStatus /* O - -1 on error, 0 on success */
3180_httpWriteCDSA(
3181 SSLConnectionRef connection, /* I - SSL/TLS connection */
3182 const void *data, /* I - Data buffer */
3183 size_t *dataLength) /* IO - Number of bytes */
3184{
411affcf 3185 OSStatus result; /* Return value */
3186 ssize_t bytes; /* Number of bytes read */
3187 http_t *http; /* HTTP connection */
e53920b9 3188
3189
411affcf 3190 http = (http_t *)connection;
ef416fc2 3191
b423cd4c 3192 do
411affcf 3193 {
3194 bytes = write(http->fd, data, *dataLength);
3195 }
e07d4801 3196 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 3197
b423cd4c 3198 if (bytes == *dataLength)
411affcf 3199 {
b423cd4c 3200 result = 0;
411affcf 3201 }
b423cd4c 3202 else if (bytes >= 0)
3203 {
3204 *dataLength = bytes;
3205 result = errSSLWouldBlock;
3206 }
3207 else
3208 {
3209 *dataLength = 0;
ef55b745 3210
fa73b229 3211 if (errno == EAGAIN)
b423cd4c 3212 result = errSSLWouldBlock;
b423cd4c 3213 else
ed486911 3214 result = errSSLClosedAbort;
ef416fc2 3215 }
b423cd4c 3216
411affcf 3217 return (result);
ef416fc2 3218}
3219#endif /* HAVE_SSL && HAVE_CDSASSL */
3220
3221
411affcf 3222#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
3223/*
3224 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
3225 */
3226
3227ssize_t /* O - Number of bytes written or -1 on error */
3228_httpWriteGNUTLS(
568fa3fa 3229 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 3230 const void *data, /* I - Data buffer */
3231 size_t length) /* I - Number of bytes to write */
3232{
a4845881
MS
3233 ssize_t bytes; /* Bytes written */
3234
3235
3236 DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data,
3237 (int)length));
a2326b5b 3238#ifdef DEBUG
a4845881 3239 http_debug_hex("_httpWriteGNUTLS", data, (int)length);
a2326b5b 3240#endif /* DEBUG */
a4845881
MS
3241
3242 bytes = send(((http_t *)ptr)->fd, data, length, 0);
3243 DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes));
a2326b5b 3244
a4845881 3245 return (bytes);
411affcf 3246}
3247#endif /* HAVE_SSL && HAVE_GNUTLS */
3248
3249
3250#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
3251/*
3252 * 'http_bio_ctrl()' - Control the HTTP connection.
3253 */
3254
3255static long /* O - Result/data */
3256http_bio_ctrl(BIO *h, /* I - BIO data */
3257 int cmd, /* I - Control command */
3258 long arg1, /* I - First argument */
3259 void *arg2) /* I - Second argument */
3260{
3261 switch (cmd)
3262 {
3263 default :
3264 return (0);
3265
3266 case BIO_CTRL_RESET :
3267 h->ptr = NULL;
3268 return (0);
3269
3270 case BIO_C_SET_FILE_PTR :
3271 h->ptr = arg2;
3272 h->init = 1;
3273 return (1);
3274
3275 case BIO_C_GET_FILE_PTR :
3276 if (arg2)
3277 {
3278 *((void **)arg2) = h->ptr;
3279 return (1);
3280 }
3281 else
3282 return (0);
ef55b745 3283
411affcf 3284 case BIO_CTRL_DUP :
3285 case BIO_CTRL_FLUSH :
3286 return (1);
3287 }
3288}
3289
3290
3291/*
3292 * 'http_bio_free()' - Free OpenSSL data.
3293 */
3294
3295static int /* O - 1 on success, 0 on failure */
3296http_bio_free(BIO *h) /* I - BIO data */
3297{
3298 if (!h)
3299 return (0);
3300
3301 if (h->shutdown)
3302 {
3303 h->init = 0;
3304 h->flags = 0;
3305 }
3306
3307 return (1);
3308}
3309
3310
3311/*
3312 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
3313 */
3314
3315static int /* O - 1 on success, 0 on failure */
3316http_bio_new(BIO *h) /* I - BIO data */
3317{
3318 if (!h)
3319 return (0);
3320
3321 h->init = 0;
3322 h->num = 0;
3323 h->ptr = NULL;
3324 h->flags = 0;
3325
3326 return (1);
3327}
3328
3329
3330/*
3331 * 'http_bio_puts()' - Send a string for OpenSSL.
3332 */
3333
3334static int /* O - Bytes written */
3335http_bio_puts(BIO *h, /* I - BIO data */
3336 const char *str) /* I - String to write */
3337{
b86bc4cf 3338#ifdef WIN32
3339 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
3340#else
411affcf 3341 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 3342#endif /* WIN32 */
411affcf 3343}
3344
3345
3346/*
3347 * 'http_bio_read()' - Read data for OpenSSL.
3348 */
3349
3350static int /* O - Bytes read */
3351http_bio_read(BIO *h, /* I - BIO data */
3352 char *buf, /* I - Buffer */
3353 int size) /* I - Number of bytes to read */
3354{
3355 http_t *http; /* HTTP connection */
3356
3357
3358 http = (http_t *)h->ptr;
3359
3360 if (!http->blocking)
3361 {
3362 /*
3363 * Make sure we have data before we read...
3364 */
3365
85dda01c 3366 while (!_httpWait(http, http->wait_value, 0))
411affcf 3367 {
f228370c
MS
3368 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
3369 continue;
3370
b86bc4cf 3371#ifdef WIN32
3372 http->error = WSAETIMEDOUT;
3373#else
411affcf 3374 http->error = ETIMEDOUT;
b86bc4cf 3375#endif /* WIN32 */
3376
411affcf 3377 return (-1);
3378 }
3379 }
3380
3381 return (recv(http->fd, buf, size, 0));
3382}
3383
3384
3385/*
3386 * 'http_bio_write()' - Write data for OpenSSL.
3387 */
3388
3389static int /* O - Bytes written */
3390http_bio_write(BIO *h, /* I - BIO data */
3391 const char *buf, /* I - Buffer to write */
3392 int num) /* I - Number of bytes to write */
3393{
3394 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
3395}
3396#endif /* HAVE_SSL && HAVE_LIBSSL */
3397
3398
ae71f5de
MS
3399#ifdef DEBUG
3400/*
3401 * 'http_debug_hex()' - Do a hex dump of a buffer.
3402 */
3403
3404static void
3405http_debug_hex(const char *prefix, /* I - Prefix for line */
3406 const char *buffer, /* I - Buffer to dump */
3407 int bytes) /* I - Bytes to dump */
3408{
3409 int i, j, /* Looping vars */
3410 ch; /* Current character */
3411 char line[255], /* Line buffer */
3412 *start, /* Start of line after prefix */
3413 *ptr; /* Pointer into line */
3414
3415
f11a948a 3416 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
3417 return;
3418
83e08001 3419 DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
ae71f5de 3420
f11a948a 3421 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
3422 start = line + strlen(line);
3423
3424 for (i = 0; i < bytes; i += 16)
3425 {
3426 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
3427 sprintf(ptr, "%02X", buffer[i + j] & 255);
3428
3429 while (j < 16)
3430 {
3431 strcpy(ptr, " ");
3432 ptr += 2;
3433 j ++;
3434 }
3435
3436 strcpy(ptr, " ");
3437 ptr += 2;
3438
3439 for (j = 0; j < 16 && (i + j) < bytes; j ++)
3440 {
3441 ch = buffer[i + j] & 255;
3442
3443 if (ch < ' ' || ch >= 127)
3444 ch = '.';
3445
3446 *ptr++ = ch;
3447 }
3448
3449 *ptr = '\0';
3450 DEBUG_puts(line);
3451 }
3452}
3453#endif /* DEBUG */
3454
3455
ef416fc2 3456/*
3457 * 'http_field()' - Return the field index for a field name.
3458 */
3459
ae71f5de
MS
3460static http_field_t /* O - Field index */
3461http_field(const char *name) /* I - String name */
ef416fc2 3462{
ae71f5de 3463 int i; /* Looping var */
ef416fc2 3464
3465
3466 for (i = 0; i < HTTP_FIELD_MAX; i ++)
88f9aafc 3467 if (_cups_strcasecmp(name, http_fields[i]) == 0)
ef416fc2 3468 return ((http_field_t)i);
3469
3470 return (HTTP_FIELD_UNKNOWN);
3471}
3472
3473
3474#ifdef HAVE_SSL
3475/*
3476 * 'http_read_ssl()' - Read from a SSL/TLS connection.
3477 */
3478
3479static int /* O - Bytes read */
568fa3fa 3480http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3481 char *buf, /* I - Buffer to store data */
3482 int len) /* I - Length of buffer */
3483{
3484# if defined(HAVE_LIBSSL)
3485 return (SSL_read((SSL *)(http->tls), buf, len));
3486
3487# elif defined(HAVE_GNUTLS)
ef55b745
MS
3488 ssize_t result; /* Return value */
3489
3490
7cf5915e 3491 result = gnutls_record_recv(http->tls, buf, len);
ef55b745
MS
3492
3493 if (result < 0 && !errno)
3494 {
3495 /*
3496 * Convert GNU TLS error to errno value...
3497 */
3498
3499 switch (result)
3500 {
3501 case GNUTLS_E_INTERRUPTED :
3502 errno = EINTR;
3503 break;
3504
3505 case GNUTLS_E_AGAIN :
3506 errno = EAGAIN;
3507 break;
3508
3509 default :
3510 errno = EPIPE;
3511 break;
3512 }
3513
3514 result = -1;
3515 }
3516
3517 return ((int)result);
ef416fc2 3518
3519# elif defined(HAVE_CDSASSL)
fa73b229 3520 int result; /* Return value */
ef416fc2 3521 OSStatus error; /* Error info */
3522 size_t processed; /* Number of bytes processed */
3523
3524
7cf5915e 3525 error = SSLRead(http->tls, buf, len, &processed);
83e08001
MS
3526 DEBUG_printf(("6http_read_ssl: error=%d, processed=%d", (int)error,
3527 (int)processed));
fa73b229 3528 switch (error)
ef416fc2 3529 {
fa73b229 3530 case 0 :
3531 result = (int)processed;
3532 break;
84315f46 3533
fa73b229 3534 case errSSLWouldBlock :
b423cd4c 3535 if (processed)
3536 result = (int)processed;
3537 else
3538 {
3539 result = -1;
83e08001 3540 errno = EINTR;
b423cd4c 3541 }
fa73b229 3542 break;
84315f46
MS
3543
3544 case errSSLClosedGraceful :
fa73b229 3545 default :
84315f46
MS
3546 if (processed)
3547 result = (int)processed;
3548 else
3549 {
3550 result = -1;
83e08001 3551 errno = EPIPE;
84315f46 3552 }
fa73b229 3553 break;
ef416fc2 3554 }
fa73b229 3555
3556 return (result);
83e08001 3557
cc754834
MS
3558# elif defined(HAVE_SSPISSL)
3559 return _sspiRead((_sspi_struct_t*) http->tls, buf, len);
ef416fc2 3560# endif /* HAVE_LIBSSL */
3561}
3562#endif /* HAVE_SSL */
3563
3564
3565/*
3566 * 'http_send()' - Send a request with all fields and the trailing blank line.
3567 */
3568
3569static int /* O - 0 on success, non-zero on error */
568fa3fa 3570http_send(http_t *http, /* I - Connection to server */
ef416fc2 3571 http_state_t request, /* I - Request code */
3572 const char *uri) /* I - URI */
3573{
3574 int i; /* Looping var */
839a51c8 3575 char buf[1024]; /* Encoded URI buffer */
ef416fc2 3576 static const char * const codes[] =
3577 { /* Request code strings */
3578 NULL,
3579 "OPTIONS",
3580 "GET",
3581 NULL,
3582 "HEAD",
3583 "POST",
3584 NULL,
3585 NULL,
3586 "PUT",
3587 NULL,
3588 "DELETE",
3589 "TRACE",
3590 "CLOSE"
3591 };
ef416fc2 3592
3593
e07d4801 3594 DEBUG_printf(("7http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 3595 http, codes[request], uri));
3596
3597 if (http == NULL || uri == NULL)
3598 return (-1);
3599
3600 /*
3601 * Set the User-Agent field if it isn't already...
3602 */
3603
3604 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
3605 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
3606
3607 /*
3608 * Encode the URI as needed...
3609 */
3610
839a51c8 3611 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 3612
3613 /*
3614 * See if we had an error the last time around; if so, reconnect...
3615 */
3616
3617 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 3618 if (httpReconnect(http))
3619 return (-1);
ef416fc2 3620
d09495fa 3621 /*
3622 * Flush any written data that is pending...
3623 */
3624
3625 if (http->wused)
536bc2c6
MS
3626 {
3627 if (httpFlushWrite(http) < 0)
3628 if (httpReconnect(http))
3629 return (-1);
3630 }
d09495fa 3631
ef416fc2 3632 /*
3633 * Send the request header...
3634 */
3635
d09495fa 3636 http->state = request;
3637 http->data_encoding = HTTP_ENCODE_FIELDS;
3638
ef416fc2 3639 if (request == HTTP_POST || request == HTTP_PUT)
3640 http->state ++;
3641
3642 http->status = HTTP_CONTINUE;
3643
3644#ifdef HAVE_SSL
3645 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
3646 {
3647 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
3648 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
3649 }
3650#endif /* HAVE_SSL */
3651
3652 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
3653 {
3654 http->status = HTTP_ERROR;
3655 return (-1);
3656 }
3657
3658 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3659 if (http->fields[i][0] != '\0')
3660 {
e07d4801 3661 DEBUG_printf(("9http_send: %s: %s", http_fields[i],
ae71f5de 3662 httpGetField(http, i)));
ef416fc2 3663
ef55b745 3664 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
f7deaa1a 3665 httpGetField(http, i)) < 1)
ef416fc2 3666 {
3667 http->status = HTTP_ERROR;
3668 return (-1);
3669 }
3670 }
3671
3672 if (http->cookie)
3673 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
3674 {
3675 http->status = HTTP_ERROR;
3676 return (-1);
3677 }
3678
b423cd4c 3679 if (http->expect == HTTP_CONTINUE &&
3680 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
3681 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
3682 {
3683 http->status = HTTP_ERROR;
3684 return (-1);
3685 }
3686
ef416fc2 3687 if (httpPrintf(http, "\r\n") < 1)
3688 {
3689 http->status = HTTP_ERROR;
3690 return (-1);
3691 }
3692
536bc2c6
MS
3693 if (httpFlushWrite(http) < 0)
3694 return (-1);
3695
ef416fc2 3696 httpGetLength2(http);
3697 httpClearFields(http);
3698
f7deaa1a 3699 /*
b94498cf 3700 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 3701 */
3702
ef55b745
MS
3703 if (http->field_authorization && http->authstring &&
3704 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 3705 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 3706 {
3707 http->_authstring[0] = '\0';
3708
3709 if (http->authstring != http->_authstring)
3710 free(http->authstring);
ef55b745 3711
f7deaa1a 3712 http->authstring = http->_authstring;
3713 }
3714
ef416fc2 3715 return (0);
3716}
3717
3718
3719#ifdef HAVE_SSL
82f97232 3720# if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
7cf5915e
MS
3721/*
3722 * 'http_set_credentials()' - Set the SSL/TLS credentials.
3723 */
3724
3725static int /* O - Status of connection */
3726http_set_credentials(http_t *http) /* I - Connection to server */
3727{
3728 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
7cf5915e
MS
3729 OSStatus error = 0; /* Error code */
3730 http_tls_credentials_t credentials = NULL;
3731 /* TLS credentials */
7cf5915e
MS
3732
3733
3734 DEBUG_printf(("7http_set_credentials(%p)", http));
3735
7cf5915e
MS
3736 /*
3737 * Prefer connection specific credentials...
3738 */
3739
3740 if ((credentials = http->tls_credentials) == NULL)
3741 credentials = cg->tls_credentials;
3742
3743# if HAVE_SECPOLICYCREATESSL
3744 /*
3745 * Otherwise root around in the user's keychain to see if one can be found...
3746 */
3747
3748 if (!credentials)
3749 {
3750 CFDictionaryRef query; /* Query dictionary */
3751 CFTypeRef matches = NULL; /* Matching credentials */
3752 CFArrayRef dn_array = NULL;/* Distinguished names array */
3753 CFTypeRef keys[] = { kSecClass,
3754 kSecMatchLimit,
3755 kSecReturnRef };
3756 /* Keys for dictionary */
3757 CFTypeRef values[] = { kSecClassCertificate,
3758 kSecMatchLimitOne,
3759 kCFBooleanTrue };
3760 /* Values for dictionary */
3761
3762 /*
3763 * Get the names associated with the server.
3764 */
3765
3766 if ((error = SSLCopyDistinguishedNames(http->tls, &dn_array)) != noErr)
3767 {
3768 DEBUG_printf(("4http_set_credentials: SSLCopyDistinguishedNames, error=%d",
3769 (int)error));
3770 return (error);
3771 }
3772
3773 /*
3774 * Create a query which will return all identities that can sign and match
3775 * the passed in policy.
3776 */
3777
3778 query = CFDictionaryCreate(NULL,
3779 (const void**)(&keys[0]),
3780 (const void**)(&values[0]),
3781 sizeof(keys) / sizeof(keys[0]),
3782 &kCFTypeDictionaryKeyCallBacks,
3783 &kCFTypeDictionaryValueCallBacks);
3784 if (query)
3785 {
3786 error = SecItemCopyMatching(query, &matches);
3787 DEBUG_printf(("4http_set_credentials: SecItemCopyMatching, error=%d",
3788 (int)error));
3789 CFRelease(query);
3790 }
3791
3792 if (matches)
3793 CFRelease(matches);
3794
3795 if (dn_array)
3796 CFRelease(dn_array);
3797 }
3798# endif /* HAVE_SECPOLICYCREATESSL */
3799
3800 if (credentials)
3801 {
3802 error = SSLSetCertificate(http->tls, credentials);
3803 DEBUG_printf(("4http_set_credentials: SSLSetCertificate, error=%d",
3804 (int)error));
3805 }
3806 else
3807 DEBUG_puts("4http_set_credentials: No credentials to set.");
3808
3809 return (error);
7cf5915e 3810}
82f97232 3811# endif /* HAVE_CDSASSL && HAVE_SECCERTIFICATECOPYDATA */
9b66acc5 3812#endif /* HAVE_SSL */
7cf5915e
MS
3813
3814
85dda01c
MS
3815/*
3816 * 'http_set_timeout()' - Set the socket timeout values.
3817 */
3818
3819static void
3820http_set_timeout(int fd, /* I - File descriptor */
3821 double timeout) /* I - Timeout in seconds */
3822{
3823#ifdef WIN32
3824 DWORD tv = (DWORD)(timeout * 1000);
3825 /* Timeout in milliseconds */
3826
3827 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
3828 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
3829
3830#else
3831 struct timeval tv; /* Timeout in secs and usecs */
3832
3833 tv.tv_sec = (int)timeout;
3834 tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
3835
3836 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
3837 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
3838#endif /* WIN32 */
3839}
3840
3841
3842/*
3843 * 'http_set_wait()' - Set the default wait value for reads.
3844 */
3845
3846static void
3847http_set_wait(http_t *http) /* I - Connection to server */
3848{
3849 if (http->blocking)
3850 {
3851 http->wait_value = (int)(http->timeout_value * 1000);
3852
3853 if (http->wait_value <= 0)
3854 http->wait_value = 60000;
3855 }
3856 else
3857 http->wait_value = 10000;
3858}
3859
3860
9b66acc5 3861#ifdef HAVE_SSL
ef416fc2 3862/*
3863 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
3864 */
3865
a4845881 3866static int /* O - 0 on success, -1 on failure */
568fa3fa 3867http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 3868{
7cf5915e
MS
3869 _cups_globals_t *cg = _cupsGlobals();
3870 /* Pointer to library globals */
3871 int any_root; /* Allow any root */
dcb445bc 3872 char *hostname; /* Hostname */
7cf5915e 3873
ef416fc2 3874# ifdef HAVE_LIBSSL
a4845881
MS
3875 SSL_CTX *context; /* Context for encryption */
3876 BIO *bio; /* BIO data */
3877 const char *message = NULL;/* Error message */
ef416fc2 3878# elif defined(HAVE_GNUTLS)
a4845881 3879 int status; /* Status of handshake */
ef416fc2 3880 gnutls_certificate_client_credentials *credentials;
89d46774 3881 /* TLS credentials */
ef416fc2 3882# elif defined(HAVE_CDSASSL)
a4845881 3883 OSStatus error; /* Error code */
a4845881 3884 const char *message = NULL;/* Error message */
82f97232 3885# ifdef HAVE_SECCERTIFICATECOPYDATA
a4845881
MS
3886 cups_array_t *credentials; /* Credentials array */
3887 cups_array_t *names; /* CUPS distinguished names */
3888 CFArrayRef dn_array; /* CF distinguished names array */
3889 CFIndex count; /* Number of credentials */
3890 CFDataRef data; /* Certificate data */
3891 int i; /* Looping var */
3892 http_credential_t *credential; /* Credential data */
82f97232 3893# endif /* HAVE_SECCERTIFICATECOPYDATA */
cc754834 3894# elif defined(HAVE_SSPISSL)
a4845881
MS
3895 TCHAR username[256]; /* Username returned from GetUserName() */
3896 TCHAR commonName[256];/* Common name for certificate */
3897 DWORD dwSize; /* 32 bit size */
ef416fc2 3898# endif /* HAVE_LIBSSL */
3899
3900
e07d4801 3901 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 3902
7cf5915e
MS
3903 /*
3904 * Always allow self-signed certificates for the local loopback address...
3905 */
3906
3907 if (httpAddrLocalhost(http->hostaddr))
3908 any_root = 1;
3909 else
3910 any_root = cg->any_root;
3911
dcb445bc
MS
3912 hostname = httpAddrLocalhost(http->hostaddr) ? "localhost" : http->hostname;
3913
ef416fc2 3914# ifdef HAVE_LIBSSL
a4845881
MS
3915 (void)any_root;
3916
ef416fc2 3917 context = SSL_CTX_new(SSLv23_client_method());
3918
3919 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
3920
411affcf 3921 bio = BIO_new(_httpBIOMethods());
3922 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
3923
7cf5915e 3924 http->tls = SSL_new(context);
a4845881 3925 SSL_set_bio(http->tls, bio, bio);
ef416fc2 3926
dcb445bc
MS
3927 SSL_set_tlsext_host_name(http->tls, hostname);
3928
7cf5915e 3929 if (SSL_connect(http->tls) != 1)
ef416fc2 3930 {
ef416fc2 3931 unsigned long error; /* Error code */
3932
3933 while ((error = ERR_get_error()) != 0)
a4845881
MS
3934 {
3935 message = ERR_error_string(error, NULL);
3936 DEBUG_printf(("8http_setup_ssl: %s", message));
3937 }
ef416fc2 3938
3939 SSL_CTX_free(context);
7cf5915e
MS
3940 SSL_free(http->tls);
3941 http->tls = NULL;
ef416fc2 3942
3943# ifdef WIN32
3944 http->error = WSAGetLastError();
3945# else
3946 http->error = errno;
3947# endif /* WIN32 */
3948 http->status = HTTP_ERROR;
3949
a4845881
MS
3950 if (!message)
3951 message = _("Unable to establish a secure connection to host.");
3952
3953 _cupsSetError(IPP_PKI_ERROR, message, 1);
3954
3955 return (-1);
ef416fc2 3956 }
3957
3958# elif defined(HAVE_GNUTLS)
83e08001
MS
3959 (void)any_root;
3960
ef416fc2 3961 credentials = (gnutls_certificate_client_credentials *)
3962 malloc(sizeof(gnutls_certificate_client_credentials));
3963 if (credentials == NULL)
3964 {
a4845881
MS
3965 DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s",
3966 strerror(errno)));
3967 http->error = errno;
ef416fc2 3968 http->status = HTTP_ERROR;
a4845881 3969 _cupsSetHTTPError(HTTP_ERROR);
ef416fc2 3970
3971 return (-1);
3972 }
3973
3974 gnutls_certificate_allocate_credentials(credentials);
3975
7cf5915e
MS
3976 gnutls_init(&http->tls, GNUTLS_CLIENT);
3977 gnutls_set_default_priority(http->tls);
dcb445bc
MS
3978 gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname,
3979 strlen(hostname));
7cf5915e
MS
3980 gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);
3981 gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr)http);
3982 gnutls_transport_set_pull_function(http->tls, _httpReadGNUTLS);
3983 gnutls_transport_set_push_function(http->tls, _httpWriteGNUTLS);
ef416fc2 3984
a4845881 3985 while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
ef416fc2 3986 {
a4845881
MS
3987 DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)",
3988 status, gnutls_strerror(status)));
ef416fc2 3989
a4845881
MS
3990 if (gnutls_error_is_fatal(status))
3991 {
3992 http->error = EIO;
3993 http->status = HTTP_ERROR;
85b5d1df 3994
a4845881
MS
3995 _cupsSetError(IPP_PKI_ERROR, gnutls_strerror(status), 0);
3996
3997 gnutls_deinit(http->tls);
3998 gnutls_certificate_free_credentials(*credentials);
3999 free(credentials);
4000 http->tls = NULL;
4001
4002 return (-1);
4003 }
ef416fc2 4004 }
4005
7cf5915e 4006 http->tls_credentials = credentials;
ef416fc2 4007
4008# elif defined(HAVE_CDSASSL)
7cf5915e 4009 if ((error = SSLNewContext(false, &http->tls)))
e53920b9 4010 {
a4845881 4011 http->error = errno;
89d46774 4012 http->status = HTTP_ERROR;
a4845881 4013 _cupsSetHTTPError(HTTP_ERROR);
e53920b9 4014
89d46774 4015 return (-1);
e53920b9 4016 }
ef416fc2 4017
7cf5915e
MS
4018 error = SSLSetConnection(http->tls, http);
4019 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error));
4020
4021 if (!error)
4022 {
4023 error = SSLSetIOFuncs(http->tls, _httpReadCDSA, _httpWriteCDSA);
4024 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error));
4025 }
4026
7cf5915e
MS
4027 if (!error)
4028 {
4029 error = SSLSetAllowsAnyRoot(http->tls, any_root);
4030 DEBUG_printf(("4http_setup_ssl: SSLSetAllowsAnyRoot(%d), error=%d",
4031 any_root, (int)error));
4032 }
89d46774 4033
4034 if (!error)
7cf5915e
MS
4035 {
4036 error = SSLSetAllowsExpiredCerts(http->tls, cg->expired_certs);
4037 DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredCerts(%d), error=%d",
4038 cg->expired_certs, (int)error));
4039 }
89d46774 4040
ef416fc2 4041 if (!error)
7cf5915e
MS
4042 {
4043 error = SSLSetAllowsExpiredRoots(http->tls, cg->expired_root);
4044 DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredRoots(%d), error=%d",
4045 cg->expired_root, (int)error));
4046 }
ef416fc2 4047
771bd8cb
MS
4048# ifdef HAVE_SSLSETPROTOCOLVERSIONMAX
4049 if (!error)
4050 {
4051 error = SSLSetProtocolVersionMax(http->tls, kTLSProtocol1);
4052 DEBUG_printf(("4http_setup_ssl: SSLSetProtocolVersionMax(kTLSProtocol1), "
4053 "error=%d", (int)error));
4054 }
4055# endif /* HAVE_SSLSETPROTOCOLVERSIONMAX */
4056
10ddcf65
MS
4057 /*
4058 * In general, don't verify certificates since things like the common name
4059 * often do not match...
4060 */
4061
4062 if (!error)
4063 {
4064 error = SSLSetEnableCertVerify(http->tls, false);
4065 DEBUG_printf(("4http_setup_ssl: SSLSetEnableCertVerify, error=%d",
4066 (int)error));
4067 }
4068
82f97232 4069# ifdef HAVE_SECCERTIFICATECOPYDATA
ef416fc2 4070 if (!error)
7cf5915e
MS
4071 {
4072 if (cg->client_cert_cb)
4073 {
4074 error = SSLSetSessionOption(http->tls,
4075 kSSLSessionOptionBreakOnCertRequested, true);
4076 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, "
4077 "error=%d", (int)error));
4078 }
4079 else
4080 {
4081 error = http_set_credentials(http);
4082 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d",
4083 (int)error));
4084 }
4085 }
4086
4087 /*
4088 * If there's a server certificate callback installed let it evaluate the
4089 * certificate(s) during the handshake...
4090 */
4091
4092 if (!error && cg->server_cert_cb != NULL)
4093 {
10ddcf65
MS
4094 error = SSLSetSessionOption(http->tls,
4095 kSSLSessionOptionBreakOnServerAuth, true);
4096 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnServerAuth, "
4097 "error=%d", (int)error));
7cf5915e 4098 }
82f97232 4099# endif /* HAVE_SECCERTIFICATECOPYDATA */
ef416fc2 4100
10ddcf65
MS
4101 /*
4102 * Let the server know which hostname/domain we are trying to connect to
4103 * in case it wants to serve up a certificate with a matching common name.
4104 */
4105
ed486911 4106 if (!error)
7cf5915e 4107 {
dcb445bc 4108 error = SSLSetPeerDomainName(http->tls, hostname, strlen(hostname));
7cf5915e
MS
4109
4110 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d",
4111 (int)error));
4112 }
ed486911 4113
ef416fc2 4114 if (!error)
b423cd4c 4115 {
7cf5915e
MS
4116 int done = 0; /* Are we done yet? */
4117
4118 while (!error && !done)
4119 {
4120 error = SSLHandshake(http->tls);
4121
85dda01c 4122 DEBUG_printf(("4http_setup_ssl: SSLHandshake returned %d.", (int)error));
7cf5915e
MS
4123
4124 switch (error)
4125 {
4126 case noErr :
4127 done = 1;
4128 break;
4129
4130 case errSSLWouldBlock :
4131 usleep(1000);
4132 break;
4133
82f97232 4134# ifdef HAVE_SECCERTIFICATECOPYDATA
7cf5915e
MS
4135 case errSSLServerAuthCompleted :
4136 error = 0;
4137 if (cg->server_cert_cb)
4138 {
4139 error = httpCopyCredentials(http, &credentials);
4140 if (!error)
4141 {
4142 error = (cg->server_cert_cb)(http, http->tls, credentials,
4143 cg->server_cert_data);
4144 httpFreeCredentials(credentials);
4145 }
4146
10ddcf65
MS
4147 DEBUG_printf(("4http_setup_ssl: Server certificate callback "
4148 "returned %d.", (int)error));
7cf5915e
MS
4149 }
4150 break;
4151
4152 case errSSLClientCertRequested :
4153 error = 0;
4154
4155 if (cg->client_cert_cb)
4156 {
4157 names = NULL;
82f97232 4158 if (!(error = SSLCopyDistinguishedNames(http->tls, &dn_array)) &&
7cf5915e
MS
4159 dn_array)
4160 {
4161 if ((names = cupsArrayNew(NULL, NULL)) != NULL)
4162 {
4163 for (i = 0, count = CFArrayGetCount(dn_array); i < count; i++)
4164 {
4165 data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i);
4166
4167 if ((credential = malloc(sizeof(*credential))))
4168 {
4169 credential->datalen = CFDataGetLength(data);
4170 if ((credential->data = malloc(credential->datalen)))
4171 {
82f97232 4172 memcpy((void *)credential->data, CFDataGetBytePtr(data),
7cf5915e
MS
4173 credential->datalen);
4174 cupsArrayAdd(names, credential);
4175 }
4176 }
4177 }
4178 }
4179
4180 CFRelease(dn_array);
4181 }
4182
4183 if (!error)
4184 {
82f97232 4185 error = (cg->client_cert_cb)(http, http->tls, names,
7cf5915e
MS
4186 cg->client_cert_data);
4187
85dda01c 4188 DEBUG_printf(("4http_setup_ssl: Client certificate callback "
7cf5915e
MS
4189 "returned %d.", (int)error));
4190 }
4191
4192 httpFreeCredentials(names);
4193 }
4194 break;
82f97232 4195# endif /* HAVE_SECCERTIFICATECOPYDATA */
7cf5915e
MS
4196
4197 case errSSLUnknownRootCert :
4198 message = _("Unable to establish a secure connection to host "
4199 "(untrusted certificate).");
4200 break;
4201
4202 case errSSLNoRootCert :
4203 message = _("Unable to establish a secure connection to host "
4204 "(self-signed certificate).");
4205 break;
4206
4207 case errSSLCertExpired :
4208 message = _("Unable to establish a secure connection to host "
4209 "(expired certificate).");
4210 break;
4211
4212 case errSSLCertNotYetValid :
4213 message = _("Unable to establish a secure connection to host "
4214 "(certificate not yet valid).");
4215 break;
4216
4217 case errSSLHostNameMismatch :
4218 message = _("Unable to establish a secure connection to host "
4219 "(host name mismatch).");
4220 break;
4221
4222 case errSSLXCertChainInvalid :
4223 message = _("Unable to establish a secure connection to host "
4224 "(certificate chain invalid).");
4225 break;
4226
4227 case errSSLConnectionRefused :
4228 message = _("Unable to establish a secure connection to host "
4229 "(peer dropped connection before responding).");
4230 break;
4231
4232 default :
4233 break;
4234 }
4235 }
b423cd4c 4236 }
ef416fc2 4237
89d46774 4238 if (error)
ef416fc2 4239 {
4240 http->error = error;
4241 http->status = HTTP_ERROR;
7cf5915e
MS
4242 errno = ECONNREFUSED;
4243
4244 SSLDisposeContext(http->tls);
4245 http->tls = NULL;
ef416fc2 4246
7cf5915e
MS
4247 /*
4248 * If an error string wasn't set by the callbacks use a generic one...
4249 */
4250
4251 if (!message)
4252#ifdef HAVE_CSSMERRORSTRING
4253 message = cssmErrorString(error);
4254#else
4255 message = _("Unable to establish a secure connection to host.");
4256#endif /* HAVE_CSSMERRORSTRING */
ef416fc2 4257
7cf5915e 4258 _cupsSetError(IPP_PKI_ERROR, message, 1);
ef416fc2 4259
cc754834
MS
4260 return (-1);
4261 }
7cf5915e 4262
cc754834 4263# elif defined(HAVE_SSPISSL)
7cf5915e 4264 http->tls = _sspiAlloc();
cc754834 4265
7cf5915e 4266 if (!http->tls)
a4845881 4267 {
83e08001 4268 _cupsSetHTTPError(HTTP_ERROR);
cc754834 4269 return (-1);
83e08001 4270 }
cc754834 4271
7cf5915e
MS
4272 http->tls->sock = http->fd;
4273 dwSize = sizeof(username) / sizeof(TCHAR);
cc754834
MS
4274 GetUserName(username, &dwSize);
4275 _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
4276 sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
4277
7cf5915e
MS
4278 if (!_sspiGetCredentials(http->tls_credentials, L"ClientContainer",
4279 commonName, FALSE))
cc754834 4280 {
7cf5915e
MS
4281 _sspiFree(http->tls_credentials);
4282 http->tls_credentials = NULL;
a4845881
MS
4283
4284 http->error = EIO;
4285 http->status = HTTP_ERROR;
4286
4287 _cupsSetError(IPP_PKI_ERROR,
4288 _("Unable to establish a secure connection to host."), 1);
4289
cc754834
MS
4290 return (-1);
4291 }
4292
83e08001 4293 _sspiSetAllowsAnyRoot(http->tls_credentials, any_root);
7cf5915e 4294 _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
cc754834 4295
dcb445bc 4296 if (!_sspiConnect(http->tls_credentials, hostname))
cc754834 4297 {
7cf5915e
MS
4298 _sspiFree(http->tls_credentials);
4299 http->tls_credentials = NULL;
a4845881
MS
4300
4301 http->error = EIO;
4302 http->status = HTTP_ERROR;
4303
4304 _cupsSetError(IPP_PKI_ERROR,
4305 _("Unable to establish a secure connection to host."), 1);
4306
ef416fc2 4307 return (-1);
4308 }
4309# endif /* HAVE_CDSASSL */
4310
ef416fc2 4311 return (0);
4312}
ef416fc2 4313
4314
ef416fc2 4315/*
4316 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
4317 */
4318
4319static void
568fa3fa 4320http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 4321{
4322# ifdef HAVE_LIBSSL
89d46774 4323 SSL_CTX *context; /* Context for encryption */
ef416fc2 4324
a4845881 4325 context = SSL_get_SSL_CTX(http->tls);
ef416fc2 4326
a4845881 4327 SSL_shutdown(http->tls);
ef416fc2 4328 SSL_CTX_free(context);
a4845881 4329 SSL_free(http->tls);
ef416fc2 4330
4331# elif defined(HAVE_GNUTLS)
ef416fc2 4332 gnutls_certificate_client_credentials *credentials;
89d46774 4333 /* TLS credentials */
ef416fc2 4334
7cf5915e 4335 credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials);
ef416fc2 4336
7cf5915e
MS
4337 gnutls_bye(http->tls, GNUTLS_SHUT_RDWR);
4338 gnutls_deinit(http->tls);
ef416fc2 4339 gnutls_certificate_free_credentials(*credentials);
4340 free(credentials);
ef416fc2 4341
4342# elif defined(HAVE_CDSASSL)
7cf5915e 4343 while (SSLClose(http->tls) == errSSLWouldBlock)
b423cd4c 4344 usleep(1000);
4345
7cf5915e 4346 SSLDisposeContext(http->tls);
89d46774 4347
7cf5915e
MS
4348 if (http->tls_credentials)
4349 CFRelease(http->tls_credentials);
89d46774 4350
cc754834 4351# elif defined(HAVE_SSPISSL)
7cf5915e 4352 _sspiFree(http->tls_credentials);
ef416fc2 4353# endif /* HAVE_LIBSSL */
4354
7cf5915e
MS
4355 http->tls = NULL;
4356 http->tls_credentials = NULL;
ef416fc2 4357}
4358#endif /* HAVE_SSL */
4359
4360
4361#ifdef HAVE_SSL
4362/*
4363 * 'http_upgrade()' - Force upgrade to TLS encryption.
4364 */
4365
89d46774 4366static int /* O - Status of connection */
568fa3fa 4367http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 4368{
89d46774 4369 int ret; /* Return value */
4370 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 4371
4372
e07d4801 4373 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 4374
85b5d1df
MS
4375 /*
4376 * Flush the connection to make sure any previous "Upgrade" message
4377 * has been read.
4378 */
4379
4380 httpFlush(http);
4381
ef416fc2 4382 /*
4383 * Copy the HTTP data to a local variable so we can do the OPTIONS
4384 * request without interfering with the existing request data...
4385 */
4386
4387 memcpy(&myhttp, http, sizeof(myhttp));
4388
4389 /*
4390 * Send an OPTIONS request to the server, requiring SSL or TLS
4391 * encryption on the link...
4392 */
4393
f7deaa1a 4394 http->field_authorization = NULL; /* Don't free the auth string */
4395
b86bc4cf 4396 httpClearFields(http);
4397 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
7cf5915e 4398 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2, TLS/1.1, TLS/1.0, SSL/3.0");
ef416fc2 4399
b86bc4cf 4400 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 4401 {
4402 /*
4403 * Wait for the secure connection...
4404 */
4405
b86bc4cf 4406 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 4407 }
4408
ef416fc2 4409 /*
b86bc4cf 4410 * Restore the HTTP request data...
ef416fc2 4411 */
4412
b86bc4cf 4413 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 4414 http->data_encoding = myhttp.data_encoding;
4415 http->data_remaining = myhttp.data_remaining;
4416 http->_data_remaining = myhttp._data_remaining;
4417 http->expect = myhttp.expect;
4418 http->field_authorization = myhttp.field_authorization;
bc44d920 4419 http->digest_tries = myhttp.digest_tries;
ef416fc2 4420
4421 /*
4422 * See if we actually went secure...
4423 */
4424
4425 if (!http->tls)
4426 {
4427 /*
4428 * Server does not support HTTP upgrade...
4429 */
4430
e07d4801 4431 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 4432
4433# ifdef WIN32
4434 closesocket(http->fd);
4435# else
4436 close(http->fd);
4437# endif
4438
4439 http->fd = -1;
4440
4441 return (-1);
4442 }
4443 else
4444 return (ret);
4445}
4446#endif /* HAVE_SSL */
4447
4448
ef416fc2 4449/*
4450 * 'http_write()' - Write a buffer to a HTTP connection.
4451 */
ef55b745 4452
ef416fc2 4453static int /* O - Number of bytes written */
568fa3fa 4454http_write(http_t *http, /* I - Connection to server */
f11a948a
MS
4455 const char *buffer, /* I - Buffer for data */
4456 int length) /* I - Number of bytes to write */
ef416fc2 4457{
4458 int tbytes, /* Total bytes sent */
4459 bytes; /* Bytes sent */
4460
4461
f8b3a85b
MS
4462 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=%d)", http, buffer,
4463 length));
f11a948a
MS
4464 http->error = 0;
4465 tbytes = 0;
ef416fc2 4466
4467 while (length > 0)
4468 {
85dda01c
MS
4469 if (http->timeout_cb)
4470 {
4471#ifdef HAVE_POLL
4472 struct pollfd pfd; /* Polled file descriptor */
4473#else
4474 fd_set output_set; /* Output ready for write? */
4475 struct timeval timeout; /* Timeout value */
4476#endif /* HAVE_POLL */
4477 int nfds; /* Result from select()/poll() */
4478
4479 do
4480 {
4481#ifdef HAVE_POLL
4482 pfd.fd = http->fd;
4483 pfd.events = POLLOUT;
4484
4485 while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
4486 (errno == EINTR || errno == EAGAIN));
4487
4488#else
4489 do
4490 {
4491 FD_ZERO(&output_set);
4492 FD_SET(http->fd, &output_set);
4493
4494 timeout.tv_sec = http->wait_value / 1000;
4495 timeout.tv_usec = 1000 * (http->wait_value % 1000);
4496
4497 nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
4498 }
4499# ifdef WIN32
4500 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
4501 WSAGetLastError() == WSAEWOULDBLOCK));
4502# else
4503 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
4504# endif /* WIN32 */
4505#endif /* HAVE_POLL */
4506
4507 if (nfds < 0)
4508 {
4509 http->error = errno;
4510 return (-1);
4511 }
4512 else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
4513 {
4514#ifdef WIN32
83e08001 4515 http->error = WSAEWOULDBLOCK;
85dda01c
MS
4516#else
4517 http->error = EWOULDBLOCK;
4518#endif /* WIN32 */
4519 return (-1);
4520 }
4521 }
4522 while (nfds <= 0);
4523 }
4524
ef416fc2 4525#ifdef HAVE_SSL
4526 if (http->tls)
4527 bytes = http_write_ssl(http, buffer, length);
4528 else
4529#endif /* HAVE_SSL */
4530 bytes = send(http->fd, buffer, length, 0);
4531
4532 if (bytes < 0)
4533 {
4534#ifdef WIN32
10d09e33 4535 if (WSAGetLastError() == WSAEINTR)
cc754834 4536 continue;
10d09e33
MS
4537 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4538 {
4539 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4540 continue;
4541
4542 http->error = WSAGetLastError();
4543 }
4544 else if (WSAGetLastError() != http->error &&
4545 WSAGetLastError() != WSAECONNRESET)
ef416fc2 4546 {
4547 http->error = WSAGetLastError();
4548 continue;
4549 }
10d09e33 4550
ef416fc2 4551#else
10d09e33 4552 if (errno == EINTR)
ef416fc2 4553 continue;
10d09e33
MS
4554 else if (errno == EWOULDBLOCK || errno == EAGAIN)
4555 {
4556 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4557 continue;
4558 else if (!http->timeout_cb && errno == EAGAIN)
4559 continue;
4560
4561 http->error = errno;
4562 }
ef416fc2 4563 else if (errno != http->error && errno != ECONNRESET)
4564 {
4565 http->error = errno;
4566 continue;
4567 }
4568#endif /* WIN32 */
4569
f8b3a85b
MS
4570 DEBUG_printf(("3http_write: error writing data (%s).",
4571 strerror(http->error)));
ef416fc2 4572
4573 return (-1);
4574 }
4575
4576 buffer += bytes;
4577 tbytes += bytes;
4578 length -= bytes;
4579 }
4580
4581#ifdef DEBUG
ae71f5de 4582 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 4583#endif /* DEBUG */
4584
f8b3a85b
MS
4585 DEBUG_printf(("3http_write: Returning %d.", tbytes));
4586
ef416fc2 4587 return (tbytes);
4588}
4589
4590
4591/*
4592 * 'http_write_chunk()' - Write a chunked buffer.
4593 */
4594
4595static int /* O - Number bytes written */
568fa3fa 4596http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 4597 const char *buffer, /* I - Buffer to write */
4598 int length) /* I - Length of buffer */
4599{
4600 char header[255]; /* Chunk header */
4601 int bytes; /* Bytes written */
4602
f11a948a 4603
e07d4801 4604 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
ef416fc2 4605 http, buffer, length));
4606
4607 /*
4608 * Write the chunk header, data, and trailer.
4609 */
4610
4611 sprintf(header, "%x\r\n", length);
b86bc4cf 4612 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 4613 {
e07d4801 4614 DEBUG_puts("8http_write_chunk: http_write of length failed!");
ef416fc2 4615 return (-1);
4616 }
4617
4618 if ((bytes = http_write(http, buffer, length)) < 0)
4619 {
e07d4801 4620 DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
ef416fc2 4621 return (-1);
4622 }
4623
4624 if (http_write(http, "\r\n", 2) < 0)
4625 {
e07d4801 4626 DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
ef416fc2 4627 return (-1);
4628 }
4629
4630 return (bytes);
4631}
4632
4633
4634#ifdef HAVE_SSL
4635/*
4636 * 'http_write_ssl()' - Write to a SSL/TLS connection.
4637 */
4638
4639static int /* O - Bytes written */
568fa3fa 4640http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 4641 const char *buf, /* I - Buffer holding data */
4642 int len) /* I - Length of buffer */
4643{
f8b3a85b
MS
4644 ssize_t result; /* Return value */
4645
4646
4647 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
4648
ef416fc2 4649# if defined(HAVE_LIBSSL)
f8b3a85b 4650 result = SSL_write((SSL *)(http->tls), buf, len);
ef416fc2 4651
4652# elif defined(HAVE_GNUTLS)
7cf5915e 4653 result = gnutls_record_send(http->tls, buf, len);
ef55b745
MS
4654
4655 if (result < 0 && !errno)
4656 {
4657 /*
4658 * Convert GNU TLS error to errno value...
4659 */
4660
4661 switch (result)
4662 {
4663 case GNUTLS_E_INTERRUPTED :
4664 errno = EINTR;
4665 break;
4666
4667 case GNUTLS_E_AGAIN :
4668 errno = EAGAIN;
4669 break;
4670
4671 default :
4672 errno = EPIPE;
4673 break;
4674 }
4675
4676 result = -1;
4677 }
4678
ef416fc2 4679# elif defined(HAVE_CDSASSL)
4680 OSStatus error; /* Error info */
4681 size_t processed; /* Number of bytes processed */
4682
4683
7cf5915e 4684 error = SSLWrite(http->tls, buf, len, &processed);
ef416fc2 4685
fa73b229 4686 switch (error)
ef416fc2 4687 {
fa73b229 4688 case 0 :
4689 result = (int)processed;
4690 break;
84315f46 4691
fa73b229 4692 case errSSLWouldBlock :
b423cd4c 4693 if (processed)
4694 result = (int)processed;
4695 else
4696 {
4697 result = -1;
ef55b745 4698 errno = EINTR;
b423cd4c 4699 }
fa73b229 4700 break;
84315f46
MS
4701
4702 case errSSLClosedGraceful :
fa73b229 4703 default :
84315f46
MS
4704 if (processed)
4705 result = (int)processed;
4706 else
4707 {
4708 result = -1;
4709 errno = EPIPE;
4710 }
fa73b229 4711 break;
ef416fc2 4712 }
cc754834 4713# elif defined(HAVE_SSPISSL)
84315f46 4714 return _sspiWrite((_sspi_struct_t *)http->tls, (void *)buf, len);
ef416fc2 4715# endif /* HAVE_LIBSSL */
f8b3a85b
MS
4716
4717 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
4718
4719 return ((int)result);
ef416fc2 4720}
4721#endif /* HAVE_SSL */
4722
4723
4724/*
b19ccc9e 4725 * End of "$Id: http.c 7850 2008-08-20 00:07:25Z mike $".
ef416fc2 4726 */