]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.4svn-r8628.
[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
1ff0402e
MS
1688 usleep(100000);
1689
bd7854cb 1690 http->fd = -1;
1691 }
1692
ef416fc2 1693 /*
1694 * Connect to the server...
1695 */
1696
1ff0402e
MS
1697#ifdef DEBUG
1698 for (current = http->addrlist; current; current = current->next)
e07d4801 1699 DEBUG_printf(("2httpReconnect: Address %s:%d",
1ff0402e
MS
1700 httpAddrString(&(current->addr), temp, sizeof(temp)),
1701 _httpAddrPort(&(current->addr))));
1702#endif /* DEBUG */
1703
ef416fc2 1704 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
1705 {
1706 /*
1707 * Unable to connect...
1708 */
1709
1710#ifdef WIN32
1711 http->error = WSAGetLastError();
1712#else
1713 http->error = errno;
1714#endif /* WIN32 */
1715 http->status = HTTP_ERROR;
1716
e07d4801 1717 DEBUG_printf(("1httpReconnect: httpAddrConnect failed: %s",
1ff0402e
MS
1718 strerror(http->error)));
1719
ef416fc2 1720 return (-1);
1721 }
1722
e07d4801 1723 DEBUG_printf(("2httpReconnect: New socket=%d", http->fd));
1ff0402e 1724
ef416fc2 1725 http->hostaddr = &(addr->addr);
1726 http->error = 0;
1727 http->status = HTTP_CONTINUE;
1728
1729#ifdef HAVE_SSL
1730 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1731 {
1732 /*
1733 * Always do encryption via SSL.
1734 */
1735
1736 if (http_setup_ssl(http) != 0)
1737 {
f7deaa1a 1738# ifdef WIN32
ef416fc2 1739 closesocket(http->fd);
f7deaa1a 1740# else
ef416fc2 1741 close(http->fd);
f7deaa1a 1742# endif /* WIN32 */
ef416fc2 1743
1744 return (-1);
1745 }
1746 }
1747 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1748 return (http_upgrade(http));
1749#endif /* HAVE_SSL */
1750
e07d4801 1751 DEBUG_printf(("1httpReconnect: Connected to %s:%d...",
1ff0402e
MS
1752 httpAddrString(http->hostaddr, temp, sizeof(temp)),
1753 _httpAddrPort(http->hostaddr)));
1754
ef416fc2 1755 return (0);
1756}
1757
1758
355e94dc
MS
1759/*
1760 * 'httpSetAuthString()' - Set the current authorization string.
1761 *
1762 * This function just stores a copy of the current authorization string in
1763 * the HTTP connection object. You must still call httpSetField() to set
1764 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
1765 * httpHead(), httpOptions(), httpPost, or httpPut().
1766 *
426c6a59 1767 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
1768 */
1769
1770void
568fa3fa 1771httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
1772 const char *scheme, /* I - Auth scheme (NULL to clear it) */
1773 const char *data) /* I - Auth data (NULL for none) */
1774{
1775 /*
1776 * Range check input...
1777 */
1778
1779 if (!http)
1780 return;
1781
1782 if (http->authstring && http->authstring != http->_authstring)
1783 free(http->authstring);
1784
1785 http->authstring = http->_authstring;
1786
1787 if (scheme)
1788 {
1789 /*
1790 * Set the current authorization string...
1791 */
1792
1793 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 1794 char *temp;
355e94dc
MS
1795
1796 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
1797 {
1798 if ((temp = malloc(len)) == NULL)
1799 len = sizeof(http->_authstring);
1800 else
1801 http->authstring = temp;
1802 }
355e94dc
MS
1803
1804 if (data)
1805 snprintf(http->authstring, len, "%s %s", scheme, data);
1806 else
1807 strlcpy(http->authstring, scheme, len);
1808 }
1809 else
1810 {
1811 /*
1812 * Clear the current authorization string...
1813 */
1814
1815 http->_authstring[0] = '\0';
1816 }
1817}
1818
1819
ef416fc2 1820/*
1821 * 'httpSetCookie()' - Set the cookie value(s)...
1822 *
426c6a59 1823 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 1824 */
1825
1826void
1827httpSetCookie(http_t *http, /* I - Connection */
1828 const char *cookie) /* I - Cookie string */
1829{
1830 if (!http)
1831 return;
1832
1833 if (http->cookie)
1834 free(http->cookie);
1835
1836 if (cookie)
1837 http->cookie = strdup(cookie);
1838 else
1839 http->cookie = NULL;
1840}
1841
1842
b423cd4c 1843/*
1844 * 'httpSetExpect()' - Set the Expect: header in a request.
1845 *
1846 * Currently only HTTP_CONTINUE is supported for the "expect" argument.
1847 *
426c6a59 1848 * @since CUPS 1.2/Mac OS X 10.5@
b423cd4c 1849 */
1850
1851void
568fa3fa 1852httpSetExpect(http_t *http, /* I - Connection to server */
b423cd4c 1853 http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
1854{
1855 if (http)
1856 http->expect = expect;
1857}
1858
1859
ef416fc2 1860/*
1861 * 'httpSetField()' - Set the value of an HTTP header.
1862 */
1863
1864void
568fa3fa 1865httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 1866 http_field_t field, /* I - Field index */
1867 const char *value) /* I - Value */
1868{
1869 if (http == NULL ||
1870 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1871 field > HTTP_FIELD_WWW_AUTHENTICATE ||
1872 value == NULL)
1873 return;
1874
1875 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
f7deaa1a 1876
f7deaa1a 1877 if (field == HTTP_FIELD_AUTHORIZATION)
1878 {
e07d4801
MS
1879 /*
1880 * Special case for Authorization: as its contents can be
1881 * longer than HTTP_MAX_VALUE
1882 */
1883
f7deaa1a 1884 if (http->field_authorization)
1885 free(http->field_authorization);
1886
1887 http->field_authorization = strdup(value);
1888 }
e07d4801
MS
1889 else if (field == HTTP_FIELD_HOST)
1890 {
1891 /*
f11a948a
MS
1892 * Special-case for Host: as we don't want a trailing "." on the hostname and
1893 * need to bracket IPv6 numeric addresses.
e07d4801
MS
1894 */
1895
178cb736
MS
1896 char *ptr = strchr(value, ':');
1897
1898 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
1899 {
1900 /*
1901 * Bracket IPv6 numeric addresses...
1902 *
1903 * This is slightly inefficient (basically copying twice), but is an edge
1904 * case and not worth optimizing...
1905 */
e07d4801 1906
f11a948a
MS
1907 snprintf(http->fields[HTTP_FIELD_HOST],
1908 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
1909 }
1910 else
e07d4801 1911 {
f11a948a
MS
1912 /*
1913 * Check for a trailing dot on the hostname...
1914 */
1915
178cb736 1916 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
1917
1918 if (*ptr)
1919 {
1920 ptr += strlen(ptr) - 1;
e07d4801 1921
f11a948a
MS
1922 if (*ptr == '.')
1923 *ptr = '\0';
1924 }
e07d4801
MS
1925 }
1926 }
ef416fc2 1927}
1928
1929
1930/*
1931 * 'httpSetLength()' - Set the content-length and content-encoding.
1932 *
426c6a59 1933 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 1934 */
1935
1936void
568fa3fa 1937httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 1938 size_t length) /* I - Length (0 for chunked) */
1939{
1940 if (!http)
1941 return;
1942
1943 if (!length)
1944 {
1945 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
1946 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
1947 }
1948 else
1949 {
1950 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
1951 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
1952 CUPS_LLFMT, CUPS_LLCAST length);
1953 }
1954}
1955
1956
1957/*
1958 * 'httpTrace()' - Send an TRACE request to the server.
1959 */
1960
1961int /* O - Status of call (0 = success) */
568fa3fa 1962httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 1963 const char *uri) /* I - URI for trace */
1964{
1965 return (http_send(http, HTTP_TRACE, uri));
1966}
1967
1968
1969/*
1970 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1971 */
1972
1973http_status_t /* O - HTTP status */
568fa3fa 1974httpUpdate(http_t *http) /* I - Connection to server */
ef416fc2 1975{
1976 char line[32768], /* Line from connection... */
1977 *value; /* Pointer to value on line */
1978 http_field_t field; /* Field index */
1979 int major, minor, /* HTTP version numbers */
1980 status; /* Request status */
1981
1982
f11a948a
MS
1983 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
1984 http_states[http->state]));
ef416fc2 1985
1986 /*
1987 * Flush pending data, if any...
1988 */
1989
1990 if (http->wused)
1991 {
e07d4801 1992 DEBUG_puts("2httpUpdate: flushing buffer...");
ef416fc2 1993
1994 if (httpFlushWrite(http) < 0)
1995 return (HTTP_ERROR);
1996 }
1997
1998 /*
1999 * If we haven't issued any commands, then there is nothing to "update"...
2000 */
2001
2002 if (http->state == HTTP_WAITING)
2003 return (HTTP_CONTINUE);
2004
2005 /*
2006 * Grab all of the lines we can from the connection...
2007 */
2008
2009 while (httpGets(line, sizeof(line), http) != NULL)
2010 {
e07d4801 2011 DEBUG_printf(("2httpUpdate: Got \"%s\"", line));
ef416fc2 2012
2013 if (line[0] == '\0')
2014 {
2015 /*
2016 * Blank line means the start of the data section (if any). Return
2017 * the result code, too...
2018 *
2019 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
2020 * Instead, we just return HTTP_CONTINUE to the caller and keep on
2021 * tryin'...
2022 */
2023
2024 if (http->status == HTTP_CONTINUE)
2025 return (http->status);
2026
2027 if (http->status < HTTP_BAD_REQUEST)
2028 http->digest_tries = 0;
2029
2030#ifdef HAVE_SSL
2031 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
2032 {
2033 if (http_setup_ssl(http) != 0)
2034 {
2035# ifdef WIN32
2036 closesocket(http->fd);
2037# else
2038 close(http->fd);
2039# endif /* WIN32 */
2040
2041 return (HTTP_ERROR);
2042 }
2043
2044 return (HTTP_CONTINUE);
2045 }
2046#endif /* HAVE_SSL */
2047
2048 httpGetLength2(http);
2049
2050 switch (http->state)
2051 {
2052 case HTTP_GET :
2053 case HTTP_POST :
2054 case HTTP_POST_RECV :
2055 case HTTP_PUT :
2056 http->state ++;
2057 case HTTP_POST_SEND :
e1d6a774 2058 case HTTP_HEAD :
ef416fc2 2059 break;
2060
2061 default :
2062 http->state = HTTP_WAITING;
2063 break;
2064 }
2065
2066 return (http->status);
2067 }
e07d4801 2068 else if (!strncmp(line, "HTTP/", 5))
ef416fc2 2069 {
2070 /*
2071 * Got the beginning of a response...
2072 */
2073
2074 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
2075 return (HTTP_ERROR);
2076
2077 http->version = (http_version_t)(major * 100 + minor);
2078 http->status = (http_status_t)status;
2079 }
2080 else if ((value = strchr(line, ':')) != NULL)
2081 {
2082 /*
2083 * Got a value...
2084 */
2085
2086 *value++ = '\0';
2087 while (isspace(*value & 255))
2088 value ++;
2089
2090 /*
2091 * Be tolerants of servers that send unknown attribute fields...
2092 */
2093
2094 if (!strcasecmp(line, "expect"))
2095 {
2096 /*
2097 * "Expect: 100-continue" or similar...
2098 */
2099
2100 http->expect = (http_status_t)atoi(value);
2101 }
2102 else if (!strcasecmp(line, "cookie"))
2103 {
2104 /*
2105 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
2106 */
2107
2108 httpSetCookie(http, value);
2109 }
2110 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
2111 {
e07d4801 2112 DEBUG_printf(("1httpUpdate: unknown field %s seen!", line));
ef416fc2 2113 continue;
2114 }
2115 else
2116 httpSetField(http, field, value);
2117 }
2118 else
2119 {
e07d4801 2120 DEBUG_printf(("1httpUpdate: Bad response line \"%s\"!", line));
ef416fc2 2121 http->status = HTTP_ERROR;
2122 return (HTTP_ERROR);
2123 }
2124 }
2125
2126 /*
2127 * See if there was an error...
2128 */
2129
2130 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
e07d4801
MS
2131 {
2132 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 2133 return (http->status);
e07d4801 2134 }
ef416fc2 2135
2136 if (http->error)
2137 {
e07d4801 2138 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 2139 strerror(http->error)));
2140 http->status = HTTP_ERROR;
2141 return (HTTP_ERROR);
2142 }
2143
2144 /*
2145 * If we haven't already returned, then there is nothing new...
2146 */
2147
2148 return (HTTP_CONTINUE);
2149}
2150
2151
38e73f87
MS
2152/*
2153 * '_httpWait()' - Wait for data available on a connection (no flush).
2154 */
2155
2156int /* O - 1 if data is available, 0 otherwise */
2157_httpWait(http_t *http, /* I - Connection to server */
2158 int msec, /* I - Milliseconds to wait */
2159 int usessl) /* I - Use SSL context? */
2160{
2161#ifdef HAVE_POLL
2162 struct pollfd pfd; /* Polled file descriptor */
2163#else
2164 fd_set input_set; /* select() input set */
2165 struct timeval timeout; /* Timeout */
2166#endif /* HAVE_POLL */
2167 int nfds; /* Result from select()/poll() */
2168
2169
e07d4801 2170 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
2171
2172 if (http->fd < 0)
2173 return (0);
2174
2175 /*
2176 * Check the SSL/TLS buffers for data first...
2177 */
2178
2179#ifdef HAVE_SSL
2180 if (http->tls && usessl)
2181 {
2182# ifdef HAVE_LIBSSL
2183 if (SSL_pending((SSL *)(http->tls)))
2184 return (1);
2185# elif defined(HAVE_GNUTLS)
2186 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2187 return (1);
2188# elif defined(HAVE_CDSASSL)
2189 size_t bytes; /* Bytes that are available */
2190
2191 if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
2192 bytes > 0)
2193 return (1);
2194# endif /* HAVE_LIBSSL */
2195 }
2196#endif /* HAVE_SSL */
2197
2198 /*
2199 * Then try doing a select() or poll() to poll the socket...
2200 */
2201
2202#ifdef HAVE_POLL
2203 pfd.fd = http->fd;
2204 pfd.events = POLLIN;
2205
e07d4801
MS
2206 while ((nfds = poll(&pfd, 1, msec)) < 0 &&
2207 (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2208
2209#else
2210 do
2211 {
2212 FD_ZERO(&input_set);
2213 FD_SET(http->fd, &input_set);
2214
e07d4801 2215 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
2216
2217 if (msec >= 0)
2218 {
2219 timeout.tv_sec = msec / 1000;
2220 timeout.tv_usec = (msec % 1000) * 1000;
2221
2222 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
2223 }
2224 else
2225 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
2226
e07d4801 2227 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
2228 }
2229# ifdef WIN32
2230 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2231# else
e07d4801 2232 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2233# endif /* WIN32 */
2234#endif /* HAVE_POLL */
2235
e07d4801 2236 DEBUG_printf(("5_httpWait: returning with nfds=%d...", nfds));
38e73f87
MS
2237
2238 return (nfds > 0);
2239}
2240
2241
ef416fc2 2242/*
2243 * 'httpWait()' - Wait for data available on a connection.
2244 *
426c6a59 2245 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2246 */
2247
2248int /* O - 1 if data is available, 0 otherwise */
568fa3fa 2249httpWait(http_t *http, /* I - Connection to server */
ef416fc2 2250 int msec) /* I - Milliseconds to wait */
2251{
2252 /*
2253 * First see if there is data in the buffer...
2254 */
2255
2256 if (http == NULL)
2257 return (0);
2258
2259 if (http->used)
2260 return (1);
2261
8ca02f3c 2262 /*
2263 * Flush pending data, if any...
2264 */
2265
2266 if (http->wused)
2267 {
2268 if (httpFlushWrite(http) < 0)
2269 return (0);
2270 }
2271
ef416fc2 2272 /*
2273 * If not, check the SSL/TLS buffers and do a select() on the connection...
2274 */
2275
38e73f87 2276 return (_httpWait(http, msec, 1));
ef416fc2 2277}
2278
2279
2280/*
2281 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 2282 *
2283 * This function is deprecated. Use the httpWrite2() function which can
2284 * write more than 2GB of data.
2285 *
2286 * @deprecated@
ef416fc2 2287 */
2288
2289int /* O - Number of bytes written */
568fa3fa 2290httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 2291 const char *buffer, /* I - Buffer for data */
2292 int length) /* I - Number of bytes to write */
2293{
a4d04587 2294 return ((int)httpWrite2(http, buffer, length));
2295}
2296
2297
2298/*
2299 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 2300 *
426c6a59 2301 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 2302 */
2303
2304ssize_t /* O - Number of bytes written */
568fa3fa 2305httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 2306 const char *buffer, /* I - Buffer for data */
2307 size_t length) /* I - Number of bytes to write */
2308{
2309 ssize_t bytes; /* Bytes written */
ef416fc2 2310
2311
e07d4801 2312 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 2313 buffer, CUPS_LLCAST length));
ef416fc2 2314
2315 /*
2316 * Range check input...
2317 */
2318
2319 if (http == NULL || buffer == NULL)
2320 return (-1);
2321
2322 /*
2323 * Mark activity on the connection...
2324 */
2325
2326 http->activity = time(NULL);
2327
2328 /*
2329 * Buffer small writes for better performance...
2330 */
2331
2332 if (length > 0)
2333 {
2334 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
2335 {
e07d4801
MS
2336 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
2337 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 2338
2339 httpFlushWrite(http);
2340 }
2341
38e73f87
MS
2342 if ((length + http->wused) <= sizeof(http->wbuffer) &&
2343 length < sizeof(http->wbuffer))
ef416fc2 2344 {
2345 /*
2346 * Write to buffer...
2347 */
2348
e07d4801 2349 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 2350 CUPS_LLCAST length));
ef416fc2 2351
2352 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 2353 http->wused += (int)length;
2354 bytes = (ssize_t)length;
ef416fc2 2355 }
2356 else
2357 {
2358 /*
2359 * Otherwise write the data directly...
2360 */
2361
e07d4801 2362 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 2363 CUPS_LLCAST length));
ef416fc2 2364
2365 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
b86bc4cf 2366 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 2367 else
b86bc4cf 2368 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 2369
e07d4801 2370 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 2371 CUPS_LLCAST bytes));
ef416fc2 2372 }
2373
2374 if (http->data_encoding == HTTP_ENCODE_LENGTH)
2375 http->data_remaining -= bytes;
2376 }
2377 else
2378 bytes = 0;
2379
2380 /*
2381 * Handle end-of-request processing...
2382 */
2383
2384 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
2385 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
2386 {
2387 /*
2388 * Finished with the transfer; unless we are sending POST or PUT
2389 * data, go idle...
2390 */
2391
e07d4801 2392 DEBUG_puts("2httpWrite: changing states...");
ef416fc2 2393
2394 if (http->wused)
2395 httpFlushWrite(http);
2396
2397 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2398 {
2399 /*
2400 * Send a 0-length chunk at the end of the request...
2401 */
2402
2403 http_write(http, "0\r\n\r\n", 5);
2404
2405 /*
2406 * Reset the data state...
2407 */
2408
2409 http->data_encoding = HTTP_ENCODE_LENGTH;
2410 http->data_remaining = 0;
2411 }
2412
2413 if (http->state == HTTP_POST_RECV)
2414 http->state ++;
2415 else if (http->state == HTTP_PUT_RECV)
2416 http->state = HTTP_STATUS;
2417 else
2418 http->state = HTTP_WAITING;
2419 }
2420
2421 return (bytes);
2422}
2423
2424
2425#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2426/*
411affcf 2427 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 2428 */
2429
2430OSStatus /* O - -1 on error, 0 on success */
2431_httpWriteCDSA(
2432 SSLConnectionRef connection, /* I - SSL/TLS connection */
2433 const void *data, /* I - Data buffer */
2434 size_t *dataLength) /* IO - Number of bytes */
2435{
411affcf 2436 OSStatus result; /* Return value */
2437 ssize_t bytes; /* Number of bytes read */
2438 http_t *http; /* HTTP connection */
e53920b9 2439
2440
411affcf 2441 http = (http_t *)connection;
ef416fc2 2442
b423cd4c 2443 do
411affcf 2444 {
2445 bytes = write(http->fd, data, *dataLength);
2446 }
e07d4801 2447 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2448
b423cd4c 2449 if (bytes == *dataLength)
411affcf 2450 {
b423cd4c 2451 result = 0;
411affcf 2452 }
b423cd4c 2453 else if (bytes >= 0)
2454 {
2455 *dataLength = bytes;
2456 result = errSSLWouldBlock;
2457 }
2458 else
2459 {
2460 *dataLength = 0;
2461
fa73b229 2462 if (errno == EAGAIN)
b423cd4c 2463 result = errSSLWouldBlock;
b423cd4c 2464 else
ed486911 2465 result = errSSLClosedAbort;
ef416fc2 2466 }
b423cd4c 2467
411affcf 2468 return (result);
ef416fc2 2469}
2470#endif /* HAVE_SSL && HAVE_CDSASSL */
2471
2472
411affcf 2473#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2474/*
2475 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
2476 */
2477
2478ssize_t /* O - Number of bytes written or -1 on error */
2479_httpWriteGNUTLS(
568fa3fa 2480 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2481 const void *data, /* I - Data buffer */
2482 size_t length) /* I - Number of bytes to write */
2483{
2484 return (send(((http_t *)ptr)->fd, data, length, 0));
2485}
2486#endif /* HAVE_SSL && HAVE_GNUTLS */
2487
2488
2489#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
2490/*
2491 * 'http_bio_ctrl()' - Control the HTTP connection.
2492 */
2493
2494static long /* O - Result/data */
2495http_bio_ctrl(BIO *h, /* I - BIO data */
2496 int cmd, /* I - Control command */
2497 long arg1, /* I - First argument */
2498 void *arg2) /* I - Second argument */
2499{
2500 switch (cmd)
2501 {
2502 default :
2503 return (0);
2504
2505 case BIO_CTRL_RESET :
2506 h->ptr = NULL;
2507 return (0);
2508
2509 case BIO_C_SET_FILE_PTR :
2510 h->ptr = arg2;
2511 h->init = 1;
2512 return (1);
2513
2514 case BIO_C_GET_FILE_PTR :
2515 if (arg2)
2516 {
2517 *((void **)arg2) = h->ptr;
2518 return (1);
2519 }
2520 else
2521 return (0);
2522
2523 case BIO_CTRL_DUP :
2524 case BIO_CTRL_FLUSH :
2525 return (1);
2526 }
2527}
2528
2529
2530/*
2531 * 'http_bio_free()' - Free OpenSSL data.
2532 */
2533
2534static int /* O - 1 on success, 0 on failure */
2535http_bio_free(BIO *h) /* I - BIO data */
2536{
2537 if (!h)
2538 return (0);
2539
2540 if (h->shutdown)
2541 {
2542 h->init = 0;
2543 h->flags = 0;
2544 }
2545
2546 return (1);
2547}
2548
2549
2550/*
2551 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
2552 */
2553
2554static int /* O - 1 on success, 0 on failure */
2555http_bio_new(BIO *h) /* I - BIO data */
2556{
2557 if (!h)
2558 return (0);
2559
2560 h->init = 0;
2561 h->num = 0;
2562 h->ptr = NULL;
2563 h->flags = 0;
2564
2565 return (1);
2566}
2567
2568
2569/*
2570 * 'http_bio_puts()' - Send a string for OpenSSL.
2571 */
2572
2573static int /* O - Bytes written */
2574http_bio_puts(BIO *h, /* I - BIO data */
2575 const char *str) /* I - String to write */
2576{
b86bc4cf 2577#ifdef WIN32
2578 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
2579#else
411affcf 2580 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 2581#endif /* WIN32 */
411affcf 2582}
2583
2584
2585/*
2586 * 'http_bio_read()' - Read data for OpenSSL.
2587 */
2588
2589static int /* O - Bytes read */
2590http_bio_read(BIO *h, /* I - BIO data */
2591 char *buf, /* I - Buffer */
2592 int size) /* I - Number of bytes to read */
2593{
2594 http_t *http; /* HTTP connection */
2595
2596
2597 http = (http_t *)h->ptr;
2598
2599 if (!http->blocking)
2600 {
2601 /*
2602 * Make sure we have data before we read...
2603 */
2604
38e73f87 2605 if (!_httpWait(http, 10000, 0))
411affcf 2606 {
b86bc4cf 2607#ifdef WIN32
2608 http->error = WSAETIMEDOUT;
2609#else
411affcf 2610 http->error = ETIMEDOUT;
b86bc4cf 2611#endif /* WIN32 */
2612
411affcf 2613 return (-1);
2614 }
2615 }
2616
2617 return (recv(http->fd, buf, size, 0));
2618}
2619
2620
2621/*
2622 * 'http_bio_write()' - Write data for OpenSSL.
2623 */
2624
2625static int /* O - Bytes written */
2626http_bio_write(BIO *h, /* I - BIO data */
2627 const char *buf, /* I - Buffer to write */
2628 int num) /* I - Number of bytes to write */
2629{
2630 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
2631}
2632#endif /* HAVE_SSL && HAVE_LIBSSL */
2633
2634
ae71f5de
MS
2635#ifdef DEBUG
2636/*
2637 * 'http_debug_hex()' - Do a hex dump of a buffer.
2638 */
2639
2640static void
2641http_debug_hex(const char *prefix, /* I - Prefix for line */
2642 const char *buffer, /* I - Buffer to dump */
2643 int bytes) /* I - Bytes to dump */
2644{
2645 int i, j, /* Looping vars */
2646 ch; /* Current character */
2647 char line[255], /* Line buffer */
2648 *start, /* Start of line after prefix */
2649 *ptr; /* Pointer into line */
2650
2651
f11a948a 2652 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
2653 return;
2654
e07d4801 2655 DEBUG_printf(("6%s: %d bytes:\n", prefix, bytes));
ae71f5de 2656
f11a948a 2657 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
2658 start = line + strlen(line);
2659
2660 for (i = 0; i < bytes; i += 16)
2661 {
2662 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
2663 sprintf(ptr, "%02X", buffer[i + j] & 255);
2664
2665 while (j < 16)
2666 {
2667 strcpy(ptr, " ");
2668 ptr += 2;
2669 j ++;
2670 }
2671
2672 strcpy(ptr, " ");
2673 ptr += 2;
2674
2675 for (j = 0; j < 16 && (i + j) < bytes; j ++)
2676 {
2677 ch = buffer[i + j] & 255;
2678
2679 if (ch < ' ' || ch >= 127)
2680 ch = '.';
2681
2682 *ptr++ = ch;
2683 }
2684
2685 *ptr = '\0';
2686 DEBUG_puts(line);
2687 }
2688}
2689#endif /* DEBUG */
2690
2691
ef416fc2 2692/*
2693 * 'http_field()' - Return the field index for a field name.
2694 */
2695
ae71f5de
MS
2696static http_field_t /* O - Field index */
2697http_field(const char *name) /* I - String name */
ef416fc2 2698{
ae71f5de 2699 int i; /* Looping var */
ef416fc2 2700
2701
2702 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2703 if (strcasecmp(name, http_fields[i]) == 0)
2704 return ((http_field_t)i);
2705
2706 return (HTTP_FIELD_UNKNOWN);
2707}
2708
2709
2710#ifdef HAVE_SSL
2711/*
2712 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2713 */
2714
2715static int /* O - Bytes read */
568fa3fa 2716http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 2717 char *buf, /* I - Buffer to store data */
2718 int len) /* I - Length of buffer */
2719{
2720# if defined(HAVE_LIBSSL)
2721 return (SSL_read((SSL *)(http->tls), buf, len));
2722
2723# elif defined(HAVE_GNUTLS)
2724 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
2725
2726# elif defined(HAVE_CDSASSL)
fa73b229 2727 int result; /* Return value */
ef416fc2 2728 OSStatus error; /* Error info */
2729 size_t processed; /* Number of bytes processed */
2730
2731
89d46774 2732 error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 2733
fa73b229 2734 switch (error)
ef416fc2 2735 {
fa73b229 2736 case 0 :
2737 result = (int)processed;
2738 break;
2739 case errSSLClosedGraceful :
2740 result = 0;
2741 break;
2742 case errSSLWouldBlock :
b423cd4c 2743 if (processed)
2744 result = (int)processed;
2745 else
2746 {
2747 result = -1;
2748 errno = EINTR;
2749 }
fa73b229 2750 break;
2751 default :
2752 errno = EPIPE;
2753 result = -1;
2754 break;
ef416fc2 2755 }
fa73b229 2756
2757 return (result);
ef416fc2 2758# endif /* HAVE_LIBSSL */
2759}
2760#endif /* HAVE_SSL */
2761
2762
2763/*
2764 * 'http_send()' - Send a request with all fields and the trailing blank line.
2765 */
2766
2767static int /* O - 0 on success, non-zero on error */
568fa3fa 2768http_send(http_t *http, /* I - Connection to server */
ef416fc2 2769 http_state_t request, /* I - Request code */
2770 const char *uri) /* I - URI */
2771{
2772 int i; /* Looping var */
839a51c8 2773 char buf[1024]; /* Encoded URI buffer */
ef416fc2 2774 static const char * const codes[] =
2775 { /* Request code strings */
2776 NULL,
2777 "OPTIONS",
2778 "GET",
2779 NULL,
2780 "HEAD",
2781 "POST",
2782 NULL,
2783 NULL,
2784 "PUT",
2785 NULL,
2786 "DELETE",
2787 "TRACE",
2788 "CLOSE"
2789 };
ef416fc2 2790
2791
e07d4801 2792 DEBUG_printf(("7http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 2793 http, codes[request], uri));
2794
2795 if (http == NULL || uri == NULL)
2796 return (-1);
2797
2798 /*
2799 * Set the User-Agent field if it isn't already...
2800 */
2801
2802 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
2803 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
2804
2805 /*
2806 * Encode the URI as needed...
2807 */
2808
839a51c8 2809 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 2810
2811 /*
2812 * See if we had an error the last time around; if so, reconnect...
2813 */
2814
2815 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 2816 if (httpReconnect(http))
2817 return (-1);
ef416fc2 2818
d09495fa 2819 /*
2820 * Flush any written data that is pending...
2821 */
2822
2823 if (http->wused)
2824 httpFlushWrite(http);
2825
ef416fc2 2826 /*
2827 * Send the request header...
2828 */
2829
d09495fa 2830 http->state = request;
2831 http->data_encoding = HTTP_ENCODE_FIELDS;
2832
ef416fc2 2833 if (request == HTTP_POST || request == HTTP_PUT)
2834 http->state ++;
2835
2836 http->status = HTTP_CONTINUE;
2837
2838#ifdef HAVE_SSL
2839 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2840 {
2841 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2842 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2843 }
2844#endif /* HAVE_SSL */
2845
2846 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2847 {
2848 http->status = HTTP_ERROR;
2849 return (-1);
2850 }
2851
2852 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2853 if (http->fields[i][0] != '\0')
2854 {
e07d4801 2855 DEBUG_printf(("9http_send: %s: %s", http_fields[i],
ae71f5de 2856 httpGetField(http, i)));
ef416fc2 2857
f7deaa1a 2858 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
2859 httpGetField(http, i)) < 1)
ef416fc2 2860 {
2861 http->status = HTTP_ERROR;
2862 return (-1);
2863 }
2864 }
2865
2866 if (http->cookie)
2867 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
2868 {
2869 http->status = HTTP_ERROR;
2870 return (-1);
2871 }
2872
b423cd4c 2873 if (http->expect == HTTP_CONTINUE &&
2874 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
2875 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
2876 {
2877 http->status = HTTP_ERROR;
2878 return (-1);
2879 }
2880
ef416fc2 2881 if (httpPrintf(http, "\r\n") < 1)
2882 {
2883 http->status = HTTP_ERROR;
2884 return (-1);
2885 }
2886
d09495fa 2887 httpFlushWrite(http);
ef416fc2 2888 httpGetLength2(http);
2889 httpClearFields(http);
2890
f7deaa1a 2891 /*
b94498cf 2892 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 2893 */
2894
bc44d920 2895 if (http->field_authorization && http->authstring &&
b94498cf 2896 (!strncmp(http->authstring, "Negotiate", 9) ||
2897 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 2898 {
2899 http->_authstring[0] = '\0';
2900
2901 if (http->authstring != http->_authstring)
2902 free(http->authstring);
2903
2904 http->authstring = http->_authstring;
2905 }
2906
ef416fc2 2907 return (0);
2908}
2909
2910
2911#ifdef HAVE_SSL
2912/*
2913 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2914 */
2915
2916static int /* O - Status of connection */
568fa3fa 2917http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 2918{
2919# ifdef HAVE_LIBSSL
89d46774 2920 SSL_CTX *context; /* Context for encryption */
2921 SSL *conn; /* Connection for encryption */
411affcf 2922 BIO *bio; /* BIO data */
ef416fc2 2923# elif defined(HAVE_GNUTLS)
89d46774 2924 http_tls_t *conn; /* TLS session object */
ef416fc2 2925 gnutls_certificate_client_credentials *credentials;
89d46774 2926 /* TLS credentials */
ef416fc2 2927# elif defined(HAVE_CDSASSL)
89d46774 2928 OSStatus error; /* Error code */
2929 http_tls_t *conn; /* CDSA connection information */
ef416fc2 2930# endif /* HAVE_LIBSSL */
2931
2932
e07d4801 2933 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 2934
2935# ifdef HAVE_LIBSSL
2936 context = SSL_CTX_new(SSLv23_client_method());
2937
2938 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2939
411affcf 2940 bio = BIO_new(_httpBIOMethods());
2941 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
2942
ef416fc2 2943 conn = SSL_new(context);
411affcf 2944 SSL_set_bio(conn, bio, bio);
ef416fc2 2945
ef416fc2 2946 if (SSL_connect(conn) != 1)
2947 {
2948# ifdef DEBUG
2949 unsigned long error; /* Error code */
2950
2951 while ((error = ERR_get_error()) != 0)
e07d4801 2952 DEBUG_printf(("8http_setup_ssl: %s", ERR_error_string(error, NULL)));
ef416fc2 2953# endif /* DEBUG */
2954
2955 SSL_CTX_free(context);
2956 SSL_free(conn);
2957
2958# ifdef WIN32
2959 http->error = WSAGetLastError();
2960# else
2961 http->error = errno;
2962# endif /* WIN32 */
2963 http->status = HTTP_ERROR;
2964
2965 return (HTTP_ERROR);
2966 }
2967
2968# elif defined(HAVE_GNUTLS)
89d46774 2969 if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
ef416fc2 2970 {
2971 http->error = errno;
2972 http->status = HTTP_ERROR;
2973
2974 return (-1);
2975 }
2976
2977 credentials = (gnutls_certificate_client_credentials *)
2978 malloc(sizeof(gnutls_certificate_client_credentials));
2979 if (credentials == NULL)
2980 {
2981 free(conn);
2982
2983 http->error = errno;
2984 http->status = HTTP_ERROR;
2985
2986 return (-1);
2987 }
2988
2989 gnutls_certificate_allocate_credentials(credentials);
2990
2991 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2992 gnutls_set_default_priority(conn->session);
2993 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
411affcf 2994 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
2995 gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
2996 gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
ef416fc2 2997
2998 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2999 {
3000 http->error = errno;
3001 http->status = HTTP_ERROR;
3002
3003 return (-1);
3004 }
3005
3006 conn->credentials = credentials;
3007
3008# elif defined(HAVE_CDSASSL)
89d46774 3009 conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
e53920b9 3010
89d46774 3011 if (conn == NULL)
3012 return (-1);
e53920b9 3013
89d46774 3014 if ((error = SSLNewContext(false, &conn->session)))
e53920b9 3015 {
89d46774 3016 http->error = error;
3017 http->status = HTTP_ERROR;
e53920b9 3018
89d46774 3019 free(conn);
3020 return (-1);
e53920b9 3021 }
ef416fc2 3022
89d46774 3023 /*
3024 * Use a union to resolve warnings about int/pointer size mismatches...
3025 */
3026
411affcf 3027 error = SSLSetConnection(conn->session, http);
89d46774 3028
3029 if (!error)
3030 error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
3031
ef416fc2 3032 if (!error)
89d46774 3033 error = SSLSetAllowsExpiredCerts(conn->session, true);
ef416fc2 3034
3035 if (!error)
89d46774 3036 error = SSLSetAllowsAnyRoot(conn->session, true);
ef416fc2 3037
ed486911 3038 if (!error)
3039 error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
3040
ef416fc2 3041 if (!error)
b423cd4c 3042 {
89d46774 3043 while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
b423cd4c 3044 usleep(1000);
3045 }
ef416fc2 3046
89d46774 3047 if (error)
ef416fc2 3048 {
3049 http->error = error;
3050 http->status = HTTP_ERROR;
3051
89d46774 3052 SSLDisposeContext(conn->session);
ef416fc2 3053
89d46774 3054 free(conn);
ef416fc2 3055
3056 return (-1);
3057 }
3058# endif /* HAVE_CDSASSL */
3059
3060 http->tls = conn;
3061 return (0);
3062}
3063#endif /* HAVE_SSL */
3064
3065
3066#ifdef HAVE_SSL
3067/*
3068 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
3069 */
3070
3071static void
568fa3fa 3072http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 3073{
3074# ifdef HAVE_LIBSSL
89d46774 3075 SSL_CTX *context; /* Context for encryption */
3076 SSL *conn; /* Connection for encryption */
ef416fc2 3077
3078
3079 conn = (SSL *)(http->tls);
3080 context = SSL_get_SSL_CTX(conn);
3081
3082 SSL_shutdown(conn);
3083 SSL_CTX_free(context);
3084 SSL_free(conn);
3085
3086# elif defined(HAVE_GNUTLS)
89d46774 3087 http_tls_t *conn; /* Encryption session */
ef416fc2 3088 gnutls_certificate_client_credentials *credentials;
89d46774 3089 /* TLS credentials */
ef416fc2 3090
3091
3092 conn = (http_tls_t *)(http->tls);
3093 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
3094
3095 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
3096 gnutls_deinit(conn->session);
3097 gnutls_certificate_free_credentials(*credentials);
3098 free(credentials);
3099 free(conn);
3100
3101# elif defined(HAVE_CDSASSL)
89d46774 3102 http_tls_t *conn; /* CDSA connection information */
3103
3104
3105 conn = (http_tls_t *)(http->tls);
3106
3107 while (SSLClose(conn->session) == errSSLWouldBlock)
b423cd4c 3108 usleep(1000);
3109
89d46774 3110 SSLDisposeContext(conn->session);
3111
3112 if (conn->certsArray)
3113 CFRelease(conn->certsArray);
3114
3115 free(conn);
ef416fc2 3116# endif /* HAVE_LIBSSL */
3117
3118 http->tls = NULL;
3119}
3120#endif /* HAVE_SSL */
3121
3122
3123#ifdef HAVE_SSL
3124/*
3125 * 'http_upgrade()' - Force upgrade to TLS encryption.
3126 */
3127
89d46774 3128static int /* O - Status of connection */
568fa3fa 3129http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 3130{
89d46774 3131 int ret; /* Return value */
3132 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 3133
3134
e07d4801 3135 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 3136
3137 /*
3138 * Copy the HTTP data to a local variable so we can do the OPTIONS
3139 * request without interfering with the existing request data...
3140 */
3141
3142 memcpy(&myhttp, http, sizeof(myhttp));
3143
3144 /*
3145 * Send an OPTIONS request to the server, requiring SSL or TLS
3146 * encryption on the link...
3147 */
3148
f7deaa1a 3149 http->field_authorization = NULL; /* Don't free the auth string */
3150
b86bc4cf 3151 httpClearFields(http);
3152 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
3153 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
ef416fc2 3154
b86bc4cf 3155 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 3156 {
3157 /*
3158 * Wait for the secure connection...
3159 */
3160
b86bc4cf 3161 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 3162 }
3163
b86bc4cf 3164 httpFlush(http);
ef416fc2 3165
3166 /*
b86bc4cf 3167 * Restore the HTTP request data...
ef416fc2 3168 */
3169
b86bc4cf 3170 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 3171 http->data_encoding = myhttp.data_encoding;
3172 http->data_remaining = myhttp.data_remaining;
3173 http->_data_remaining = myhttp._data_remaining;
3174 http->expect = myhttp.expect;
3175 http->field_authorization = myhttp.field_authorization;
bc44d920 3176 http->digest_tries = myhttp.digest_tries;
ef416fc2 3177
3178 /*
3179 * See if we actually went secure...
3180 */
3181
3182 if (!http->tls)
3183 {
3184 /*
3185 * Server does not support HTTP upgrade...
3186 */
3187
e07d4801 3188 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 3189
3190# ifdef WIN32
3191 closesocket(http->fd);
3192# else
3193 close(http->fd);
3194# endif
3195
3196 http->fd = -1;
3197
3198 return (-1);
3199 }
3200 else
3201 return (ret);
3202}
3203#endif /* HAVE_SSL */
3204
3205
ef416fc2 3206/*
3207 * 'http_write()' - Write a buffer to a HTTP connection.
3208 */
3209
3210static int /* O - Number of bytes written */
568fa3fa 3211http_write(http_t *http, /* I - Connection to server */
f11a948a
MS
3212 const char *buffer, /* I - Buffer for data */
3213 int length) /* I - Number of bytes to write */
ef416fc2 3214{
3215 int tbytes, /* Total bytes sent */
3216 bytes; /* Bytes sent */
3217
3218
f11a948a
MS
3219 http->error = 0;
3220 tbytes = 0;
ef416fc2 3221
3222 while (length > 0)
3223 {
3224#ifdef HAVE_SSL
3225 if (http->tls)
3226 bytes = http_write_ssl(http, buffer, length);
3227 else
3228#endif /* HAVE_SSL */
3229 bytes = send(http->fd, buffer, length, 0);
3230
3231 if (bytes < 0)
3232 {
3233#ifdef WIN32
3234 if (WSAGetLastError() != http->error)
3235 {
3236 http->error = WSAGetLastError();
3237 continue;
3238 }
3239#else
e07d4801 3240 if (errno == EINTR || errno == EAGAIN)
ef416fc2 3241 continue;
3242 else if (errno != http->error && errno != ECONNRESET)
3243 {
3244 http->error = errno;
3245 continue;
3246 }
3247#endif /* WIN32 */
3248
e07d4801 3249 DEBUG_puts("8http_write: error writing data...");
ef416fc2 3250
3251 return (-1);
3252 }
3253
3254 buffer += bytes;
3255 tbytes += bytes;
3256 length -= bytes;
3257 }
3258
3259#ifdef DEBUG
ae71f5de 3260 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 3261#endif /* DEBUG */
3262
3263 return (tbytes);
3264}
3265
3266
3267/*
3268 * 'http_write_chunk()' - Write a chunked buffer.
3269 */
3270
3271static int /* O - Number bytes written */
568fa3fa 3272http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 3273 const char *buffer, /* I - Buffer to write */
3274 int length) /* I - Length of buffer */
3275{
3276 char header[255]; /* Chunk header */
3277 int bytes; /* Bytes written */
3278
f11a948a 3279
e07d4801 3280 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
ef416fc2 3281 http, buffer, length));
3282
3283 /*
3284 * Write the chunk header, data, and trailer.
3285 */
3286
3287 sprintf(header, "%x\r\n", length);
b86bc4cf 3288 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 3289 {
e07d4801 3290 DEBUG_puts("8http_write_chunk: http_write of length failed!");
ef416fc2 3291 return (-1);
3292 }
3293
3294 if ((bytes = http_write(http, buffer, length)) < 0)
3295 {
e07d4801 3296 DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
ef416fc2 3297 return (-1);
3298 }
3299
3300 if (http_write(http, "\r\n", 2) < 0)
3301 {
e07d4801 3302 DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
ef416fc2 3303 return (-1);
3304 }
3305
3306 return (bytes);
3307}
3308
3309
3310#ifdef HAVE_SSL
3311/*
3312 * 'http_write_ssl()' - Write to a SSL/TLS connection.
3313 */
3314
3315static int /* O - Bytes written */
568fa3fa 3316http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3317 const char *buf, /* I - Buffer holding data */
3318 int len) /* I - Length of buffer */
3319{
3320# if defined(HAVE_LIBSSL)
3321 return (SSL_write((SSL *)(http->tls), buf, len));
3322
3323# elif defined(HAVE_GNUTLS)
3324 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
3325# elif defined(HAVE_CDSASSL)
fa73b229 3326 int result; /* Return value */
ef416fc2 3327 OSStatus error; /* Error info */
3328 size_t processed; /* Number of bytes processed */
3329
3330
89d46774 3331 error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 3332
fa73b229 3333 switch (error)
ef416fc2 3334 {
fa73b229 3335 case 0 :
3336 result = (int)processed;
3337 break;
3338 case errSSLClosedGraceful :
3339 result = 0;
3340 break;
3341 case errSSLWouldBlock :
b423cd4c 3342 if (processed)
3343 result = (int)processed;
3344 else
3345 {
3346 result = -1;
3347 errno = EINTR;
3348 }
fa73b229 3349 break;
3350 default :
3351 errno = EPIPE;
3352 result = -1;
3353 break;
ef416fc2 3354 }
fa73b229 3355
3356 return (result);
ef416fc2 3357# endif /* HAVE_LIBSSL */
3358}
3359#endif /* HAVE_SSL */
3360
3361
3362/*
b19ccc9e 3363 * End of "$Id: http.c 7850 2008-08-20 00:07:25Z mike $".
ef416fc2 3364 */