]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.5svn-r8950.
[thirdparty/cups.git] / cups / http.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: http.c 7850 2008-08-20 00:07:25Z mike $"
ef416fc2 3 *
4 * HTTP routines for the Common UNIX Printing System (CUPS).
5 *
38e73f87 6 * Copyright 2007-2009 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
f7deaa1a 9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
11 *
ef416fc2 12 * These coded instructions, statements, and computer programs are the
bc44d920 13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
18 * This file is subject to the Apple OS-Developed Software exception.
19 *
20 * Contents:
21 *
411affcf 22 * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP connections.
ecdc0628 23 * httpBlocking() - Set blocking/non-blocking behavior on a connection.
38e73f87
MS
24 * httpCheck() - Check to see if there is a pending response from the
25 * server.
ef416fc2 26 * httpClearCookie() - Clear the cookie value(s).
ecdc0628 27 * httpClearFields() - Clear HTTP request fields.
ef416fc2 28 * httpClose() - Close an HTTP connection...
ef416fc2 29 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
38e73f87 30 * _httpCreate() - Create an unconnected HTTP connection.
ef416fc2 31 * httpDelete() - Send a DELETE request to the server.
32 * httpEncryption() - Set the required encryption on the link.
ecdc0628 33 * httpError() - Get the last error on a connection.
ef416fc2 34 * httpFlush() - Flush data from a HTTP connection.
35 * httpFlushWrite() - Flush data in write buffer.
36 * httpGet() - Send a GET request to the server.
355e94dc 37 * httpGetAuthString() - Get the current authorization string.
ecdc0628 38 * httpGetBlocking() - Get the blocking/non-block state of a connection.
39 * httpGetCookie() - Get any cookie data from the response.
40 * httpGetFd() - Get the file descriptor associated with a
41 * connection.
42 * httpGetField() - Get a field value from a request/response.
ef416fc2 43 * httpGetLength() - Get the amount of data remaining from the
44 * content-length or transfer-encoding fields.
45 * httpGetLength2() - Get the amount of data remaining from the
46 * content-length or transfer-encoding fields.
ecdc0628 47 * httpGetStatus() - Get the status of the last HTTP request.
ef416fc2 48 * httpGetSubField() - Get a sub-field value.
38e73f87 49 * httpGetSubField2() - Get a sub-field value.
ef416fc2 50 * httpGets() - Get a line of text from a HTTP connection.
51 * httpHead() - Send a HEAD request to the server.
52 * httpInitialize() - Initialize the HTTP interface library and set the
53 * default HTTP proxy (if any).
54 * httpOptions() - Send an OPTIONS request to the server.
55 * httpPost() - Send a POST request to the server.
56 * httpPrintf() - Print a formatted string to a HTTP connection.
57 * httpPut() - Send a PUT request to the server.
58 * httpRead() - Read data from a HTTP connection.
a4d04587 59 * httpRead2() - Read data from a HTTP connection.
411affcf 60 * _httpReadCDSA() - Read function for the CDSA library.
61 * _httpReadGNUTLS() - Read function for the GNU TLS library.
38e73f87 62 * httpReconnect() - Reconnect to a HTTP server.
355e94dc 63 * httpSetAuthString() - Set the current authorization string.
ef416fc2 64 * httpSetCookie() - Set the cookie value(s)...
b423cd4c 65 * httpSetExpect() - Set the Expect: header in a request.
ef416fc2 66 * httpSetField() - Set the value of an HTTP header.
38e73f87 67 * httpSetLength() - Set the content-length and content-encoding.
ef416fc2 68 * httpTrace() - Send an TRACE request to the server.
69 * httpUpdate() - Update the current HTTP state for incoming data.
38e73f87 70 * _httpWait() - Wait for data available on a connection (no flush).
ef416fc2 71 * httpWait() - Wait for data available on a connection.
72 * httpWrite() - Write data to a HTTP connection.
a4d04587 73 * httpWrite2() - Write data to a HTTP connection.
411affcf 74 * _httpWriteCDSA() - Write function for the CDSA library.
75 * _httpWriteGNUTLS() - Write function for the GNU TLS library.
76 * http_bio_ctrl() - Control the HTTP connection.
77 * http_bio_free() - Free OpenSSL data.
78 * http_bio_new() - Initialize an OpenSSL BIO structure.
79 * http_bio_puts() - Send a string for OpenSSL.
80 * http_bio_read() - Read data for OpenSSL.
81 * http_bio_write() - Write data for OpenSSL.
ae71f5de 82 * http_debug_hex() - Do a hex dump of a buffer.
ef416fc2 83 * http_field() - Return the field index for a field name.
84 * http_read_ssl() - Read from a SSL/TLS connection.
85 * http_send() - Send a request with all fields and the trailing
86 * blank line.
38e73f87 87 * http_setup_ssl() - Set up SSL/TLS support on a connection.
ef416fc2 88 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
89 * http_upgrade() - Force upgrade to TLS encryption.
38e73f87
MS
90 * http_write() - Write a buffer to a HTTP connection.
91 * http_write_chunk() - Write a chunked buffer.
ef416fc2 92 * http_write_ssl() - Write to a SSL/TLS connection.
93 */
94
95/*
96 * Include necessary headers...
97 */
98
99#include "http-private.h"
100#include "globals.h"
101#include "debug.h"
102#include <stdlib.h>
103#include <fcntl.h>
104#include <errno.h>
105#ifndef WIN32
106# include <signal.h>
107# include <sys/time.h>
108# include <sys/resource.h>
109#endif /* !WIN32 */
f7deaa1a 110#ifdef HAVE_POLL
111# include <sys/poll.h>
112#endif /* HAVE_POLL */
ef416fc2 113
114
115/*
116 * Some operating systems have done away with the Fxxxx constants for
117 * the fcntl() call; this works around that "feature"...
118 */
119
120#ifndef FNONBLK
121# define FNONBLK O_NONBLOCK
122#endif /* !FNONBLK */
123
124
125/*
126 * Local functions...
127 */
128
ae71f5de
MS
129#ifdef DEBUG
130static void http_debug_hex(const char *prefix, const char *buffer,
131 int bytes);
132#endif /* DEBUG */
ef416fc2 133static http_field_t http_field(const char *name);
134static int http_send(http_t *http, http_state_t request,
135 const char *uri);
ef416fc2 136static int http_write(http_t *http, const char *buffer,
137 int length);
138static int http_write_chunk(http_t *http, const char *buffer,
139 int length);
140#ifdef HAVE_SSL
141static int http_read_ssl(http_t *http, char *buf, int len);
142static int http_setup_ssl(http_t *http);
143static void http_shutdown_ssl(http_t *http);
144static int http_upgrade(http_t *http);
145static int http_write_ssl(http_t *http, const char *buf, int len);
146#endif /* HAVE_SSL */
147
148
149/*
150 * Local globals...
151 */
152
153static const char * const http_fields[] =
154 {
155 "Accept-Language",
156 "Accept-Ranges",
157 "Authorization",
158 "Connection",
159 "Content-Encoding",
160 "Content-Language",
161 "Content-Length",
162 "Content-Location",
163 "Content-MD5",
164 "Content-Range",
165 "Content-Type",
166 "Content-Version",
167 "Date",
168 "Host",
169 "If-Modified-Since",
170 "If-Unmodified-since",
171 "Keep-Alive",
172 "Last-Modified",
173 "Link",
174 "Location",
175 "Range",
176 "Referer",
177 "Retry-After",
178 "Transfer-Encoding",
179 "Upgrade",
180 "User-Agent",
181 "WWW-Authenticate"
182 };
f11a948a
MS
183#ifdef DEBUG
184static const char * const http_states[] =
185 {
186 "HTTP_WAITING",
187 "HTTP_OPTIONS",
188 "HTTP_GET",
189 "HTTP_GET_SEND",
190 "HTTP_HEAD",
191 "HTTP_POST",
192 "HTTP_POST_RECV",
193 "HTTP_POST_SEND",
194 "HTTP_PUT",
195 "HTTP_PUT_RECV",
196 "HTTP_DELETE",
197 "HTTP_TRACE",
198 "HTTP_CLOSE",
199 "HTTP_STATUS"
200 };
201#endif /* DEBUG */
ef416fc2 202
203
411affcf 204#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
205/*
206 * BIO methods for OpenSSL...
207 */
208
209static int http_bio_write(BIO *h, const char *buf, int num);
210static int http_bio_read(BIO *h, char *buf, int size);
211static int http_bio_puts(BIO *h, const char *str);
212static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
213static int http_bio_new(BIO *h);
214static int http_bio_free(BIO *data);
215
216static BIO_METHOD http_bio_methods =
217 {
218 BIO_TYPE_SOCKET,
219 "http",
220 http_bio_write,
221 http_bio_read,
222 http_bio_puts,
223 NULL, /* http_bio_gets, */
224 http_bio_ctrl,
225 http_bio_new,
226 http_bio_free,
227 NULL,
228 };
229
230
231/*
232 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
233 */
234
235BIO_METHOD * /* O - BIO methods for OpenSSL */
236_httpBIOMethods(void)
237{
238 return (&http_bio_methods);
239}
240#endif /* HAVE_SSL && HAVE_LIBSSL */
241
242
ecdc0628 243/*
244 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
245 */
246
247void
568fa3fa 248httpBlocking(http_t *http, /* I - Connection to server */
ecdc0628 249 int b) /* I - 1 = blocking, 0 = non-blocking */
250{
251 if (http)
252 http->blocking = b;
253}
254
255
ef416fc2 256/*
257 * 'httpCheck()' - Check to see if there is a pending response from the server.
258 */
259
ecdc0628 260int /* O - 0 = no data, 1 = data available */
568fa3fa 261httpCheck(http_t *http) /* I - Connection to server */
ef416fc2 262{
263 return (httpWait(http, 0));
264}
265
266
267/*
268 * 'httpClearCookie()' - Clear the cookie value(s).
269 *
426c6a59 270 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 271 */
272
273void
568fa3fa 274httpClearCookie(http_t *http) /* I - Connection to server */
ef416fc2 275{
276 if (!http)
277 return;
278
279 if (http->cookie)
280 {
281 free(http->cookie);
282 http->cookie = NULL;
283 }
284}
285
286
ecdc0628 287/*
288 * 'httpClearFields()' - Clear HTTP request fields.
289 */
290
291void
568fa3fa 292httpClearFields(http_t *http) /* I - Connection to server */
ecdc0628 293{
294 if (http)
295 {
296 memset(http->fields, 0, sizeof(http->fields));
07725fee 297 if (http->hostname[0] == '/')
298 httpSetField(http, HTTP_FIELD_HOST, "localhost");
299 else
300 httpSetField(http, HTTP_FIELD_HOST, http->hostname);
b423cd4c 301
f7deaa1a 302 if (http->field_authorization)
303 {
304 free(http->field_authorization);
305 http->field_authorization = NULL;
306 }
307
b423cd4c 308 http->expect = (http_status_t)0;
ecdc0628 309 }
310}
311
312
ef416fc2 313/*
314 * 'httpClose()' - Close an HTTP connection...
315 */
316
317void
568fa3fa 318httpClose(http_t *http) /* I - Connection to server */
ef416fc2 319{
f7deaa1a 320#ifdef HAVE_GSSAPI
1f0275e3 321 OM_uint32 minor_status; /* Minor status code */
f7deaa1a 322#endif /* HAVE_GSSAPI */
323
324
e07d4801 325 DEBUG_printf(("httpClose(http=%p)", http));
ef416fc2 326
327 if (!http)
328 return;
329
330 httpAddrFreeList(http->addrlist);
331
ef416fc2 332 if (http->cookie)
333 free(http->cookie);
334
335#ifdef HAVE_SSL
336 if (http->tls)
337 http_shutdown_ssl(http);
338#endif /* HAVE_SSL */
339
340#ifdef WIN32
341 closesocket(http->fd);
342#else
343 close(http->fd);
344#endif /* WIN32 */
345
f7deaa1a 346#ifdef HAVE_GSSAPI
347 if (http->gssctx != GSS_C_NO_CONTEXT)
1f0275e3 348 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
f7deaa1a 349
350 if (http->gssname != GSS_C_NO_NAME)
1f0275e3 351 gss_release_name(&minor_status, &http->gssname);
f7deaa1a 352#endif /* HAVE_GSSAPI */
353
b94498cf 354#ifdef HAVE_AUTHORIZATION_H
355 if (http->auth_ref)
356 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
357#endif /* HAVE_AUTHORIZATION_H */
358
f7deaa1a 359 httpClearFields(http);
360
361 if (http->authstring && http->authstring != http->_authstring)
362 free(http->authstring);
363
ef416fc2 364 free(http);
365}
366
367
368/*
369 * 'httpConnect()' - Connect to a HTTP server.
1ff0402e
MS
370 *
371 * This function is deprecated - use @link httpConnectEncrypt@ instead.
372 *
373 * @deprecated@
ef416fc2 374 */
375
376http_t * /* O - New HTTP connection */
377httpConnect(const char *host, /* I - Host to connect to */
378 int port) /* I - Port number */
379{
1ff0402e
MS
380 return (httpConnectEncrypt(host, port, HTTP_ENCRYPT_IF_REQUESTED));
381}
382
383
384/*
385 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
386 */
387
388http_t * /* O - New HTTP connection */
389httpConnectEncrypt(
390 const char *host, /* I - Host to connect to */
391 int port, /* I - Port number */
392 http_encryption_t encryption) /* I - Type of encryption to use */
393{
394 http_t *http; /* New HTTP connection */
ef416fc2 395
396
e07d4801 397 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
1ff0402e
MS
398 host, port, encryption));
399
ef416fc2 400 /*
1ff0402e 401 * Create the HTTP structure...
ef416fc2 402 */
403
1ff0402e
MS
404 if ((http = _httpCreate(host, port, encryption)) == NULL)
405 return (NULL);
ef416fc2 406
1ff0402e
MS
407 /*
408 * Connect to the remote system...
409 */
410
411 if (!httpReconnect(http))
412 return (http);
413
414 /*
415 * Could not connect to any known address - bail out!
416 */
417
418 httpAddrFreeList(http->addrlist);
419
420 free(http);
421
422 return (NULL);
ef416fc2 423}
424
425
426/*
1ff0402e 427 * '_httpCreate()' - Create an unconnected HTTP connection.
ef416fc2 428 */
429
1ff0402e
MS
430http_t * /* O - HTTP connection */
431_httpCreate(
432 const char *host, /* I - Hostname */
ef416fc2 433 int port, /* I - Port number */
1ff0402e 434 http_encryption_t encryption) /* I - Encryption to use */
ef416fc2 435{
436 http_t *http; /* New HTTP connection */
437 http_addrlist_t *addrlist; /* Host address data */
438 char service[255]; /* Service name */
439
440
e07d4801 441 DEBUG_printf(("4_httpCreate(host=\"%s\", port=%d, encryption=%d)",
1ff0402e 442 host, port, encryption));
ef416fc2 443
444 if (!host)
445 return (NULL);
446
447 httpInitialize();
448
449 /*
450 * Lookup the host...
451 */
452
453 sprintf(service, "%d", port);
454
455 if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
456 return (NULL);
457
458 /*
459 * Allocate memory for the structure...
460 */
461
91c84a35
MS
462 if ((http = calloc(sizeof(http_t), 1)) == NULL)
463 {
464 httpAddrFreeList(addrlist);
ef416fc2 465 return (NULL);
91c84a35 466 }
ef416fc2 467
1ff0402e
MS
468 /*
469 * Initialize the HTTP data...
470 */
471
ef416fc2 472 http->activity = time(NULL);
1ff0402e
MS
473 http->addrlist = addrlist;
474 http->blocking = 1;
ef416fc2 475 http->fd = -1;
f7deaa1a 476#ifdef HAVE_GSSAPI
1ff0402e
MS
477 http->gssctx = GSS_C_NO_CONTEXT;
478 http->gssname = GSS_C_NO_NAME;
f7deaa1a 479#endif /* HAVE_GSSAPI */
1ff0402e 480 http->version = HTTP_1_1;
f7deaa1a 481
1ff0402e 482 strlcpy(http->hostname, host, sizeof(http->hostname));
ef416fc2 483
484 if (port == 443) /* Always use encryption for https */
485 http->encryption = HTTP_ENCRYPT_ALWAYS;
486 else
487 http->encryption = encryption;
488
489 /*
1ff0402e 490 * Return the new structure...
ef416fc2 491 */
492
1ff0402e 493 return (http);
ef416fc2 494}
495
496
497/*
498 * 'httpDelete()' - Send a DELETE request to the server.
499 */
500
501int /* O - Status of call (0 = success) */
568fa3fa 502httpDelete(http_t *http, /* I - Connection to server */
ef416fc2 503 const char *uri) /* I - URI to delete */
504{
505 return (http_send(http, HTTP_DELETE, uri));
506}
507
508
509/*
510 * 'httpEncryption()' - Set the required encryption on the link.
511 */
512
513int /* O - -1 on error, 0 on success */
568fa3fa 514httpEncryption(http_t *http, /* I - Connection to server */
ef416fc2 515 http_encryption_t e) /* I - New encryption preference */
516{
e07d4801 517 DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
ef416fc2 518
519#ifdef HAVE_SSL
520 if (!http)
521 return (0);
522
523 http->encryption = e;
524
525 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
526 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
527 return (httpReconnect(http));
528 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
529 return (http_upgrade(http));
530 else
531 return (0);
532#else
533 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
534 return (-1);
535 else
536 return (0);
537#endif /* HAVE_SSL */
538}
539
540
ecdc0628 541/*
542 * 'httpError()' - Get the last error on a connection.
543 */
544
545int /* O - Error code (errno) value */
568fa3fa 546httpError(http_t *http) /* I - Connection to server */
ecdc0628 547{
548 if (http)
549 return (http->error);
550 else
551 return (EINVAL);
552}
553
554
ef416fc2 555/*
556 * 'httpFlush()' - Flush data from a HTTP connection.
557 */
558
559void
568fa3fa 560httpFlush(http_t *http) /* I - Connection to server */
ef416fc2 561{
562 char buffer[8192]; /* Junk buffer */
fa73b229 563 int blocking; /* To block or not to block */
ef416fc2 564
565
f11a948a
MS
566 DEBUG_printf(("httpFlush(http=%p), state=%s", http,
567 http_states[http->state]));
ef416fc2 568
fa73b229 569 /*
570 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
571 */
572
573 blocking = http->blocking;
574 http->blocking = 0;
575
576 /*
577 * Read any data we can...
578 */
579
a4d04587 580 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 581
582 /*
583 * Restore blocking and reset the connection if we didn't get all of
584 * the remaining data...
585 */
586
587 http->blocking = blocking;
588
589 if (http->state != HTTP_WAITING && http->fd >= 0)
590 {
591 /*
592 * Didn't get the data back, so close the current connection.
593 */
594
595 http->state = HTTP_WAITING;
596
597#ifdef HAVE_SSL
598 if (http->tls)
599 http_shutdown_ssl(http);
600#endif /* HAVE_SSL */
601
602#ifdef WIN32
603 closesocket(http->fd);
604#else
605 close(http->fd);
606#endif /* WIN32 */
607
608 http->fd = -1;
609 }
ef416fc2 610}
611
612
613/*
614 * 'httpFlushWrite()' - Flush data in write buffer.
615 *
426c6a59 616 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 617 */
618
619int /* O - Bytes written or -1 on error */
568fa3fa 620httpFlushWrite(http_t *http) /* I - Connection to server */
ef416fc2 621{
622 int bytes; /* Bytes written */
623
624
e07d4801 625 DEBUG_printf(("httpFlushWrite(http=%p)", http));
ef416fc2 626
627 if (!http || !http->wused)
628 return (0);
629
630 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
631 bytes = http_write_chunk(http, http->wbuffer, http->wused);
632 else
633 bytes = http_write(http, http->wbuffer, http->wused);
634
635 http->wused = 0;
636
637 return (bytes);
638}
639
640
641/*
642 * 'httpGet()' - Send a GET request to the server.
643 */
644
645int /* O - Status of call (0 = success) */
568fa3fa 646httpGet(http_t *http, /* I - Connection to server */
ef416fc2 647 const char *uri) /* I - URI to get */
648{
649 return (http_send(http, HTTP_GET, uri));
650}
651
652
355e94dc
MS
653/*
654 * 'httpGetAuthString()' - Get the current authorization string.
655 *
656 * The authorization string is set by cupsDoAuthentication() and
657 * httpSetAuthString(). Use httpGetAuthString() to retrieve the
658 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
659 * value.
660 *
426c6a59 661 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
662 */
663
664char * /* O - Authorization string */
568fa3fa 665httpGetAuthString(http_t *http) /* I - Connection to server */
355e94dc
MS
666{
667 if (http)
668 return (http->authstring);
669 else
670 return (NULL);
671}
672
673
ecdc0628 674/*
675 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
676 *
426c6a59 677 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 678 */
679
680int /* O - 1 if blocking, 0 if non-blocking */
568fa3fa 681httpGetBlocking(http_t *http) /* I - Connection to server */
ecdc0628 682{
683 return (http ? http->blocking : 0);
684}
685
686
687/*
688 * 'httpGetCookie()' - Get any cookie data from the response.
757d2cad 689 *
426c6a59 690 * @since CUPS 1.1.19/Mac OS X 10.3@
ecdc0628 691 */
692
693const char * /* O - Cookie data or NULL */
694httpGetCookie(http_t *http) /* I - HTTP connecion */
695{
696 return (http ? http->cookie : NULL);
697}
698
699
700/*
701 * 'httpGetFd()' - Get the file descriptor associated with a connection.
702 *
426c6a59 703 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 704 */
705
706int /* O - File descriptor or -1 if none */
568fa3fa 707httpGetFd(http_t *http) /* I - Connection to server */
ecdc0628 708{
709 return (http ? http->fd : -1);
710}
711
712
713/*
714 * 'httpGetField()' - Get a field value from a request/response.
715 */
716
717const char * /* O - Field value */
568fa3fa 718httpGetField(http_t *http, /* I - Connection to server */
ecdc0628 719 http_field_t field) /* I - Field to get */
720{
721 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
722 return (NULL);
ef55b745 723 else if (field == HTTP_FIELD_AUTHORIZATION &&
f7deaa1a 724 http->field_authorization)
725 {
726 /*
727 * Special case for WWW-Authenticate: as its contents can be
728 * longer than HTTP_MAX_VALUE...
729 */
730
731 return (http->field_authorization);
732 }
ecdc0628 733 else
734 return (http->fields[field]);
735}
736
737
738/*
739 * 'httpGetLength()' - Get the amount of data remaining from the
740 * content-length or transfer-encoding fields.
741 *
742 * This function is deprecated and will not return lengths larger than
743 * 2^31 - 1; use httpGetLength2() instead.
744 *
745 * @deprecated@
746 */
747
748int /* O - Content length */
568fa3fa 749httpGetLength(http_t *http) /* I - Connection to server */
ecdc0628 750{
751 /*
752 * Get the read content length and return the 32-bit value.
753 */
754
755 if (http)
756 {
757 httpGetLength2(http);
758
759 return (http->_data_remaining);
760 }
761 else
762 return (-1);
763}
764
765
766/*
767 * 'httpGetLength2()' - Get the amount of data remaining from the
768 * content-length or transfer-encoding fields.
769 *
770 * This function returns the complete content length, even for
771 * content larger than 2^31 - 1.
772 *
426c6a59 773 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 774 */
775
776off_t /* O - Content length */
568fa3fa 777httpGetLength2(http_t *http) /* I - Connection to server */
ecdc0628 778{
f11a948a
MS
779 DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
780 http_states[http->state]));
ecdc0628 781
782 if (!http)
783 return (-1);
784
785 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
786 {
e07d4801 787 DEBUG_puts("4httpGetLength2: chunked request!");
ecdc0628 788
789 http->data_encoding = HTTP_ENCODE_CHUNKED;
790 http->data_remaining = 0;
791 }
792 else
793 {
794 http->data_encoding = HTTP_ENCODE_LENGTH;
795
796 /*
797 * The following is a hack for HTTP servers that don't send a
798 * content-length or transfer-encoding field...
799 *
800 * If there is no content-length then the connection must close
801 * after the transfer is complete...
802 */
803
b86bc4cf 804 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
805 {
806 /*
807 * Default content length is 0 for errors and 2^31-1 for other
808 * successful requests...
809 */
810
811 if (http->status >= HTTP_MULTIPLE_CHOICES)
812 http->data_remaining = 0;
813 else
814 http->data_remaining = 2147483647;
815 }
ecdc0628 816 else
817 http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
818 NULL, 10);
819
e07d4801 820 DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
ecdc0628 821 CUPS_LLCAST http->data_remaining));
822 }
823
824 if (http->data_remaining <= INT_MAX)
825 http->_data_remaining = (int)http->data_remaining;
826 else
827 http->_data_remaining = INT_MAX;
828
829 return (http->data_remaining);
830}
831
832
833/*
834 * 'httpGetStatus()' - Get the status of the last HTTP request.
835 *
426c6a59 836 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 837 */
838
839http_status_t /* O - HTTP status */
568fa3fa 840httpGetStatus(http_t *http) /* I - Connection to server */
ecdc0628 841{
842 return (http ? http->status : HTTP_ERROR);
843}
844
845
ef416fc2 846/*
847 * 'httpGetSubField()' - Get a sub-field value.
848 *
849 * @deprecated@
850 */
851
852char * /* O - Value or NULL */
568fa3fa 853httpGetSubField(http_t *http, /* I - Connection to server */
ef416fc2 854 http_field_t field, /* I - Field index */
855 const char *name, /* I - Name of sub-field */
856 char *value) /* O - Value string */
857{
858 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
859}
860
861
862/*
863 * 'httpGetSubField2()' - Get a sub-field value.
864 *
426c6a59 865 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 866 */
867
868char * /* O - Value or NULL */
568fa3fa 869httpGetSubField2(http_t *http, /* I - Connection to server */
ef416fc2 870 http_field_t field, /* I - Field index */
871 const char *name, /* I - Name of sub-field */
872 char *value, /* O - Value string */
873 int valuelen) /* I - Size of value buffer */
874{
875 const char *fptr; /* Pointer into field */
876 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
877 *ptr, /* Pointer into string buffer */
878 *end; /* End of value buffer */
879
e07d4801
MS
880 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
881 "valuelen=%d)", http, field, name, value, valuelen));
ef416fc2 882
883 if (!http || !name || !value || valuelen < 2 ||
ecdc0628 884 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
ef416fc2 885 return (NULL);
886
887 end = value + valuelen - 1;
888
889 for (fptr = http->fields[field]; *fptr;)
890 {
891 /*
892 * Skip leading whitespace...
893 */
894
895 while (isspace(*fptr & 255))
896 fptr ++;
897
898 if (*fptr == ',')
899 {
900 fptr ++;
901 continue;
902 }
903
904 /*
905 * Get the sub-field name...
906 */
907
908 for (ptr = temp;
909 *fptr && *fptr != '=' && !isspace(*fptr & 255) &&
910 ptr < (temp + sizeof(temp) - 1);
911 *ptr++ = *fptr++);
912
913 *ptr = '\0';
914
e07d4801 915 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
ef416fc2 916
917 /*
918 * Skip trailing chars up to the '='...
919 */
920
921 while (isspace(*fptr & 255))
922 fptr ++;
923
924 if (!*fptr)
925 break;
926
927 if (*fptr != '=')
928 continue;
929
930 /*
931 * Skip = and leading whitespace...
932 */
933
934 fptr ++;
935
936 while (isspace(*fptr & 255))
937 fptr ++;
938
939 if (*fptr == '\"')
940 {
941 /*
942 * Read quoted string...
943 */
944
945 for (ptr = value, fptr ++;
946 *fptr && *fptr != '\"' && ptr < end;
947 *ptr++ = *fptr++);
948
949 *ptr = '\0';
950
951 while (*fptr && *fptr != '\"')
952 fptr ++;
953
954 if (*fptr)
955 fptr ++;
956 }
957 else
958 {
959 /*
960 * Read unquoted string...
961 */
962
963 for (ptr = value;
964 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < end;
965 *ptr++ = *fptr++);
966
967 *ptr = '\0';
968
969 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
970 fptr ++;
971 }
972
e07d4801 973 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
ef416fc2 974
975 /*
976 * See if this is the one...
977 */
978
979 if (!strcmp(name, temp))
e07d4801
MS
980 {
981 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
ef416fc2 982 return (value);
e07d4801 983 }
ef416fc2 984 }
985
986 value[0] = '\0';
987
e07d4801
MS
988 DEBUG_puts("3httpGetSubField2: Returning NULL");
989
ef416fc2 990 return (NULL);
991}
992
993
ef416fc2 994/*
995 * 'httpGets()' - Get a line of text from a HTTP connection.
996 */
997
998char * /* O - Line or NULL */
999httpGets(char *line, /* I - Line to read into */
1000 int length, /* I - Max length of buffer */
568fa3fa 1001 http_t *http) /* I - Connection to server */
ef416fc2 1002{
1003 char *lineptr, /* Pointer into line */
1004 *lineend, /* End of line */
1005 *bufptr, /* Pointer into input buffer */
1006 *bufend; /* Pointer to end of buffer */
1007 int bytes, /* Number of bytes read */
1008 eol; /* End-of-line? */
1009
1010
e07d4801 1011 DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
ef416fc2 1012
1013 if (http == NULL || line == NULL)
1014 return (NULL);
1015
1016 /*
1017 * Read a line from the buffer...
1018 */
f11a948a
MS
1019
1020 http->error = 0;
1021 lineptr = line;
1022 lineend = line + length - 1;
1023 eol = 0;
ef416fc2 1024
1025 while (lineptr < lineend)
1026 {
1027 /*
1028 * Pre-load the buffer as needed...
1029 */
1030
1031#ifdef WIN32
1032 WSASetLastError(0);
1033#else
1034 errno = 0;
1035#endif /* WIN32 */
1036
1037 while (http->used == 0)
1038 {
1039 /*
1040 * No newline; see if there is more data to be read...
1041 */
1042
38e73f87 1043 if (!http->blocking && !_httpWait(http, 10000, 1))
89d46774 1044 {
e07d4801 1045 DEBUG_puts("3httpGets: Timed out!");
b86bc4cf 1046#ifdef WIN32
1047 http->error = WSAETIMEDOUT;
1048#else
89d46774 1049 http->error = ETIMEDOUT;
b86bc4cf 1050#endif /* WIN32 */
ef416fc2 1051 return (NULL);
89d46774 1052 }
ef416fc2 1053
1054#ifdef HAVE_SSL
1055 if (http->tls)
1056 bytes = http_read_ssl(http, http->buffer + http->used,
1057 HTTP_MAX_BUFFER - http->used);
1058 else
1059#endif /* HAVE_SSL */
1060 bytes = recv(http->fd, http->buffer + http->used,
1061 HTTP_MAX_BUFFER - http->used, 0);
1062
e07d4801 1063 DEBUG_printf(("4httpGets: read %d bytes...", bytes));
ef416fc2 1064
1065 if (bytes < 0)
1066 {
1067 /*
1068 * Nope, can't get a line this time...
1069 */
1070
1071#ifdef WIN32
1072 if (WSAGetLastError() != http->error)
1073 {
1074 http->error = WSAGetLastError();
1075 continue;
1076 }
1077
e07d4801 1078 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
ef416fc2 1079#else
e07d4801 1080 DEBUG_printf(("3httpGets: recv() error %d!", errno));
ef416fc2 1081
e07d4801 1082 if (errno == EINTR || errno == EAGAIN)
ef416fc2 1083 continue;
1084 else if (errno != http->error)
1085 {
1086 http->error = errno;
1087 continue;
1088 }
1089#endif /* WIN32 */
1090
1091 return (NULL);
1092 }
1093 else if (bytes == 0)
1094 {
1095 http->error = EPIPE;
1096
1097 return (NULL);
1098 }
1099
1100 /*
1101 * Yup, update the amount used...
1102 */
1103
1104 http->used += bytes;
1105 }
1106
1107 /*
1108 * Now copy as much of the current line as possible...
1109 */
1110
1111 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1112 lineptr < lineend && bufptr < bufend;)
1113 {
1114 if (*bufptr == 0x0a)
1115 {
1116 eol = 1;
1117 bufptr ++;
1118 break;
1119 }
1120 else if (*bufptr == 0x0d)
1121 bufptr ++;
1122 else
1123 *lineptr++ = *bufptr++;
1124 }
1125
b86bc4cf 1126 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1127 if (http->used > 0)
1128 memmove(http->buffer, bufptr, http->used);
1129
1130 if (eol)
1131 {
1132 /*
1133 * End of line...
1134 */
1135
1136 http->activity = time(NULL);
1137
1138 *lineptr = '\0';
ef55b745 1139
e07d4801 1140 DEBUG_printf(("3httpGets: Returning \"%s\"", line));
ef416fc2 1141
1142 return (line);
1143 }
1144 }
1145
e07d4801 1146 DEBUG_puts("3httpGets: No new line available!");
ef416fc2 1147
1148 return (NULL);
1149}
1150
1151
1152/*
1153 * 'httpHead()' - Send a HEAD request to the server.
1154 */
1155
1156int /* O - Status of call (0 = success) */
568fa3fa 1157httpHead(http_t *http, /* I - Connection to server */
ef416fc2 1158 const char *uri) /* I - URI for head */
1159{
e07d4801 1160 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1161 return (http_send(http, HTTP_HEAD, uri));
1162}
1163
1164
1165/*
1166 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1167 * default HTTP proxy (if any).
1168 */
1169
1170void
1171httpInitialize(void)
1172{
1173#ifdef HAVE_LIBSSL
1174# ifndef WIN32
1175 struct timeval curtime; /* Current time in microseconds */
1176# endif /* !WIN32 */
1177 int i; /* Looping var */
1178 unsigned char data[1024]; /* Seed data */
1179#endif /* HAVE_LIBSSL */
1180
1181#ifdef WIN32
1182 WSADATA winsockdata; /* WinSock data */
1183 static int initialized = 0; /* Has WinSock been initialized? */
1184
1185
1186 if (!initialized)
1187 WSAStartup(MAKEWORD(1,1), &winsockdata);
fa73b229 1188#elif !defined(SO_NOSIGPIPE)
ef416fc2 1189 /*
1190 * Ignore SIGPIPE signals...
1191 */
1192
fa73b229 1193# ifdef HAVE_SIGSET
1194 sigset(SIGPIPE, SIG_IGN);
1195# elif defined(HAVE_SIGACTION)
1196 struct sigaction action; /* POSIX sigaction data */
1197
1198
ef416fc2 1199 memset(&action, 0, sizeof(action));
1200 action.sa_handler = SIG_IGN;
1201 sigaction(SIGPIPE, &action, NULL);
fa73b229 1202# else
ef416fc2 1203 signal(SIGPIPE, SIG_IGN);
fa73b229 1204# endif /* !SO_NOSIGPIPE */
ef416fc2 1205#endif /* WIN32 */
1206
1207#ifdef HAVE_GNUTLS
1208 gnutls_global_init();
1209#endif /* HAVE_GNUTLS */
1210
1211#ifdef HAVE_LIBSSL
1212 SSL_load_error_strings();
1213 SSL_library_init();
1214
1215 /*
1216 * Using the current time is a dubious random seed, but on some systems
1217 * it is the best we can do (on others, this seed isn't even used...)
1218 */
1219
dfd5680b
MS
1220# ifdef WIN32
1221# else
ef416fc2 1222 gettimeofday(&curtime, NULL);
1223 srand(curtime.tv_sec + curtime.tv_usec);
dfd5680b 1224# endif /* WIN32 */
ef416fc2 1225
1226 for (i = 0; i < sizeof(data); i ++)
dfd5680b 1227 data[i] = rand();
ef416fc2 1228
dfd5680b 1229 RAND_seed(data, sizeof(data));
ef416fc2 1230#endif /* HAVE_LIBSSL */
1231}
1232
1233
1234/*
1235 * 'httpOptions()' - Send an OPTIONS request to the server.
1236 */
1237
1238int /* O - Status of call (0 = success) */
568fa3fa 1239httpOptions(http_t *http, /* I - Connection to server */
ef416fc2 1240 const char *uri) /* I - URI for options */
1241{
1242 return (http_send(http, HTTP_OPTIONS, uri));
1243}
1244
1245
1246/*
1247 * 'httpPost()' - Send a POST request to the server.
1248 */
1249
1250int /* O - Status of call (0 = success) */
568fa3fa 1251httpPost(http_t *http, /* I - Connection to server */
ef416fc2 1252 const char *uri) /* I - URI for post */
1253{
1254 return (http_send(http, HTTP_POST, uri));
1255}
1256
1257
1258/*
1259 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 1260 *
1261 * @private@
ef416fc2 1262 */
1263
1264int /* O - Number of bytes written */
568fa3fa 1265httpPrintf(http_t *http, /* I - Connection to server */
ef416fc2 1266 const char *format, /* I - printf-style format string */
1267 ...) /* I - Additional args as needed */
1268{
1269 int bytes; /* Number of bytes to write */
1270 char buf[16384]; /* Buffer for formatted string */
1271 va_list ap; /* Variable argument pointer */
1272
1273
e07d4801 1274 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
ef416fc2 1275
1276 va_start(ap, format);
1277 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1278 va_end(ap);
1279
e07d4801 1280 DEBUG_printf(("3httpPrintf: %s", buf));
ef416fc2 1281
d09495fa 1282 if (http->data_encoding == HTTP_ENCODE_FIELDS)
1283 return (httpWrite2(http, buf, bytes));
1284 else
ef416fc2 1285 {
d09495fa 1286 if (http->wused)
1287 {
e07d4801 1288 DEBUG_puts("4httpPrintf: flushing existing data...");
ef416fc2 1289
d09495fa 1290 if (httpFlushWrite(http) < 0)
1291 return (-1);
1292 }
ef416fc2 1293
d09495fa 1294 return (http_write(http, buf, bytes));
1295 }
ef416fc2 1296}
1297
1298
1299/*
1300 * 'httpPut()' - Send a PUT request to the server.
1301 */
1302
1303int /* O - Status of call (0 = success) */
568fa3fa 1304httpPut(http_t *http, /* I - Connection to server */
ef416fc2 1305 const char *uri) /* I - URI to put */
1306{
e07d4801 1307 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1308 return (http_send(http, HTTP_PUT, uri));
1309}
1310
1311
1312/*
1313 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 1314 *
1315 * This function is deprecated. Use the httpRead2() function which can
1316 * read more than 2GB of data.
1317 *
1318 * @deprecated@
ef416fc2 1319 */
1320
1321int /* O - Number of bytes read */
568fa3fa 1322httpRead(http_t *http, /* I - Connection to server */
ef416fc2 1323 char *buffer, /* I - Buffer for data */
1324 int length) /* I - Maximum number of bytes */
1325{
a4d04587 1326 return ((int)httpRead2(http, buffer, length));
1327}
1328
1329
1330/*
1331 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 1332 *
426c6a59 1333 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 1334 */
1335
1336ssize_t /* O - Number of bytes read */
568fa3fa 1337httpRead2(http_t *http, /* I - Connection to server */
a4d04587 1338 char *buffer, /* I - Buffer for data */
1339 size_t length) /* I - Maximum number of bytes */
1340{
1341 ssize_t bytes; /* Bytes read */
ef416fc2 1342 char len[32]; /* Length string */
1343
1344
e07d4801 1345 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
a603edef 1346 http, buffer, CUPS_LLCAST length));
ef416fc2 1347
1348 if (http == NULL || buffer == NULL)
1349 return (-1);
1350
1351 http->activity = time(NULL);
f11a948a 1352 http->error = 0;
ef416fc2 1353
1354 if (length <= 0)
1355 return (0);
1356
1357 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1358 http->data_remaining <= 0)
1359 {
e07d4801 1360 DEBUG_puts("2httpRead2: Getting chunk length...");
ef416fc2 1361
1362 if (httpGets(len, sizeof(len), http) == NULL)
1363 {
e07d4801 1364 DEBUG_puts("1httpRead2: Could not get length!");
ef416fc2 1365 return (0);
1366 }
1367
1368 http->data_remaining = strtoll(len, NULL, 16);
1369 if (http->data_remaining < 0)
1370 {
e07d4801 1371 DEBUG_puts("1httpRead2: Negative chunk length!");
ef416fc2 1372 return (0);
1373 }
1374 }
1375
e07d4801 1376 DEBUG_printf(("2httpRead2: data_remaining=" CUPS_LLFMT,
ef416fc2 1377 CUPS_LLCAST http->data_remaining));
1378
1379 if (http->data_remaining <= 0)
1380 {
1381 /*
1382 * A zero-length chunk ends a transfer; unless we are reading POST
1383 * data, go idle...
1384 */
1385
1386 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1387 httpGets(len, sizeof(len), http);
1388
1389 if (http->state == HTTP_POST_RECV)
1390 http->state ++;
1391 else
1392 http->state = HTTP_WAITING;
1393
1394 /*
1395 * Prevent future reads for this request...
1396 */
1397
1398 http->data_encoding = HTTP_ENCODE_LENGTH;
1399
1400 return (0);
1401 }
b86bc4cf 1402 else if (length > (size_t)http->data_remaining)
1403 length = (size_t)http->data_remaining;
ef416fc2 1404
1405 if (http->used == 0 && length <= 256)
1406 {
1407 /*
1408 * Buffer small reads for better performance...
1409 */
1410
ed486911 1411 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1412 return (0);
1413
1414 if (http->data_remaining > sizeof(http->buffer))
1415 bytes = sizeof(http->buffer);
1416 else
1417 bytes = http->data_remaining;
1418
1419#ifdef HAVE_SSL
1420 if (http->tls)
1421 bytes = http_read_ssl(http, http->buffer, bytes);
1422 else
1423#endif /* HAVE_SSL */
1424 {
e07d4801 1425 DEBUG_printf(("2httpRead2: reading %d bytes from socket into buffer...",
a603edef 1426 (int)bytes));
ef416fc2 1427
1428 bytes = recv(http->fd, http->buffer, bytes, 0);
1429
e07d4801 1430 DEBUG_printf(("2httpRead2: read %d bytes from socket into buffer...",
a603edef 1431 (int)bytes));
ef416fc2 1432 }
1433
1434 if (bytes > 0)
1435 http->used = bytes;
1436 else if (bytes < 0)
1437 {
1438#ifdef WIN32
1439 http->error = WSAGetLastError();
1440 return (-1);
1441#else
e07d4801 1442 if (errno != EINTR && errno != EAGAIN)
ef416fc2 1443 {
1444 http->error = errno;
1445 return (-1);
1446 }
1447#endif /* WIN32 */
1448 }
1449 else
1450 {
1451 http->error = EPIPE;
1452 return (0);
1453 }
1454 }
1455
1456 if (http->used > 0)
1457 {
b86bc4cf 1458 if (length > (size_t)http->used)
1459 length = (size_t)http->used;
ef416fc2 1460
b86bc4cf 1461 bytes = (ssize_t)length;
ef416fc2 1462
e07d4801 1463 DEBUG_printf(("2httpRead2: grabbing %d bytes from input buffer...",
a603edef 1464 (int)bytes));
ef416fc2 1465
1466 memcpy(buffer, http->buffer, length);
b86bc4cf 1467 http->used -= (int)length;
ef416fc2 1468
1469 if (http->used > 0)
1470 memmove(http->buffer, http->buffer + length, http->used);
1471 }
1472#ifdef HAVE_SSL
1473 else if (http->tls)
1474 {
ed486911 1475 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1476 return (0);
1477
b86bc4cf 1478 bytes = (ssize_t)http_read_ssl(http, buffer, (int)length);
ef416fc2 1479 }
1480#endif /* HAVE_SSL */
1481 else
1482 {
ed486911 1483 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1484 return (0);
1485
e07d4801 1486 DEBUG_printf(("2httpRead2: reading " CUPS_LLFMT " bytes from socket...",
a603edef 1487 CUPS_LLCAST length));
ef416fc2 1488
b86bc4cf 1489#ifdef WIN32
1490 bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0);
1491#else
ef416fc2 1492 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
d1c13e16 1493 if (errno != EINTR && errno != EAGAIN)
ef416fc2 1494 break;
b86bc4cf 1495#endif /* WIN32 */
ef416fc2 1496
e07d4801 1497 DEBUG_printf(("2httpRead2: read " CUPS_LLFMT " bytes from socket...",
a603edef 1498 CUPS_LLCAST bytes));
ef416fc2 1499 }
1500
1501 if (bytes > 0)
1502 {
1503 http->data_remaining -= bytes;
1504
1505 if (http->data_remaining <= INT_MAX)
1506 http->_data_remaining = (int)http->data_remaining;
1507 else
1508 http->_data_remaining = INT_MAX;
1509 }
1510 else if (bytes < 0)
1511 {
1512#ifdef WIN32
1513 http->error = WSAGetLastError();
1514#else
d1c13e16 1515 if (errno == EINTR || errno == EAGAIN)
ef416fc2 1516 bytes = 0;
1517 else
1518 http->error = errno;
1519#endif /* WIN32 */
1520 }
1521 else
1522 {
1523 http->error = EPIPE;
1524 return (0);
1525 }
1526
1527 if (http->data_remaining == 0)
1528 {
1529 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1530 httpGets(len, sizeof(len), http);
1531
1532 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1533 {
1534 if (http->state == HTTP_POST_RECV)
1535 http->state ++;
1536 else
1537 http->state = HTTP_WAITING;
1538 }
1539 }
1540
1541#ifdef DEBUG
ae71f5de 1542 http_debug_hex("httpRead2", buffer, (int)bytes);
ef416fc2 1543#endif /* DEBUG */
1544
1545 return (bytes);
1546}
1547
1548
1549#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1550/*
411affcf 1551 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 1552 */
1553
1554OSStatus /* O - -1 on error, 0 on success */
1555_httpReadCDSA(
1556 SSLConnectionRef connection, /* I - SSL/TLS connection */
1557 void *data, /* I - Data buffer */
1558 size_t *dataLength) /* IO - Number of bytes */
1559{
411affcf 1560 OSStatus result; /* Return value */
1561 ssize_t bytes; /* Number of bytes read */
1562 http_t *http; /* HTTP connection */
1563
1564
1565 http = (http_t *)connection;
e53920b9 1566
411affcf 1567 if (!http->blocking)
1568 {
1569 /*
1570 * Make sure we have data before we read...
1571 */
e53920b9 1572
38e73f87 1573 if (!_httpWait(http, 10000, 0))
411affcf 1574 {
1575 http->error = ETIMEDOUT;
1576 return (-1);
1577 }
1578 }
ef416fc2 1579
b423cd4c 1580 do
411affcf 1581 {
1582 bytes = recv(http->fd, data, *dataLength, 0);
1583 }
e07d4801 1584 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 1585
b423cd4c 1586 if (bytes == *dataLength)
411affcf 1587 {
b423cd4c 1588 result = 0;
411affcf 1589 }
b423cd4c 1590 else if (bytes > 0)
1591 {
1592 *dataLength = bytes;
1593 result = errSSLWouldBlock;
1594 }
1595 else
1596 {
1597 *dataLength = 0;
fa73b229 1598
1599 if (bytes == 0)
ed486911 1600 result = errSSLClosedGraceful;
b423cd4c 1601 else if (errno == EAGAIN)
1602 result = errSSLWouldBlock;
b423cd4c 1603 else
ed486911 1604 result = errSSLClosedAbort;
ef416fc2 1605 }
b423cd4c 1606
411affcf 1607 return (result);
ef416fc2 1608}
1609#endif /* HAVE_SSL && HAVE_CDSASSL */
1610
1611
411affcf 1612#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
1613/*
1614 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
1615 */
1616
1617ssize_t /* O - Number of bytes read or -1 on error */
1618_httpReadGNUTLS(
568fa3fa 1619 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 1620 void *data, /* I - Buffer */
1621 size_t length) /* I - Number of bytes to read */
1622{
1623 http_t *http; /* HTTP connection */
1624
1625
1626 http = (http_t *)ptr;
1627
1628 if (!http->blocking)
1629 {
1630 /*
1631 * Make sure we have data before we read...
1632 */
1633
38e73f87 1634 if (!_httpWait(http, 10000, 0))
411affcf 1635 {
1636 http->error = ETIMEDOUT;
1637 return (-1);
1638 }
1639 }
1640
1641 return (recv(http->fd, data, length, 0));
1642}
1643#endif /* HAVE_SSL && HAVE_GNUTLS */
1644
1645
ef416fc2 1646/*
ecdc0628 1647 * 'httpReconnect()' - Reconnect to a HTTP server.
ef416fc2 1648 */
1649
1650int /* O - 0 on success, non-zero on failure */
568fa3fa 1651httpReconnect(http_t *http) /* I - Connection to server */
ef416fc2 1652{
1653 http_addrlist_t *addr; /* Connected address */
1ff0402e
MS
1654#ifdef DEBUG
1655 http_addrlist_t *current; /* Current address */
1656 char temp[256]; /* Temporary address string */
1657#endif /* DEBUG */
ef416fc2 1658
1659
e07d4801 1660 DEBUG_printf(("httpReconnect(http=%p)", http));
ef416fc2 1661
1662 if (!http)
1663 return (-1);
1664
1665#ifdef HAVE_SSL
1666 if (http->tls)
1ff0402e 1667 {
e07d4801 1668 DEBUG_puts("2httpReconnect: Shutting down SSL/TLS...");
ef416fc2 1669 http_shutdown_ssl(http);
1ff0402e 1670 }
ef416fc2 1671#endif /* HAVE_SSL */
1672
1673 /*
1674 * Close any previously open socket...
1675 */
1676
1677 if (http->fd >= 0)
bd7854cb 1678 {
e07d4801 1679 DEBUG_printf(("2httpReconnect: Closing socket %d...", http->fd));
1ff0402e 1680
ef416fc2 1681#ifdef WIN32
1682 closesocket(http->fd);
1683#else
1684 close(http->fd);
1685#endif /* WIN32 */
1686
bd7854cb 1687 http->fd = -1;
1688 }
1689
ef416fc2 1690 /*
1691 * Connect to the server...
1692 */
1693
1ff0402e
MS
1694#ifdef DEBUG
1695 for (current = http->addrlist; current; current = current->next)
e07d4801 1696 DEBUG_printf(("2httpReconnect: Address %s:%d",
1ff0402e
MS
1697 httpAddrString(&(current->addr), temp, sizeof(temp)),
1698 _httpAddrPort(&(current->addr))));
1699#endif /* DEBUG */
1700
ef416fc2 1701 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
1702 {
1703 /*
1704 * Unable to connect...
1705 */
1706
1707#ifdef WIN32
1708 http->error = WSAGetLastError();
1709#else
1710 http->error = errno;
1711#endif /* WIN32 */
1712 http->status = HTTP_ERROR;
1713
e07d4801 1714 DEBUG_printf(("1httpReconnect: httpAddrConnect failed: %s",
1ff0402e
MS
1715 strerror(http->error)));
1716
ef416fc2 1717 return (-1);
1718 }
1719
e07d4801 1720 DEBUG_printf(("2httpReconnect: New socket=%d", http->fd));
1ff0402e 1721
ef416fc2 1722 http->hostaddr = &(addr->addr);
1723 http->error = 0;
1724 http->status = HTTP_CONTINUE;
1725
1726#ifdef HAVE_SSL
1727 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1728 {
1729 /*
1730 * Always do encryption via SSL.
1731 */
1732
1733 if (http_setup_ssl(http) != 0)
1734 {
f7deaa1a 1735# ifdef WIN32
ef416fc2 1736 closesocket(http->fd);
f7deaa1a 1737# else
ef416fc2 1738 close(http->fd);
f7deaa1a 1739# endif /* WIN32 */
ef416fc2 1740
1741 return (-1);
1742 }
1743 }
1744 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1745 return (http_upgrade(http));
1746#endif /* HAVE_SSL */
1747
e07d4801 1748 DEBUG_printf(("1httpReconnect: Connected to %s:%d...",
1ff0402e
MS
1749 httpAddrString(http->hostaddr, temp, sizeof(temp)),
1750 _httpAddrPort(http->hostaddr)));
1751
ef416fc2 1752 return (0);
1753}
1754
1755
355e94dc
MS
1756/*
1757 * 'httpSetAuthString()' - Set the current authorization string.
1758 *
1759 * This function just stores a copy of the current authorization string in
1760 * the HTTP connection object. You must still call httpSetField() to set
1761 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
1762 * httpHead(), httpOptions(), httpPost, or httpPut().
1763 *
426c6a59 1764 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
1765 */
1766
1767void
568fa3fa 1768httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
1769 const char *scheme, /* I - Auth scheme (NULL to clear it) */
1770 const char *data) /* I - Auth data (NULL for none) */
1771{
1772 /*
1773 * Range check input...
1774 */
1775
1776 if (!http)
1777 return;
1778
1779 if (http->authstring && http->authstring != http->_authstring)
1780 free(http->authstring);
1781
1782 http->authstring = http->_authstring;
1783
1784 if (scheme)
1785 {
1786 /*
1787 * Set the current authorization string...
1788 */
1789
1790 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 1791 char *temp;
355e94dc
MS
1792
1793 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
1794 {
1795 if ((temp = malloc(len)) == NULL)
1796 len = sizeof(http->_authstring);
1797 else
1798 http->authstring = temp;
1799 }
355e94dc
MS
1800
1801 if (data)
1802 snprintf(http->authstring, len, "%s %s", scheme, data);
1803 else
1804 strlcpy(http->authstring, scheme, len);
1805 }
1806 else
1807 {
1808 /*
1809 * Clear the current authorization string...
1810 */
1811
1812 http->_authstring[0] = '\0';
1813 }
1814}
1815
1816
ef416fc2 1817/*
1818 * 'httpSetCookie()' - Set the cookie value(s)...
1819 *
426c6a59 1820 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 1821 */
1822
1823void
1824httpSetCookie(http_t *http, /* I - Connection */
1825 const char *cookie) /* I - Cookie string */
1826{
1827 if (!http)
1828 return;
1829
1830 if (http->cookie)
1831 free(http->cookie);
1832
1833 if (cookie)
1834 http->cookie = strdup(cookie);
1835 else
1836 http->cookie = NULL;
1837}
1838
1839
b423cd4c 1840/*
1841 * 'httpSetExpect()' - Set the Expect: header in a request.
1842 *
1843 * Currently only HTTP_CONTINUE is supported for the "expect" argument.
1844 *
426c6a59 1845 * @since CUPS 1.2/Mac OS X 10.5@
b423cd4c 1846 */
1847
1848void
568fa3fa 1849httpSetExpect(http_t *http, /* I - Connection to server */
b423cd4c 1850 http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
1851{
1852 if (http)
1853 http->expect = expect;
1854}
1855
1856
ef416fc2 1857/*
1858 * 'httpSetField()' - Set the value of an HTTP header.
1859 */
1860
1861void
568fa3fa 1862httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 1863 http_field_t field, /* I - Field index */
1864 const char *value) /* I - Value */
1865{
1866 if (http == NULL ||
1867 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1868 field > HTTP_FIELD_WWW_AUTHENTICATE ||
1869 value == NULL)
1870 return;
1871
1872 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
f7deaa1a 1873
f7deaa1a 1874 if (field == HTTP_FIELD_AUTHORIZATION)
1875 {
e07d4801
MS
1876 /*
1877 * Special case for Authorization: as its contents can be
1878 * longer than HTTP_MAX_VALUE
1879 */
1880
f7deaa1a 1881 if (http->field_authorization)
1882 free(http->field_authorization);
1883
1884 http->field_authorization = strdup(value);
1885 }
e07d4801
MS
1886 else if (field == HTTP_FIELD_HOST)
1887 {
1888 /*
f11a948a
MS
1889 * Special-case for Host: as we don't want a trailing "." on the hostname and
1890 * need to bracket IPv6 numeric addresses.
e07d4801
MS
1891 */
1892
178cb736
MS
1893 char *ptr = strchr(value, ':');
1894
1895 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
1896 {
1897 /*
1898 * Bracket IPv6 numeric addresses...
1899 *
1900 * This is slightly inefficient (basically copying twice), but is an edge
1901 * case and not worth optimizing...
1902 */
e07d4801 1903
f11a948a
MS
1904 snprintf(http->fields[HTTP_FIELD_HOST],
1905 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
1906 }
1907 else
e07d4801 1908 {
f11a948a
MS
1909 /*
1910 * Check for a trailing dot on the hostname...
1911 */
1912
178cb736 1913 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
1914
1915 if (*ptr)
1916 {
1917 ptr += strlen(ptr) - 1;
e07d4801 1918
f11a948a
MS
1919 if (*ptr == '.')
1920 *ptr = '\0';
1921 }
e07d4801
MS
1922 }
1923 }
ef416fc2 1924}
1925
1926
1927/*
1928 * 'httpSetLength()' - Set the content-length and content-encoding.
1929 *
426c6a59 1930 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 1931 */
1932
1933void
568fa3fa 1934httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 1935 size_t length) /* I - Length (0 for chunked) */
1936{
1937 if (!http)
1938 return;
1939
1940 if (!length)
1941 {
1942 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
1943 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
1944 }
1945 else
1946 {
1947 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
1948 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
1949 CUPS_LLFMT, CUPS_LLCAST length);
1950 }
1951}
1952
1953
1954/*
1955 * 'httpTrace()' - Send an TRACE request to the server.
1956 */
1957
1958int /* O - Status of call (0 = success) */
568fa3fa 1959httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 1960 const char *uri) /* I - URI for trace */
1961{
1962 return (http_send(http, HTTP_TRACE, uri));
1963}
1964
1965
1966/*
1967 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1968 */
1969
1970http_status_t /* O - HTTP status */
568fa3fa 1971httpUpdate(http_t *http) /* I - Connection to server */
ef416fc2 1972{
1973 char line[32768], /* Line from connection... */
1974 *value; /* Pointer to value on line */
1975 http_field_t field; /* Field index */
1976 int major, minor, /* HTTP version numbers */
1977 status; /* Request status */
1978
1979
f11a948a
MS
1980 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
1981 http_states[http->state]));
ef416fc2 1982
1983 /*
1984 * Flush pending data, if any...
1985 */
1986
1987 if (http->wused)
1988 {
e07d4801 1989 DEBUG_puts("2httpUpdate: flushing buffer...");
ef416fc2 1990
1991 if (httpFlushWrite(http) < 0)
1992 return (HTTP_ERROR);
1993 }
1994
1995 /*
1996 * If we haven't issued any commands, then there is nothing to "update"...
1997 */
1998
1999 if (http->state == HTTP_WAITING)
2000 return (HTTP_CONTINUE);
2001
2002 /*
2003 * Grab all of the lines we can from the connection...
2004 */
2005
2006 while (httpGets(line, sizeof(line), http) != NULL)
2007 {
e07d4801 2008 DEBUG_printf(("2httpUpdate: Got \"%s\"", line));
ef416fc2 2009
2010 if (line[0] == '\0')
2011 {
2012 /*
2013 * Blank line means the start of the data section (if any). Return
2014 * the result code, too...
2015 *
2016 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
2017 * Instead, we just return HTTP_CONTINUE to the caller and keep on
2018 * tryin'...
2019 */
2020
2021 if (http->status == HTTP_CONTINUE)
2022 return (http->status);
2023
2024 if (http->status < HTTP_BAD_REQUEST)
2025 http->digest_tries = 0;
2026
2027#ifdef HAVE_SSL
2028 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
2029 {
2030 if (http_setup_ssl(http) != 0)
2031 {
2032# ifdef WIN32
2033 closesocket(http->fd);
2034# else
2035 close(http->fd);
2036# endif /* WIN32 */
2037
2038 return (HTTP_ERROR);
2039 }
2040
2041 return (HTTP_CONTINUE);
2042 }
2043#endif /* HAVE_SSL */
2044
2045 httpGetLength2(http);
2046
2047 switch (http->state)
2048 {
2049 case HTTP_GET :
2050 case HTTP_POST :
2051 case HTTP_POST_RECV :
2052 case HTTP_PUT :
2053 http->state ++;
2054 case HTTP_POST_SEND :
e1d6a774 2055 case HTTP_HEAD :
ef416fc2 2056 break;
2057
2058 default :
2059 http->state = HTTP_WAITING;
2060 break;
2061 }
2062
2063 return (http->status);
2064 }
e07d4801 2065 else if (!strncmp(line, "HTTP/", 5))
ef416fc2 2066 {
2067 /*
2068 * Got the beginning of a response...
2069 */
2070
2071 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
2072 return (HTTP_ERROR);
2073
2074 http->version = (http_version_t)(major * 100 + minor);
2075 http->status = (http_status_t)status;
2076 }
2077 else if ((value = strchr(line, ':')) != NULL)
2078 {
2079 /*
2080 * Got a value...
2081 */
2082
2083 *value++ = '\0';
2084 while (isspace(*value & 255))
2085 value ++;
2086
2087 /*
2088 * Be tolerants of servers that send unknown attribute fields...
2089 */
2090
2091 if (!strcasecmp(line, "expect"))
2092 {
2093 /*
2094 * "Expect: 100-continue" or similar...
2095 */
2096
2097 http->expect = (http_status_t)atoi(value);
2098 }
2099 else if (!strcasecmp(line, "cookie"))
2100 {
2101 /*
2102 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
2103 */
2104
2105 httpSetCookie(http, value);
2106 }
2107 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
2108 {
e07d4801 2109 DEBUG_printf(("1httpUpdate: unknown field %s seen!", line));
ef416fc2 2110 continue;
2111 }
2112 else
2113 httpSetField(http, field, value);
2114 }
2115 else
2116 {
e07d4801 2117 DEBUG_printf(("1httpUpdate: Bad response line \"%s\"!", line));
ef416fc2 2118 http->status = HTTP_ERROR;
2119 return (HTTP_ERROR);
2120 }
2121 }
2122
2123 /*
2124 * See if there was an error...
2125 */
2126
2127 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
e07d4801
MS
2128 {
2129 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 2130 return (http->status);
e07d4801 2131 }
ef416fc2 2132
2133 if (http->error)
2134 {
e07d4801 2135 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 2136 strerror(http->error)));
2137 http->status = HTTP_ERROR;
2138 return (HTTP_ERROR);
2139 }
2140
2141 /*
2142 * If we haven't already returned, then there is nothing new...
2143 */
2144
2145 return (HTTP_CONTINUE);
2146}
2147
2148
38e73f87
MS
2149/*
2150 * '_httpWait()' - Wait for data available on a connection (no flush).
2151 */
2152
2153int /* O - 1 if data is available, 0 otherwise */
2154_httpWait(http_t *http, /* I - Connection to server */
2155 int msec, /* I - Milliseconds to wait */
2156 int usessl) /* I - Use SSL context? */
2157{
2158#ifdef HAVE_POLL
2159 struct pollfd pfd; /* Polled file descriptor */
2160#else
2161 fd_set input_set; /* select() input set */
2162 struct timeval timeout; /* Timeout */
2163#endif /* HAVE_POLL */
2164 int nfds; /* Result from select()/poll() */
2165
2166
e07d4801 2167 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
2168
2169 if (http->fd < 0)
2170 return (0);
2171
2172 /*
2173 * Check the SSL/TLS buffers for data first...
2174 */
2175
2176#ifdef HAVE_SSL
2177 if (http->tls && usessl)
2178 {
2179# ifdef HAVE_LIBSSL
2180 if (SSL_pending((SSL *)(http->tls)))
2181 return (1);
2182# elif defined(HAVE_GNUTLS)
2183 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2184 return (1);
2185# elif defined(HAVE_CDSASSL)
2186 size_t bytes; /* Bytes that are available */
2187
2188 if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
2189 bytes > 0)
2190 return (1);
2191# endif /* HAVE_LIBSSL */
2192 }
2193#endif /* HAVE_SSL */
2194
2195 /*
2196 * Then try doing a select() or poll() to poll the socket...
2197 */
2198
2199#ifdef HAVE_POLL
2200 pfd.fd = http->fd;
2201 pfd.events = POLLIN;
2202
e07d4801
MS
2203 while ((nfds = poll(&pfd, 1, msec)) < 0 &&
2204 (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2205
2206#else
2207 do
2208 {
2209 FD_ZERO(&input_set);
2210 FD_SET(http->fd, &input_set);
2211
e07d4801 2212 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
2213
2214 if (msec >= 0)
2215 {
2216 timeout.tv_sec = msec / 1000;
2217 timeout.tv_usec = (msec % 1000) * 1000;
2218
2219 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
2220 }
2221 else
2222 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
2223
e07d4801 2224 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
2225 }
2226# ifdef WIN32
2227 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2228# else
e07d4801 2229 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2230# endif /* WIN32 */
2231#endif /* HAVE_POLL */
2232
e07d4801 2233 DEBUG_printf(("5_httpWait: returning with nfds=%d...", nfds));
38e73f87
MS
2234
2235 return (nfds > 0);
2236}
2237
2238
ef416fc2 2239/*
2240 * 'httpWait()' - Wait for data available on a connection.
2241 *
426c6a59 2242 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2243 */
2244
2245int /* O - 1 if data is available, 0 otherwise */
568fa3fa 2246httpWait(http_t *http, /* I - Connection to server */
ef416fc2 2247 int msec) /* I - Milliseconds to wait */
2248{
2249 /*
2250 * First see if there is data in the buffer...
2251 */
2252
2253 if (http == NULL)
2254 return (0);
2255
2256 if (http->used)
2257 return (1);
2258
8ca02f3c 2259 /*
2260 * Flush pending data, if any...
2261 */
2262
2263 if (http->wused)
2264 {
2265 if (httpFlushWrite(http) < 0)
2266 return (0);
2267 }
2268
ef416fc2 2269 /*
2270 * If not, check the SSL/TLS buffers and do a select() on the connection...
2271 */
2272
38e73f87 2273 return (_httpWait(http, msec, 1));
ef416fc2 2274}
2275
2276
2277/*
2278 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 2279 *
2280 * This function is deprecated. Use the httpWrite2() function which can
2281 * write more than 2GB of data.
2282 *
2283 * @deprecated@
ef416fc2 2284 */
ef55b745 2285
ef416fc2 2286int /* O - Number of bytes written */
568fa3fa 2287httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 2288 const char *buffer, /* I - Buffer for data */
2289 int length) /* I - Number of bytes to write */
2290{
a4d04587 2291 return ((int)httpWrite2(http, buffer, length));
2292}
2293
2294
2295/*
2296 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 2297 *
426c6a59 2298 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 2299 */
ef55b745 2300
a4d04587 2301ssize_t /* O - Number of bytes written */
568fa3fa 2302httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 2303 const char *buffer, /* I - Buffer for data */
2304 size_t length) /* I - Number of bytes to write */
2305{
2306 ssize_t bytes; /* Bytes written */
ef416fc2 2307
2308
e07d4801 2309 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 2310 buffer, CUPS_LLCAST length));
ef416fc2 2311
2312 /*
2313 * Range check input...
2314 */
2315
2316 if (http == NULL || buffer == NULL)
2317 return (-1);
2318
2319 /*
2320 * Mark activity on the connection...
2321 */
2322
2323 http->activity = time(NULL);
2324
2325 /*
2326 * Buffer small writes for better performance...
2327 */
2328
2329 if (length > 0)
2330 {
2331 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
2332 {
e07d4801
MS
2333 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
2334 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 2335
2336 httpFlushWrite(http);
2337 }
2338
38e73f87
MS
2339 if ((length + http->wused) <= sizeof(http->wbuffer) &&
2340 length < sizeof(http->wbuffer))
ef416fc2 2341 {
2342 /*
2343 * Write to buffer...
2344 */
2345
e07d4801 2346 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 2347 CUPS_LLCAST length));
ef416fc2 2348
2349 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 2350 http->wused += (int)length;
2351 bytes = (ssize_t)length;
ef416fc2 2352 }
2353 else
2354 {
2355 /*
2356 * Otherwise write the data directly...
2357 */
2358
e07d4801 2359 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 2360 CUPS_LLCAST length));
ef416fc2 2361
2362 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
b86bc4cf 2363 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 2364 else
b86bc4cf 2365 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 2366
e07d4801 2367 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 2368 CUPS_LLCAST bytes));
ef416fc2 2369 }
2370
2371 if (http->data_encoding == HTTP_ENCODE_LENGTH)
2372 http->data_remaining -= bytes;
2373 }
2374 else
2375 bytes = 0;
2376
2377 /*
2378 * Handle end-of-request processing...
2379 */
2380
2381 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
2382 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
2383 {
2384 /*
2385 * Finished with the transfer; unless we are sending POST or PUT
2386 * data, go idle...
2387 */
2388
e07d4801 2389 DEBUG_puts("2httpWrite: changing states...");
ef416fc2 2390
2391 if (http->wused)
2392 httpFlushWrite(http);
2393
2394 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2395 {
2396 /*
2397 * Send a 0-length chunk at the end of the request...
2398 */
2399
2400 http_write(http, "0\r\n\r\n", 5);
2401
2402 /*
2403 * Reset the data state...
2404 */
2405
2406 http->data_encoding = HTTP_ENCODE_LENGTH;
2407 http->data_remaining = 0;
2408 }
2409
2410 if (http->state == HTTP_POST_RECV)
2411 http->state ++;
2412 else if (http->state == HTTP_PUT_RECV)
2413 http->state = HTTP_STATUS;
2414 else
2415 http->state = HTTP_WAITING;
2416 }
2417
2418 return (bytes);
2419}
2420
2421
2422#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2423/*
411affcf 2424 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 2425 */
2426
2427OSStatus /* O - -1 on error, 0 on success */
2428_httpWriteCDSA(
2429 SSLConnectionRef connection, /* I - SSL/TLS connection */
2430 const void *data, /* I - Data buffer */
2431 size_t *dataLength) /* IO - Number of bytes */
2432{
411affcf 2433 OSStatus result; /* Return value */
2434 ssize_t bytes; /* Number of bytes read */
2435 http_t *http; /* HTTP connection */
e53920b9 2436
2437
411affcf 2438 http = (http_t *)connection;
ef416fc2 2439
b423cd4c 2440 do
411affcf 2441 {
2442 bytes = write(http->fd, data, *dataLength);
2443 }
e07d4801 2444 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2445
b423cd4c 2446 if (bytes == *dataLength)
411affcf 2447 {
b423cd4c 2448 result = 0;
411affcf 2449 }
b423cd4c 2450 else if (bytes >= 0)
2451 {
2452 *dataLength = bytes;
2453 result = errSSLWouldBlock;
2454 }
2455 else
2456 {
2457 *dataLength = 0;
ef55b745 2458
fa73b229 2459 if (errno == EAGAIN)
b423cd4c 2460 result = errSSLWouldBlock;
b423cd4c 2461 else
ed486911 2462 result = errSSLClosedAbort;
ef416fc2 2463 }
b423cd4c 2464
411affcf 2465 return (result);
ef416fc2 2466}
2467#endif /* HAVE_SSL && HAVE_CDSASSL */
2468
2469
411affcf 2470#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2471/*
2472 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
2473 */
2474
2475ssize_t /* O - Number of bytes written or -1 on error */
2476_httpWriteGNUTLS(
568fa3fa 2477 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2478 const void *data, /* I - Data buffer */
2479 size_t length) /* I - Number of bytes to write */
2480{
2481 return (send(((http_t *)ptr)->fd, data, length, 0));
2482}
2483#endif /* HAVE_SSL && HAVE_GNUTLS */
2484
2485
2486#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
2487/*
2488 * 'http_bio_ctrl()' - Control the HTTP connection.
2489 */
2490
2491static long /* O - Result/data */
2492http_bio_ctrl(BIO *h, /* I - BIO data */
2493 int cmd, /* I - Control command */
2494 long arg1, /* I - First argument */
2495 void *arg2) /* I - Second argument */
2496{
2497 switch (cmd)
2498 {
2499 default :
2500 return (0);
2501
2502 case BIO_CTRL_RESET :
2503 h->ptr = NULL;
2504 return (0);
2505
2506 case BIO_C_SET_FILE_PTR :
2507 h->ptr = arg2;
2508 h->init = 1;
2509 return (1);
2510
2511 case BIO_C_GET_FILE_PTR :
2512 if (arg2)
2513 {
2514 *((void **)arg2) = h->ptr;
2515 return (1);
2516 }
2517 else
2518 return (0);
ef55b745 2519
411affcf 2520 case BIO_CTRL_DUP :
2521 case BIO_CTRL_FLUSH :
2522 return (1);
2523 }
2524}
2525
2526
2527/*
2528 * 'http_bio_free()' - Free OpenSSL data.
2529 */
2530
2531static int /* O - 1 on success, 0 on failure */
2532http_bio_free(BIO *h) /* I - BIO data */
2533{
2534 if (!h)
2535 return (0);
2536
2537 if (h->shutdown)
2538 {
2539 h->init = 0;
2540 h->flags = 0;
2541 }
2542
2543 return (1);
2544}
2545
2546
2547/*
2548 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
2549 */
2550
2551static int /* O - 1 on success, 0 on failure */
2552http_bio_new(BIO *h) /* I - BIO data */
2553{
2554 if (!h)
2555 return (0);
2556
2557 h->init = 0;
2558 h->num = 0;
2559 h->ptr = NULL;
2560 h->flags = 0;
2561
2562 return (1);
2563}
2564
2565
2566/*
2567 * 'http_bio_puts()' - Send a string for OpenSSL.
2568 */
2569
2570static int /* O - Bytes written */
2571http_bio_puts(BIO *h, /* I - BIO data */
2572 const char *str) /* I - String to write */
2573{
b86bc4cf 2574#ifdef WIN32
2575 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
2576#else
411affcf 2577 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 2578#endif /* WIN32 */
411affcf 2579}
2580
2581
2582/*
2583 * 'http_bio_read()' - Read data for OpenSSL.
2584 */
2585
2586static int /* O - Bytes read */
2587http_bio_read(BIO *h, /* I - BIO data */
2588 char *buf, /* I - Buffer */
2589 int size) /* I - Number of bytes to read */
2590{
2591 http_t *http; /* HTTP connection */
2592
2593
2594 http = (http_t *)h->ptr;
2595
2596 if (!http->blocking)
2597 {
2598 /*
2599 * Make sure we have data before we read...
2600 */
2601
38e73f87 2602 if (!_httpWait(http, 10000, 0))
411affcf 2603 {
b86bc4cf 2604#ifdef WIN32
2605 http->error = WSAETIMEDOUT;
2606#else
411affcf 2607 http->error = ETIMEDOUT;
b86bc4cf 2608#endif /* WIN32 */
2609
411affcf 2610 return (-1);
2611 }
2612 }
2613
2614 return (recv(http->fd, buf, size, 0));
2615}
2616
2617
2618/*
2619 * 'http_bio_write()' - Write data for OpenSSL.
2620 */
2621
2622static int /* O - Bytes written */
2623http_bio_write(BIO *h, /* I - BIO data */
2624 const char *buf, /* I - Buffer to write */
2625 int num) /* I - Number of bytes to write */
2626{
2627 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
2628}
2629#endif /* HAVE_SSL && HAVE_LIBSSL */
2630
2631
ae71f5de
MS
2632#ifdef DEBUG
2633/*
2634 * 'http_debug_hex()' - Do a hex dump of a buffer.
2635 */
2636
2637static void
2638http_debug_hex(const char *prefix, /* I - Prefix for line */
2639 const char *buffer, /* I - Buffer to dump */
2640 int bytes) /* I - Bytes to dump */
2641{
2642 int i, j, /* Looping vars */
2643 ch; /* Current character */
2644 char line[255], /* Line buffer */
2645 *start, /* Start of line after prefix */
2646 *ptr; /* Pointer into line */
2647
2648
f11a948a 2649 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
2650 return;
2651
e07d4801 2652 DEBUG_printf(("6%s: %d bytes:\n", prefix, bytes));
ae71f5de 2653
f11a948a 2654 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
2655 start = line + strlen(line);
2656
2657 for (i = 0; i < bytes; i += 16)
2658 {
2659 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
2660 sprintf(ptr, "%02X", buffer[i + j] & 255);
2661
2662 while (j < 16)
2663 {
2664 strcpy(ptr, " ");
2665 ptr += 2;
2666 j ++;
2667 }
2668
2669 strcpy(ptr, " ");
2670 ptr += 2;
2671
2672 for (j = 0; j < 16 && (i + j) < bytes; j ++)
2673 {
2674 ch = buffer[i + j] & 255;
2675
2676 if (ch < ' ' || ch >= 127)
2677 ch = '.';
2678
2679 *ptr++ = ch;
2680 }
2681
2682 *ptr = '\0';
2683 DEBUG_puts(line);
2684 }
2685}
2686#endif /* DEBUG */
2687
2688
ef416fc2 2689/*
2690 * 'http_field()' - Return the field index for a field name.
2691 */
2692
ae71f5de
MS
2693static http_field_t /* O - Field index */
2694http_field(const char *name) /* I - String name */
ef416fc2 2695{
ae71f5de 2696 int i; /* Looping var */
ef416fc2 2697
2698
2699 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2700 if (strcasecmp(name, http_fields[i]) == 0)
2701 return ((http_field_t)i);
2702
2703 return (HTTP_FIELD_UNKNOWN);
2704}
2705
2706
2707#ifdef HAVE_SSL
2708/*
2709 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2710 */
2711
2712static int /* O - Bytes read */
568fa3fa 2713http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 2714 char *buf, /* I - Buffer to store data */
2715 int len) /* I - Length of buffer */
2716{
2717# if defined(HAVE_LIBSSL)
2718 return (SSL_read((SSL *)(http->tls), buf, len));
2719
2720# elif defined(HAVE_GNUTLS)
ef55b745
MS
2721 ssize_t result; /* Return value */
2722
2723
2724 result = gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len);
2725
2726 if (result < 0 && !errno)
2727 {
2728 /*
2729 * Convert GNU TLS error to errno value...
2730 */
2731
2732 switch (result)
2733 {
2734 case GNUTLS_E_INTERRUPTED :
2735 errno = EINTR;
2736 break;
2737
2738 case GNUTLS_E_AGAIN :
2739 errno = EAGAIN;
2740 break;
2741
2742 default :
2743 errno = EPIPE;
2744 break;
2745 }
2746
2747 result = -1;
2748 }
2749
2750 return ((int)result);
ef416fc2 2751
2752# elif defined(HAVE_CDSASSL)
fa73b229 2753 int result; /* Return value */
ef416fc2 2754 OSStatus error; /* Error info */
2755 size_t processed; /* Number of bytes processed */
2756
2757
89d46774 2758 error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 2759
fa73b229 2760 switch (error)
ef416fc2 2761 {
fa73b229 2762 case 0 :
2763 result = (int)processed;
2764 break;
2765 case errSSLClosedGraceful :
2766 result = 0;
2767 break;
2768 case errSSLWouldBlock :
b423cd4c 2769 if (processed)
2770 result = (int)processed;
2771 else
2772 {
2773 result = -1;
2774 errno = EINTR;
2775 }
fa73b229 2776 break;
2777 default :
2778 errno = EPIPE;
2779 result = -1;
2780 break;
ef416fc2 2781 }
fa73b229 2782
2783 return (result);
ef416fc2 2784# endif /* HAVE_LIBSSL */
2785}
2786#endif /* HAVE_SSL */
2787
2788
2789/*
2790 * 'http_send()' - Send a request with all fields and the trailing blank line.
2791 */
2792
2793static int /* O - 0 on success, non-zero on error */
568fa3fa 2794http_send(http_t *http, /* I - Connection to server */
ef416fc2 2795 http_state_t request, /* I - Request code */
2796 const char *uri) /* I - URI */
2797{
2798 int i; /* Looping var */
839a51c8 2799 char buf[1024]; /* Encoded URI buffer */
ef416fc2 2800 static const char * const codes[] =
2801 { /* Request code strings */
2802 NULL,
2803 "OPTIONS",
2804 "GET",
2805 NULL,
2806 "HEAD",
2807 "POST",
2808 NULL,
2809 NULL,
2810 "PUT",
2811 NULL,
2812 "DELETE",
2813 "TRACE",
2814 "CLOSE"
2815 };
ef416fc2 2816
2817
e07d4801 2818 DEBUG_printf(("7http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 2819 http, codes[request], uri));
2820
2821 if (http == NULL || uri == NULL)
2822 return (-1);
2823
2824 /*
2825 * Set the User-Agent field if it isn't already...
2826 */
2827
2828 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
2829 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
2830
2831 /*
2832 * Encode the URI as needed...
2833 */
2834
839a51c8 2835 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 2836
2837 /*
2838 * See if we had an error the last time around; if so, reconnect...
2839 */
2840
2841 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 2842 if (httpReconnect(http))
2843 return (-1);
ef416fc2 2844
d09495fa 2845 /*
2846 * Flush any written data that is pending...
2847 */
2848
2849 if (http->wused)
536bc2c6
MS
2850 {
2851 if (httpFlushWrite(http) < 0)
2852 if (httpReconnect(http))
2853 return (-1);
2854 }
d09495fa 2855
ef416fc2 2856 /*
2857 * Send the request header...
2858 */
2859
d09495fa 2860 http->state = request;
2861 http->data_encoding = HTTP_ENCODE_FIELDS;
2862
ef416fc2 2863 if (request == HTTP_POST || request == HTTP_PUT)
2864 http->state ++;
2865
2866 http->status = HTTP_CONTINUE;
2867
2868#ifdef HAVE_SSL
2869 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2870 {
2871 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2872 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2873 }
2874#endif /* HAVE_SSL */
2875
2876 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2877 {
2878 http->status = HTTP_ERROR;
2879 return (-1);
2880 }
2881
2882 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2883 if (http->fields[i][0] != '\0')
2884 {
e07d4801 2885 DEBUG_printf(("9http_send: %s: %s", http_fields[i],
ae71f5de 2886 httpGetField(http, i)));
ef416fc2 2887
ef55b745 2888 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
f7deaa1a 2889 httpGetField(http, i)) < 1)
ef416fc2 2890 {
2891 http->status = HTTP_ERROR;
2892 return (-1);
2893 }
2894 }
2895
2896 if (http->cookie)
2897 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
2898 {
2899 http->status = HTTP_ERROR;
2900 return (-1);
2901 }
2902
b423cd4c 2903 if (http->expect == HTTP_CONTINUE &&
2904 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
2905 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
2906 {
2907 http->status = HTTP_ERROR;
2908 return (-1);
2909 }
2910
ef416fc2 2911 if (httpPrintf(http, "\r\n") < 1)
2912 {
2913 http->status = HTTP_ERROR;
2914 return (-1);
2915 }
2916
536bc2c6
MS
2917 if (httpFlushWrite(http) < 0)
2918 return (-1);
2919
ef416fc2 2920 httpGetLength2(http);
2921 httpClearFields(http);
2922
f7deaa1a 2923 /*
b94498cf 2924 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 2925 */
2926
ef55b745
MS
2927 if (http->field_authorization && http->authstring &&
2928 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 2929 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 2930 {
2931 http->_authstring[0] = '\0';
2932
2933 if (http->authstring != http->_authstring)
2934 free(http->authstring);
ef55b745 2935
f7deaa1a 2936 http->authstring = http->_authstring;
2937 }
2938
ef416fc2 2939 return (0);
2940}
2941
2942
2943#ifdef HAVE_SSL
2944/*
2945 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2946 */
2947
2948static int /* O - Status of connection */
568fa3fa 2949http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 2950{
2951# ifdef HAVE_LIBSSL
89d46774 2952 SSL_CTX *context; /* Context for encryption */
2953 SSL *conn; /* Connection for encryption */
411affcf 2954 BIO *bio; /* BIO data */
ef416fc2 2955# elif defined(HAVE_GNUTLS)
89d46774 2956 http_tls_t *conn; /* TLS session object */
ef416fc2 2957 gnutls_certificate_client_credentials *credentials;
89d46774 2958 /* TLS credentials */
ef416fc2 2959# elif defined(HAVE_CDSASSL)
89d46774 2960 OSStatus error; /* Error code */
2961 http_tls_t *conn; /* CDSA connection information */
ef416fc2 2962# endif /* HAVE_LIBSSL */
2963
2964
e07d4801 2965 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 2966
2967# ifdef HAVE_LIBSSL
2968 context = SSL_CTX_new(SSLv23_client_method());
2969
2970 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2971
411affcf 2972 bio = BIO_new(_httpBIOMethods());
2973 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
2974
ef416fc2 2975 conn = SSL_new(context);
411affcf 2976 SSL_set_bio(conn, bio, bio);
ef416fc2 2977
ef416fc2 2978 if (SSL_connect(conn) != 1)
2979 {
2980# ifdef DEBUG
2981 unsigned long error; /* Error code */
2982
2983 while ((error = ERR_get_error()) != 0)
e07d4801 2984 DEBUG_printf(("8http_setup_ssl: %s", ERR_error_string(error, NULL)));
ef416fc2 2985# endif /* DEBUG */
2986
2987 SSL_CTX_free(context);
2988 SSL_free(conn);
2989
2990# ifdef WIN32
2991 http->error = WSAGetLastError();
2992# else
2993 http->error = errno;
2994# endif /* WIN32 */
2995 http->status = HTTP_ERROR;
2996
2997 return (HTTP_ERROR);
2998 }
2999
3000# elif defined(HAVE_GNUTLS)
89d46774 3001 if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
ef416fc2 3002 {
3003 http->error = errno;
3004 http->status = HTTP_ERROR;
3005
3006 return (-1);
3007 }
3008
3009 credentials = (gnutls_certificate_client_credentials *)
3010 malloc(sizeof(gnutls_certificate_client_credentials));
3011 if (credentials == NULL)
3012 {
3013 free(conn);
3014
3015 http->error = errno;
3016 http->status = HTTP_ERROR;
3017
3018 return (-1);
3019 }
3020
3021 gnutls_certificate_allocate_credentials(credentials);
3022
3023 gnutls_init(&(conn->session), GNUTLS_CLIENT);
3024 gnutls_set_default_priority(conn->session);
3025 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
411affcf 3026 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
3027 gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
3028 gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
ef416fc2 3029
3030 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
3031 {
3032 http->error = errno;
3033 http->status = HTTP_ERROR;
3034
85b5d1df
MS
3035 gnutls_deinit(conn->session);
3036 gnutls_certificate_free_credentials(*credentials);
3037 free(credentials);
3038 free(conn);
3039
ef416fc2 3040 return (-1);
3041 }
3042
3043 conn->credentials = credentials;
3044
3045# elif defined(HAVE_CDSASSL)
89d46774 3046 conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
e53920b9 3047
89d46774 3048 if (conn == NULL)
3049 return (-1);
e53920b9 3050
89d46774 3051 if ((error = SSLNewContext(false, &conn->session)))
e53920b9 3052 {
89d46774 3053 http->error = error;
3054 http->status = HTTP_ERROR;
e53920b9 3055
89d46774 3056 free(conn);
3057 return (-1);
e53920b9 3058 }
ef416fc2 3059
89d46774 3060 /*
3061 * Use a union to resolve warnings about int/pointer size mismatches...
3062 */
3063
411affcf 3064 error = SSLSetConnection(conn->session, http);
89d46774 3065
3066 if (!error)
3067 error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
3068
ef416fc2 3069 if (!error)
89d46774 3070 error = SSLSetAllowsExpiredCerts(conn->session, true);
ef416fc2 3071
3072 if (!error)
89d46774 3073 error = SSLSetAllowsAnyRoot(conn->session, true);
ef416fc2 3074
ed486911 3075 if (!error)
3076 error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
3077
ef416fc2 3078 if (!error)
b423cd4c 3079 {
89d46774 3080 while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
b423cd4c 3081 usleep(1000);
3082 }
ef416fc2 3083
89d46774 3084 if (error)
ef416fc2 3085 {
3086 http->error = error;
3087 http->status = HTTP_ERROR;
3088
89d46774 3089 SSLDisposeContext(conn->session);
ef416fc2 3090
89d46774 3091 free(conn);
ef416fc2 3092
3093 return (-1);
3094 }
3095# endif /* HAVE_CDSASSL */
3096
3097 http->tls = conn;
3098 return (0);
3099}
3100#endif /* HAVE_SSL */
3101
3102
3103#ifdef HAVE_SSL
3104/*
3105 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
3106 */
3107
3108static void
568fa3fa 3109http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 3110{
3111# ifdef HAVE_LIBSSL
89d46774 3112 SSL_CTX *context; /* Context for encryption */
3113 SSL *conn; /* Connection for encryption */
ef416fc2 3114
3115
3116 conn = (SSL *)(http->tls);
3117 context = SSL_get_SSL_CTX(conn);
3118
3119 SSL_shutdown(conn);
3120 SSL_CTX_free(context);
3121 SSL_free(conn);
3122
3123# elif defined(HAVE_GNUTLS)
89d46774 3124 http_tls_t *conn; /* Encryption session */
ef416fc2 3125 gnutls_certificate_client_credentials *credentials;
89d46774 3126 /* TLS credentials */
ef416fc2 3127
3128
3129 conn = (http_tls_t *)(http->tls);
3130 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
3131
3132 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
3133 gnutls_deinit(conn->session);
3134 gnutls_certificate_free_credentials(*credentials);
3135 free(credentials);
3136 free(conn);
3137
3138# elif defined(HAVE_CDSASSL)
89d46774 3139 http_tls_t *conn; /* CDSA connection information */
3140
3141
3142 conn = (http_tls_t *)(http->tls);
3143
3144 while (SSLClose(conn->session) == errSSLWouldBlock)
b423cd4c 3145 usleep(1000);
3146
89d46774 3147 SSLDisposeContext(conn->session);
3148
3149 if (conn->certsArray)
3150 CFRelease(conn->certsArray);
3151
3152 free(conn);
ef416fc2 3153# endif /* HAVE_LIBSSL */
3154
3155 http->tls = NULL;
3156}
3157#endif /* HAVE_SSL */
3158
3159
3160#ifdef HAVE_SSL
3161/*
3162 * 'http_upgrade()' - Force upgrade to TLS encryption.
3163 */
3164
89d46774 3165static int /* O - Status of connection */
568fa3fa 3166http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 3167{
89d46774 3168 int ret; /* Return value */
3169 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 3170
3171
e07d4801 3172 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 3173
85b5d1df
MS
3174 /*
3175 * Flush the connection to make sure any previous "Upgrade" message
3176 * has been read.
3177 */
3178
3179 httpFlush(http);
3180
ef416fc2 3181 /*
3182 * Copy the HTTP data to a local variable so we can do the OPTIONS
3183 * request without interfering with the existing request data...
3184 */
3185
3186 memcpy(&myhttp, http, sizeof(myhttp));
3187
3188 /*
3189 * Send an OPTIONS request to the server, requiring SSL or TLS
3190 * encryption on the link...
3191 */
3192
f7deaa1a 3193 http->field_authorization = NULL; /* Don't free the auth string */
3194
b86bc4cf 3195 httpClearFields(http);
3196 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
3197 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
ef416fc2 3198
b86bc4cf 3199 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 3200 {
3201 /*
3202 * Wait for the secure connection...
3203 */
3204
b86bc4cf 3205 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 3206 }
3207
ef416fc2 3208 /*
b86bc4cf 3209 * Restore the HTTP request data...
ef416fc2 3210 */
3211
b86bc4cf 3212 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 3213 http->data_encoding = myhttp.data_encoding;
3214 http->data_remaining = myhttp.data_remaining;
3215 http->_data_remaining = myhttp._data_remaining;
3216 http->expect = myhttp.expect;
3217 http->field_authorization = myhttp.field_authorization;
bc44d920 3218 http->digest_tries = myhttp.digest_tries;
ef416fc2 3219
3220 /*
3221 * See if we actually went secure...
3222 */
3223
3224 if (!http->tls)
3225 {
3226 /*
3227 * Server does not support HTTP upgrade...
3228 */
3229
e07d4801 3230 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 3231
3232# ifdef WIN32
3233 closesocket(http->fd);
3234# else
3235 close(http->fd);
3236# endif
3237
3238 http->fd = -1;
3239
3240 return (-1);
3241 }
3242 else
3243 return (ret);
3244}
3245#endif /* HAVE_SSL */
3246
3247
ef416fc2 3248/*
3249 * 'http_write()' - Write a buffer to a HTTP connection.
3250 */
ef55b745 3251
ef416fc2 3252static int /* O - Number of bytes written */
568fa3fa 3253http_write(http_t *http, /* I - Connection to server */
f11a948a
MS
3254 const char *buffer, /* I - Buffer for data */
3255 int length) /* I - Number of bytes to write */
ef416fc2 3256{
3257 int tbytes, /* Total bytes sent */
3258 bytes; /* Bytes sent */
3259
3260
f11a948a
MS
3261 http->error = 0;
3262 tbytes = 0;
ef416fc2 3263
3264 while (length > 0)
3265 {
3266#ifdef HAVE_SSL
3267 if (http->tls)
3268 bytes = http_write_ssl(http, buffer, length);
3269 else
3270#endif /* HAVE_SSL */
3271 bytes = send(http->fd, buffer, length, 0);
3272
3273 if (bytes < 0)
3274 {
3275#ifdef WIN32
3276 if (WSAGetLastError() != http->error)
3277 {
3278 http->error = WSAGetLastError();
3279 continue;
3280 }
3281#else
e07d4801 3282 if (errno == EINTR || errno == EAGAIN)
ef416fc2 3283 continue;
3284 else if (errno != http->error && errno != ECONNRESET)
3285 {
3286 http->error = errno;
3287 continue;
3288 }
3289#endif /* WIN32 */
3290
e07d4801 3291 DEBUG_puts("8http_write: error writing data...");
ef416fc2 3292
3293 return (-1);
3294 }
3295
3296 buffer += bytes;
3297 tbytes += bytes;
3298 length -= bytes;
3299 }
3300
3301#ifdef DEBUG
ae71f5de 3302 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 3303#endif /* DEBUG */
3304
3305 return (tbytes);
3306}
3307
3308
3309/*
3310 * 'http_write_chunk()' - Write a chunked buffer.
3311 */
3312
3313static int /* O - Number bytes written */
568fa3fa 3314http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 3315 const char *buffer, /* I - Buffer to write */
3316 int length) /* I - Length of buffer */
3317{
3318 char header[255]; /* Chunk header */
3319 int bytes; /* Bytes written */
3320
f11a948a 3321
e07d4801 3322 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
ef416fc2 3323 http, buffer, length));
3324
3325 /*
3326 * Write the chunk header, data, and trailer.
3327 */
3328
3329 sprintf(header, "%x\r\n", length);
b86bc4cf 3330 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 3331 {
e07d4801 3332 DEBUG_puts("8http_write_chunk: http_write of length failed!");
ef416fc2 3333 return (-1);
3334 }
3335
3336 if ((bytes = http_write(http, buffer, length)) < 0)
3337 {
e07d4801 3338 DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
ef416fc2 3339 return (-1);
3340 }
3341
3342 if (http_write(http, "\r\n", 2) < 0)
3343 {
e07d4801 3344 DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
ef416fc2 3345 return (-1);
3346 }
3347
3348 return (bytes);
3349}
3350
3351
3352#ifdef HAVE_SSL
3353/*
3354 * 'http_write_ssl()' - Write to a SSL/TLS connection.
3355 */
3356
3357static int /* O - Bytes written */
568fa3fa 3358http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3359 const char *buf, /* I - Buffer holding data */
3360 int len) /* I - Length of buffer */
3361{
3362# if defined(HAVE_LIBSSL)
3363 return (SSL_write((SSL *)(http->tls), buf, len));
3364
3365# elif defined(HAVE_GNUTLS)
ef55b745
MS
3366 ssize_t result; /* Return value */
3367
3368 result = gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len);
3369
3370 if (result < 0 && !errno)
3371 {
3372 /*
3373 * Convert GNU TLS error to errno value...
3374 */
3375
3376 switch (result)
3377 {
3378 case GNUTLS_E_INTERRUPTED :
3379 errno = EINTR;
3380 break;
3381
3382 case GNUTLS_E_AGAIN :
3383 errno = EAGAIN;
3384 break;
3385
3386 default :
3387 errno = EPIPE;
3388 break;
3389 }
3390
3391 result = -1;
3392 }
3393
3394 return ((int)result);
3395
ef416fc2 3396# elif defined(HAVE_CDSASSL)
fa73b229 3397 int result; /* Return value */
ef416fc2 3398 OSStatus error; /* Error info */
3399 size_t processed; /* Number of bytes processed */
3400
3401
89d46774 3402 error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 3403
fa73b229 3404 switch (error)
ef416fc2 3405 {
fa73b229 3406 case 0 :
3407 result = (int)processed;
3408 break;
3409 case errSSLClosedGraceful :
3410 result = 0;
3411 break;
3412 case errSSLWouldBlock :
b423cd4c 3413 if (processed)
3414 result = (int)processed;
3415 else
3416 {
3417 result = -1;
ef55b745 3418 errno = EINTR;
b423cd4c 3419 }
fa73b229 3420 break;
3421 default :
ef55b745 3422 errno = EPIPE;
fa73b229 3423 result = -1;
3424 break;
ef416fc2 3425 }
fa73b229 3426
3427 return (result);
ef416fc2 3428# endif /* HAVE_LIBSSL */
3429}
3430#endif /* HAVE_SSL */
3431
3432
3433/*
b19ccc9e 3434 * End of "$Id: http.c 7850 2008-08-20 00:07:25Z mike $".
ef416fc2 3435 */