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