]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Use httpAddrListen and new httpAddrClose in cupsd and other places that need it.
[thirdparty/cups.git] / cups / http.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
996acce8 4 * HTTP routines for CUPS.
ef416fc2 5 *
996acce8
MS
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
996acce8
MS
9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
f7deaa1a 11 *
996acce8
MS
12 * These coded instructions, statements, and computer programs are the
13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
996acce8 18 * This file is subject to the Apple OS-Developed Software exception.
ef416fc2 19 */
20
21/*
22 * Include necessary headers...
23 */
24
71e16022 25#include "cups-private.h"
ef416fc2 26#include <fcntl.h>
83e08001 27#include <math.h>
cc754834
MS
28#ifdef WIN32
29# include <tchar.h>
30#else
ef416fc2 31# include <signal.h>
32# include <sys/time.h>
33# include <sys/resource.h>
cc754834 34#endif /* WIN32 */
f7deaa1a 35#ifdef HAVE_POLL
dcb445bc 36# include <poll.h>
f7deaa1a 37#endif /* HAVE_POLL */
ef416fc2 38
39
ef416fc2 40/*
41 * Local functions...
42 */
43
a469f8a5
MS
44#ifdef HAVE_LIBZ
45static void http_content_coding_finish(http_t *http);
46static void http_content_coding_start(http_t *http,
47 const char *value);
48#endif /* HAVE_LIBZ */
db8b865d
MS
49static http_t *http_create(const char *host, int port,
50 http_addrlist_t *addrlist, int family,
51 http_encryption_t encryption,
52 int blocking, _http_mode_t mode);
ae71f5de
MS
53#ifdef DEBUG
54static void http_debug_hex(const char *prefix, const char *buffer,
55 int bytes);
56#endif /* DEBUG */
0fa6c7fa
MS
57static ssize_t http_read(http_t *http, char *buffer, size_t length);
58static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length);
59static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length);
ef416fc2 60static int http_send(http_t *http, http_state_t request,
61 const char *uri);
0fa6c7fa
MS
62static ssize_t http_write(http_t *http, const char *buffer,
63 size_t length);
64static ssize_t http_write_chunk(http_t *http, const char *buffer,
65 size_t length);
ef416fc2 66#ifdef HAVE_SSL
67static int http_read_ssl(http_t *http, char *buf, int len);
7cf5915e 68static int http_set_credentials(http_t *http);
d7225fc2 69#endif /* HAVE_SSL */
a469f8a5 70static off_t http_set_length(http_t *http);
85dda01c
MS
71static void http_set_timeout(int fd, double timeout);
72static void http_set_wait(http_t *http);
d7225fc2 73#ifdef HAVE_SSL
ef416fc2 74static int http_setup_ssl(http_t *http);
75static void http_shutdown_ssl(http_t *http);
76static int http_upgrade(http_t *http);
77static int http_write_ssl(http_t *http, const char *buf, int len);
78#endif /* HAVE_SSL */
79
80
81/*
82 * Local globals...
83 */
84
85static const char * const http_fields[] =
86 {
87 "Accept-Language",
88 "Accept-Ranges",
89 "Authorization",
90 "Connection",
91 "Content-Encoding",
92 "Content-Language",
93 "Content-Length",
94 "Content-Location",
95 "Content-MD5",
96 "Content-Range",
97 "Content-Type",
98 "Content-Version",
99 "Date",
100 "Host",
101 "If-Modified-Since",
102 "If-Unmodified-since",
103 "Keep-Alive",
104 "Last-Modified",
105 "Link",
106 "Location",
107 "Range",
108 "Referer",
109 "Retry-After",
110 "Transfer-Encoding",
111 "Upgrade",
112 "User-Agent",
a469f8a5
MS
113 "WWW-Authenticate",
114 "Accept-Encoding",
115 "Allow",
116 "Server"
ef416fc2 117 };
118
119
411affcf 120#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
121/*
122 * BIO methods for OpenSSL...
123 */
124
125static int http_bio_write(BIO *h, const char *buf, int num);
126static int http_bio_read(BIO *h, char *buf, int size);
127static int http_bio_puts(BIO *h, const char *str);
128static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
129static int http_bio_new(BIO *h);
130static int http_bio_free(BIO *data);
131
132static BIO_METHOD http_bio_methods =
133 {
134 BIO_TYPE_SOCKET,
135 "http",
136 http_bio_write,
137 http_bio_read,
138 http_bio_puts,
139 NULL, /* http_bio_gets, */
140 http_bio_ctrl,
141 http_bio_new,
142 http_bio_free,
143 NULL,
144 };
7cf5915e 145#endif /* HAVE_SSL && HAVE_LIBSSL */
411affcf 146
147
a469f8a5
MS
148/*
149 * 'httpAcceptConnection()' - Accept a new HTTP client connection from the
150 * specified listening socket.
151 *
9c0e8e5d 152 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
153 */
154
155http_t * /* O - HTTP connection or @code NULL@ */
156httpAcceptConnection(int fd, /* I - Listen socket file descriptor */
157 int blocking) /* I - 1 if the connection should be
158 blocking, 0 otherwise */
159{
160 http_t *http; /* HTTP connection */
161 http_addrlist_t addrlist; /* Dummy address list */
162 socklen_t addrlen; /* Length of address */
163 int val; /* Socket option value */
164
165
166 /*
167 * Range check input...
168 */
169
170 if (fd < 0)
171 return (NULL);
172
173 /*
174 * Create the client connection...
175 */
176
177 memset(&addrlist, 0, sizeof(addrlist));
178
db8b865d 179 if ((http = http_create(NULL, 0, &addrlist, AF_UNSPEC,
a469f8a5
MS
180 HTTP_ENCRYPTION_IF_REQUESTED, blocking,
181 _HTTP_MODE_SERVER)) == NULL)
182 return (NULL);
183
184 /*
185 * Accept the client and get the remote address...
186 */
187
188 addrlen = sizeof(http_addr_t);
189
190 if ((http->fd = accept(fd, (struct sockaddr *)&(http->addrlist->addr),
191 &addrlen)) < 0)
192 {
193 _cupsSetHTTPError(HTTP_STATUS_ERROR);
194 httpClose(http);
195
196 return (NULL);
197 }
198
5ec1fd3d
MS
199 http->hostaddr = &(http->addrlist->addr);
200
201 if (httpAddrLocalhost(http->hostaddr))
202 strlcpy(http->hostname, "localhost", sizeof(http->hostname));
203 else
204 httpAddrString(http->hostaddr, http->hostname, sizeof(http->hostname));
a469f8a5
MS
205
206#ifdef SO_NOSIGPIPE
207 /*
208 * Disable SIGPIPE for this socket.
209 */
210
211 val = 1;
db8b865d 212 setsockopt(http->fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
a469f8a5
MS
213#endif /* SO_NOSIGPIPE */
214
215 /*
216 * Using TCP_NODELAY improves responsiveness, especially on systems
217 * with a slow loopback interface. Since we write large buffers
218 * when sending print files and requests, there shouldn't be any
219 * performance penalty for this...
220 */
221
222 val = 1;
db8b865d 223 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
a469f8a5
MS
224
225#ifdef FD_CLOEXEC
226 /*
227 * Close this socket when starting another process...
228 */
229
230 fcntl(http->fd, F_SETFD, FD_CLOEXEC);
231#endif /* FD_CLOEXEC */
232
233 return (http);
234}
235
236
7cf5915e
MS
237/*
238 * 'httpAddCredential()' - Allocates and adds a single credential to an array.
239 *
240 * Use @code cupsArrayNew(NULL, NULL)@ to create a credentials array.
241 *
f3c17241 242 * @since CUPS 1.5/OS X 10.7@
7cf5915e
MS
243 */
244
245int /* O - 0 on success, -1 on error */
246httpAddCredential(
247 cups_array_t *credentials, /* I - Credentials array */
248 const void *data, /* I - PEM-encoded X.509 data */
249 size_t datalen) /* I - Length of data */
250{
251 http_credential_t *credential; /* Credential data */
252
253
254 if ((credential = malloc(sizeof(http_credential_t))) != NULL)
255 {
256 credential->datalen = datalen;
257
258 if ((credential->data = malloc(datalen)) != NULL)
259 {
260 memcpy(credential->data, data, datalen);
261 cupsArrayAdd(credentials, credential);
262 return (0);
263 }
264
265 free(credential);
266 }
267
268 return (-1);
269}
270
271
272#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
411affcf 273/*
274 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
275 */
276
277BIO_METHOD * /* O - BIO methods for OpenSSL */
278_httpBIOMethods(void)
279{
280 return (&http_bio_methods);
281}
282#endif /* HAVE_SSL && HAVE_LIBSSL */
283
284
ecdc0628 285/*
286 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
287 */
288
289void
e6b1a6a9 290httpBlocking(http_t *http, /* I - HTTP connection */
ecdc0628 291 int b) /* I - 1 = blocking, 0 = non-blocking */
292{
293 if (http)
85dda01c 294 {
ecdc0628 295 http->blocking = b;
85dda01c
MS
296 http_set_wait(http);
297 }
ecdc0628 298}
299
300
ef416fc2 301/*
302 * 'httpCheck()' - Check to see if there is a pending response from the server.
303 */
304
ecdc0628 305int /* O - 0 = no data, 1 = data available */
e6b1a6a9 306httpCheck(http_t *http) /* I - HTTP connection */
ef416fc2 307{
308 return (httpWait(http, 0));
309}
310
311
312/*
313 * 'httpClearCookie()' - Clear the cookie value(s).
314 *
f3c17241 315 * @since CUPS 1.1.19/OS X 10.3@
ef416fc2 316 */
317
318void
e6b1a6a9 319httpClearCookie(http_t *http) /* I - HTTP connection */
ef416fc2 320{
321 if (!http)
322 return;
323
324 if (http->cookie)
325 {
326 free(http->cookie);
327 http->cookie = NULL;
328 }
329}
330
331
ecdc0628 332/*
333 * 'httpClearFields()' - Clear HTTP request fields.
334 */
335
336void
e6b1a6a9 337httpClearFields(http_t *http) /* I - HTTP connection */
ecdc0628 338{
a469f8a5
MS
339 DEBUG_printf(("httpClearFields(http=%p)", http));
340
ecdc0628 341 if (http)
342 {
343 memset(http->fields, 0, sizeof(http->fields));
a469f8a5
MS
344
345 if (http->mode == _HTTP_MODE_CLIENT)
346 {
347 if (http->hostname[0] == '/')
348 httpSetField(http, HTTP_FIELD_HOST, "localhost");
349 else
350 httpSetField(http, HTTP_FIELD_HOST, http->hostname);
351 }
b423cd4c 352
f7deaa1a 353 if (http->field_authorization)
354 {
355 free(http->field_authorization);
356 http->field_authorization = NULL;
357 }
358
a469f8a5
MS
359 if (http->accept_encoding)
360 {
361 _cupsStrFree(http->accept_encoding);
362 http->accept_encoding = NULL;
363 }
364
365 if (http->allow)
366 {
367 _cupsStrFree(http->allow);
368 http->allow = NULL;
369 }
370
371 if (http->server)
372 {
373 _cupsStrFree(http->server);
374 http->server = NULL;
375 }
376
b423cd4c 377 http->expect = (http_status_t)0;
ecdc0628 378 }
379}
380
381
ef416fc2 382/*
6d2f911b 383 * 'httpClose()' - Close an HTTP connection.
ef416fc2 384 */
385
386void
e6b1a6a9 387httpClose(http_t *http) /* I - HTTP connection */
ef416fc2 388{
f7deaa1a 389#ifdef HAVE_GSSAPI
1f0275e3 390 OM_uint32 minor_status; /* Minor status code */
f7deaa1a 391#endif /* HAVE_GSSAPI */
392
393
e07d4801 394 DEBUG_printf(("httpClose(http=%p)", http));
ef416fc2 395
6d2f911b
MS
396 /*
397 * Range check input...
398 */
399
ef416fc2 400 if (!http)
401 return;
402
6d2f911b
MS
403 /*
404 * Close any open connection...
405 */
406
407 _httpDisconnect(http);
408
409 /*
410 * Free memory used...
411 */
412
ef416fc2 413 httpAddrFreeList(http->addrlist);
414
ef416fc2 415 if (http->cookie)
416 free(http->cookie);
417
f7deaa1a 418#ifdef HAVE_GSSAPI
419 if (http->gssctx != GSS_C_NO_CONTEXT)
1f0275e3 420 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
f7deaa1a 421
422 if (http->gssname != GSS_C_NO_NAME)
1f0275e3 423 gss_release_name(&minor_status, &http->gssname);
f7deaa1a 424#endif /* HAVE_GSSAPI */
425
b94498cf 426#ifdef HAVE_AUTHORIZATION_H
427 if (http->auth_ref)
428 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
429#endif /* HAVE_AUTHORIZATION_H */
430
f7deaa1a 431 httpClearFields(http);
432
433 if (http->authstring && http->authstring != http->_authstring)
434 free(http->authstring);
435
ef416fc2 436 free(http);
437}
438
439
440/*
441 * 'httpConnect()' - Connect to a HTTP server.
1ff0402e 442 *
a469f8a5 443 * This function is deprecated - use @link httpConnect2@ instead.
1ff0402e
MS
444 *
445 * @deprecated@
ef416fc2 446 */
447
448http_t * /* O - New HTTP connection */
449httpConnect(const char *host, /* I - Host to connect to */
450 int port) /* I - Port number */
451{
cb7f98ee 452 return (httpConnect2(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED,
a469f8a5 453 1, 30000, NULL));
1ff0402e
MS
454}
455
456
457/*
a469f8a5
MS
458 * 'httpConnect2()' - Connect to a HTTP server.
459 *
9c0e8e5d 460 * @since CUPS 1.7/OS X 10.9@
1ff0402e
MS
461 */
462
463http_t * /* O - New HTTP connection */
a469f8a5 464httpConnect2(
1ff0402e
MS
465 const char *host, /* I - Host to connect to */
466 int port, /* I - Port number */
a469f8a5
MS
467 http_addrlist_t *addrlist, /* I - List of addresses or NULL to lookup */
468 int family, /* I - Address family to use or @code AF_UNSPEC@ for any */
469 http_encryption_t encryption, /* I - Type of encryption to use */
470 int blocking, /* I - 1 for blocking connection, 0 for non-blocking */
db8b865d 471 int msec, /* I - Connection timeout in milliseconds, 0 means don't connect */
a469f8a5 472 int *cancel) /* I - Pointer to "cancel" variable */
1ff0402e
MS
473{
474 http_t *http; /* New HTTP connection */
ef416fc2 475
476
a469f8a5
MS
477 DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, "
478 "encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port,
479 addrlist, family, encryption, blocking, msec, cancel));
1ff0402e 480
ef416fc2 481 /*
1ff0402e 482 * Create the HTTP structure...
ef416fc2 483 */
484
db8b865d 485 if ((http = http_create(host, port, addrlist, family, encryption, blocking,
a469f8a5 486 _HTTP_MODE_CLIENT)) == NULL)
1ff0402e 487 return (NULL);
ef416fc2 488
1ff0402e 489 /*
db8b865d 490 * Optionally connect to the remote system...
1ff0402e
MS
491 */
492
db8b865d 493 if (msec == 0 || !httpReconnect2(http, msec, cancel))
1ff0402e
MS
494 return (http);
495
496 /*
497 * Could not connect to any known address - bail out!
498 */
499
a469f8a5 500 httpClose(http);
1ff0402e
MS
501
502 return (NULL);
ef416fc2 503}
504
505
a469f8a5
MS
506/*
507 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
508 *
509 * This function is now deprecated. Please use the @link httpConnect2@ function
510 * instead.
511 *
512 * @deprecated@
513 */
514
515http_t * /* O - New HTTP connection */
516httpConnectEncrypt(
517 const char *host, /* I - Host to connect to */
518 int port, /* I - Port number */
519 http_encryption_t encryption) /* I - Type of encryption to use */
520{
521 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
522 host, port, encryption));
523
524 return (httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000,
525 NULL));
526}
527
528
7cf5915e
MS
529/*
530 * 'httpCopyCredentials()' - Copy the credentials associated with an encrypted
531 * connection.
532 *
f3c17241 533 * @since CUPS 1.5/OS X 10.7@
7cf5915e
MS
534 */
535
536int /* O - Status of call (0 = success) */
537httpCopyCredentials(
e6b1a6a9 538 http_t *http, /* I - HTTP connection */
7cf5915e
MS
539 cups_array_t **credentials) /* O - Array of credentials */
540{
541# ifdef HAVE_LIBSSL
542# elif defined(HAVE_GNUTLS)
c1420c87 543# elif defined(HAVE_CDSASSL)
7cf5915e 544 OSStatus error; /* Error code */
c1420c87 545 SecTrustRef peerTrust; /* Peer trust reference */
7cf5915e 546 CFIndex count; /* Number of credentials */
7cf5915e
MS
547 SecCertificateRef secCert; /* Certificate reference */
548 CFDataRef data; /* Certificate data */
549 int i; /* Looping var */
550# elif defined(HAVE_SSPISSL)
551# endif /* HAVE_LIBSSL */
552
553
554 if (credentials)
555 *credentials = NULL;
556
557 if (!http || !http->tls || !credentials)
558 return (-1);
559
560# ifdef HAVE_LIBSSL
561 return (-1);
562
563# elif defined(HAVE_GNUTLS)
564 return (-1);
565
c1420c87
MS
566# elif defined(HAVE_CDSASSL)
567 if (!(error = SSLCopyPeerTrust(http->tls, &peerTrust)) && peerTrust)
7cf5915e
MS
568 {
569 if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL)
570 {
c1420c87
MS
571 count = SecTrustGetCertificateCount(peerTrust);
572
573 for (i = 0; i < count; i ++)
7cf5915e 574 {
c1420c87 575 secCert = SecTrustGetCertificateAtIndex(peerTrust, i);
7cf5915e
MS
576 if ((data = SecCertificateCopyData(secCert)))
577 {
578 httpAddCredential(*credentials, CFDataGetBytePtr(data),
579 CFDataGetLength(data));
580 CFRelease(data);
581 }
582 }
583 }
584
c1420c87 585 CFRelease(peerTrust);
7cf5915e
MS
586 }
587
588 return (error);
589
590# elif defined(HAVE_SSPISSL)
591 return (-1);
82f97232
MS
592
593# else
594 return (-1);
7cf5915e
MS
595# endif /* HAVE_LIBSSL */
596}
597
598
85dda01c
MS
599/*
600 * '_httpCreateCredentials()' - Create credentials in the internal format.
601 */
602
603http_tls_credentials_t /* O - Internal credentials */
604_httpCreateCredentials(
605 cups_array_t *credentials) /* I - Array of credentials */
606{
607 if (!credentials)
608 return (NULL);
609
610# ifdef HAVE_LIBSSL
611 return (NULL);
612
613# elif defined(HAVE_GNUTLS)
614 return (NULL);
615
c1420c87 616# elif defined(HAVE_CDSASSL)
85dda01c
MS
617 CFMutableArrayRef peerCerts; /* Peer credentials reference */
618 SecCertificateRef secCert; /* Certificate reference */
619 CFDataRef data; /* Credential data reference */
620 http_credential_t *credential; /* Credential data */
621
622
623 if ((peerCerts = CFArrayCreateMutable(kCFAllocatorDefault,
624 cupsArrayCount(credentials),
625 &kCFTypeArrayCallBacks)) == NULL)
626 return (NULL);
627
628 for (credential = (http_credential_t *)cupsArrayFirst(credentials);
629 credential;
630 credential = (http_credential_t *)cupsArrayNext(credentials))
631 {
632 if ((data = CFDataCreate(kCFAllocatorDefault, credential->data,
633 credential->datalen)))
634 {
635 if ((secCert = SecCertificateCreateWithData(kCFAllocatorDefault, data))
636 != NULL)
637 {
638 CFArrayAppendValue(peerCerts, secCert);
639 CFRelease(secCert);
640 }
641
642 CFRelease(data);
643 }
644 }
645
646 return (peerCerts);
647
648# elif defined(HAVE_SSPISSL)
649 return (NULL);
650
651# else
652 return (NULL);
653# endif /* HAVE_LIBSSL */
654}
655
656
ef416fc2 657/*
658 * 'httpDelete()' - Send a DELETE request to the server.
659 */
660
661int /* O - Status of call (0 = success) */
e6b1a6a9 662httpDelete(http_t *http, /* I - HTTP connection */
ef416fc2 663 const char *uri) /* I - URI to delete */
664{
cb7f98ee 665 return (http_send(http, HTTP_STATE_DELETE, uri));
ef416fc2 666}
667
668
6d2f911b
MS
669/*
670 * '_httpDisconnect()' - Disconnect a HTTP connection.
671 */
672
673void
e6b1a6a9 674_httpDisconnect(http_t *http) /* I - HTTP connection */
6d2f911b
MS
675{
676#ifdef HAVE_SSL
677 if (http->tls)
678 http_shutdown_ssl(http);
679#endif /* HAVE_SSL */
680
87e98392 681 httpAddrClose(NULL, http->fd);
6d2f911b
MS
682
683 http->fd = -1;
684}
685
686
ef416fc2 687/*
688 * 'httpEncryption()' - Set the required encryption on the link.
689 */
690
691int /* O - -1 on error, 0 on success */
e6b1a6a9 692httpEncryption(http_t *http, /* I - HTTP connection */
ef416fc2 693 http_encryption_t e) /* I - New encryption preference */
694{
e07d4801 695 DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
ef416fc2 696
697#ifdef HAVE_SSL
698 if (!http)
699 return (0);
700
701 http->encryption = e;
702
cb7f98ee
MS
703 if ((http->encryption == HTTP_ENCRYPTION_ALWAYS && !http->tls) ||
704 (http->encryption == HTTP_ENCRYPTION_NEVER && http->tls))
705 return (httpReconnect2(http, 30000, NULL));
706 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
ef416fc2 707 return (http_upgrade(http));
708 else
709 return (0);
710#else
cb7f98ee 711 if (e == HTTP_ENCRYPTION_ALWAYS || e == HTTP_ENCRYPTION_REQUIRED)
ef416fc2 712 return (-1);
713 else
714 return (0);
715#endif /* HAVE_SSL */
716}
717
718
ecdc0628 719/*
720 * 'httpError()' - Get the last error on a connection.
721 */
722
723int /* O - Error code (errno) value */
e6b1a6a9 724httpError(http_t *http) /* I - HTTP connection */
ecdc0628 725{
726 if (http)
727 return (http->error);
728 else
729 return (EINVAL);
730}
731
732
48bd1142
MS
733/*
734 * 'httpFieldValue()' - Return the HTTP field enumeration value for a field
735 * name.
736 */
737
738http_field_t /* O - Field index */
739httpFieldValue(const char *name) /* I - String name */
740{
741 int i; /* Looping var */
742
743
744 for (i = 0; i < HTTP_FIELD_MAX; i ++)
745 if (!_cups_strcasecmp(name, http_fields[i]))
746 return ((http_field_t)i);
747
748 return (HTTP_FIELD_UNKNOWN);
749}
750
751
ef416fc2 752/*
753 * 'httpFlush()' - Flush data from a HTTP connection.
754 */
755
756void
e6b1a6a9 757httpFlush(http_t *http) /* I - HTTP connection */
ef416fc2 758{
f8b3a85b
MS
759 char buffer[8192]; /* Junk buffer */
760 int blocking; /* To block or not to block */
761 http_state_t oldstate; /* Old state */
ef416fc2 762
763
f11a948a 764 DEBUG_printf(("httpFlush(http=%p), state=%s", http,
48bd1142 765 httpStateString(http->state)));
ef416fc2 766
c1420c87
MS
767 /*
768 * Nothing to do if we are in the "waiting" state...
769 */
770
771 if (http->state == HTTP_STATE_WAITING)
772 return;
773
fa73b229 774 /*
775 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
776 */
777
778 blocking = http->blocking;
779 http->blocking = 0;
780
781 /*
782 * Read any data we can...
783 */
784
f8b3a85b 785 oldstate = http->state;
a4d04587 786 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 787
788 /*
789 * Restore blocking and reset the connection if we didn't get all of
790 * the remaining data...
791 */
792
793 http->blocking = blocking;
794
a469f8a5
MS
795 if (http->state == oldstate && http->state != HTTP_STATE_WAITING &&
796 http->fd >= 0)
fa73b229 797 {
798 /*
799 * Didn't get the data back, so close the current connection.
800 */
801
c41769ff
MS
802#ifdef HAVE_LIBZ
803 if (http->coding)
804 http_content_coding_finish(http);
805#endif /* HAVE_LIBZ */
806
a469f8a5
MS
807 DEBUG_puts("1httpFlush: Setting state to HTTP_STATE_WAITING and closing.");
808
809 http->state = HTTP_STATE_WAITING;
fa73b229 810
811#ifdef HAVE_SSL
812 if (http->tls)
813 http_shutdown_ssl(http);
814#endif /* HAVE_SSL */
815
87e98392 816 httpAddrClose(NULL, http->fd);
fa73b229 817
818 http->fd = -1;
819 }
ef416fc2 820}
821
822
823/*
824 * 'httpFlushWrite()' - Flush data in write buffer.
825 *
f3c17241 826 * @since CUPS 1.2/OS X 10.5@
ef416fc2 827 */
828
829int /* O - Bytes written or -1 on error */
e6b1a6a9 830httpFlushWrite(http_t *http) /* I - HTTP connection */
ef416fc2 831{
832 int bytes; /* Bytes written */
833
834
a469f8a5
MS
835 DEBUG_printf(("httpFlushWrite(http=%p) data_encoding=%d", http,
836 http ? http->data_encoding : -1));
ef416fc2 837
838 if (!http || !http->wused)
f8b3a85b
MS
839 {
840 DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." :
841 "1httpFlushWrite: No connection.");
ef416fc2 842 return (0);
f8b3a85b 843 }
ef416fc2 844
a469f8a5 845 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
ef416fc2 846 bytes = http_write_chunk(http, http->wbuffer, http->wused);
847 else
848 bytes = http_write(http, http->wbuffer, http->wused);
849
850 http->wused = 0;
851
22c9029b 852 DEBUG_printf(("1httpFlushWrite: Returning %d, errno=%d.", bytes, errno));
f8b3a85b 853
ef416fc2 854 return (bytes);
855}
856
857
7cf5915e
MS
858/*
859 * '_httpFreeCredentials()' - Free internal credentials.
860 */
861
862void
863_httpFreeCredentials(
864 http_tls_credentials_t credentials) /* I - Internal credentials */
865{
866 if (!credentials)
867 return;
868
869#ifdef HAVE_LIBSSL
870 (void)credentials;
871
872#elif defined(HAVE_GNUTLS)
873 (void)credentials;
874
875#elif defined(HAVE_CDSASSL)
876 CFRelease(credentials);
877
878#elif defined(HAVE_SSPISSL)
879 (void)credentials;
880
881#endif /* HAVE_LIBSSL */
882}
883
884
885/*
886 * 'httpFreeCredentials()' - Free an array of credentials.
887 */
888
889void
890httpFreeCredentials(
891 cups_array_t *credentials) /* I - Array of credentials */
892{
893 http_credential_t *credential; /* Credential */
894
895
896 for (credential = (http_credential_t *)cupsArrayFirst(credentials);
897 credential;
898 credential = (http_credential_t *)cupsArrayNext(credentials))
899 {
900 cupsArrayRemove(credentials, credential);
901 free((void *)credential->data);
902 free(credential);
903 }
904
905 cupsArrayDelete(credentials);
906}
907
908
ef416fc2 909/*
910 * 'httpGet()' - Send a GET request to the server.
911 */
912
913int /* O - Status of call (0 = success) */
e6b1a6a9 914httpGet(http_t *http, /* I - HTTP connection */
ef416fc2 915 const char *uri) /* I - URI to get */
916{
cb7f98ee 917 return (http_send(http, HTTP_STATE_GET, uri));
ef416fc2 918}
919
920
e6b1a6a9
MS
921/*
922 * 'httpGetActivity()' - Get the most recent activity for a connection.
923 *
924 * The return value is the UNIX time of the last read or write.
925 *
926 * @since CUPS 2.0@
927 */
928
929time_t /* O - Time of last read or write */
930httpGetActivity(http_t *http) /* I - HTTP connection */
931{
932 return (http ? http->activity : 0);
933}
934
935
6961465f
MS
936/*
937 * 'httpGetAuthString()' - Get the current authorization string.
938 *
939 * The authorization string is set by cupsDoAuthentication() and
940 * httpSetAuthString(). Use httpGetAuthString() to retrieve the
941 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
942 * value.
943 *
944 * @since CUPS 1.3/OS X 10.5@
945 */
946
947char * /* O - Authorization string */
e6b1a6a9 948httpGetAuthString(http_t *http) /* I - HTTP connection */
6961465f
MS
949{
950 if (http)
951 return (http->authstring);
952 else
953 return (NULL);
954}
955
956
957/*
958 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
959 *
960 * @since CUPS 1.2/OS X 10.5@
961 */
962
963int /* O - 1 if blocking, 0 if non-blocking */
e6b1a6a9 964httpGetBlocking(http_t *http) /* I - HTTP connection */
6961465f
MS
965{
966 return (http ? http->blocking : 0);
967}
968
969
a469f8a5
MS
970/*
971 * 'httpGetContentEncoding()' - Get a common content encoding, if any, between
972 * the client and server.
973 *
974 * This function uses the value of the Accepts-Encoding HTTP header and must be
975 * called after receiving a response from the server or a request from the
976 * client. The value returned can be use in subsequent requests (for clients)
977 * or in the response (for servers) in order to compress the content stream.
978 *
9c0e8e5d 979 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
980 */
981
982const char * /* O - Content-Coding value or
983 @code NULL@ for the identity
984 coding. */
985httpGetContentEncoding(http_t *http) /* I - Connection to client/server */
986{
987#ifdef HAVE_LIBZ
988 if (http && http->accept_encoding)
989 {
990 int i; /* Looping var */
991 char temp[HTTP_MAX_VALUE], /* Copy of Accepts-Encoding value */
992 *start, /* Start of coding value */
993 *end; /* End of coding value */
994 double qvalue; /* "qvalue" for coding */
995 struct lconv *loc = localeconv(); /* Locale data */
996 static const char * const codings[] =
997 { /* Supported content codings */
998 "deflate",
999 "gzip",
1000 "x-deflate",
1001 "x-gzip"
1002 };
1003
1004 strlcpy(temp, http->accept_encoding, sizeof(temp));
1005
1006 for (start = temp; *start; start = end)
1007 {
1008 /*
1009 * Find the end of the coding name...
1010 */
1011
1012 qvalue = 1.0;
1013 end = start;
1014 while (*end && *end != ';' && *end != ',' && !isspace(*end & 255))
1015 end ++;
1016
1017 if (*end == ';')
1018 {
1019 /*
1020 * Grab the qvalue as needed...
1021 */
1022
1023 if (!strncmp(end, ";q=", 3))
1024 qvalue = _cupsStrScand(end + 3, NULL, loc);
1025
1026 /*
1027 * Skip past all attributes...
1028 */
1029
1030 *end++ = '\0';
1031 while (*end && *end != ',' && !isspace(*end & 255))
1032 end ++;
1033 }
1034 else if (*end)
1035 *end++ = '\0';
1036
1037 while (*end && isspace(*end & 255))
1038 end ++;
1039
1040 /*
1041 * Check value if it matches something we support...
1042 */
1043
1044 if (qvalue <= 0.0)
1045 continue;
1046
1047 for (i = 0; i < (int)(sizeof(codings) / sizeof(codings[0])); i ++)
1048 if (!strcmp(start, codings[i]))
1049 return (codings[i]);
1050 }
1051 }
1052#endif /* HAVE_LIBZ */
1053
1054 return (NULL);
1055}
1056
1057
ecdc0628 1058/*
1059 * 'httpGetCookie()' - Get any cookie data from the response.
757d2cad 1060 *
f3c17241 1061 * @since CUPS 1.1.19/OS X 10.3@
ecdc0628 1062 */
1063
1064const char * /* O - Cookie data or NULL */
1065httpGetCookie(http_t *http) /* I - HTTP connecion */
1066{
1067 return (http ? http->cookie : NULL);
1068}
1069
1070
5ec1fd3d
MS
1071/*
1072 * 'httpGetEncryption()' - Get the current encryption mode of a connection.
1073 *
1074 * This function returns the encryption mode for the connection. Use the
1075 * @link httpIsEncrypted@ function to determine whether a TLS session has
1076 * been established.
1077 *
1078 * @since CUPS 2.0@
1079 */
1080
1081http_encryption_t /* O - Current encryption mode */
1082httpGetEncryption(http_t *http) /* I - HTTP connection */
1083{
1084 return (http ? http->encryption : HTTP_ENCRYPTION_IF_REQUESTED);
1085}
1086
1087
a469f8a5
MS
1088/*
1089 * 'httpGetExpect()' - Get the value of the Expect header, if any.
1090 *
1091 * Returns @code HTTP_STATUS_NONE@ if there is no Expect header, otherwise
1092 * returns the expected HTTP status code, typically @code HTTP_STATUS_CONTINUE@.
1093 *
9c0e8e5d 1094 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
1095 */
1096
1097http_status_t /* O - Expect: status, if any */
1098httpGetExpect(http_t *http) /* I - Connection to client */
1099{
1100 if (!http)
1101 return (HTTP_STATUS_ERROR);
1102 else
1103 return (http->expect);
1104}
1105
1106
ecdc0628 1107/*
1108 * 'httpGetFd()' - Get the file descriptor associated with a connection.
1109 *
f3c17241 1110 * @since CUPS 1.2/OS X 10.5@
ecdc0628 1111 */
1112
1113int /* O - File descriptor or -1 if none */
e6b1a6a9 1114httpGetFd(http_t *http) /* I - HTTP connection */
ecdc0628 1115{
1116 return (http ? http->fd : -1);
1117}
1118
1119
1120/*
1121 * 'httpGetField()' - Get a field value from a request/response.
1122 */
1123
1124const char * /* O - Field value */
e6b1a6a9 1125httpGetField(http_t *http, /* I - HTTP connection */
ecdc0628 1126 http_field_t field) /* I - Field to get */
1127{
1128 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
1129 return (NULL);
a469f8a5
MS
1130
1131 switch (field)
f7deaa1a 1132 {
a469f8a5
MS
1133 case HTTP_FIELD_ACCEPT_ENCODING :
1134 return (http->accept_encoding);
f7deaa1a 1135
a469f8a5
MS
1136 case HTTP_FIELD_ALLOW :
1137 return (http->allow);
1138
1139 case HTTP_FIELD_SERVER :
1140 return (http->server);
1141
1142 case HTTP_FIELD_AUTHORIZATION :
1143 if (http->field_authorization)
1144 {
1145 /*
1146 * Special case for WWW-Authenticate: as its contents can be
1147 * longer than HTTP_MAX_VALUE...
1148 */
1149
1150 return (http->field_authorization);
1151 }
1152
1153 default :
1154 return (http->fields[field]);
f7deaa1a 1155 }
ecdc0628 1156}
1157
1158
e6b1a6a9
MS
1159/*
1160 * 'httpGetKeepAlive()' - Get the current Keep-Alive state of the connection.
1161 *
1162 * @since CUPS 2.0@
1163 */
1164
1165http_keepalive_t /* O - Keep-Alive state */
1166httpGetKeepAlive(http_t *http) /* I - HTTP connection */
1167{
1168 return (http ? http->keep_alive : HTTP_KEEPALIVE_OFF);
1169}
1170
1171
ecdc0628 1172/*
1173 * 'httpGetLength()' - Get the amount of data remaining from the
1174 * content-length or transfer-encoding fields.
1175 *
1176 * This function is deprecated and will not return lengths larger than
1177 * 2^31 - 1; use httpGetLength2() instead.
1178 *
1179 * @deprecated@
1180 */
1181
1182int /* O - Content length */
e6b1a6a9 1183httpGetLength(http_t *http) /* I - HTTP connection */
ecdc0628 1184{
1185 /*
1186 * Get the read content length and return the 32-bit value.
1187 */
1188
1189 if (http)
1190 {
1191 httpGetLength2(http);
1192
1193 return (http->_data_remaining);
1194 }
1195 else
1196 return (-1);
1197}
1198
1199
1200/*
1201 * 'httpGetLength2()' - Get the amount of data remaining from the
1202 * content-length or transfer-encoding fields.
1203 *
1204 * This function returns the complete content length, even for
1205 * content larger than 2^31 - 1.
1206 *
f3c17241 1207 * @since CUPS 1.2/OS X 10.5@
ecdc0628 1208 */
1209
1210off_t /* O - Content length */
e6b1a6a9 1211httpGetLength2(http_t *http) /* I - HTTP connection */
ecdc0628 1212{
a469f8a5
MS
1213 off_t remaining; /* Remaining length */
1214
1215
f11a948a 1216 DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
48bd1142 1217 httpStateString(http->state)));
ecdc0628 1218
1219 if (!http)
1220 return (-1);
1221
88f9aafc 1222 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
ecdc0628 1223 {
e07d4801 1224 DEBUG_puts("4httpGetLength2: chunked request!");
a469f8a5 1225 remaining = 0;
ecdc0628 1226 }
1227 else
1228 {
ecdc0628 1229 /*
1230 * The following is a hack for HTTP servers that don't send a
a469f8a5 1231 * Content-Length or Transfer-Encoding field...
ecdc0628 1232 *
a469f8a5 1233 * If there is no Content-Length then the connection must close
ecdc0628 1234 * after the transfer is complete...
1235 */
1236
b86bc4cf 1237 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
1238 {
1239 /*
a469f8a5
MS
1240 * Default content length is 0 for errors and certain types of operations,
1241 * and 2^31-1 for other successful requests...
b86bc4cf 1242 */
1243
cb7f98ee 1244 if (http->status >= HTTP_STATUS_MULTIPLE_CHOICES ||
a469f8a5
MS
1245 http->state == HTTP_STATE_OPTIONS ||
1246 (http->state == HTTP_STATE_GET && http->mode == _HTTP_MODE_SERVER) ||
1247 http->state == HTTP_STATE_HEAD ||
1248 (http->state == HTTP_STATE_PUT && http->mode == _HTTP_MODE_CLIENT) ||
1249 http->state == HTTP_STATE_DELETE ||
1250 http->state == HTTP_STATE_TRACE ||
1251 http->state == HTTP_STATE_CONNECT)
1252 remaining = 0;
b86bc4cf 1253 else
a469f8a5 1254 remaining = 2147483647;
b86bc4cf 1255 }
a469f8a5
MS
1256 else if ((remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
1257 NULL, 10)) < 0)
1258 remaining = -1;
ecdc0628 1259
e07d4801 1260 DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
a469f8a5 1261 CUPS_LLCAST remaining));
ecdc0628 1262 }
1263
a469f8a5 1264 return (remaining);
ecdc0628 1265}
1266
1267
d21dc0ed
MS
1268/*
1269 * 'httpGetPending()' - Get the number of bytes that are buffered for writing.
1270 *
1271 * @since CUPS 2.0@
1272 */
1273
1274size_t /* O - Number of bytes buffered */
1275httpGetPending(http_t *http) /* I - HTTP connection */
1276{
1277 return (http ? http->wused : 0);
1278}
1279
1280
e6b1a6a9
MS
1281/*
1282 * 'httpGetReady()' - Get the number of bytes that can be read without blocking.
1283 *
1284 * @since CUPS 2.0@
1285 */
1286
1287size_t /* O - Number of bytes available */
1288httpGetReady(http_t *http) /* I - HTTP connection */
1289{
1290 if (!http)
1291 return (0);
1292 else if (http->used > 0)
1293 return (http->used);
1294#ifdef HAVE_SSL
1295 else if (http->tls)
1296 {
1297 size_t ready; /* Ready bytes */
1298
1299# ifdef HAVE_LIBSSL
1300 if ((ready = SSL_pending((SSL *)(http->tls))) > 0)
1301 return (ready);
1302# elif defined(HAVE_GNUTLS)
1303 if ((ready = gnutls_record_check_pending(http->tls)) > 0)
1304 return (ready);
1305# elif defined(HAVE_CDSASSL)
1306 if (!SSLGetBufferedReadSize(http->tls, &ready) && ready > 0)
1307 return (ready);
1308# endif /* HAVE_LIBSSL */
1309 }
1310#endif /* HAVE_SSL */
1311
1312 return (0);
1313}
1314
1315
5ec1fd3d
MS
1316/*
1317 * 'httpGetRemaining()' - Get the number of remaining bytes in the message
1318 * body or current chunk.
1319 *
1320 * The @link httpIsChunked@ function can be used to determine whether the
1321 * message body is chunked or fixed-length.
1322 *
1323 * @since CUPS 2.0@
1324 */
1325
1326size_t /* O - Remaining bytes */
1327httpGetRemaining(http_t *http) /* I - HTTP connection */
1328{
1329 return (http ? http->data_remaining : 0);
1330}
1331
1332
ef416fc2 1333/*
1334 * 'httpGets()' - Get a line of text from a HTTP connection.
1335 */
1336
1337char * /* O - Line or NULL */
1338httpGets(char *line, /* I - Line to read into */
1339 int length, /* I - Max length of buffer */
e6b1a6a9 1340 http_t *http) /* I - HTTP connection */
ef416fc2 1341{
1342 char *lineptr, /* Pointer into line */
1343 *lineend, /* End of line */
1344 *bufptr, /* Pointer into input buffer */
1345 *bufend; /* Pointer to end of buffer */
1346 int bytes, /* Number of bytes read */
1347 eol; /* End-of-line? */
1348
1349
e07d4801 1350 DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
ef416fc2 1351
0fa6c7fa 1352 if (!http || !line || length <= 1)
ef416fc2 1353 return (NULL);
1354
1355 /*
1356 * Read a line from the buffer...
1357 */
f11a948a
MS
1358
1359 http->error = 0;
1360 lineptr = line;
1361 lineend = line + length - 1;
1362 eol = 0;
ef416fc2 1363
1364 while (lineptr < lineend)
1365 {
1366 /*
1367 * Pre-load the buffer as needed...
1368 */
1369
1370#ifdef WIN32
1371 WSASetLastError(0);
1372#else
1373 errno = 0;
1374#endif /* WIN32 */
1375
1376 while (http->used == 0)
1377 {
1378 /*
1379 * No newline; see if there is more data to be read...
1380 */
1381
85dda01c 1382 while (!_httpWait(http, http->wait_value, 1))
89d46774 1383 {
f228370c
MS
1384 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1385 continue;
1386
e07d4801 1387 DEBUG_puts("3httpGets: Timed out!");
b86bc4cf 1388#ifdef WIN32
1389 http->error = WSAETIMEDOUT;
1390#else
89d46774 1391 http->error = ETIMEDOUT;
b86bc4cf 1392#endif /* WIN32 */
ef416fc2 1393 return (NULL);
89d46774 1394 }
ef416fc2 1395
0fa6c7fa
MS
1396 bytes = http_read(http, http->buffer + http->used,
1397 HTTP_MAX_BUFFER - http->used);
ef416fc2 1398
0fa6c7fa 1399 DEBUG_printf(("4httpGets: read %d bytes.", bytes));
12f89d24 1400
ef416fc2 1401 if (bytes < 0)
1402 {
1403 /*
1404 * Nope, can't get a line this time...
1405 */
1406
1407#ifdef WIN32
cc754834
MS
1408 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
1409
10d09e33 1410 if (WSAGetLastError() == WSAEINTR)
cc754834 1411 continue;
10d09e33
MS
1412 else if (WSAGetLastError() == WSAEWOULDBLOCK)
1413 {
1414 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1415 continue;
1416
1417 http->error = WSAGetLastError();
1418 }
cc754834 1419 else if (WSAGetLastError() != http->error)
ef416fc2 1420 {
1421 http->error = WSAGetLastError();
1422 continue;
1423 }
1424
ef416fc2 1425#else
e07d4801 1426 DEBUG_printf(("3httpGets: recv() error %d!", errno));
ef416fc2 1427
10d09e33 1428 if (errno == EINTR)
ef416fc2 1429 continue;
10d09e33
MS
1430 else if (errno == EWOULDBLOCK || errno == EAGAIN)
1431 {
1432 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1433 continue;
1434 else if (!http->timeout_cb && errno == EAGAIN)
1435 continue;
1436
1437 http->error = errno;
1438 }
ef416fc2 1439 else if (errno != http->error)
1440 {
1441 http->error = errno;
1442 continue;
1443 }
1444#endif /* WIN32 */
1445
1446 return (NULL);
1447 }
1448 else if (bytes == 0)
1449 {
1450 http->error = EPIPE;
1451
1452 return (NULL);
1453 }
1454
1455 /*
1456 * Yup, update the amount used...
1457 */
1458
1459 http->used += bytes;
1460 }
1461
1462 /*
1463 * Now copy as much of the current line as possible...
1464 */
1465
1466 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1467 lineptr < lineend && bufptr < bufend;)
1468 {
1469 if (*bufptr == 0x0a)
1470 {
1471 eol = 1;
1472 bufptr ++;
1473 break;
1474 }
1475 else if (*bufptr == 0x0d)
1476 bufptr ++;
1477 else
1478 *lineptr++ = *bufptr++;
1479 }
1480
b86bc4cf 1481 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1482 if (http->used > 0)
1483 memmove(http->buffer, bufptr, http->used);
1484
1485 if (eol)
1486 {
1487 /*
1488 * End of line...
1489 */
1490
1491 http->activity = time(NULL);
1492
1493 *lineptr = '\0';
ef55b745 1494
e07d4801 1495 DEBUG_printf(("3httpGets: Returning \"%s\"", line));
ef416fc2 1496
1497 return (line);
1498 }
1499 }
1500
e07d4801 1501 DEBUG_puts("3httpGets: No new line available!");
ef416fc2 1502
1503 return (NULL);
1504}
1505
1506
a2326b5b
MS
1507/*
1508 * 'httpGetState()' - Get the current state of the HTTP request.
1509 */
1510
1511http_state_t /* O - HTTP state */
e6b1a6a9 1512httpGetState(http_t *http) /* I - HTTP connection */
a2326b5b 1513{
a469f8a5 1514 return (http ? http->state : HTTP_STATE_ERROR);
a2326b5b
MS
1515}
1516
1517
1518/*
1519 * 'httpGetStatus()' - Get the status of the last HTTP request.
1520 *
f3c17241 1521 * @since CUPS 1.2/OS X 10.5@
a2326b5b
MS
1522 */
1523
1524http_status_t /* O - HTTP status */
e6b1a6a9 1525httpGetStatus(http_t *http) /* I - HTTP connection */
a2326b5b 1526{
cb7f98ee 1527 return (http ? http->status : HTTP_STATUS_ERROR);
a2326b5b
MS
1528}
1529
1530
1531/*
1532 * 'httpGetSubField()' - Get a sub-field value.
1533 *
1534 * @deprecated@
1535 */
1536
1537char * /* O - Value or NULL */
e6b1a6a9 1538httpGetSubField(http_t *http, /* I - HTTP connection */
a2326b5b
MS
1539 http_field_t field, /* I - Field index */
1540 const char *name, /* I - Name of sub-field */
1541 char *value) /* O - Value string */
1542{
1543 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
1544}
1545
1546
1547/*
1548 * 'httpGetSubField2()' - Get a sub-field value.
1549 *
f3c17241 1550 * @since CUPS 1.2/OS X 10.5@
a2326b5b
MS
1551 */
1552
1553char * /* O - Value or NULL */
e6b1a6a9 1554httpGetSubField2(http_t *http, /* I - HTTP connection */
a2326b5b
MS
1555 http_field_t field, /* I - Field index */
1556 const char *name, /* I - Name of sub-field */
1557 char *value, /* O - Value string */
1558 int valuelen) /* I - Size of value buffer */
1559{
1560 const char *fptr; /* Pointer into field */
1561 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
1562 *ptr, /* Pointer into string buffer */
1563 *end; /* End of value buffer */
1564
1565 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
1566 "valuelen=%d)", http, field, name, value, valuelen));
1567
1568 if (!http || !name || !value || valuelen < 2 ||
1569 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
1570 return (NULL);
1571
1572 end = value + valuelen - 1;
1573
1574 for (fptr = http->fields[field]; *fptr;)
1575 {
1576 /*
1577 * Skip leading whitespace...
1578 */
1579
1580 while (_cups_isspace(*fptr))
1581 fptr ++;
1582
1583 if (*fptr == ',')
1584 {
1585 fptr ++;
1586 continue;
1587 }
1588
1589 /*
1590 * Get the sub-field name...
1591 */
1592
1593 for (ptr = temp;
1594 *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
1595 ptr < (temp + sizeof(temp) - 1);
1596 *ptr++ = *fptr++);
1597
1598 *ptr = '\0';
1599
1600 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
1601
1602 /*
1603 * Skip trailing chars up to the '='...
1604 */
1605
1606 while (_cups_isspace(*fptr))
1607 fptr ++;
1608
1609 if (!*fptr)
1610 break;
1611
1612 if (*fptr != '=')
1613 continue;
1614
1615 /*
1616 * Skip = and leading whitespace...
1617 */
1618
1619 fptr ++;
1620
1621 while (_cups_isspace(*fptr))
1622 fptr ++;
1623
1624 if (*fptr == '\"')
1625 {
1626 /*
1627 * Read quoted string...
1628 */
1629
1630 for (ptr = value, fptr ++;
1631 *fptr && *fptr != '\"' && ptr < end;
1632 *ptr++ = *fptr++);
1633
1634 *ptr = '\0';
1635
1636 while (*fptr && *fptr != '\"')
1637 fptr ++;
1638
1639 if (*fptr)
1640 fptr ++;
1641 }
1642 else
1643 {
1644 /*
1645 * Read unquoted string...
1646 */
1647
1648 for (ptr = value;
1649 *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
1650 *ptr++ = *fptr++);
1651
1652 *ptr = '\0';
1653
1654 while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
1655 fptr ++;
1656 }
1657
1658 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
1659
1660 /*
1661 * See if this is the one...
1662 */
1663
1664 if (!strcmp(name, temp))
1665 {
1666 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
1667 return (value);
1668 }
1669 }
1670
1671 value[0] = '\0';
1672
1673 DEBUG_puts("3httpGetSubField2: Returning NULL");
1674
1675 return (NULL);
1676}
1677
1678
1679/*
1680 * 'httpGetVersion()' - Get the HTTP version at the other end.
1681 */
1682
1683http_version_t /* O - Version number */
e6b1a6a9 1684httpGetVersion(http_t *http) /* I - HTTP connection */
a2326b5b 1685{
a469f8a5 1686 return (http ? http->version : HTTP_VERSION_1_0);
a2326b5b
MS
1687}
1688
1689
ef416fc2 1690/*
1691 * 'httpHead()' - Send a HEAD request to the server.
1692 */
1693
1694int /* O - Status of call (0 = success) */
e6b1a6a9 1695httpHead(http_t *http, /* I - HTTP connection */
ef416fc2 1696 const char *uri) /* I - URI for head */
1697{
e07d4801 1698 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
cb7f98ee 1699 return (http_send(http, HTTP_STATE_HEAD, uri));
ef416fc2 1700}
1701
1702
1703/*
1704 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1705 * default HTTP proxy (if any).
1706 */
1707
1708void
1709httpInitialize(void)
1710{
6d2f911b
MS
1711 static int initialized = 0; /* Have we been called before? */
1712#ifdef WIN32
1713 WSADATA winsockdata; /* WinSock data */
1714#endif /* WIN32 */
ef416fc2 1715#ifdef HAVE_LIBSSL
6d2f911b
MS
1716 int i; /* Looping var */
1717 unsigned char data[1024]; /* Seed data */
ef416fc2 1718#endif /* HAVE_LIBSSL */
1719
ef416fc2 1720
6d2f911b
MS
1721 _cupsGlobalLock();
1722 if (initialized)
1723 {
1724 _cupsGlobalUnlock();
1725 return;
1726 }
1727
1728#ifdef WIN32
c7017ecc 1729 WSAStartup(MAKEWORD(2,2), &winsockdata);
ef416fc2 1730
fa73b229 1731#elif !defined(SO_NOSIGPIPE)
ef416fc2 1732 /*
1733 * Ignore SIGPIPE signals...
1734 */
1735
fa73b229 1736# ifdef HAVE_SIGSET
1737 sigset(SIGPIPE, SIG_IGN);
6d2f911b 1738
fa73b229 1739# elif defined(HAVE_SIGACTION)
1740 struct sigaction action; /* POSIX sigaction data */
1741
1742
ef416fc2 1743 memset(&action, 0, sizeof(action));
1744 action.sa_handler = SIG_IGN;
1745 sigaction(SIGPIPE, &action, NULL);
6d2f911b 1746
fa73b229 1747# else
ef416fc2 1748 signal(SIGPIPE, SIG_IGN);
fa73b229 1749# endif /* !SO_NOSIGPIPE */
ef416fc2 1750#endif /* WIN32 */
1751
1752#ifdef HAVE_GNUTLS
6d2f911b
MS
1753 /*
1754 * Initialize GNU TLS...
1755 */
1756
ef416fc2 1757 gnutls_global_init();
ef416fc2 1758
6d2f911b
MS
1759#elif defined(HAVE_LIBSSL)
1760 /*
1761 * Initialize OpenSSL...
1762 */
1763
ef416fc2 1764 SSL_load_error_strings();
1765 SSL_library_init();
1766
1767 /*
1768 * Using the current time is a dubious random seed, but on some systems
1769 * it is the best we can do (on others, this seed isn't even used...)
1770 */
1771
6d2f911b 1772 CUPS_SRAND(time(NULL));
ef416fc2 1773
1774 for (i = 0; i < sizeof(data); i ++)
6d2f911b 1775 data[i] = CUPS_RAND();
ef416fc2 1776
dfd5680b 1777 RAND_seed(data, sizeof(data));
6d2f911b
MS
1778#endif /* HAVE_GNUTLS */
1779
1780 initialized = 1;
1781 _cupsGlobalUnlock();
ef416fc2 1782}
1783
1784
5ec1fd3d
MS
1785/*
1786 * 'httpIsChunked()' - Report whether a message body is chunked.
1787 *
1788 * This function returns non-zero if the message body is composed of
1789 * variable-length chunks.
1790 *
1791 * @since CUPS 2.0@
1792 */
1793
1794int /* O - 1 if chunked, 0 if not */
1795httpIsChunked(http_t *http) /* I - HTTP connection */
1796{
1797 return (http ? http->data_encoding == HTTP_ENCODING_CHUNKED : 0);
1798}
1799
1800
1801/*
1802 * 'httpIsEncrypted()' - Report whether a connection is encrypted.
1803 *
1804 * This function returns non-zero if the connection is currently encrypted.
1805 *
1806 * @since CUPS 2.0@
1807 */
1808
1809int /* O - 1 if encrypted, 0 if not */
1810httpIsEncrypted(http_t *http) /* I - HTTP connection */
1811{
1812 return (http ? http->tls != NULL : 0);
1813}
1814
1815
ef416fc2 1816/*
1817 * 'httpOptions()' - Send an OPTIONS request to the server.
1818 */
1819
1820int /* O - Status of call (0 = success) */
e6b1a6a9 1821httpOptions(http_t *http, /* I - HTTP connection */
ef416fc2 1822 const char *uri) /* I - URI for options */
1823{
cb7f98ee 1824 return (http_send(http, HTTP_STATE_OPTIONS, uri));
ef416fc2 1825}
1826
1827
6d2f911b 1828/*
a469f8a5 1829 * 'httpPeek()' - Peek at data from a HTTP connection.
6d2f911b
MS
1830 *
1831 * This function copies available data from the given HTTP connection, reading
1832 * a buffer as needed. The data is still available for reading using
1833 * @link httpRead@ or @link httpRead2@.
1834 *
1835 * For non-blocking connections the usual timeouts apply.
a469f8a5 1836 *
9c0e8e5d 1837 * @since CUPS 1.7/OS X 10.9@
6d2f911b
MS
1838 */
1839
1840ssize_t /* O - Number of bytes copied */
e6b1a6a9 1841httpPeek(http_t *http, /* I - HTTP connection */
0fa6c7fa
MS
1842 char *buffer, /* I - Buffer for data */
1843 size_t length) /* I - Maximum number of bytes */
6d2f911b
MS
1844{
1845 ssize_t bytes; /* Bytes read */
1846 char len[32]; /* Length string */
1847
1848
a469f8a5 1849 DEBUG_printf(("httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
6d2f911b
MS
1850 http, buffer, CUPS_LLCAST length));
1851
1852 if (http == NULL || buffer == NULL)
1853 return (-1);
1854
1855 http->activity = time(NULL);
1856 http->error = 0;
1857
1858 if (length <= 0)
1859 return (0);
1860
a469f8a5 1861 if (http->data_encoding == HTTP_ENCODING_CHUNKED &&
6d2f911b
MS
1862 http->data_remaining <= 0)
1863 {
a469f8a5 1864 DEBUG_puts("2httpPeek: Getting chunk length...");
6d2f911b
MS
1865
1866 if (httpGets(len, sizeof(len), http) == NULL)
1867 {
a469f8a5 1868 DEBUG_puts("1httpPeek: Could not get length!");
6d2f911b
MS
1869 return (0);
1870 }
1871
db8b865d
MS
1872 if (!len[0])
1873 {
1874 DEBUG_puts("1httpPeek: Blank chunk length, trying again...");
1875 if (!httpGets(len, sizeof(len), http))
1876 {
1877 DEBUG_puts("1httpPeek: Could not get chunk length.");
1878 return (0);
1879 }
1880 }
1881
6d2f911b 1882 http->data_remaining = strtoll(len, NULL, 16);
db8b865d 1883
6d2f911b
MS
1884 if (http->data_remaining < 0)
1885 {
a469f8a5 1886 DEBUG_puts("1httpPeek: Negative chunk length!");
6d2f911b
MS
1887 return (0);
1888 }
1889 }
1890
a469f8a5 1891 DEBUG_printf(("2httpPeek: data_remaining=" CUPS_LLFMT,
6d2f911b
MS
1892 CUPS_LLCAST http->data_remaining));
1893
0fa6c7fa 1894 if (http->data_remaining <= 0 && http->data_encoding != HTTP_ENCODING_FIELDS)
6d2f911b
MS
1895 {
1896 /*
1897 * A zero-length chunk ends a transfer; unless we are reading POST
1898 * data, go idle...
1899 */
1900
c41769ff
MS
1901#ifdef HAVE_LIBZ
1902 if (http->coding)
1903 http_content_coding_finish(http);
1904#endif /* HAVE_LIBZ */
1905
0fa6c7fa
MS
1906 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
1907 httpGets(len, sizeof(len), http);
1908
a469f8a5 1909 if (http->state == HTTP_STATE_POST_RECV)
6d2f911b
MS
1910 http->state ++;
1911 else
cb7f98ee 1912 http->state = HTTP_STATE_STATUS;
a469f8a5
MS
1913
1914 DEBUG_printf(("1httpPeek: 0-length chunk, set state to %s.",
48bd1142 1915 httpStateString(http->state)));
6d2f911b
MS
1916
1917 /*
1918 * Prevent future reads for this request...
1919 */
1920
a469f8a5 1921 http->data_encoding = HTTP_ENCODING_FIELDS;
6d2f911b
MS
1922
1923 return (0);
1924 }
0fa6c7fa 1925 else if (length > (size_t)http->data_remaining)
6d2f911b
MS
1926 length = (size_t)http->data_remaining;
1927
0fa6c7fa
MS
1928#ifdef HAVE_LIBZ
1929 if (http->used == 0 &&
1930 (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0))
1931#else
6d2f911b 1932 if (http->used == 0)
0fa6c7fa 1933#endif /* HAVE_LIBZ */
6d2f911b
MS
1934 {
1935 /*
1936 * Buffer small reads for better performance...
1937 */
1938
3e7fe0ca
MS
1939 ssize_t buflen; /* Length of read for buffer */
1940
f228370c
MS
1941 if (!http->blocking)
1942 {
85dda01c 1943 while (!httpWait(http, http->wait_value))
f228370c
MS
1944 {
1945 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
1946 continue;
1947
1948 return (0);
1949 }
1950 }
6d2f911b
MS
1951
1952 if (http->data_remaining > sizeof(http->buffer))
3e7fe0ca 1953 buflen = sizeof(http->buffer);
6d2f911b 1954 else
3e7fe0ca
MS
1955 buflen = http->data_remaining;
1956
a469f8a5 1957 DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen));
db8b865d 1958 bytes = http_read(http, http->buffer, buflen);
3e7fe0ca 1959
a469f8a5 1960 DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.",
3e7fe0ca 1961 CUPS_LLCAST bytes));
db8b865d
MS
1962 if (bytes > 0)
1963 {
3e7fe0ca 1964#ifdef DEBUG
db8b865d 1965 http_debug_hex("httpPeek", http->buffer, (int)bytes);
3e7fe0ca
MS
1966#endif /* DEBUG */
1967
db8b865d
MS
1968 http->used = bytes;
1969 }
6d2f911b
MS
1970 }
1971
c1420c87
MS
1972#ifdef HAVE_LIBZ
1973 if (http->coding)
1974 {
db8b865d 1975# ifdef HAVE_INFLATECOPY
c1420c87 1976 int zerr; /* Decompressor error */
c1420c87
MS
1977 z_stream stream; /* Copy of decompressor stream */
1978
0fa6c7fa
MS
1979 if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER)
1980 {
1981 size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
1982 /* Number of bytes to copy */
1983
1984 if (http->stream.avail_in > 0 &&
1985 http->stream.next_in > http->dbuffer)
1986 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
1987
1988 http->stream.next_in = http->dbuffer;
1989
1990 if (buflen > http->data_remaining)
1991 buflen = http->data_remaining;
1992
1993 if (buflen > http->used)
1994 buflen = http->used;
1995
1996 DEBUG_printf(("1httpPeek: Copying %d more bytes of data into "
1997 "decompression buffer.", (int)buflen));
1998
1999 memcpy(http->dbuffer + http->stream.avail_in, http->buffer, buflen);
2000 http->stream.avail_in += buflen;
2001 http->used -= buflen;
2002 http->data_remaining -= buflen;
2003
2004 if (http->used > 0)
2005 memmove(http->buffer, http->buffer + buflen, http->used);
2006 }
c1420c87
MS
2007
2008 DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length,
0fa6c7fa 2009 (int)http->stream.avail_in));
c1420c87
MS
2010
2011 if (inflateCopy(&stream, &(http->stream)) != Z_OK)
2012 {
2013 DEBUG_puts("2httpPeek: Unable to copy decompressor stream.");
2014 http->error = ENOMEM;
2015 return (-1);
2016 }
2017
c1420c87
MS
2018 stream.next_out = (Bytef *)buffer;
2019 stream.avail_out = length;
2020
2021 zerr = inflate(&stream, Z_SYNC_FLUSH);
2022 inflateEnd(&stream);
2023
2024 if (zerr < Z_OK)
2025 {
2026 DEBUG_printf(("2httpPeek: zerr=%d", zerr));
0fa6c7fa
MS
2027#ifdef DEBUG
2028 http_debug_hex("2httpPeek", (char *)http->dbuffer,
2029 http->stream.avail_in);
2030#endif /* DEBUG */
2031
c1420c87
MS
2032 http->error = EIO;
2033 return (-1);
2034 }
2035
2036 bytes = length - http->stream.avail_out;
db8b865d
MS
2037
2038# else
2039 DEBUG_puts("2httpPeek: No inflateCopy on this platform, httpPeek does not "
2040 "work with compressed streams.");
2041 return (-1);
2042# endif /* HAVE_INFLATECOPY */
c1420c87
MS
2043 }
2044 else
2045#endif /* HAVE_LIBZ */
6d2f911b
MS
2046 if (http->used > 0)
2047 {
2048 if (length > (size_t)http->used)
2049 length = (size_t)http->used;
2050
2051 bytes = (ssize_t)length;
2052
a469f8a5 2053 DEBUG_printf(("2httpPeek: grabbing %d bytes from input buffer...",
6d2f911b
MS
2054 (int)bytes));
2055
2056 memcpy(buffer, http->buffer, length);
2057 }
2058 else
2059 bytes = 0;
2060
2061 if (bytes < 0)
2062 {
2063#ifdef WIN32
cc754834
MS
2064 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)
2065 bytes = 0;
2066 else
2067 http->error = WSAGetLastError();
6d2f911b
MS
2068#else
2069 if (errno == EINTR || errno == EAGAIN)
2070 bytes = 0;
2071 else
2072 http->error = errno;
2073#endif /* WIN32 */
2074 }
2075 else if (bytes == 0)
2076 {
2077 http->error = EPIPE;
2078 return (0);
2079 }
2080
6d2f911b
MS
2081 return (bytes);
2082}
2083
c1420c87
MS
2084/* For OS X 10.8 and earlier */
2085ssize_t _httpPeek(http_t *http, char *buffer, size_t length)
2086{ return (httpPeek(http, buffer, length)); }
2087
6d2f911b 2088
ef416fc2 2089/*
2090 * 'httpPost()' - Send a POST request to the server.
2091 */
2092
2093int /* O - Status of call (0 = success) */
e6b1a6a9 2094httpPost(http_t *http, /* I - HTTP connection */
ef416fc2 2095 const char *uri) /* I - URI for post */
2096{
cb7f98ee 2097 return (http_send(http, HTTP_STATE_POST, uri));
ef416fc2 2098}
2099
2100
2101/*
2102 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 2103 *
2104 * @private@
ef416fc2 2105 */
2106
2107int /* O - Number of bytes written */
e6b1a6a9 2108httpPrintf(http_t *http, /* I - HTTP connection */
ef416fc2 2109 const char *format, /* I - printf-style format string */
2110 ...) /* I - Additional args as needed */
2111{
2112 int bytes; /* Number of bytes to write */
2113 char buf[16384]; /* Buffer for formatted string */
2114 va_list ap; /* Variable argument pointer */
2115
2116
e07d4801 2117 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
ef416fc2 2118
2119 va_start(ap, format);
2120 bytes = vsnprintf(buf, sizeof(buf), format, ap);
2121 va_end(ap);
2122
a469f8a5 2123 DEBUG_printf(("3httpPrintf: (%d bytes) %s", bytes, buf));
ef416fc2 2124
a469f8a5 2125 if (http->data_encoding == HTTP_ENCODING_FIELDS)
d09495fa 2126 return (httpWrite2(http, buf, bytes));
2127 else
ef416fc2 2128 {
d09495fa 2129 if (http->wused)
2130 {
e07d4801 2131 DEBUG_puts("4httpPrintf: flushing existing data...");
ef416fc2 2132
d09495fa 2133 if (httpFlushWrite(http) < 0)
2134 return (-1);
2135 }
ef416fc2 2136
d09495fa 2137 return (http_write(http, buf, bytes));
2138 }
ef416fc2 2139}
2140
2141
2142/*
2143 * 'httpPut()' - Send a PUT request to the server.
2144 */
2145
2146int /* O - Status of call (0 = success) */
e6b1a6a9 2147httpPut(http_t *http, /* I - HTTP connection */
ef416fc2 2148 const char *uri) /* I - URI to put */
2149{
e07d4801 2150 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
cb7f98ee 2151 return (http_send(http, HTTP_STATE_PUT, uri));
ef416fc2 2152}
2153
2154
2155/*
2156 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 2157 *
2158 * This function is deprecated. Use the httpRead2() function which can
2159 * read more than 2GB of data.
2160 *
2161 * @deprecated@
ef416fc2 2162 */
2163
2164int /* O - Number of bytes read */
e6b1a6a9 2165httpRead(http_t *http, /* I - HTTP connection */
ef416fc2 2166 char *buffer, /* I - Buffer for data */
2167 int length) /* I - Maximum number of bytes */
2168{
a4d04587 2169 return ((int)httpRead2(http, buffer, length));
2170}
2171
2172
2173/*
2174 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 2175 *
f3c17241 2176 * @since CUPS 1.2/OS X 10.5@
a4d04587 2177 */
2178
2179ssize_t /* O - Number of bytes read */
e6b1a6a9 2180httpRead2(http_t *http, /* I - HTTP connection */
a4d04587 2181 char *buffer, /* I - Buffer for data */
2182 size_t length) /* I - Maximum number of bytes */
2183{
2184 ssize_t bytes; /* Bytes read */
ef416fc2 2185
2186
db8b865d 2187#ifdef HAVE_LIBZ
a469f8a5 2188 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
0fa6c7fa 2189 ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT,
db8b865d
MS
2190 http, buffer, CUPS_LLCAST length,
2191 http->coding,
0fa6c7fa 2192 http->data_encoding, CUPS_LLCAST http->data_remaining));
db8b865d
MS
2193#else
2194 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
2195 ") data_encoding=%d data_remaining=" CUPS_LLFMT,
2196 http, buffer, CUPS_LLCAST length,
2197 http->data_encoding, CUPS_LLCAST http->data_remaining));
2198#endif /* HAVE_LIBZ */
ef416fc2 2199
2200 if (http == NULL || buffer == NULL)
2201 return (-1);
2202
2203 http->activity = time(NULL);
f11a948a 2204 http->error = 0;
ef416fc2 2205
2206 if (length <= 0)
2207 return (0);
2208
a469f8a5 2209#ifdef HAVE_LIBZ
0fa6c7fa 2210 if (http->coding)
ef416fc2 2211 {
0fa6c7fa 2212 do
f228370c 2213 {
0fa6c7fa 2214 if (http->stream.avail_in > 0)
f228370c 2215 {
0fa6c7fa 2216 int zerr; /* Decompressor error */
f228370c 2217
0fa6c7fa
MS
2218 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d",
2219 (int)http->stream.avail_in, (int)length));
ef416fc2 2220
0fa6c7fa
MS
2221 http->stream.next_out = (Bytef *)buffer;
2222 http->stream.avail_out = length;
83e08001 2223
0fa6c7fa 2224 if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK)
83e08001 2225 {
0fa6c7fa 2226 DEBUG_printf(("2httpRead2: zerr=%d", zerr));
12f89d24 2227#ifdef DEBUG
0fa6c7fa
MS
2228 http_debug_hex("2httpRead2", (char *)http->dbuffer,
2229 http->stream.avail_in);
12f89d24 2230#endif /* DEBUG */
83e08001 2231
0fa6c7fa
MS
2232 http->error = EIO;
2233 return (-1);
2234 }
a469f8a5 2235
0fa6c7fa 2236 bytes = length - http->stream.avail_out;
a469f8a5 2237
0fa6c7fa
MS
2238 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d",
2239 http->stream.avail_in, http->stream.avail_out,
2240 (int)bytes));
2241 }
2242 else
2243 bytes = 0;
a469f8a5 2244
0fa6c7fa
MS
2245 if (bytes == 0)
2246 {
2247 ssize_t buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
2248 /* Additional bytes for buffer */
a469f8a5 2249
0fa6c7fa
MS
2250 if (buflen > 0)
2251 {
2252 if (http->stream.avail_in > 0 &&
2253 http->stream.next_in > http->dbuffer)
2254 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
2255
2256 http->stream.next_in = http->dbuffer;
2257
2258 DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into "
2259 "decompression buffer.", (int)buflen));
2260
2261 if (http->data_remaining > 0)
2262 {
2263 if (buflen > http->data_remaining)
2264 buflen = http->data_remaining;
2265
2266 bytes = http_read_buffered(http,
2267 (char *)http->dbuffer +
2268 http->stream.avail_in, buflen);
2269 }
2270 else if (http->data_encoding == HTTP_ENCODING_CHUNKED)
2271 bytes = http_read_chunk(http,
2272 (char *)http->dbuffer +
2273 http->stream.avail_in, buflen);
2274 else
2275 bytes = 0;
2276
2277 if (bytes < 0)
2278 return (bytes);
2279 else if (bytes == 0)
2280 break;
2281
db8b865d
MS
2282 DEBUG_printf(("1httpRead2: Adding " CUPS_LLFMT " bytes to "
2283 "decompression buffer.", CUPS_LLCAST bytes));
2284
0fa6c7fa
MS
2285 http->data_remaining -= bytes;
2286 http->stream.avail_in += bytes;
db8b865d 2287
cb7f98ee
MS
2288 if (http->data_remaining <= 0 &&
2289 http->data_encoding == HTTP_ENCODING_CHUNKED)
2290 {
2291 /*
2292 * Read the trailing blank line now...
2293 */
2294
2295 char len[32]; /* Length string */
2296
2297 httpGets(len, sizeof(len), http);
2298 }
2299
db8b865d 2300 bytes = 0;
0fa6c7fa
MS
2301 }
2302 else
2303 return (0);
2304 }
a469f8a5 2305 }
0fa6c7fa 2306 while (bytes == 0);
a469f8a5
MS
2307 }
2308 else
2309#endif /* HAVE_LIBZ */
0fa6c7fa 2310 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
ef416fc2 2311 {
0fa6c7fa 2312 if ((bytes = http_read_chunk(http, buffer, length)) > 0)
cb7f98ee 2313 {
0fa6c7fa 2314 http->data_remaining -= bytes;
cb7f98ee
MS
2315
2316 if (http->data_remaining <= 0)
2317 {
2318 /*
2319 * Read the trailing blank line now...
2320 */
2321
2322 char len[32]; /* Length string */
2323
2324 httpGets(len, sizeof(len), http);
2325 }
2326 }
ef416fc2 2327 }
0fa6c7fa 2328 else if (http->data_remaining <= 0)
ef416fc2 2329 {
0fa6c7fa
MS
2330 /*
2331 * No more data to read...
2332 */
ef416fc2 2333
0fa6c7fa 2334 return (0);
ef416fc2 2335 }
ef416fc2 2336 else
2337 {
0fa6c7fa
MS
2338 DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.",
2339 (int)length));
ef416fc2 2340
db8b865d
MS
2341 if (length > (size_t)http->data_remaining)
2342 length = (size_t)http->data_remaining;
ef416fc2 2343
0fa6c7fa 2344 if ((bytes = http_read_buffered(http, buffer, length)) > 0)
cb7f98ee 2345 {
0fa6c7fa 2346 http->data_remaining -= bytes;
cb7f98ee
MS
2347
2348 if (http->data_remaining <= 0 &&
2349 http->data_encoding == HTTP_ENCODING_CHUNKED)
2350 {
2351 /*
2352 * Read the trailing blank line now...
2353 */
2354
2355 char len[32]; /* Length string */
2356
2357 httpGets(len, sizeof(len), http);
2358 }
2359 }
ef416fc2 2360 }
2361
0fa6c7fa
MS
2362 if (
2363#ifdef HAVE_LIBZ
2364 (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0) &&
2365#endif /* HAVE_LIBZ */
2366 ((http->data_remaining <= 0 &&
2367 http->data_encoding == HTTP_ENCODING_LENGTH) ||
2368 (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0)))
ef416fc2 2369 {
a469f8a5 2370#ifdef HAVE_LIBZ
0fa6c7fa
MS
2371 if (http->coding)
2372 http_content_coding_finish(http);
a469f8a5
MS
2373#endif /* HAVE_LIBZ */
2374
0fa6c7fa
MS
2375 if (http->state == HTTP_STATE_POST_RECV)
2376 http->state ++;
6961465f
MS
2377 else if (http->state == HTTP_STATE_GET_SEND ||
2378 http->state == HTTP_STATE_POST_SEND)
2379 http->state = HTTP_STATE_WAITING;
0fa6c7fa 2380 else
cb7f98ee 2381 http->state = HTTP_STATE_STATUS;
a469f8a5 2382
0fa6c7fa 2383 DEBUG_printf(("1httpRead2: End of content, set state to %s.",
48bd1142 2384 httpStateString(http->state)));
ef416fc2 2385 }
2386
ef416fc2 2387 return (bytes);
2388}
2389
2390
2391#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2392/*
411affcf 2393 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 2394 */
2395
2396OSStatus /* O - -1 on error, 0 on success */
2397_httpReadCDSA(
2398 SSLConnectionRef connection, /* I - SSL/TLS connection */
2399 void *data, /* I - Data buffer */
2400 size_t *dataLength) /* IO - Number of bytes */
2401{
411affcf 2402 OSStatus result; /* Return value */
2403 ssize_t bytes; /* Number of bytes read */
2404 http_t *http; /* HTTP connection */
2405
2406
2407 http = (http_t *)connection;
e53920b9 2408
411affcf 2409 if (!http->blocking)
2410 {
2411 /*
2412 * Make sure we have data before we read...
2413 */
e53920b9 2414
85dda01c 2415 while (!_httpWait(http, http->wait_value, 0))
411affcf 2416 {
f228370c
MS
2417 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2418 continue;
2419
411affcf 2420 http->error = ETIMEDOUT;
2421 return (-1);
2422 }
2423 }
ef416fc2 2424
b423cd4c 2425 do
411affcf 2426 {
2427 bytes = recv(http->fd, data, *dataLength, 0);
2428 }
e07d4801 2429 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2430
b423cd4c 2431 if (bytes == *dataLength)
411affcf 2432 {
b423cd4c 2433 result = 0;
411affcf 2434 }
b423cd4c 2435 else if (bytes > 0)
2436 {
2437 *dataLength = bytes;
2438 result = errSSLWouldBlock;
2439 }
2440 else
2441 {
2442 *dataLength = 0;
fa73b229 2443
2444 if (bytes == 0)
ed486911 2445 result = errSSLClosedGraceful;
b423cd4c 2446 else if (errno == EAGAIN)
2447 result = errSSLWouldBlock;
b423cd4c 2448 else
ed486911 2449 result = errSSLClosedAbort;
ef416fc2 2450 }
b423cd4c 2451
411affcf 2452 return (result);
ef416fc2 2453}
2454#endif /* HAVE_SSL && HAVE_CDSASSL */
2455
2456
411affcf 2457#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2458/*
2459 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
2460 */
2461
2462ssize_t /* O - Number of bytes read or -1 on error */
2463_httpReadGNUTLS(
e6b1a6a9 2464 gnutls_transport_ptr ptr, /* I - HTTP connection */
411affcf 2465 void *data, /* I - Buffer */
2466 size_t length) /* I - Number of bytes to read */
2467{
2468 http_t *http; /* HTTP connection */
a4845881
MS
2469 ssize_t bytes; /* Bytes read */
2470
411affcf 2471
a4845881 2472 DEBUG_printf(("6_httpReadGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data, (int)length));
411affcf 2473
2474 http = (http_t *)ptr;
2475
2476 if (!http->blocking)
2477 {
2478 /*
2479 * Make sure we have data before we read...
2480 */
2481
85dda01c 2482 while (!_httpWait(http, http->wait_value, 0))
411affcf 2483 {
f228370c
MS
2484 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
2485 continue;
2486
411affcf 2487 http->error = ETIMEDOUT;
2488 return (-1);
2489 }
2490 }
2491
a4845881
MS
2492 bytes = recv(http->fd, data, length, 0);
2493 DEBUG_printf(("6_httpReadGNUTLS: bytes=%d", (int)bytes));
2494 return (bytes);
411affcf 2495}
2496#endif /* HAVE_SSL && HAVE_GNUTLS */
2497
2498
ef416fc2 2499/*
a469f8a5
MS
2500 * 'httpReadRequest()' - Read a HTTP request from a connection.
2501 *
9c0e8e5d 2502 * @since CUPS 1.7/OS X 10.9@
ef416fc2 2503 */
2504
a469f8a5
MS
2505http_state_t /* O - New state of connection */
2506httpReadRequest(http_t *http, /* I - HTTP connection */
2507 char *uri, /* I - URI buffer */
2508 size_t urilen) /* I - Size of URI buffer */
dcb445bc 2509{
a469f8a5
MS
2510 char line[4096], /* HTTP request line */
2511 *req_method, /* HTTP request method */
2512 *req_uri, /* HTTP request URI */
2513 *req_version; /* HTTP request version number string */
dcb445bc
MS
2514
2515
a469f8a5
MS
2516 /*
2517 * Range check input...
2518 */
ef416fc2 2519
a469f8a5
MS
2520 DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")",
2521 http, uri, CUPS_LLCAST urilen));
ef416fc2 2522
a469f8a5
MS
2523 if (uri)
2524 *uri = '\0';
ef416fc2 2525
a469f8a5 2526 if (!http || !uri || urilen < 1)
dcb445bc 2527 {
a469f8a5
MS
2528 DEBUG_puts("1httpReadRequest: Bad arguments, returning HTTP_STATE_ERROR.");
2529 return (HTTP_STATE_ERROR);
dcb445bc 2530 }
a469f8a5 2531 else if (http->state != HTTP_STATE_WAITING)
1ff0402e 2532 {
a469f8a5 2533 DEBUG_printf(("1httpReadRequest: Bad state %s, returning HTTP_STATE_ERROR.",
48bd1142 2534 httpStateString(http->state)));
a469f8a5 2535 return (HTTP_STATE_ERROR);
1ff0402e 2536 }
ef416fc2 2537
2538 /*
a469f8a5 2539 * Reset state...
ef416fc2 2540 */
2541
a469f8a5 2542 httpClearFields(http);
ef416fc2 2543
a469f8a5
MS
2544 http->activity = time(NULL);
2545 http->data_encoding = HTTP_ENCODING_FIELDS;
2546 http->data_remaining = 0;
2547 http->keep_alive = HTTP_KEEPALIVE_OFF;
2548 http->status = HTTP_STATUS_OK;
2549 http->version = HTTP_VERSION_1_1;
bd7854cb 2550
a29fd7dd 2551 /*
a469f8a5 2552 * Read a line from the socket...
a29fd7dd
MS
2553 */
2554
a469f8a5
MS
2555 if (!httpGets(line, sizeof(line), http))
2556 {
2557 DEBUG_puts("1httpReadRequest: Unable to read, returning HTTP_STATE_ERROR");
2558 return (HTTP_STATE_ERROR);
2559 }
2560
2561 if (!line[0])
2562 {
2563 DEBUG_puts("1httpReadRequest: Blank line, returning HTTP_STATE_WAITING");
2564 return (HTTP_STATE_WAITING);
2565 }
2566
2567 DEBUG_printf(("1httpReadRequest: %s", line));
2568
2569 /*
2570 * Parse it...
2571 */
2572
2573 req_method = line;
2574 req_uri = line;
2575
2576 while (*req_uri && !isspace(*req_uri & 255))
2577 req_uri ++;
2578
2579 if (!*req_uri)
2580 {
2581 DEBUG_puts("1httpReadRequest: No request URI.");
d21dc0ed 2582 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No request URI."), 1);
a469f8a5
MS
2583 return (HTTP_STATE_ERROR);
2584 }
2585
2586 *req_uri++ = '\0';
2587
2588 while (*req_uri && isspace(*req_uri & 255))
2589 req_uri ++;
2590
2591 req_version = req_uri;
2592
2593 while (*req_version && !isspace(*req_version & 255))
2594 req_version ++;
2595
2596 if (!*req_version)
2597 {
2598 DEBUG_puts("1httpReadRequest: No request protocol version.");
d21dc0ed 2599 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No request protocol version."), 1);
a469f8a5
MS
2600 return (HTTP_STATE_ERROR);
2601 }
2602
2603 *req_version++ = '\0';
2604
2605 while (*req_version && isspace(*req_version & 255))
2606 req_version ++;
2607
2608 /*
2609 * Validate...
2610 */
2611
2612 if (!strcmp(req_method, "OPTIONS"))
2613 http->state = HTTP_STATE_OPTIONS;
2614 else if (!strcmp(req_method, "GET"))
2615 http->state = HTTP_STATE_GET;
2616 else if (!strcmp(req_method, "HEAD"))
2617 http->state = HTTP_STATE_HEAD;
2618 else if (!strcmp(req_method, "POST"))
2619 http->state = HTTP_STATE_POST;
2620 else if (!strcmp(req_method, "PUT"))
2621 http->state = HTTP_STATE_PUT;
2622 else if (!strcmp(req_method, "DELETE"))
2623 http->state = HTTP_STATE_DELETE;
2624 else if (!strcmp(req_method, "TRACE"))
2625 http->state = HTTP_STATE_TRACE;
2626 else if (!strcmp(req_method, "CONNECT"))
2627 http->state = HTTP_STATE_CONNECT;
2628 else
2629 {
2630 DEBUG_printf(("1httpReadRequest: Unknown method \"%s\".", req_method));
d21dc0ed 2631 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown request method."), 1);
a469f8a5
MS
2632 return (HTTP_STATE_UNKNOWN_METHOD);
2633 }
2634
2635 DEBUG_printf(("1httpReadRequest: Set state to %s.",
48bd1142 2636 httpStateString(http->state)));
a469f8a5
MS
2637
2638 if (!strcmp(req_version, "HTTP/1.0"))
2639 {
2640 http->version = HTTP_VERSION_1_0;
2641 http->keep_alive = HTTP_KEEPALIVE_OFF;
2642 }
2643 else if (!strcmp(req_version, "HTTP/1.1"))
2644 {
2645 http->version = HTTP_VERSION_1_1;
2646 http->keep_alive = HTTP_KEEPALIVE_ON;
2647 }
2648 else
2649 {
2650 DEBUG_printf(("1httpReadRequest: Unknown version \"%s\".", req_version));
d21dc0ed 2651 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown request version."), 1);
a469f8a5
MS
2652 return (HTTP_STATE_UNKNOWN_VERSION);
2653 }
2654
2655 DEBUG_printf(("1httpReadRequest: URI is \"%s\".", req_uri));
2656 strlcpy(uri, req_uri, urilen);
2657
2658 return (http->state);
2659}
2660
2661
2662/*
2663 * 'httpReconnect()' - Reconnect to a HTTP server.
2664 *
2665 * This function is deprecated. Please use the @link httpReconnect2@ function
2666 * instead.
2667 *
2668 * @deprecated@
2669 */
2670
2671int /* O - 0 on success, non-zero on failure */
e6b1a6a9 2672httpReconnect(http_t *http) /* I - HTTP connection */
a469f8a5
MS
2673{
2674 DEBUG_printf(("httpReconnect(http=%p)", http));
2675
2676 return (httpReconnect2(http, 30000, NULL));
2677}
2678
2679
2680/*
2681 * 'httpReconnect2()' - Reconnect to a HTTP server with timeout and optional
2682 * cancel.
2683 */
2684
2685int /* O - 0 on success, non-zero on failure */
e6b1a6a9 2686httpReconnect2(http_t *http, /* I - HTTP connection */
a469f8a5
MS
2687 int msec, /* I - Timeout in milliseconds */
2688 int *cancel) /* I - Pointer to "cancel" variable */
2689{
2690 http_addrlist_t *addr; /* Connected address */
2691#ifdef DEBUG
2692 http_addrlist_t *current; /* Current address */
2693 char temp[256]; /* Temporary address string */
2694#endif /* DEBUG */
2695
2696
2697 DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", http, msec,
2698 cancel));
2699
2700 if (!http)
2701 {
cb7f98ee 2702 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
a469f8a5
MS
2703 return (-1);
2704 }
2705
2706#ifdef HAVE_SSL
2707 if (http->tls)
2708 {
2709 DEBUG_puts("2httpReconnect2: Shutting down SSL/TLS...");
2710 http_shutdown_ssl(http);
2711 }
2712#endif /* HAVE_SSL */
2713
2714 /*
2715 * Close any previously open socket...
2716 */
2717
2718 if (http->fd >= 0)
2719 {
2720 DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd));
2721
87e98392 2722 httpAddrClose(NULL, http->fd);
a469f8a5
MS
2723
2724 http->fd = -1;
2725 }
2726
2727 /*
2728 * Reset all state (except fields, which may be reused)...
2729 */
2730
2731 http->state = HTTP_STATE_WAITING;
a469f8a5
MS
2732 http->version = HTTP_VERSION_1_1;
2733 http->keep_alive = HTTP_KEEPALIVE_OFF;
a29fd7dd 2734 memset(&http->_hostaddr, 0, sizeof(http->_hostaddr));
a469f8a5 2735 http->data_encoding = HTTP_ENCODING_FIELDS;
a29fd7dd
MS
2736 http->_data_remaining = 0;
2737 http->used = 0;
a29fd7dd
MS
2738 http->data_remaining = 0;
2739 http->hostaddr = NULL;
2740 http->wused = 0;
2741
ef416fc2 2742 /*
2743 * Connect to the server...
2744 */
2745
1ff0402e
MS
2746#ifdef DEBUG
2747 for (current = http->addrlist; current; current = current->next)
12f89d24 2748 DEBUG_printf(("2httpReconnect2: Address %s:%d",
1ff0402e 2749 httpAddrString(&(current->addr), temp, sizeof(temp)),
a469f8a5 2750 httpAddrPort(&(current->addr))));
1ff0402e
MS
2751#endif /* DEBUG */
2752
dcb445bc
MS
2753 if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec,
2754 cancel)) == NULL)
ef416fc2 2755 {
2756 /*
2757 * Unable to connect...
2758 */
2759
2760#ifdef WIN32
2761 http->error = WSAGetLastError();
2762#else
2763 http->error = errno;
2764#endif /* WIN32 */
cb7f98ee 2765 http->status = HTTP_STATUS_ERROR;
ef416fc2 2766
12f89d24 2767 DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s",
1ff0402e
MS
2768 strerror(http->error)));
2769
ef416fc2 2770 return (-1);
2771 }
2772
12f89d24 2773 DEBUG_printf(("2httpReconnect2: New socket=%d", http->fd));
1ff0402e 2774
85dda01c
MS
2775 if (http->timeout_value > 0)
2776 http_set_timeout(http->fd, http->timeout_value);
10d09e33 2777
ef416fc2 2778 http->hostaddr = &(addr->addr);
2779 http->error = 0;
ef416fc2 2780
2781#ifdef HAVE_SSL
cb7f98ee 2782 if (http->encryption == HTTP_ENCRYPTION_ALWAYS)
ef416fc2 2783 {
2784 /*
2785 * Always do encryption via SSL.
2786 */
2787
2788 if (http_setup_ssl(http) != 0)
2789 {
87e98392 2790 httpAddrClose(NULL, http->fd);
ef416fc2 2791
2792 return (-1);
2793 }
2794 }
cb7f98ee 2795 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls_upgrade)
ef416fc2 2796 return (http_upgrade(http));
2797#endif /* HAVE_SSL */
2798
12f89d24 2799 DEBUG_printf(("1httpReconnect2: Connected to %s:%d...",
1ff0402e 2800 httpAddrString(http->hostaddr, temp, sizeof(temp)),
a469f8a5 2801 httpAddrPort(http->hostaddr)));
1ff0402e 2802
ef416fc2 2803 return (0);
2804}
2805
2806
355e94dc
MS
2807/*
2808 * 'httpSetAuthString()' - Set the current authorization string.
2809 *
2810 * This function just stores a copy of the current authorization string in
2811 * the HTTP connection object. You must still call httpSetField() to set
2812 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
2813 * httpHead(), httpOptions(), httpPost, or httpPut().
2814 *
f3c17241 2815 * @since CUPS 1.3/OS X 10.5@
355e94dc
MS
2816 */
2817
2818void
e6b1a6a9 2819httpSetAuthString(http_t *http, /* I - HTTP connection */
355e94dc
MS
2820 const char *scheme, /* I - Auth scheme (NULL to clear it) */
2821 const char *data) /* I - Auth data (NULL for none) */
2822{
2823 /*
2824 * Range check input...
2825 */
2826
2827 if (!http)
2828 return;
2829
2830 if (http->authstring && http->authstring != http->_authstring)
2831 free(http->authstring);
2832
2833 http->authstring = http->_authstring;
2834
2835 if (scheme)
2836 {
2837 /*
2838 * Set the current authorization string...
2839 */
2840
2841 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 2842 char *temp;
355e94dc
MS
2843
2844 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
2845 {
2846 if ((temp = malloc(len)) == NULL)
2847 len = sizeof(http->_authstring);
2848 else
2849 http->authstring = temp;
2850 }
355e94dc
MS
2851
2852 if (data)
2853 snprintf(http->authstring, len, "%s %s", scheme, data);
2854 else
2855 strlcpy(http->authstring, scheme, len);
2856 }
2857 else
2858 {
2859 /*
2860 * Clear the current authorization string...
2861 */
2862
2863 http->_authstring[0] = '\0';
2864 }
2865}
2866
2867
7cf5915e
MS
2868/*
2869 * 'httpSetCredentials()' - Set the credentials associated with an encrypted
2870 * connection.
2871 *
f3c17241 2872 * @since CUPS 1.5/OS X 10.7@
7cf5915e
MS
2873 */
2874
2875int /* O - Status of call (0 = success) */
e6b1a6a9 2876httpSetCredentials(http_t *http, /* I - HTTP connection */
7cf5915e
MS
2877 cups_array_t *credentials) /* I - Array of credentials */
2878{
2879 if (!http || cupsArrayCount(credentials) < 1)
2880 return (-1);
2881
2882 _httpFreeCredentials(http->tls_credentials);
2883
85dda01c 2884 http->tls_credentials = _httpCreateCredentials(credentials);
7cf5915e
MS
2885
2886 return (http->tls_credentials ? 0 : -1);
2887}
2888
2889
ef416fc2 2890/*
6d2f911b 2891 * 'httpSetCookie()' - Set the cookie value(s).
ef416fc2 2892 *
f3c17241 2893 * @since CUPS 1.1.19/OS X 10.3@
ef416fc2 2894 */
2895
2896void
2897httpSetCookie(http_t *http, /* I - Connection */
2898 const char *cookie) /* I - Cookie string */
2899{
2900 if (!http)
2901 return;
2902
2903 if (http->cookie)
2904 free(http->cookie);
2905
2906 if (cookie)
2907 http->cookie = strdup(cookie);
2908 else
2909 http->cookie = NULL;
2910}
2911
2912
c1420c87
MS
2913/*
2914 * 'httpSetDefaultField()' - Set the default value of an HTTP header.
2915 *
6961465f
MS
2916 * Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@,
2917 * and @code HTTP_FIELD_USER_AGENT@ can be set.
c1420c87 2918 *
9c0e8e5d 2919 * @since CUPS 1.7/OS X 10.9@
c1420c87
MS
2920 */
2921
2922void
e6b1a6a9 2923httpSetDefaultField(http_t *http, /* I - HTTP connection */
c1420c87
MS
2924 http_field_t field, /* I - Field index */
2925 const char *value)/* I - Value */
2926{
2927 DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")",
2928 http, field, http_fields[field], value));
2929
2930 if (!http)
2931 return;
2932
2933 switch (field)
2934 {
2935 case HTTP_FIELD_ACCEPT_ENCODING :
2936 if (http->default_accept_encoding)
2937 _cupsStrFree(http->default_accept_encoding);
2938
2939 http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
2940 break;
2941
2942 case HTTP_FIELD_SERVER :
2943 if (http->default_server)
2944 _cupsStrFree(http->default_server);
2945
2946 http->default_server = value ? _cupsStrAlloc(value) : NULL;
2947 break;
2948
2949 case HTTP_FIELD_USER_AGENT :
2950 if (http->default_user_agent)
2951 _cupsStrFree(http->default_user_agent);
2952
2953 http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
2954 break;
2955
2956 default :
2957 DEBUG_puts("1httpSetDefaultField: Ignored.");
2958 break;
2959 }
2960}
2961
2962
b423cd4c 2963/*
2964 * 'httpSetExpect()' - Set the Expect: header in a request.
2965 *
a469f8a5
MS
2966 * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
2967 * argument.
b423cd4c 2968 *
f3c17241 2969 * @since CUPS 1.2/OS X 10.5@
b423cd4c 2970 */
2971
2972void
e6b1a6a9 2973httpSetExpect(http_t *http, /* I - HTTP connection */
a469f8a5 2974 http_status_t expect) /* I - HTTP status to expect
cb7f98ee 2975 (@code HTTP_STATUS_CONTINUE@) */
b423cd4c 2976{
cb7f98ee
MS
2977 DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", http, expect));
2978
b423cd4c 2979 if (http)
2980 http->expect = expect;
2981}
2982
2983
ef416fc2 2984/*
2985 * 'httpSetField()' - Set the value of an HTTP header.
2986 */
2987
2988void
e6b1a6a9 2989httpSetField(http_t *http, /* I - HTTP connection */
ef416fc2 2990 http_field_t field, /* I - Field index */
2991 const char *value) /* I - Value */
2992{
a469f8a5
MS
2993 DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", http,
2994 field, http_fields[field], value));
2995
ef416fc2 2996 if (http == NULL ||
2997 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
a469f8a5 2998 field >= HTTP_FIELD_MAX ||
ef416fc2 2999 value == NULL)
3000 return;
3001
a469f8a5
MS
3002 switch (field)
3003 {
3004 case HTTP_FIELD_ACCEPT_ENCODING :
3005 if (http->accept_encoding)
3006 _cupsStrFree(http->accept_encoding);
3007
3008 http->accept_encoding = _cupsStrAlloc(value);
3009 break;
3010
3011 case HTTP_FIELD_ALLOW :
3012 if (http->allow)
3013 _cupsStrFree(http->allow);
3014
3015 http->allow = _cupsStrAlloc(value);
3016 break;
3017
3018 case HTTP_FIELD_SERVER :
3019 if (http->server)
3020 _cupsStrFree(http->server);
3021
3022 http->server = _cupsStrAlloc(value);
3023 break;
3024
3025 default :
3026 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
3027 break;
3028 }
f7deaa1a 3029
f7deaa1a 3030 if (field == HTTP_FIELD_AUTHORIZATION)
3031 {
e07d4801
MS
3032 /*
3033 * Special case for Authorization: as its contents can be
3034 * longer than HTTP_MAX_VALUE
3035 */
3036
f7deaa1a 3037 if (http->field_authorization)
3038 free(http->field_authorization);
3039
3040 http->field_authorization = strdup(value);
3041 }
e07d4801
MS
3042 else if (field == HTTP_FIELD_HOST)
3043 {
3044 /*
f11a948a
MS
3045 * Special-case for Host: as we don't want a trailing "." on the hostname and
3046 * need to bracket IPv6 numeric addresses.
e07d4801
MS
3047 */
3048
178cb736
MS
3049 char *ptr = strchr(value, ':');
3050
3051 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
3052 {
3053 /*
3054 * Bracket IPv6 numeric addresses...
3055 *
3056 * This is slightly inefficient (basically copying twice), but is an edge
3057 * case and not worth optimizing...
3058 */
e07d4801 3059
f11a948a
MS
3060 snprintf(http->fields[HTTP_FIELD_HOST],
3061 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
3062 }
3063 else
e07d4801 3064 {
f11a948a
MS
3065 /*
3066 * Check for a trailing dot on the hostname...
3067 */
3068
178cb736 3069 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
3070
3071 if (*ptr)
3072 {
3073 ptr += strlen(ptr) - 1;
e07d4801 3074
f11a948a
MS
3075 if (*ptr == '.')
3076 *ptr = '\0';
3077 }
e07d4801
MS
3078 }
3079 }
a469f8a5
MS
3080#ifdef HAVE_LIBZ
3081 else if (field == HTTP_FIELD_CONTENT_ENCODING &&
3082 http->data_encoding != HTTP_ENCODING_FIELDS)
3083 {
3084 DEBUG_puts("1httpSetField: Calling http_content_coding_start.");
3085 http_content_coding_start(http, value);
3086 }
3087#endif /* HAVE_LIBZ */
ef416fc2 3088}
3089
3090
e6b1a6a9
MS
3091/*
3092 * 'httpSetKeepAlive()' - Set the current Keep-Alive state of a connection.
3093 *
3094 * @since CUPS 2.0@
3095 */
3096
3097void
3098httpSetKeepAlive(
3099 http_t *http, /* I - HTTP connection */
3100 http_keepalive_t keep_alive) /* I - New Keep-Alive value */
3101{
3102 if (http)
3103 http->keep_alive = keep_alive;
3104}
3105
3106
ef416fc2 3107/*
3108 * 'httpSetLength()' - Set the content-length and content-encoding.
3109 *
f3c17241 3110 * @since CUPS 1.2/OS X 10.5@
ef416fc2 3111 */
3112
3113void
e6b1a6a9 3114httpSetLength(http_t *http, /* I - HTTP connection */
ef416fc2 3115 size_t length) /* I - Length (0 for chunked) */
3116{
a469f8a5
MS
3117 DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", http,
3118 CUPS_LLCAST length));
3119
ef416fc2 3120 if (!http)
3121 return;
3122
3123 if (!length)
3124 {
5a9febac
MS
3125 strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked",
3126 HTTP_MAX_VALUE);
ef416fc2 3127 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
3128 }
3129 else
3130 {
3131 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
3132 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
3133 CUPS_LLFMT, CUPS_LLCAST length);
3134 }
3135}
3136
3137
10d09e33 3138/*
f228370c 3139 * 'httpSetTimeout()' - Set read/write timeouts and an optional callback.
10d09e33
MS
3140 *
3141 * The optional timeout callback receives both the HTTP connection and a user
f228370c
MS
3142 * data pointer and must return 1 to continue or 0 to error (time) out.
3143 *
f3c17241 3144 * @since CUPS 1.5/OS X 10.7@
10d09e33
MS
3145 */
3146
3147void
f228370c 3148httpSetTimeout(
e6b1a6a9 3149 http_t *http, /* I - HTTP connection */
f228370c 3150 double timeout, /* I - Number of seconds for timeout,
10d09e33 3151 must be greater than 0 */
f228370c
MS
3152 http_timeout_cb_t cb, /* I - Callback function or NULL */
3153 void *user_data) /* I - User data pointer */
10d09e33
MS
3154{
3155 if (!http || timeout <= 0.0)
3156 return;
3157
85dda01c
MS
3158 http->timeout_cb = cb;
3159 http->timeout_data = user_data;
3160 http->timeout_value = timeout;
10d09e33
MS
3161
3162 if (http->fd >= 0)
85dda01c 3163 http_set_timeout(http->fd, timeout);
c8fef167 3164
85dda01c 3165 http_set_wait(http);
10d09e33
MS
3166}
3167
3168
5ec1fd3d
MS
3169/*
3170 * 'httpShutdown()' - Shutdown one side of an HTTP connection.
3171 *
3172 * @since CUPS 2.0@
3173 */
3174
3175void
3176httpShutdown(http_t *http) /* I - HTTP connection */
3177{
3178 if (!http || http->fd < 0)
3179 return;
3180
3181 if (http->tls)
3182 http_shutdown_ssl(http);
3183
3184 shutdown(http->fd, SHUT_RD);
3185}
3186
3187
ef416fc2 3188/*
3189 * 'httpTrace()' - Send an TRACE request to the server.
3190 */
3191
3192int /* O - Status of call (0 = success) */
e6b1a6a9 3193httpTrace(http_t *http, /* I - HTTP connection */
ef416fc2 3194 const char *uri) /* I - URI for trace */
3195{
cb7f98ee 3196 return (http_send(http, HTTP_STATE_TRACE, uri));
ef416fc2 3197}
3198
3199
3200/*
e60ec91f
MS
3201 * '_httpUpdate()' - Update the current HTTP status for incoming data.
3202 *
3203 * Note: Unlike httpUpdate(), this function does not flush pending write data
3204 * and only retrieves a single status line from the HTTP connection.
ef416fc2 3205 */
3206
e60ec91f 3207int /* O - 1 to continue, 0 to stop */
e6b1a6a9 3208_httpUpdate(http_t *http, /* I - HTTP connection */
e60ec91f 3209 http_status_t *status) /* O - Current HTTP status */
ef416fc2 3210{
3211 char line[32768], /* Line from connection... */
3212 *value; /* Pointer to value on line */
3213 http_field_t field; /* Field index */
e60ec91f 3214 int major, minor; /* HTTP version numbers */
ef416fc2 3215
3216
e60ec91f 3217 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status,
48bd1142 3218 httpStateString(http->state)));
ef416fc2 3219
3220 /*
e60ec91f 3221 * Grab a single line from the connection...
ef416fc2 3222 */
3223
e60ec91f 3224 if (!httpGets(line, sizeof(line), http))
ef416fc2 3225 {
cb7f98ee 3226 *status = HTTP_STATUS_ERROR;
e60ec91f 3227 return (0);
ef416fc2 3228 }
3229
e60ec91f 3230 DEBUG_printf(("2_httpUpdate: Got \"%s\"", line));
ef416fc2 3231
e60ec91f 3232 if (line[0] == '\0')
ef416fc2 3233 {
e60ec91f
MS
3234 /*
3235 * Blank line means the start of the data section (if any). Return
3236 * the result code, too...
3237 *
a469f8a5
MS
3238 * If we get status 100 (HTTP_STATUS_CONTINUE), then we *don't* change
3239 * states. Instead, we just return HTTP_STATUS_CONTINUE to the caller and
3240 * keep on tryin'...
e60ec91f 3241 */
ef416fc2 3242
a469f8a5 3243 if (http->status == HTTP_STATUS_CONTINUE)
ef416fc2 3244 {
e60ec91f
MS
3245 *status = http->status;
3246 return (0);
3247 }
ef416fc2 3248
cb7f98ee 3249 if (http->status < HTTP_STATUS_BAD_REQUEST)
e60ec91f 3250 http->digest_tries = 0;
ef416fc2 3251
3252#ifdef HAVE_SSL
cb7f98ee 3253 if (http->status == HTTP_STATUS_SWITCHING_PROTOCOLS && !http->tls)
e60ec91f
MS
3254 {
3255 if (http_setup_ssl(http) != 0)
ef416fc2 3256 {
87e98392 3257 httpAddrClose(NULL, http->fd);
ef416fc2 3258
cb7f98ee 3259 *status = http->status = HTTP_STATUS_ERROR;
e60ec91f 3260 return (0);
ef416fc2 3261 }
e60ec91f 3262
a469f8a5 3263 *status = HTTP_STATUS_CONTINUE;
e60ec91f
MS
3264 return (0);
3265 }
ef416fc2 3266#endif /* HAVE_SSL */
3267
a469f8a5
MS
3268 if (http_set_length(http) < 0)
3269 {
3270 DEBUG_puts("1_httpUpdate: Bad Content-Length.");
3271 http->error = EINVAL;
cb7f98ee 3272 http->status = *status = HTTP_STATUS_ERROR;
a469f8a5
MS
3273 return (0);
3274 }
ef416fc2 3275
e60ec91f
MS
3276 switch (http->state)
3277 {
c41769ff
MS
3278 case HTTP_STATE_GET :
3279 case HTTP_STATE_POST :
a469f8a5 3280 case HTTP_STATE_POST_RECV :
c41769ff 3281 case HTTP_STATE_PUT :
e60ec91f 3282 http->state ++;
a469f8a5
MS
3283
3284 DEBUG_printf(("1_httpUpdate: Set state to %s.",
48bd1142 3285 httpStateString(http->state)));
a469f8a5 3286
c41769ff
MS
3287 case HTTP_STATE_POST_SEND :
3288 case HTTP_STATE_HEAD :
e60ec91f 3289 break;
ef416fc2 3290
e60ec91f 3291 default :
a469f8a5
MS
3292 http->state = HTTP_STATE_WAITING;
3293
cb7f98ee 3294 DEBUG_puts("1_httpUpdate: Reset state to HTTP_STATE_WAITING.");
e60ec91f 3295 break;
ef416fc2 3296 }
e60ec91f 3297
a469f8a5
MS
3298#ifdef HAVE_LIBZ
3299 DEBUG_puts("1_httpUpdate: Calling http_content_coding_start.");
3300 http_content_coding_start(http,
3301 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
3302#endif /* HAVE_LIBZ */
3303
e60ec91f
MS
3304 *status = http->status;
3305 return (0);
3306 }
3307 else if (!strncmp(line, "HTTP/", 5))
3308 {
3309 /*
3310 * Got the beginning of a response...
3311 */
3312
3313 int intstatus; /* Status value as an integer */
3314
3315 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3)
3316 {
cb7f98ee 3317 *status = http->status = HTTP_STATUS_ERROR;
e60ec91f
MS
3318 return (0);
3319 }
3320
a469f8a5
MS
3321 httpClearFields(http);
3322
e60ec91f
MS
3323 http->version = (http_version_t)(major * 100 + minor);
3324 *status = http->status = (http_status_t)intstatus;
3325 }
3326 else if ((value = strchr(line, ':')) != NULL)
3327 {
3328 /*
3329 * Got a value...
3330 */
3331
3332 *value++ = '\0';
3333 while (_cups_isspace(*value))
3334 value ++;
3335
a469f8a5
MS
3336 DEBUG_printf(("1_httpUpdate: Header %s: %s", line, value));
3337
e60ec91f
MS
3338 /*
3339 * Be tolerants of servers that send unknown attribute fields...
3340 */
3341
88f9aafc 3342 if (!_cups_strcasecmp(line, "expect"))
ef416fc2 3343 {
3344 /*
e60ec91f 3345 * "Expect: 100-continue" or similar...
ef416fc2 3346 */
3347
e60ec91f 3348 http->expect = (http_status_t)atoi(value);
ef416fc2 3349 }
88f9aafc 3350 else if (!_cups_strcasecmp(line, "cookie"))
ef416fc2 3351 {
3352 /*
e60ec91f 3353 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
ef416fc2 3354 */
3355
e60ec91f
MS
3356 httpSetCookie(http, value);
3357 }
48bd1142 3358 else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN)
e60ec91f
MS
3359 httpSetField(http, field, value);
3360#ifdef DEBUG
3361 else
3362 DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
3363#endif /* DEBUG */
3364 }
3365 else
3366 {
3367 DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line));
a469f8a5 3368 http->error = EINVAL;
cb7f98ee 3369 http->status = *status = HTTP_STATUS_ERROR;
e60ec91f
MS
3370 return (0);
3371 }
ef416fc2 3372
e60ec91f
MS
3373 return (1);
3374}
ef416fc2 3375
ef416fc2 3376
e60ec91f
MS
3377/*
3378 * 'httpUpdate()' - Update the current HTTP state for incoming data.
3379 */
ef416fc2 3380
e60ec91f 3381http_status_t /* O - HTTP status */
e6b1a6a9 3382httpUpdate(http_t *http) /* I - HTTP connection */
e60ec91f
MS
3383{
3384 http_status_t status; /* Request status */
3385
3386
3387 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
48bd1142 3388 httpStateString(http->state)));
e60ec91f
MS
3389
3390 /*
3391 * Flush pending data, if any...
3392 */
3393
3394 if (http->wused)
3395 {
3396 DEBUG_puts("2httpUpdate: flushing buffer...");
3397
3398 if (httpFlushWrite(http) < 0)
cb7f98ee 3399 return (HTTP_STATUS_ERROR);
ef416fc2 3400 }
3401
e60ec91f
MS
3402 /*
3403 * If we haven't issued any commands, then there is nothing to "update"...
3404 */
3405
a469f8a5 3406 if (http->state == HTTP_STATE_WAITING)
cb7f98ee 3407 return (HTTP_STATUS_CONTINUE);
e60ec91f
MS
3408
3409 /*
3410 * Grab all of the lines we can from the connection...
3411 */
3412
3413 while (_httpUpdate(http, &status));
3414
ef416fc2 3415 /*
3416 * See if there was an error...
3417 */
3418
cb7f98ee 3419 if (http->error == EPIPE && http->status > HTTP_STATUS_CONTINUE)
e07d4801
MS
3420 {
3421 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 3422 return (http->status);
e07d4801 3423 }
ef416fc2 3424
3425 if (http->error)
3426 {
e07d4801 3427 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 3428 strerror(http->error)));
cb7f98ee
MS
3429 http->status = HTTP_STATUS_ERROR;
3430 return (HTTP_STATUS_ERROR);
ef416fc2 3431 }
3432
3433 /*
e60ec91f 3434 * Return the current status...
ef416fc2 3435 */
3436
e60ec91f 3437 return (status);
ef416fc2 3438}
3439
3440
38e73f87
MS
3441/*
3442 * '_httpWait()' - Wait for data available on a connection (no flush).
3443 */
3444
3445int /* O - 1 if data is available, 0 otherwise */
e6b1a6a9 3446_httpWait(http_t *http, /* I - HTTP connection */
38e73f87
MS
3447 int msec, /* I - Milliseconds to wait */
3448 int usessl) /* I - Use SSL context? */
3449{
3450#ifdef HAVE_POLL
3451 struct pollfd pfd; /* Polled file descriptor */
3452#else
3453 fd_set input_set; /* select() input set */
3454 struct timeval timeout; /* Timeout */
3455#endif /* HAVE_POLL */
3456 int nfds; /* Result from select()/poll() */
3457
3458
e07d4801 3459 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
3460
3461 if (http->fd < 0)
f8b3a85b
MS
3462 {
3463 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
38e73f87 3464 return (0);
f8b3a85b 3465 }
38e73f87
MS
3466
3467 /*
3468 * Check the SSL/TLS buffers for data first...
3469 */
3470
3471#ifdef HAVE_SSL
3472 if (http->tls && usessl)
3473 {
3474# ifdef HAVE_LIBSSL
7cf5915e 3475 if (SSL_pending(http->tls))
f8b3a85b
MS
3476 {
3477 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 3478 return (1);
f8b3a85b
MS
3479 }
3480
38e73f87 3481# elif defined(HAVE_GNUTLS)
7cf5915e 3482 if (gnutls_record_check_pending(http->tls))
f8b3a85b
MS
3483 {
3484 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 3485 return (1);
f8b3a85b
MS
3486 }
3487
38e73f87
MS
3488# elif defined(HAVE_CDSASSL)
3489 size_t bytes; /* Bytes that are available */
3490
7cf5915e 3491 if (!SSLGetBufferedReadSize(http->tls, &bytes) &&
38e73f87 3492 bytes > 0)
f8b3a85b
MS
3493 {
3494 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 3495 return (1);
f8b3a85b 3496 }
38e73f87
MS
3497# endif /* HAVE_LIBSSL */
3498 }
3499#endif /* HAVE_SSL */
3500
3501 /*
3502 * Then try doing a select() or poll() to poll the socket...
3503 */
3504
3505#ifdef HAVE_POLL
3506 pfd.fd = http->fd;
3507 pfd.events = POLLIN;
3508
5a9febac
MS
3509 do
3510 {
3511 nfds = poll(&pfd, 1, msec);
3512 }
3513 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
3514
3515#else
3516 do
3517 {
3518 FD_ZERO(&input_set);
3519 FD_SET(http->fd, &input_set);
3520
e07d4801 3521 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
3522
3523 if (msec >= 0)
3524 {
3525 timeout.tv_sec = msec / 1000;
3526 timeout.tv_usec = (msec % 1000) * 1000;
3527
3528 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
3529 }
3530 else
3531 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
3532
e07d4801 3533 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
3534 }
3535# ifdef WIN32
cc754834
MS
3536 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
3537 WSAGetLastError() == WSAEWOULDBLOCK));
38e73f87 3538# else
e07d4801 3539 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
3540# endif /* WIN32 */
3541#endif /* HAVE_POLL */
3542
f8b3a85b
MS
3543 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
3544 errno));
38e73f87
MS
3545
3546 return (nfds > 0);
3547}
3548
3549
ef416fc2 3550/*
3551 * 'httpWait()' - Wait for data available on a connection.
3552 *
f3c17241 3553 * @since CUPS 1.1.19/OS X 10.3@
ef416fc2 3554 */
3555
3556int /* O - 1 if data is available, 0 otherwise */
e6b1a6a9 3557httpWait(http_t *http, /* I - HTTP connection */
ef416fc2 3558 int msec) /* I - Milliseconds to wait */
3559{
3560 /*
3561 * First see if there is data in the buffer...
3562 */
3563
22c9029b
MS
3564 DEBUG_printf(("2httpWait(http=%p, msec=%d)", http, msec));
3565
ef416fc2 3566 if (http == NULL)
3567 return (0);
3568
3569 if (http->used)
22c9029b
MS
3570 {
3571 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
ef416fc2 3572 return (1);
22c9029b 3573 }
ef416fc2 3574
0fa6c7fa
MS
3575#ifdef HAVE_LIBZ
3576 if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0)
3577 {
3578 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
3579 return (1);
3580 }
3581#endif /* HAVE_LIBZ */
3582
8ca02f3c 3583 /*
3584 * Flush pending data, if any...
3585 */
3586
3587 if (http->wused)
3588 {
22c9029b
MS
3589 DEBUG_puts("3httpWait: Flushing write buffer.");
3590
8ca02f3c 3591 if (httpFlushWrite(http) < 0)
3592 return (0);
3593 }
3594
ef416fc2 3595 /*
3596 * If not, check the SSL/TLS buffers and do a select() on the connection...
3597 */
3598
38e73f87 3599 return (_httpWait(http, msec, 1));
ef416fc2 3600}
3601
3602
3603/*
3604 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 3605 *
3606 * This function is deprecated. Use the httpWrite2() function which can
3607 * write more than 2GB of data.
3608 *
3609 * @deprecated@
ef416fc2 3610 */
ef55b745 3611
ef416fc2 3612int /* O - Number of bytes written */
e6b1a6a9 3613httpWrite(http_t *http, /* I - HTTP connection */
ef416fc2 3614 const char *buffer, /* I - Buffer for data */
3615 int length) /* I - Number of bytes to write */
3616{
a4d04587 3617 return ((int)httpWrite2(http, buffer, length));
3618}
3619
3620
3621/*
3622 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 3623 *
f3c17241 3624 * @since CUPS 1.2/OS X 10.5@
a4d04587 3625 */
ef55b745 3626
a4d04587 3627ssize_t /* O - Number of bytes written */
e6b1a6a9 3628httpWrite2(http_t *http, /* I - HTTP connection */
a4d04587 3629 const char *buffer, /* I - Buffer for data */
3630 size_t length) /* I - Number of bytes to write */
3631{
3632 ssize_t bytes; /* Bytes written */
ef416fc2 3633
3634
e07d4801 3635 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 3636 buffer, CUPS_LLCAST length));
ef416fc2 3637
3638 /*
3639 * Range check input...
3640 */
3641
a469f8a5
MS
3642 if (!http || !buffer)
3643 {
3644 DEBUG_puts("1httpWrite2: Returning -1 due to bad input.");
ef416fc2 3645 return (-1);
a469f8a5 3646 }
ef416fc2 3647
3648 /*
3649 * Mark activity on the connection...
3650 */
3651
3652 http->activity = time(NULL);
3653
3654 /*
3655 * Buffer small writes for better performance...
3656 */
3657
a469f8a5
MS
3658#ifdef HAVE_LIBZ
3659 if (http->coding)
3660 {
3661 DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding));
3662
3663 if (length == 0)
3664 {
3665 http_content_coding_finish(http);
3666 bytes = 0;
3667 }
3668 else
3669 {
3670 http->stream.next_in = (Bytef *)buffer;
3671 http->stream.avail_in = length;
3672 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
3673 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
3674
3675 while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK)
3676 {
3677 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3678
3679 if (http->stream.avail_out == 0)
3680 {
3681 if (httpFlushWrite(http) < 0)
3682 {
3683 DEBUG_puts("1httpWrite2: Unable to flush, returning -1.");
3684 return (-1);
3685 }
3686
3687 http->stream.next_out = (Bytef *)http->wbuffer;
3688 http->stream.avail_out = sizeof(http->wbuffer);
3689 }
3690 }
3691
3692 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3693 bytes = length;
3694 }
3695 }
3696 else
3697#endif /* HAVE_LIBZ */
ef416fc2 3698 if (length > 0)
3699 {
3700 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
3701 {
e07d4801
MS
3702 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
3703 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 3704
3705 httpFlushWrite(http);
3706 }
3707
38e73f87
MS
3708 if ((length + http->wused) <= sizeof(http->wbuffer) &&
3709 length < sizeof(http->wbuffer))
ef416fc2 3710 {
3711 /*
3712 * Write to buffer...
3713 */
3714
e07d4801 3715 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 3716 CUPS_LLCAST length));
ef416fc2 3717
3718 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 3719 http->wused += (int)length;
3720 bytes = (ssize_t)length;
ef416fc2 3721 }
3722 else
3723 {
3724 /*
3725 * Otherwise write the data directly...
3726 */
3727
e07d4801 3728 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 3729 CUPS_LLCAST length));
ef416fc2 3730
a469f8a5 3731 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
b86bc4cf 3732 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 3733 else
b86bc4cf 3734 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 3735
e07d4801 3736 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 3737 CUPS_LLCAST bytes));
ef416fc2 3738 }
3739
a469f8a5 3740 if (http->data_encoding == HTTP_ENCODING_LENGTH)
ef416fc2 3741 http->data_remaining -= bytes;
3742 }
3743 else
3744 bytes = 0;
3745
3746 /*
3747 * Handle end-of-request processing...
3748 */
3749
a469f8a5
MS
3750 if ((http->data_encoding == HTTP_ENCODING_CHUNKED && length == 0) ||
3751 (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0))
ef416fc2 3752 {
3753 /*
3754 * Finished with the transfer; unless we are sending POST or PUT
3755 * data, go idle...
3756 */
3757
db8b865d
MS
3758#ifdef HAVE_LIBZ
3759 if (http->coding)
3760 http_content_coding_finish(http);
3761#endif /* HAVE_LIBZ */
3762
ef416fc2 3763 if (http->wused)
a469f8a5
MS
3764 {
3765 if (httpFlushWrite(http) < 0)
3766 return (-1);
3767 }
ef416fc2 3768
a469f8a5 3769 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
ef416fc2 3770 {
3771 /*
3772 * Send a 0-length chunk at the end of the request...
3773 */
3774
3775 http_write(http, "0\r\n\r\n", 5);
3776
3777 /*
3778 * Reset the data state...
3779 */
3780
a469f8a5 3781 http->data_encoding = HTTP_ENCODING_FIELDS;
ef416fc2 3782 http->data_remaining = 0;
3783 }
a469f8a5
MS
3784
3785 if (http->state == HTTP_STATE_POST_RECV)
3786 http->state ++;
ad29aeab
MS
3787 else if (http->state == HTTP_STATE_POST_SEND)
3788 http->state = HTTP_STATE_WAITING;
db8b865d 3789 else
cb7f98ee 3790 http->state = HTTP_STATE_STATUS;
a469f8a5 3791
db8b865d 3792 DEBUG_printf(("2httpWrite2: Changed state to %s.",
48bd1142 3793 httpStateString(http->state)));
ef416fc2 3794 }
3795
a469f8a5
MS
3796 DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes));
3797
ef416fc2 3798 return (bytes);
3799}
3800
3801
3802#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
3803/*
411affcf 3804 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 3805 */
3806
3807OSStatus /* O - -1 on error, 0 on success */
3808_httpWriteCDSA(
3809 SSLConnectionRef connection, /* I - SSL/TLS connection */
3810 const void *data, /* I - Data buffer */
3811 size_t *dataLength) /* IO - Number of bytes */
3812{
411affcf 3813 OSStatus result; /* Return value */
3814 ssize_t bytes; /* Number of bytes read */
3815 http_t *http; /* HTTP connection */
e53920b9 3816
3817
411affcf 3818 http = (http_t *)connection;
ef416fc2 3819
b423cd4c 3820 do
411affcf 3821 {
3822 bytes = write(http->fd, data, *dataLength);
3823 }
e07d4801 3824 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 3825
b423cd4c 3826 if (bytes == *dataLength)
411affcf 3827 {
b423cd4c 3828 result = 0;
411affcf 3829 }
b423cd4c 3830 else if (bytes >= 0)
3831 {
3832 *dataLength = bytes;
3833 result = errSSLWouldBlock;
3834 }
3835 else
3836 {
3837 *dataLength = 0;
ef55b745 3838
fa73b229 3839 if (errno == EAGAIN)
b423cd4c 3840 result = errSSLWouldBlock;
b423cd4c 3841 else
ed486911 3842 result = errSSLClosedAbort;
ef416fc2 3843 }
b423cd4c 3844
411affcf 3845 return (result);
ef416fc2 3846}
3847#endif /* HAVE_SSL && HAVE_CDSASSL */
3848
3849
411affcf 3850#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
3851/*
3852 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
3853 */
3854
3855ssize_t /* O - Number of bytes written or -1 on error */
3856_httpWriteGNUTLS(
e6b1a6a9 3857 gnutls_transport_ptr ptr, /* I - HTTP connection */
411affcf 3858 const void *data, /* I - Data buffer */
3859 size_t length) /* I - Number of bytes to write */
3860{
a4845881
MS
3861 ssize_t bytes; /* Bytes written */
3862
3863
3864 DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data,
3865 (int)length));
a2326b5b 3866#ifdef DEBUG
a4845881 3867 http_debug_hex("_httpWriteGNUTLS", data, (int)length);
a2326b5b 3868#endif /* DEBUG */
a4845881
MS
3869
3870 bytes = send(((http_t *)ptr)->fd, data, length, 0);
3871 DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes));
a2326b5b 3872
a4845881 3873 return (bytes);
411affcf 3874}
3875#endif /* HAVE_SSL && HAVE_GNUTLS */
3876
3877
a469f8a5
MS
3878/*
3879 * 'httpWriteResponse()' - Write a HTTP response to a client connection.
3880 *
9c0e8e5d 3881 * @since CUPS 1.7/OS X 10.9@
a469f8a5
MS
3882 */
3883
3884int /* O - 0 on success, -1 on error */
3885httpWriteResponse(http_t *http, /* I - HTTP connection */
3886 http_status_t status) /* I - Status code */
3887{
3888 http_encoding_t old_encoding; /* Old data_encoding value */
3889 off_t old_remaining; /* Old data_remaining value */
3890
3891
3892 /*
3893 * Range check input...
3894 */
3895
3896 DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", http, status));
3897
3898 if (!http || status < HTTP_STATUS_CONTINUE)
3899 {
3900 DEBUG_puts("1httpWriteResponse: Bad input.");
3901 return (-1);
3902 }
3903
3904 /*
3905 * Set the various standard fields if they aren't already...
3906 */
3907
3908 if (!http->fields[HTTP_FIELD_DATE][0])
3909 httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL)));
3910
cb7f98ee 3911 if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive)
a469f8a5 3912 {
5ec1fd3d 3913 http->keep_alive = HTTP_KEEPALIVE_OFF;
a469f8a5
MS
3914 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "");
3915 }
3916
3917 if (http->version == HTTP_VERSION_1_1)
3918 {
3919 if (!http->fields[HTTP_FIELD_CONNECTION][0])
3920 {
3921 if (http->keep_alive)
3922 httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
3923 else
3924 httpSetField(http, HTTP_FIELD_CONNECTION, "close");
3925 }
3926
3927 if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0])
3928 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10");
3929 }
3930
3931#ifdef HAVE_SSL
e200616a
MS
3932 if (status == HTTP_STATUS_UPGRADE_REQUIRED ||
3933 status == HTTP_STATUS_SWITCHING_PROTOCOLS)
a469f8a5
MS
3934 {
3935 if (!http->fields[HTTP_FIELD_CONNECTION][0])
3936 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
3937
3938 if (!http->fields[HTTP_FIELD_UPGRADE][0])
3939 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
e200616a
MS
3940
3941 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
3942 httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, "0");
a469f8a5
MS
3943 }
3944#endif /* HAVE_SSL */
3945
3946 if (!http->server)
c1420c87
MS
3947 httpSetField(http, HTTP_FIELD_SERVER,
3948 http->default_server ? http->default_server : CUPS_MINIMAL);
a469f8a5 3949
a469f8a5
MS
3950 /*
3951 * Set the Accept-Encoding field if it isn't already...
3952 */
3953
3954 if (!http->accept_encoding)
c1420c87
MS
3955 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
3956 http->default_accept_encoding ? http->default_accept_encoding :
3957#ifdef HAVE_LIBZ
3958 "gzip, deflate, identity");
3959#else
3960 "identity");
a469f8a5
MS
3961#endif /* HAVE_LIBZ */
3962
3963 /*
3964 * Send the response header...
3965 */
3966
3967 old_encoding = http->data_encoding;
3968 old_remaining = http->data_remaining;
3969 http->data_encoding = HTTP_ENCODING_FIELDS;
3970
3971 if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100,
3972 http->version % 100, (int)status, httpStatus(status)) < 0)
3973 {
3974 http->status = HTTP_STATUS_ERROR;
3975 return (-1);
3976 }
3977
3978 if (status != HTTP_STATUS_CONTINUE)
3979 {
3980 /*
3981 * 100 Continue doesn't have the rest of the response headers...
3982 */
3983
3984 int i; /* Looping var */
3985 const char *value; /* Field value */
3986
3987 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3988 {
3989 if ((value = httpGetField(http, i)) != NULL && *value)
3990 {
3991 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
3992 {
3993 http->status = HTTP_STATUS_ERROR;
3994 return (-1);
3995 }
3996 }
3997 }
3998
3999 if (http->cookie)
4000 {
e200616a
MS
4001 if (httpPrintf(http, "Set-Cookie: %s path=/ httponly%s\r\n",
4002 http->cookie, http->tls ? " secure" : "") < 1)
a469f8a5 4003 {
cb7f98ee 4004 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
4005 return (-1);
4006 }
4007 }
4008 }
4009
4010 if (httpWrite2(http, "\r\n", 2) < 2)
4011 {
cb7f98ee 4012 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
4013 return (-1);
4014 }
4015
4016 if (httpFlushWrite(http) < 0)
4017 {
cb7f98ee 4018 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
4019 return (-1);
4020 }
4021
e200616a
MS
4022 if (status == HTTP_STATUS_CONTINUE ||
4023 status == HTTP_STATUS_SWITCHING_PROTOCOLS)
a469f8a5
MS
4024 {
4025 /*
4026 * Restore the old data_encoding and data_length values...
4027 */
4028
4029 http->data_encoding = old_encoding;
4030 http->data_remaining = old_remaining;
4031
4032 if (old_remaining <= INT_MAX)
4033 http->_data_remaining = (int)old_remaining;
4034 else
4035 http->_data_remaining = INT_MAX;
4036 }
4037 else if (http->state == HTTP_STATE_OPTIONS ||
4038 http->state == HTTP_STATE_HEAD ||
4039 http->state == HTTP_STATE_PUT ||
4040 http->state == HTTP_STATE_TRACE ||
cb7f98ee
MS
4041 http->state == HTTP_STATE_CONNECT ||
4042 http->state == HTTP_STATE_STATUS)
a469f8a5
MS
4043 {
4044 DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
48bd1142 4045 "was %s.", httpStateString(http->state)));
a469f8a5
MS
4046 http->state = HTTP_STATE_WAITING;
4047 }
4048 else
4049 {
4050 /*
4051 * Force data_encoding and data_length to be set according to the response
4052 * headers...
4053 */
4054
4055 http_set_length(http);
4056
db8b865d 4057#ifdef HAVE_LIBZ
a469f8a5
MS
4058 /*
4059 * Then start any content encoding...
4060 */
4061
4062 DEBUG_puts("1httpWriteResponse: Calling http_content_coding_start.");
4063 http_content_coding_start(http,
4064 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
db8b865d 4065#endif /* HAVE_LIBZ */
a469f8a5
MS
4066 }
4067
4068 return (0);
4069}
4070
4071
411affcf 4072#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
4073/*
4074 * 'http_bio_ctrl()' - Control the HTTP connection.
4075 */
4076
4077static long /* O - Result/data */
4078http_bio_ctrl(BIO *h, /* I - BIO data */
4079 int cmd, /* I - Control command */
4080 long arg1, /* I - First argument */
4081 void *arg2) /* I - Second argument */
4082{
4083 switch (cmd)
4084 {
4085 default :
4086 return (0);
4087
4088 case BIO_CTRL_RESET :
4089 h->ptr = NULL;
4090 return (0);
4091
4092 case BIO_C_SET_FILE_PTR :
4093 h->ptr = arg2;
4094 h->init = 1;
4095 return (1);
4096
4097 case BIO_C_GET_FILE_PTR :
4098 if (arg2)
4099 {
4100 *((void **)arg2) = h->ptr;
4101 return (1);
4102 }
4103 else
4104 return (0);
ef55b745 4105
411affcf 4106 case BIO_CTRL_DUP :
4107 case BIO_CTRL_FLUSH :
4108 return (1);
4109 }
4110}
4111
4112
4113/*
4114 * 'http_bio_free()' - Free OpenSSL data.
4115 */
4116
4117static int /* O - 1 on success, 0 on failure */
4118http_bio_free(BIO *h) /* I - BIO data */
4119{
4120 if (!h)
4121 return (0);
4122
4123 if (h->shutdown)
4124 {
4125 h->init = 0;
4126 h->flags = 0;
4127 }
4128
4129 return (1);
4130}
4131
4132
4133/*
4134 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
4135 */
4136
4137static int /* O - 1 on success, 0 on failure */
4138http_bio_new(BIO *h) /* I - BIO data */
4139{
4140 if (!h)
4141 return (0);
4142
4143 h->init = 0;
4144 h->num = 0;
4145 h->ptr = NULL;
4146 h->flags = 0;
4147
4148 return (1);
4149}
4150
4151
4152/*
4153 * 'http_bio_puts()' - Send a string for OpenSSL.
4154 */
4155
4156static int /* O - Bytes written */
4157http_bio_puts(BIO *h, /* I - BIO data */
4158 const char *str) /* I - String to write */
4159{
b86bc4cf 4160#ifdef WIN32
4161 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
4162#else
411affcf 4163 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 4164#endif /* WIN32 */
411affcf 4165}
4166
4167
4168/*
4169 * 'http_bio_read()' - Read data for OpenSSL.
4170 */
4171
4172static int /* O - Bytes read */
4173http_bio_read(BIO *h, /* I - BIO data */
4174 char *buf, /* I - Buffer */
4175 int size) /* I - Number of bytes to read */
4176{
4177 http_t *http; /* HTTP connection */
4178
4179
4180 http = (http_t *)h->ptr;
4181
4182 if (!http->blocking)
4183 {
4184 /*
4185 * Make sure we have data before we read...
4186 */
4187
85dda01c 4188 while (!_httpWait(http, http->wait_value, 0))
411affcf 4189 {
f228370c
MS
4190 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4191 continue;
4192
b86bc4cf 4193#ifdef WIN32
4194 http->error = WSAETIMEDOUT;
4195#else
411affcf 4196 http->error = ETIMEDOUT;
b86bc4cf 4197#endif /* WIN32 */
4198
411affcf 4199 return (-1);
4200 }
4201 }
4202
4203 return (recv(http->fd, buf, size, 0));
4204}
4205
4206
4207/*
4208 * 'http_bio_write()' - Write data for OpenSSL.
4209 */
4210
4211static int /* O - Bytes written */
4212http_bio_write(BIO *h, /* I - BIO data */
4213 const char *buf, /* I - Buffer to write */
4214 int num) /* I - Number of bytes to write */
4215{
4216 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
4217}
4218#endif /* HAVE_SSL && HAVE_LIBSSL */
4219
4220
a469f8a5
MS
4221#ifdef HAVE_LIBZ
4222/*
4223 * 'http_content_coding_finish()' - Finish doing any content encoding.
4224 */
4225
4226static void
4227http_content_coding_finish(
4228 http_t *http) /* I - HTTP connection */
4229{
4230 int zerr; /* Compression status */
4231
4232
4233 switch (http->coding)
4234 {
4235 case _HTTP_CODING_DEFLATE :
4236 case _HTTP_CODING_GZIP :
4237 do
4238 {
4239 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
4240 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
4241
4242 zerr = deflate(&(http->stream), Z_FINISH);
4243
4244 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
4245 if (http->wused == sizeof(http->wbuffer))
4246 httpFlushWrite(http);
4247 }
4248 while (zerr == Z_OK);
4249
4250 deflateEnd(&(http->stream));
4251
4252 if (http->wused)
4253 httpFlushWrite(http);
4254 break;
4255
4256 case _HTTP_CODING_INFLATE :
4257 case _HTTP_CODING_GUNZIP :
4258 inflateEnd(&(http->stream));
0fa6c7fa
MS
4259 free(http->dbuffer);
4260 http->dbuffer = NULL;
a469f8a5
MS
4261 break;
4262
4263 default :
4264 break;
4265 }
4266
4267 http->coding = _HTTP_CODING_IDENTITY;
4268}
4269
4270
4271/*
4272 * 'http_content_coding_start()' - Start doing content encoding.
4273 */
4274
4275static void
4276http_content_coding_start(
4277 http_t *http, /* I - HTTP connection */
4278 const char *value) /* I - Value of Content-Encoding */
4279{
4280 int zerr; /* Error/status */
4281 _http_coding_t coding; /* Content coding value */
4282
4283
4284 DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http,
4285 value));
4286
4287 if (http->coding != _HTTP_CODING_IDENTITY)
4288 {
4289 DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
4290 http->coding));
4291 return;
4292 }
4293 else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
4294 {
cb7f98ee
MS
4295 if (http->state == HTTP_STATE_GET_SEND ||
4296 http->state == HTTP_STATE_POST_SEND)
a469f8a5
MS
4297 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP :
4298 _HTTP_CODING_GUNZIP;
cb7f98ee
MS
4299 else if (http->state == HTTP_STATE_POST_RECV ||
4300 http->state == HTTP_STATE_PUT_RECV)
a469f8a5
MS
4301 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
4302 _HTTP_CODING_GUNZIP;
4303 else
4304 {
4305 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4306 return;
4307 }
4308 }
4309 else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
4310 {
cb7f98ee
MS
4311 if (http->state == HTTP_STATE_GET_SEND ||
4312 http->state == HTTP_STATE_POST_SEND)
a469f8a5
MS
4313 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
4314 _HTTP_CODING_INFLATE;
cb7f98ee
MS
4315 else if (http->state == HTTP_STATE_POST_RECV ||
4316 http->state == HTTP_STATE_PUT_RECV)
a469f8a5
MS
4317 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
4318 _HTTP_CODING_INFLATE;
4319 else
4320 {
4321 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4322 return;
4323 }
4324 }
4325 else
4326 {
4327 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
4328 return;
4329 }
4330
4331 memset(&(http->stream), 0, sizeof(http->stream));
4332
4333 switch (coding)
4334 {
4335 case _HTTP_CODING_DEFLATE :
4336 case _HTTP_CODING_GZIP :
4337 if (http->wused)
4338 httpFlushWrite(http);
4339
db8b865d
MS
4340 /*
4341 * Window size for compression is 11 bits - optimal based on PWG Raster
4342 * sample files on pwg.org. -11 is raw deflate, 27 is gzip, per ZLIB
4343 * documentation.
4344 */
4345
a469f8a5
MS
4346 if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION,
4347 Z_DEFLATED,
db8b865d 4348 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7,
a469f8a5
MS
4349 Z_DEFAULT_STRATEGY)) < Z_OK)
4350 {
cb7f98ee 4351 http->status = HTTP_STATUS_ERROR;
a469f8a5
MS
4352 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
4353 return;
4354 }
4355 break;
4356
4357 case _HTTP_CODING_INFLATE :
4358 case _HTTP_CODING_GUNZIP :
0fa6c7fa 4359 if ((http->dbuffer = malloc(HTTP_MAX_BUFFER)) == NULL)
a469f8a5 4360 {
cb7f98ee 4361 http->status = HTTP_STATUS_ERROR;
0fa6c7fa 4362 http->error = errno;
a469f8a5
MS
4363 return;
4364 }
0fa6c7fa 4365
db8b865d
MS
4366 /*
4367 * Window size for decompression is up to 15 bits (maximum supported).
4368 * -15 is raw inflate, 31 is gunzip, per ZLIB documentation.
4369 */
4370
0fa6c7fa 4371 if ((zerr = inflateInit2(&(http->stream),
db8b865d 4372 coding == _HTTP_CODING_INFLATE ? -15 : 31))
0fa6c7fa
MS
4373 < Z_OK)
4374 {
4375 free(http->dbuffer);
4376 http->dbuffer = NULL;
cb7f98ee 4377 http->status = HTTP_STATUS_ERROR;
0fa6c7fa
MS
4378 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
4379 return;
4380 }
4381
4382 http->stream.avail_in = 0;
4383 http->stream.next_in = http->dbuffer;
a469f8a5
MS
4384 break;
4385
4386 default :
4387 break;
4388 }
4389
4390 http->coding = coding;
4391
4392 DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
4393 http->coding));
4394}
4395#endif /* HAVE_LIBZ */
4396
4397
db8b865d
MS
4398/*
4399 * 'http_create()' - Create an unconnected HTTP connection.
4400 */
4401
4402static http_t * /* O - HTTP connection */
4403http_create(
4404 const char *host, /* I - Hostname */
4405 int port, /* I - Port number */
4406 http_addrlist_t *addrlist, /* I - Address list or NULL */
4407 int family, /* I - Address family or AF_UNSPEC */
4408 http_encryption_t encryption, /* I - Encryption to use */
4409 int blocking, /* I - 1 for blocking mode */
4410 _http_mode_t mode) /* I - _HTTP_MODE_CLIENT or _SERVER */
4411{
4412 http_t *http; /* New HTTP connection */
4413 char service[255]; /* Service name */
4414 http_addrlist_t *myaddrlist = NULL; /* My address list */
4415
4416
4417 DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, "
4418 "encryption=%d, blocking=%d, mode=%d)", host, port, addrlist,
4419 family, encryption, blocking, mode));
4420
4421 if (!host && mode == _HTTP_MODE_CLIENT)
4422 return (NULL);
4423
4424 httpInitialize();
4425
4426 /*
4427 * Lookup the host...
4428 */
4429
4430 if (addrlist)
4431 {
4432 myaddrlist = httpAddrCopyList(addrlist);
4433 }
4434 else
4435 {
4436 snprintf(service, sizeof(service), "%d", port);
4437
4438 myaddrlist = httpAddrGetList(host, family, service);
4439 }
4440
4441 if (!myaddrlist)
4442 return (NULL);
4443
4444 /*
4445 * Allocate memory for the structure...
4446 */
4447
4448 if ((http = calloc(sizeof(http_t), 1)) == NULL)
4449 {
cb7f98ee 4450 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
db8b865d
MS
4451 httpAddrFreeList(addrlist);
4452 return (NULL);
4453 }
4454
4455 /*
4456 * Initialize the HTTP data...
4457 */
4458
4459 http->mode = mode;
4460 http->activity = time(NULL);
4461 http->addrlist = myaddrlist;
4462 http->blocking = blocking;
4463 http->fd = -1;
4464#ifdef HAVE_GSSAPI
4465 http->gssctx = GSS_C_NO_CONTEXT;
4466 http->gssname = GSS_C_NO_NAME;
4467#endif /* HAVE_GSSAPI */
cb7f98ee 4468 http->status = HTTP_STATUS_CONTINUE;
db8b865d
MS
4469 http->version = HTTP_VERSION_1_1;
4470
4471 if (host)
4472 strlcpy(http->hostname, host, sizeof(http->hostname));
4473
4474 if (port == 443) /* Always use encryption for https */
4475 http->encryption = HTTP_ENCRYPTION_ALWAYS;
4476 else
4477 http->encryption = encryption;
4478
4479 http_set_wait(http);
4480
4481 /*
4482 * Return the new structure...
4483 */
4484
4485 return (http);
4486}
4487
4488/* For OS X 10.8 and earlier */
4489http_t *_httpCreate(const char *host, int port, http_addrlist_t *addrlist,
4490 http_encryption_t encryption, int family)
4491{ return (http_create(host, port, addrlist, family, encryption, 1,
4492 _HTTP_MODE_CLIENT)); }
4493
4494
ae71f5de
MS
4495#ifdef DEBUG
4496/*
4497 * 'http_debug_hex()' - Do a hex dump of a buffer.
4498 */
4499
4500static void
4501http_debug_hex(const char *prefix, /* I - Prefix for line */
4502 const char *buffer, /* I - Buffer to dump */
4503 int bytes) /* I - Bytes to dump */
4504{
4505 int i, j, /* Looping vars */
4506 ch; /* Current character */
4507 char line[255], /* Line buffer */
4508 *start, /* Start of line after prefix */
4509 *ptr; /* Pointer into line */
4510
4511
f11a948a 4512 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
4513 return;
4514
83e08001 4515 DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
ae71f5de 4516
f11a948a 4517 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
4518 start = line + strlen(line);
4519
4520 for (i = 0; i < bytes; i += 16)
4521 {
4522 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
4523 sprintf(ptr, "%02X", buffer[i + j] & 255);
4524
4525 while (j < 16)
4526 {
5a9febac 4527 memcpy(ptr, " ", 3);
ae71f5de
MS
4528 ptr += 2;
4529 j ++;
4530 }
4531
5a9febac 4532 memcpy(ptr, " ", 3);
ae71f5de
MS
4533 ptr += 2;
4534
4535 for (j = 0; j < 16 && (i + j) < bytes; j ++)
4536 {
4537 ch = buffer[i + j] & 255;
4538
4539 if (ch < ' ' || ch >= 127)
4540 ch = '.';
4541
4542 *ptr++ = ch;
4543 }
4544
4545 *ptr = '\0';
4546 DEBUG_puts(line);
4547 }
4548}
4549#endif /* DEBUG */
4550
4551
0fa6c7fa
MS
4552/*
4553 * 'http_read()' - Read a buffer from a HTTP connection.
4554 *
4555 * This function does the low-level read from the socket, retrying and timing
4556 * out as needed.
4557 */
4558
4559static ssize_t /* O - Number of bytes read or -1 on error */
e6b1a6a9 4560http_read(http_t *http, /* I - HTTP connection */
0fa6c7fa
MS
4561 char *buffer, /* I - Buffer */
4562 size_t length) /* I - Maximum bytes to read */
4563{
4564 ssize_t bytes; /* Bytes read */
4565
4566
4567 DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
4568 buffer, CUPS_LLCAST length));
4569
4570 if (!http->blocking)
4571 {
4572 while (!httpWait(http, http->wait_value))
4573 {
4574 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4575 continue;
4576
4577 DEBUG_puts("2http_read: Timeout.");
4578 return (0);
4579 }
4580 }
4581
4582 DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
4583
4584 do
4585 {
4586#ifdef HAVE_SSL
4587 if (http->tls)
4588 bytes = http_read_ssl(http, buffer, length);
4589 else
4590#endif /* HAVE_SSL */
4591 bytes = recv(http->fd, buffer, length, 0);
4592
4593 if (bytes < 0)
4594 {
4595#ifdef WIN32
4596 if (WSAGetLastError() != WSAEINTR)
4597 {
4598 http->error = WSAGetLastError();
4599 return (-1);
4600 }
4601 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4602 {
4603 if (!http->timeout_cb ||
4604 !(*http->timeout_cb)(http, http->timeout_data))
4605 {
4606 http->error = WSAEWOULDBLOCK;
4607 return (-1);
4608 }
4609 }
4610#else
4611 DEBUG_printf(("2http_read: %s", strerror(errno)));
4612
4613 if (errno == EWOULDBLOCK || errno == EAGAIN)
4614 {
4615 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
4616 {
4617 http->error = errno;
4618 return (-1);
4619 }
4620 else if (!http->timeout_cb && errno != EAGAIN)
4621 {
4622 http->error = errno;
4623 return (-1);
4624 }
4625 }
4626 else if (errno != EINTR)
4627 {
4628 http->error = errno;
4629 return (-1);
4630 }
4631#endif /* WIN32 */
4632 }
4633 }
4634 while (bytes < 0);
4635
4636 DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
4637 CUPS_LLCAST bytes));
4638#ifdef DEBUG
4639 if (bytes > 0)
6961465f 4640 http_debug_hex("http_read", buffer, (int)bytes);
0fa6c7fa
MS
4641#endif /* DEBUG */
4642
4643 if (bytes < 0)
4644 {
4645#ifdef WIN32
4646 if (WSAGetLastError() == WSAEINTR)
4647 bytes = 0;
4648 else
4649 http->error = WSAGetLastError();
4650#else
4651 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
4652 bytes = 0;
4653 else
4654 http->error = errno;
4655#endif /* WIN32 */
4656 }
4657 else if (bytes == 0)
4658 {
4659 http->error = EPIPE;
4660 return (0);
4661 }
4662
4663 return (bytes);
4664}
4665
4666
4667/*
4668 * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
4669 *
4670 * This function reads data from the HTTP buffer or from the socket, as needed.
4671 */
4672
4673static ssize_t /* O - Number of bytes read or -1 on error */
e6b1a6a9 4674http_read_buffered(http_t *http, /* I - HTTP connection */
0fa6c7fa
MS
4675 char *buffer, /* I - Buffer */
4676 size_t length) /* I - Maximum bytes to read */
4677{
4678 ssize_t bytes; /* Bytes read */
4679
4680
4681 DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT
4682 ") used=%d",
4683 http, buffer, CUPS_LLCAST length, http->used));
4684
4685 if (http->used > 0)
4686 {
4687 if (length > (size_t)http->used)
4688 bytes = (size_t)http->used;
4689 else
4690 bytes = length;
4691
4692 DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
4693 (int)bytes));
4694
4695 memcpy(buffer, http->buffer, bytes);
4696 http->used -= (int)bytes;
4697
4698 if (http->used > 0)
4699 memmove(http->buffer, http->buffer + bytes, http->used);
4700 }
4701 else
4702 bytes = http_read(http, buffer, length);
4703
4704 return (bytes);
4705}
4706
4707
4708/*
4709 * 'http_read_chunk()' - Read a chunk from a HTTP connection.
4710 *
4711 * This function reads and validates the chunk length, then does a buffered read
4712 * returning the number of bytes placed in the buffer.
4713 */
4714
4715static ssize_t /* O - Number of bytes read or -1 on error */
e6b1a6a9 4716http_read_chunk(http_t *http, /* I - HTTP connection */
0fa6c7fa
MS
4717 char *buffer, /* I - Buffer */
4718 size_t length) /* I - Maximum bytes to read */
4719{
4720 DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
4721 http, buffer, CUPS_LLCAST length));
4722
4723 if (http->data_remaining <= 0)
4724 {
4725 char len[32]; /* Length string */
4726
4727 if (!httpGets(len, sizeof(len), http))
4728 {
4729 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4730 return (0);
4731 }
4732
4733 if (!len[0])
4734 {
4735 DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
4736 if (!httpGets(len, sizeof(len), http))
4737 {
4738 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4739 return (0);
4740 }
4741 }
4742
4743 http->data_remaining = strtoll(len, NULL, 16);
4744
4745 if (http->data_remaining < 0)
4746 {
4747 DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
4748 CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
4749 return (0);
4750 }
4751
4752 DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
4753 len, CUPS_LLCAST http->data_remaining));
4754
4755 if (http->data_remaining == 0)
4756 {
4757 /*
4758 * 0-length chunk, grab trailing blank line...
4759 */
4760
4761 httpGets(len, sizeof(len), http);
4762 }
4763 }
4764
4765 DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
4766 CUPS_LLCAST http->data_remaining));
4767
4768 if (http->data_remaining <= 0)
4769 return (0);
4770 else if (length > (size_t)http->data_remaining)
4771 length = (size_t)http->data_remaining;
4772
4773 return (http_read_buffered(http, buffer, length));
4774}
4775
4776
ef416fc2 4777#ifdef HAVE_SSL
4778/*
4779 * 'http_read_ssl()' - Read from a SSL/TLS connection.
4780 */
4781
4782static int /* O - Bytes read */
e6b1a6a9 4783http_read_ssl(http_t *http, /* I - HTTP connection */
ef416fc2 4784 char *buf, /* I - Buffer to store data */
4785 int len) /* I - Length of buffer */
4786{
4787# if defined(HAVE_LIBSSL)
4788 return (SSL_read((SSL *)(http->tls), buf, len));
4789
4790# elif defined(HAVE_GNUTLS)
ef55b745
MS
4791 ssize_t result; /* Return value */
4792
4793
7cf5915e 4794 result = gnutls_record_recv(http->tls, buf, len);
ef55b745
MS
4795
4796 if (result < 0 && !errno)
4797 {
4798 /*
4799 * Convert GNU TLS error to errno value...
4800 */
4801
4802 switch (result)
4803 {
4804 case GNUTLS_E_INTERRUPTED :
4805 errno = EINTR;
4806 break;
4807
4808 case GNUTLS_E_AGAIN :
4809 errno = EAGAIN;
4810 break;
4811
4812 default :
4813 errno = EPIPE;
4814 break;
4815 }
4816
4817 result = -1;
4818 }
4819
4820 return ((int)result);
ef416fc2 4821
4822# elif defined(HAVE_CDSASSL)
fa73b229 4823 int result; /* Return value */
ef416fc2 4824 OSStatus error; /* Error info */
4825 size_t processed; /* Number of bytes processed */
4826
4827
7cf5915e 4828 error = SSLRead(http->tls, buf, len, &processed);
83e08001
MS
4829 DEBUG_printf(("6http_read_ssl: error=%d, processed=%d", (int)error,
4830 (int)processed));
fa73b229 4831 switch (error)
ef416fc2 4832 {
fa73b229 4833 case 0 :
4834 result = (int)processed;
4835 break;
84315f46 4836
fa73b229 4837 case errSSLWouldBlock :
b423cd4c 4838 if (processed)
4839 result = (int)processed;
4840 else
4841 {
4842 result = -1;
83e08001 4843 errno = EINTR;
b423cd4c 4844 }
fa73b229 4845 break;
84315f46
MS
4846
4847 case errSSLClosedGraceful :
fa73b229 4848 default :
84315f46
MS
4849 if (processed)
4850 result = (int)processed;
4851 else
4852 {
4853 result = -1;
83e08001 4854 errno = EPIPE;
84315f46 4855 }
fa73b229 4856 break;
ef416fc2 4857 }
fa73b229 4858
4859 return (result);
83e08001 4860
cc754834
MS
4861# elif defined(HAVE_SSPISSL)
4862 return _sspiRead((_sspi_struct_t*) http->tls, buf, len);
ef416fc2 4863# endif /* HAVE_LIBSSL */
4864}
4865#endif /* HAVE_SSL */
4866
4867
4868/*
4869 * 'http_send()' - Send a request with all fields and the trailing blank line.
4870 */
4871
a469f8a5 4872static int /* O - 0 on success, non-zero on error */
e6b1a6a9 4873http_send(http_t *http, /* I - HTTP connection */
a469f8a5
MS
4874 http_state_t request, /* I - Request code */
4875 const char *uri) /* I - URI */
ef416fc2 4876{
a469f8a5
MS
4877 int i; /* Looping var */
4878 char buf[1024]; /* Encoded URI buffer */
4879 const char *value; /* Field value */
4880 static const char * const codes[] = /* Request code strings */
4881 {
ef416fc2 4882 NULL,
4883 "OPTIONS",
4884 "GET",
4885 NULL,
4886 "HEAD",
4887 "POST",
4888 NULL,
4889 NULL,
4890 "PUT",
4891 NULL,
4892 "DELETE",
4893 "TRACE",
a469f8a5
MS
4894 "CLOSE",
4895 NULL,
4896 NULL
ef416fc2 4897 };
ef416fc2 4898
4899
cb7f98ee 4900 DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 4901 http, codes[request], uri));
4902
4903 if (http == NULL || uri == NULL)
4904 return (-1);
4905
4906 /*
4907 * Set the User-Agent field if it isn't already...
4908 */
4909
4910 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
db8b865d
MS
4911 {
4912 if (http->default_user_agent)
4913 httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent);
4914 else
4915 httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent());
4916 }
ef416fc2 4917
a469f8a5
MS
4918 /*
4919 * Set the Accept-Encoding field if it isn't already...
4920 */
4921
c1420c87
MS
4922 if (!http->accept_encoding && http->default_accept_encoding)
4923 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
4924 http->default_accept_encoding);
a469f8a5 4925
ef416fc2 4926 /*
4927 * Encode the URI as needed...
4928 */
4929
839a51c8 4930 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 4931
4932 /*
4933 * See if we had an error the last time around; if so, reconnect...
4934 */
4935
cb7f98ee
MS
4936 if (http->fd < 0 || http->status == HTTP_STATUS_ERROR ||
4937 http->status >= HTTP_STATUS_BAD_REQUEST)
4938 {
4939 DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d",
4940 http->fd, http->status, http->tls_upgrade));
4941
4942 if (httpReconnect2(http, 30000, NULL))
fa73b229 4943 return (-1);
cb7f98ee 4944 }
ef416fc2 4945
d09495fa 4946 /*
4947 * Flush any written data that is pending...
4948 */
4949
4950 if (http->wused)
536bc2c6
MS
4951 {
4952 if (httpFlushWrite(http) < 0)
cb7f98ee 4953 if (httpReconnect2(http, 30000, NULL))
536bc2c6
MS
4954 return (-1);
4955 }
d09495fa 4956
ef416fc2 4957 /*
4958 * Send the request header...
4959 */
4960
d09495fa 4961 http->state = request;
a469f8a5 4962 http->data_encoding = HTTP_ENCODING_FIELDS;
d09495fa 4963
cb7f98ee 4964 if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT)
ef416fc2 4965 http->state ++;
4966
cb7f98ee 4967 http->status = HTTP_STATUS_CONTINUE;
ef416fc2 4968
4969#ifdef HAVE_SSL
cb7f98ee 4970 if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
ef416fc2 4971 {
4972 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
a469f8a5 4973 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
ef416fc2 4974 }
4975#endif /* HAVE_SSL */
4976
4977 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
4978 {
cb7f98ee 4979 http->status = HTTP_STATUS_ERROR;
ef416fc2 4980 return (-1);
4981 }
4982
4983 for (i = 0; i < HTTP_FIELD_MAX; i ++)
a469f8a5 4984 if ((value = httpGetField(http, i)) != NULL && *value)
ef416fc2 4985 {
cb7f98ee 4986 DEBUG_printf(("5http_send: %s: %s", http_fields[i], value));
ef416fc2 4987
37e7e6e0
MS
4988 if (i == HTTP_FIELD_HOST)
4989 {
a469f8a5
MS
4990 if (httpPrintf(http, "Host: %s:%d\r\n", value,
4991 httpAddrPort(http->hostaddr)) < 1)
37e7e6e0 4992 {
cb7f98ee 4993 http->status = HTTP_STATUS_ERROR;
37e7e6e0
MS
4994 return (-1);
4995 }
4996 }
a469f8a5 4997 else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
ef416fc2 4998 {
cb7f98ee 4999 http->status = HTTP_STATUS_ERROR;
ef416fc2 5000 return (-1);
5001 }
5002 }
5003
5004 if (http->cookie)
5005 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
5006 {
cb7f98ee 5007 http->status = HTTP_STATUS_ERROR;
ef416fc2 5008 return (-1);
5009 }
5010
cb7f98ee
MS
5011 DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect,
5012 http->mode, http->state));
5013
5014 if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT &&
5015 (http->state == HTTP_STATE_POST_RECV ||
5016 http->state == HTTP_STATE_PUT_RECV))
b423cd4c 5017 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
5018 {
cb7f98ee 5019 http->status = HTTP_STATUS_ERROR;
b423cd4c 5020 return (-1);
5021 }
5022
ef416fc2 5023 if (httpPrintf(http, "\r\n") < 1)
5024 {
cb7f98ee 5025 http->status = HTTP_STATUS_ERROR;
ef416fc2 5026 return (-1);
5027 }
5028
536bc2c6
MS
5029 if (httpFlushWrite(http) < 0)
5030 return (-1);
5031
a469f8a5 5032 http_set_length(http);
ef416fc2 5033 httpClearFields(http);
5034
f7deaa1a 5035 /*
b94498cf 5036 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 5037 */
5038
ef55b745
MS
5039 if (http->field_authorization && http->authstring &&
5040 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 5041 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 5042 {
5043 http->_authstring[0] = '\0';
5044
5045 if (http->authstring != http->_authstring)
5046 free(http->authstring);
ef55b745 5047
f7deaa1a 5048 http->authstring = http->_authstring;
5049 }
5050
ef416fc2 5051 return (0);
5052}
5053
5054
5055#ifdef HAVE_SSL
c1420c87 5056# if defined(HAVE_CDSASSL)
7cf5915e
MS
5057/*
5058 * 'http_set_credentials()' - Set the SSL/TLS credentials.
5059 */
5060
5061static int /* O - Status of connection */
e6b1a6a9 5062http_set_credentials(http_t *http) /* I - HTTP connection */
7cf5915e
MS
5063{
5064 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
7cf5915e
MS
5065 OSStatus error = 0; /* Error code */
5066 http_tls_credentials_t credentials = NULL;
5067 /* TLS credentials */
7cf5915e
MS
5068
5069
5070 DEBUG_printf(("7http_set_credentials(%p)", http));
5071
7cf5915e
MS
5072 /*
5073 * Prefer connection specific credentials...
5074 */
5075
5076 if ((credentials = http->tls_credentials) == NULL)
5077 credentials = cg->tls_credentials;
5078
7cf5915e
MS
5079 if (credentials)
5080 {
5081 error = SSLSetCertificate(http->tls, credentials);
5082 DEBUG_printf(("4http_set_credentials: SSLSetCertificate, error=%d",
5083 (int)error));
5084 }
5085 else
5086 DEBUG_puts("4http_set_credentials: No credentials to set.");
5087
5088 return (error);
7cf5915e 5089}
c1420c87 5090# endif /* HAVE_CDSASSL */
9b66acc5 5091#endif /* HAVE_SSL */
7cf5915e
MS
5092
5093
a469f8a5
MS
5094/*
5095 * 'http_set_length()' - Set the data_encoding and data_remaining values.
5096 */
5097
5098static off_t /* O - Remainder or -1 on error */
5099http_set_length(http_t *http) /* I - Connection */
5100{
5101 off_t remaining; /* Remainder */
5102
5103
5104 DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", http, http->mode,
48bd1142 5105 httpStateString(http->state)));
a469f8a5
MS
5106
5107 if ((remaining = httpGetLength2(http)) >= 0)
5108 {
5109 if (http->mode == _HTTP_MODE_SERVER &&
5110 http->state != HTTP_STATE_GET_SEND &&
c41769ff 5111 http->state != HTTP_STATE_PUT &&
a469f8a5
MS
5112 http->state != HTTP_STATE_POST &&
5113 http->state != HTTP_STATE_POST_SEND)
5114 {
5115 DEBUG_puts("1http_set_length: Not setting data_encoding/remaining.");
5116 return (remaining);
5117 }
5118
5119 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING],
5120 "chunked"))
5121 {
5122 DEBUG_puts("1http_set_length: Setting data_encoding to "
5123 "HTTP_ENCODING_CHUNKED.");
5124 http->data_encoding = HTTP_ENCODING_CHUNKED;
5125 }
5126 else
5127 {
5128 DEBUG_puts("1http_set_length: Setting data_encoding to "
5129 "HTTP_ENCODING_LENGTH.");
5130 http->data_encoding = HTTP_ENCODING_LENGTH;
5131 }
5132
5133 DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".",
5134 CUPS_LLCAST remaining));
5135 http->data_remaining = remaining;
5136
5137 if (remaining <= INT_MAX)
5138 http->_data_remaining = remaining;
5139 else
5140 http->_data_remaining = INT_MAX;
5141 }
5142
5143 return (remaining);
5144}
5145
85dda01c
MS
5146/*
5147 * 'http_set_timeout()' - Set the socket timeout values.
5148 */
5149
5150static void
5151http_set_timeout(int fd, /* I - File descriptor */
5152 double timeout) /* I - Timeout in seconds */
5153{
5154#ifdef WIN32
5155 DWORD tv = (DWORD)(timeout * 1000);
5156 /* Timeout in milliseconds */
5157
db8b865d
MS
5158 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
5159 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
85dda01c
MS
5160
5161#else
5162 struct timeval tv; /* Timeout in secs and usecs */
5163
5164 tv.tv_sec = (int)timeout;
5165 tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
5166
db8b865d
MS
5167 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
5168 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
85dda01c
MS
5169#endif /* WIN32 */
5170}
5171
5172
5173/*
5174 * 'http_set_wait()' - Set the default wait value for reads.
5175 */
5176
5177static void
e6b1a6a9 5178http_set_wait(http_t *http) /* I - HTTP connection */
85dda01c
MS
5179{
5180 if (http->blocking)
5181 {
5182 http->wait_value = (int)(http->timeout_value * 1000);
5183
5184 if (http->wait_value <= 0)
5185 http->wait_value = 60000;
5186 }
5187 else
5188 http->wait_value = 10000;
5189}
5190
5191
9b66acc5 5192#ifdef HAVE_SSL
ef416fc2 5193/*
5194 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
5195 */
5196
a4845881 5197static int /* O - 0 on success, -1 on failure */
e6b1a6a9 5198http_setup_ssl(http_t *http) /* I - HTTP connection */
ef416fc2 5199{
12f89d24
MS
5200 char hostname[256], /* Hostname */
5201 *hostptr; /* Pointer into hostname */
7cf5915e 5202
ef416fc2 5203# ifdef HAVE_LIBSSL
a4845881
MS
5204 SSL_CTX *context; /* Context for encryption */
5205 BIO *bio; /* BIO data */
5206 const char *message = NULL;/* Error message */
ef416fc2 5207# elif defined(HAVE_GNUTLS)
a4845881 5208 int status; /* Status of handshake */
ef416fc2 5209 gnutls_certificate_client_credentials *credentials;
89d46774 5210 /* TLS credentials */
ef416fc2 5211# elif defined(HAVE_CDSASSL)
0fa6c7fa
MS
5212 _cups_globals_t *cg = _cupsGlobals();
5213 /* Pointer to library globals */
a4845881 5214 OSStatus error; /* Error code */
a4845881 5215 const char *message = NULL;/* Error message */
a4845881
MS
5216 cups_array_t *credentials; /* Credentials array */
5217 cups_array_t *names; /* CUPS distinguished names */
5218 CFArrayRef dn_array; /* CF distinguished names array */
5219 CFIndex count; /* Number of credentials */
5220 CFDataRef data; /* Certificate data */
5221 int i; /* Looping var */
5222 http_credential_t *credential; /* Credential data */
cc754834 5223# elif defined(HAVE_SSPISSL)
a4845881
MS
5224 TCHAR username[256]; /* Username returned from GetUserName() */
5225 TCHAR commonName[256];/* Common name for certificate */
5226 DWORD dwSize; /* 32 bit size */
ef416fc2 5227# endif /* HAVE_LIBSSL */
5228
5229
e07d4801 5230 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 5231
7cf5915e 5232 /*
c1420c87 5233 * Get the hostname to use for SSL...
7cf5915e
MS
5234 */
5235
5236 if (httpAddrLocalhost(http->hostaddr))
12f89d24 5237 {
12f89d24
MS
5238 strlcpy(hostname, "localhost", sizeof(hostname));
5239 }
7cf5915e 5240 else
12f89d24
MS
5241 {
5242 /*
c1420c87 5243 * Otherwise make sure the hostname we have does not end in a trailing dot.
12f89d24
MS
5244 */
5245
12f89d24
MS
5246 strlcpy(hostname, http->hostname, sizeof(hostname));
5247 if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
5248 *hostptr == '.')
5249 *hostptr = '\0';
5250 }
dcb445bc 5251
ef416fc2 5252# ifdef HAVE_LIBSSL
5253 context = SSL_CTX_new(SSLv23_client_method());
5254
5255 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
5256
411affcf 5257 bio = BIO_new(_httpBIOMethods());
5258 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
5259
7cf5915e 5260 http->tls = SSL_new(context);
a4845881 5261 SSL_set_bio(http->tls, bio, bio);
ef416fc2 5262
a29fd7dd 5263# ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
dcb445bc 5264 SSL_set_tlsext_host_name(http->tls, hostname);
a29fd7dd 5265# endif /* HAVE_SSL_SET_TLSEXT_HOST_NAME */
dcb445bc 5266
7cf5915e 5267 if (SSL_connect(http->tls) != 1)
ef416fc2 5268 {
ef416fc2 5269 unsigned long error; /* Error code */
5270
5271 while ((error = ERR_get_error()) != 0)
a4845881
MS
5272 {
5273 message = ERR_error_string(error, NULL);
5274 DEBUG_printf(("8http_setup_ssl: %s", message));
5275 }
ef416fc2 5276
5277 SSL_CTX_free(context);
7cf5915e
MS
5278 SSL_free(http->tls);
5279 http->tls = NULL;
ef416fc2 5280
5281# ifdef WIN32
5282 http->error = WSAGetLastError();
5283# else
5284 http->error = errno;
5285# endif /* WIN32 */
cb7f98ee 5286 http->status = HTTP_STATUS_ERROR;
ef416fc2 5287
a4845881
MS
5288 if (!message)
5289 message = _("Unable to establish a secure connection to host.");
5290
e924ce80 5291 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
a4845881
MS
5292
5293 return (-1);
ef416fc2 5294 }
5295
5296# elif defined(HAVE_GNUTLS)
ef416fc2 5297 credentials = (gnutls_certificate_client_credentials *)
5298 malloc(sizeof(gnutls_certificate_client_credentials));
5299 if (credentials == NULL)
5300 {
a4845881
MS
5301 DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s",
5302 strerror(errno)));
5303 http->error = errno;
cb7f98ee
MS
5304 http->status = HTTP_STATUS_ERROR;
5305 _cupsSetHTTPError(HTTP_STATUS_ERROR);
ef416fc2 5306
5307 return (-1);
5308 }
5309
5310 gnutls_certificate_allocate_credentials(credentials);
5311
7cf5915e
MS
5312 gnutls_init(&http->tls, GNUTLS_CLIENT);
5313 gnutls_set_default_priority(http->tls);
dcb445bc
MS
5314 gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname,
5315 strlen(hostname));
7cf5915e
MS
5316 gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials);
5317 gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr)http);
5318 gnutls_transport_set_pull_function(http->tls, _httpReadGNUTLS);
5319 gnutls_transport_set_push_function(http->tls, _httpWriteGNUTLS);
ef416fc2 5320
a4845881 5321 while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS)
ef416fc2 5322 {
a4845881
MS
5323 DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)",
5324 status, gnutls_strerror(status)));
ef416fc2 5325
a4845881
MS
5326 if (gnutls_error_is_fatal(status))
5327 {
5328 http->error = EIO;
cb7f98ee 5329 http->status = HTTP_STATUS_ERROR;
85b5d1df 5330
6961465f 5331 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0);
a4845881
MS
5332
5333 gnutls_deinit(http->tls);
5334 gnutls_certificate_free_credentials(*credentials);
5335 free(credentials);
5336 http->tls = NULL;
5337
5338 return (-1);
5339 }
ef416fc2 5340 }
5341
7cf5915e 5342 http->tls_credentials = credentials;
ef416fc2 5343
5344# elif defined(HAVE_CDSASSL)
c1420c87
MS
5345 if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
5346 kSSLStreamType)) == NULL)
e53920b9 5347 {
c1420c87
MS
5348 DEBUG_puts("4http_setup_ssl: SSLCreateContext failed.");
5349 http->error = errno = ENOMEM;
cb7f98ee
MS
5350 http->status = HTTP_STATUS_ERROR;
5351 _cupsSetHTTPError(HTTP_STATUS_ERROR);
e53920b9 5352
89d46774 5353 return (-1);
e53920b9 5354 }
ef416fc2 5355
7cf5915e
MS
5356 error = SSLSetConnection(http->tls, http);
5357 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error));
5358
5359 if (!error)
5360 {
5361 error = SSLSetIOFuncs(http->tls, _httpReadCDSA, _httpWriteCDSA);
5362 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error));
5363 }
5364
7cf5915e
MS
5365 if (!error)
5366 {
c1420c87
MS
5367 error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth,
5368 true);
5369 DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d",
10ddcf65
MS
5370 (int)error));
5371 }
5372
ef416fc2 5373 if (!error)
7cf5915e
MS
5374 {
5375 if (cg->client_cert_cb)
5376 {
5377 error = SSLSetSessionOption(http->tls,
5378 kSSLSessionOptionBreakOnCertRequested, true);
5379 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, "
5380 "error=%d", (int)error));
5381 }
5382 else
5383 {
5384 error = http_set_credentials(http);
5385 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d",
5386 (int)error));
5387 }
5388 }
5389
10ddcf65
MS
5390 /*
5391 * Let the server know which hostname/domain we are trying to connect to
5392 * in case it wants to serve up a certificate with a matching common name.
5393 */
5394
ed486911 5395 if (!error)
7cf5915e 5396 {
dcb445bc 5397 error = SSLSetPeerDomainName(http->tls, hostname, strlen(hostname));
7cf5915e
MS
5398
5399 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d",
5400 (int)error));
5401 }
ed486911 5402
ef416fc2 5403 if (!error)
b423cd4c 5404 {
7cf5915e
MS
5405 int done = 0; /* Are we done yet? */
5406
5407 while (!error && !done)
5408 {
5409 error = SSLHandshake(http->tls);
5410
85dda01c 5411 DEBUG_printf(("4http_setup_ssl: SSLHandshake returned %d.", (int)error));
7cf5915e
MS
5412
5413 switch (error)
5414 {
5415 case noErr :
5416 done = 1;
5417 break;
5418
5419 case errSSLWouldBlock :
82cc1f9a
MS
5420 error = noErr; /* Force a retry */
5421 usleep(1000); /* in 1 millisecond */
7cf5915e
MS
5422 break;
5423
5424 case errSSLServerAuthCompleted :
5425 error = 0;
5426 if (cg->server_cert_cb)
5427 {
5428 error = httpCopyCredentials(http, &credentials);
5429 if (!error)
5430 {
5431 error = (cg->server_cert_cb)(http, http->tls, credentials,
5432 cg->server_cert_data);
5433 httpFreeCredentials(credentials);
5434 }
5435
10ddcf65
MS
5436 DEBUG_printf(("4http_setup_ssl: Server certificate callback "
5437 "returned %d.", (int)error));
7cf5915e
MS
5438 }
5439 break;
5440
5441 case errSSLClientCertRequested :
5442 error = 0;
5443
5444 if (cg->client_cert_cb)
5445 {
5446 names = NULL;
82f97232 5447 if (!(error = SSLCopyDistinguishedNames(http->tls, &dn_array)) &&
7cf5915e
MS
5448 dn_array)
5449 {
5450 if ((names = cupsArrayNew(NULL, NULL)) != NULL)
5451 {
5452 for (i = 0, count = CFArrayGetCount(dn_array); i < count; i++)
5453 {
5454 data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i);
5455
82cc1f9a 5456 if ((credential = malloc(sizeof(*credential))) != NULL)
7cf5915e
MS
5457 {
5458 credential->datalen = CFDataGetLength(data);
5459 if ((credential->data = malloc(credential->datalen)))
5460 {
82f97232 5461 memcpy((void *)credential->data, CFDataGetBytePtr(data),
7cf5915e
MS
5462 credential->datalen);
5463 cupsArrayAdd(names, credential);
5464 }
5a9febac
MS
5465 else
5466 free(credential);
7cf5915e
MS
5467 }
5468 }
5469 }
5470
5471 CFRelease(dn_array);
5472 }
5473
5474 if (!error)
5475 {
82f97232 5476 error = (cg->client_cert_cb)(http, http->tls, names,
7cf5915e
MS
5477 cg->client_cert_data);
5478
85dda01c 5479 DEBUG_printf(("4http_setup_ssl: Client certificate callback "
7cf5915e
MS
5480 "returned %d.", (int)error));
5481 }
5482
5483 httpFreeCredentials(names);
5484 }
5485 break;
5486
5487 case errSSLUnknownRootCert :
5488 message = _("Unable to establish a secure connection to host "
5489 "(untrusted certificate).");
5490 break;
5491
5492 case errSSLNoRootCert :
5493 message = _("Unable to establish a secure connection to host "
5494 "(self-signed certificate).");
5495 break;
5496
5497 case errSSLCertExpired :
5498 message = _("Unable to establish a secure connection to host "
5499 "(expired certificate).");
5500 break;
5501
5502 case errSSLCertNotYetValid :
5503 message = _("Unable to establish a secure connection to host "
5504 "(certificate not yet valid).");
5505 break;
5506
5507 case errSSLHostNameMismatch :
5508 message = _("Unable to establish a secure connection to host "
5509 "(host name mismatch).");
5510 break;
5511
5512 case errSSLXCertChainInvalid :
5513 message = _("Unable to establish a secure connection to host "
5514 "(certificate chain invalid).");
5515 break;
5516
5517 case errSSLConnectionRefused :
5518 message = _("Unable to establish a secure connection to host "
5519 "(peer dropped connection before responding).");
5520 break;
5521
5522 default :
5523 break;
5524 }
5525 }
b423cd4c 5526 }
ef416fc2 5527
89d46774 5528 if (error)
ef416fc2 5529 {
5530 http->error = error;
cb7f98ee 5531 http->status = HTTP_STATUS_ERROR;
7cf5915e
MS
5532 errno = ECONNREFUSED;
5533
c1420c87 5534 CFRelease(http->tls);
7cf5915e 5535 http->tls = NULL;
ef416fc2 5536
7cf5915e
MS
5537 /*
5538 * If an error string wasn't set by the callbacks use a generic one...
5539 */
5540
5541 if (!message)
5542#ifdef HAVE_CSSMERRORSTRING
5543 message = cssmErrorString(error);
5544#else
5545 message = _("Unable to establish a secure connection to host.");
5546#endif /* HAVE_CSSMERRORSTRING */
ef416fc2 5547
cb7f98ee 5548 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
ef416fc2 5549
cc754834
MS
5550 return (-1);
5551 }
7cf5915e 5552
cc754834 5553# elif defined(HAVE_SSPISSL)
7cf5915e 5554 http->tls = _sspiAlloc();
cc754834 5555
7cf5915e 5556 if (!http->tls)
a4845881 5557 {
cb7f98ee 5558 _cupsSetHTTPError(HTTP_STATUS_ERROR);
cc754834 5559 return (-1);
83e08001 5560 }
cc754834 5561
7cf5915e
MS
5562 http->tls->sock = http->fd;
5563 dwSize = sizeof(username) / sizeof(TCHAR);
cc754834
MS
5564 GetUserName(username, &dwSize);
5565 _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR),
5566 sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username);
5567
7cf5915e
MS
5568 if (!_sspiGetCredentials(http->tls_credentials, L"ClientContainer",
5569 commonName, FALSE))
cc754834 5570 {
7cf5915e
MS
5571 _sspiFree(http->tls_credentials);
5572 http->tls_credentials = NULL;
a4845881
MS
5573
5574 http->error = EIO;
cb7f98ee 5575 http->status = HTTP_STATUS_ERROR;
a4845881 5576
e924ce80 5577 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
a4845881
MS
5578 _("Unable to establish a secure connection to host."), 1);
5579
cc754834
MS
5580 return (-1);
5581 }
5582
c1420c87 5583 _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE);
7cf5915e 5584 _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
cc754834 5585
dcb445bc 5586 if (!_sspiConnect(http->tls_credentials, hostname))
cc754834 5587 {
7cf5915e
MS
5588 _sspiFree(http->tls_credentials);
5589 http->tls_credentials = NULL;
a4845881
MS
5590
5591 http->error = EIO;
cb7f98ee 5592 http->status = HTTP_STATUS_ERROR;
a4845881 5593
e924ce80 5594 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI,
a4845881
MS
5595 _("Unable to establish a secure connection to host."), 1);
5596
ef416fc2 5597 return (-1);
5598 }
5599# endif /* HAVE_CDSASSL */
5600
ef416fc2 5601 return (0);
5602}
ef416fc2 5603
5604
ef416fc2 5605/*
5606 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
5607 */
5608
5609static void
e6b1a6a9 5610http_shutdown_ssl(http_t *http) /* I - HTTP connection */
ef416fc2 5611{
5612# ifdef HAVE_LIBSSL
89d46774 5613 SSL_CTX *context; /* Context for encryption */
ef416fc2 5614
a4845881 5615 context = SSL_get_SSL_CTX(http->tls);
ef416fc2 5616
a4845881 5617 SSL_shutdown(http->tls);
ef416fc2 5618 SSL_CTX_free(context);
a4845881 5619 SSL_free(http->tls);
ef416fc2 5620
5621# elif defined(HAVE_GNUTLS)
ef416fc2 5622 gnutls_certificate_client_credentials *credentials;
89d46774 5623 /* TLS credentials */
ef416fc2 5624
7cf5915e 5625 credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials);
ef416fc2 5626
7cf5915e
MS
5627 gnutls_bye(http->tls, GNUTLS_SHUT_RDWR);
5628 gnutls_deinit(http->tls);
ef416fc2 5629 gnutls_certificate_free_credentials(*credentials);
5630 free(credentials);
ef416fc2 5631
5632# elif defined(HAVE_CDSASSL)
7cf5915e 5633 while (SSLClose(http->tls) == errSSLWouldBlock)
b423cd4c 5634 usleep(1000);
5635
c1420c87 5636 CFRelease(http->tls);
89d46774 5637
7cf5915e
MS
5638 if (http->tls_credentials)
5639 CFRelease(http->tls_credentials);
89d46774 5640
cc754834 5641# elif defined(HAVE_SSPISSL)
7cf5915e 5642 _sspiFree(http->tls_credentials);
ef416fc2 5643# endif /* HAVE_LIBSSL */
5644
7cf5915e
MS
5645 http->tls = NULL;
5646 http->tls_credentials = NULL;
ef416fc2 5647}
5648#endif /* HAVE_SSL */
5649
5650
5651#ifdef HAVE_SSL
5652/*
5653 * 'http_upgrade()' - Force upgrade to TLS encryption.
5654 */
5655
89d46774 5656static int /* O - Status of connection */
e6b1a6a9 5657http_upgrade(http_t *http) /* I - HTTP connection */
ef416fc2 5658{
89d46774 5659 int ret; /* Return value */
5660 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 5661
5662
e07d4801 5663 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 5664
85b5d1df
MS
5665 /*
5666 * Flush the connection to make sure any previous "Upgrade" message
5667 * has been read.
5668 */
5669
5670 httpFlush(http);
5671
ef416fc2 5672 /*
5673 * Copy the HTTP data to a local variable so we can do the OPTIONS
5674 * request without interfering with the existing request data...
5675 */
5676
5677 memcpy(&myhttp, http, sizeof(myhttp));
5678
5679 /*
5680 * Send an OPTIONS request to the server, requiring SSL or TLS
5681 * encryption on the link...
5682 */
5683
cb7f98ee 5684 http->tls_upgrade = 1;
f7deaa1a 5685 http->field_authorization = NULL; /* Don't free the auth string */
5686
b86bc4cf 5687 httpClearFields(http);
5688 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
a469f8a5 5689 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
ef416fc2 5690
b86bc4cf 5691 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 5692 {
5693 /*
5694 * Wait for the secure connection...
5695 */
5696
cb7f98ee 5697 while (httpUpdate(http) == HTTP_STATUS_CONTINUE);
ef416fc2 5698 }
5699
ef416fc2 5700 /*
b86bc4cf 5701 * Restore the HTTP request data...
ef416fc2 5702 */
5703
b86bc4cf 5704 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 5705 http->data_encoding = myhttp.data_encoding;
5706 http->data_remaining = myhttp.data_remaining;
5707 http->_data_remaining = myhttp._data_remaining;
5708 http->expect = myhttp.expect;
5709 http->field_authorization = myhttp.field_authorization;
bc44d920 5710 http->digest_tries = myhttp.digest_tries;
cb7f98ee 5711 http->tls_upgrade = 0;
ef416fc2 5712
5713 /*
5714 * See if we actually went secure...
5715 */
5716
5717 if (!http->tls)
5718 {
5719 /*
5720 * Server does not support HTTP upgrade...
5721 */
5722
e07d4801 5723 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 5724
87e98392 5725 httpAddrClose(NULL, http->fd);
ef416fc2 5726
5727 http->fd = -1;
5728
5729 return (-1);
5730 }
5731 else
5732 return (ret);
5733}
5734#endif /* HAVE_SSL */
5735
5736
ef416fc2 5737/*
5738 * 'http_write()' - Write a buffer to a HTTP connection.
5739 */
ef55b745 5740
0fa6c7fa 5741static ssize_t /* O - Number of bytes written */
e6b1a6a9 5742http_write(http_t *http, /* I - HTTP connection */
f11a948a 5743 const char *buffer, /* I - Buffer for data */
0fa6c7fa 5744 size_t length) /* I - Number of bytes to write */
ef416fc2 5745{
0fa6c7fa
MS
5746 ssize_t tbytes, /* Total bytes sent */
5747 bytes; /* Bytes sent */
ef416fc2 5748
5749
0fa6c7fa
MS
5750 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
5751 buffer, CUPS_LLCAST length));
f11a948a
MS
5752 http->error = 0;
5753 tbytes = 0;
ef416fc2 5754
5755 while (length > 0)
5756 {
12f89d24
MS
5757 DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
5758
85dda01c
MS
5759 if (http->timeout_cb)
5760 {
5761#ifdef HAVE_POLL
5762 struct pollfd pfd; /* Polled file descriptor */
5763#else
5764 fd_set output_set; /* Output ready for write? */
5765 struct timeval timeout; /* Timeout value */
5766#endif /* HAVE_POLL */
5767 int nfds; /* Result from select()/poll() */
5768
5769 do
5770 {
5771#ifdef HAVE_POLL
5772 pfd.fd = http->fd;
5773 pfd.events = POLLOUT;
5774
5775 while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
82cc1f9a
MS
5776 (errno == EINTR || errno == EAGAIN))
5777 /* do nothing */;
85dda01c
MS
5778
5779#else
5780 do
5781 {
5782 FD_ZERO(&output_set);
5783 FD_SET(http->fd, &output_set);
5784
5785 timeout.tv_sec = http->wait_value / 1000;
5786 timeout.tv_usec = 1000 * (http->wait_value % 1000);
5787
5788 nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
5789 }
5790# ifdef WIN32
5791 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
5792 WSAGetLastError() == WSAEWOULDBLOCK));
5793# else
5794 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
5795# endif /* WIN32 */
5796#endif /* HAVE_POLL */
5797
5798 if (nfds < 0)
5799 {
5800 http->error = errno;
5801 return (-1);
5802 }
5803 else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
5804 {
5805#ifdef WIN32
83e08001 5806 http->error = WSAEWOULDBLOCK;
85dda01c
MS
5807#else
5808 http->error = EWOULDBLOCK;
5809#endif /* WIN32 */
5810 return (-1);
5811 }
5812 }
5813 while (nfds <= 0);
5814 }
5815
ef416fc2 5816#ifdef HAVE_SSL
5817 if (http->tls)
5818 bytes = http_write_ssl(http, buffer, length);
5819 else
5820#endif /* HAVE_SSL */
5821 bytes = send(http->fd, buffer, length, 0);
5822
0fa6c7fa
MS
5823 DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
5824 CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
12f89d24 5825
ef416fc2 5826 if (bytes < 0)
5827 {
5828#ifdef WIN32
10d09e33 5829 if (WSAGetLastError() == WSAEINTR)
cc754834 5830 continue;
10d09e33
MS
5831 else if (WSAGetLastError() == WSAEWOULDBLOCK)
5832 {
5833 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
5834 continue;
5835
5836 http->error = WSAGetLastError();
5837 }
5838 else if (WSAGetLastError() != http->error &&
5839 WSAGetLastError() != WSAECONNRESET)
ef416fc2 5840 {
5841 http->error = WSAGetLastError();
5842 continue;
5843 }
10d09e33 5844
ef416fc2 5845#else
10d09e33 5846 if (errno == EINTR)
ef416fc2 5847 continue;
10d09e33
MS
5848 else if (errno == EWOULDBLOCK || errno == EAGAIN)
5849 {
5850 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
5851 continue;
5852 else if (!http->timeout_cb && errno == EAGAIN)
5853 continue;
5854
5855 http->error = errno;
5856 }
ef416fc2 5857 else if (errno != http->error && errno != ECONNRESET)
5858 {
5859 http->error = errno;
5860 continue;
5861 }
5862#endif /* WIN32 */
5863
f8b3a85b
MS
5864 DEBUG_printf(("3http_write: error writing data (%s).",
5865 strerror(http->error)));
ef416fc2 5866
5867 return (-1);
5868 }
5869
5870 buffer += bytes;
5871 tbytes += bytes;
5872 length -= bytes;
5873 }
5874
5875#ifdef DEBUG
ae71f5de 5876 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 5877#endif /* DEBUG */
5878
0fa6c7fa 5879 DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
f8b3a85b 5880
ef416fc2 5881 return (tbytes);
5882}
5883
5884
5885/*
5886 * 'http_write_chunk()' - Write a chunked buffer.
5887 */
5888
0fa6c7fa 5889static ssize_t /* O - Number bytes written */
e6b1a6a9 5890http_write_chunk(http_t *http, /* I - HTTP connection */
ef416fc2 5891 const char *buffer, /* I - Buffer to write */
0fa6c7fa 5892 size_t length) /* I - Length of buffer */
ef416fc2 5893{
0fa6c7fa
MS
5894 char header[16]; /* Chunk header */
5895 ssize_t bytes; /* Bytes written */
ef416fc2 5896
f11a948a 5897
0fa6c7fa
MS
5898 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
5899 http, buffer, CUPS_LLCAST length));
ef416fc2 5900
5901 /*
5902 * Write the chunk header, data, and trailer.
5903 */
5904
0fa6c7fa
MS
5905 snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
5906 if (http_write(http, header, strlen(header)) < 0)
ef416fc2 5907 {
0fa6c7fa 5908 DEBUG_puts("8http_write_chunk: http_write of length failed.");
ef416fc2 5909 return (-1);
5910 }
5911
5912 if ((bytes = http_write(http, buffer, length)) < 0)
5913 {
0fa6c7fa 5914 DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
ef416fc2 5915 return (-1);
5916 }
5917
5918 if (http_write(http, "\r\n", 2) < 0)
5919 {
0fa6c7fa 5920 DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
ef416fc2 5921 return (-1);
5922 }
5923
5924 return (bytes);
5925}
5926
5927
5928#ifdef HAVE_SSL
5929/*
5930 * 'http_write_ssl()' - Write to a SSL/TLS connection.
5931 */
5932
5933static int /* O - Bytes written */
e6b1a6a9 5934http_write_ssl(http_t *http, /* I - HTTP connection */
ef416fc2 5935 const char *buf, /* I - Buffer holding data */
5936 int len) /* I - Length of buffer */
5937{
f8b3a85b
MS
5938 ssize_t result; /* Return value */
5939
5940
5941 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
5942
ef416fc2 5943# if defined(HAVE_LIBSSL)
f8b3a85b 5944 result = SSL_write((SSL *)(http->tls), buf, len);
ef416fc2 5945
5946# elif defined(HAVE_GNUTLS)
7cf5915e 5947 result = gnutls_record_send(http->tls, buf, len);
ef55b745
MS
5948
5949 if (result < 0 && !errno)
5950 {
5951 /*
5952 * Convert GNU TLS error to errno value...
5953 */
5954
5955 switch (result)
5956 {
5957 case GNUTLS_E_INTERRUPTED :
5958 errno = EINTR;
5959 break;
5960
5961 case GNUTLS_E_AGAIN :
5962 errno = EAGAIN;
5963 break;
5964
5965 default :
5966 errno = EPIPE;
5967 break;
5968 }
5969
5970 result = -1;
5971 }
5972
ef416fc2 5973# elif defined(HAVE_CDSASSL)
5974 OSStatus error; /* Error info */
5975 size_t processed; /* Number of bytes processed */
5976
5977
7cf5915e 5978 error = SSLWrite(http->tls, buf, len, &processed);
ef416fc2 5979
fa73b229 5980 switch (error)
ef416fc2 5981 {
fa73b229 5982 case 0 :
5983 result = (int)processed;
5984 break;
84315f46 5985
fa73b229 5986 case errSSLWouldBlock :
b423cd4c 5987 if (processed)
5988 result = (int)processed;
5989 else
5990 {
5991 result = -1;
ef55b745 5992 errno = EINTR;
b423cd4c 5993 }
fa73b229 5994 break;
84315f46
MS
5995
5996 case errSSLClosedGraceful :
fa73b229 5997 default :
84315f46
MS
5998 if (processed)
5999 result = (int)processed;
6000 else
6001 {
6002 result = -1;
6003 errno = EPIPE;
6004 }
fa73b229 6005 break;
ef416fc2 6006 }
cc754834 6007# elif defined(HAVE_SSPISSL)
84315f46 6008 return _sspiWrite((_sspi_struct_t *)http->tls, (void *)buf, len);
ef416fc2 6009# endif /* HAVE_LIBSSL */
f8b3a85b
MS
6010
6011 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
6012
6013 return ((int)result);
ef416fc2 6014}
6015#endif /* HAVE_SSL */
6016
6017
6018/*
f2d18633 6019 * End of "$Id$".
ef416fc2 6020 */