Coverage Report

Created: 2024-02-25 06:14

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