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