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