Coverage Report

Created: 2023-03-26 06:11

/src/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
    /* error codes not used by current libcurl */
323
0
  case CURLE_OBSOLETE20:
324
0
  case CURLE_OBSOLETE24:
325
0
  case CURLE_OBSOLETE29:
326
0
  case CURLE_OBSOLETE32:
327
0
  case CURLE_OBSOLETE40:
328
0
  case CURLE_OBSOLETE44:
329
0
  case CURLE_OBSOLETE46:
330
0
  case CURLE_OBSOLETE50:
331
0
  case CURLE_OBSOLETE51:
332
0
  case CURLE_OBSOLETE57:
333
0
  case CURLE_OBSOLETE62:
334
0
  case CURLE_OBSOLETE75:
335
0
  case CURLE_OBSOLETE76:
336
0
  case CURL_LAST:
337
0
    break;
338
0
  }
339
  /*
340
   * By using a switch, gcc -Wall will complain about enum values
341
   * which do not appear, helping keep this function up-to-date.
342
   * By using gcc -Wall -Werror, you can't forget.
343
   *
344
   * A table would not have the same benefit.  Most compilers will
345
   * generate code very similar to a table in any case, so there
346
   * is little performance gain from a table.  And something is broken
347
   * for the user's application, anyways, so does it matter how fast
348
   * it _doesn't_ work?
349
   *
350
   * The line number for the error will be near this comment, which
351
   * is why it is here, and not at the start of the switch.
352
   */
353
0
  return "Unknown error";
354
#else
355
  if(!error)
356
    return "No error";
357
  else
358
    return "Error";
359
#endif
360
0
}
361
362
const char *
363
curl_multi_strerror(CURLMcode error)
364
0
{
365
0
#ifndef CURL_DISABLE_VERBOSE_STRINGS
366
0
  switch(error) {
367
0
  case CURLM_CALL_MULTI_PERFORM:
368
0
    return "Please call curl_multi_perform() soon";
369
370
0
  case CURLM_OK:
371
0
    return "No error";
372
373
0
  case CURLM_BAD_HANDLE:
374
0
    return "Invalid multi handle";
375
376
0
  case CURLM_BAD_EASY_HANDLE:
377
0
    return "Invalid easy handle";
378
379
0
  case CURLM_OUT_OF_MEMORY:
380
0
    return "Out of memory";
381
382
0
  case CURLM_INTERNAL_ERROR:
383
0
    return "Internal error";
384
385
0
  case CURLM_BAD_SOCKET:
386
0
    return "Invalid socket argument";
387
388
0
  case CURLM_UNKNOWN_OPTION:
389
0
    return "Unknown option";
390
391
0
  case CURLM_ADDED_ALREADY:
392
0
    return "The easy handle is already added to a multi handle";
393
394
0
  case CURLM_RECURSIVE_API_CALL:
395
0
    return "API function called from within callback";
396
397
0
  case CURLM_WAKEUP_FAILURE:
398
0
    return "Wakeup is unavailable or failed";
399
400
0
  case CURLM_BAD_FUNCTION_ARGUMENT:
401
0
    return "A libcurl function was given a bad argument";
402
403
0
  case CURLM_ABORTED_BY_CALLBACK:
404
0
    return "Operation was aborted by an application callback";
405
406
0
  case CURLM_UNRECOVERABLE_POLL:
407
0
    return "Unrecoverable error in select/poll";
408
409
0
  case CURLM_LAST:
410
0
    break;
411
0
  }
412
413
0
  return "Unknown error";
414
#else
415
  if(error == CURLM_OK)
416
    return "No error";
417
  else
418
    return "Error";
419
#endif
420
0
}
421
422
const char *
423
curl_share_strerror(CURLSHcode error)
424
0
{
425
0
#ifndef CURL_DISABLE_VERBOSE_STRINGS
426
0
  switch(error) {
427
0
  case CURLSHE_OK:
428
0
    return "No error";
429
430
0
  case CURLSHE_BAD_OPTION:
431
0
    return "Unknown share option";
432
433
0
  case CURLSHE_IN_USE:
434
0
    return "Share currently in use";
435
436
0
  case CURLSHE_INVALID:
437
0
    return "Invalid share handle";
438
439
0
  case CURLSHE_NOMEM:
440
0
    return "Out of memory";
441
442
0
  case CURLSHE_NOT_BUILT_IN:
443
0
    return "Feature not enabled in this library";
444
445
0
  case CURLSHE_LAST:
446
0
    break;
447
0
  }
448
449
0
  return "CURLSHcode unknown";
450
#else
451
  if(error == CURLSHE_OK)
452
    return "No error";
453
  else
454
    return "Error";
455
#endif
456
0
}
457
458
const char *
459
curl_url_strerror(CURLUcode error)
460
0
{
461
0
#ifndef CURL_DISABLE_VERBOSE_STRINGS
462
0
  switch(error) {
463
0
  case CURLUE_OK:
464
0
    return "No error";
465
466
0
  case CURLUE_BAD_HANDLE:
467
0
    return "An invalid CURLU pointer was passed as argument";
468
469
0
  case CURLUE_BAD_PARTPOINTER:
470
0
    return "An invalid 'part' argument was passed as argument";
471
472
0
  case CURLUE_MALFORMED_INPUT:
473
0
    return "Malformed input to a URL function";
474
475
0
  case CURLUE_BAD_PORT_NUMBER:
476
0
    return "Port number was not a decimal number between 0 and 65535";
477
478
0
  case CURLUE_UNSUPPORTED_SCHEME:
479
0
    return "Unsupported URL scheme";
480
481
0
  case CURLUE_URLDECODE:
482
0
    return "URL decode error, most likely because of rubbish in the input";
483
484
0
  case CURLUE_OUT_OF_MEMORY:
485
0
    return "A memory function failed";
486
487
0
  case CURLUE_USER_NOT_ALLOWED:
488
0
    return "Credentials was passed in the URL when prohibited";
489
490
0
  case CURLUE_UNKNOWN_PART:
491
0
    return "An unknown part ID was passed to a URL API function";
492
493
0
  case CURLUE_NO_SCHEME:
494
0
    return "No scheme part in the URL";
495
496
0
  case CURLUE_NO_USER:
497
0
    return "No user part in the URL";
498
499
0
  case CURLUE_NO_PASSWORD:
500
0
    return "No password part in the URL";
501
502
0
  case CURLUE_NO_OPTIONS:
503
0
    return "No options part in the URL";
504
505
0
  case CURLUE_NO_HOST:
506
0
    return "No host part in the URL";
507
508
0
  case CURLUE_NO_PORT:
509
0
    return "No port part in the URL";
510
511
0
  case CURLUE_NO_QUERY:
512
0
    return "No query part in the URL";
513
514
0
  case CURLUE_NO_FRAGMENT:
515
0
    return "No fragment part in the URL";
516
517
0
  case CURLUE_NO_ZONEID:
518
0
    return "No zoneid part in the URL";
519
520
0
  case CURLUE_BAD_LOGIN:
521
0
    return "Bad login part";
522
523
0
  case CURLUE_BAD_IPV6:
524
0
    return "Bad IPv6 address";
525
526
0
  case CURLUE_BAD_HOSTNAME:
527
0
    return "Bad hostname";
528
529
0
  case CURLUE_BAD_FILE_URL:
530
0
    return "Bad file:// URL";
531
532
0
  case CURLUE_BAD_SLASHES:
533
0
    return "Unsupported number of slashes following scheme";
534
535
0
  case CURLUE_BAD_SCHEME:
536
0
    return "Bad scheme";
537
538
0
  case CURLUE_BAD_PATH:
539
0
    return "Bad path";
540
541
0
  case CURLUE_BAD_FRAGMENT:
542
0
    return "Bad fragment";
543
544
0
  case CURLUE_BAD_QUERY:
545
0
    return "Bad query";
546
547
0
  case CURLUE_BAD_PASSWORD:
548
0
    return "Bad password";
549
550
0
  case CURLUE_BAD_USER:
551
0
    return "Bad user";
552
553
0
  case CURLUE_LACKS_IDN:
554
0
    return "libcurl lacks IDN support";
555
556
0
  case CURLUE_LAST:
557
0
    break;
558
0
  }
559
560
0
  return "CURLUcode unknown";
561
#else
562
  if(error == CURLUE_OK)
563
    return "No error";
564
  else
565
    return "Error";
566
#endif
567
0
}
568
569
#ifdef USE_WINSOCK
570
/* This is a helper function for Curl_strerror that converts Winsock error
571
 * codes (WSAGetLastError) to error messages.
572
 * Returns NULL if no error message was found for error code.
573
 */
574
static const char *
575
get_winsock_error (int err, char *buf, size_t len)
576
{
577
#ifndef CURL_DISABLE_VERBOSE_STRINGS
578
  const char *p;
579
#endif
580
581
  if(!len)
582
    return NULL;
583
584
  *buf = '\0';
585
586
#ifdef CURL_DISABLE_VERBOSE_STRINGS
587
  (void)err;
588
  return NULL;
589
#else
590
  switch(err) {
591
  case WSAEINTR:
592
    p = "Call interrupted";
593
    break;
594
  case WSAEBADF:
595
    p = "Bad file";
596
    break;
597
  case WSAEACCES:
598
    p = "Bad access";
599
    break;
600
  case WSAEFAULT:
601
    p = "Bad argument";
602
    break;
603
  case WSAEINVAL:
604
    p = "Invalid arguments";
605
    break;
606
  case WSAEMFILE:
607
    p = "Out of file descriptors";
608
    break;
609
  case WSAEWOULDBLOCK:
610
    p = "Call would block";
611
    break;
612
  case WSAEINPROGRESS:
613
  case WSAEALREADY:
614
    p = "Blocking call in progress";
615
    break;
616
  case WSAENOTSOCK:
617
    p = "Descriptor is not a socket";
618
    break;
619
  case WSAEDESTADDRREQ:
620
    p = "Need destination address";
621
    break;
622
  case WSAEMSGSIZE:
623
    p = "Bad message size";
624
    break;
625
  case WSAEPROTOTYPE:
626
    p = "Bad protocol";
627
    break;
628
  case WSAENOPROTOOPT:
629
    p = "Protocol option is unsupported";
630
    break;
631
  case WSAEPROTONOSUPPORT:
632
    p = "Protocol is unsupported";
633
    break;
634
  case WSAESOCKTNOSUPPORT:
635
    p = "Socket is unsupported";
636
    break;
637
  case WSAEOPNOTSUPP:
638
    p = "Operation not supported";
639
    break;
640
  case WSAEAFNOSUPPORT:
641
    p = "Address family not supported";
642
    break;
643
  case WSAEPFNOSUPPORT:
644
    p = "Protocol family not supported";
645
    break;
646
  case WSAEADDRINUSE:
647
    p = "Address already in use";
648
    break;
649
  case WSAEADDRNOTAVAIL:
650
    p = "Address not available";
651
    break;
652
  case WSAENETDOWN:
653
    p = "Network down";
654
    break;
655
  case WSAENETUNREACH:
656
    p = "Network unreachable";
657
    break;
658
  case WSAENETRESET:
659
    p = "Network has been reset";
660
    break;
661
  case WSAECONNABORTED:
662
    p = "Connection was aborted";
663
    break;
664
  case WSAECONNRESET:
665
    p = "Connection was reset";
666
    break;
667
  case WSAENOBUFS:
668
    p = "No buffer space";
669
    break;
670
  case WSAEISCONN:
671
    p = "Socket is already connected";
672
    break;
673
  case WSAENOTCONN:
674
    p = "Socket is not connected";
675
    break;
676
  case WSAESHUTDOWN:
677
    p = "Socket has been shut down";
678
    break;
679
  case WSAETOOMANYREFS:
680
    p = "Too many references";
681
    break;
682
  case WSAETIMEDOUT:
683
    p = "Timed out";
684
    break;
685
  case WSAECONNREFUSED:
686
    p = "Connection refused";
687
    break;
688
  case WSAELOOP:
689
    p = "Loop??";
690
    break;
691
  case WSAENAMETOOLONG:
692
    p = "Name too long";
693
    break;
694
  case WSAEHOSTDOWN:
695
    p = "Host down";
696
    break;
697
  case WSAEHOSTUNREACH:
698
    p = "Host unreachable";
699
    break;
700
  case WSAENOTEMPTY:
701
    p = "Not empty";
702
    break;
703
  case WSAEPROCLIM:
704
    p = "Process limit reached";
705
    break;
706
  case WSAEUSERS:
707
    p = "Too many users";
708
    break;
709
  case WSAEDQUOT:
710
    p = "Bad quota";
711
    break;
712
  case WSAESTALE:
713
    p = "Something is stale";
714
    break;
715
  case WSAEREMOTE:
716
    p = "Remote error";
717
    break;
718
#ifdef WSAEDISCON  /* missing in SalfordC! */
719
  case WSAEDISCON:
720
    p = "Disconnected";
721
    break;
722
#endif
723
    /* Extended Winsock errors */
724
  case WSASYSNOTREADY:
725
    p = "Winsock library is not ready";
726
    break;
727
  case WSANOTINITIALISED:
728
    p = "Winsock library not initialised";
729
    break;
730
  case WSAVERNOTSUPPORTED:
731
    p = "Winsock version not supported";
732
    break;
733
734
    /* getXbyY() errors (already handled in herrmsg):
735
     * Authoritative Answer: Host not found */
736
  case WSAHOST_NOT_FOUND:
737
    p = "Host not found";
738
    break;
739
740
    /* Non-Authoritative: Host not found, or SERVERFAIL */
741
  case WSATRY_AGAIN:
742
    p = "Host not found, try again";
743
    break;
744
745
    /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
746
  case WSANO_RECOVERY:
747
    p = "Unrecoverable error in call to nameserver";
748
    break;
749
750
    /* Valid name, no data record of requested type */
751
  case WSANO_DATA:
752
    p = "No data record of requested type";
753
    break;
754
755
  default:
756
    return NULL;
757
  }
758
  strncpy(buf, p, len);
759
  buf [len-1] = '\0';
760
  return buf;
761
#endif
762
}
763
#endif   /* USE_WINSOCK */
764
765
#if defined(WIN32) || defined(_WIN32_WCE)
766
/* This is a helper function for Curl_strerror that converts Windows API error
767
 * codes (GetLastError) to error messages.
768
 * Returns NULL if no error message was found for error code.
769
 */
770
static const char *
771
get_winapi_error(int err, char *buf, size_t buflen)
772
{
773
  char *p;
774
  wchar_t wbuf[256];
775
776
  if(!buflen)
777
    return NULL;
778
779
  *buf = '\0';
780
  *wbuf = L'\0';
781
782
  /* We return the local codepage version of the error string because if it is
783
     output to the user's terminal it will likely be with functions which
784
     expect the local codepage (eg fprintf, failf, infof).
785
     FormatMessageW -> wcstombs is used for Windows CE compatibility. */
786
  if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
787
                     FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
788
                    LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
789
    size_t written = wcstombs(buf, wbuf, buflen - 1);
790
    if(written != (size_t)-1)
791
      buf[written] = '\0';
792
    else
793
      *buf = '\0';
794
  }
795
796
  /* Truncate multiple lines */
797
  p = strchr(buf, '\n');
798
  if(p) {
799
    if(p > buf && *(p-1) == '\r')
800
      *(p-1) = '\0';
801
    else
802
      *p = '\0';
803
  }
804
805
  return (*buf ? buf : NULL);
806
}
807
#endif /* WIN32 || _WIN32_WCE */
808
809
/*
810
 * Our thread-safe and smart strerror() replacement.
811
 *
812
 * The 'err' argument passed in to this function MUST be a true errno number
813
 * as reported on this system. We do no range checking on the number before
814
 * we pass it to the "number-to-message" conversion function and there might
815
 * be systems that don't do proper range checking in there themselves.
816
 *
817
 * We don't do range checking (on systems other than Windows) since there is
818
 * no good reliable and portable way to do it.
819
 *
820
 * On Windows different types of error codes overlap. This function has an
821
 * order of preference when trying to match error codes:
822
 * CRT (errno), Winsock (WSAGetLastError), Windows API (GetLastError).
823
 *
824
 * It may be more correct to call one of the variant functions instead:
825
 * Call Curl_sspi_strerror if the error code is definitely Windows SSPI.
826
 * Call Curl_winapi_strerror if the error code is definitely Windows API.
827
 */
828
const char *Curl_strerror(int err, char *buf, size_t buflen)
829
0
{
830
#ifdef PRESERVE_WINDOWS_ERROR_CODE
831
  DWORD old_win_err = GetLastError();
832
#endif
833
0
  int old_errno = errno;
834
0
  char *p;
835
0
  size_t max;
836
837
0
  if(!buflen)
838
0
    return NULL;
839
840
0
#ifndef WIN32
841
0
  DEBUGASSERT(err >= 0);
842
0
#endif
843
844
0
  max = buflen - 1;
845
0
  *buf = '\0';
846
847
#if defined(WIN32) || defined(_WIN32_WCE)
848
#if defined(WIN32)
849
  /* 'sys_nerr' is the maximum errno number, it is not widely portable */
850
  if(err >= 0 && err < sys_nerr)
851
    strncpy(buf, sys_errlist[err], max);
852
  else
853
#endif
854
  {
855
    if(
856
#ifdef USE_WINSOCK
857
       !get_winsock_error(err, buf, max) &&
858
#endif
859
       !get_winapi_error((DWORD)err, buf, max))
860
      msnprintf(buf, max, "Unknown error %d (%#x)", err, err);
861
  }
862
#else /* not Windows coming up */
863
864
0
#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
865
 /*
866
  * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
867
  * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
868
  * message string, or EINVAL if 'errnum' is not a valid error number.
869
  */
870
0
  if(0 != strerror_r(err, buf, max)) {
871
0
    if('\0' == buf[0])
872
0
      msnprintf(buf, max, "Unknown error %d", err);
873
0
  }
874
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
875
 /*
876
  * The glibc-style strerror_r() only *might* use the buffer we pass to
877
  * the function, but it always returns the error message as a pointer,
878
  * so we must copy that string unconditionally (if non-NULL).
879
  */
880
  {
881
    char buffer[256];
882
    char *msg = strerror_r(err, buffer, sizeof(buffer));
883
    if(msg)
884
      strncpy(buf, msg, max);
885
    else
886
      msnprintf(buf, max, "Unknown error %d", err);
887
  }
888
#else
889
  {
890
    /* !checksrc! disable STRERROR 1 */
891
    const char *msg = strerror(err);
892
    if(msg)
893
      strncpy(buf, msg, max);
894
    else
895
      msnprintf(buf, max, "Unknown error %d", err);
896
  }
897
#endif
898
899
0
#endif /* end of not Windows */
900
901
0
  buf[max] = '\0'; /* make sure the string is null-terminated */
902
903
  /* strip trailing '\r\n' or '\n'. */
904
0
  p = strrchr(buf, '\n');
905
0
  if(p && (p - buf) >= 2)
906
0
    *p = '\0';
907
0
  p = strrchr(buf, '\r');
908
0
  if(p && (p - buf) >= 1)
909
0
    *p = '\0';
910
911
0
  if(errno != old_errno)
912
0
    errno = old_errno;
913
914
#ifdef PRESERVE_WINDOWS_ERROR_CODE
915
  if(old_win_err != GetLastError())
916
    SetLastError(old_win_err);
917
#endif
918
919
0
  return buf;
920
0
}
921
922
/*
923
 * Curl_winapi_strerror:
924
 * Variant of Curl_strerror if the error code is definitely Windows API.
925
 */
926
#if defined(WIN32) || defined(_WIN32_WCE)
927
const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
928
{
929
#ifdef PRESERVE_WINDOWS_ERROR_CODE
930
  DWORD old_win_err = GetLastError();
931
#endif
932
  int old_errno = errno;
933
934
  if(!buflen)
935
    return NULL;
936
937
  *buf = '\0';
938
939
#ifndef CURL_DISABLE_VERBOSE_STRINGS
940
  if(!get_winapi_error(err, buf, buflen)) {
941
    msnprintf(buf, buflen, "Unknown error %u (0x%08X)", err, err);
942
  }
943
#else
944
  {
945
    const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error";
946
    strncpy(buf, txt, buflen);
947
    buf[buflen - 1] = '\0';
948
  }
949
#endif
950
951
  if(errno != old_errno)
952
    errno = old_errno;
953
954
#ifdef PRESERVE_WINDOWS_ERROR_CODE
955
  if(old_win_err != GetLastError())
956
    SetLastError(old_win_err);
957
#endif
958
959
  return buf;
960
}
961
#endif /* WIN32 || _WIN32_WCE */
962
963
#ifdef USE_WINDOWS_SSPI
964
/*
965
 * Curl_sspi_strerror:
966
 * Variant of Curl_strerror if the error code is definitely Windows SSPI.
967
 */
968
const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
969
{
970
#ifdef PRESERVE_WINDOWS_ERROR_CODE
971
  DWORD old_win_err = GetLastError();
972
#endif
973
  int old_errno = errno;
974
  const char *txt;
975
976
  if(!buflen)
977
    return NULL;
978
979
  *buf = '\0';
980
981
#ifndef CURL_DISABLE_VERBOSE_STRINGS
982
983
  switch(err) {
984
    case SEC_E_OK:
985
      txt = "No error";
986
      break;
987
#define SEC2TXT(sec) case sec: txt = #sec; break
988
    SEC2TXT(CRYPT_E_REVOKED);
989
    SEC2TXT(SEC_E_ALGORITHM_MISMATCH);
990
    SEC2TXT(SEC_E_BAD_BINDINGS);
991
    SEC2TXT(SEC_E_BAD_PKGID);
992
    SEC2TXT(SEC_E_BUFFER_TOO_SMALL);
993
    SEC2TXT(SEC_E_CANNOT_INSTALL);
994
    SEC2TXT(SEC_E_CANNOT_PACK);
995
    SEC2TXT(SEC_E_CERT_EXPIRED);
996
    SEC2TXT(SEC_E_CERT_UNKNOWN);
997
    SEC2TXT(SEC_E_CERT_WRONG_USAGE);
998
    SEC2TXT(SEC_E_CONTEXT_EXPIRED);
999
    SEC2TXT(SEC_E_CROSSREALM_DELEGATION_FAILURE);
1000
    SEC2TXT(SEC_E_CRYPTO_SYSTEM_INVALID);
1001
    SEC2TXT(SEC_E_DECRYPT_FAILURE);
1002
    SEC2TXT(SEC_E_DELEGATION_POLICY);
1003
    SEC2TXT(SEC_E_DELEGATION_REQUIRED);
1004
    SEC2TXT(SEC_E_DOWNGRADE_DETECTED);
1005
    SEC2TXT(SEC_E_ENCRYPT_FAILURE);
1006
    SEC2TXT(SEC_E_ILLEGAL_MESSAGE);
1007
    SEC2TXT(SEC_E_INCOMPLETE_CREDENTIALS);
1008
    SEC2TXT(SEC_E_INCOMPLETE_MESSAGE);
1009
    SEC2TXT(SEC_E_INSUFFICIENT_MEMORY);
1010
    SEC2TXT(SEC_E_INTERNAL_ERROR);
1011
    SEC2TXT(SEC_E_INVALID_HANDLE);
1012
    SEC2TXT(SEC_E_INVALID_PARAMETER);
1013
    SEC2TXT(SEC_E_INVALID_TOKEN);
1014
    SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED);
1015
    SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED_KDC);
1016
    SEC2TXT(SEC_E_KDC_CERT_EXPIRED);
1017
    SEC2TXT(SEC_E_KDC_CERT_REVOKED);
1018
    SEC2TXT(SEC_E_KDC_INVALID_REQUEST);
1019
    SEC2TXT(SEC_E_KDC_UNABLE_TO_REFER);
1020
    SEC2TXT(SEC_E_KDC_UNKNOWN_ETYPE);
1021
    SEC2TXT(SEC_E_LOGON_DENIED);
1022
    SEC2TXT(SEC_E_MAX_REFERRALS_EXCEEDED);
1023
    SEC2TXT(SEC_E_MESSAGE_ALTERED);
1024
    SEC2TXT(SEC_E_MULTIPLE_ACCOUNTS);
1025
    SEC2TXT(SEC_E_MUST_BE_KDC);
1026
    SEC2TXT(SEC_E_NOT_OWNER);
1027
    SEC2TXT(SEC_E_NO_AUTHENTICATING_AUTHORITY);
1028
    SEC2TXT(SEC_E_NO_CREDENTIALS);
1029
    SEC2TXT(SEC_E_NO_IMPERSONATION);
1030
    SEC2TXT(SEC_E_NO_IP_ADDRESSES);
1031
    SEC2TXT(SEC_E_NO_KERB_KEY);
1032
    SEC2TXT(SEC_E_NO_PA_DATA);
1033
    SEC2TXT(SEC_E_NO_S4U_PROT_SUPPORT);
1034
    SEC2TXT(SEC_E_NO_TGT_REPLY);
1035
    SEC2TXT(SEC_E_OUT_OF_SEQUENCE);
1036
    SEC2TXT(SEC_E_PKINIT_CLIENT_FAILURE);
1037
    SEC2TXT(SEC_E_PKINIT_NAME_MISMATCH);
1038
    SEC2TXT(SEC_E_POLICY_NLTM_ONLY);
1039
    SEC2TXT(SEC_E_QOP_NOT_SUPPORTED);
1040
    SEC2TXT(SEC_E_REVOCATION_OFFLINE_C);
1041
    SEC2TXT(SEC_E_REVOCATION_OFFLINE_KDC);
1042
    SEC2TXT(SEC_E_SECPKG_NOT_FOUND);
1043
    SEC2TXT(SEC_E_SECURITY_QOS_FAILED);
1044
    SEC2TXT(SEC_E_SHUTDOWN_IN_PROGRESS);
1045
    SEC2TXT(SEC_E_SMARTCARD_CERT_EXPIRED);
1046
    SEC2TXT(SEC_E_SMARTCARD_CERT_REVOKED);
1047
    SEC2TXT(SEC_E_SMARTCARD_LOGON_REQUIRED);
1048
    SEC2TXT(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED);
1049
    SEC2TXT(SEC_E_TARGET_UNKNOWN);
1050
    SEC2TXT(SEC_E_TIME_SKEW);
1051
    SEC2TXT(SEC_E_TOO_MANY_PRINCIPALS);
1052
    SEC2TXT(SEC_E_UNFINISHED_CONTEXT_DELETED);
1053
    SEC2TXT(SEC_E_UNKNOWN_CREDENTIALS);
1054
    SEC2TXT(SEC_E_UNSUPPORTED_FUNCTION);
1055
    SEC2TXT(SEC_E_UNSUPPORTED_PREAUTH);
1056
    SEC2TXT(SEC_E_UNTRUSTED_ROOT);
1057
    SEC2TXT(SEC_E_WRONG_CREDENTIAL_HANDLE);
1058
    SEC2TXT(SEC_E_WRONG_PRINCIPAL);
1059
    SEC2TXT(SEC_I_COMPLETE_AND_CONTINUE);
1060
    SEC2TXT(SEC_I_COMPLETE_NEEDED);
1061
    SEC2TXT(SEC_I_CONTEXT_EXPIRED);
1062
    SEC2TXT(SEC_I_CONTINUE_NEEDED);
1063
    SEC2TXT(SEC_I_INCOMPLETE_CREDENTIALS);
1064
    SEC2TXT(SEC_I_LOCAL_LOGON);
1065
    SEC2TXT(SEC_I_NO_LSA_CONTEXT);
1066
    SEC2TXT(SEC_I_RENEGOTIATE);
1067
    SEC2TXT(SEC_I_SIGNATURE_NEEDED);
1068
    default:
1069
      txt = "Unknown error";
1070
  }
1071
1072
  if(err == SEC_E_ILLEGAL_MESSAGE) {
1073
    msnprintf(buf, buflen,
1074
              "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
1075
              "when a fatal SSL/TLS alert is received (e.g. handshake failed)."
1076
              " More detail may be available in the Windows System event log.",
1077
              err);
1078
  }
1079
  else {
1080
    char txtbuf[80];
1081
    char msgbuf[256];
1082
1083
    msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
1084
1085
    if(get_winapi_error(err, msgbuf, sizeof(msgbuf)))
1086
      msnprintf(buf, buflen, "%s - %s", txtbuf, msgbuf);
1087
    else {
1088
      strncpy(buf, txtbuf, buflen);
1089
      buf[buflen - 1] = '\0';
1090
    }
1091
  }
1092
1093
#else
1094
  if(err == SEC_E_OK)
1095
    txt = "No error";
1096
  else
1097
    txt = "Error";
1098
  strncpy(buf, txt, buflen);
1099
  buf[buflen - 1] = '\0';
1100
#endif
1101
1102
  if(errno != old_errno)
1103
    errno = old_errno;
1104
1105
#ifdef PRESERVE_WINDOWS_ERROR_CODE
1106
  if(old_win_err != GetLastError())
1107
    SetLastError(old_win_err);
1108
#endif
1109
1110
  return buf;
1111
}
1112
#endif /* USE_WINDOWS_SSPI */