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