1/* 2 * "$Id: http.c 11780 2014-03-28 20:51:12Z msweet $" 3 * 4 * HTTP routines for CUPS. 5 * 6 * Copyright 2007-2014 by Apple Inc. 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved. 8 * 9 * This file contains Kerberos support code, copyright 2006 by Jelmer Vernooij. 10 * 11 * These coded instructions, statements, and computer programs are the 12 * property of Apple Inc. and are protected by Federal copyright 13 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 14 * which should have been included with this file. If this file is 15 * file is missing or damaged, see the license at "http://www.cups.org/". 16 * 17 * This file is subject to the Apple OS-Developed Software exception. 18 */ 19 20/* 21 * Include necessary headers... 22 */ 23 24#include "cups-private.h" 25#include <fcntl.h> 26#include <math.h> 27#ifdef WIN32 28# include <tchar.h> 29#else 30# include <signal.h> 31# include <sys/time.h> 32# include <sys/resource.h> 33#endif /* WIN32 */ 34#ifdef HAVE_POLL 35# include <poll.h> 36#endif /* HAVE_POLL */ 37 38 39/* 40 * Local functions... 41 */ 42 43#ifdef HAVE_LIBZ 44static void http_content_coding_finish(http_t *http); 45static void http_content_coding_start(http_t *http, 46 const char *value); 47#endif /* HAVE_LIBZ */ 48static http_t *http_create(const char *host, int port, 49 http_addrlist_t *addrlist, int family, 50 http_encryption_t encryption, 51 int blocking, _http_mode_t mode); 52#ifdef DEBUG 53static void http_debug_hex(const char *prefix, const char *buffer, 54 int bytes); 55#endif /* DEBUG */ 56static http_field_t http_field(const char *name); 57static ssize_t http_read(http_t *http, char *buffer, size_t length); 58static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length); 59static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length); 60static int http_send(http_t *http, http_state_t request, 61 const char *uri); 62static ssize_t http_write(http_t *http, const char *buffer, 63 size_t length); 64static ssize_t http_write_chunk(http_t *http, const char *buffer, 65 size_t length); 66#ifdef HAVE_SSL 67static int http_read_ssl(http_t *http, char *buf, int len); 68# ifdef HAVE_CDSASSL 69static int http_set_credentials(http_t *http); 70# endif /* HAVE_CDSASSL */ 71#endif /* HAVE_SSL */ 72static off_t http_set_length(http_t *http); 73static void http_set_timeout(int fd, double timeout); 74static void http_set_wait(http_t *http); 75#ifdef DEBUG 76static const char *http_state_string(http_state_t state); 77#endif /* DEBUG */ 78#ifdef HAVE_SSL 79static int http_setup_ssl(http_t *http); 80static void http_shutdown_ssl(http_t *http); 81static int http_upgrade(http_t *http); 82static int http_write_ssl(http_t *http, const char *buf, int len); 83#endif /* HAVE_SSL */ 84 85 86/* 87 * Local globals... 88 */ 89 90static const char * const http_fields[] = 91 { 92 "Accept-Language", 93 "Accept-Ranges", 94 "Authorization", 95 "Connection", 96 "Content-Encoding", 97 "Content-Language", 98 "Content-Length", 99 "Content-Location", 100 "Content-MD5", 101 "Content-Range", 102 "Content-Type", 103 "Content-Version", 104 "Date", 105 "Host", 106 "If-Modified-Since", 107 "If-Unmodified-since", 108 "Keep-Alive", 109 "Last-Modified", 110 "Link", 111 "Location", 112 "Range", 113 "Referer", 114 "Retry-After", 115 "Transfer-Encoding", 116 "Upgrade", 117 "User-Agent", 118 "WWW-Authenticate", 119 "Accept-Encoding", 120 "Allow", 121 "Server" 122 }; 123 124 125#if defined(HAVE_SSL) && defined(HAVE_LIBSSL) 126/* 127 * BIO methods for OpenSSL... 128 */ 129 130static int http_bio_write(BIO *h, const char *buf, int num); 131static int http_bio_read(BIO *h, char *buf, int size); 132static int http_bio_puts(BIO *h, const char *str); 133static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); 134static int http_bio_new(BIO *h); 135static int http_bio_free(BIO *data); 136 137static BIO_METHOD http_bio_methods = 138 { 139 BIO_TYPE_SOCKET, 140 "http", 141 http_bio_write, 142 http_bio_read, 143 http_bio_puts, 144 NULL, /* http_bio_gets, */ 145 http_bio_ctrl, 146 http_bio_new, 147 http_bio_free, 148 NULL, 149 }; 150#endif /* HAVE_SSL && HAVE_LIBSSL */ 151 152 153/* 154 * 'httpAcceptConnection()' - Accept a new HTTP client connection from the 155 * specified listening socket. 156 * 157 * @since CUPS 1.7/OS X 10.9@ 158 */ 159 160http_t * /* O - HTTP connection or @code NULL@ */ 161httpAcceptConnection(int fd, /* I - Listen socket file descriptor */ 162 int blocking) /* I - 1 if the connection should be 163 blocking, 0 otherwise */ 164{ 165 http_t *http; /* HTTP connection */ 166 http_addrlist_t addrlist; /* Dummy address list */ 167 socklen_t addrlen; /* Length of address */ 168 int val; /* Socket option value */ 169 170 171 /* 172 * Range check input... 173 */ 174 175 if (fd < 0) 176 return (NULL); 177 178 /* 179 * Create the client connection... 180 */ 181 182 memset(&addrlist, 0, sizeof(addrlist)); 183 184 if ((http = http_create(NULL, 0, &addrlist, AF_UNSPEC, 185 HTTP_ENCRYPTION_IF_REQUESTED, blocking, 186 _HTTP_MODE_SERVER)) == NULL) 187 return (NULL); 188 189 /* 190 * Accept the client and get the remote address... 191 */ 192 193 addrlen = sizeof(http_addr_t); 194 195 if ((http->fd = accept(fd, (struct sockaddr *)&(http->addrlist->addr), 196 &addrlen)) < 0) 197 { 198 _cupsSetHTTPError(HTTP_STATUS_ERROR); 199 httpClose(http); 200 201 return (NULL); 202 } 203 204 httpAddrString(&(http->addrlist->addr), http->hostname, 205 sizeof(http->hostname)); 206 207#ifdef SO_NOSIGPIPE 208 /* 209 * Disable SIGPIPE for this socket. 210 */ 211 212 val = 1; 213 setsockopt(http->fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val)); 214#endif /* SO_NOSIGPIPE */ 215 216 /* 217 * Using TCP_NODELAY improves responsiveness, especially on systems 218 * with a slow loopback interface. Since we write large buffers 219 * when sending print files and requests, there shouldn't be any 220 * performance penalty for this... 221 */ 222 223 val = 1; 224 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val)); 225 226#ifdef FD_CLOEXEC 227 /* 228 * Close this socket when starting another process... 229 */ 230 231 fcntl(http->fd, F_SETFD, FD_CLOEXEC); 232#endif /* FD_CLOEXEC */ 233 234 return (http); 235} 236 237 238/* 239 * 'httpAddCredential()' - Allocates and adds a single credential to an array. 240 * 241 * Use @code cupsArrayNew(NULL, NULL)@ to create a credentials array. 242 * 243 * @since CUPS 1.5/OS X 10.7@ 244 */ 245 246int /* O - 0 on success, -1 on error */ 247httpAddCredential( 248 cups_array_t *credentials, /* I - Credentials array */ 249 const void *data, /* I - PEM-encoded X.509 data */ 250 size_t datalen) /* I - Length of data */ 251{ 252 http_credential_t *credential; /* Credential data */ 253 254 255 if ((credential = malloc(sizeof(http_credential_t))) != NULL) 256 { 257 credential->datalen = datalen; 258 259 if ((credential->data = malloc(datalen)) != NULL) 260 { 261 memcpy(credential->data, data, datalen); 262 cupsArrayAdd(credentials, credential); 263 return (0); 264 } 265 266 free(credential); 267 } 268 269 return (-1); 270} 271 272 273#if defined(HAVE_SSL) && defined(HAVE_LIBSSL) 274/* 275 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections. 276 */ 277 278BIO_METHOD * /* O - BIO methods for OpenSSL */ 279_httpBIOMethods(void) 280{ 281 return (&http_bio_methods); 282} 283#endif /* HAVE_SSL && HAVE_LIBSSL */ 284 285 286/* 287 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection. 288 */ 289 290void 291httpBlocking(http_t *http, /* I - Connection to server */ 292 int b) /* I - 1 = blocking, 0 = non-blocking */ 293{ 294 if (http) 295 { 296 http->blocking = b; 297 http_set_wait(http); 298 } 299} 300 301 302/* 303 * 'httpCheck()' - Check to see if there is a pending response from the server. 304 */ 305 306int /* O - 0 = no data, 1 = data available */ 307httpCheck(http_t *http) /* I - Connection to server */ 308{ 309 return (httpWait(http, 0)); 310} 311 312 313/* 314 * 'httpClearCookie()' - Clear the cookie value(s). 315 * 316 * @since CUPS 1.1.19/OS X 10.3@ 317 */ 318 319void 320httpClearCookie(http_t *http) /* I - Connection to server */ 321{ 322 if (!http) 323 return; 324 325 if (http->cookie) 326 { 327 free(http->cookie); 328 http->cookie = NULL; 329 } 330} 331 332 333/* 334 * 'httpClearFields()' - Clear HTTP request fields. 335 */ 336 337void 338httpClearFields(http_t *http) /* I - Connection to server */ 339{ 340 DEBUG_printf(("httpClearFields(http=%p)", http)); 341 342 if (http) 343 { 344 memset(http->fields, 0, sizeof(http->fields)); 345 346 if (http->mode == _HTTP_MODE_CLIENT) 347 { 348 if (http->hostname[0] == '/') 349 httpSetField(http, HTTP_FIELD_HOST, "localhost"); 350 else 351 httpSetField(http, HTTP_FIELD_HOST, http->hostname); 352 } 353 354 if (http->field_authorization) 355 { 356 free(http->field_authorization); 357 http->field_authorization = NULL; 358 } 359 360 if (http->accept_encoding) 361 { 362 _cupsStrFree(http->accept_encoding); 363 http->accept_encoding = NULL; 364 } 365 366 if (http->allow) 367 { 368 _cupsStrFree(http->allow); 369 http->allow = NULL; 370 } 371 372 if (http->server) 373 { 374 _cupsStrFree(http->server); 375 http->server = NULL; 376 } 377 378 http->expect = (http_status_t)0; 379 } 380} 381 382 383/* 384 * 'httpClose()' - Close an HTTP connection. 385 */ 386 387void 388httpClose(http_t *http) /* I - Connection to server */ 389{ 390#ifdef HAVE_GSSAPI 391 OM_uint32 minor_status; /* Minor status code */ 392#endif /* HAVE_GSSAPI */ 393 394 395 DEBUG_printf(("httpClose(http=%p)", http)); 396 397 /* 398 * Range check input... 399 */ 400 401 if (!http) 402 return; 403 404 /* 405 * Close any open connection... 406 */ 407 408 _httpDisconnect(http); 409 410 /* 411 * Free memory used... 412 */ 413 414 httpAddrFreeList(http->addrlist); 415 416 if (http->cookie) 417 free(http->cookie); 418 419#ifdef HAVE_GSSAPI 420 if (http->gssctx != GSS_C_NO_CONTEXT) 421 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER); 422 423 if (http->gssname != GSS_C_NO_NAME) 424 gss_release_name(&minor_status, &http->gssname); 425#endif /* HAVE_GSSAPI */ 426 427#ifdef HAVE_AUTHORIZATION_H 428 if (http->auth_ref) 429 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults); 430#endif /* HAVE_AUTHORIZATION_H */ 431 432 httpClearFields(http); 433 434 if (http->authstring && http->authstring != http->_authstring) 435 free(http->authstring); 436 437 free(http); 438} 439 440 441/* 442 * 'httpConnect()' - Connect to a HTTP server. 443 * 444 * This function is deprecated - use @link httpConnect2@ instead. 445 * 446 * @deprecated@ 447 */ 448 449http_t * /* O - New HTTP connection */ 450httpConnect(const char *host, /* I - Host to connect to */ 451 int port) /* I - Port number */ 452{ 453 return (httpConnect2(host, port, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 454 1, 30000, NULL)); 455} 456 457 458/* 459 * 'httpConnect2()' - Connect to a HTTP server. 460 * 461 * @since CUPS 1.7/OS X 10.9@ 462 */ 463 464http_t * /* O - New HTTP connection */ 465httpConnect2( 466 const char *host, /* I - Host to connect to */ 467 int port, /* I - Port number */ 468 http_addrlist_t *addrlist, /* I - List of addresses or NULL to lookup */ 469 int family, /* I - Address family to use or @code AF_UNSPEC@ for any */ 470 http_encryption_t encryption, /* I - Type of encryption to use */ 471 int blocking, /* I - 1 for blocking connection, 0 for non-blocking */ 472 int msec, /* I - Connection timeout in milliseconds, 0 means don't connect */ 473 int *cancel) /* I - Pointer to "cancel" variable */ 474{ 475 http_t *http; /* New HTTP connection */ 476 477 478 DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, " 479 "encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port, 480 addrlist, family, encryption, blocking, msec, cancel)); 481 482 /* 483 * Create the HTTP structure... 484 */ 485 486 if ((http = http_create(host, port, addrlist, family, encryption, blocking, 487 _HTTP_MODE_CLIENT)) == NULL) 488 return (NULL); 489 490 /* 491 * Optionally connect to the remote system... 492 */ 493 494 if (msec == 0 || !httpReconnect2(http, msec, cancel)) 495 return (http); 496 497 /* 498 * Could not connect to any known address - bail out! 499 */ 500 501 httpClose(http); 502 503 return (NULL); 504} 505 506 507/* 508 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption. 509 * 510 * This function is now deprecated. Please use the @link httpConnect2@ function 511 * instead. 512 * 513 * @deprecated@ 514 */ 515 516http_t * /* O - New HTTP connection */ 517httpConnectEncrypt( 518 const char *host, /* I - Host to connect to */ 519 int port, /* I - Port number */ 520 http_encryption_t encryption) /* I - Type of encryption to use */ 521{ 522 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)", 523 host, port, encryption)); 524 525 return (httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000, 526 NULL)); 527} 528 529 530/* 531 * 'httpCopyCredentials()' - Copy the credentials associated with an encrypted 532 * connection. 533 * 534 * @since CUPS 1.5/OS X 10.7@ 535 */ 536 537int /* O - Status of call (0 = success) */ 538httpCopyCredentials( 539 http_t *http, /* I - Connection to server */ 540 cups_array_t **credentials) /* O - Array of credentials */ 541{ 542# ifdef HAVE_LIBSSL 543# elif defined(HAVE_GNUTLS) 544# elif defined(HAVE_CDSASSL) 545 OSStatus error; /* Error code */ 546 SecTrustRef peerTrust; /* Peer trust reference */ 547 CFIndex count; /* Number of credentials */ 548 SecCertificateRef secCert; /* Certificate reference */ 549 CFDataRef data; /* Certificate data */ 550 int i; /* Looping var */ 551# elif defined(HAVE_SSPISSL) 552# endif /* HAVE_LIBSSL */ 553 554 555 if (credentials) 556 *credentials = NULL; 557 558 if (!http || !http->tls || !credentials) 559 return (-1); 560 561# ifdef HAVE_LIBSSL 562 return (-1); 563 564# elif defined(HAVE_GNUTLS) 565 return (-1); 566 567# elif defined(HAVE_CDSASSL) 568 if (!(error = SSLCopyPeerTrust(http->tls, &peerTrust)) && peerTrust) 569 { 570 if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL) 571 { 572 count = SecTrustGetCertificateCount(peerTrust); 573 574 for (i = 0; i < count; i ++) 575 { 576 secCert = SecTrustGetCertificateAtIndex(peerTrust, i); 577 if ((data = SecCertificateCopyData(secCert))) 578 { 579 httpAddCredential(*credentials, CFDataGetBytePtr(data), 580 CFDataGetLength(data)); 581 CFRelease(data); 582 } 583 } 584 } 585 586 CFRelease(peerTrust); 587 } 588 589 return (error); 590 591# elif defined(HAVE_SSPISSL) 592 return (-1); 593 594# else 595 return (-1); 596# endif /* HAVE_LIBSSL */ 597} 598 599 600/* 601 * '_httpCreateCredentials()' - Create credentials in the internal format. 602 */ 603 604http_tls_credentials_t /* O - Internal credentials */ 605_httpCreateCredentials( 606 cups_array_t *credentials) /* I - Array of credentials */ 607{ 608 if (!credentials) 609 return (NULL); 610 611# ifdef HAVE_LIBSSL 612 return (NULL); 613 614# elif defined(HAVE_GNUTLS) 615 return (NULL); 616 617# elif defined(HAVE_CDSASSL) 618 CFMutableArrayRef peerCerts; /* Peer credentials reference */ 619 SecCertificateRef secCert; /* Certificate reference */ 620 CFDataRef data; /* Credential data reference */ 621 http_credential_t *credential; /* Credential data */ 622 623 624 if ((peerCerts = CFArrayCreateMutable(kCFAllocatorDefault, 625 cupsArrayCount(credentials), 626 &kCFTypeArrayCallBacks)) == NULL) 627 return (NULL); 628 629 for (credential = (http_credential_t *)cupsArrayFirst(credentials); 630 credential; 631 credential = (http_credential_t *)cupsArrayNext(credentials)) 632 { 633 if ((data = CFDataCreate(kCFAllocatorDefault, credential->data, 634 credential->datalen))) 635 { 636 if ((secCert = SecCertificateCreateWithData(kCFAllocatorDefault, data)) 637 != NULL) 638 { 639 CFArrayAppendValue(peerCerts, secCert); 640 CFRelease(secCert); 641 } 642 643 CFRelease(data); 644 } 645 } 646 647 return (peerCerts); 648 649# elif defined(HAVE_SSPISSL) 650 return (NULL); 651 652# else 653 return (NULL); 654# endif /* HAVE_LIBSSL */ 655} 656 657 658/* 659 * 'httpDelete()' - Send a DELETE request to the server. 660 */ 661 662int /* O - Status of call (0 = success) */ 663httpDelete(http_t *http, /* I - Connection to server */ 664 const char *uri) /* I - URI to delete */ 665{ 666 return (http_send(http, HTTP_STATE_DELETE, uri)); 667} 668 669 670/* 671 * '_httpDisconnect()' - Disconnect a HTTP connection. 672 */ 673 674void 675_httpDisconnect(http_t *http) /* I - Connection to server */ 676{ 677#ifdef HAVE_SSL 678 if (http->tls) 679 http_shutdown_ssl(http); 680#endif /* HAVE_SSL */ 681 682#ifdef WIN32 683 closesocket(http->fd); 684#else 685 close(http->fd); 686#endif /* WIN32 */ 687 688 http->fd = -1; 689} 690 691 692/* 693 * 'httpEncryption()' - Set the required encryption on the link. 694 */ 695 696int /* O - -1 on error, 0 on success */ 697httpEncryption(http_t *http, /* I - Connection to server */ 698 http_encryption_t e) /* I - New encryption preference */ 699{ 700 DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e)); 701 702#ifdef HAVE_SSL 703 if (!http) 704 return (0); 705 706 http->encryption = e; 707 708 if ((http->encryption == HTTP_ENCRYPTION_ALWAYS && !http->tls) || 709 (http->encryption == HTTP_ENCRYPTION_NEVER && http->tls)) 710 return (httpReconnect2(http, 30000, NULL)); 711 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls) 712 return (http_upgrade(http)); 713 else 714 return (0); 715#else 716 if (e == HTTP_ENCRYPTION_ALWAYS || e == HTTP_ENCRYPTION_REQUIRED) 717 return (-1); 718 else 719 return (0); 720#endif /* HAVE_SSL */ 721} 722 723 724/* 725 * 'httpError()' - Get the last error on a connection. 726 */ 727 728int /* O - Error code (errno) value */ 729httpError(http_t *http) /* I - Connection to server */ 730{ 731 if (http) 732 return (http->error); 733 else 734 return (EINVAL); 735} 736 737 738/* 739 * 'httpFlush()' - Flush data from a HTTP connection. 740 */ 741 742void 743httpFlush(http_t *http) /* I - Connection to server */ 744{ 745 char buffer[8192]; /* Junk buffer */ 746 int blocking; /* To block or not to block */ 747 http_state_t oldstate; /* Old state */ 748 749 750 DEBUG_printf(("httpFlush(http=%p), state=%s", http, 751 http_state_string(http->state))); 752 753 /* 754 * Nothing to do if we are in the "waiting" state... 755 */ 756 757 if (http->state == HTTP_STATE_WAITING) 758 return; 759 760 /* 761 * Temporarily set non-blocking mode so we don't get stuck in httpRead()... 762 */ 763 764 blocking = http->blocking; 765 http->blocking = 0; 766 767 /* 768 * Read any data we can... 769 */ 770 771 oldstate = http->state; 772 while (httpRead2(http, buffer, sizeof(buffer)) > 0); 773 774 /* 775 * Restore blocking and reset the connection if we didn't get all of 776 * the remaining data... 777 */ 778 779 http->blocking = blocking; 780 781 if (http->state == oldstate && http->state != HTTP_STATE_WAITING && 782 http->fd >= 0) 783 { 784 /* 785 * Didn't get the data back, so close the current connection. 786 */ 787 788#ifdef HAVE_LIBZ 789 if (http->coding) 790 http_content_coding_finish(http); 791#endif /* HAVE_LIBZ */ 792 793 DEBUG_puts("1httpFlush: Setting state to HTTP_STATE_WAITING and closing."); 794 795 http->state = HTTP_STATE_WAITING; 796 797#ifdef HAVE_SSL 798 if (http->tls) 799 http_shutdown_ssl(http); 800#endif /* HAVE_SSL */ 801 802#ifdef WIN32 803 closesocket(http->fd); 804#else 805 close(http->fd); 806#endif /* WIN32 */ 807 808 http->fd = -1; 809 } 810} 811 812 813/* 814 * 'httpFlushWrite()' - Flush data in write buffer. 815 * 816 * @since CUPS 1.2/OS X 10.5@ 817 */ 818 819int /* O - Bytes written or -1 on error */ 820httpFlushWrite(http_t *http) /* I - Connection to server */ 821{ 822 int bytes; /* Bytes written */ 823 824 825 DEBUG_printf(("httpFlushWrite(http=%p) data_encoding=%d", http, 826 http ? http->data_encoding : -1)); 827 828 if (!http || !http->wused) 829 { 830 DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." : 831 "1httpFlushWrite: No connection."); 832 return (0); 833 } 834 835 if (http->data_encoding == HTTP_ENCODING_CHUNKED) 836 bytes = http_write_chunk(http, http->wbuffer, http->wused); 837 else 838 bytes = http_write(http, http->wbuffer, http->wused); 839 840 http->wused = 0; 841 842 DEBUG_printf(("1httpFlushWrite: Returning %d, errno=%d.", bytes, errno)); 843 844 return (bytes); 845} 846 847 848/* 849 * '_httpFreeCredentials()' - Free internal credentials. 850 */ 851 852void 853_httpFreeCredentials( 854 http_tls_credentials_t credentials) /* I - Internal credentials */ 855{ 856 if (!credentials) 857 return; 858 859#ifdef HAVE_LIBSSL 860 (void)credentials; 861 862#elif defined(HAVE_GNUTLS) 863 (void)credentials; 864 865#elif defined(HAVE_CDSASSL) 866 CFRelease(credentials); 867 868#elif defined(HAVE_SSPISSL) 869 (void)credentials; 870 871#endif /* HAVE_LIBSSL */ 872} 873 874 875/* 876 * 'httpFreeCredentials()' - Free an array of credentials. 877 */ 878 879void 880httpFreeCredentials( 881 cups_array_t *credentials) /* I - Array of credentials */ 882{ 883 http_credential_t *credential; /* Credential */ 884 885 886 for (credential = (http_credential_t *)cupsArrayFirst(credentials); 887 credential; 888 credential = (http_credential_t *)cupsArrayNext(credentials)) 889 { 890 cupsArrayRemove(credentials, credential); 891 free((void *)credential->data); 892 free(credential); 893 } 894 895 cupsArrayDelete(credentials); 896} 897 898 899/* 900 * 'httpGet()' - Send a GET request to the server. 901 */ 902 903int /* O - Status of call (0 = success) */ 904httpGet(http_t *http, /* I - Connection to server */ 905 const char *uri) /* I - URI to get */ 906{ 907 return (http_send(http, HTTP_STATE_GET, uri)); 908} 909 910 911/* 912 * 'httpGetAuthString()' - Get the current authorization string. 913 * 914 * The authorization string is set by cupsDoAuthentication() and 915 * httpSetAuthString(). Use httpGetAuthString() to retrieve the 916 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION 917 * value. 918 * 919 * @since CUPS 1.3/OS X 10.5@ 920 */ 921 922char * /* O - Authorization string */ 923httpGetAuthString(http_t *http) /* I - Connection to server */ 924{ 925 if (http) 926 return (http->authstring); 927 else 928 return (NULL); 929} 930 931 932/* 933 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection. 934 * 935 * @since CUPS 1.2/OS X 10.5@ 936 */ 937 938int /* O - 1 if blocking, 0 if non-blocking */ 939httpGetBlocking(http_t *http) /* I - Connection to server */ 940{ 941 return (http ? http->blocking : 0); 942} 943 944 945/* 946 * 'httpGetContentEncoding()' - Get a common content encoding, if any, between 947 * the client and server. 948 * 949 * This function uses the value of the Accepts-Encoding HTTP header and must be 950 * called after receiving a response from the server or a request from the 951 * client. The value returned can be use in subsequent requests (for clients) 952 * or in the response (for servers) in order to compress the content stream. 953 * 954 * @since CUPS 1.7/OS X 10.9@ 955 */ 956 957const char * /* O - Content-Coding value or 958 @code NULL@ for the identity 959 coding. */ 960httpGetContentEncoding(http_t *http) /* I - Connection to client/server */ 961{ 962#ifdef HAVE_LIBZ 963 if (http && http->accept_encoding) 964 { 965 int i; /* Looping var */ 966 char temp[HTTP_MAX_VALUE], /* Copy of Accepts-Encoding value */ 967 *start, /* Start of coding value */ 968 *end; /* End of coding value */ 969 double qvalue; /* "qvalue" for coding */ 970 struct lconv *loc = localeconv(); /* Locale data */ 971 static const char * const codings[] = 972 { /* Supported content codings */ 973 "deflate", 974 "gzip", 975 "x-deflate", 976 "x-gzip" 977 }; 978 979 strlcpy(temp, http->accept_encoding, sizeof(temp)); 980 981 for (start = temp; *start; start = end) 982 { 983 /* 984 * Find the end of the coding name... 985 */ 986 987 qvalue = 1.0; 988 end = start; 989 while (*end && *end != ';' && *end != ',' && !isspace(*end & 255)) 990 end ++; 991 992 if (*end == ';') 993 { 994 /* 995 * Grab the qvalue as needed... 996 */ 997 998 if (!strncmp(end, ";q=", 3)) 999 qvalue = _cupsStrScand(end + 3, NULL, loc); 1000 1001 /* 1002 * Skip past all attributes... 1003 */ 1004 1005 *end++ = '\0'; 1006 while (*end && *end != ',' && !isspace(*end & 255)) 1007 end ++; 1008 } 1009 else if (*end) 1010 *end++ = '\0'; 1011 1012 while (*end && isspace(*end & 255)) 1013 end ++; 1014 1015 /* 1016 * Check value if it matches something we support... 1017 */ 1018 1019 if (qvalue <= 0.0) 1020 continue; 1021 1022 for (i = 0; i < (int)(sizeof(codings) / sizeof(codings[0])); i ++) 1023 if (!strcmp(start, codings[i])) 1024 return (codings[i]); 1025 } 1026 } 1027#endif /* HAVE_LIBZ */ 1028 1029 return (NULL); 1030} 1031 1032 1033/* 1034 * 'httpGetCookie()' - Get any cookie data from the response. 1035 * 1036 * @since CUPS 1.1.19/OS X 10.3@ 1037 */ 1038 1039const char * /* O - Cookie data or NULL */ 1040httpGetCookie(http_t *http) /* I - HTTP connecion */ 1041{ 1042 return (http ? http->cookie : NULL); 1043} 1044 1045 1046/* 1047 * 'httpGetExpect()' - Get the value of the Expect header, if any. 1048 * 1049 * Returns @code HTTP_STATUS_NONE@ if there is no Expect header, otherwise 1050 * returns the expected HTTP status code, typically @code HTTP_STATUS_CONTINUE@. 1051 * 1052 * @since CUPS 1.7/OS X 10.9@ 1053 */ 1054 1055http_status_t /* O - Expect: status, if any */ 1056httpGetExpect(http_t *http) /* I - Connection to client */ 1057{ 1058 if (!http) 1059 return (HTTP_STATUS_ERROR); 1060 else 1061 return (http->expect); 1062} 1063 1064 1065/* 1066 * 'httpGetFd()' - Get the file descriptor associated with a connection. 1067 * 1068 * @since CUPS 1.2/OS X 10.5@ 1069 */ 1070 1071int /* O - File descriptor or -1 if none */ 1072httpGetFd(http_t *http) /* I - Connection to server */ 1073{ 1074 return (http ? http->fd : -1); 1075} 1076 1077 1078/* 1079 * 'httpGetField()' - Get a field value from a request/response. 1080 */ 1081 1082const char * /* O - Field value */ 1083httpGetField(http_t *http, /* I - Connection to server */ 1084 http_field_t field) /* I - Field to get */ 1085{ 1086 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) 1087 return (NULL); 1088 1089 switch (field) 1090 { 1091 case HTTP_FIELD_ACCEPT_ENCODING : 1092 return (http->accept_encoding); 1093 1094 case HTTP_FIELD_ALLOW : 1095 return (http->allow); 1096 1097 case HTTP_FIELD_SERVER : 1098 return (http->server); 1099 1100 case HTTP_FIELD_AUTHORIZATION : 1101 if (http->field_authorization) 1102 { 1103 /* 1104 * Special case for WWW-Authenticate: as its contents can be 1105 * longer than HTTP_MAX_VALUE... 1106 */ 1107 1108 return (http->field_authorization); 1109 } 1110 1111 default : 1112 return (http->fields[field]); 1113 } 1114} 1115 1116 1117/* 1118 * 'httpGetLength()' - Get the amount of data remaining from the 1119 * content-length or transfer-encoding fields. 1120 * 1121 * This function is deprecated and will not return lengths larger than 1122 * 2^31 - 1; use httpGetLength2() instead. 1123 * 1124 * @deprecated@ 1125 */ 1126 1127int /* O - Content length */ 1128httpGetLength(http_t *http) /* I - Connection to server */ 1129{ 1130 /* 1131 * Get the read content length and return the 32-bit value. 1132 */ 1133 1134 if (http) 1135 { 1136 httpGetLength2(http); 1137 1138 return (http->_data_remaining); 1139 } 1140 else 1141 return (-1); 1142} 1143 1144 1145/* 1146 * 'httpGetLength2()' - Get the amount of data remaining from the 1147 * content-length or transfer-encoding fields. 1148 * 1149 * This function returns the complete content length, even for 1150 * content larger than 2^31 - 1. 1151 * 1152 * @since CUPS 1.2/OS X 10.5@ 1153 */ 1154 1155off_t /* O - Content length */ 1156httpGetLength2(http_t *http) /* I - Connection to server */ 1157{ 1158 off_t remaining; /* Remaining length */ 1159 1160 1161 DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http, 1162 http_state_string(http->state))); 1163 1164 if (!http) 1165 return (-1); 1166 1167 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked")) 1168 { 1169 DEBUG_puts("4httpGetLength2: chunked request!"); 1170 remaining = 0; 1171 } 1172 else 1173 { 1174 /* 1175 * The following is a hack for HTTP servers that don't send a 1176 * Content-Length or Transfer-Encoding field... 1177 * 1178 * If there is no Content-Length then the connection must close 1179 * after the transfer is complete... 1180 */ 1181 1182 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0]) 1183 { 1184 /* 1185 * Default content length is 0 for errors and certain types of operations, 1186 * and 2^31-1 for other successful requests... 1187 */ 1188 1189 if (http->status >= HTTP_STATUS_MULTIPLE_CHOICES || 1190 http->state == HTTP_STATE_OPTIONS || 1191 (http->state == HTTP_STATE_GET && http->mode == _HTTP_MODE_SERVER) || 1192 http->state == HTTP_STATE_HEAD || 1193 (http->state == HTTP_STATE_PUT && http->mode == _HTTP_MODE_CLIENT) || 1194 http->state == HTTP_STATE_DELETE || 1195 http->state == HTTP_STATE_TRACE || 1196 http->state == HTTP_STATE_CONNECT) 1197 remaining = 0; 1198 else 1199 remaining = 2147483647; 1200 } 1201 else if ((remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH], 1202 NULL, 10)) < 0) 1203 remaining = -1; 1204 1205 DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT, 1206 CUPS_LLCAST remaining)); 1207 } 1208 1209 return (remaining); 1210} 1211 1212 1213/* 1214 * 'httpGets()' - Get a line of text from a HTTP connection. 1215 */ 1216 1217char * /* O - Line or NULL */ 1218httpGets(char *line, /* I - Line to read into */ 1219 int length, /* I - Max length of buffer */ 1220 http_t *http) /* I - Connection to server */ 1221{ 1222 char *lineptr, /* Pointer into line */ 1223 *lineend, /* End of line */ 1224 *bufptr, /* Pointer into input buffer */ 1225 *bufend; /* Pointer to end of buffer */ 1226 int bytes, /* Number of bytes read */ 1227 eol; /* End-of-line? */ 1228 1229 1230 DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http)); 1231 1232 if (!http || !line || length <= 1) 1233 return (NULL); 1234 1235 /* 1236 * Read a line from the buffer... 1237 */ 1238 1239 http->error = 0; 1240 lineptr = line; 1241 lineend = line + length - 1; 1242 eol = 0; 1243 1244 while (lineptr < lineend) 1245 { 1246 /* 1247 * Pre-load the buffer as needed... 1248 */ 1249 1250#ifdef WIN32 1251 WSASetLastError(0); 1252#else 1253 errno = 0; 1254#endif /* WIN32 */ 1255 1256 while (http->used == 0) 1257 { 1258 /* 1259 * No newline; see if there is more data to be read... 1260 */ 1261 1262 while (!_httpWait(http, http->wait_value, 1)) 1263 { 1264 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 1265 continue; 1266 1267 DEBUG_puts("3httpGets: Timed out!"); 1268#ifdef WIN32 1269 http->error = WSAETIMEDOUT; 1270#else 1271 http->error = ETIMEDOUT; 1272#endif /* WIN32 */ 1273 return (NULL); 1274 } 1275 1276 bytes = http_read(http, http->buffer + http->used, 1277 HTTP_MAX_BUFFER - http->used); 1278 1279 DEBUG_printf(("4httpGets: read %d bytes.", bytes)); 1280 1281 if (bytes < 0) 1282 { 1283 /* 1284 * Nope, can't get a line this time... 1285 */ 1286 1287#ifdef WIN32 1288 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError())); 1289 1290 if (WSAGetLastError() == WSAEINTR) 1291 continue; 1292 else if (WSAGetLastError() == WSAEWOULDBLOCK) 1293 { 1294 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 1295 continue; 1296 1297 http->error = WSAGetLastError(); 1298 } 1299 else if (WSAGetLastError() != http->error) 1300 { 1301 http->error = WSAGetLastError(); 1302 continue; 1303 } 1304 1305#else 1306 DEBUG_printf(("3httpGets: recv() error %d!", errno)); 1307 1308 if (errno == EINTR) 1309 continue; 1310 else if (errno == EWOULDBLOCK || errno == EAGAIN) 1311 { 1312 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 1313 continue; 1314 else if (!http->timeout_cb && errno == EAGAIN) 1315 continue; 1316 1317 http->error = errno; 1318 } 1319 else if (errno != http->error) 1320 { 1321 http->error = errno; 1322 continue; 1323 } 1324#endif /* WIN32 */ 1325 1326 return (NULL); 1327 } 1328 else if (bytes == 0) 1329 { 1330 http->error = EPIPE; 1331 1332 return (NULL); 1333 } 1334 1335 /* 1336 * Yup, update the amount used... 1337 */ 1338 1339 http->used += bytes; 1340 } 1341 1342 /* 1343 * Now copy as much of the current line as possible... 1344 */ 1345 1346 for (bufptr = http->buffer, bufend = http->buffer + http->used; 1347 lineptr < lineend && bufptr < bufend;) 1348 { 1349 if (*bufptr == 0x0a) 1350 { 1351 eol = 1; 1352 bufptr ++; 1353 break; 1354 } 1355 else if (*bufptr == 0x0d) 1356 bufptr ++; 1357 else 1358 *lineptr++ = *bufptr++; 1359 } 1360 1361 http->used -= (int)(bufptr - http->buffer); 1362 if (http->used > 0) 1363 memmove(http->buffer, bufptr, http->used); 1364 1365 if (eol) 1366 { 1367 /* 1368 * End of line... 1369 */ 1370 1371 http->activity = time(NULL); 1372 1373 *lineptr = '\0'; 1374 1375 DEBUG_printf(("3httpGets: Returning \"%s\"", line)); 1376 1377 return (line); 1378 } 1379 } 1380 1381 DEBUG_puts("3httpGets: No new line available!"); 1382 1383 return (NULL); 1384} 1385 1386 1387/* 1388 * 'httpGetState()' - Get the current state of the HTTP request. 1389 */ 1390 1391http_state_t /* O - HTTP state */ 1392httpGetState(http_t *http) /* I - Connection to server */ 1393{ 1394 return (http ? http->state : HTTP_STATE_ERROR); 1395} 1396 1397 1398/* 1399 * 'httpGetStatus()' - Get the status of the last HTTP request. 1400 * 1401 * @since CUPS 1.2/OS X 10.5@ 1402 */ 1403 1404http_status_t /* O - HTTP status */ 1405httpGetStatus(http_t *http) /* I - Connection to server */ 1406{ 1407 return (http ? http->status : HTTP_STATUS_ERROR); 1408} 1409 1410 1411/* 1412 * 'httpGetSubField()' - Get a sub-field value. 1413 * 1414 * @deprecated@ 1415 */ 1416 1417char * /* O - Value or NULL */ 1418httpGetSubField(http_t *http, /* I - Connection to server */ 1419 http_field_t field, /* I - Field index */ 1420 const char *name, /* I - Name of sub-field */ 1421 char *value) /* O - Value string */ 1422{ 1423 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE)); 1424} 1425 1426 1427/* 1428 * 'httpGetSubField2()' - Get a sub-field value. 1429 * 1430 * @since CUPS 1.2/OS X 10.5@ 1431 */ 1432 1433char * /* O - Value or NULL */ 1434httpGetSubField2(http_t *http, /* I - Connection to server */ 1435 http_field_t field, /* I - Field index */ 1436 const char *name, /* I - Name of sub-field */ 1437 char *value, /* O - Value string */ 1438 int valuelen) /* I - Size of value buffer */ 1439{ 1440 const char *fptr; /* Pointer into field */ 1441 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */ 1442 *ptr, /* Pointer into string buffer */ 1443 *end; /* End of value buffer */ 1444 1445 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, " 1446 "valuelen=%d)", http, field, name, value, valuelen)); 1447 1448 if (!http || !name || !value || valuelen < 2 || 1449 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) 1450 return (NULL); 1451 1452 end = value + valuelen - 1; 1453 1454 for (fptr = http->fields[field]; *fptr;) 1455 { 1456 /* 1457 * Skip leading whitespace... 1458 */ 1459 1460 while (_cups_isspace(*fptr)) 1461 fptr ++; 1462 1463 if (*fptr == ',') 1464 { 1465 fptr ++; 1466 continue; 1467 } 1468 1469 /* 1470 * Get the sub-field name... 1471 */ 1472 1473 for (ptr = temp; 1474 *fptr && *fptr != '=' && !_cups_isspace(*fptr) && 1475 ptr < (temp + sizeof(temp) - 1); 1476 *ptr++ = *fptr++); 1477 1478 *ptr = '\0'; 1479 1480 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp)); 1481 1482 /* 1483 * Skip trailing chars up to the '='... 1484 */ 1485 1486 while (_cups_isspace(*fptr)) 1487 fptr ++; 1488 1489 if (!*fptr) 1490 break; 1491 1492 if (*fptr != '=') 1493 continue; 1494 1495 /* 1496 * Skip = and leading whitespace... 1497 */ 1498 1499 fptr ++; 1500 1501 while (_cups_isspace(*fptr)) 1502 fptr ++; 1503 1504 if (*fptr == '\"') 1505 { 1506 /* 1507 * Read quoted string... 1508 */ 1509 1510 for (ptr = value, fptr ++; 1511 *fptr && *fptr != '\"' && ptr < end; 1512 *ptr++ = *fptr++); 1513 1514 *ptr = '\0'; 1515 1516 while (*fptr && *fptr != '\"') 1517 fptr ++; 1518 1519 if (*fptr) 1520 fptr ++; 1521 } 1522 else 1523 { 1524 /* 1525 * Read unquoted string... 1526 */ 1527 1528 for (ptr = value; 1529 *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end; 1530 *ptr++ = *fptr++); 1531 1532 *ptr = '\0'; 1533 1534 while (*fptr && !_cups_isspace(*fptr) && *fptr != ',') 1535 fptr ++; 1536 } 1537 1538 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value)); 1539 1540 /* 1541 * See if this is the one... 1542 */ 1543 1544 if (!strcmp(name, temp)) 1545 { 1546 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value)); 1547 return (value); 1548 } 1549 } 1550 1551 value[0] = '\0'; 1552 1553 DEBUG_puts("3httpGetSubField2: Returning NULL"); 1554 1555 return (NULL); 1556} 1557 1558 1559/* 1560 * 'httpGetVersion()' - Get the HTTP version at the other end. 1561 */ 1562 1563http_version_t /* O - Version number */ 1564httpGetVersion(http_t *http) /* I - Connection to server */ 1565{ 1566 return (http ? http->version : HTTP_VERSION_1_0); 1567} 1568 1569 1570/* 1571 * 'httpHead()' - Send a HEAD request to the server. 1572 */ 1573 1574int /* O - Status of call (0 = success) */ 1575httpHead(http_t *http, /* I - Connection to server */ 1576 const char *uri) /* I - URI for head */ 1577{ 1578 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri)); 1579 return (http_send(http, HTTP_STATE_HEAD, uri)); 1580} 1581 1582 1583/* 1584 * 'httpInitialize()' - Initialize the HTTP interface library and set the 1585 * default HTTP proxy (if any). 1586 */ 1587 1588void 1589httpInitialize(void) 1590{ 1591 static int initialized = 0; /* Have we been called before? */ 1592#ifdef WIN32 1593 WSADATA winsockdata; /* WinSock data */ 1594#endif /* WIN32 */ 1595#ifdef HAVE_LIBSSL 1596 int i; /* Looping var */ 1597 unsigned char data[1024]; /* Seed data */ 1598#endif /* HAVE_LIBSSL */ 1599 1600 1601 _cupsGlobalLock(); 1602 if (initialized) 1603 { 1604 _cupsGlobalUnlock(); 1605 return; 1606 } 1607 1608#ifdef WIN32 1609 WSAStartup(MAKEWORD(2,2), &winsockdata); 1610 1611#elif !defined(SO_NOSIGPIPE) 1612 /* 1613 * Ignore SIGPIPE signals... 1614 */ 1615 1616# ifdef HAVE_SIGSET 1617 sigset(SIGPIPE, SIG_IGN); 1618 1619# elif defined(HAVE_SIGACTION) 1620 struct sigaction action; /* POSIX sigaction data */ 1621 1622 1623 memset(&action, 0, sizeof(action)); 1624 action.sa_handler = SIG_IGN; 1625 sigaction(SIGPIPE, &action, NULL); 1626 1627# else 1628 signal(SIGPIPE, SIG_IGN); 1629# endif /* !SO_NOSIGPIPE */ 1630#endif /* WIN32 */ 1631 1632#ifdef HAVE_GNUTLS 1633 /* 1634 * Initialize GNU TLS... 1635 */ 1636 1637 gnutls_global_init(); 1638 1639#elif defined(HAVE_LIBSSL) 1640 /* 1641 * Initialize OpenSSL... 1642 */ 1643 1644 SSL_load_error_strings(); 1645 SSL_library_init(); 1646 1647 /* 1648 * Using the current time is a dubious random seed, but on some systems 1649 * it is the best we can do (on others, this seed isn't even used...) 1650 */ 1651 1652 CUPS_SRAND(time(NULL)); 1653 1654 for (i = 0; i < sizeof(data); i ++) 1655 data[i] = CUPS_RAND(); 1656 1657 RAND_seed(data, sizeof(data)); 1658#endif /* HAVE_GNUTLS */ 1659 1660 initialized = 1; 1661 _cupsGlobalUnlock(); 1662} 1663 1664 1665/* 1666 * 'httpOptions()' - Send an OPTIONS request to the server. 1667 */ 1668 1669int /* O - Status of call (0 = success) */ 1670httpOptions(http_t *http, /* I - Connection to server */ 1671 const char *uri) /* I - URI for options */ 1672{ 1673 return (http_send(http, HTTP_STATE_OPTIONS, uri)); 1674} 1675 1676 1677/* 1678 * 'httpPeek()' - Peek at data from a HTTP connection. 1679 * 1680 * This function copies available data from the given HTTP connection, reading 1681 * a buffer as needed. The data is still available for reading using 1682 * @link httpRead@ or @link httpRead2@. 1683 * 1684 * For non-blocking connections the usual timeouts apply. 1685 * 1686 * @since CUPS 1.7/OS X 10.9@ 1687 */ 1688 1689ssize_t /* O - Number of bytes copied */ 1690httpPeek(http_t *http, /* I - Connection to server */ 1691 char *buffer, /* I - Buffer for data */ 1692 size_t length) /* I - Maximum number of bytes */ 1693{ 1694 ssize_t bytes; /* Bytes read */ 1695 char len[32]; /* Length string */ 1696 1697 1698 DEBUG_printf(("httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")", 1699 http, buffer, CUPS_LLCAST length)); 1700 1701 if (http == NULL || buffer == NULL) 1702 return (-1); 1703 1704 http->activity = time(NULL); 1705 http->error = 0; 1706 1707 if (length <= 0) 1708 return (0); 1709 1710 if (http->data_encoding == HTTP_ENCODING_CHUNKED && 1711 http->data_remaining <= 0) 1712 { 1713 DEBUG_puts("2httpPeek: Getting chunk length..."); 1714 1715 if (httpGets(len, sizeof(len), http) == NULL) 1716 { 1717 DEBUG_puts("1httpPeek: Could not get length!"); 1718 return (0); 1719 } 1720 1721 if (!len[0]) 1722 { 1723 DEBUG_puts("1httpPeek: Blank chunk length, trying again..."); 1724 if (!httpGets(len, sizeof(len), http)) 1725 { 1726 DEBUG_puts("1httpPeek: Could not get chunk length."); 1727 return (0); 1728 } 1729 } 1730 1731 http->data_remaining = strtoll(len, NULL, 16); 1732 1733 if (http->data_remaining < 0) 1734 { 1735 DEBUG_puts("1httpPeek: Negative chunk length!"); 1736 return (0); 1737 } 1738 } 1739 1740 DEBUG_printf(("2httpPeek: data_remaining=" CUPS_LLFMT, 1741 CUPS_LLCAST http->data_remaining)); 1742 1743 if (http->data_remaining <= 0 && http->data_encoding != HTTP_ENCODING_FIELDS) 1744 { 1745 /* 1746 * A zero-length chunk ends a transfer; unless we are reading POST 1747 * data, go idle... 1748 */ 1749 1750#ifdef HAVE_LIBZ 1751 if (http->coding >= _HTTP_CODING_GUNZIP) 1752 http_content_coding_finish(http); 1753#endif /* HAVE_LIBZ */ 1754 1755 if (http->data_encoding == HTTP_ENCODING_CHUNKED) 1756 httpGets(len, sizeof(len), http); 1757 1758 if (http->state == HTTP_STATE_POST_RECV) 1759 http->state ++; 1760 else 1761 http->state = HTTP_STATE_STATUS; 1762 1763 DEBUG_printf(("1httpPeek: 0-length chunk, set state to %s.", 1764 http_state_string(http->state))); 1765 1766 /* 1767 * Prevent future reads for this request... 1768 */ 1769 1770 http->data_encoding = HTTP_ENCODING_FIELDS; 1771 1772 return (0); 1773 } 1774 else if (length > (size_t)http->data_remaining) 1775 length = (size_t)http->data_remaining; 1776 1777#ifdef HAVE_LIBZ 1778 if (http->used == 0 && 1779 (http->coding == _HTTP_CODING_IDENTITY || 1780 (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0))) 1781#else 1782 if (http->used == 0) 1783#endif /* HAVE_LIBZ */ 1784 { 1785 /* 1786 * Buffer small reads for better performance... 1787 */ 1788 1789 ssize_t buflen; /* Length of read for buffer */ 1790 1791 if (!http->blocking) 1792 { 1793 while (!httpWait(http, http->wait_value)) 1794 { 1795 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 1796 continue; 1797 1798 return (0); 1799 } 1800 } 1801 1802 if (http->data_remaining > sizeof(http->buffer)) 1803 buflen = sizeof(http->buffer); 1804 else 1805 buflen = http->data_remaining; 1806 1807 DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen)); 1808 bytes = http_read(http, http->buffer, buflen); 1809 1810 DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.", 1811 CUPS_LLCAST bytes)); 1812 if (bytes > 0) 1813 { 1814#ifdef DEBUG 1815 http_debug_hex("httpPeek", http->buffer, (int)bytes); 1816#endif /* DEBUG */ 1817 1818 http->used = bytes; 1819 } 1820 } 1821 1822#ifdef HAVE_LIBZ 1823 if (http->coding >= _HTTP_CODING_GUNZIP) 1824 { 1825# ifdef HAVE_INFLATECOPY 1826 int zerr; /* Decompressor error */ 1827 z_stream stream; /* Copy of decompressor stream */ 1828 1829 if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER) 1830 { 1831 size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in; 1832 /* Number of bytes to copy */ 1833 1834 if (http->stream.avail_in > 0 && 1835 http->stream.next_in > http->dbuffer) 1836 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in); 1837 1838 http->stream.next_in = http->dbuffer; 1839 1840 if (buflen > http->data_remaining) 1841 buflen = http->data_remaining; 1842 1843 if (buflen > http->used) 1844 buflen = http->used; 1845 1846 DEBUG_printf(("1httpPeek: Copying %d more bytes of data into " 1847 "decompression buffer.", (int)buflen)); 1848 1849 memcpy(http->dbuffer + http->stream.avail_in, http->buffer, buflen); 1850 http->stream.avail_in += buflen; 1851 http->used -= buflen; 1852 http->data_remaining -= buflen; 1853 1854 if (http->used > 0) 1855 memmove(http->buffer, http->buffer + buflen, http->used); 1856 } 1857 1858 DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length, 1859 (int)http->stream.avail_in)); 1860 1861 if (inflateCopy(&stream, &(http->stream)) != Z_OK) 1862 { 1863 DEBUG_puts("2httpPeek: Unable to copy decompressor stream."); 1864 http->error = ENOMEM; 1865 return (-1); 1866 } 1867 1868 stream.next_out = (Bytef *)buffer; 1869 stream.avail_out = length; 1870 1871 zerr = inflate(&stream, Z_SYNC_FLUSH); 1872 inflateEnd(&stream); 1873 1874 if (zerr < Z_OK) 1875 { 1876 DEBUG_printf(("2httpPeek: zerr=%d", zerr)); 1877#ifdef DEBUG 1878 http_debug_hex("2httpPeek", (char *)http->dbuffer, 1879 http->stream.avail_in); 1880#endif /* DEBUG */ 1881 1882 http->error = EIO; 1883 return (-1); 1884 } 1885 1886 bytes = length - http->stream.avail_out; 1887 1888# else 1889 DEBUG_puts("2httpPeek: No inflateCopy on this platform, httpPeek does not " 1890 "work with compressed streams."); 1891 return (-1); 1892# endif /* HAVE_INFLATECOPY */ 1893 } 1894 else 1895#endif /* HAVE_LIBZ */ 1896 if (http->used > 0) 1897 { 1898 if (length > (size_t)http->used) 1899 length = (size_t)http->used; 1900 1901 bytes = (ssize_t)length; 1902 1903 DEBUG_printf(("2httpPeek: grabbing %d bytes from input buffer...", 1904 (int)bytes)); 1905 1906 memcpy(buffer, http->buffer, length); 1907 } 1908 else 1909 bytes = 0; 1910 1911 if (bytes < 0) 1912 { 1913#ifdef WIN32 1914 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) 1915 bytes = 0; 1916 else 1917 http->error = WSAGetLastError(); 1918#else 1919 if (errno == EINTR || errno == EAGAIN) 1920 bytes = 0; 1921 else 1922 http->error = errno; 1923#endif /* WIN32 */ 1924 } 1925 else if (bytes == 0) 1926 { 1927 http->error = EPIPE; 1928 return (0); 1929 } 1930 1931 return (bytes); 1932} 1933 1934/* For OS X 10.8 and earlier */ 1935ssize_t _httpPeek(http_t *http, char *buffer, size_t length) 1936{ return (httpPeek(http, buffer, length)); } 1937 1938 1939/* 1940 * 'httpPost()' - Send a POST request to the server. 1941 */ 1942 1943int /* O - Status of call (0 = success) */ 1944httpPost(http_t *http, /* I - Connection to server */ 1945 const char *uri) /* I - URI for post */ 1946{ 1947 return (http_send(http, HTTP_STATE_POST, uri)); 1948} 1949 1950 1951/* 1952 * 'httpPrintf()' - Print a formatted string to a HTTP connection. 1953 * 1954 * @private@ 1955 */ 1956 1957int /* O - Number of bytes written */ 1958httpPrintf(http_t *http, /* I - Connection to server */ 1959 const char *format, /* I - printf-style format string */ 1960 ...) /* I - Additional args as needed */ 1961{ 1962 int bytes; /* Number of bytes to write */ 1963 char buf[16384]; /* Buffer for formatted string */ 1964 va_list ap; /* Variable argument pointer */ 1965 1966 1967 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format)); 1968 1969 va_start(ap, format); 1970 bytes = vsnprintf(buf, sizeof(buf), format, ap); 1971 va_end(ap); 1972 1973 DEBUG_printf(("3httpPrintf: (%d bytes) %s", bytes, buf)); 1974 1975 if (http->data_encoding == HTTP_ENCODING_FIELDS) 1976 return (httpWrite2(http, buf, bytes)); 1977 else 1978 { 1979 if (http->wused) 1980 { 1981 DEBUG_puts("4httpPrintf: flushing existing data..."); 1982 1983 if (httpFlushWrite(http) < 0) 1984 return (-1); 1985 } 1986 1987 return (http_write(http, buf, bytes)); 1988 } 1989} 1990 1991 1992/* 1993 * 'httpPut()' - Send a PUT request to the server. 1994 */ 1995 1996int /* O - Status of call (0 = success) */ 1997httpPut(http_t *http, /* I - Connection to server */ 1998 const char *uri) /* I - URI to put */ 1999{ 2000 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri)); 2001 return (http_send(http, HTTP_STATE_PUT, uri)); 2002} 2003 2004 2005/* 2006 * 'httpRead()' - Read data from a HTTP connection. 2007 * 2008 * This function is deprecated. Use the httpRead2() function which can 2009 * read more than 2GB of data. 2010 * 2011 * @deprecated@ 2012 */ 2013 2014int /* O - Number of bytes read */ 2015httpRead(http_t *http, /* I - Connection to server */ 2016 char *buffer, /* I - Buffer for data */ 2017 int length) /* I - Maximum number of bytes */ 2018{ 2019 return ((int)httpRead2(http, buffer, length)); 2020} 2021 2022 2023/* 2024 * 'httpRead2()' - Read data from a HTTP connection. 2025 * 2026 * @since CUPS 1.2/OS X 10.5@ 2027 */ 2028 2029ssize_t /* O - Number of bytes read */ 2030httpRead2(http_t *http, /* I - Connection to server */ 2031 char *buffer, /* I - Buffer for data */ 2032 size_t length) /* I - Maximum number of bytes */ 2033{ 2034 ssize_t bytes; /* Bytes read */ 2035 2036 2037#ifdef HAVE_LIBZ 2038 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT 2039 ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT, 2040 http, buffer, CUPS_LLCAST length, 2041 http->coding, 2042 http->data_encoding, CUPS_LLCAST http->data_remaining)); 2043#else 2044 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT 2045 ") data_encoding=%d data_remaining=" CUPS_LLFMT, 2046 http, buffer, CUPS_LLCAST length, 2047 http->data_encoding, CUPS_LLCAST http->data_remaining)); 2048#endif /* HAVE_LIBZ */ 2049 2050 if (http == NULL || buffer == NULL) 2051 return (-1); 2052 2053 http->activity = time(NULL); 2054 http->error = 0; 2055 2056 if (length <= 0) 2057 return (0); 2058 2059#ifdef HAVE_LIBZ 2060 if (http->coding >= _HTTP_CODING_GUNZIP) 2061 { 2062 do 2063 { 2064 if (http->stream.avail_in > 0) 2065 { 2066 int zerr; /* Decompressor error */ 2067 2068 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d", 2069 (int)http->stream.avail_in, (int)length)); 2070 2071 http->stream.next_out = (Bytef *)buffer; 2072 http->stream.avail_out = length; 2073 2074 if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK) 2075 { 2076 DEBUG_printf(("2httpRead2: zerr=%d", zerr)); 2077#ifdef DEBUG 2078 http_debug_hex("2httpRead2", (char *)http->dbuffer, 2079 http->stream.avail_in); 2080#endif /* DEBUG */ 2081 2082 http->error = EIO; 2083 return (-1); 2084 } 2085 2086 bytes = length - http->stream.avail_out; 2087 2088 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d", 2089 http->stream.avail_in, http->stream.avail_out, 2090 (int)bytes)); 2091 } 2092 else 2093 bytes = 0; 2094 2095 if (bytes == 0) 2096 { 2097 ssize_t buflen = HTTP_MAX_BUFFER - http->stream.avail_in; 2098 /* Additional bytes for buffer */ 2099 2100 if (buflen > 0) 2101 { 2102 if (http->stream.avail_in > 0 && 2103 http->stream.next_in > http->dbuffer) 2104 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in); 2105 2106 http->stream.next_in = http->dbuffer; 2107 2108 DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into " 2109 "decompression buffer.", (int)buflen)); 2110 2111 if (http->data_remaining > 0) 2112 { 2113 if (buflen > http->data_remaining) 2114 buflen = http->data_remaining; 2115 2116 bytes = http_read_buffered(http, 2117 (char *)http->dbuffer + 2118 http->stream.avail_in, buflen); 2119 } 2120 else if (http->data_encoding == HTTP_ENCODING_CHUNKED) 2121 bytes = http_read_chunk(http, 2122 (char *)http->dbuffer + 2123 http->stream.avail_in, buflen); 2124 else 2125 bytes = 0; 2126 2127 if (bytes < 0) 2128 return (bytes); 2129 else if (bytes == 0) 2130 break; 2131 2132 DEBUG_printf(("1httpRead2: Adding " CUPS_LLFMT " bytes to " 2133 "decompression buffer.", CUPS_LLCAST bytes)); 2134 2135 http->data_remaining -= bytes; 2136 http->stream.avail_in += bytes; 2137 2138 if (http->data_remaining <= 0 && 2139 http->data_encoding == HTTP_ENCODING_CHUNKED) 2140 { 2141 /* 2142 * Read the trailing blank line now... 2143 */ 2144 2145 char len[32]; /* Length string */ 2146 2147 httpGets(len, sizeof(len), http); 2148 } 2149 2150 bytes = 0; 2151 } 2152 else 2153 return (0); 2154 } 2155 } 2156 while (bytes == 0); 2157 } 2158 else 2159#endif /* HAVE_LIBZ */ 2160 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED) 2161 { 2162 if ((bytes = http_read_chunk(http, buffer, length)) > 0) 2163 { 2164 http->data_remaining -= bytes; 2165 2166 if (http->data_remaining <= 0) 2167 { 2168 /* 2169 * Read the trailing blank line now... 2170 */ 2171 2172 char len[32]; /* Length string */ 2173 2174 httpGets(len, sizeof(len), http); 2175 } 2176 } 2177 } 2178 else if (http->data_remaining <= 0) 2179 { 2180 /* 2181 * No more data to read... 2182 */ 2183 2184 return (0); 2185 } 2186 else 2187 { 2188 DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.", 2189 (int)length)); 2190 2191 if (length > (size_t)http->data_remaining) 2192 length = (size_t)http->data_remaining; 2193 2194 if ((bytes = http_read_buffered(http, buffer, length)) > 0) 2195 { 2196 http->data_remaining -= bytes; 2197 2198 if (http->data_remaining <= 0 && 2199 http->data_encoding == HTTP_ENCODING_CHUNKED) 2200 { 2201 /* 2202 * Read the trailing blank line now... 2203 */ 2204 2205 char len[32]; /* Length string */ 2206 2207 httpGets(len, sizeof(len), http); 2208 } 2209 } 2210 } 2211 2212 if ( 2213#ifdef HAVE_LIBZ 2214 (http->coding == _HTTP_CODING_IDENTITY || 2215 (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0)) && 2216#endif /* HAVE_LIBZ */ 2217 ((http->data_remaining <= 0 && 2218 http->data_encoding == HTTP_ENCODING_LENGTH) || 2219 (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0))) 2220 { 2221#ifdef HAVE_LIBZ 2222 if (http->coding >= _HTTP_CODING_GUNZIP) 2223 http_content_coding_finish(http); 2224#endif /* HAVE_LIBZ */ 2225 2226 if (http->state == HTTP_STATE_POST_RECV) 2227 http->state ++; 2228 else if (http->state == HTTP_STATE_GET_SEND || 2229 http->state == HTTP_STATE_POST_SEND) 2230 http->state = HTTP_STATE_WAITING; 2231 else 2232 http->state = HTTP_STATE_STATUS; 2233 2234 DEBUG_printf(("1httpRead2: End of content, set state to %s.", 2235 http_state_string(http->state))); 2236 } 2237 2238 return (bytes); 2239} 2240 2241 2242#if defined(HAVE_SSL) && defined(HAVE_CDSASSL) 2243/* 2244 * '_httpReadCDSA()' - Read function for the CDSA library. 2245 */ 2246 2247OSStatus /* O - -1 on error, 0 on success */ 2248_httpReadCDSA( 2249 SSLConnectionRef connection, /* I - SSL/TLS connection */ 2250 void *data, /* I - Data buffer */ 2251 size_t *dataLength) /* IO - Number of bytes */ 2252{ 2253 OSStatus result; /* Return value */ 2254 ssize_t bytes; /* Number of bytes read */ 2255 http_t *http; /* HTTP connection */ 2256 2257 2258 http = (http_t *)connection; 2259 2260 if (!http->blocking) 2261 { 2262 /* 2263 * Make sure we have data before we read... 2264 */ 2265 2266 while (!_httpWait(http, http->wait_value, 0)) 2267 { 2268 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 2269 continue; 2270 2271 http->error = ETIMEDOUT; 2272 return (-1); 2273 } 2274 } 2275 2276 do 2277 { 2278 bytes = recv(http->fd, data, *dataLength, 0); 2279 } 2280 while (bytes == -1 && (errno == EINTR || errno == EAGAIN)); 2281 2282 if (bytes == *dataLength) 2283 { 2284 result = 0; 2285 } 2286 else if (bytes > 0) 2287 { 2288 *dataLength = bytes; 2289 result = errSSLWouldBlock; 2290 } 2291 else 2292 { 2293 *dataLength = 0; 2294 2295 if (bytes == 0) 2296 result = errSSLClosedGraceful; 2297 else if (errno == EAGAIN) 2298 result = errSSLWouldBlock; 2299 else 2300 result = errSSLClosedAbort; 2301 } 2302 2303 return (result); 2304} 2305#endif /* HAVE_SSL && HAVE_CDSASSL */ 2306 2307 2308#if defined(HAVE_SSL) && defined(HAVE_GNUTLS) 2309/* 2310 * '_httpReadGNUTLS()' - Read function for the GNU TLS library. 2311 */ 2312 2313ssize_t /* O - Number of bytes read or -1 on error */ 2314_httpReadGNUTLS( 2315 gnutls_transport_ptr_t ptr, /* I - Connection to server */ 2316 void *data, /* I - Buffer */ 2317 size_t length) /* I - Number of bytes to read */ 2318{ 2319 http_t *http; /* HTTP connection */ 2320 ssize_t bytes; /* Bytes read */ 2321 2322 2323 DEBUG_printf(("6_httpReadGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data, (int)length)); 2324 2325 http = (http_t *)ptr; 2326 2327 if (!http->blocking) 2328 { 2329 /* 2330 * Make sure we have data before we read... 2331 */ 2332 2333 while (!_httpWait(http, http->wait_value, 0)) 2334 { 2335 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 2336 continue; 2337 2338 http->error = ETIMEDOUT; 2339 return (-1); 2340 } 2341 } 2342 2343 bytes = recv(http->fd, data, length, 0); 2344 DEBUG_printf(("6_httpReadGNUTLS: bytes=%d", (int)bytes)); 2345 return (bytes); 2346} 2347#endif /* HAVE_SSL && HAVE_GNUTLS */ 2348 2349 2350/* 2351 * 'httpReadRequest()' - Read a HTTP request from a connection. 2352 * 2353 * @since CUPS 1.7/OS X 10.9@ 2354 */ 2355 2356http_state_t /* O - New state of connection */ 2357httpReadRequest(http_t *http, /* I - HTTP connection */ 2358 char *uri, /* I - URI buffer */ 2359 size_t urilen) /* I - Size of URI buffer */ 2360{ 2361 char line[4096], /* HTTP request line */ 2362 *req_method, /* HTTP request method */ 2363 *req_uri, /* HTTP request URI */ 2364 *req_version; /* HTTP request version number string */ 2365 2366 2367 /* 2368 * Range check input... 2369 */ 2370 2371 DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")", 2372 http, uri, CUPS_LLCAST urilen)); 2373 2374 if (uri) 2375 *uri = '\0'; 2376 2377 if (!http || !uri || urilen < 1) 2378 { 2379 DEBUG_puts("1httpReadRequest: Bad arguments, returning HTTP_STATE_ERROR."); 2380 return (HTTP_STATE_ERROR); 2381 } 2382 else if (http->state != HTTP_STATE_WAITING) 2383 { 2384 DEBUG_printf(("1httpReadRequest: Bad state %s, returning HTTP_STATE_ERROR.", 2385 http_state_string(http->state))); 2386 return (HTTP_STATE_ERROR); 2387 } 2388 2389 /* 2390 * Reset state... 2391 */ 2392 2393 httpClearFields(http); 2394 2395 http->activity = time(NULL); 2396 http->data_encoding = HTTP_ENCODING_FIELDS; 2397 http->data_remaining = 0; 2398 http->keep_alive = HTTP_KEEPALIVE_OFF; 2399 http->status = HTTP_STATUS_OK; 2400 http->version = HTTP_VERSION_1_1; 2401 2402 /* 2403 * Read a line from the socket... 2404 */ 2405 2406 if (!httpGets(line, sizeof(line), http)) 2407 { 2408 DEBUG_puts("1httpReadRequest: Unable to read, returning HTTP_STATE_ERROR"); 2409 return (HTTP_STATE_ERROR); 2410 } 2411 2412 if (!line[0]) 2413 { 2414 DEBUG_puts("1httpReadRequest: Blank line, returning HTTP_STATE_WAITING"); 2415 return (HTTP_STATE_WAITING); 2416 } 2417 2418 DEBUG_printf(("1httpReadRequest: %s", line)); 2419 2420 /* 2421 * Parse it... 2422 */ 2423 2424 req_method = line; 2425 req_uri = line; 2426 2427 while (*req_uri && !isspace(*req_uri & 255)) 2428 req_uri ++; 2429 2430 if (!*req_uri) 2431 { 2432 DEBUG_puts("1httpReadRequest: No request URI."); 2433 return (HTTP_STATE_ERROR); 2434 } 2435 2436 *req_uri++ = '\0'; 2437 2438 while (*req_uri && isspace(*req_uri & 255)) 2439 req_uri ++; 2440 2441 req_version = req_uri; 2442 2443 while (*req_version && !isspace(*req_version & 255)) 2444 req_version ++; 2445 2446 if (!*req_version) 2447 { 2448 DEBUG_puts("1httpReadRequest: No request protocol version."); 2449 return (HTTP_STATE_ERROR); 2450 } 2451 2452 *req_version++ = '\0'; 2453 2454 while (*req_version && isspace(*req_version & 255)) 2455 req_version ++; 2456 2457 /* 2458 * Validate... 2459 */ 2460 2461 if (!strcmp(req_method, "OPTIONS")) 2462 http->state = HTTP_STATE_OPTIONS; 2463 else if (!strcmp(req_method, "GET")) 2464 http->state = HTTP_STATE_GET; 2465 else if (!strcmp(req_method, "HEAD")) 2466 http->state = HTTP_STATE_HEAD; 2467 else if (!strcmp(req_method, "POST")) 2468 http->state = HTTP_STATE_POST; 2469 else if (!strcmp(req_method, "PUT")) 2470 http->state = HTTP_STATE_PUT; 2471 else if (!strcmp(req_method, "DELETE")) 2472 http->state = HTTP_STATE_DELETE; 2473 else if (!strcmp(req_method, "TRACE")) 2474 http->state = HTTP_STATE_TRACE; 2475 else if (!strcmp(req_method, "CONNECT")) 2476 http->state = HTTP_STATE_CONNECT; 2477 else 2478 { 2479 DEBUG_printf(("1httpReadRequest: Unknown method \"%s\".", req_method)); 2480 return (HTTP_STATE_UNKNOWN_METHOD); 2481 } 2482 2483 DEBUG_printf(("1httpReadRequest: Set state to %s.", 2484 http_state_string(http->state))); 2485 2486 if (!strcmp(req_version, "HTTP/1.0")) 2487 { 2488 http->version = HTTP_VERSION_1_0; 2489 http->keep_alive = HTTP_KEEPALIVE_OFF; 2490 } 2491 else if (!strcmp(req_version, "HTTP/1.1")) 2492 { 2493 http->version = HTTP_VERSION_1_1; 2494 http->keep_alive = HTTP_KEEPALIVE_ON; 2495 } 2496 else 2497 { 2498 DEBUG_printf(("1httpReadRequest: Unknown version \"%s\".", req_version)); 2499 return (HTTP_STATE_UNKNOWN_VERSION); 2500 } 2501 2502 DEBUG_printf(("1httpReadRequest: URI is \"%s\".", req_uri)); 2503 strlcpy(uri, req_uri, urilen); 2504 2505 return (http->state); 2506} 2507 2508 2509/* 2510 * 'httpReconnect()' - Reconnect to a HTTP server. 2511 * 2512 * This function is deprecated. Please use the @link httpReconnect2@ function 2513 * instead. 2514 * 2515 * @deprecated@ 2516 */ 2517 2518int /* O - 0 on success, non-zero on failure */ 2519httpReconnect(http_t *http) /* I - Connection to server */ 2520{ 2521 DEBUG_printf(("httpReconnect(http=%p)", http)); 2522 2523 return (httpReconnect2(http, 30000, NULL)); 2524} 2525 2526 2527/* 2528 * 'httpReconnect2()' - Reconnect to a HTTP server with timeout and optional 2529 * cancel. 2530 */ 2531 2532int /* O - 0 on success, non-zero on failure */ 2533httpReconnect2(http_t *http, /* I - Connection to server */ 2534 int msec, /* I - Timeout in milliseconds */ 2535 int *cancel) /* I - Pointer to "cancel" variable */ 2536{ 2537 http_addrlist_t *addr; /* Connected address */ 2538#ifdef DEBUG 2539 http_addrlist_t *current; /* Current address */ 2540 char temp[256]; /* Temporary address string */ 2541#endif /* DEBUG */ 2542 2543 2544 DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", http, msec, 2545 cancel)); 2546 2547 if (!http) 2548 { 2549 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); 2550 return (-1); 2551 } 2552 2553#ifdef HAVE_SSL 2554 if (http->tls) 2555 { 2556 DEBUG_puts("2httpReconnect2: Shutting down SSL/TLS..."); 2557 http_shutdown_ssl(http); 2558 } 2559#endif /* HAVE_SSL */ 2560 2561 /* 2562 * Close any previously open socket... 2563 */ 2564 2565 if (http->fd >= 0) 2566 { 2567 DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd)); 2568 2569#ifdef WIN32 2570 closesocket(http->fd); 2571#else 2572 close(http->fd); 2573#endif /* WIN32 */ 2574 2575 http->fd = -1; 2576 } 2577 2578 /* 2579 * Reset all state (except fields, which may be reused)... 2580 */ 2581 2582 http->state = HTTP_STATE_WAITING; 2583 http->version = HTTP_VERSION_1_1; 2584 http->keep_alive = HTTP_KEEPALIVE_OFF; 2585 memset(&http->_hostaddr, 0, sizeof(http->_hostaddr)); 2586 http->data_encoding = HTTP_ENCODING_FIELDS; 2587 http->_data_remaining = 0; 2588 http->used = 0; 2589 http->data_remaining = 0; 2590 http->hostaddr = NULL; 2591 http->wused = 0; 2592 2593 /* 2594 * Connect to the server... 2595 */ 2596 2597#ifdef DEBUG 2598 for (current = http->addrlist; current; current = current->next) 2599 DEBUG_printf(("2httpReconnect2: Address %s:%d", 2600 httpAddrString(&(current->addr), temp, sizeof(temp)), 2601 httpAddrPort(&(current->addr)))); 2602#endif /* DEBUG */ 2603 2604 if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec, 2605 cancel)) == NULL) 2606 { 2607 /* 2608 * Unable to connect... 2609 */ 2610 2611#ifdef WIN32 2612 http->error = WSAGetLastError(); 2613#else 2614 http->error = errno; 2615#endif /* WIN32 */ 2616 http->status = HTTP_STATUS_ERROR; 2617 2618 DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s", 2619 strerror(http->error))); 2620 2621 return (-1); 2622 } 2623 2624 DEBUG_printf(("2httpReconnect2: New socket=%d", http->fd)); 2625 2626 if (http->timeout_value > 0) 2627 http_set_timeout(http->fd, http->timeout_value); 2628 2629 http->hostaddr = &(addr->addr); 2630 http->error = 0; 2631 2632#ifdef HAVE_SSL 2633 if (http->encryption == HTTP_ENCRYPTION_ALWAYS) 2634 { 2635 /* 2636 * Always do encryption via SSL. 2637 */ 2638 2639 if (http_setup_ssl(http) != 0) 2640 { 2641# ifdef WIN32 2642 closesocket(http->fd); 2643# else 2644 close(http->fd); 2645# endif /* WIN32 */ 2646 2647 return (-1); 2648 } 2649 } 2650 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls_upgrade) 2651 return (http_upgrade(http)); 2652#endif /* HAVE_SSL */ 2653 2654 DEBUG_printf(("1httpReconnect2: Connected to %s:%d...", 2655 httpAddrString(http->hostaddr, temp, sizeof(temp)), 2656 httpAddrPort(http->hostaddr))); 2657 2658 return (0); 2659} 2660 2661 2662/* 2663 * 'httpSetAuthString()' - Set the current authorization string. 2664 * 2665 * This function just stores a copy of the current authorization string in 2666 * the HTTP connection object. You must still call httpSetField() to set 2667 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(), 2668 * httpHead(), httpOptions(), httpPost, or httpPut(). 2669 * 2670 * @since CUPS 1.3/OS X 10.5@ 2671 */ 2672 2673void 2674httpSetAuthString(http_t *http, /* I - Connection to server */ 2675 const char *scheme, /* I - Auth scheme (NULL to clear it) */ 2676 const char *data) /* I - Auth data (NULL for none) */ 2677{ 2678 /* 2679 * Range check input... 2680 */ 2681 2682 if (!http) 2683 return; 2684 2685 if (http->authstring && http->authstring != http->_authstring) 2686 free(http->authstring); 2687 2688 http->authstring = http->_authstring; 2689 2690 if (scheme) 2691 { 2692 /* 2693 * Set the current authorization string... 2694 */ 2695 2696 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1; 2697 char *temp; 2698 2699 if (len > (int)sizeof(http->_authstring)) 2700 { 2701 if ((temp = malloc(len)) == NULL) 2702 len = sizeof(http->_authstring); 2703 else 2704 http->authstring = temp; 2705 } 2706 2707 if (data) 2708 snprintf(http->authstring, len, "%s %s", scheme, data); 2709 else 2710 strlcpy(http->authstring, scheme, len); 2711 } 2712 else 2713 { 2714 /* 2715 * Clear the current authorization string... 2716 */ 2717 2718 http->_authstring[0] = '\0'; 2719 } 2720} 2721 2722 2723/* 2724 * 'httpSetCredentials()' - Set the credentials associated with an encrypted 2725 * connection. 2726 * 2727 * @since CUPS 1.5/OS X 10.7@ 2728 */ 2729 2730int /* O - Status of call (0 = success) */ 2731httpSetCredentials(http_t *http, /* I - Connection to server */ 2732 cups_array_t *credentials) /* I - Array of credentials */ 2733{ 2734 if (!http || cupsArrayCount(credentials) < 1) 2735 return (-1); 2736 2737 _httpFreeCredentials(http->tls_credentials); 2738 2739 http->tls_credentials = _httpCreateCredentials(credentials); 2740 2741 return (http->tls_credentials ? 0 : -1); 2742} 2743 2744 2745/* 2746 * 'httpSetCookie()' - Set the cookie value(s). 2747 * 2748 * @since CUPS 1.1.19/OS X 10.3@ 2749 */ 2750 2751void 2752httpSetCookie(http_t *http, /* I - Connection */ 2753 const char *cookie) /* I - Cookie string */ 2754{ 2755 if (!http) 2756 return; 2757 2758 if (http->cookie) 2759 free(http->cookie); 2760 2761 if (cookie) 2762 http->cookie = strdup(cookie); 2763 else 2764 http->cookie = NULL; 2765} 2766 2767 2768/* 2769 * 'httpSetDefaultField()' - Set the default value of an HTTP header. 2770 * 2771 * Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@, 2772 * and @code HTTP_FIELD_USER_AGENT@ can be set. 2773 * 2774 * @since CUPS 1.7/OS X 10.9@ 2775 */ 2776 2777void 2778httpSetDefaultField(http_t *http, /* I - Connection to server */ 2779 http_field_t field, /* I - Field index */ 2780 const char *value)/* I - Value */ 2781{ 2782 DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")", 2783 http, field, http_fields[field], value)); 2784 2785 if (!http) 2786 return; 2787 2788 switch (field) 2789 { 2790 case HTTP_FIELD_ACCEPT_ENCODING : 2791 if (http->default_accept_encoding) 2792 _cupsStrFree(http->default_accept_encoding); 2793 2794 http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL; 2795 break; 2796 2797 case HTTP_FIELD_SERVER : 2798 if (http->default_server) 2799 _cupsStrFree(http->default_server); 2800 2801 http->default_server = value ? _cupsStrAlloc(value) : NULL; 2802 break; 2803 2804 case HTTP_FIELD_USER_AGENT : 2805 if (http->default_user_agent) 2806 _cupsStrFree(http->default_user_agent); 2807 2808 http->default_user_agent = value ? _cupsStrAlloc(value) : NULL; 2809 break; 2810 2811 default : 2812 DEBUG_puts("1httpSetDefaultField: Ignored."); 2813 break; 2814 } 2815} 2816 2817 2818/* 2819 * 'httpSetExpect()' - Set the Expect: header in a request. 2820 * 2821 * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect" 2822 * argument. 2823 * 2824 * @since CUPS 1.2/OS X 10.5@ 2825 */ 2826 2827void 2828httpSetExpect(http_t *http, /* I - Connection to server */ 2829 http_status_t expect) /* I - HTTP status to expect 2830 (@code HTTP_STATUS_CONTINUE@) */ 2831{ 2832 DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", http, expect)); 2833 2834 if (http) 2835 http->expect = expect; 2836} 2837 2838 2839/* 2840 * 'httpSetField()' - Set the value of an HTTP header. 2841 */ 2842 2843void 2844httpSetField(http_t *http, /* I - Connection to server */ 2845 http_field_t field, /* I - Field index */ 2846 const char *value) /* I - Value */ 2847{ 2848 DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", http, 2849 field, http_fields[field], value)); 2850 2851 if (http == NULL || 2852 field < HTTP_FIELD_ACCEPT_LANGUAGE || 2853 field >= HTTP_FIELD_MAX || 2854 value == NULL) 2855 return; 2856 2857 switch (field) 2858 { 2859 case HTTP_FIELD_ACCEPT_ENCODING : 2860 if (http->accept_encoding) 2861 _cupsStrFree(http->accept_encoding); 2862 2863 http->accept_encoding = _cupsStrAlloc(value); 2864 break; 2865 2866 case HTTP_FIELD_ALLOW : 2867 if (http->allow) 2868 _cupsStrFree(http->allow); 2869 2870 http->allow = _cupsStrAlloc(value); 2871 break; 2872 2873 case HTTP_FIELD_SERVER : 2874 if (http->server) 2875 _cupsStrFree(http->server); 2876 2877 http->server = _cupsStrAlloc(value); 2878 break; 2879 2880 default : 2881 strlcpy(http->fields[field], value, HTTP_MAX_VALUE); 2882 break; 2883 } 2884 2885 if (field == HTTP_FIELD_AUTHORIZATION) 2886 { 2887 /* 2888 * Special case for Authorization: as its contents can be 2889 * longer than HTTP_MAX_VALUE 2890 */ 2891 2892 if (http->field_authorization) 2893 free(http->field_authorization); 2894 2895 http->field_authorization = strdup(value); 2896 } 2897 else if (field == HTTP_FIELD_HOST) 2898 { 2899 /* 2900 * Special-case for Host: as we don't want a trailing "." on the hostname and 2901 * need to bracket IPv6 numeric addresses. 2902 */ 2903 2904 char *ptr = strchr(value, ':'); 2905 2906 if (value[0] != '[' && ptr && strchr(ptr + 1, ':')) 2907 { 2908 /* 2909 * Bracket IPv6 numeric addresses... 2910 * 2911 * This is slightly inefficient (basically copying twice), but is an edge 2912 * case and not worth optimizing... 2913 */ 2914 2915 snprintf(http->fields[HTTP_FIELD_HOST], 2916 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value); 2917 } 2918 else 2919 { 2920 /* 2921 * Check for a trailing dot on the hostname... 2922 */ 2923 2924 ptr = http->fields[HTTP_FIELD_HOST]; 2925 2926 if (*ptr) 2927 { 2928 ptr += strlen(ptr) - 1; 2929 2930 if (*ptr == '.') 2931 *ptr = '\0'; 2932 } 2933 } 2934 } 2935#ifdef HAVE_LIBZ 2936 else if (field == HTTP_FIELD_CONTENT_ENCODING && 2937 http->data_encoding != HTTP_ENCODING_FIELDS) 2938 { 2939 DEBUG_puts("1httpSetField: Calling http_content_coding_start."); 2940 http_content_coding_start(http, value); 2941 } 2942#endif /* HAVE_LIBZ */ 2943} 2944 2945 2946/* 2947 * 'httpSetLength()' - Set the content-length and content-encoding. 2948 * 2949 * @since CUPS 1.2/OS X 10.5@ 2950 */ 2951 2952void 2953httpSetLength(http_t *http, /* I - Connection to server */ 2954 size_t length) /* I - Length (0 for chunked) */ 2955{ 2956 DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", http, 2957 CUPS_LLCAST length)); 2958 2959 if (!http) 2960 return; 2961 2962 if (!length) 2963 { 2964 strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked", 2965 HTTP_MAX_VALUE); 2966 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0'; 2967 } 2968 else 2969 { 2970 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0'; 2971 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE, 2972 CUPS_LLFMT, CUPS_LLCAST length); 2973 } 2974} 2975 2976 2977/* 2978 * 'httpSetTimeout()' - Set read/write timeouts and an optional callback. 2979 * 2980 * The optional timeout callback receives both the HTTP connection and a user 2981 * data pointer and must return 1 to continue or 0 to error (time) out. 2982 * 2983 * @since CUPS 1.5/OS X 10.7@ 2984 */ 2985 2986void 2987httpSetTimeout( 2988 http_t *http, /* I - Connection to server */ 2989 double timeout, /* I - Number of seconds for timeout, 2990 must be greater than 0 */ 2991 http_timeout_cb_t cb, /* I - Callback function or NULL */ 2992 void *user_data) /* I - User data pointer */ 2993{ 2994 if (!http || timeout <= 0.0) 2995 return; 2996 2997 http->timeout_cb = cb; 2998 http->timeout_data = user_data; 2999 http->timeout_value = timeout; 3000 3001 if (http->fd >= 0) 3002 http_set_timeout(http->fd, timeout); 3003 3004 http_set_wait(http); 3005} 3006 3007 3008/* 3009 * 'httpTrace()' - Send an TRACE request to the server. 3010 */ 3011 3012int /* O - Status of call (0 = success) */ 3013httpTrace(http_t *http, /* I - Connection to server */ 3014 const char *uri) /* I - URI for trace */ 3015{ 3016 return (http_send(http, HTTP_STATE_TRACE, uri)); 3017} 3018 3019 3020/* 3021 * '_httpUpdate()' - Update the current HTTP status for incoming data. 3022 * 3023 * Note: Unlike httpUpdate(), this function does not flush pending write data 3024 * and only retrieves a single status line from the HTTP connection. 3025 */ 3026 3027int /* O - 1 to continue, 0 to stop */ 3028_httpUpdate(http_t *http, /* I - Connection to server */ 3029 http_status_t *status) /* O - Current HTTP status */ 3030{ 3031 char line[32768], /* Line from connection... */ 3032 *value; /* Pointer to value on line */ 3033 http_field_t field; /* Field index */ 3034 int major, minor; /* HTTP version numbers */ 3035 3036 3037 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status, 3038 http_state_string(http->state))); 3039 3040 /* 3041 * Grab a single line from the connection... 3042 */ 3043 3044 if (!httpGets(line, sizeof(line), http)) 3045 { 3046 *status = HTTP_STATUS_ERROR; 3047 return (0); 3048 } 3049 3050 DEBUG_printf(("2_httpUpdate: Got \"%s\"", line)); 3051 3052 if (line[0] == '\0') 3053 { 3054 /* 3055 * Blank line means the start of the data section (if any). Return 3056 * the result code, too... 3057 * 3058 * If we get status 100 (HTTP_STATUS_CONTINUE), then we *don't* change 3059 * states. Instead, we just return HTTP_STATUS_CONTINUE to the caller and 3060 * keep on tryin'... 3061 */ 3062 3063 if (http->status == HTTP_STATUS_CONTINUE) 3064 { 3065 *status = http->status; 3066 return (0); 3067 } 3068 3069 if (http->status < HTTP_STATUS_BAD_REQUEST) 3070 http->digest_tries = 0; 3071 3072#ifdef HAVE_SSL 3073 if (http->status == HTTP_STATUS_SWITCHING_PROTOCOLS && !http->tls) 3074 { 3075 if (http_setup_ssl(http) != 0) 3076 { 3077# ifdef WIN32 3078 closesocket(http->fd); 3079# else 3080 close(http->fd); 3081# endif /* WIN32 */ 3082 3083 *status = http->status = HTTP_STATUS_ERROR; 3084 return (0); 3085 } 3086 3087 *status = HTTP_STATUS_CONTINUE; 3088 return (0); 3089 } 3090#endif /* HAVE_SSL */ 3091 3092 if (http_set_length(http) < 0) 3093 { 3094 DEBUG_puts("1_httpUpdate: Bad Content-Length."); 3095 http->error = EINVAL; 3096 http->status = *status = HTTP_STATUS_ERROR; 3097 return (0); 3098 } 3099 3100 switch (http->state) 3101 { 3102 case HTTP_STATE_GET : 3103 case HTTP_STATE_POST : 3104 case HTTP_STATE_POST_RECV : 3105 case HTTP_STATE_PUT : 3106 http->state ++; 3107 3108 DEBUG_printf(("1_httpUpdate: Set state to %s.", 3109 http_state_string(http->state))); 3110 3111 case HTTP_STATE_POST_SEND : 3112 case HTTP_STATE_HEAD : 3113 break; 3114 3115 default : 3116 http->state = HTTP_STATE_WAITING; 3117 3118 DEBUG_puts("1_httpUpdate: Reset state to HTTP_STATE_WAITING."); 3119 break; 3120 } 3121 3122#ifdef HAVE_LIBZ 3123 DEBUG_puts("1_httpUpdate: Calling http_content_coding_start."); 3124 http_content_coding_start(http, 3125 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING)); 3126#endif /* HAVE_LIBZ */ 3127 3128 *status = http->status; 3129 return (0); 3130 } 3131 else if (!strncmp(line, "HTTP/", 5)) 3132 { 3133 /* 3134 * Got the beginning of a response... 3135 */ 3136 3137 int intstatus; /* Status value as an integer */ 3138 3139 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3) 3140 { 3141 *status = http->status = HTTP_STATUS_ERROR; 3142 return (0); 3143 } 3144 3145 httpClearFields(http); 3146 3147 http->version = (http_version_t)(major * 100 + minor); 3148 *status = http->status = (http_status_t)intstatus; 3149 } 3150 else if ((value = strchr(line, ':')) != NULL) 3151 { 3152 /* 3153 * Got a value... 3154 */ 3155 3156 *value++ = '\0'; 3157 while (_cups_isspace(*value)) 3158 value ++; 3159 3160 DEBUG_printf(("1_httpUpdate: Header %s: %s", line, value)); 3161 3162 /* 3163 * Be tolerants of servers that send unknown attribute fields... 3164 */ 3165 3166 if (!_cups_strcasecmp(line, "expect")) 3167 { 3168 /* 3169 * "Expect: 100-continue" or similar... 3170 */ 3171 3172 http->expect = (http_status_t)atoi(value); 3173 } 3174 else if (!_cups_strcasecmp(line, "cookie")) 3175 { 3176 /* 3177 * "Cookie: name=value[; name=value ...]" - replaces previous cookies... 3178 */ 3179 3180 httpSetCookie(http, value); 3181 } 3182 else if ((field = http_field(line)) != HTTP_FIELD_UNKNOWN) 3183 httpSetField(http, field, value); 3184#ifdef DEBUG 3185 else 3186 DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line)); 3187#endif /* DEBUG */ 3188 } 3189 else 3190 { 3191 DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line)); 3192 http->error = EINVAL; 3193 http->status = *status = HTTP_STATUS_ERROR; 3194 return (0); 3195 } 3196 3197 return (1); 3198} 3199 3200 3201/* 3202 * 'httpUpdate()' - Update the current HTTP state for incoming data. 3203 */ 3204 3205http_status_t /* O - HTTP status */ 3206httpUpdate(http_t *http) /* I - Connection to server */ 3207{ 3208 http_status_t status; /* Request status */ 3209 3210 3211 DEBUG_printf(("httpUpdate(http=%p), state=%s", http, 3212 http_state_string(http->state))); 3213 3214 /* 3215 * Flush pending data, if any... 3216 */ 3217 3218 if (http->wused) 3219 { 3220 DEBUG_puts("2httpUpdate: flushing buffer..."); 3221 3222 if (httpFlushWrite(http) < 0) 3223 return (HTTP_STATUS_ERROR); 3224 } 3225 3226 /* 3227 * If we haven't issued any commands, then there is nothing to "update"... 3228 */ 3229 3230 if (http->state == HTTP_STATE_WAITING) 3231 return (HTTP_STATUS_CONTINUE); 3232 3233 /* 3234 * Grab all of the lines we can from the connection... 3235 */ 3236 3237 while (_httpUpdate(http, &status)); 3238 3239 /* 3240 * See if there was an error... 3241 */ 3242 3243 if (http->error == EPIPE && http->status > HTTP_STATUS_CONTINUE) 3244 { 3245 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status)); 3246 return (http->status); 3247 } 3248 3249 if (http->error) 3250 { 3251 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error, 3252 strerror(http->error))); 3253 http->status = HTTP_STATUS_ERROR; 3254 return (HTTP_STATUS_ERROR); 3255 } 3256 3257 /* 3258 * Return the current status... 3259 */ 3260 3261 return (status); 3262} 3263 3264 3265/* 3266 * '_httpWait()' - Wait for data available on a connection (no flush). 3267 */ 3268 3269int /* O - 1 if data is available, 0 otherwise */ 3270_httpWait(http_t *http, /* I - Connection to server */ 3271 int msec, /* I - Milliseconds to wait */ 3272 int usessl) /* I - Use SSL context? */ 3273{ 3274#ifdef HAVE_POLL 3275 struct pollfd pfd; /* Polled file descriptor */ 3276#else 3277 fd_set input_set; /* select() input set */ 3278 struct timeval timeout; /* Timeout */ 3279#endif /* HAVE_POLL */ 3280 int nfds; /* Result from select()/poll() */ 3281 3282 3283 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl)); 3284 3285 if (http->fd < 0) 3286 { 3287 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd)); 3288 return (0); 3289 } 3290 3291 /* 3292 * Check the SSL/TLS buffers for data first... 3293 */ 3294 3295#ifdef HAVE_SSL 3296 if (http->tls && usessl) 3297 { 3298# ifdef HAVE_LIBSSL 3299 if (SSL_pending(http->tls)) 3300 { 3301 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data."); 3302 return (1); 3303 } 3304 3305# elif defined(HAVE_GNUTLS) 3306 if (gnutls_record_check_pending(http->tls)) 3307 { 3308 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data."); 3309 return (1); 3310 } 3311 3312# elif defined(HAVE_CDSASSL) 3313 size_t bytes; /* Bytes that are available */ 3314 3315 if (!SSLGetBufferedReadSize(http->tls, &bytes) && 3316 bytes > 0) 3317 { 3318 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data."); 3319 return (1); 3320 } 3321# endif /* HAVE_LIBSSL */ 3322 } 3323#endif /* HAVE_SSL */ 3324 3325 /* 3326 * Then try doing a select() or poll() to poll the socket... 3327 */ 3328 3329#ifdef HAVE_POLL 3330 pfd.fd = http->fd; 3331 pfd.events = POLLIN; 3332 3333 do 3334 { 3335 nfds = poll(&pfd, 1, msec); 3336 } 3337 while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); 3338 3339#else 3340 do 3341 { 3342 FD_ZERO(&input_set); 3343 FD_SET(http->fd, &input_set); 3344 3345 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd)); 3346 3347 if (msec >= 0) 3348 { 3349 timeout.tv_sec = msec / 1000; 3350 timeout.tv_usec = (msec % 1000) * 1000; 3351 3352 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout); 3353 } 3354 else 3355 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL); 3356 3357 DEBUG_printf(("6_httpWait: select() returned %d...", nfds)); 3358 } 3359# ifdef WIN32 3360 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || 3361 WSAGetLastError() == WSAEWOULDBLOCK)); 3362# else 3363 while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); 3364# endif /* WIN32 */ 3365#endif /* HAVE_POLL */ 3366 3367 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds, 3368 errno)); 3369 3370 return (nfds > 0); 3371} 3372 3373 3374/* 3375 * 'httpWait()' - Wait for data available on a connection. 3376 * 3377 * @since CUPS 1.1.19/OS X 10.3@ 3378 */ 3379 3380int /* O - 1 if data is available, 0 otherwise */ 3381httpWait(http_t *http, /* I - Connection to server */ 3382 int msec) /* I - Milliseconds to wait */ 3383{ 3384 /* 3385 * First see if there is data in the buffer... 3386 */ 3387 3388 DEBUG_printf(("2httpWait(http=%p, msec=%d)", http, msec)); 3389 3390 if (http == NULL) 3391 return (0); 3392 3393 if (http->used) 3394 { 3395 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready."); 3396 return (1); 3397 } 3398 3399#ifdef HAVE_LIBZ 3400 if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0) 3401 { 3402 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready."); 3403 return (1); 3404 } 3405#endif /* HAVE_LIBZ */ 3406 3407 /* 3408 * Flush pending data, if any... 3409 */ 3410 3411 if (http->wused) 3412 { 3413 DEBUG_puts("3httpWait: Flushing write buffer."); 3414 3415 if (httpFlushWrite(http) < 0) 3416 return (0); 3417 } 3418 3419 /* 3420 * If not, check the SSL/TLS buffers and do a select() on the connection... 3421 */ 3422 3423 return (_httpWait(http, msec, 1)); 3424} 3425 3426 3427/* 3428 * 'httpWrite()' - Write data to a HTTP connection. 3429 * 3430 * This function is deprecated. Use the httpWrite2() function which can 3431 * write more than 2GB of data. 3432 * 3433 * @deprecated@ 3434 */ 3435 3436int /* O - Number of bytes written */ 3437httpWrite(http_t *http, /* I - Connection to server */ 3438 const char *buffer, /* I - Buffer for data */ 3439 int length) /* I - Number of bytes to write */ 3440{ 3441 return ((int)httpWrite2(http, buffer, length)); 3442} 3443 3444 3445/* 3446 * 'httpWrite2()' - Write data to a HTTP connection. 3447 * 3448 * @since CUPS 1.2/OS X 10.5@ 3449 */ 3450 3451ssize_t /* O - Number of bytes written */ 3452httpWrite2(http_t *http, /* I - Connection to server */ 3453 const char *buffer, /* I - Buffer for data */ 3454 size_t length) /* I - Number of bytes to write */ 3455{ 3456 ssize_t bytes; /* Bytes written */ 3457 3458 3459 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http, 3460 buffer, CUPS_LLCAST length)); 3461 3462 /* 3463 * Range check input... 3464 */ 3465 3466 if (!http || !buffer) 3467 { 3468 DEBUG_puts("1httpWrite2: Returning -1 due to bad input."); 3469 return (-1); 3470 } 3471 3472 /* 3473 * Mark activity on the connection... 3474 */ 3475 3476 http->activity = time(NULL); 3477 3478 /* 3479 * Buffer small writes for better performance... 3480 */ 3481 3482#ifdef HAVE_LIBZ 3483 if (http->coding == _HTTP_CODING_GZIP || http->coding == _HTTP_CODING_DEFLATE) 3484 { 3485 DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding)); 3486 3487 if (length == 0) 3488 { 3489 http_content_coding_finish(http); 3490 bytes = 0; 3491 } 3492 else 3493 { 3494 http->stream.next_in = (Bytef *)buffer; 3495 http->stream.avail_in = length; 3496 http->stream.next_out = (Bytef *)http->wbuffer + http->wused; 3497 http->stream.avail_out = sizeof(http->wbuffer) - http->wused; 3498 3499 while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK) 3500 { 3501 http->wused = sizeof(http->wbuffer) - http->stream.avail_out; 3502 3503 if (http->stream.avail_out == 0) 3504 { 3505 if (httpFlushWrite(http) < 0) 3506 { 3507 DEBUG_puts("1httpWrite2: Unable to flush, returning -1."); 3508 return (-1); 3509 } 3510 3511 http->stream.next_out = (Bytef *)http->wbuffer; 3512 http->stream.avail_out = sizeof(http->wbuffer); 3513 } 3514 } 3515 3516 http->wused = sizeof(http->wbuffer) - http->stream.avail_out; 3517 bytes = length; 3518 } 3519 } 3520 else 3521#endif /* HAVE_LIBZ */ 3522 if (length > 0) 3523 { 3524 if (http->wused && (length + http->wused) > sizeof(http->wbuffer)) 3525 { 3526 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length=" 3527 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length)); 3528 3529 httpFlushWrite(http); 3530 } 3531 3532 if ((length + http->wused) <= sizeof(http->wbuffer) && 3533 length < sizeof(http->wbuffer)) 3534 { 3535 /* 3536 * Write to buffer... 3537 */ 3538 3539 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...", 3540 CUPS_LLCAST length)); 3541 3542 memcpy(http->wbuffer + http->wused, buffer, length); 3543 http->wused += (int)length; 3544 bytes = (ssize_t)length; 3545 } 3546 else 3547 { 3548 /* 3549 * Otherwise write the data directly... 3550 */ 3551 3552 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...", 3553 CUPS_LLCAST length)); 3554 3555 if (http->data_encoding == HTTP_ENCODING_CHUNKED) 3556 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length); 3557 else 3558 bytes = (ssize_t)http_write(http, buffer, (int)length); 3559 3560 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...", 3561 CUPS_LLCAST bytes)); 3562 } 3563 3564 if (http->data_encoding == HTTP_ENCODING_LENGTH) 3565 http->data_remaining -= bytes; 3566 } 3567 else 3568 bytes = 0; 3569 3570 /* 3571 * Handle end-of-request processing... 3572 */ 3573 3574 if ((http->data_encoding == HTTP_ENCODING_CHUNKED && length == 0) || 3575 (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0)) 3576 { 3577 /* 3578 * Finished with the transfer; unless we are sending POST or PUT 3579 * data, go idle... 3580 */ 3581 3582#ifdef HAVE_LIBZ 3583 if (http->coding == _HTTP_CODING_GZIP || http->coding == _HTTP_CODING_DEFLATE) 3584 http_content_coding_finish(http); 3585#endif /* HAVE_LIBZ */ 3586 3587 if (http->wused) 3588 { 3589 if (httpFlushWrite(http) < 0) 3590 return (-1); 3591 } 3592 3593 if (http->data_encoding == HTTP_ENCODING_CHUNKED) 3594 { 3595 /* 3596 * Send a 0-length chunk at the end of the request... 3597 */ 3598 3599 http_write(http, "0\r\n\r\n", 5); 3600 3601 /* 3602 * Reset the data state... 3603 */ 3604 3605 http->data_encoding = HTTP_ENCODING_FIELDS; 3606 http->data_remaining = 0; 3607 } 3608 3609 if (http->state == HTTP_STATE_POST_RECV) 3610 http->state ++; 3611 else if (http->state == HTTP_STATE_POST_SEND) 3612 http->state = HTTP_STATE_WAITING; 3613 else 3614 http->state = HTTP_STATE_STATUS; 3615 3616 DEBUG_printf(("2httpWrite2: Changed state to %s.", 3617 http_state_string(http->state))); 3618 } 3619 3620 DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes)); 3621 3622 return (bytes); 3623} 3624 3625 3626#if defined(HAVE_SSL) && defined(HAVE_CDSASSL) 3627/* 3628 * '_httpWriteCDSA()' - Write function for the CDSA library. 3629 */ 3630 3631OSStatus /* O - -1 on error, 0 on success */ 3632_httpWriteCDSA( 3633 SSLConnectionRef connection, /* I - SSL/TLS connection */ 3634 const void *data, /* I - Data buffer */ 3635 size_t *dataLength) /* IO - Number of bytes */ 3636{ 3637 OSStatus result; /* Return value */ 3638 ssize_t bytes; /* Number of bytes read */ 3639 http_t *http; /* HTTP connection */ 3640 3641 3642 http = (http_t *)connection; 3643 3644 do 3645 { 3646 bytes = write(http->fd, data, *dataLength); 3647 } 3648 while (bytes == -1 && (errno == EINTR || errno == EAGAIN)); 3649 3650 if (bytes == *dataLength) 3651 { 3652 result = 0; 3653 } 3654 else if (bytes >= 0) 3655 { 3656 *dataLength = bytes; 3657 result = errSSLWouldBlock; 3658 } 3659 else 3660 { 3661 *dataLength = 0; 3662 3663 if (errno == EAGAIN) 3664 result = errSSLWouldBlock; 3665 else 3666 result = errSSLClosedAbort; 3667 } 3668 3669 return (result); 3670} 3671#endif /* HAVE_SSL && HAVE_CDSASSL */ 3672 3673 3674#if defined(HAVE_SSL) && defined(HAVE_GNUTLS) 3675/* 3676 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library. 3677 */ 3678 3679ssize_t /* O - Number of bytes written or -1 on error */ 3680_httpWriteGNUTLS( 3681 gnutls_transport_ptr_t ptr, /* I - Connection to server */ 3682 const void *data, /* I - Data buffer */ 3683 size_t length) /* I - Number of bytes to write */ 3684{ 3685 ssize_t bytes; /* Bytes written */ 3686 3687 3688 DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data, 3689 (int)length)); 3690#ifdef DEBUG 3691 http_debug_hex("_httpWriteGNUTLS", data, (int)length); 3692#endif /* DEBUG */ 3693 3694 bytes = send(((http_t *)ptr)->fd, data, length, 0); 3695 DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes)); 3696 3697 return (bytes); 3698} 3699#endif /* HAVE_SSL && HAVE_GNUTLS */ 3700 3701 3702/* 3703 * 'httpWriteResponse()' - Write a HTTP response to a client connection. 3704 * 3705 * @since CUPS 1.7/OS X 10.9@ 3706 */ 3707 3708int /* O - 0 on success, -1 on error */ 3709httpWriteResponse(http_t *http, /* I - HTTP connection */ 3710 http_status_t status) /* I - Status code */ 3711{ 3712 http_encoding_t old_encoding; /* Old data_encoding value */ 3713 off_t old_remaining; /* Old data_remaining value */ 3714 3715 3716 /* 3717 * Range check input... 3718 */ 3719 3720 DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", http, status)); 3721 3722 if (!http || status < HTTP_STATUS_CONTINUE) 3723 { 3724 DEBUG_puts("1httpWriteResponse: Bad input."); 3725 return (-1); 3726 } 3727 3728 /* 3729 * Set the various standard fields if they aren't already... 3730 */ 3731 3732 if (!http->fields[HTTP_FIELD_DATE][0]) 3733 httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL))); 3734 3735 if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive) 3736 { 3737 http->keep_alive = 0; 3738 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, ""); 3739 } 3740 3741 if (http->version == HTTP_VERSION_1_1) 3742 { 3743 if (!http->fields[HTTP_FIELD_CONNECTION][0]) 3744 { 3745 if (http->keep_alive) 3746 httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive"); 3747 else 3748 httpSetField(http, HTTP_FIELD_CONNECTION, "close"); 3749 } 3750 3751 if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0]) 3752 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10"); 3753 } 3754 3755#ifdef HAVE_SSL 3756 if (status == HTTP_STATUS_UPGRADE_REQUIRED) 3757 { 3758 if (!http->fields[HTTP_FIELD_CONNECTION][0]) 3759 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); 3760 3761 if (!http->fields[HTTP_FIELD_UPGRADE][0]) 3762 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0"); 3763 } 3764#endif /* HAVE_SSL */ 3765 3766 if (!http->server) 3767 httpSetField(http, HTTP_FIELD_SERVER, 3768 http->default_server ? http->default_server : CUPS_MINIMAL); 3769 3770 /* 3771 * Set the Accept-Encoding field if it isn't already... 3772 */ 3773 3774 if (!http->accept_encoding) 3775 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, 3776 http->default_accept_encoding ? http->default_accept_encoding : 3777#ifdef HAVE_LIBZ 3778 "gzip, deflate, identity"); 3779#else 3780 "identity"); 3781#endif /* HAVE_LIBZ */ 3782 3783 /* 3784 * Send the response header... 3785 */ 3786 3787 old_encoding = http->data_encoding; 3788 old_remaining = http->data_remaining; 3789 http->data_encoding = HTTP_ENCODING_FIELDS; 3790 3791 if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100, 3792 http->version % 100, (int)status, httpStatus(status)) < 0) 3793 { 3794 http->status = HTTP_STATUS_ERROR; 3795 return (-1); 3796 } 3797 3798 if (status != HTTP_STATUS_CONTINUE) 3799 { 3800 /* 3801 * 100 Continue doesn't have the rest of the response headers... 3802 */ 3803 3804 int i; /* Looping var */ 3805 const char *value; /* Field value */ 3806 3807 for (i = 0; i < HTTP_FIELD_MAX; i ++) 3808 { 3809 if ((value = httpGetField(http, i)) != NULL && *value) 3810 { 3811 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1) 3812 { 3813 http->status = HTTP_STATUS_ERROR; 3814 return (-1); 3815 } 3816 } 3817 } 3818 3819 if (http->cookie) 3820 { 3821 if (httpPrintf(http, "Set-Cookie: %s path=/%s\r\n", http->cookie, 3822 http->tls ? " secure" : "") < 1) 3823 { 3824 http->status = HTTP_STATUS_ERROR; 3825 return (-1); 3826 } 3827 } 3828 } 3829 3830 if (httpWrite2(http, "\r\n", 2) < 2) 3831 { 3832 http->status = HTTP_STATUS_ERROR; 3833 return (-1); 3834 } 3835 3836 if (httpFlushWrite(http) < 0) 3837 { 3838 http->status = HTTP_STATUS_ERROR; 3839 return (-1); 3840 } 3841 3842 if (status == HTTP_STATUS_CONTINUE) 3843 { 3844 /* 3845 * Restore the old data_encoding and data_length values... 3846 */ 3847 3848 http->data_encoding = old_encoding; 3849 http->data_remaining = old_remaining; 3850 3851 if (old_remaining <= INT_MAX) 3852 http->_data_remaining = (int)old_remaining; 3853 else 3854 http->_data_remaining = INT_MAX; 3855 } 3856 else if (http->state == HTTP_STATE_OPTIONS || 3857 http->state == HTTP_STATE_HEAD || 3858 http->state == HTTP_STATE_PUT || 3859 http->state == HTTP_STATE_TRACE || 3860 http->state == HTTP_STATE_CONNECT || 3861 http->state == HTTP_STATE_STATUS) 3862 { 3863 DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, " 3864 "was %s.", http_state_string(http->state))); 3865 http->state = HTTP_STATE_WAITING; 3866 } 3867 else 3868 { 3869 /* 3870 * Force data_encoding and data_length to be set according to the response 3871 * headers... 3872 */ 3873 3874 http_set_length(http); 3875 3876#ifdef HAVE_LIBZ 3877 /* 3878 * Then start any content encoding... 3879 */ 3880 3881 DEBUG_puts("1httpWriteResponse: Calling http_content_coding_start."); 3882 http_content_coding_start(http, 3883 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING)); 3884#endif /* HAVE_LIBZ */ 3885 } 3886 3887 return (0); 3888} 3889 3890 3891#if defined(HAVE_SSL) && defined(HAVE_LIBSSL) 3892/* 3893 * 'http_bio_ctrl()' - Control the HTTP connection. 3894 */ 3895 3896static long /* O - Result/data */ 3897http_bio_ctrl(BIO *h, /* I - BIO data */ 3898 int cmd, /* I - Control command */ 3899 long arg1, /* I - First argument */ 3900 void *arg2) /* I - Second argument */ 3901{ 3902 switch (cmd) 3903 { 3904 default : 3905 return (0); 3906 3907 case BIO_CTRL_RESET : 3908 h->ptr = NULL; 3909 return (0); 3910 3911 case BIO_C_SET_FILE_PTR : 3912 h->ptr = arg2; 3913 h->init = 1; 3914 return (1); 3915 3916 case BIO_C_GET_FILE_PTR : 3917 if (arg2) 3918 { 3919 *((void **)arg2) = h->ptr; 3920 return (1); 3921 } 3922 else 3923 return (0); 3924 3925 case BIO_CTRL_DUP : 3926 case BIO_CTRL_FLUSH : 3927 return (1); 3928 } 3929} 3930 3931 3932/* 3933 * 'http_bio_free()' - Free OpenSSL data. 3934 */ 3935 3936static int /* O - 1 on success, 0 on failure */ 3937http_bio_free(BIO *h) /* I - BIO data */ 3938{ 3939 if (!h) 3940 return (0); 3941 3942 if (h->shutdown) 3943 { 3944 h->init = 0; 3945 h->flags = 0; 3946 } 3947 3948 return (1); 3949} 3950 3951 3952/* 3953 * 'http_bio_new()' - Initialize an OpenSSL BIO structure. 3954 */ 3955 3956static int /* O - 1 on success, 0 on failure */ 3957http_bio_new(BIO *h) /* I - BIO data */ 3958{ 3959 if (!h) 3960 return (0); 3961 3962 h->init = 0; 3963 h->num = 0; 3964 h->ptr = NULL; 3965 h->flags = 0; 3966 3967 return (1); 3968} 3969 3970 3971/* 3972 * 'http_bio_puts()' - Send a string for OpenSSL. 3973 */ 3974 3975static int /* O - Bytes written */ 3976http_bio_puts(BIO *h, /* I - BIO data */ 3977 const char *str) /* I - String to write */ 3978{ 3979#ifdef WIN32 3980 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0)); 3981#else 3982 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0)); 3983#endif /* WIN32 */ 3984} 3985 3986 3987/* 3988 * 'http_bio_read()' - Read data for OpenSSL. 3989 */ 3990 3991static int /* O - Bytes read */ 3992http_bio_read(BIO *h, /* I - BIO data */ 3993 char *buf, /* I - Buffer */ 3994 int size) /* I - Number of bytes to read */ 3995{ 3996 http_t *http; /* HTTP connection */ 3997 3998 3999 http = (http_t *)h->ptr; 4000 4001 if (!http->blocking) 4002 { 4003 /* 4004 * Make sure we have data before we read... 4005 */ 4006 4007 while (!_httpWait(http, http->wait_value, 0)) 4008 { 4009 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 4010 continue; 4011 4012#ifdef WIN32 4013 http->error = WSAETIMEDOUT; 4014#else 4015 http->error = ETIMEDOUT; 4016#endif /* WIN32 */ 4017 4018 return (-1); 4019 } 4020 } 4021 4022 return (recv(http->fd, buf, size, 0)); 4023} 4024 4025 4026/* 4027 * 'http_bio_write()' - Write data for OpenSSL. 4028 */ 4029 4030static int /* O - Bytes written */ 4031http_bio_write(BIO *h, /* I - BIO data */ 4032 const char *buf, /* I - Buffer to write */ 4033 int num) /* I - Number of bytes to write */ 4034{ 4035 return (send(((http_t *)h->ptr)->fd, buf, num, 0)); 4036} 4037#endif /* HAVE_SSL && HAVE_LIBSSL */ 4038 4039 4040#ifdef HAVE_LIBZ 4041/* 4042 * 'http_content_coding_finish()' - Finish doing any content encoding. 4043 */ 4044 4045static void 4046http_content_coding_finish( 4047 http_t *http) /* I - HTTP connection */ 4048{ 4049 int zerr; /* Compression status */ 4050 Byte dummy[1]; /* Dummy read buffer */ 4051 4052 4053 switch (http->coding) 4054 { 4055 case _HTTP_CODING_DEFLATE : 4056 case _HTTP_CODING_GZIP : 4057 http->stream.next_in = dummy; 4058 http->stream.avail_in = 0; 4059 4060 do 4061 { 4062 http->stream.next_out = (Bytef *)http->wbuffer + http->wused; 4063 http->stream.avail_out = sizeof(http->wbuffer) - http->wused; 4064 4065 zerr = deflate(&(http->stream), Z_FINISH); 4066 4067 http->wused = sizeof(http->wbuffer) - http->stream.avail_out; 4068 if (http->wused == sizeof(http->wbuffer)) 4069 httpFlushWrite(http); 4070 } 4071 while (zerr == Z_OK); 4072 4073 deflateEnd(&(http->stream)); 4074 4075 if (http->wused) 4076 httpFlushWrite(http); 4077 break; 4078 4079 case _HTTP_CODING_INFLATE : 4080 case _HTTP_CODING_GUNZIP : 4081 inflateEnd(&(http->stream)); 4082 free(http->dbuffer); 4083 http->dbuffer = NULL; 4084 break; 4085 4086 default : 4087 break; 4088 } 4089 4090 http->coding = _HTTP_CODING_IDENTITY; 4091} 4092 4093 4094/* 4095 * 'http_content_coding_start()' - Start doing content encoding. 4096 */ 4097 4098static void 4099http_content_coding_start( 4100 http_t *http, /* I - HTTP connection */ 4101 const char *value) /* I - Value of Content-Encoding */ 4102{ 4103 int zerr; /* Error/status */ 4104 _http_coding_t coding; /* Content coding value */ 4105 4106 4107 DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http, 4108 value)); 4109 4110 if (http->coding != _HTTP_CODING_IDENTITY) 4111 { 4112 DEBUG_printf(("1http_content_coding_start: http->coding already %d.", 4113 http->coding)); 4114 return; 4115 } 4116 else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip")) 4117 { 4118 if (http->state == HTTP_STATE_GET_SEND || 4119 http->state == HTTP_STATE_POST_SEND) 4120 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP : 4121 _HTTP_CODING_GUNZIP; 4122 else if (http->state == HTTP_STATE_POST_RECV || 4123 http->state == HTTP_STATE_PUT_RECV) 4124 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP : 4125 _HTTP_CODING_GUNZIP; 4126 else 4127 { 4128 DEBUG_puts("1http_content_coding_start: Not doing content coding."); 4129 return; 4130 } 4131 } 4132 else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate")) 4133 { 4134 if (http->state == HTTP_STATE_GET_SEND || 4135 http->state == HTTP_STATE_POST_SEND) 4136 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE : 4137 _HTTP_CODING_INFLATE; 4138 else if (http->state == HTTP_STATE_POST_RECV || 4139 http->state == HTTP_STATE_PUT_RECV) 4140 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE : 4141 _HTTP_CODING_INFLATE; 4142 else 4143 { 4144 DEBUG_puts("1http_content_coding_start: Not doing content coding."); 4145 return; 4146 } 4147 } 4148 else 4149 { 4150 DEBUG_puts("1http_content_coding_start: Not doing content coding."); 4151 return; 4152 } 4153 4154 memset(&(http->stream), 0, sizeof(http->stream)); 4155 4156 switch (coding) 4157 { 4158 case _HTTP_CODING_DEFLATE : 4159 case _HTTP_CODING_GZIP : 4160 if (http->wused) 4161 httpFlushWrite(http); 4162 4163 /* 4164 * Window size for compression is 11 bits - optimal based on PWG Raster 4165 * sample files on pwg.org. -11 is raw deflate, 27 is gzip, per ZLIB 4166 * documentation. 4167 */ 4168 4169 if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION, 4170 Z_DEFLATED, 4171 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7, 4172 Z_DEFAULT_STRATEGY)) < Z_OK) 4173 { 4174 http->status = HTTP_STATUS_ERROR; 4175 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; 4176 return; 4177 } 4178 break; 4179 4180 case _HTTP_CODING_INFLATE : 4181 case _HTTP_CODING_GUNZIP : 4182 if ((http->dbuffer = malloc(HTTP_MAX_BUFFER)) == NULL) 4183 { 4184 http->status = HTTP_STATUS_ERROR; 4185 http->error = errno; 4186 return; 4187 } 4188 4189 /* 4190 * Window size for decompression is up to 15 bits (maximum supported). 4191 * -15 is raw inflate, 31 is gunzip, per ZLIB documentation. 4192 */ 4193 4194 if ((zerr = inflateInit2(&(http->stream), 4195 coding == _HTTP_CODING_INFLATE ? -15 : 31)) 4196 < Z_OK) 4197 { 4198 free(http->dbuffer); 4199 http->dbuffer = NULL; 4200 http->status = HTTP_STATUS_ERROR; 4201 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; 4202 return; 4203 } 4204 4205 http->stream.avail_in = 0; 4206 http->stream.next_in = http->dbuffer; 4207 break; 4208 4209 default : 4210 break; 4211 } 4212 4213 http->coding = coding; 4214 4215 DEBUG_printf(("1http_content_coding_start: http->coding now %d.", 4216 http->coding)); 4217} 4218#endif /* HAVE_LIBZ */ 4219 4220 4221/* 4222 * 'http_create()' - Create an unconnected HTTP connection. 4223 */ 4224 4225static http_t * /* O - HTTP connection */ 4226http_create( 4227 const char *host, /* I - Hostname */ 4228 int port, /* I - Port number */ 4229 http_addrlist_t *addrlist, /* I - Address list or NULL */ 4230 int family, /* I - Address family or AF_UNSPEC */ 4231 http_encryption_t encryption, /* I - Encryption to use */ 4232 int blocking, /* I - 1 for blocking mode */ 4233 _http_mode_t mode) /* I - _HTTP_MODE_CLIENT or _SERVER */ 4234{ 4235 http_t *http; /* New HTTP connection */ 4236 char service[255]; /* Service name */ 4237 http_addrlist_t *myaddrlist = NULL; /* My address list */ 4238 4239 4240 DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, " 4241 "encryption=%d, blocking=%d, mode=%d)", host, port, addrlist, 4242 family, encryption, blocking, mode)); 4243 4244 if (!host && mode == _HTTP_MODE_CLIENT) 4245 return (NULL); 4246 4247 httpInitialize(); 4248 4249 /* 4250 * Lookup the host... 4251 */ 4252 4253 if (addrlist) 4254 { 4255 myaddrlist = httpAddrCopyList(addrlist); 4256 } 4257 else 4258 { 4259 snprintf(service, sizeof(service), "%d", port); 4260 4261 myaddrlist = httpAddrGetList(host, family, service); 4262 } 4263 4264 if (!myaddrlist) 4265 return (NULL); 4266 4267 /* 4268 * Allocate memory for the structure... 4269 */ 4270 4271 if ((http = calloc(sizeof(http_t), 1)) == NULL) 4272 { 4273 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 4274 httpAddrFreeList(addrlist); 4275 return (NULL); 4276 } 4277 4278 /* 4279 * Initialize the HTTP data... 4280 */ 4281 4282 http->mode = mode; 4283 http->activity = time(NULL); 4284 http->addrlist = myaddrlist; 4285 http->blocking = blocking; 4286 http->fd = -1; 4287#ifdef HAVE_GSSAPI 4288 http->gssctx = GSS_C_NO_CONTEXT; 4289 http->gssname = GSS_C_NO_NAME; 4290#endif /* HAVE_GSSAPI */ 4291 http->status = HTTP_STATUS_CONTINUE; 4292 http->version = HTTP_VERSION_1_1; 4293 4294 if (host) 4295 strlcpy(http->hostname, host, sizeof(http->hostname)); 4296 4297 if (port == 443) /* Always use encryption for https */ 4298 http->encryption = HTTP_ENCRYPTION_ALWAYS; 4299 else 4300 http->encryption = encryption; 4301 4302 http_set_wait(http); 4303 4304 /* 4305 * Return the new structure... 4306 */ 4307 4308 return (http); 4309} 4310 4311/* For OS X 10.8 and earlier */ 4312http_t *_httpCreate(const char *host, int port, http_addrlist_t *addrlist, 4313 http_encryption_t encryption, int family) 4314{ return (http_create(host, port, addrlist, family, encryption, 1, 4315 _HTTP_MODE_CLIENT)); } 4316 4317 4318#ifdef DEBUG 4319/* 4320 * 'http_debug_hex()' - Do a hex dump of a buffer. 4321 */ 4322 4323static void 4324http_debug_hex(const char *prefix, /* I - Prefix for line */ 4325 const char *buffer, /* I - Buffer to dump */ 4326 int bytes) /* I - Bytes to dump */ 4327{ 4328 int i, j, /* Looping vars */ 4329 ch; /* Current character */ 4330 char line[255], /* Line buffer */ 4331 *start, /* Start of line after prefix */ 4332 *ptr; /* Pointer into line */ 4333 4334 4335 if (_cups_debug_fd < 0 || _cups_debug_level < 6) 4336 return; 4337 4338 DEBUG_printf(("6%s: %d bytes:", prefix, bytes)); 4339 4340 snprintf(line, sizeof(line), "6%s: ", prefix); 4341 start = line + strlen(line); 4342 4343 for (i = 0; i < bytes; i += 16) 4344 { 4345 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2) 4346 sprintf(ptr, "%02X", buffer[i + j] & 255); 4347 4348 while (j < 16) 4349 { 4350 memcpy(ptr, " ", 3); 4351 ptr += 2; 4352 j ++; 4353 } 4354 4355 memcpy(ptr, " ", 3); 4356 ptr += 2; 4357 4358 for (j = 0; j < 16 && (i + j) < bytes; j ++) 4359 { 4360 ch = buffer[i + j] & 255; 4361 4362 if (ch < ' ' || ch >= 127) 4363 ch = '.'; 4364 4365 *ptr++ = ch; 4366 } 4367 4368 *ptr = '\0'; 4369 DEBUG_puts(line); 4370 } 4371} 4372#endif /* DEBUG */ 4373 4374 4375/* 4376 * 'http_field()' - Return the field index for a field name. 4377 */ 4378 4379static http_field_t /* O - Field index */ 4380http_field(const char *name) /* I - String name */ 4381{ 4382 int i; /* Looping var */ 4383 4384 4385 for (i = 0; i < HTTP_FIELD_MAX; i ++) 4386 if (_cups_strcasecmp(name, http_fields[i]) == 0) 4387 return ((http_field_t)i); 4388 4389 return (HTTP_FIELD_UNKNOWN); 4390} 4391 4392 4393/* 4394 * 'http_read()' - Read a buffer from a HTTP connection. 4395 * 4396 * This function does the low-level read from the socket, retrying and timing 4397 * out as needed. 4398 */ 4399 4400static ssize_t /* O - Number of bytes read or -1 on error */ 4401http_read(http_t *http, /* I - Connection to server */ 4402 char *buffer, /* I - Buffer */ 4403 size_t length) /* I - Maximum bytes to read */ 4404{ 4405 ssize_t bytes; /* Bytes read */ 4406 4407 4408 DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http, 4409 buffer, CUPS_LLCAST length)); 4410 4411 if (!http->blocking) 4412 { 4413 while (!httpWait(http, http->wait_value)) 4414 { 4415 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 4416 continue; 4417 4418 DEBUG_puts("2http_read: Timeout."); 4419 return (0); 4420 } 4421 } 4422 4423 DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length)); 4424 4425 do 4426 { 4427#ifdef HAVE_SSL 4428 if (http->tls) 4429 bytes = http_read_ssl(http, buffer, length); 4430 else 4431#endif /* HAVE_SSL */ 4432 bytes = recv(http->fd, buffer, length, 0); 4433 4434 if (bytes < 0) 4435 { 4436#ifdef WIN32 4437 if (WSAGetLastError() != WSAEINTR) 4438 { 4439 http->error = WSAGetLastError(); 4440 return (-1); 4441 } 4442 else if (WSAGetLastError() == WSAEWOULDBLOCK) 4443 { 4444 if (!http->timeout_cb || 4445 !(*http->timeout_cb)(http, http->timeout_data)) 4446 { 4447 http->error = WSAEWOULDBLOCK; 4448 return (-1); 4449 } 4450 } 4451#else 4452 DEBUG_printf(("2http_read: %s", strerror(errno))); 4453 4454 if (errno == EWOULDBLOCK || errno == EAGAIN) 4455 { 4456 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data)) 4457 { 4458 http->error = errno; 4459 return (-1); 4460 } 4461 else if (!http->timeout_cb && errno != EAGAIN) 4462 { 4463 http->error = errno; 4464 return (-1); 4465 } 4466 } 4467 else if (errno != EINTR) 4468 { 4469 http->error = errno; 4470 return (-1); 4471 } 4472#endif /* WIN32 */ 4473 } 4474 } 4475 while (bytes < 0); 4476 4477 DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.", 4478 CUPS_LLCAST bytes)); 4479#ifdef DEBUG 4480 if (bytes > 0) 4481 http_debug_hex("http_read", buffer, (int)bytes); 4482#endif /* DEBUG */ 4483 4484 if (bytes < 0) 4485 { 4486#ifdef WIN32 4487 if (WSAGetLastError() == WSAEINTR) 4488 bytes = 0; 4489 else 4490 http->error = WSAGetLastError(); 4491#else 4492 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb)) 4493 bytes = 0; 4494 else 4495 http->error = errno; 4496#endif /* WIN32 */ 4497 } 4498 else if (bytes == 0) 4499 { 4500 http->error = EPIPE; 4501 return (0); 4502 } 4503 4504 return (bytes); 4505} 4506 4507 4508/* 4509 * 'http_read_buffered()' - Do a buffered read from a HTTP connection. 4510 * 4511 * This function reads data from the HTTP buffer or from the socket, as needed. 4512 */ 4513 4514static ssize_t /* O - Number of bytes read or -1 on error */ 4515http_read_buffered(http_t *http, /* I - Connection to server */ 4516 char *buffer, /* I - Buffer */ 4517 size_t length) /* I - Maximum bytes to read */ 4518{ 4519 ssize_t bytes; /* Bytes read */ 4520 4521 4522 DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT 4523 ") used=%d", 4524 http, buffer, CUPS_LLCAST length, http->used)); 4525 4526 if (http->used > 0) 4527 { 4528 if (length > (size_t)http->used) 4529 bytes = (size_t)http->used; 4530 else 4531 bytes = length; 4532 4533 DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.", 4534 (int)bytes)); 4535 4536 memcpy(buffer, http->buffer, bytes); 4537 http->used -= (int)bytes; 4538 4539 if (http->used > 0) 4540 memmove(http->buffer, http->buffer + bytes, http->used); 4541 } 4542 else 4543 bytes = http_read(http, buffer, length); 4544 4545 return (bytes); 4546} 4547 4548 4549/* 4550 * 'http_read_chunk()' - Read a chunk from a HTTP connection. 4551 * 4552 * This function reads and validates the chunk length, then does a buffered read 4553 * returning the number of bytes placed in the buffer. 4554 */ 4555 4556static ssize_t /* O - Number of bytes read or -1 on error */ 4557http_read_chunk(http_t *http, /* I - Connection to server */ 4558 char *buffer, /* I - Buffer */ 4559 size_t length) /* I - Maximum bytes to read */ 4560{ 4561 DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", 4562 http, buffer, CUPS_LLCAST length)); 4563 4564 if (http->data_remaining <= 0) 4565 { 4566 char len[32]; /* Length string */ 4567 4568 if (!httpGets(len, sizeof(len), http)) 4569 { 4570 DEBUG_puts("1http_read_chunk: Could not get chunk length."); 4571 return (0); 4572 } 4573 4574 if (!len[0]) 4575 { 4576 DEBUG_puts("1http_read_chunk: Blank chunk length, trying again..."); 4577 if (!httpGets(len, sizeof(len), http)) 4578 { 4579 DEBUG_puts("1http_read_chunk: Could not get chunk length."); 4580 return (0); 4581 } 4582 } 4583 4584 http->data_remaining = strtoll(len, NULL, 16); 4585 4586 if (http->data_remaining < 0) 4587 { 4588 DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" (" 4589 CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining)); 4590 return (0); 4591 } 4592 4593 DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")", 4594 len, CUPS_LLCAST http->data_remaining)); 4595 4596 if (http->data_remaining == 0) 4597 { 4598 /* 4599 * 0-length chunk, grab trailing blank line... 4600 */ 4601 4602 httpGets(len, sizeof(len), http); 4603 } 4604 } 4605 4606 DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT, 4607 CUPS_LLCAST http->data_remaining)); 4608 4609 if (http->data_remaining <= 0) 4610 return (0); 4611 else if (length > (size_t)http->data_remaining) 4612 length = (size_t)http->data_remaining; 4613 4614 return (http_read_buffered(http, buffer, length)); 4615} 4616 4617 4618#ifdef HAVE_SSL 4619/* 4620 * 'http_read_ssl()' - Read from a SSL/TLS connection. 4621 */ 4622 4623static int /* O - Bytes read */ 4624http_read_ssl(http_t *http, /* I - Connection to server */ 4625 char *buf, /* I - Buffer to store data */ 4626 int len) /* I - Length of buffer */ 4627{ 4628# if defined(HAVE_LIBSSL) 4629 return (SSL_read((SSL *)(http->tls), buf, len)); 4630 4631# elif defined(HAVE_GNUTLS) 4632 ssize_t result; /* Return value */ 4633 4634 4635 result = gnutls_record_recv(http->tls, buf, len); 4636 4637 if (result < 0 && !errno) 4638 { 4639 /* 4640 * Convert GNU TLS error to errno value... 4641 */ 4642 4643 switch (result) 4644 { 4645 case GNUTLS_E_INTERRUPTED : 4646 errno = EINTR; 4647 break; 4648 4649 case GNUTLS_E_AGAIN : 4650 errno = EAGAIN; 4651 break; 4652 4653 default : 4654 errno = EPIPE; 4655 break; 4656 } 4657 4658 result = -1; 4659 } 4660 4661 return ((int)result); 4662 4663# elif defined(HAVE_CDSASSL) 4664 int result; /* Return value */ 4665 OSStatus error; /* Error info */ 4666 size_t processed; /* Number of bytes processed */ 4667 4668 4669 error = SSLRead(http->tls, buf, len, &processed); 4670 DEBUG_printf(("6http_read_ssl: error=%d, processed=%d", (int)error, 4671 (int)processed)); 4672 switch (error) 4673 { 4674 case 0 : 4675 result = (int)processed; 4676 break; 4677 4678 case errSSLWouldBlock : 4679 if (processed) 4680 result = (int)processed; 4681 else 4682 { 4683 result = -1; 4684 errno = EINTR; 4685 } 4686 break; 4687 4688 case errSSLClosedGraceful : 4689 default : 4690 if (processed) 4691 result = (int)processed; 4692 else 4693 { 4694 result = -1; 4695 errno = EPIPE; 4696 } 4697 break; 4698 } 4699 4700 return (result); 4701 4702# elif defined(HAVE_SSPISSL) 4703 return _sspiRead((_sspi_struct_t*) http->tls, buf, len); 4704# endif /* HAVE_LIBSSL */ 4705} 4706#endif /* HAVE_SSL */ 4707 4708 4709/* 4710 * 'http_send()' - Send a request with all fields and the trailing blank line. 4711 */ 4712 4713static int /* O - 0 on success, non-zero on error */ 4714http_send(http_t *http, /* I - Connection to server */ 4715 http_state_t request, /* I - Request code */ 4716 const char *uri) /* I - URI */ 4717{ 4718 int i; /* Looping var */ 4719 char buf[1024]; /* Encoded URI buffer */ 4720 const char *value; /* Field value */ 4721 static const char * const codes[] = /* Request code strings */ 4722 { 4723 NULL, 4724 "OPTIONS", 4725 "GET", 4726 NULL, 4727 "HEAD", 4728 "POST", 4729 NULL, 4730 NULL, 4731 "PUT", 4732 NULL, 4733 "DELETE", 4734 "TRACE", 4735 "CLOSE", 4736 NULL, 4737 NULL 4738 }; 4739 4740 4741 DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")", 4742 http, codes[request], uri)); 4743 4744 if (http == NULL || uri == NULL) 4745 return (-1); 4746 4747 /* 4748 * Set the User-Agent field if it isn't already... 4749 */ 4750 4751 if (!http->fields[HTTP_FIELD_USER_AGENT][0]) 4752 { 4753 if (http->default_user_agent) 4754 httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent); 4755 else 4756 httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent()); 4757 } 4758 4759 /* 4760 * Set the Accept-Encoding field if it isn't already... 4761 */ 4762 4763 if (!http->accept_encoding && http->default_accept_encoding) 4764 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, 4765 http->default_accept_encoding); 4766 4767 /* 4768 * Encode the URI as needed... 4769 */ 4770 4771 _httpEncodeURI(buf, uri, sizeof(buf)); 4772 4773 /* 4774 * See if we had an error the last time around; if so, reconnect... 4775 */ 4776 4777 if (http->fd < 0 || http->status == HTTP_STATUS_ERROR || 4778 http->status >= HTTP_STATUS_BAD_REQUEST) 4779 { 4780 DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d", 4781 http->fd, http->status, http->tls_upgrade)); 4782 4783 if (httpReconnect2(http, 30000, NULL)) 4784 return (-1); 4785 } 4786 4787 /* 4788 * Flush any written data that is pending... 4789 */ 4790 4791 if (http->wused) 4792 { 4793 if (httpFlushWrite(http) < 0) 4794 if (httpReconnect2(http, 30000, NULL)) 4795 return (-1); 4796 } 4797 4798 /* 4799 * Send the request header... 4800 */ 4801 4802 http->state = request; 4803 http->data_encoding = HTTP_ENCODING_FIELDS; 4804 4805 if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT) 4806 http->state ++; 4807 4808 http->status = HTTP_STATUS_CONTINUE; 4809 4810#ifdef HAVE_SSL 4811 if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls) 4812 { 4813 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); 4814 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0"); 4815 } 4816#endif /* HAVE_SSL */ 4817 4818 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1) 4819 { 4820 http->status = HTTP_STATUS_ERROR; 4821 return (-1); 4822 } 4823 4824 for (i = 0; i < HTTP_FIELD_MAX; i ++) 4825 if ((value = httpGetField(http, i)) != NULL && *value) 4826 { 4827 DEBUG_printf(("5http_send: %s: %s", http_fields[i], value)); 4828 4829 if (i == HTTP_FIELD_HOST) 4830 { 4831 if (httpPrintf(http, "Host: %s:%d\r\n", value, 4832 httpAddrPort(http->hostaddr)) < 1) 4833 { 4834 http->status = HTTP_STATUS_ERROR; 4835 return (-1); 4836 } 4837 } 4838 else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1) 4839 { 4840 http->status = HTTP_STATUS_ERROR; 4841 return (-1); 4842 } 4843 } 4844 4845 if (http->cookie) 4846 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1) 4847 { 4848 http->status = HTTP_STATUS_ERROR; 4849 return (-1); 4850 } 4851 4852 DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect, 4853 http->mode, http->state)); 4854 4855 if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT && 4856 (http->state == HTTP_STATE_POST_RECV || 4857 http->state == HTTP_STATE_PUT_RECV)) 4858 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1) 4859 { 4860 http->status = HTTP_STATUS_ERROR; 4861 return (-1); 4862 } 4863 4864 if (httpPrintf(http, "\r\n") < 1) 4865 { 4866 http->status = HTTP_STATUS_ERROR; 4867 return (-1); 4868 } 4869 4870 if (httpFlushWrite(http) < 0) 4871 return (-1); 4872 4873 http_set_length(http); 4874 httpClearFields(http); 4875 4876 /* 4877 * The Kerberos and AuthRef authentication strings can only be used once... 4878 */ 4879 4880 if (http->field_authorization && http->authstring && 4881 (!strncmp(http->authstring, "Negotiate", 9) || 4882 !strncmp(http->authstring, "AuthRef", 7))) 4883 { 4884 http->_authstring[0] = '\0'; 4885 4886 if (http->authstring != http->_authstring) 4887 free(http->authstring); 4888 4889 http->authstring = http->_authstring; 4890 } 4891 4892 return (0); 4893} 4894 4895 4896#ifdef HAVE_SSL 4897# if defined(HAVE_CDSASSL) 4898/* 4899 * 'http_set_credentials()' - Set the SSL/TLS credentials. 4900 */ 4901 4902static int /* O - Status of connection */ 4903http_set_credentials(http_t *http) /* I - Connection to server */ 4904{ 4905 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ 4906 OSStatus error = 0; /* Error code */ 4907 http_tls_credentials_t credentials = NULL; 4908 /* TLS credentials */ 4909 4910 4911 DEBUG_printf(("7http_set_credentials(%p)", http)); 4912 4913 /* 4914 * Prefer connection specific credentials... 4915 */ 4916 4917 if ((credentials = http->tls_credentials) == NULL) 4918 credentials = cg->tls_credentials; 4919 4920 if (credentials) 4921 { 4922 error = SSLSetCertificate(http->tls, credentials); 4923 DEBUG_printf(("4http_set_credentials: SSLSetCertificate, error=%d", 4924 (int)error)); 4925 } 4926 else 4927 DEBUG_puts("4http_set_credentials: No credentials to set."); 4928 4929 return (error); 4930} 4931# endif /* HAVE_CDSASSL */ 4932#endif /* HAVE_SSL */ 4933 4934 4935/* 4936 * 'http_set_length()' - Set the data_encoding and data_remaining values. 4937 */ 4938 4939static off_t /* O - Remainder or -1 on error */ 4940http_set_length(http_t *http) /* I - Connection */ 4941{ 4942 off_t remaining; /* Remainder */ 4943 4944 4945 DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", http, http->mode, 4946 http_state_string(http->state))); 4947 4948 if ((remaining = httpGetLength2(http)) >= 0) 4949 { 4950 if (http->mode == _HTTP_MODE_SERVER && 4951 http->state != HTTP_STATE_GET_SEND && 4952 http->state != HTTP_STATE_PUT && 4953 http->state != HTTP_STATE_POST && 4954 http->state != HTTP_STATE_POST_SEND) 4955 { 4956 DEBUG_puts("1http_set_length: Not setting data_encoding/remaining."); 4957 return (remaining); 4958 } 4959 4960 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], 4961 "chunked")) 4962 { 4963 DEBUG_puts("1http_set_length: Setting data_encoding to " 4964 "HTTP_ENCODING_CHUNKED."); 4965 http->data_encoding = HTTP_ENCODING_CHUNKED; 4966 } 4967 else 4968 { 4969 DEBUG_puts("1http_set_length: Setting data_encoding to " 4970 "HTTP_ENCODING_LENGTH."); 4971 http->data_encoding = HTTP_ENCODING_LENGTH; 4972 } 4973 4974 DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".", 4975 CUPS_LLCAST remaining)); 4976 http->data_remaining = remaining; 4977 4978 if (remaining <= INT_MAX) 4979 http->_data_remaining = remaining; 4980 else 4981 http->_data_remaining = INT_MAX; 4982 } 4983 4984 return (remaining); 4985} 4986 4987/* 4988 * 'http_set_timeout()' - Set the socket timeout values. 4989 */ 4990 4991static void 4992http_set_timeout(int fd, /* I - File descriptor */ 4993 double timeout) /* I - Timeout in seconds */ 4994{ 4995#ifdef WIN32 4996 DWORD tv = (DWORD)(timeout * 1000); 4997 /* Timeout in milliseconds */ 4998 4999 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv)); 5000 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv)); 5001 5002#else 5003 struct timeval tv; /* Timeout in secs and usecs */ 5004 5005 tv.tv_sec = (int)timeout; 5006 tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0)); 5007 5008 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv)); 5009 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv)); 5010#endif /* WIN32 */ 5011} 5012 5013 5014/* 5015 * 'http_set_wait()' - Set the default wait value for reads. 5016 */ 5017 5018static void 5019http_set_wait(http_t *http) /* I - Connection to server */ 5020{ 5021 if (http->blocking) 5022 { 5023 http->wait_value = (int)(http->timeout_value * 1000); 5024 5025 if (http->wait_value <= 0) 5026 http->wait_value = 60000; 5027 } 5028 else 5029 http->wait_value = 10000; 5030} 5031 5032 5033#ifdef HAVE_SSL 5034/* 5035 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection. 5036 */ 5037 5038static int /* O - 0 on success, -1 on failure */ 5039http_setup_ssl(http_t *http) /* I - Connection to server */ 5040{ 5041 char hostname[256], /* Hostname */ 5042 *hostptr; /* Pointer into hostname */ 5043 5044# ifdef HAVE_LIBSSL 5045 SSL_CTX *context; /* Context for encryption */ 5046 BIO *bio; /* BIO data */ 5047 const char *message = NULL;/* Error message */ 5048# elif defined(HAVE_GNUTLS) 5049 int status; /* Status of handshake */ 5050 gnutls_certificate_client_credentials *credentials; 5051 /* TLS credentials */ 5052# elif defined(HAVE_CDSASSL) 5053 _cups_globals_t *cg = _cupsGlobals(); 5054 /* Pointer to library globals */ 5055 OSStatus error; /* Error code */ 5056 const char *message = NULL;/* Error message */ 5057 cups_array_t *credentials; /* Credentials array */ 5058 cups_array_t *names; /* CUPS distinguished names */ 5059 CFArrayRef dn_array; /* CF distinguished names array */ 5060 CFIndex count; /* Number of credentials */ 5061 CFDataRef data; /* Certificate data */ 5062 int i; /* Looping var */ 5063 http_credential_t *credential; /* Credential data */ 5064# elif defined(HAVE_SSPISSL) 5065 TCHAR username[256]; /* Username returned from GetUserName() */ 5066 TCHAR commonName[256];/* Common name for certificate */ 5067 DWORD dwSize; /* 32 bit size */ 5068# endif /* HAVE_LIBSSL */ 5069 5070 5071 DEBUG_printf(("7http_setup_ssl(http=%p)", http)); 5072 5073 /* 5074 * Get the hostname to use for SSL... 5075 */ 5076 5077 if (httpAddrLocalhost(http->hostaddr)) 5078 { 5079 strlcpy(hostname, "localhost", sizeof(hostname)); 5080 } 5081 else 5082 { 5083 /* 5084 * Otherwise make sure the hostname we have does not end in a trailing dot. 5085 */ 5086 5087 strlcpy(hostname, http->hostname, sizeof(hostname)); 5088 if ((hostptr = hostname + strlen(hostname) - 1) >= hostname && 5089 *hostptr == '.') 5090 *hostptr = '\0'; 5091 } 5092 5093# ifdef HAVE_LIBSSL 5094 context = SSL_CTX_new(SSLv23_client_method()); 5095 5096 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ 5097 5098 bio = BIO_new(_httpBIOMethods()); 5099 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http); 5100 5101 http->tls = SSL_new(context); 5102 SSL_set_bio(http->tls, bio, bio); 5103 5104# ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME 5105 SSL_set_tlsext_host_name(http->tls, hostname); 5106# endif /* HAVE_SSL_SET_TLSEXT_HOST_NAME */ 5107 5108 if (SSL_connect(http->tls) != 1) 5109 { 5110 unsigned long error; /* Error code */ 5111 5112 while ((error = ERR_get_error()) != 0) 5113 { 5114 message = ERR_error_string(error, NULL); 5115 DEBUG_printf(("8http_setup_ssl: %s", message)); 5116 } 5117 5118 SSL_CTX_free(context); 5119 SSL_free(http->tls); 5120 http->tls = NULL; 5121 5122# ifdef WIN32 5123 http->error = WSAGetLastError(); 5124# else 5125 http->error = errno; 5126# endif /* WIN32 */ 5127 http->status = HTTP_STATUS_ERROR; 5128 5129 if (!message) 5130 message = _("Unable to establish a secure connection to host."); 5131 5132 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1); 5133 5134 return (-1); 5135 } 5136 5137# elif defined(HAVE_GNUTLS) 5138 credentials = (gnutls_certificate_client_credentials *) 5139 malloc(sizeof(gnutls_certificate_client_credentials)); 5140 if (credentials == NULL) 5141 { 5142 DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s", 5143 strerror(errno))); 5144 http->error = errno; 5145 http->status = HTTP_STATUS_ERROR; 5146 _cupsSetHTTPError(HTTP_STATUS_ERROR); 5147 5148 return (-1); 5149 } 5150 5151 gnutls_certificate_allocate_credentials(credentials); 5152 5153 gnutls_init(&http->tls, GNUTLS_CLIENT); 5154 gnutls_set_default_priority(http->tls); 5155 gnutls_server_name_set(http->tls, GNUTLS_NAME_DNS, hostname, 5156 strlen(hostname)); 5157 gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials); 5158 gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr_t)http); 5159 gnutls_transport_set_pull_function(http->tls, _httpReadGNUTLS); 5160 gnutls_transport_set_push_function(http->tls, _httpWriteGNUTLS); 5161 5162 while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS) 5163 { 5164 DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)", 5165 status, gnutls_strerror(status))); 5166 5167 if (gnutls_error_is_fatal(status)) 5168 { 5169 http->error = EIO; 5170 http->status = HTTP_STATUS_ERROR; 5171 5172 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0); 5173 5174 gnutls_deinit(http->tls); 5175 gnutls_certificate_free_credentials(*credentials); 5176 free(credentials); 5177 http->tls = NULL; 5178 5179 return (-1); 5180 } 5181 } 5182 5183 http->tls_credentials = credentials; 5184 5185# elif defined(HAVE_CDSASSL) 5186 if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, 5187 kSSLStreamType)) == NULL) 5188 { 5189 DEBUG_puts("4http_setup_ssl: SSLCreateContext failed."); 5190 http->error = errno = ENOMEM; 5191 http->status = HTTP_STATUS_ERROR; 5192 _cupsSetHTTPError(HTTP_STATUS_ERROR); 5193 5194 return (-1); 5195 } 5196 5197 error = SSLSetConnection(http->tls, http); 5198 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error)); 5199 5200 if (!error) 5201 { 5202 error = SSLSetIOFuncs(http->tls, _httpReadCDSA, _httpWriteCDSA); 5203 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error)); 5204 } 5205 5206 if (!error) 5207 { 5208 error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth, 5209 true); 5210 DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d", 5211 (int)error)); 5212 } 5213 5214 if (!error) 5215 { 5216 if (cg->client_cert_cb) 5217 { 5218 error = SSLSetSessionOption(http->tls, 5219 kSSLSessionOptionBreakOnCertRequested, true); 5220 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, " 5221 "error=%d", (int)error)); 5222 } 5223 else 5224 { 5225 error = http_set_credentials(http); 5226 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d", 5227 (int)error)); 5228 } 5229 } 5230 5231 /* 5232 * Let the server know which hostname/domain we are trying to connect to 5233 * in case it wants to serve up a certificate with a matching common name. 5234 */ 5235 5236 if (!error) 5237 { 5238 error = SSLSetPeerDomainName(http->tls, hostname, strlen(hostname)); 5239 5240 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d", 5241 (int)error)); 5242 } 5243 5244 if (!error) 5245 { 5246 int done = 0; /* Are we done yet? */ 5247 5248 while (!error && !done) 5249 { 5250 error = SSLHandshake(http->tls); 5251 5252 DEBUG_printf(("4http_setup_ssl: SSLHandshake returned %d.", (int)error)); 5253 5254 switch (error) 5255 { 5256 case noErr : 5257 done = 1; 5258 break; 5259 5260 case errSSLWouldBlock : 5261 error = noErr; /* Force a retry */ 5262 usleep(1000); /* in 1 millisecond */ 5263 break; 5264 5265 case errSSLServerAuthCompleted : 5266 error = 0; 5267 if (cg->server_cert_cb) 5268 { 5269 error = httpCopyCredentials(http, &credentials); 5270 if (!error) 5271 { 5272 error = (cg->server_cert_cb)(http, http->tls, credentials, 5273 cg->server_cert_data); 5274 httpFreeCredentials(credentials); 5275 } 5276 5277 DEBUG_printf(("4http_setup_ssl: Server certificate callback " 5278 "returned %d.", (int)error)); 5279 } 5280 break; 5281 5282 case errSSLClientCertRequested : 5283 error = 0; 5284 5285 if (cg->client_cert_cb) 5286 { 5287 names = NULL; 5288 if (!(error = SSLCopyDistinguishedNames(http->tls, &dn_array)) && 5289 dn_array) 5290 { 5291 if ((names = cupsArrayNew(NULL, NULL)) != NULL) 5292 { 5293 for (i = 0, count = CFArrayGetCount(dn_array); i < count; i++) 5294 { 5295 data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i); 5296 5297 if ((credential = malloc(sizeof(*credential))) != NULL) 5298 { 5299 credential->datalen = CFDataGetLength(data); 5300 if ((credential->data = malloc(credential->datalen))) 5301 { 5302 memcpy((void *)credential->data, CFDataGetBytePtr(data), 5303 credential->datalen); 5304 cupsArrayAdd(names, credential); 5305 } 5306 else 5307 free(credential); 5308 } 5309 } 5310 } 5311 5312 CFRelease(dn_array); 5313 } 5314 5315 if (!error) 5316 { 5317 error = (cg->client_cert_cb)(http, http->tls, names, 5318 cg->client_cert_data); 5319 5320 DEBUG_printf(("4http_setup_ssl: Client certificate callback " 5321 "returned %d.", (int)error)); 5322 } 5323 5324 httpFreeCredentials(names); 5325 } 5326 break; 5327 5328 case errSSLUnknownRootCert : 5329 message = _("Unable to establish a secure connection to host " 5330 "(untrusted certificate)."); 5331 break; 5332 5333 case errSSLNoRootCert : 5334 message = _("Unable to establish a secure connection to host " 5335 "(self-signed certificate)."); 5336 break; 5337 5338 case errSSLCertExpired : 5339 message = _("Unable to establish a secure connection to host " 5340 "(expired certificate)."); 5341 break; 5342 5343 case errSSLCertNotYetValid : 5344 message = _("Unable to establish a secure connection to host " 5345 "(certificate not yet valid)."); 5346 break; 5347 5348 case errSSLHostNameMismatch : 5349 message = _("Unable to establish a secure connection to host " 5350 "(host name mismatch)."); 5351 break; 5352 5353 case errSSLXCertChainInvalid : 5354 message = _("Unable to establish a secure connection to host " 5355 "(certificate chain invalid)."); 5356 break; 5357 5358 case errSSLConnectionRefused : 5359 message = _("Unable to establish a secure connection to host " 5360 "(peer dropped connection before responding)."); 5361 break; 5362 5363 default : 5364 break; 5365 } 5366 } 5367 } 5368 5369 if (error) 5370 { 5371 http->error = error; 5372 http->status = HTTP_STATUS_ERROR; 5373 errno = ECONNREFUSED; 5374 5375 CFRelease(http->tls); 5376 http->tls = NULL; 5377 5378 /* 5379 * If an error string wasn't set by the callbacks use a generic one... 5380 */ 5381 5382 if (!message) 5383#ifdef HAVE_CSSMERRORSTRING 5384 message = cssmErrorString(error); 5385#else 5386 message = _("Unable to establish a secure connection to host."); 5387#endif /* HAVE_CSSMERRORSTRING */ 5388 5389 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1); 5390 5391 return (-1); 5392 } 5393 5394# elif defined(HAVE_SSPISSL) 5395 http->tls = _sspiAlloc(); 5396 5397 if (!http->tls) 5398 { 5399 DEBUG_puts("8http_setup_ssl: Unable to allocate SSPI data."); 5400 _cupsSetHTTPError(HTTP_STATUS_ERROR); 5401 return (-1); 5402 } 5403 5404 http->tls->sock = http->fd; 5405 dwSize = sizeof(username) / sizeof(TCHAR); 5406 GetUserName(username, &dwSize); 5407 _sntprintf_s(commonName, sizeof(commonName) / sizeof(TCHAR), 5408 sizeof(commonName) / sizeof(TCHAR), TEXT("CN=%s"), username); 5409 5410 DEBUG_printf(("8http_setup_ssl: commonName=\"%s\"", commonName)); 5411 5412 if (!_sspiGetCredentials(http->tls, L"ClientContainer", commonName, FALSE)) 5413 { 5414 DEBUG_puts("8http_setup_ssl: _sspiGetCredentials failed."); 5415 5416 _sspiFree(http->tls); 5417 http->tls = NULL; 5418 5419 http->error = EIO; 5420 http->status = HTTP_STATUS_ERROR; 5421 5422 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, 5423 _("Unable to establish a secure connection to host."), 1); 5424 5425 return (-1); 5426 } 5427 5428 _sspiSetAllowsAnyRoot(http->tls, TRUE); 5429 _sspiSetAllowsExpiredCerts(http->tls, TRUE); 5430 5431 if (!_sspiConnect(http->tls, hostname)) 5432 { 5433 DEBUG_printf(("8http_setup_ssl: _sspiConnect failed for \"%s\".", hostname)); 5434 5435 _sspiFree(http->tls); 5436 http->tls = NULL; 5437 5438 http->error = EIO; 5439 http->status = HTTP_STATUS_ERROR; 5440 5441 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, 5442 _("Unable to establish a secure connection to host."), 1); 5443 5444 return (-1); 5445 } 5446# endif /* HAVE_CDSASSL */ 5447 5448 return (0); 5449} 5450 5451 5452/* 5453 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection. 5454 */ 5455 5456static void 5457http_shutdown_ssl(http_t *http) /* I - Connection to server */ 5458{ 5459# ifdef HAVE_LIBSSL 5460 SSL_CTX *context; /* Context for encryption */ 5461 5462 context = SSL_get_SSL_CTX(http->tls); 5463 5464 SSL_shutdown(http->tls); 5465 SSL_CTX_free(context); 5466 SSL_free(http->tls); 5467 5468# elif defined(HAVE_GNUTLS) 5469 gnutls_certificate_client_credentials *credentials; 5470 /* TLS credentials */ 5471 5472 credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials); 5473 5474 gnutls_bye(http->tls, GNUTLS_SHUT_RDWR); 5475 gnutls_deinit(http->tls); 5476 gnutls_certificate_free_credentials(*credentials); 5477 free(credentials); 5478 5479# elif defined(HAVE_CDSASSL) 5480 while (SSLClose(http->tls) == errSSLWouldBlock) 5481 usleep(1000); 5482 5483 CFRelease(http->tls); 5484 5485 if (http->tls_credentials) 5486 CFRelease(http->tls_credentials); 5487 5488# elif defined(HAVE_SSPISSL) 5489 _sspiFree(http->tls); 5490# endif /* HAVE_LIBSSL */ 5491 5492 http->tls = NULL; 5493 http->tls_credentials = NULL; 5494} 5495#endif /* HAVE_SSL */ 5496 5497 5498#ifdef DEBUG 5499/* 5500 * 'http_state_string()' - Return the string associated with a given HTTP state. 5501 */ 5502 5503static const char * /* O - State string */ 5504http_state_string(http_state_t state) /* I - HTTP state */ 5505{ 5506 static char buffer[255]; /* Unknown value buffer */ 5507 static const char * const states[] = /* State strings */ 5508 { 5509 "HTTP_STATE_ERROR", 5510 "HTTP_STATE_WAITING", 5511 "HTTP_STATE_OPTIONS", 5512 "HTTP_STATE_GET", 5513 "HTTP_STATE_GET_SEND", 5514 "HTTP_STATE_HEAD", 5515 "HTTP_STATE_POST", 5516 "HTTP_STATE_POST_RECV", 5517 "HTTP_STATE_POST_SEND", 5518 "HTTP_STATE_PUT", 5519 "HTTP_STATE_PUT_RECV", 5520 "HTTP_STATE_DELETE", 5521 "HTTP_STATE_TRACE", 5522 "HTTP_STATE_CONNECT", 5523 "HTTP_STATE_STATUS", 5524 "HTTP_STATE_UNKNOWN_METHOD", 5525 "HTTP_STATE_UNKNOWN_VERSION" 5526 }; 5527 5528 if (state >= HTTP_STATE_ERROR && state <= HTTP_STATE_UNKNOWN_VERSION) 5529 return (states[state - HTTP_STATE_ERROR]); 5530 5531 snprintf(buffer, sizeof(buffer), "??? %d ???", (int)state); 5532 return (buffer); 5533} 5534#endif /* DEBUG */ 5535 5536 5537#ifdef HAVE_SSL 5538/* 5539 * 'http_upgrade()' - Force upgrade to TLS encryption. 5540 */ 5541 5542static int /* O - Status of connection */ 5543http_upgrade(http_t *http) /* I - Connection to server */ 5544{ 5545 int ret; /* Return value */ 5546 http_t myhttp; /* Local copy of HTTP data */ 5547 5548 5549 DEBUG_printf(("7http_upgrade(%p)", http)); 5550 5551 /* 5552 * Flush the connection to make sure any previous "Upgrade" message 5553 * has been read. 5554 */ 5555 5556 httpFlush(http); 5557 5558 /* 5559 * Copy the HTTP data to a local variable so we can do the OPTIONS 5560 * request without interfering with the existing request data... 5561 */ 5562 5563 memcpy(&myhttp, http, sizeof(myhttp)); 5564 5565 /* 5566 * Send an OPTIONS request to the server, requiring SSL or TLS 5567 * encryption on the link... 5568 */ 5569 5570 http->tls_upgrade = 1; 5571 http->field_authorization = NULL; /* Don't free the auth string */ 5572 5573 httpClearFields(http); 5574 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade"); 5575 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0"); 5576 5577 if ((ret = httpOptions(http, "*")) == 0) 5578 { 5579 /* 5580 * Wait for the secure connection... 5581 */ 5582 5583 while (httpUpdate(http) == HTTP_STATUS_CONTINUE); 5584 } 5585 5586 /* 5587 * Restore the HTTP request data... 5588 */ 5589 5590 memcpy(http->fields, myhttp.fields, sizeof(http->fields)); 5591 http->data_encoding = myhttp.data_encoding; 5592 http->data_remaining = myhttp.data_remaining; 5593 http->_data_remaining = myhttp._data_remaining; 5594 http->expect = myhttp.expect; 5595 http->field_authorization = myhttp.field_authorization; 5596 http->digest_tries = myhttp.digest_tries; 5597 http->tls_upgrade = 0; 5598 5599 /* 5600 * See if we actually went secure... 5601 */ 5602 5603 if (!http->tls) 5604 { 5605 /* 5606 * Server does not support HTTP upgrade... 5607 */ 5608 5609 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!"); 5610 5611# ifdef WIN32 5612 closesocket(http->fd); 5613# else 5614 close(http->fd); 5615# endif 5616 5617 http->fd = -1; 5618 5619 return (-1); 5620 } 5621 else 5622 return (ret); 5623} 5624#endif /* HAVE_SSL */ 5625 5626 5627/* 5628 * 'http_write()' - Write a buffer to a HTTP connection. 5629 */ 5630 5631static ssize_t /* O - Number of bytes written */ 5632http_write(http_t *http, /* I - Connection to server */ 5633 const char *buffer, /* I - Buffer for data */ 5634 size_t length) /* I - Number of bytes to write */ 5635{ 5636 ssize_t tbytes, /* Total bytes sent */ 5637 bytes; /* Bytes sent */ 5638 5639 5640 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http, 5641 buffer, CUPS_LLCAST length)); 5642 http->error = 0; 5643 tbytes = 0; 5644 5645 while (length > 0) 5646 { 5647 DEBUG_printf(("3http_write: About to write %d bytes.", (int)length)); 5648 5649 if (http->timeout_cb) 5650 { 5651#ifdef HAVE_POLL 5652 struct pollfd pfd; /* Polled file descriptor */ 5653#else 5654 fd_set output_set; /* Output ready for write? */ 5655 struct timeval timeout; /* Timeout value */ 5656#endif /* HAVE_POLL */ 5657 int nfds; /* Result from select()/poll() */ 5658 5659 do 5660 { 5661#ifdef HAVE_POLL 5662 pfd.fd = http->fd; 5663 pfd.events = POLLOUT; 5664 5665 while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 && 5666 (errno == EINTR || errno == EAGAIN)) 5667 /* do nothing */; 5668 5669#else 5670 do 5671 { 5672 FD_ZERO(&output_set); 5673 FD_SET(http->fd, &output_set); 5674 5675 timeout.tv_sec = http->wait_value / 1000; 5676 timeout.tv_usec = 1000 * (http->wait_value % 1000); 5677 5678 nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout); 5679 } 5680# ifdef WIN32 5681 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || 5682 WSAGetLastError() == WSAEWOULDBLOCK)); 5683# else 5684 while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); 5685# endif /* WIN32 */ 5686#endif /* HAVE_POLL */ 5687 5688 if (nfds < 0) 5689 { 5690 http->error = errno; 5691 return (-1); 5692 } 5693 else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data)) 5694 { 5695#ifdef WIN32 5696 http->error = WSAEWOULDBLOCK; 5697#else 5698 http->error = EWOULDBLOCK; 5699#endif /* WIN32 */ 5700 return (-1); 5701 } 5702 } 5703 while (nfds <= 0); 5704 } 5705 5706#ifdef HAVE_SSL 5707 if (http->tls) 5708 bytes = http_write_ssl(http, buffer, length); 5709 else 5710#endif /* HAVE_SSL */ 5711 bytes = send(http->fd, buffer, length, 0); 5712 5713 DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned " 5714 CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes)); 5715 5716 if (bytes < 0) 5717 { 5718#ifdef WIN32 5719 if (WSAGetLastError() == WSAEINTR) 5720 continue; 5721 else if (WSAGetLastError() == WSAEWOULDBLOCK) 5722 { 5723 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 5724 continue; 5725 5726 http->error = WSAGetLastError(); 5727 } 5728 else if (WSAGetLastError() != http->error && 5729 WSAGetLastError() != WSAECONNRESET) 5730 { 5731 http->error = WSAGetLastError(); 5732 continue; 5733 } 5734 5735#else 5736 if (errno == EINTR) 5737 continue; 5738 else if (errno == EWOULDBLOCK || errno == EAGAIN) 5739 { 5740 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) 5741 continue; 5742 else if (!http->timeout_cb && errno == EAGAIN) 5743 continue; 5744 5745 http->error = errno; 5746 } 5747 else if (errno != http->error && errno != ECONNRESET) 5748 { 5749 http->error = errno; 5750 continue; 5751 } 5752#endif /* WIN32 */ 5753 5754 DEBUG_printf(("3http_write: error writing data (%s).", 5755 strerror(http->error))); 5756 5757 return (-1); 5758 } 5759 5760 buffer += bytes; 5761 tbytes += bytes; 5762 length -= bytes; 5763 } 5764 5765#ifdef DEBUG 5766 http_debug_hex("http_write", buffer - tbytes, tbytes); 5767#endif /* DEBUG */ 5768 5769 DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes)); 5770 5771 return (tbytes); 5772} 5773 5774 5775/* 5776 * 'http_write_chunk()' - Write a chunked buffer. 5777 */ 5778 5779static ssize_t /* O - Number bytes written */ 5780http_write_chunk(http_t *http, /* I - Connection to server */ 5781 const char *buffer, /* I - Buffer to write */ 5782 size_t length) /* I - Length of buffer */ 5783{ 5784 char header[16]; /* Chunk header */ 5785 ssize_t bytes; /* Bytes written */ 5786 5787 5788 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", 5789 http, buffer, CUPS_LLCAST length)); 5790 5791 /* 5792 * Write the chunk header, data, and trailer. 5793 */ 5794 5795 snprintf(header, sizeof(header), "%x\r\n", (unsigned)length); 5796 if (http_write(http, header, strlen(header)) < 0) 5797 { 5798 DEBUG_puts("8http_write_chunk: http_write of length failed."); 5799 return (-1); 5800 } 5801 5802 if ((bytes = http_write(http, buffer, length)) < 0) 5803 { 5804 DEBUG_puts("8http_write_chunk: http_write of buffer failed."); 5805 return (-1); 5806 } 5807 5808 if (http_write(http, "\r\n", 2) < 0) 5809 { 5810 DEBUG_puts("8http_write_chunk: http_write of CR LF failed."); 5811 return (-1); 5812 } 5813 5814 return (bytes); 5815} 5816 5817 5818#ifdef HAVE_SSL 5819/* 5820 * 'http_write_ssl()' - Write to a SSL/TLS connection. 5821 */ 5822 5823static int /* O - Bytes written */ 5824http_write_ssl(http_t *http, /* I - Connection to server */ 5825 const char *buf, /* I - Buffer holding data */ 5826 int len) /* I - Length of buffer */ 5827{ 5828 ssize_t result; /* Return value */ 5829 5830 5831 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len)); 5832 5833# if defined(HAVE_LIBSSL) 5834 result = SSL_write((SSL *)(http->tls), buf, len); 5835 5836# elif defined(HAVE_GNUTLS) 5837 result = gnutls_record_send(http->tls, buf, len); 5838 5839 if (result < 0 && !errno) 5840 { 5841 /* 5842 * Convert GNU TLS error to errno value... 5843 */ 5844 5845 switch (result) 5846 { 5847 case GNUTLS_E_INTERRUPTED : 5848 errno = EINTR; 5849 break; 5850 5851 case GNUTLS_E_AGAIN : 5852 errno = EAGAIN; 5853 break; 5854 5855 default : 5856 errno = EPIPE; 5857 break; 5858 } 5859 5860 result = -1; 5861 } 5862 5863# elif defined(HAVE_CDSASSL) 5864 OSStatus error; /* Error info */ 5865 size_t processed; /* Number of bytes processed */ 5866 5867 5868 error = SSLWrite(http->tls, buf, len, &processed); 5869 5870 switch (error) 5871 { 5872 case 0 : 5873 result = (int)processed; 5874 break; 5875 5876 case errSSLWouldBlock : 5877 if (processed) 5878 result = (int)processed; 5879 else 5880 { 5881 result = -1; 5882 errno = EINTR; 5883 } 5884 break; 5885 5886 case errSSLClosedGraceful : 5887 default : 5888 if (processed) 5889 result = (int)processed; 5890 else 5891 { 5892 result = -1; 5893 errno = EPIPE; 5894 } 5895 break; 5896 } 5897# elif defined(HAVE_SSPISSL) 5898 return _sspiWrite((_sspi_struct_t *)http->tls, (void *)buf, len); 5899# endif /* HAVE_LIBSSL */ 5900 5901 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result)); 5902 5903 return ((int)result); 5904} 5905#endif /* HAVE_SSL */ 5906 5907 5908/* 5909 * End of "$Id: http.c 11780 2014-03-28 20:51:12Z msweet $". 5910 */ 5911