]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Send cookies in requests.
[thirdparty/cups.git] / cups / http.c
CommitLineData
3840d6ba 1/*
c9d3f842 2 * "$Id$"
3840d6ba 3 *
99de6da0 4 * HTTP routines for the Common UNIX Printing System (CUPS).
fd8b1cf8 5 *
c9d3f842 6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
fd8b1cf8 7 *
b38fb7fc 8 * These coded instructions, statements, and computer programs are the
fd8b1cf8 9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
8784b6a6 17 * 44141 Airport View Drive, Suite 204
c9d3f842 18 * Hollywood, Maryland 20636 USA
fd8b1cf8 19 *
c4dcf3cc 20 * Voice: (301) 373-9600
fd8b1cf8 21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
3840d6ba 23 *
dab1a4d8 24 * This file is subject to the Apple OS-Developed Software exception.
25 *
3840d6ba 26 * Contents:
27 *
b5cb0608 28 * httpCheck() - Check to see if there is a pending response from
29 * the server.
d40085f1 30 * httpClearCookie() - Clear the cookie value(s).
b5cb0608 31 * httpClose() - Close an HTTP connection...
32 * httpConnect() - Connect to a HTTP server.
33 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
b5cb0608 34 * httpDelete() - Send a DELETE request to the server.
ad4be4c3 35 * httpEncryption() - Set the required encryption on the link.
36 * httpFlush() - Flush data from a HTTP connection.
37 * httpFlushWrite() - Flush data in write buffer.
b5cb0608 38 * httpGet() - Send a GET request to the server.
ad4be4c3 39 * httpGetLength() - Get the amount of data remaining from the
40 * content-length or transfer-encoding fields.
1479646d 41 * httpGetLength2() - Get the amount of data remaining from the
42 * content-length or transfer-encoding fields.
ad4be4c3 43 * httpGetSubField() - Get a sub-field value.
44 * httpGets() - Get a line of text from a HTTP connection.
b5cb0608 45 * httpHead() - Send a HEAD request to the server.
ad4be4c3 46 * httpInitialize() - Initialize the HTTP interface library and set the
47 * default HTTP proxy (if any).
b5cb0608 48 * httpOptions() - Send an OPTIONS request to the server.
49 * httpPost() - Send a POST request to the server.
ad4be4c3 50 * httpPrintf() - Print a formatted string to a HTTP connection.
b5cb0608 51 * httpPut() - Send a PUT request to the server.
b5cb0608 52 * httpRead() - Read data from a HTTP connection.
fe3f3c8c 53 * _httpReadCDSA() - Read function for CDSA decryption code.
ad4be4c3 54 * httpReconnect() - Reconnect to a HTTP server...
d40085f1 55 * httpSetCookie() - Set the cookie value(s)...
ad4be4c3 56 * httpSetField() - Set the value of an HTTP header.
1479646d 57 * httpSetLength() - Set the content-length and transfer-encoding.
ad4be4c3 58 * httpTrace() - Send an TRACE request to the server.
59 * httpUpdate() - Update the current HTTP state for incoming data.
2e32fcdb 60 * httpWait() - Wait for data available on a connection.
b5cb0608 61 * httpWrite() - Write data to a HTTP connection.
fe3f3c8c 62 * _httpWriteCDSA() - Write function for CDSA encryption code.
b5cb0608 63 * http_field() - Return the field index for a field name.
ad4be4c3 64 * http_read_ssl() - Read from a SSL/TLS connection.
b5cb0608 65 * http_send() - Send a request with all fields and the trailing
66 * blank line.
bcf61448 67 * http_setup_ssl() - Set up SSL/TLS on a connection.
68 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
ad4be4c3 69 * http_upgrade() - Force upgrade to TLS encryption.
70 * http_wait() - Wait for data available on a connection.
71 * http_write() - Write data to a connection.
bcf61448 72 * http_write_ssl() - Write to a SSL/TLS connection.
3840d6ba 73 */
74
75/*
76 * Include necessary headers...
77 */
78
0a0621ae 79#include "http-private.h"
03f61bf3 80#include "globals.h"
81#include "debug.h"
3b960317 82#include <stdlib.h>
3b960317 83#include <fcntl.h>
4e8f6c6a 84#include <errno.h>
c3026ddc 85#ifndef WIN32
5356dc5a 86# include <signal.h>
63d94476 87# include <sys/time.h>
88# include <sys/resource.h>
c3026ddc 89#endif /* !WIN32 */
5356dc5a 90
a75c006a 91
42d48bd2 92/*
93 * Some operating systems have done away with the Fxxxx constants for
94 * the fcntl() call; this works around that "feature"...
95 */
96
97#ifndef FNONBLK
98# define FNONBLK O_NONBLOCK
99#endif /* !FNONBLK */
100
992cf15a 101
102/*
3a193f5e 103 * Local functions...
992cf15a 104 */
105
063e1ac7 106static http_field_t http_field(const char *name);
107static int http_send(http_t *http, http_state_t request,
108 const char *uri);
33b8a82d 109static int http_wait(http_t *http, int msec);
ad4be4c3 110static int http_write(http_t *http, const char *buffer,
111 int length);
112static int http_write_chunk(http_t *http, const char *buffer,
113 int length);
bcf61448 114#ifdef HAVE_SSL
ad4be4c3 115static int http_read_ssl(http_t *http, char *buf, int len);
bcf61448 116static int http_setup_ssl(http_t *http);
117static void http_shutdown_ssl(http_t *http);
ad4be4c3 118static int http_upgrade(http_t *http);
ad4be4c3 119static int http_write_ssl(http_t *http, const char *buf, int len);
bcf61448 120#endif /* HAVE_SSL */
3840d6ba 121
122
123/*
3a193f5e 124 * Local globals...
3840d6ba 125 */
126
6db7190f 127static const char * const http_fields[] =
3a193f5e 128 {
3a193f5e 129 "Accept-Language",
0542e38e 130 "Accept-Ranges",
3a193f5e 131 "Authorization",
3a193f5e 132 "Connection",
3a193f5e 133 "Content-Encoding",
134 "Content-Language",
135 "Content-Length",
136 "Content-Location",
137 "Content-MD5",
138 "Content-Range",
139 "Content-Type",
0d1f75a3 140 "Content-Version",
3a193f5e 141 "Date",
3a193f5e 142 "Host",
3a193f5e 143 "If-Modified-Since",
3a193f5e 144 "If-Unmodified-since",
0d1f75a3 145 "Keep-Alive",
3a193f5e 146 "Last-Modified",
0d1f75a3 147 "Link",
3a193f5e 148 "Location",
3a193f5e 149 "Range",
150 "Referer",
151 "Retry-After",
3a193f5e 152 "Transfer-Encoding",
153 "Upgrade",
154 "User-Agent",
3a193f5e 155 "WWW-Authenticate"
156 };
3840d6ba 157
158
c1918ec5 159/*
160 * 'httpCheck()' - Check to see if there is a pending response from the server.
161 */
162
163int /* O - 0 = no data, 1 = data available */
164httpCheck(http_t *http) /* I - HTTP connection */
165{
2e32fcdb 166 return (httpWait(http, 0));
c1918ec5 167}
168
169
d40085f1 170/*
171 * 'httpClearCookie()' - Clear the cookie value(s).
c94f4aa9 172 *
173 * @since CUPS 1.1.19@
d40085f1 174 */
175
176void
177httpClearCookie(http_t *http) /* I - Connection */
178{
179 if (!http)
180 return;
181
182 if (http->cookie)
183 {
184 free(http->cookie);
185 http->cookie = NULL;
186 }
187}
188
189
50146867 190/*
191 * 'httpClose()' - Close an HTTP connection...
192 */
193
194void
195httpClose(http_t *http) /* I - Connection to close */
196{
cda1bd04 197 DEBUG_printf(("httpClose(http=%p)\n", http));
198
2a0ef17a 199 if (!http)
50146867 200 return;
201
086c584d 202 httpAddrFreeList(http->addrlist);
203
2e32fcdb 204 if (http->input_set)
205 free(http->input_set);
206
d40085f1 207 if (http->cookie)
208 free(http->cookie);
209
bcf61448 210#ifdef HAVE_SSL
2a0ef17a 211 if (http->tls)
bcf61448 212 http_shutdown_ssl(http);
213#endif /* HAVE_SSL */
2a0ef17a 214
50146867 215#ifdef WIN32
216 closesocket(http->fd);
217#else
218 close(http->fd);
219#endif /* WIN32 */
220
221 free(http);
9cba63f2 222}
223
224
3840d6ba 225/*
50146867 226 * 'httpConnect()' - Connect to a HTTP server.
3840d6ba 227 */
228
c6075312 229http_t * /* O - New HTTP connection */
230httpConnect(const char *host, /* I - Host to connect to */
231 int port) /* I - Port number */
b5cb0608 232{
7c298ddc 233 http_encryption_t encryption; /* Type of encryption to use */
b5cb0608 234
235
236 /*
237 * Set the default encryption status...
238 */
239
240 if (port == 443)
7c298ddc 241 encryption = HTTP_ENCRYPT_ALWAYS;
b5cb0608 242 else
7c298ddc 243 encryption = HTTP_ENCRYPT_IF_REQUESTED;
b5cb0608 244
7c298ddc 245 return (httpConnectEncrypt(host, port, encryption));
b5cb0608 246}
247
248
249/*
250 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
251 */
252
253http_t * /* O - New HTTP connection */
7c298ddc 254httpConnectEncrypt(
255 const char *host, /* I - Host to connect to */
256 int port, /* I - Port number */
257 http_encryption_t encryption) /* I - Type of encryption to use */
3840d6ba 258{
50146867 259 http_t *http; /* New HTTP connection */
086c584d 260 http_addrlist_t *addrlist; /* Host address data */
261 char service[255]; /* Service name */
50146867 262
263
ed5ceafb 264 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)\n",
265 host ? host : "(null)", port, encryption));
cda1bd04 266
267 if (!host)
db8c0a8c 268 return (NULL);
269
0b83a6c8 270 httpInitialize();
271
50146867 272 /*
273 * Lookup the host...
274 */
275
086c584d 276 sprintf(service, "%d", port);
7e9dc5e9 277
086c584d 278 if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
8eba4f2f 279 return (NULL);
7e9dc5e9 280
3840d6ba 281 /*
3a193f5e 282 * Allocate memory for the structure...
3840d6ba 283 */
284
3a193f5e 285 http = calloc(sizeof(http_t), 1);
286 if (http == NULL)
287 return (NULL);
3840d6ba 288
a8374e1e 289 http->version = HTTP_1_1;
0542e38e 290 http->blocking = 1;
3a193f5e 291 http->activity = time(NULL);
7e9dc5e9 292 http->fd = -1;
3840d6ba 293
b5cb0608 294 /*
295 * Set the encryption status...
296 */
297
c6075312 298 if (port == 443) /* Always use encryption for https */
753453e4 299 http->encryption = HTTP_ENCRYPT_ALWAYS;
300 else
7c298ddc 301 http->encryption = encryption;
b5cb0608 302
a75c006a 303 /*
99de6da0 304 * Loop through the addresses we have until one of them connects...
a75c006a 305 */
306
def978d5 307 strlcpy(http->hostname, host, sizeof(http->hostname));
07c5adda 308
086c584d 309 /*
310 * Connect to the remote system...
311 */
99de6da0 312
086c584d 313 http->addrlist = addrlist;
99de6da0 314
086c584d 315 if (!httpReconnect(http))
316 return (http);
99de6da0 317
318 /*
9b4bc2a5 319 * Could not connect to any known address - bail out!
99de6da0 320 */
321
086c584d 322 httpAddrFreeList(addrlist);
323
9b4bc2a5 324 free(http);
086c584d 325
9b4bc2a5 326 return (NULL);
3a193f5e 327}
3840d6ba 328
3840d6ba 329
ad4be4c3 330/*
331 * 'httpDelete()' - Send a DELETE request to the server.
332 */
333
334int /* O - Status of call (0 = success) */
335httpDelete(http_t *http, /* I - HTTP data */
336 const char *uri) /* I - URI to delete */
337{
338 return (http_send(http, HTTP_DELETE, uri));
339}
340
341
ad4be4c3 342/*
343 * 'httpEncryption()' - Set the required encryption on the link.
344 */
345
346int /* O - -1 on error, 0 on success */
347httpEncryption(http_t *http, /* I - HTTP data */
348 http_encryption_t e) /* I - New encryption preference */
349{
350 DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
351
352#ifdef HAVE_SSL
353 if (!http)
354 return (0);
355
356 http->encryption = e;
357
358 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
359 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
360 return (httpReconnect(http));
361 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2a0ef17a 362 return (http_upgrade(http));
ad4be4c3 363 else
364 return (0);
365#else
366 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
367 return (-1);
368 else
369 return (0);
bcf61448 370#endif /* HAVE_SSL */
ad4be4c3 371}
a75c006a 372
ad4be4c3 373
374/*
375 * 'httpFlush()' - Flush data from a HTTP connection.
376 */
377
378void
379httpFlush(http_t *http) /* I - HTTP data */
380{
381 char buffer[8192]; /* Junk buffer */
382
383
384 DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
385
386 while (httpRead(http, buffer, sizeof(buffer)) > 0);
387}
388
389
390/*
391 * 'httpFlushWrite()' - Flush data in write buffer.
c94f4aa9 392 *
393 * @since CUPS 1.2@
ad4be4c3 394 */
395
396int /* O - Bytes written or -1 on error */
397httpFlushWrite(http_t *http) /* I - HTTP data */
398{
399 int bytes; /* Bytes written */
400
401
402 DEBUG_printf(("httpFlushWrite(http=%p)\n", http));
403
404 if (!http || !http->wused)
405 return (0);
406
407 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
408 bytes = http_write_chunk(http, http->wbuffer, http->wused);
409 else
410 bytes = http_write(http, http->wbuffer, http->wused);
411
412 http->wused = 0;
413
414 return (bytes);
415}
416
417
418/*
419 * 'httpGet()' - Send a GET request to the server.
420 */
421
422int /* O - Status of call (0 = success) */
423httpGet(http_t *http, /* I - HTTP data */
424 const char *uri) /* I - URI to get */
425{
426 return (http_send(http, HTTP_GET, uri));
427}
428
429
83e740a5 430/*
431 * 'httpGetSubField()' - Get a sub-field value.
ff84728d 432 *
433 * @deprecated@
83e740a5 434 */
435
436char * /* O - Value or NULL */
437httpGetSubField(http_t *http, /* I - HTTP data */
438 http_field_t field, /* I - Field index */
439 const char *name, /* I - Name of sub-field */
440 char *value) /* O - Value string */
ff84728d 441{
442 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
443}
444
445
446/*
447 * 'httpGetSubField2()' - Get a sub-field value.
448 *
449 * @since CUPS 1.2@
450 */
451
452char * /* O - Value or NULL */
453httpGetSubField2(http_t *http, /* I - HTTP data */
454 http_field_t field, /* I - Field index */
455 const char *name, /* I - Name of sub-field */
456 char *value, /* O - Value string */
457 int valuelen) /* I - Size of value buffer */
83e740a5 458{
459 const char *fptr; /* Pointer into field */
460 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
ff84728d 461 *ptr, /* Pointer into string buffer */
462 *end; /* End of value buffer */
83e740a5 463
ff84728d 464 DEBUG_printf(("httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)\n",
465 http, field, name, value, valuelen));
9b4bc2a5 466
ff84728d 467 if (!http || !name || !value || valuelen < 2 ||
83e740a5 468 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
ff84728d 469 field > HTTP_FIELD_WWW_AUTHENTICATE)
83e740a5 470 return (NULL);
471
ff84728d 472 end = value + valuelen - 1;
473
83e740a5 474 for (fptr = http->fields[field]; *fptr;)
475 {
476 /*
477 * Skip leading whitespace...
478 */
479
64bbab09 480 while (isspace(*fptr & 255))
83e740a5 481 fptr ++;
482
483 if (*fptr == ',')
484 {
485 fptr ++;
486 continue;
487 }
488
489 /*
490 * Get the sub-field name...
491 */
492
493 for (ptr = temp;
ff84728d 494 *fptr && *fptr != '=' && !isspace(*fptr & 255) &&
495 ptr < (temp + sizeof(temp) - 1);
83e740a5 496 *ptr++ = *fptr++);
497
498 *ptr = '\0';
499
9b4bc2a5 500 DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
501
83e740a5 502 /*
503 * Skip trailing chars up to the '='...
504 */
505
64bbab09 506 while (isspace(*fptr & 255))
83e740a5 507 fptr ++;
508
509 if (!*fptr)
510 break;
511
9b4bc2a5 512 if (*fptr != '=')
513 continue;
514
83e740a5 515 /*
516 * Skip = and leading whitespace...
517 */
518
519 fptr ++;
520
ad4be4c3 521 while (isspace(*fptr & 255))
522 fptr ++;
523
524 if (*fptr == '\"')
525 {
526 /*
527 * Read quoted string...
528 */
529
530 for (ptr = value, fptr ++;
ff84728d 531 *fptr && *fptr != '\"' && ptr < end;
ad4be4c3 532 *ptr++ = *fptr++);
533
534 *ptr = '\0';
535
536 while (*fptr && *fptr != '\"')
537 fptr ++;
538
539 if (*fptr)
540 fptr ++;
541 }
542 else
543 {
544 /*
545 * Read unquoted string...
546 */
547
548 for (ptr = value;
ff84728d 549 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < end;
ad4be4c3 550 *ptr++ = *fptr++);
551
552 *ptr = '\0';
553
554 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
555 fptr ++;
556 }
557
558 DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
559
560 /*
561 * See if this is the one...
562 */
563
ff84728d 564 if (!strcmp(name, temp))
ad4be4c3 565 return (value);
566 }
567
568 value[0] = '\0';
569
570 return (NULL);
571}
572
573
574/*
575 * 'httpGetLength()' - Get the amount of data remaining from the
576 * content-length or transfer-encoding fields.
1479646d 577 *
578 * This function is deprecated and will not return lengths larger than
579 * 2^31 - 1; use httpGetLength2() instead.
c94f4aa9 580 *
581 * @since CUPS 1.2@
1479646d 582 */
583
584int /* O - Content length */
585httpGetLength(http_t *http) /* I - HTTP data */
586{
587 /*
588 * Get the read content length and return the 32-bit value.
589 */
590
591 httpGetLength2(http);
592
593 return (http->_data_remaining);
594}
595
596
597/*
598 * 'httpGetLength2()' - Get the amount of data remaining from the
599 * content-length or transfer-encoding fields.
600 *
601 * This function returns the complete content length, even for
602 * content larger than 2^31 - 1.
ad4be4c3 603 */
604
1479646d 605off_t /* O - Content length */
606httpGetLength2(http_t *http) /* I - HTTP data */
ad4be4c3 607{
1479646d 608 DEBUG_printf(("httpGetLength2(http=%p), state=%d\n", http, http->state));
ad4be4c3 609
610 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
611 {
1479646d 612 DEBUG_puts("httpGetLength2: chunked request!");
ad4be4c3 613
614 http->data_encoding = HTTP_ENCODE_CHUNKED;
615 http->data_remaining = 0;
616 }
617 else
618 {
619 http->data_encoding = HTTP_ENCODE_LENGTH;
620
621 /*
622 * The following is a hack for HTTP servers that don't send a
623 * content-length or transfer-encoding field...
624 *
625 * If there is no content-length then the connection must close
626 * after the transfer is complete...
627 */
628
629 if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
630 http->data_remaining = 2147483647;
631 else
1479646d 632 http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
633 NULL, 10);
ad4be4c3 634
352ab579 635 DEBUG_printf(("httpGetLength2: content_length=" CUPS_LLFMT "\n",
1479646d 636 CUPS_LLCAST http->data_remaining));
ad4be4c3 637 }
638
1479646d 639 if (http->data_remaining <= INT_MAX)
640 http->_data_remaining = (int)http->data_remaining;
641 else
642 http->_data_remaining = INT_MAX;
643
ad4be4c3 644 return (http->data_remaining);
645}
646
647
648/*
649 * 'httpGets()' - Get a line of text from a HTTP connection.
650 */
651
652char * /* O - Line or NULL */
653httpGets(char *line, /* I - Line to read into */
654 int length, /* I - Max length of buffer */
655 http_t *http) /* I - HTTP data */
656{
657 char *lineptr, /* Pointer into line */
af6dfa48 658 *lineend, /* End of line */
ad4be4c3 659 *bufptr, /* Pointer into input buffer */
660 *bufend; /* Pointer to end of buffer */
af6dfa48 661 int bytes, /* Number of bytes read */
662 eol; /* End-of-line? */
ad4be4c3 663
664
665 DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
666
667 if (http == NULL || line == NULL)
668 return (NULL);
83e740a5 669
ad4be4c3 670 /*
af6dfa48 671 * Read a line from the buffer...
ad4be4c3 672 */
af6dfa48 673
674 lineptr = line;
675 lineend = line + length - 1;
676 eol = 0;
677
678 while (lineptr < lineend)
679 {
680 /*
681 * Pre-load the buffer as needed...
682 */
83e740a5 683
ad4be4c3 684#ifdef WIN32
af6dfa48 685 WSASetLastError(0);
ad4be4c3 686#else
af6dfa48 687 errno = 0;
ad4be4c3 688#endif /* WIN32 */
83e740a5 689
af6dfa48 690 while (http->used == 0)
83e740a5 691 {
692 /*
ad4be4c3 693 * No newline; see if there is more data to be read...
83e740a5 694 */
695
ad4be4c3 696 if (!http->blocking && !http_wait(http, 1000))
697 return (NULL);
83e740a5 698
ad4be4c3 699#ifdef HAVE_SSL
700 if (http->tls)
af6dfa48 701 bytes = http_read_ssl(http, http->buffer + http->used,
702 HTTP_MAX_BUFFER - http->used);
ad4be4c3 703 else
704#endif /* HAVE_SSL */
af6dfa48 705 bytes = recv(http->fd, http->buffer + http->used,
706 HTTP_MAX_BUFFER - http->used, 0);
83e740a5 707
ad4be4c3 708 DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
83e740a5 709
ad4be4c3 710 if (bytes < 0)
711 {
712 /*
713 * Nope, can't get a line this time...
714 */
9b4bc2a5 715
ad4be4c3 716#ifdef WIN32
717 if (WSAGetLastError() != http->error)
718 {
719 http->error = WSAGetLastError();
720 continue;
721 }
83e740a5 722
ad4be4c3 723 DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
724#else
725 DEBUG_printf(("httpGets: recv() error %d!\n", errno));
83e740a5 726
ad4be4c3 727 if (errno == EINTR)
728 continue;
729 else if (errno != http->error)
730 {
731 http->error = errno;
732 continue;
733 }
734#endif /* WIN32 */
83e740a5 735
ad4be4c3 736 return (NULL);
737 }
738 else if (bytes == 0)
739 {
740 http->error = EPIPE;
83e740a5 741
ad4be4c3 742 return (NULL);
743 }
83e740a5 744
ad4be4c3 745 /*
af6dfa48 746 * Yup, update the amount used...
ad4be4c3 747 */
3a193f5e 748
ad4be4c3 749 http->used += bytes;
ad4be4c3 750 }
3a193f5e 751
af6dfa48 752 /*
753 * Now copy as much of the current line as possible...
754 */
3a193f5e 755
af6dfa48 756 for (bufptr = http->buffer, bufend = http->buffer + http->used;
757 lineptr < lineend && bufptr < bufend;)
ad4be4c3 758 {
af6dfa48 759 if (*bufptr == 0x0a)
760 {
761 eol = 1;
762 bufptr ++;
763 break;
764 }
765 else if (*bufptr == 0x0d)
766 bufptr ++;
767 else
768 *lineptr++ = *bufptr++;
ad4be4c3 769 }
3a193f5e 770
af6dfa48 771 http->used -= bufptr - http->buffer;
ad4be4c3 772 if (http->used > 0)
773 memmove(http->buffer, bufptr, http->used);
3a193f5e 774
af6dfa48 775 if (eol)
776 {
777 /*
778 * End of line...
779 */
780
781 http->activity = time(NULL);
782
783 *lineptr = '\0';
784
785 DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
786
787 return (line);
788 }
ad4be4c3 789 }
50146867 790
ad4be4c3 791 DEBUG_puts("httpGets: No new line available!");
792
793 return (NULL);
3a193f5e 794}
795
796
50146867 797/*
798 * 'httpHead()' - Send a HEAD request to the server.
799 */
800
801int /* O - Status of call (0 = success) */
063e1ac7 802httpHead(http_t *http, /* I - HTTP data */
803 const char *uri) /* I - URI for head */
3a193f5e 804{
a8374e1e 805 return (http_send(http, HTTP_HEAD, uri));
3a193f5e 806}
807
808
50146867 809/*
ad4be4c3 810 * 'httpInitialize()' - Initialize the HTTP interface library and set the
811 * default HTTP proxy (if any).
50146867 812 */
813
ad4be4c3 814void
815httpInitialize(void)
3a193f5e 816{
ad4be4c3 817#ifdef HAVE_LIBSSL
818# ifndef WIN32
819 struct timeval curtime; /* Current time in microseconds */
820# endif /* !WIN32 */
821 int i; /* Looping var */
822 unsigned char data[1024]; /* Seed data */
823#endif /* HAVE_LIBSSL */
3a193f5e 824
ad4be4c3 825#ifdef WIN32
826 WSADATA winsockdata; /* WinSock data */
827 static int initialized = 0; /* Has WinSock been initialized? */
3a193f5e 828
50146867 829
ad4be4c3 830 if (!initialized)
831 WSAStartup(MAKEWORD(1,1), &winsockdata);
832#elif defined(HAVE_SIGSET)
833 sigset(SIGPIPE, SIG_IGN);
834#elif defined(HAVE_SIGACTION)
835 struct sigaction action; /* POSIX sigaction data */
0542e38e 836
3a193f5e 837
ad4be4c3 838 /*
839 * Ignore SIGPIPE signals...
840 */
3a193f5e 841
ad4be4c3 842 memset(&action, 0, sizeof(action));
843 action.sa_handler = SIG_IGN;
844 sigaction(SIGPIPE, &action, NULL);
845#else
846 signal(SIGPIPE, SIG_IGN);
847#endif /* WIN32 */
3a193f5e 848
ad4be4c3 849#ifdef HAVE_GNUTLS
850 gnutls_global_init();
851#endif /* HAVE_GNUTLS */
0542e38e 852
ad4be4c3 853#ifdef HAVE_LIBSSL
854 SSL_load_error_strings();
855 SSL_library_init();
856
857 /*
858 * Using the current time is a dubious random seed, but on some systems
859 * it is the best we can do (on others, this seed isn't even used...)
860 */
861
862#ifdef WIN32
863#else
864 gettimeofday(&curtime, NULL);
865 srand(curtime.tv_sec + curtime.tv_usec);
866#endif /* WIN32 */
867
868 for (i = 0; i < sizeof(data); i ++)
869 data[i] = rand(); /* Yes, this is a poor source of random data... */
870
871 RAND_seed(&data, sizeof(data));
872#endif /* HAVE_LIBSSL */
3840d6ba 873}
874
875
876/*
ad4be4c3 877 * 'httpOptions()' - Send an OPTIONS request to the server.
3840d6ba 878 */
879
50146867 880int /* O - Status of call (0 = success) */
ad4be4c3 881httpOptions(http_t *http, /* I - HTTP data */
882 const char *uri) /* I - URI for options */
3840d6ba 883{
ad4be4c3 884 return (http_send(http, HTTP_OPTIONS, uri));
3840d6ba 885}
886
887
69ee1496 888/*
ad4be4c3 889 * 'httpPost()' - Send a POST request to the server.
69ee1496 890 */
891
ad4be4c3 892int /* O - Status of call (0 = success) */
893httpPost(http_t *http, /* I - HTTP data */
894 const char *uri) /* I - URI for post */
69ee1496 895{
ad4be4c3 896 return (http_send(http, HTTP_POST, uri));
69ee1496 897}
898
899
e7bede57 900/*
ad4be4c3 901 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
e7bede57 902 */
903
ad4be4c3 904int /* O - Number of bytes written */
905httpPrintf(http_t *http, /* I - HTTP data */
906 const char *format, /* I - printf-style format string */
907 ...) /* I - Additional args as needed */
e7bede57 908{
ad4be4c3 909 int bytes; /* Number of bytes to write */
910 char buf[16384]; /* Buffer for formatted string */
911 va_list ap; /* Variable argument pointer */
e7bede57 912
913
ad4be4c3 914 DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
e7bede57 915
ad4be4c3 916 va_start(ap, format);
917 bytes = vsnprintf(buf, sizeof(buf), format, ap);
918 va_end(ap);
e7bede57 919
ad4be4c3 920 DEBUG_printf(("httpPrintf: %s", buf));
e7bede57 921
ad4be4c3 922 if (http->wused)
ed5ceafb 923 {
924 DEBUG_puts(" flushing existing data...");
925
926 if (httpFlushWrite(http) < 0)
927 return (-1);
928 }
e7bede57 929
ad4be4c3 930 return (http_write(http, buf, bytes));
931}
e7bede57 932
e7bede57 933
ad4be4c3 934/*
935 * 'httpPut()' - Send a PUT request to the server.
936 */
e7bede57 937
ad4be4c3 938int /* O - Status of call (0 = success) */
939httpPut(http_t *http, /* I - HTTP data */
940 const char *uri) /* I - URI to put */
941{
942 return (http_send(http, HTTP_PUT, uri));
e7bede57 943}
944
945
3840d6ba 946/*
50146867 947 * 'httpRead()' - Read data from a HTTP connection.
3840d6ba 948 */
949
50146867 950int /* O - Number of bytes read */
951httpRead(http_t *http, /* I - HTTP data */
952 char *buffer, /* I - Buffer for data */
953 int length) /* I - Maximum number of bytes */
3840d6ba 954{
2456b740 955 int bytes; /* Bytes read */
50146867 956 char len[32]; /* Length string */
3840d6ba 957
958
9b4bc2a5 959 DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n",
960 http, buffer, length));
4a73831b 961
50146867 962 if (http == NULL || buffer == NULL)
963 return (-1);
3840d6ba 964
50146867 965 http->activity = time(NULL);
3840d6ba 966
50146867 967 if (length <= 0)
968 return (0);
fd8b1cf8 969
0542e38e 970 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
5e879034 971 http->data_remaining <= 0)
50146867 972 {
5e879034 973 DEBUG_puts("httpRead: Getting chunk length...");
974
50146867 975 if (httpGets(len, sizeof(len), http) == NULL)
5e879034 976 {
977 DEBUG_puts("httpRead: Could not get length!");
50146867 978 return (0);
5e879034 979 }
3840d6ba 980
1479646d 981 http->data_remaining = strtoll(len, NULL, 16);
901b295d 982 if (http->data_remaining < 0)
983 {
984 DEBUG_puts("httpRead: Negative chunk length!");
985 return (0);
986 }
50146867 987 }
3840d6ba 988
352ab579 989 DEBUG_printf(("httpRead: data_remaining=" CUPS_LLFMT "\n",
990 CUPS_LLCAST http->data_remaining));
4a73831b 991
901b295d 992 if (http->data_remaining <= 0)
3840d6ba 993 {
50146867 994 /*
995 * A zero-length chunk ends a transfer; unless we are reading POST
996 * data, go idle...
997 */
f736c0e3 998
5e879034 999 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
4355fb2f 1000 httpGets(len, sizeof(len), http);
1001
50146867 1002 if (http->state == HTTP_POST_RECV)
1003 http->state ++;
1004 else
1005 http->state = HTTP_WAITING;
3840d6ba 1006
9b4bc2a5 1007 /*
1008 * Prevent future reads for this request...
1009 */
1010
1011 http->data_encoding = HTTP_ENCODE_LENGTH;
1012
50146867 1013 return (0);
1014 }
0542e38e 1015 else if (length > http->data_remaining)
1016 length = http->data_remaining;
50146867 1017
753453e4 1018 if (http->used == 0 && length <= 256)
1019 {
1020 /*
1021 * Buffer small reads for better performance...
1022 */
1023
e8e7f1b2 1024 if (!http->blocking && !httpWait(http, 1000))
1025 return (0);
1026
753453e4 1027 if (http->data_remaining > sizeof(http->buffer))
1028 bytes = sizeof(http->buffer);
1029 else
1030 bytes = http->data_remaining;
1031
bcf61448 1032#ifdef HAVE_SSL
753453e4 1033 if (http->tls)
bcf61448 1034 bytes = http_read_ssl(http, http->buffer, bytes);
753453e4 1035 else
bcf61448 1036#endif /* HAVE_SSL */
753453e4 1037 {
1038 DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
1039 bytes));
1040
1041 bytes = recv(http->fd, http->buffer, bytes, 0);
1042
1043 DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
1044 bytes));
1045 }
1046
1047 if (bytes > 0)
1048 http->used = bytes;
1049 else if (bytes < 0)
1050 {
c3026ddc 1051#ifdef WIN32
753453e4 1052 http->error = WSAGetLastError();
bdbaa675 1053 return (-1);
753453e4 1054#else
bdbaa675 1055 if (errno != EINTR)
1056 {
1057 http->error = errno;
1058 return (-1);
1059 }
c3026ddc 1060#endif /* WIN32 */
753453e4 1061 }
e8e7f1b2 1062 else
92e48f04 1063 {
1064 http->error = EPIPE;
753453e4 1065 return (0);
92e48f04 1066 }
753453e4 1067 }
1068
0542e38e 1069 if (http->used > 0)
50146867 1070 {
0542e38e 1071 if (length > http->used)
1072 length = http->used;
3840d6ba 1073
0542e38e 1074 bytes = length;
1075
4a73831b 1076 DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes));
1077
0542e38e 1078 memcpy(buffer, http->buffer, length);
1079 http->used -= length;
1080
1081 if (http->used > 0)
dfac1292 1082 memmove(http->buffer, http->buffer + length, http->used);
50146867 1083 }
bcf61448 1084#ifdef HAVE_SSL
a75c006a 1085 else if (http->tls)
5cbd6e60 1086 {
1087 if (!http->blocking && !httpWait(http, 1000))
1088 return (0);
1089
bcf61448 1090 bytes = http_read_ssl(http, buffer, length);
5cbd6e60 1091 }
bcf61448 1092#endif /* HAVE_SSL */
0542e38e 1093 else
4a73831b 1094 {
92e48f04 1095 if (!http->blocking && !httpWait(http, 1000))
1096 return (0);
e8e7f1b2 1097
4a73831b 1098 DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length));
81566a54 1099
1100 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
1101 if (errno != EINTR)
1102 break;
1103
4a73831b 1104 DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes));
1105 }
3840d6ba 1106
0542e38e 1107 if (bytes > 0)
1479646d 1108 {
0542e38e 1109 http->data_remaining -= bytes;
1479646d 1110
1111 if (http->data_remaining <= INT_MAX)
1112 http->_data_remaining = (int)http->data_remaining;
1113 else
1114 http->_data_remaining = INT_MAX;
1115 }
0bf5ae82 1116 else if (bytes < 0)
bdbaa675 1117 {
c3026ddc 1118#ifdef WIN32
977acbd3 1119 http->error = WSAGetLastError();
1120#else
bdbaa675 1121 if (errno == EINTR)
1122 bytes = 0;
1123 else
1124 http->error = errno;
c3026ddc 1125#endif /* WIN32 */
bdbaa675 1126 }
e8e7f1b2 1127 else
92e48f04 1128 {
1129 http->error = EPIPE;
e8e7f1b2 1130 return (0);
92e48f04 1131 }
0542e38e 1132
4355fb2f 1133 if (http->data_remaining == 0)
4a73831b 1134 {
5e879034 1135 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
4355fb2f 1136 httpGets(len, sizeof(len), http);
1137
1138 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1139 {
1140 if (http->state == HTTP_POST_RECV)
1141 http->state ++;
1142 else
1143 http->state = HTTP_WAITING;
1144 }
4a73831b 1145 }
1146
0f33610c 1147#ifdef DEBUG
1148 {
1149 int i, j, ch;
1150 printf("httpRead: Read %d bytes:\n", bytes);
1151 for (i = 0; i < bytes; i += 16)
1152 {
1153 printf(" ");
1154
1155 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1156 printf(" %02X", buffer[i + j] & 255);
1157
1158 while (j < 16)
1159 {
1160 printf(" ");
1161 j ++;
1162 }
1163
1164 printf(" ");
ad4be4c3 1165 for (j = 0; j < 16 && (i + j) < bytes; j ++)
0f33610c 1166 {
1167 ch = buffer[i + j] & 255;
1168
1169 if (ch < ' ' || ch == 127)
1170 ch = '.';
1171
1172 putchar(ch);
1173 }
1174 putchar('\n');
1175 }
1176 }
1177#endif /* DEBUG */
ad4be4c3 1178
1179 return (bytes);
50146867 1180}
1181
1182
fe3f3c8c 1183#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1184/*
1185 * '_httpReadCDSA()' - Read function for CDSA decryption code.
1186 */
1187
1188OSStatus /* O - -1 on error, 0 on success */
1189_httpReadCDSA(
1190 SSLConnectionRef connection, /* I - SSL/TLS connection */
1191 void *data, /* I - Data buffer */
1192 size_t *dataLength) /* IO - Number of bytes */
1193{
1194 ssize_t bytes; /* Number of bytes read */
1195
1196
1197 bytes = recv((int)connection, data, *dataLength, 0);
1198 if (bytes >= 0)
1199 {
1200 *dataLength = bytes;
1201 return (0);
1202 }
1203 else
1204 return (-1);
1205}
1206#endif /* HAVE_SSL && HAVE_CDSASSL */
1207
1208
50146867 1209/*
ad4be4c3 1210 * 'httpReconnect()' - Reconnect to a HTTP server...
50146867 1211 */
1212
ad4be4c3 1213int /* O - 0 on success, non-zero on failure */
1214httpReconnect(http_t *http) /* I - HTTP data */
50146867 1215{
086c584d 1216 http_addrlist_t *addr; /* Connected address */
50146867 1217
1218
ad4be4c3 1219 DEBUG_printf(("httpReconnect(http=%p)\n", http));
4a73831b 1220
ad4be4c3 1221 if (!http)
1222 return (-1);
1223
1224#ifdef HAVE_SSL
1225 if (http->tls)
1226 http_shutdown_ssl(http);
1227#endif /* HAVE_SSL */
50146867 1228
1229 /*
ad4be4c3 1230 * Close any previously open socket...
50146867 1231 */
1232
ad4be4c3 1233 if (http->fd >= 0)
c3026ddc 1234#ifdef WIN32
ad4be4c3 1235 closesocket(http->fd);
977acbd3 1236#else
ad4be4c3 1237 close(http->fd);
c3026ddc 1238#endif /* WIN32 */
f5174332 1239
50146867 1240 /*
ad4be4c3 1241 * Connect to the server...
50146867 1242 */
50146867 1243
086c584d 1244 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
584886cb 1245 {
086c584d 1246 /*
1247 * Unable to connect...
1248 */
1249
ad4be4c3 1250#ifdef WIN32
1251 http->error = WSAGetLastError();
1252#else
1253 http->error = errno;
1254#endif /* WIN32 */
1255 http->status = HTTP_ERROR;
50146867 1256
ad4be4c3 1257 return (-1);
e7bede57 1258 }
1259
086c584d 1260 http->hostaddr = &(addr->addr);
1261 http->error = 0;
1262 http->status = HTTP_CONTINUE;
e7bede57 1263
bcf61448 1264#ifdef HAVE_SSL
ad4be4c3 1265 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1266 {
1267 /*
1268 * Always do encryption via SSL.
1269 */
a75c006a 1270
ad4be4c3 1271 if (http_setup_ssl(http) != 0)
bdbaa675 1272 {
bdbaa675 1273#ifdef WIN32
ad4be4c3 1274 closesocket(http->fd);
bdbaa675 1275#else
ad4be4c3 1276 close(http->fd);
bdbaa675 1277#endif /* WIN32 */
1278
1118e338 1279 return (-1);
bdbaa675 1280 }
a75c006a 1281 }
ad4be4c3 1282 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1283 return (http_upgrade(http));
1284#endif /* HAVE_SSL */
1118e338 1285
ad4be4c3 1286 return (0);
50146867 1287}
1288
1289
50146867 1290/*
ad4be4c3 1291 * 'httpSetCookie()' - Set the cookie value(s)...
c94f4aa9 1292 *
1293 * @since CUPS 1.1.19@
50146867 1294 */
1295
ad4be4c3 1296void
1297httpSetCookie(http_t *http, /* I - Connection */
1298 const char *cookie) /* I - Cookie string */
50146867 1299{
ad4be4c3 1300 if (!http)
1301 return;
50146867 1302
ad4be4c3 1303 if (http->cookie)
1304 free(http->cookie);
50146867 1305
ad4be4c3 1306 if (cookie)
1307 http->cookie = strdup(cookie);
1308 else
1309 http->cookie = NULL;
af175786 1310}
1311
1312
1313/*
ad4be4c3 1314 * 'httpSetField()' - Set the value of an HTTP header.
af175786 1315 */
1316
ad4be4c3 1317void
1318httpSetField(http_t *http, /* I - HTTP data */
1319 http_field_t field, /* I - Field index */
1320 const char *value) /* I - Value */
af175786 1321{
ad4be4c3 1322 if (http == NULL ||
1323 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1324 field > HTTP_FIELD_WWW_AUTHENTICATE ||
1325 value == NULL)
1326 return;
50146867 1327
ad4be4c3 1328 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
50146867 1329}
1330
1331
1479646d 1332/*
1333 * 'httpSetLength()' - Set the content-length and content-encoding.
c94f4aa9 1334 *
1335 * @since CUPS 1.2@
1479646d 1336 */
1337
1338void
1339httpSetLength(http_t *http, /* I - HTTP data */
1340 off_t length) /* I - Length (0 for chunked) */
1341{
1342 if (!http || length < 0)
1343 return;
1344
1345 if (!length)
1346 {
1347 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
1348 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
1349 }
1350 else
1351 {
1352 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
1353 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
1354 CUPS_LLFMT, CUPS_LLCAST length);
1355 }
1356}
1357
1358
50146867 1359/*
ad4be4c3 1360 * 'httpTrace()' - Send an TRACE request to the server.
50146867 1361 */
1362
ad4be4c3 1363int /* O - Status of call (0 = success) */
1364httpTrace(http_t *http, /* I - HTTP data */
1365 const char *uri) /* I - URI for trace */
50146867 1366{
ad4be4c3 1367 return (http_send(http, HTTP_TRACE, uri));
50146867 1368}
1369
1370
1371/*
1372 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1373 */
1374
a8374e1e 1375http_status_t /* O - HTTP status */
50146867 1376httpUpdate(http_t *http) /* I - HTTP data */
1377{
af6dfa48 1378 char line[32768], /* Line from connection... */
a8374e1e 1379 *value; /* Pointer to value on line */
1380 http_field_t field; /* Field index */
7abb7137 1381 int major, minor, /* HTTP version numbers */
1382 status; /* Request status */
50146867 1383
50146867 1384
9b4bc2a5 1385 DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
4a73831b 1386
e7bede57 1387 /*
1388 * Flush pending data, if any...
1389 */
1390
1391 if (http->wused)
ed5ceafb 1392 {
1393 DEBUG_puts(" flushing buffer...");
1394
1395 if (httpFlushWrite(http) < 0)
1396 return (HTTP_ERROR);
1397 }
e7bede57 1398
a8374e1e 1399 /*
1400 * If we haven't issued any commands, then there is nothing to "update"...
1401 */
3840d6ba 1402
a8374e1e 1403 if (http->state == HTTP_WAITING)
1404 return (HTTP_CONTINUE);
3840d6ba 1405
1406 /*
a8374e1e 1407 * Grab all of the lines we can from the connection...
3840d6ba 1408 */
1409
a8374e1e 1410 while (httpGets(line, sizeof(line), http) != NULL)
fd8b1cf8 1411 {
9b4bc2a5 1412 DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
9ae9d67c 1413
a8374e1e 1414 if (line[0] == '\0')
fd8b1cf8 1415 {
a8374e1e 1416 /*
1417 * Blank line means the start of the data section (if any). Return
1418 * the result code, too...
11b9b0d7 1419 *
1420 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1421 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1422 * tryin'...
a8374e1e 1423 */
1424
11b9b0d7 1425 if (http->status == HTTP_CONTINUE)
1426 return (http->status);
1427
cda1bd04 1428 if (http->status < HTTP_BAD_REQUEST)
1429 http->digest_tries = 0;
1430
bcf61448 1431#ifdef HAVE_SSL
b38fb7fc 1432 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
a75c006a 1433 {
bcf61448 1434 if (http_setup_ssl(http) != 0)
a75c006a 1435 {
bcf61448 1436# ifdef WIN32
a75c006a 1437 closesocket(http->fd);
bcf61448 1438# else
a75c006a 1439 close(http->fd);
bcf61448 1440# endif /* WIN32 */
a75c006a 1441
1442 return (HTTP_ERROR);
1443 }
1444
a75c006a 1445 return (HTTP_CONTINUE);
1446 }
bcf61448 1447#endif /* HAVE_SSL */
a75c006a 1448
1479646d 1449 httpGetLength2(http);
0542e38e 1450
1451 switch (http->state)
1452 {
1453 case HTTP_GET :
1454 case HTTP_POST :
1455 case HTTP_POST_RECV :
1456 case HTTP_PUT :
1457 http->state ++;
dd63ebe2 1458 case HTTP_POST_SEND :
0542e38e 1459 break;
1460
1461 default :
1462 http->state = HTTP_WAITING;
1463 break;
1464 }
a8374e1e 1465
1466 return (http->status);
fd8b1cf8 1467 }
a8374e1e 1468 else if (strncmp(line, "HTTP/", 5) == 0)
fd8b1cf8 1469 {
1470 /*
a8374e1e 1471 * Got the beginning of a response...
fd8b1cf8 1472 */
1473
7abb7137 1474 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
a8374e1e 1475 return (HTTP_ERROR);
1476
1477 http->version = (http_version_t)(major * 100 + minor);
7abb7137 1478 http->status = (http_status_t)status;
fd8b1cf8 1479 }
a8374e1e 1480 else if ((value = strchr(line, ':')) != NULL)
3840d6ba 1481 {
a8374e1e 1482 /*
1483 * Got a value...
1484 */
3a193f5e 1485
a8374e1e 1486 *value++ = '\0';
64bbab09 1487 while (isspace(*value & 255))
a8374e1e 1488 value ++;
1489
0d1f75a3 1490 /*
1491 * Be tolerants of servers that send unknown attribute fields...
1492 */
1493
d40085f1 1494 if (!strcasecmp(line, "expect"))
1495 {
1496 /*
1497 * "Expect: 100-continue" or similar...
1498 */
1499
1500 http->expect = (http_status_t)atoi(value);
1501 }
1502 else if (!strcasecmp(line, "cookie"))
1503 {
1504 /*
1505 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
1506 */
1507
1508 httpSetCookie(http, value);
1509 }
1510 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
f4cafe91 1511 {
4a73831b 1512 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
0d1f75a3 1513 continue;
f4cafe91 1514 }
d40085f1 1515 else
1516 httpSetField(http, field, value);
3840d6ba 1517 }
a8374e1e 1518 else
f44afac9 1519 {
1520 http->status = HTTP_ERROR;
a8374e1e 1521 return (HTTP_ERROR);
f44afac9 1522 }
fd8b1cf8 1523 }
3840d6ba 1524
4e8f6c6a 1525 /*
1526 * See if there was an error...
1527 */
1528
7e736f7d 1529 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
1530 return (http->status);
1531
0bf5ae82 1532 if (http->error)
f44afac9 1533 {
4cdd993e 1534 DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
1535 strerror(http->error)));
f44afac9 1536 http->status = HTTP_ERROR;
4e8f6c6a 1537 return (HTTP_ERROR);
f44afac9 1538 }
4e8f6c6a 1539
3840d6ba 1540 /*
a8374e1e 1541 * If we haven't already returned, then there is nothing new...
3840d6ba 1542 */
1543
a8374e1e 1544 return (HTTP_CONTINUE);
3840d6ba 1545}
1546
1547
3a193f5e 1548/*
ad4be4c3 1549 * 'httpWait()' - Wait for data available on a connection.
c94f4aa9 1550 *
1551 * @since CUPS 1.1.19@
1e88d784 1552 */
1553
ad4be4c3 1554int /* O - 1 if data is available, 0 otherwise */
1555httpWait(http_t *http, /* I - HTTP data */
1556 int msec) /* I - Milliseconds to wait */
1e88d784 1557{
edd6ee99 1558 /*
ad4be4c3 1559 * First see if there is data in the buffer...
edd6ee99 1560 */
1561
ad4be4c3 1562 if (http == NULL)
1563 return (0);
992cf15a 1564
ad4be4c3 1565 if (http->used)
1566 return (1);
3840d6ba 1567
1568 /*
ad4be4c3 1569 * If not, check the SSL/TLS buffers and do a select() on the connection...
3840d6ba 1570 */
1571
ad4be4c3 1572 return (http_wait(http, msec));
1e88d784 1573}
1574
1575
1576/*
ad4be4c3 1577 * 'httpWrite()' - Write data to a HTTP connection.
1e88d784 1578 */
ad4be4c3 1579
1580int /* O - Number of bytes written */
1581httpWrite(http_t *http, /* I - HTTP data */
1582 const char *buffer, /* I - Buffer for data */
1583 int length) /* I - Number of bytes to write */
1584{
1585 int bytes; /* Bytes written */
f736c0e3 1586
f736c0e3 1587
ed5ceafb 1588 DEBUG_printf(("httpWrite(http=%p, buffer=%p, length=%d)\n", http,
1589 buffer, length));
1590
edd6ee99 1591 /*
1592 * Range check input...
1593 */
1594
ad4be4c3 1595 if (http == NULL || buffer == NULL)
1596 return (-1);
edd6ee99 1597
1598 /*
ad4be4c3 1599 * Mark activity on the connection...
edd6ee99 1600 */
1601
ad4be4c3 1602 http->activity = time(NULL);
f736c0e3 1603
ad4be4c3 1604 /*
1605 * Buffer small writes for better performance...
1606 */
f736c0e3 1607
ad4be4c3 1608 if (length > 0)
1609 {
ed5ceafb 1610 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
1611 {
1612 DEBUG_printf((" flushing buffer (wused=%d, length=%d)\n",
1613 http->wused, length));
1614
ad4be4c3 1615 httpFlushWrite(http);
ed5ceafb 1616 }
f736c0e3 1617
ad4be4c3 1618 if ((length + http->wused) <= sizeof(http->wbuffer))
1619 {
1620 /*
1621 * Write to buffer...
1622 */
f736c0e3 1623
ed5ceafb 1624 DEBUG_printf((" copying %d bytes to wbuffer...\n", length));
1625
ad4be4c3 1626 memcpy(http->wbuffer + http->wused, buffer, length);
1627 http->wused += length;
1628 bytes = length;
1629 }
1630 else
9b4bc2a5 1631 {
ad4be4c3 1632 /*
1633 * Otherwise write the data directly...
1634 */
1635
ed5ceafb 1636 DEBUG_printf((" writing %d bytes to socket...\n", length));
1637
ad4be4c3 1638 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
ed5ceafb 1639 bytes = http_write_chunk(http, buffer, length);
ad4be4c3 1640 else
ed5ceafb 1641 bytes = http_write(http, buffer, length);
1642
1643 DEBUG_printf((" wrote %d bytes...\n", bytes));
9b4bc2a5 1644 }
f736c0e3 1645
ad4be4c3 1646 if (http->data_encoding == HTTP_ENCODE_LENGTH)
1647 http->data_remaining -= bytes;
f736c0e3 1648 }
e6e44566 1649 else
1650 bytes = 0;
f736c0e3 1651
50146867 1652 /*
ad4be4c3 1653 * Handle end-of-request processing...
50146867 1654 */
f736c0e3 1655
ad4be4c3 1656 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
1657 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
1658 {
1659 /*
1660 * Finished with the transfer; unless we are sending POST or PUT
1661 * data, go idle...
1662 */
f736c0e3 1663
ad4be4c3 1664 DEBUG_puts("httpWrite: changing states...");
f736c0e3 1665
ad4be4c3 1666 if (http->wused)
1667 httpFlushWrite(http);
0542e38e 1668
ad4be4c3 1669 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1670 {
1671 /*
1672 * Send a 0-length chunk at the end of the request...
1673 */
5e879034 1674
ad4be4c3 1675 http_write(http, "0\r\n\r\n", 5);
5e879034 1676
ad4be4c3 1677 /*
1678 * Reset the data state...
1679 */
0542e38e 1680
ad4be4c3 1681 http->data_encoding = HTTP_ENCODE_LENGTH;
1682 http->data_remaining = 0;
1683 }
0542e38e 1684
ad4be4c3 1685 if (http->state == HTTP_POST_RECV)
1686 http->state ++;
1687 else if (http->state == HTTP_PUT_RECV)
1688 http->state = HTTP_STATUS;
0542e38e 1689 else
ad4be4c3 1690 http->state = HTTP_WAITING;
0542e38e 1691 }
4a73831b 1692
ad4be4c3 1693 return (bytes);
4a73831b 1694}
1695
1696
ad4be4c3 1697#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1698/*
fe3f3c8c 1699 * '_httpWriteCDSA()' - Write function for CDSA encryption code.
ad4be4c3 1700 */
1701
fe3f3c8c 1702OSStatus /* O - -1 on error, 0 on success */
1703_httpWriteCDSA(
ad4be4c3 1704 SSLConnectionRef connection, /* I - SSL/TLS connection */
fe3f3c8c 1705 const void *data, /* I - Data buffer */
ad4be4c3 1706 size_t *dataLength) /* IO - Number of bytes */
1707{
fe3f3c8c 1708 ssize_t bytes; /* Number of write written */
ad4be4c3 1709
1710
fe3f3c8c 1711 bytes = write((int)connection, data, *dataLength);
ad4be4c3 1712 if (bytes >= 0)
1713 {
1714 *dataLength = bytes;
1715 return (0);
1716 }
1717 else
1718 return (-1);
1719}
1720#endif /* HAVE_SSL && HAVE_CDSASSL */
1721
1722
fe3f3c8c 1723/*
1724 * 'http_field()' - Return the field index for a field name.
1725 */
1726
1727static http_field_t /* O - Field index */
1728http_field(const char *name) /* I - String name */
1729{
1730 int i; /* Looping var */
1731
1732
1733 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1734 if (strcasecmp(name, http_fields[i]) == 0)
1735 return ((http_field_t)i);
1736
1737 return (HTTP_FIELD_UNKNOWN);
1738}
1739
1740
ad4be4c3 1741#ifdef HAVE_SSL
1742/*
1743 * 'http_read_ssl()' - Read from a SSL/TLS connection.
1744 */
1745
1746static int /* O - Bytes read */
1747http_read_ssl(http_t *http, /* I - HTTP data */
1748 char *buf, /* I - Buffer to store data */
1749 int len) /* I - Length of buffer */
1750{
1751# if defined(HAVE_LIBSSL)
1752 return (SSL_read((SSL *)(http->tls), buf, len));
1753
1754# elif defined(HAVE_GNUTLS)
1755 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
1756
1757# elif defined(HAVE_CDSASSL)
1758 OSStatus error; /* Error info */
1759 size_t processed; /* Number of bytes processed */
1760
1761
1762 error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
1763
1764 if (error == 0)
1765 return (processed);
1766 else
1767 {
1768 http->error = error;
1769
1770 return (-1);
1771 }
1772# endif /* HAVE_LIBSSL */
1773}
1774#endif /* HAVE_SSL */
1775
1776
a8374e1e 1777/*
1778 * 'http_send()' - Send a request with all fields and the trailing blank line.
1779 */
1780
1781static int /* O - 0 on success, non-zero on error */
1782http_send(http_t *http, /* I - HTTP data */
1783 http_state_t request, /* I - Request code */
063e1ac7 1784 const char *uri) /* I - URI */
a8374e1e 1785{
1786 int i; /* Looping var */
1787 char *ptr, /* Pointer in buffer */
1788 buf[1024]; /* Encoded URI buffer */
6db7190f 1789 static const char * const codes[] =
1790 { /* Request code strings */
a8374e1e 1791 NULL,
1792 "OPTIONS",
1793 "GET",
1794 NULL,
1795 "HEAD",
1796 "POST",
1797 NULL,
1798 NULL,
1799 "PUT",
1800 NULL,
1801 "DELETE",
1802 "TRACE",
1803 "CLOSE"
1804 };
6db7190f 1805 static const char hex[] = "0123456789ABCDEF";
a8374e1e 1806 /* Hex digits */
1807
1808
9b4bc2a5 1809 DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
1810 http, codes[request], uri));
1811
a8374e1e 1812 if (http == NULL || uri == NULL)
1813 return (-1);
1814
1815 /*
1816 * Encode the URI as needed...
1817 */
1818
d2e58bfa 1819 for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
a8374e1e 1820 if (*uri <= ' ' || *uri >= 127)
1821 {
d2e58bfa 1822 if (ptr < (buf + sizeof(buf) - 1))
1823 *ptr ++ = '%';
1824 if (ptr < (buf + sizeof(buf) - 1))
1825 *ptr ++ = hex[(*uri >> 4) & 15];
1826 if (ptr < (buf + sizeof(buf) - 1))
1827 *ptr ++ = hex[*uri & 15];
a8374e1e 1828 }
1829 else
1830 *ptr ++ = *uri;
1831
1832 *ptr = '\0';
1833
f44afac9 1834 /*
1835 * See if we had an error the last time around; if so, reconnect...
1836 */
1837
1838 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
1839 httpReconnect(http);
1840
a8374e1e 1841 /*
1842 * Send the request header...
1843 */
1844
ad4be4c3 1845 http->state = request;
1846 if (request == HTTP_POST || request == HTTP_PUT)
1847 http->state ++;
1848
1849 http->status = HTTP_CONTINUE;
1850
1851#ifdef HAVE_SSL
1852 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
1853 {
1854 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
1855 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
1856 }
1857#endif /* HAVE_SSL */
1858
1859 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
1860 {
1861 http->status = HTTP_ERROR;
1862 return (-1);
1863 }
1864
1865 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1866 if (http->fields[i][0] != '\0')
1867 {
1868 DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
1869
1870 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
1871 {
1872 http->status = HTTP_ERROR;
1873 return (-1);
1874 }
1875 }
1876
f98b3a0d 1877 if (http->cookie)
1878 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
1879 {
1880 http->status = HTTP_ERROR;
1881 return (-1);
1882 }
1883
ad4be4c3 1884 if (httpPrintf(http, "\r\n") < 1)
1885 {
1886 http->status = HTTP_ERROR;
1887 return (-1);
1888 }
1889
1479646d 1890 httpGetLength2(http);
ad4be4c3 1891 httpClearFields(http);
1892
1893 return (0);
1894}
1895
1896
1897#ifdef HAVE_SSL
1898/*
1899 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
1900 */
1901
1902static int /* O - Status of connection */
1903http_setup_ssl(http_t *http) /* I - HTTP data */
1904{
1905# ifdef HAVE_LIBSSL
1906 SSL_CTX *context; /* Context for encryption */
1907 SSL *conn; /* Connection for encryption */
1908# elif defined(HAVE_GNUTLS)
1909 http_tls_t *conn; /* TLS session object */
1910 gnutls_certificate_client_credentials *credentials;
1911 /* TLS credentials */
1912# elif defined(HAVE_CDSASSL)
1913 SSLContextRef conn; /* Context for encryption */
1914 OSStatus error; /* Error info */
1915# endif /* HAVE_LIBSSL */
1916
1917
1918 DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
1919
1920# ifdef HAVE_LIBSSL
1921 context = SSL_CTX_new(SSLv23_client_method());
1922
1923 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
1924
1925 conn = SSL_new(context);
1926
1927 SSL_set_fd(conn, http->fd);
1928 if (SSL_connect(conn) != 1)
1929 {
1930# ifdef DEBUG
1931 unsigned long error; /* Error code */
1932
1933 while ((error = ERR_get_error()) != 0)
1934 printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
1935# endif /* DEBUG */
1936
1937 SSL_CTX_free(context);
1938 SSL_free(conn);
1939
1940# ifdef WIN32
1941 http->error = WSAGetLastError();
1942# else
1943 http->error = errno;
1944# endif /* WIN32 */
1945 http->status = HTTP_ERROR;
1946
1947 return (HTTP_ERROR);
1948 }
5356dc5a 1949
ad4be4c3 1950# elif defined(HAVE_GNUTLS)
1951 conn = (http_tls_t *)malloc(sizeof(http_tls_t));
c1918ec5 1952
ad4be4c3 1953 if (conn == NULL)
a75c006a 1954 {
ad4be4c3 1955 http->error = errno;
1956 http->status = HTTP_ERROR;
1957
1958 return (-1);
a75c006a 1959 }
a75c006a 1960
ad4be4c3 1961 credentials = (gnutls_certificate_client_credentials *)
1962 malloc(sizeof(gnutls_certificate_client_credentials));
1963 if (credentials == NULL)
a8374e1e 1964 {
ad4be4c3 1965 free(conn);
1966
1967 http->error = errno;
f44afac9 1968 http->status = HTTP_ERROR;
ad4be4c3 1969
f44afac9 1970 return (-1);
a8374e1e 1971 }
1972
ad4be4c3 1973 gnutls_certificate_allocate_credentials(credentials);
4a73831b 1974
ad4be4c3 1975 gnutls_init(&(conn->session), GNUTLS_CLIENT);
1976 gnutls_set_default_priority(conn->session);
1977 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
1978 gnutls_transport_set_ptr(conn->session, http->fd);
a8374e1e 1979
ad4be4c3 1980 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
f44afac9 1981 {
ad4be4c3 1982 http->error = errno;
f44afac9 1983 http->status = HTTP_ERROR;
ad4be4c3 1984
a8374e1e 1985 return (-1);
f44afac9 1986 }
a8374e1e 1987
ad4be4c3 1988 conn->credentials = credentials;
a8374e1e 1989
ad4be4c3 1990# elif defined(HAVE_CDSASSL)
1991 error = SSLNewContext(false, &conn);
a8374e1e 1992
ad4be4c3 1993 if (!error)
fe3f3c8c 1994 error = SSLSetIOFuncs(conn, _httpReadCDSA, _httpWriteCDSA);
33b8a82d 1995
ad4be4c3 1996 if (!error)
1997 error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
33b8a82d 1998
ad4be4c3 1999 if (!error)
2000 error = SSLSetAllowsExpiredCerts(conn, true);
33b8a82d 2001
ad4be4c3 2002 if (!error)
2003 error = SSLSetAllowsAnyRoot(conn, true);
9b4bc2a5 2004
ad4be4c3 2005 if (!error)
2006 error = SSLHandshake(conn);
33b8a82d 2007
ad4be4c3 2008 if (error != 0)
33b8a82d 2009 {
ad4be4c3 2010 http->error = error;
2011 http->status = HTTP_ERROR;
33b8a82d 2012
ad4be4c3 2013 SSLDisposeContext(conn);
2014
2015 close(http->fd);
2016
2017 return (-1);
33b8a82d 2018 }
ad4be4c3 2019# endif /* HAVE_CDSASSL */
2020
2021 http->tls = conn;
2022 return (0);
2023}
33b8a82d 2024#endif /* HAVE_SSL */
2025
33b8a82d 2026
ad4be4c3 2027#ifdef HAVE_SSL
2028/*
2029 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2030 */
33b8a82d 2031
ad4be4c3 2032static void
2033http_shutdown_ssl(http_t *http) /* I - HTTP data */
2034{
2035# ifdef HAVE_LIBSSL
2036 SSL_CTX *context; /* Context for encryption */
2037 SSL *conn; /* Connection for encryption */
33b8a82d 2038
33b8a82d 2039
ad4be4c3 2040 conn = (SSL *)(http->tls);
2041 context = SSL_get_SSL_CTX(conn);
7250da12 2042
ad4be4c3 2043 SSL_shutdown(conn);
2044 SSL_CTX_free(context);
2045 SSL_free(conn);
33b8a82d 2046
ad4be4c3 2047# elif defined(HAVE_GNUTLS)
2048 http_tls_t *conn; /* Encryption session */
2049 gnutls_certificate_client_credentials *credentials;
2050 /* TLS credentials */
33b8a82d 2051
33b8a82d 2052
ad4be4c3 2053 conn = (http_tls_t *)(http->tls);
2054 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
78c12025 2055
ad4be4c3 2056 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2057 gnutls_deinit(conn->session);
2058 gnutls_certificate_free_credentials(*credentials);
2059 free(credentials);
2060 free(conn);
33b8a82d 2061
ad4be4c3 2062# elif defined(HAVE_CDSASSL)
2063 SSLClose((SSLContextRef)http->tls);
2064 SSLDisposeContext((SSLContextRef)http->tls);
2065# endif /* HAVE_LIBSSL */
33b8a82d 2066
ad4be4c3 2067 http->tls = NULL;
33b8a82d 2068}
ad4be4c3 2069#endif /* HAVE_SSL */
33b8a82d 2070
2071
bcf61448 2072#ifdef HAVE_SSL
2a0ef17a 2073/*
2074 * 'http_upgrade()' - Force upgrade to TLS encryption.
2075 */
2076
2077static int /* O - Status of connection */
2078http_upgrade(http_t *http) /* I - HTTP data */
2079{
1c6682dd 2080 int ret; /* Return value */
2081 http_t myhttp; /* Local copy of HTTP data */
2082
2a0ef17a 2083
1c6682dd 2084 DEBUG_printf(("http_upgrade(%p)\n", http));
2085
2086 /*
2087 * Copy the HTTP data to a local variable so we can do the OPTIONS
2088 * request without interfering with the existing request data...
2089 */
2090
2091 memcpy(&myhttp, http, sizeof(myhttp));
2a0ef17a 2092
2093 /*
2094 * Send an OPTIONS request to the server, requiring SSL or TLS
2095 * encryption on the link...
2096 */
2097
1c6682dd 2098 httpClearFields(&myhttp);
2099 httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
2100 httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
2101
2102 if ((ret = httpOptions(&myhttp, "*")) == 0)
2103 {
2104 /*
2105 * Wait for the secure connection...
2106 */
2107
2108 while (httpUpdate(&myhttp) == HTTP_CONTINUE);
2109 }
2110
2111 httpFlush(&myhttp);
2a0ef17a 2112
2113 /*
1c6682dd 2114 * Copy the HTTP data back over, if any...
2a0ef17a 2115 */
2116
1c6682dd 2117 http->fd = myhttp.fd;
2118 http->error = myhttp.error;
2119 http->activity = myhttp.activity;
2120 http->status = myhttp.status;
2121 http->version = myhttp.version;
2122 http->keep_alive = myhttp.keep_alive;
2123 http->used = myhttp.used;
2a0ef17a 2124
1c6682dd 2125 if (http->used)
2126 memcpy(http->buffer, myhttp.buffer, http->used);
2127
2128 http->auth_type = myhttp.auth_type;
2129 http->nonce_count = myhttp.nonce_count;
2130
2131 memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
2a0ef17a 2132
1c6682dd 2133 http->tls = myhttp.tls;
2134 http->encryption = myhttp.encryption;
2135
2136 /*
2137 * See if we actually went secure...
2138 */
2139
2140 if (!http->tls)
2a0ef17a 2141 {
1c6682dd 2142 /*
2143 * Server does not support HTTP upgrade...
2144 */
2a0ef17a 2145
1c6682dd 2146 DEBUG_puts("Server does not support HTTP upgrade!");
2a0ef17a 2147
dcfcaeac 2148# ifdef WIN32
2a0ef17a 2149 closesocket(http->fd);
dcfcaeac 2150# else
2a0ef17a 2151 close(http->fd);
dcfcaeac 2152# endif
2a0ef17a 2153
1c6682dd 2154 http->fd = -1;
2155
2a0ef17a 2156 return (-1);
2157 }
1c6682dd 2158 else
2159 return (ret);
2a0ef17a 2160}
ad4be4c3 2161#endif /* HAVE_SSL */
2a0ef17a 2162
2163
3840d6ba 2164/*
ad4be4c3 2165 * 'http_wait()' - Wait for data available on a connection.
bcf61448 2166 */
2167
ad4be4c3 2168static int /* O - 1 if data is available, 0 otherwise */
2169http_wait(http_t *http, /* I - HTTP data */
2170 int msec) /* I - Milliseconds to wait */
bcf61448 2171{
ad4be4c3 2172#ifndef WIN32
2173 struct rlimit limit; /* Runtime limit */
2174#endif /* !WIN32 */
2175 struct timeval timeout; /* Timeout */
2176 int nfds; /* Result from select() */
2177 int set_size; /* Size of select set */
4cdd993e 2178
836c8127 2179
ad4be4c3 2180 DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
836c8127 2181
ad4be4c3 2182 /*
2183 * Check the SSL/TLS buffers for data first...
2184 */
bcf61448 2185
ad4be4c3 2186#ifdef HAVE_SSL
2187 if (http->tls)
bcf61448 2188 {
ad4be4c3 2189# ifdef HAVE_LIBSSL
2190 if (SSL_pending((SSL *)(http->tls)))
2191 return (1);
2192# elif defined(HAVE_GNUTLS)
2193 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2194 return (1);
2195# elif defined(HAVE_CDSASSL)
2196 size_t bytes; /* Bytes that are available */
4cdd993e 2197
ad4be4c3 2198 if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0)
2199 return (1);
2200# endif /* HAVE_LIBSSL */
2201 }
2202#endif /* HAVE_SSL */
4cdd993e 2203
ad4be4c3 2204 /*
2205 * Then try doing a select() to poll the socket...
2206 */
bcf61448 2207
ad4be4c3 2208 if (!http->input_set)
2209 {
2210#ifdef WIN32
2211 /*
2212 * Windows has a fixed-size select() structure, different (surprise,
2213 * surprise!) from all UNIX implementations. Just allocate this
2214 * fixed structure...
2215 */
bcf61448 2216
ad4be4c3 2217 http->input_set = calloc(1, sizeof(fd_set));
2218#else
2219 /*
2220 * Allocate the select() input set based upon the max number of file
2221 * descriptors available for this process...
2222 */
bcf61448 2223
ad4be4c3 2224 getrlimit(RLIMIT_NOFILE, &limit);
dcfcaeac 2225
ad4be4c3 2226 set_size = (limit.rlim_cur + 31) / 8 + 4;
2227 if (set_size < sizeof(fd_set))
2228 set_size = sizeof(fd_set);
bcf61448 2229
ad4be4c3 2230 http->input_set = calloc(1, set_size);
2231#endif /* WIN32 */
2232
2233 if (!http->input_set)
2234 return (0);
bcf61448 2235 }
dcfcaeac 2236
ad4be4c3 2237 do
bcf61448 2238 {
ad4be4c3 2239 FD_SET(http->fd, http->input_set);
bcf61448 2240
ad4be4c3 2241 if (msec >= 0)
2242 {
2243 timeout.tv_sec = msec / 1000;
2244 timeout.tv_usec = (msec % 1000) * 1000;
bcf61448 2245
ad4be4c3 2246 nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
2247 }
2248 else
2249 nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
bcf61448 2250 }
ad4be4c3 2251#ifdef WIN32
2252 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2253#else
2254 while (nfds < 0 && errno == EINTR);
2255#endif /* WIN32 */
bcf61448 2256
ad4be4c3 2257 FD_CLR(http->fd, http->input_set);
bcf61448 2258
ad4be4c3 2259 return (nfds > 0);
2260}
bcf61448 2261
bcf61448 2262
ad4be4c3 2263/*
2264 * 'http_write()' - Write a buffer to a HTTP connection.
2265 */
2266
d12c5b68 2267static int /* O - Number of bytes written */
ad4be4c3 2268http_write(http_t *http, /* I - HTTP data */
2269 const char *buffer, /* I - Buffer for data */
2270 int length) /* I - Number of bytes to write */
2271{
2272 int tbytes, /* Total bytes sent */
2273 bytes; /* Bytes sent */
bcf61448 2274
bcf61448 2275
ad4be4c3 2276 tbytes = 0;
dcfcaeac 2277
ad4be4c3 2278 while (length > 0)
2279 {
2280#ifdef HAVE_SSL
2281 if (http->tls)
2282 bytes = http_write_ssl(http, buffer, length);
2283 else
2284#endif /* HAVE_SSL */
2285 bytes = send(http->fd, buffer, length, 0);
dcfcaeac 2286
ad4be4c3 2287 if (bytes < 0)
2288 {
2289#ifdef WIN32
2290 if (WSAGetLastError() != http->error)
2291 {
2292 http->error = WSAGetLastError();
2293 continue;
2294 }
2295#else
2296 if (errno == EINTR)
2297 continue;
2298 else if (errno != http->error && errno != ECONNRESET)
2299 {
2300 http->error = errno;
2301 continue;
2302 }
2303#endif /* WIN32 */
dcfcaeac 2304
ad4be4c3 2305 DEBUG_puts("http_write: error writing data...\n");
dcfcaeac 2306
ad4be4c3 2307 return (-1);
2308 }
dcfcaeac 2309
ad4be4c3 2310 buffer += bytes;
2311 tbytes += bytes;
2312 length -= bytes;
2313 }
dcfcaeac 2314
ad4be4c3 2315#ifdef DEBUG
dcfcaeac 2316 {
ad4be4c3 2317 int i, j, ch;
2318 printf("http_write: wrote %d bytes: \n", tbytes);
2319 for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
2320 {
2321 printf(" ");
dcfcaeac 2322
ad4be4c3 2323 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
2324 printf(" %02X", buffer[i + j] & 255);
dcfcaeac 2325
ad4be4c3 2326 while (j < 16)
2327 {
2328 printf(" ");
2329 j ++;
2330 }
dcfcaeac 2331
ad4be4c3 2332 printf(" ");
2333 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
2334 {
2335 ch = buffer[i + j] & 255;
2336
2337 if (ch < ' ' || ch == 127)
2338 ch = '.';
2339
2340 putchar(ch);
2341 }
2342 putchar('\n');
2343 }
dcfcaeac 2344 }
ad4be4c3 2345#endif /* DEBUG */
bcf61448 2346
ad4be4c3 2347 return (tbytes);
bcf61448 2348}
2349
2350
bcf61448 2351/*
ad4be4c3 2352 * 'http_write_chunk()' - Write a chunked buffer.
bcf61448 2353 */
2354
d12c5b68 2355static int /* O - Number bytes written */
ad4be4c3 2356http_write_chunk(http_t *http, /* I - HTTP data */
2357 const char *buffer, /* I - Buffer to write */
2358 int length) /* I - Length of buffer */
bcf61448 2359{
ad4be4c3 2360 char header[255]; /* Chunk header */
2361 int bytes; /* Bytes written */
dcfcaeac 2362
ad4be4c3 2363 DEBUG_printf(("http_write_chunk(http=%p, buffer=%p, length=%d)\n",
2364 http, buffer, length));
dcfcaeac 2365
ad4be4c3 2366 /*
2367 * Write the chunk header, data, and trailer.
2368 */
dcfcaeac 2369
ad4be4c3 2370 sprintf(header, "%x\r\n", length);
2371 if (http_write(http, header, strlen(header)) < 0)
ed5ceafb 2372 {
2373 DEBUG_puts(" http_write of length failed!");
ad4be4c3 2374 return (-1);
ed5ceafb 2375 }
dcfcaeac 2376
ad4be4c3 2377 if ((bytes = http_write(http, buffer, length)) < 0)
ed5ceafb 2378 {
2379 DEBUG_puts(" http_write of buffer failed!");
ad4be4c3 2380 return (-1);
ed5ceafb 2381 }
dcfcaeac 2382
ad4be4c3 2383 if (http_write(http, "\r\n", 2) < 0)
ed5ceafb 2384 {
2385 DEBUG_puts(" http_write of CR LF failed!");
dcfcaeac 2386 return (-1);
ed5ceafb 2387 }
ad4be4c3 2388
2389 return (bytes);
bcf61448 2390}
2391
2392
ad4be4c3 2393#ifdef HAVE_SSL
bcf61448 2394/*
2395 * 'http_write_ssl()' - Write to a SSL/TLS connection.
2396 */
2397
2398static int /* O - Bytes written */
2399http_write_ssl(http_t *http, /* I - HTTP data */
2400 const char *buf, /* I - Buffer holding data */
2401 int len) /* I - Length of buffer */
2402{
dcfcaeac 2403# if defined(HAVE_LIBSSL)
bcf61448 2404 return (SSL_write((SSL *)(http->tls), buf, len));
dcfcaeac 2405
2406# elif defined(HAVE_GNUTLS)
bcf61448 2407 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
dcfcaeac 2408# elif defined(HAVE_CDSASSL)
2409 OSStatus error; /* Error info */
2410 size_t processed; /* Number of bytes processed */
2411
2412
2413 error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
2414
2415 if (error == 0)
2416 return (processed);
2417 else
2418 {
2419 http->error = error;
2420 return (-1);
2421 }
2422# endif /* HAVE_LIBSSL */
2423}
bcf61448 2424#endif /* HAVE_SSL */
2425
dcfcaeac 2426
bcf61448 2427/*
c9d3f842 2428 * End of "$Id$".
3840d6ba 2429 */