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