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