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