strerror.c (25884B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #ifdef HAVE_STRERROR_R 28 # if (!defined(HAVE_POSIX_STRERROR_R) && \ 29 !defined(HAVE_GLIBC_STRERROR_R)) || \ 30 (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) 31 # error "strerror_r MUST be either POSIX, glibc style" 32 # endif 33 #endif 34 35 #include <curl/curl.h> 36 37 #ifdef USE_LIBIDN2 38 #include <idn2.h> 39 #endif 40 41 #ifdef USE_WINDOWS_SSPI 42 #include "curl_sspi.h" 43 #endif 44 45 #include "curlx/winapi.h" 46 #include "strerror.h" 47 /* The last 3 #include files should be in this order */ 48 #include "curl_printf.h" 49 #include "curl_memory.h" 50 #include "memdebug.h" 51 52 const char * 53 curl_easy_strerror(CURLcode error) 54 { 55 #ifndef CURL_DISABLE_VERBOSE_STRINGS 56 switch(error) { 57 case CURLE_OK: 58 return "No error"; 59 60 case CURLE_UNSUPPORTED_PROTOCOL: 61 return "Unsupported protocol"; 62 63 case CURLE_FAILED_INIT: 64 return "Failed initialization"; 65 66 case CURLE_URL_MALFORMAT: 67 return "URL using bad/illegal format or missing URL"; 68 69 case CURLE_NOT_BUILT_IN: 70 return "A requested feature, protocol or option was not found built-in in" 71 " this libcurl due to a build-time decision."; 72 73 case CURLE_COULDNT_RESOLVE_PROXY: 74 return "Could not resolve proxy name"; 75 76 case CURLE_COULDNT_RESOLVE_HOST: 77 return "Could not resolve hostname"; 78 79 case CURLE_COULDNT_CONNECT: 80 return "Could not connect to server"; 81 82 case CURLE_WEIRD_SERVER_REPLY: 83 return "Weird server reply"; 84 85 case CURLE_REMOTE_ACCESS_DENIED: 86 return "Access denied to remote resource"; 87 88 case CURLE_FTP_ACCEPT_FAILED: 89 return "FTP: The server failed to connect to data port"; 90 91 case CURLE_FTP_ACCEPT_TIMEOUT: 92 return "FTP: Accepting server connect has timed out"; 93 94 case CURLE_FTP_PRET_FAILED: 95 return "FTP: The server did not accept the PRET command."; 96 97 case CURLE_FTP_WEIRD_PASS_REPLY: 98 return "FTP: unknown PASS reply"; 99 100 case CURLE_FTP_WEIRD_PASV_REPLY: 101 return "FTP: unknown PASV reply"; 102 103 case CURLE_FTP_WEIRD_227_FORMAT: 104 return "FTP: unknown 227 response format"; 105 106 case CURLE_FTP_CANT_GET_HOST: 107 return "FTP: cannot figure out the host in the PASV response"; 108 109 case CURLE_HTTP2: 110 return "Error in the HTTP2 framing layer"; 111 112 case CURLE_FTP_COULDNT_SET_TYPE: 113 return "FTP: could not set file type"; 114 115 case CURLE_PARTIAL_FILE: 116 return "Transferred a partial file"; 117 118 case CURLE_FTP_COULDNT_RETR_FILE: 119 return "FTP: could not retrieve (RETR failed) the specified file"; 120 121 case CURLE_QUOTE_ERROR: 122 return "Quote command returned error"; 123 124 case CURLE_HTTP_RETURNED_ERROR: 125 return "HTTP response code said error"; 126 127 case CURLE_WRITE_ERROR: 128 return "Failed writing received data to disk/application"; 129 130 case CURLE_UPLOAD_FAILED: 131 return "Upload failed (at start/before it took off)"; 132 133 case CURLE_READ_ERROR: 134 return "Failed to open/read local data from file/application"; 135 136 case CURLE_OUT_OF_MEMORY: 137 return "Out of memory"; 138 139 case CURLE_OPERATION_TIMEDOUT: 140 return "Timeout was reached"; 141 142 case CURLE_FTP_PORT_FAILED: 143 return "FTP: command PORT failed"; 144 145 case CURLE_FTP_COULDNT_USE_REST: 146 return "FTP: command REST failed"; 147 148 case CURLE_RANGE_ERROR: 149 return "Requested range was not delivered by the server"; 150 151 case CURLE_SSL_CONNECT_ERROR: 152 return "SSL connect error"; 153 154 case CURLE_BAD_DOWNLOAD_RESUME: 155 return "Could not resume download"; 156 157 case CURLE_FILE_COULDNT_READ_FILE: 158 return "Could not read a file:// file"; 159 160 case CURLE_LDAP_CANNOT_BIND: 161 return "LDAP: cannot bind"; 162 163 case CURLE_LDAP_SEARCH_FAILED: 164 return "LDAP: search failed"; 165 166 case CURLE_ABORTED_BY_CALLBACK: 167 return "Operation was aborted by an application callback"; 168 169 case CURLE_BAD_FUNCTION_ARGUMENT: 170 return "A libcurl function was given a bad argument"; 171 172 case CURLE_INTERFACE_FAILED: 173 return "Failed binding local connection end"; 174 175 case CURLE_TOO_MANY_REDIRECTS: 176 return "Number of redirects hit maximum amount"; 177 178 case CURLE_UNKNOWN_OPTION: 179 return "An unknown option was passed in to libcurl"; 180 181 case CURLE_SETOPT_OPTION_SYNTAX: 182 return "Malformed option provided in a setopt"; 183 184 case CURLE_GOT_NOTHING: 185 return "Server returned nothing (no headers, no data)"; 186 187 case CURLE_SSL_ENGINE_NOTFOUND: 188 return "SSL crypto engine not found"; 189 190 case CURLE_SSL_ENGINE_SETFAILED: 191 return "Can not set SSL crypto engine as default"; 192 193 case CURLE_SSL_ENGINE_INITFAILED: 194 return "Failed to initialise SSL crypto engine"; 195 196 case CURLE_SEND_ERROR: 197 return "Failed sending data to the peer"; 198 199 case CURLE_RECV_ERROR: 200 return "Failure when receiving data from the peer"; 201 202 case CURLE_SSL_CERTPROBLEM: 203 return "Problem with the local SSL certificate"; 204 205 case CURLE_SSL_CIPHER: 206 return "Could not use specified SSL cipher"; 207 208 case CURLE_PEER_FAILED_VERIFICATION: 209 return "SSL peer certificate or SSH remote key was not OK"; 210 211 case CURLE_SSL_CACERT_BADFILE: 212 return "Problem with the SSL CA cert (path? access rights?)"; 213 214 case CURLE_BAD_CONTENT_ENCODING: 215 return "Unrecognized or bad HTTP Content or Transfer-Encoding"; 216 217 case CURLE_FILESIZE_EXCEEDED: 218 return "Maximum file size exceeded"; 219 220 case CURLE_USE_SSL_FAILED: 221 return "Requested SSL level failed"; 222 223 case CURLE_SSL_SHUTDOWN_FAILED: 224 return "Failed to shut down the SSL connection"; 225 226 case CURLE_SSL_CRL_BADFILE: 227 return "Failed to load CRL file (path? access rights?, format?)"; 228 229 case CURLE_SSL_ISSUER_ERROR: 230 return "Issuer check against peer certificate failed"; 231 232 case CURLE_SEND_FAIL_REWIND: 233 return "Send failed since rewinding of the data stream failed"; 234 235 case CURLE_LOGIN_DENIED: 236 return "Login denied"; 237 238 case CURLE_TFTP_NOTFOUND: 239 return "TFTP: File Not Found"; 240 241 case CURLE_TFTP_PERM: 242 return "TFTP: Access Violation"; 243 244 case CURLE_REMOTE_DISK_FULL: 245 return "Disk full or allocation exceeded"; 246 247 case CURLE_TFTP_ILLEGAL: 248 return "TFTP: Illegal operation"; 249 250 case CURLE_TFTP_UNKNOWNID: 251 return "TFTP: Unknown transfer ID"; 252 253 case CURLE_REMOTE_FILE_EXISTS: 254 return "Remote file already exists"; 255 256 case CURLE_TFTP_NOSUCHUSER: 257 return "TFTP: No such user"; 258 259 case CURLE_REMOTE_FILE_NOT_FOUND: 260 return "Remote file not found"; 261 262 case CURLE_SSH: 263 return "Error in the SSH layer"; 264 265 case CURLE_AGAIN: 266 return "Socket not ready for send/recv"; 267 268 case CURLE_RTSP_CSEQ_ERROR: 269 return "RTSP CSeq mismatch or invalid CSeq"; 270 271 case CURLE_RTSP_SESSION_ERROR: 272 return "RTSP session error"; 273 274 case CURLE_FTP_BAD_FILE_LIST: 275 return "Unable to parse FTP file list"; 276 277 case CURLE_CHUNK_FAILED: 278 return "Chunk callback failed"; 279 280 case CURLE_NO_CONNECTION_AVAILABLE: 281 return "The max connection limit is reached"; 282 283 case CURLE_SSL_PINNEDPUBKEYNOTMATCH: 284 return "SSL public key does not match pinned public key"; 285 286 case CURLE_SSL_INVALIDCERTSTATUS: 287 return "SSL server certificate status verification FAILED"; 288 289 case CURLE_HTTP2_STREAM: 290 return "Stream error in the HTTP/2 framing layer"; 291 292 case CURLE_RECURSIVE_API_CALL: 293 return "API function called from within callback"; 294 295 case CURLE_AUTH_ERROR: 296 return "An authentication function returned an error"; 297 298 case CURLE_HTTP3: 299 return "HTTP/3 error"; 300 301 case CURLE_QUIC_CONNECT_ERROR: 302 return "QUIC connection error"; 303 304 case CURLE_PROXY: 305 return "proxy handshake error"; 306 307 case CURLE_SSL_CLIENTCERT: 308 return "SSL Client Certificate required"; 309 310 case CURLE_UNRECOVERABLE_POLL: 311 return "Unrecoverable error in select/poll"; 312 313 case CURLE_TOO_LARGE: 314 return "A value or data field grew larger than allowed"; 315 316 case CURLE_ECH_REQUIRED: 317 return "ECH attempted but failed"; 318 319 /* error codes not used by current libcurl */ 320 default: 321 break; 322 } 323 /* 324 * By using a switch, gcc -Wall will complain about enum values 325 * which do not appear, helping keep this function up-to-date. 326 * By using gcc -Wall -Werror, you cannot forget. 327 * 328 * A table would not have the same benefit. Most compilers will generate 329 * code similar to a table in any case, so there is little performance gain 330 * from a table. Something is broken for the user's application, anyways, so 331 * does it matter how fast it _does not_ work? 332 * 333 * The line number for the error will be near this comment, which is why it 334 * is here, and not at the start of the switch. 335 */ 336 return "Unknown error"; 337 #else 338 if(!error) 339 return "No error"; 340 else 341 return "Error"; 342 #endif 343 } 344 345 const char * 346 curl_multi_strerror(CURLMcode error) 347 { 348 #ifndef CURL_DISABLE_VERBOSE_STRINGS 349 switch(error) { 350 case CURLM_CALL_MULTI_PERFORM: 351 return "Please call curl_multi_perform() soon"; 352 353 case CURLM_OK: 354 return "No error"; 355 356 case CURLM_BAD_HANDLE: 357 return "Invalid multi handle"; 358 359 case CURLM_BAD_EASY_HANDLE: 360 return "Invalid easy handle"; 361 362 case CURLM_OUT_OF_MEMORY: 363 return "Out of memory"; 364 365 case CURLM_INTERNAL_ERROR: 366 return "Internal error"; 367 368 case CURLM_BAD_SOCKET: 369 return "Invalid socket argument"; 370 371 case CURLM_UNKNOWN_OPTION: 372 return "Unknown option"; 373 374 case CURLM_ADDED_ALREADY: 375 return "The easy handle is already added to a multi handle"; 376 377 case CURLM_RECURSIVE_API_CALL: 378 return "API function called from within callback"; 379 380 case CURLM_WAKEUP_FAILURE: 381 return "Wakeup is unavailable or failed"; 382 383 case CURLM_BAD_FUNCTION_ARGUMENT: 384 return "A libcurl function was given a bad argument"; 385 386 case CURLM_ABORTED_BY_CALLBACK: 387 return "Operation was aborted by an application callback"; 388 389 case CURLM_UNRECOVERABLE_POLL: 390 return "Unrecoverable error in select/poll"; 391 392 case CURLM_LAST: 393 break; 394 } 395 396 return "Unknown error"; 397 #else 398 if(error == CURLM_OK) 399 return "No error"; 400 else 401 return "Error"; 402 #endif 403 } 404 405 const char * 406 curl_share_strerror(CURLSHcode error) 407 { 408 #ifndef CURL_DISABLE_VERBOSE_STRINGS 409 switch(error) { 410 case CURLSHE_OK: 411 return "No error"; 412 413 case CURLSHE_BAD_OPTION: 414 return "Unknown share option"; 415 416 case CURLSHE_IN_USE: 417 return "Share currently in use"; 418 419 case CURLSHE_INVALID: 420 return "Invalid share handle"; 421 422 case CURLSHE_NOMEM: 423 return "Out of memory"; 424 425 case CURLSHE_NOT_BUILT_IN: 426 return "Feature not enabled in this library"; 427 428 case CURLSHE_LAST: 429 break; 430 } 431 432 return "CURLSHcode unknown"; 433 #else 434 if(error == CURLSHE_OK) 435 return "No error"; 436 else 437 return "Error"; 438 #endif 439 } 440 441 const char * 442 curl_url_strerror(CURLUcode error) 443 { 444 #ifndef CURL_DISABLE_VERBOSE_STRINGS 445 switch(error) { 446 case CURLUE_OK: 447 return "No error"; 448 449 case CURLUE_BAD_HANDLE: 450 return "An invalid CURLU pointer was passed as argument"; 451 452 case CURLUE_BAD_PARTPOINTER: 453 return "An invalid 'part' argument was passed as argument"; 454 455 case CURLUE_MALFORMED_INPUT: 456 return "Malformed input to a URL function"; 457 458 case CURLUE_BAD_PORT_NUMBER: 459 return "Port number was not a decimal number between 0 and 65535"; 460 461 case CURLUE_UNSUPPORTED_SCHEME: 462 return "Unsupported URL scheme"; 463 464 case CURLUE_URLDECODE: 465 return "URL decode error, most likely because of rubbish in the input"; 466 467 case CURLUE_OUT_OF_MEMORY: 468 return "A memory function failed"; 469 470 case CURLUE_USER_NOT_ALLOWED: 471 return "Credentials was passed in the URL when prohibited"; 472 473 case CURLUE_UNKNOWN_PART: 474 return "An unknown part ID was passed to a URL API function"; 475 476 case CURLUE_NO_SCHEME: 477 return "No scheme part in the URL"; 478 479 case CURLUE_NO_USER: 480 return "No user part in the URL"; 481 482 case CURLUE_NO_PASSWORD: 483 return "No password part in the URL"; 484 485 case CURLUE_NO_OPTIONS: 486 return "No options part in the URL"; 487 488 case CURLUE_NO_HOST: 489 return "No host part in the URL"; 490 491 case CURLUE_NO_PORT: 492 return "No port part in the URL"; 493 494 case CURLUE_NO_QUERY: 495 return "No query part in the URL"; 496 497 case CURLUE_NO_FRAGMENT: 498 return "No fragment part in the URL"; 499 500 case CURLUE_NO_ZONEID: 501 return "No zoneid part in the URL"; 502 503 case CURLUE_BAD_LOGIN: 504 return "Bad login part"; 505 506 case CURLUE_BAD_IPV6: 507 return "Bad IPv6 address"; 508 509 case CURLUE_BAD_HOSTNAME: 510 return "Bad hostname"; 511 512 case CURLUE_BAD_FILE_URL: 513 return "Bad file:// URL"; 514 515 case CURLUE_BAD_SLASHES: 516 return "Unsupported number of slashes following scheme"; 517 518 case CURLUE_BAD_SCHEME: 519 return "Bad scheme"; 520 521 case CURLUE_BAD_PATH: 522 return "Bad path"; 523 524 case CURLUE_BAD_FRAGMENT: 525 return "Bad fragment"; 526 527 case CURLUE_BAD_QUERY: 528 return "Bad query"; 529 530 case CURLUE_BAD_PASSWORD: 531 return "Bad password"; 532 533 case CURLUE_BAD_USER: 534 return "Bad user"; 535 536 case CURLUE_LACKS_IDN: 537 return "libcurl lacks IDN support"; 538 539 case CURLUE_TOO_LARGE: 540 return "A value or data field is larger than allowed"; 541 542 case CURLUE_LAST: 543 break; 544 } 545 546 return "CURLUcode unknown"; 547 #else 548 if(error == CURLUE_OK) 549 return "No error"; 550 else 551 return "Error"; 552 #endif 553 } 554 555 #ifdef USE_WINSOCK 556 /* This is a helper function for Curl_strerror that converts Winsock error 557 * codes (WSAGetLastError) to error messages. 558 * Returns NULL if no error message was found for error code. 559 */ 560 static const char * 561 get_winsock_error(int err, char *buf, size_t len) 562 { 563 #ifndef CURL_DISABLE_VERBOSE_STRINGS 564 const char *p; 565 size_t alen; 566 #endif 567 568 if(!len) 569 return NULL; 570 571 *buf = '\0'; 572 573 #ifdef CURL_DISABLE_VERBOSE_STRINGS 574 (void)err; 575 return NULL; 576 #else 577 switch(err) { 578 case WSAEINTR: 579 p = "Call interrupted"; 580 break; 581 case WSAEBADF: 582 p = "Bad file"; 583 break; 584 case WSAEACCES: 585 p = "Bad access"; 586 break; 587 case WSAEFAULT: 588 p = "Bad argument"; 589 break; 590 case WSAEINVAL: 591 p = "Invalid arguments"; 592 break; 593 case WSAEMFILE: 594 p = "Out of file descriptors"; 595 break; 596 case WSAEWOULDBLOCK: 597 p = "Call would block"; 598 break; 599 case WSAEINPROGRESS: 600 case WSAEALREADY: 601 p = "Blocking call in progress"; 602 break; 603 case WSAENOTSOCK: 604 p = "Descriptor is not a socket"; 605 break; 606 case WSAEDESTADDRREQ: 607 p = "Need destination address"; 608 break; 609 case WSAEMSGSIZE: 610 p = "Bad message size"; 611 break; 612 case WSAEPROTOTYPE: 613 p = "Bad protocol"; 614 break; 615 case WSAENOPROTOOPT: 616 p = "Protocol option is unsupported"; 617 break; 618 case WSAEPROTONOSUPPORT: 619 p = "Protocol is unsupported"; 620 break; 621 case WSAESOCKTNOSUPPORT: 622 p = "Socket is unsupported"; 623 break; 624 case WSAEOPNOTSUPP: 625 p = "Operation not supported"; 626 break; 627 case WSAEAFNOSUPPORT: 628 p = "Address family not supported"; 629 break; 630 case WSAEPFNOSUPPORT: 631 p = "Protocol family not supported"; 632 break; 633 case WSAEADDRINUSE: 634 p = "Address already in use"; 635 break; 636 case WSAEADDRNOTAVAIL: 637 p = "Address not available"; 638 break; 639 case WSAENETDOWN: 640 p = "Network down"; 641 break; 642 case WSAENETUNREACH: 643 p = "Network unreachable"; 644 break; 645 case WSAENETRESET: 646 p = "Network has been reset"; 647 break; 648 case WSAECONNABORTED: 649 p = "Connection was aborted"; 650 break; 651 case WSAECONNRESET: 652 p = "Connection was reset"; 653 break; 654 case WSAENOBUFS: 655 p = "No buffer space"; 656 break; 657 case WSAEISCONN: 658 p = "Socket is already connected"; 659 break; 660 case WSAENOTCONN: 661 p = "Socket is not connected"; 662 break; 663 case WSAESHUTDOWN: 664 p = "Socket has been shut down"; 665 break; 666 case WSAETOOMANYREFS: 667 p = "Too many references"; 668 break; 669 case WSAETIMEDOUT: 670 p = "Timed out"; 671 break; 672 case WSAECONNREFUSED: 673 p = "Connection refused"; 674 break; 675 case WSAELOOP: 676 p = "Loop??"; 677 break; 678 case WSAENAMETOOLONG: 679 p = "Name too long"; 680 break; 681 case WSAEHOSTDOWN: 682 p = "Host down"; 683 break; 684 case WSAEHOSTUNREACH: 685 p = "Host unreachable"; 686 break; 687 case WSAENOTEMPTY: 688 p = "Not empty"; 689 break; 690 case WSAEPROCLIM: 691 p = "Process limit reached"; 692 break; 693 case WSAEUSERS: 694 p = "Too many users"; 695 break; 696 case WSAEDQUOT: 697 p = "Bad quota"; 698 break; 699 case WSAESTALE: 700 p = "Something is stale"; 701 break; 702 case WSAEREMOTE: 703 p = "Remote error"; 704 break; 705 #ifdef WSAEDISCON /* missing in SalfordC! */ 706 case WSAEDISCON: 707 p = "Disconnected"; 708 break; 709 #endif 710 /* Extended Winsock errors */ 711 case WSASYSNOTREADY: 712 p = "Winsock library is not ready"; 713 break; 714 case WSANOTINITIALISED: 715 p = "Winsock library not initialised"; 716 break; 717 case WSAVERNOTSUPPORTED: 718 p = "Winsock version not supported"; 719 break; 720 721 /* getXbyY() errors (already handled in herrmsg): 722 * Authoritative Answer: Host not found */ 723 case WSAHOST_NOT_FOUND: 724 p = "Host not found"; 725 break; 726 727 /* Non-Authoritative: Host not found, or SERVERFAIL */ 728 case WSATRY_AGAIN: 729 p = "Host not found, try again"; 730 break; 731 732 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ 733 case WSANO_RECOVERY: 734 p = "Unrecoverable error in call to nameserver"; 735 break; 736 737 /* Valid name, no data record of requested type */ 738 case WSANO_DATA: 739 p = "No data record of requested type"; 740 break; 741 742 default: 743 return NULL; 744 } 745 alen = strlen(p); 746 if(alen < len) 747 strcpy(buf, p); 748 return buf; 749 #endif 750 } 751 #endif /* USE_WINSOCK */ 752 753 /* 754 * Our thread-safe and smart strerror() replacement. 755 * 756 * The 'err' argument passed in to this function MUST be a true errno number 757 * as reported on this system. We do no range checking on the number before 758 * we pass it to the "number-to-message" conversion function and there might 759 * be systems that do not do proper range checking in there themselves. 760 * 761 * We do not do range checking (on systems other than Windows) since there is 762 * no good reliable and portable way to do it. 763 * 764 * On Windows different types of error codes overlap. This function has an 765 * order of preference when trying to match error codes: 766 * CRT (errno), Winsock (WSAGetLastError), Windows API (GetLastError). 767 * 768 * It may be more correct to call one of the variant functions instead: 769 * Call Curl_sspi_strerror if the error code is definitely Windows SSPI. 770 * Call curlx_winapi_strerror if the error code is definitely Windows API. 771 */ 772 const char *Curl_strerror(int err, char *buf, size_t buflen) 773 { 774 #ifdef _WIN32 775 DWORD old_win_err = GetLastError(); 776 #endif 777 int old_errno = errno; 778 char *p; 779 780 if(!buflen) 781 return NULL; 782 783 #ifndef _WIN32 784 DEBUGASSERT(err >= 0); 785 #endif 786 787 *buf = '\0'; 788 789 #ifdef _WIN32 790 #ifndef UNDER_CE 791 /* 'sys_nerr' is the maximum errno number, it is not widely portable */ 792 if(err >= 0 && err < sys_nerr) 793 curl_msnprintf(buf, buflen, "%s", sys_errlist[err]); 794 else 795 #endif 796 { 797 if( 798 #ifdef USE_WINSOCK 799 !get_winsock_error(err, buf, buflen) && 800 #endif 801 !curlx_get_winapi_error(err, buf, buflen)) 802 curl_msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err); 803 } 804 #else /* not Windows coming up */ 805 806 #if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) 807 /* 808 * The POSIX-style strerror_r() may set errno to ERANGE if insufficient 809 * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated 810 * message string, or EINVAL if 'errnum' is not a valid error number. 811 */ 812 if(0 != strerror_r(err, buf, buflen)) { 813 if('\0' == buf[0]) 814 curl_msnprintf(buf, buflen, "Unknown error %d", err); 815 } 816 #elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) 817 /* 818 * The glibc-style strerror_r() only *might* use the buffer we pass to 819 * the function, but it always returns the error message as a pointer, 820 * so we must copy that string unconditionally (if non-NULL). 821 */ 822 { 823 char buffer[256]; 824 char *msg = strerror_r(err, buffer, sizeof(buffer)); 825 if(msg) 826 curl_msnprintf(buf, buflen, "%s", msg); 827 else 828 curl_msnprintf(buf, buflen, "Unknown error %d", err); 829 } 830 #else 831 { 832 /* !checksrc! disable BANNEDFUNC 1 */ 833 const char *msg = strerror(err); 834 if(msg) 835 curl_msnprintf(buf, buflen, "%s", msg); 836 else 837 curl_msnprintf(buf, buflen, "Unknown error %d", err); 838 } 839 #endif 840 841 #endif /* end of not Windows */ 842 843 /* strip trailing '\r\n' or '\n'. */ 844 p = strrchr(buf, '\n'); 845 if(p && (p - buf) >= 2) 846 *p = '\0'; 847 p = strrchr(buf, '\r'); 848 if(p && (p - buf) >= 1) 849 *p = '\0'; 850 851 if(errno != old_errno) 852 CURL_SETERRNO(old_errno); 853 854 #ifdef _WIN32 855 if(old_win_err != GetLastError()) 856 SetLastError(old_win_err); 857 #endif 858 859 return buf; 860 } 861 862 #ifdef USE_WINDOWS_SSPI 863 /* 864 * Curl_sspi_strerror: 865 * Variant of Curl_strerror if the error code is definitely Windows SSPI. 866 */ 867 const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) 868 { 869 #ifdef _WIN32 870 DWORD old_win_err = GetLastError(); 871 #endif 872 int old_errno = errno; 873 const char *txt; 874 875 if(!buflen) 876 return NULL; 877 878 *buf = '\0'; 879 880 #ifndef CURL_DISABLE_VERBOSE_STRINGS 881 882 switch(err) { 883 case SEC_E_OK: 884 txt = "No error"; 885 break; 886 #define SEC2TXT(sec) case sec: txt = #sec; break 887 SEC2TXT(CRYPT_E_REVOKED); 888 SEC2TXT(CRYPT_E_NO_REVOCATION_DLL); 889 SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK); 890 SEC2TXT(CRYPT_E_REVOCATION_OFFLINE); 891 SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE); 892 SEC2TXT(SEC_E_ALGORITHM_MISMATCH); 893 SEC2TXT(SEC_E_BAD_BINDINGS); 894 SEC2TXT(SEC_E_BAD_PKGID); 895 SEC2TXT(SEC_E_BUFFER_TOO_SMALL); 896 SEC2TXT(SEC_E_CANNOT_INSTALL); 897 SEC2TXT(SEC_E_CANNOT_PACK); 898 SEC2TXT(SEC_E_CERT_EXPIRED); 899 SEC2TXT(SEC_E_CERT_UNKNOWN); 900 SEC2TXT(SEC_E_CERT_WRONG_USAGE); 901 SEC2TXT(SEC_E_CONTEXT_EXPIRED); 902 SEC2TXT(SEC_E_CROSSREALM_DELEGATION_FAILURE); 903 SEC2TXT(SEC_E_CRYPTO_SYSTEM_INVALID); 904 SEC2TXT(SEC_E_DECRYPT_FAILURE); 905 SEC2TXT(SEC_E_DELEGATION_POLICY); 906 SEC2TXT(SEC_E_DELEGATION_REQUIRED); 907 SEC2TXT(SEC_E_DOWNGRADE_DETECTED); 908 SEC2TXT(SEC_E_ENCRYPT_FAILURE); 909 SEC2TXT(SEC_E_ILLEGAL_MESSAGE); 910 SEC2TXT(SEC_E_INCOMPLETE_CREDENTIALS); 911 SEC2TXT(SEC_E_INCOMPLETE_MESSAGE); 912 SEC2TXT(SEC_E_INSUFFICIENT_MEMORY); 913 SEC2TXT(SEC_E_INTERNAL_ERROR); 914 SEC2TXT(SEC_E_INVALID_HANDLE); 915 SEC2TXT(SEC_E_INVALID_PARAMETER); 916 SEC2TXT(SEC_E_INVALID_TOKEN); 917 SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED); 918 SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED_KDC); 919 SEC2TXT(SEC_E_KDC_CERT_EXPIRED); 920 SEC2TXT(SEC_E_KDC_CERT_REVOKED); 921 SEC2TXT(SEC_E_KDC_INVALID_REQUEST); 922 SEC2TXT(SEC_E_KDC_UNABLE_TO_REFER); 923 SEC2TXT(SEC_E_KDC_UNKNOWN_ETYPE); 924 SEC2TXT(SEC_E_LOGON_DENIED); 925 SEC2TXT(SEC_E_MAX_REFERRALS_EXCEEDED); 926 SEC2TXT(SEC_E_MESSAGE_ALTERED); 927 SEC2TXT(SEC_E_MULTIPLE_ACCOUNTS); 928 SEC2TXT(SEC_E_MUST_BE_KDC); 929 SEC2TXT(SEC_E_NOT_OWNER); 930 SEC2TXT(SEC_E_NO_AUTHENTICATING_AUTHORITY); 931 SEC2TXT(SEC_E_NO_CREDENTIALS); 932 SEC2TXT(SEC_E_NO_IMPERSONATION); 933 SEC2TXT(SEC_E_NO_IP_ADDRESSES); 934 SEC2TXT(SEC_E_NO_KERB_KEY); 935 SEC2TXT(SEC_E_NO_PA_DATA); 936 SEC2TXT(SEC_E_NO_S4U_PROT_SUPPORT); 937 SEC2TXT(SEC_E_NO_TGT_REPLY); 938 SEC2TXT(SEC_E_OUT_OF_SEQUENCE); 939 SEC2TXT(SEC_E_PKINIT_CLIENT_FAILURE); 940 SEC2TXT(SEC_E_PKINIT_NAME_MISMATCH); 941 SEC2TXT(SEC_E_POLICY_NLTM_ONLY); 942 SEC2TXT(SEC_E_QOP_NOT_SUPPORTED); 943 SEC2TXT(SEC_E_REVOCATION_OFFLINE_C); 944 SEC2TXT(SEC_E_REVOCATION_OFFLINE_KDC); 945 SEC2TXT(SEC_E_SECPKG_NOT_FOUND); 946 SEC2TXT(SEC_E_SECURITY_QOS_FAILED); 947 SEC2TXT(SEC_E_SHUTDOWN_IN_PROGRESS); 948 SEC2TXT(SEC_E_SMARTCARD_CERT_EXPIRED); 949 SEC2TXT(SEC_E_SMARTCARD_CERT_REVOKED); 950 SEC2TXT(SEC_E_SMARTCARD_LOGON_REQUIRED); 951 SEC2TXT(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED); 952 SEC2TXT(SEC_E_TARGET_UNKNOWN); 953 SEC2TXT(SEC_E_TIME_SKEW); 954 SEC2TXT(SEC_E_TOO_MANY_PRINCIPALS); 955 SEC2TXT(SEC_E_UNFINISHED_CONTEXT_DELETED); 956 SEC2TXT(SEC_E_UNKNOWN_CREDENTIALS); 957 SEC2TXT(SEC_E_UNSUPPORTED_FUNCTION); 958 SEC2TXT(SEC_E_UNSUPPORTED_PREAUTH); 959 SEC2TXT(SEC_E_UNTRUSTED_ROOT); 960 SEC2TXT(SEC_E_WRONG_CREDENTIAL_HANDLE); 961 SEC2TXT(SEC_E_WRONG_PRINCIPAL); 962 SEC2TXT(SEC_I_COMPLETE_AND_CONTINUE); 963 SEC2TXT(SEC_I_COMPLETE_NEEDED); 964 SEC2TXT(SEC_I_CONTEXT_EXPIRED); 965 SEC2TXT(SEC_I_CONTINUE_NEEDED); 966 SEC2TXT(SEC_I_INCOMPLETE_CREDENTIALS); 967 SEC2TXT(SEC_I_LOCAL_LOGON); 968 SEC2TXT(SEC_I_NO_LSA_CONTEXT); 969 SEC2TXT(SEC_I_RENEGOTIATE); 970 SEC2TXT(SEC_I_SIGNATURE_NEEDED); 971 default: 972 txt = "Unknown error"; 973 } 974 975 if(err == SEC_E_ILLEGAL_MESSAGE) { 976 curl_msnprintf(buf, buflen, 977 "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually " 978 "occurs when a fatal SSL/TLS alert is received (e.g. " 979 "handshake failed). More detail may be available in " 980 "the Windows System event log.", err); 981 } 982 else { 983 char msgbuf[256]; 984 if(curlx_get_winapi_error(err, msgbuf, sizeof(msgbuf))) 985 curl_msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf); 986 else 987 curl_msnprintf(buf, buflen, "%s (0x%08X)", txt, err); 988 } 989 990 #else 991 if(err == SEC_E_OK) 992 txt = "No error"; 993 else 994 txt = "Error"; 995 if(buflen > strlen(txt)) 996 strcpy(buf, txt); 997 #endif 998 999 if(errno != old_errno) 1000 CURL_SETERRNO(old_errno); 1001 1002 #ifdef _WIN32 1003 if(old_win_err != GetLastError()) 1004 SetLastError(old_win_err); 1005 #endif 1006 1007 return buf; 1008 } 1009 #endif /* USE_WINDOWS_SSPI */