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