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