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