Coverage Report

Created: 2026-05-30 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/protocol.c
Line
Count
Source
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
#include "curl_setup.h"
25
26
#include "protocol.h"
27
#include "strcase.h"
28
29
#include "dict.h"
30
#include "file.h"
31
#include "ftp.h"
32
#include "gopher.h"
33
#include "http.h"
34
#include "imap.h"
35
#include "curl_ldap.h"
36
#include "mqtt.h"
37
#include "pop3.h"
38
#include "rtsp.h"
39
#include "smb.h"
40
#include "smtp.h"
41
#include "telnet.h"
42
#include "tftp.h"
43
#include "ws.h"
44
#include "vssh/ssh.h"
45
46
47
/* All URI schemes known to libcurl, but not necessarily implemented
48
 * by protocol handlers. */
49
const struct Curl_scheme Curl_scheme_dict = {
50
  "dict",                               /* scheme */
51
#ifdef CURL_DISABLE_DICT
52
  ZERO_NULL,
53
#else
54
  &Curl_protocol_dict,
55
#endif
56
  CURLPROTO_DICT,                       /* protocol */
57
  CURLPROTO_DICT,                       /* family */
58
  PROTOPT_NONE | PROTOPT_NOURLQUERY,    /* flags */
59
  PORT_DICT,                            /* defport */
60
};
61
62
const struct Curl_scheme Curl_scheme_file = {
63
  "file",                               /* scheme */
64
#ifdef CURL_DISABLE_FILE
65
  ZERO_NULL,
66
#else
67
  &Curl_protocol_file,
68
#endif
69
  CURLPROTO_FILE,                       /* protocol */
70
  CURLPROTO_FILE,                       /* family */
71
  PROTOPT_NONETWORK | PROTOPT_NOURLQUERY, /* flags */
72
  0                                     /* defport */
73
};
74
75
const struct Curl_scheme Curl_scheme_ftp = {
76
  "ftp",                           /* scheme */
77
#ifdef CURL_DISABLE_FTP
78
  ZERO_NULL,
79
#else
80
  &Curl_protocol_ftp,
81
#endif
82
  CURLPROTO_FTP,                   /* protocol */
83
  CURLPROTO_FTP,                   /* family */
84
  PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
85
  PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
86
  PROTOPT_WILDCARD | PROTOPT_SSL_REUSE |
87
  PROTOPT_CONN_REUSE, /* flags */
88
  PORT_FTP,                        /* defport */
89
};
90
91
const struct Curl_scheme Curl_scheme_ftps = {
92
  "ftps",                          /* scheme */
93
#if defined(CURL_DISABLE_FTP) || !defined(USE_SSL)
94
  ZERO_NULL,
95
#else
96
  &Curl_protocol_ftp,
97
#endif
98
  CURLPROTO_FTPS,                  /* protocol */
99
  CURLPROTO_FTP,                   /* family */
100
  PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
101
  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD |
102
  PROTOPT_CONN_REUSE, /* flags */
103
  PORT_FTPS,                       /* defport */
104
};
105
106
const struct Curl_scheme Curl_scheme_gopher = {
107
  "gopher",                             /* scheme */
108
#ifdef CURL_DISABLE_GOPHER
109
  ZERO_NULL,
110
#else
111
  &Curl_protocol_gopher,
112
#endif
113
  CURLPROTO_GOPHER,                     /* protocol */
114
  CURLPROTO_GOPHER,                     /* family */
115
  PROTOPT_NONE,                         /* flags */
116
  PORT_GOPHER,                          /* defport */
117
};
118
119
const struct Curl_scheme Curl_scheme_gophers = {
120
  "gophers",                            /* scheme */
121
#if defined(CURL_DISABLE_GOPHER) || !defined(USE_SSL)
122
  ZERO_NULL,
123
#else
124
  &Curl_protocol_gophers,
125
#endif
126
  CURLPROTO_GOPHERS,                    /* protocol */
127
  CURLPROTO_GOPHER,                     /* family */
128
  PROTOPT_SSL,                          /* flags */
129
  PORT_GOPHER,                          /* defport */
130
};
131
132
const struct Curl_scheme Curl_scheme_http = {
133
  "http",                               /* scheme */
134
#ifdef CURL_DISABLE_HTTP
135
  ZERO_NULL,
136
#else
137
  &Curl_protocol_http,
138
#endif
139
  CURLPROTO_HTTP,                       /* protocol */
140
  CURLPROTO_HTTP,                       /* family */
141
  PROTOPT_CREDSPERREQUEST |             /* flags */
142
  PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE,
143
  PORT_HTTP,                            /* defport */
144
};
145
146
const struct Curl_scheme Curl_scheme_https = {
147
  "https",                              /* scheme */
148
#if defined(CURL_DISABLE_HTTP) || !defined(USE_SSL)
149
  ZERO_NULL,
150
#else
151
  &Curl_protocol_http,
152
#endif
153
  CURLPROTO_HTTPS,                      /* protocol */
154
  CURLPROTO_HTTP,                       /* family */
155
  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */
156
  PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE |
157
  PROTOPT_HTTP_PROXY_TUNNEL,
158
  PORT_HTTPS,                           /* defport */
159
};
160
161
const struct Curl_scheme Curl_scheme_imap = {
162
  "imap",                           /* scheme */
163
#ifdef CURL_DISABLE_IMAP
164
  ZERO_NULL,
165
#else
166
  &Curl_protocol_imap,
167
#endif
168
  CURLPROTO_IMAP,                   /* protocol */
169
  CURLPROTO_IMAP,                   /* family */
170
  PROTOPT_CLOSEACTION |             /* flags */
171
  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE |
172
  PROTOPT_CONN_REUSE,
173
  PORT_IMAP,                        /* defport */
174
};
175
176
const struct Curl_scheme Curl_scheme_imaps = {
177
  "imaps",                          /* scheme */
178
#if defined(CURL_DISABLE_IMAP) || !defined(USE_SSL)
179
  ZERO_NULL,
180
#else
181
  &Curl_protocol_imap,
182
#endif
183
  CURLPROTO_IMAPS,                  /* protocol */
184
  CURLPROTO_IMAP,                   /* family */
185
  PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
186
  PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE,
187
  PORT_IMAPS,                       /* defport */
188
};
189
190
const struct Curl_scheme Curl_scheme_ldap = {
191
  "ldap",                               /* scheme */
192
#ifdef CURL_DISABLE_LDAP
193
  ZERO_NULL,
194
#else
195
  &Curl_protocol_ldap,
196
#endif
197
  CURLPROTO_LDAP,                       /* protocol */
198
  CURLPROTO_LDAP,                       /* family */
199
  PROTOPT_SSL_REUSE,                    /* flags */
200
  PORT_LDAP,                            /* defport */
201
};
202
203
const struct Curl_scheme Curl_scheme_ldaps = {
204
  "ldaps",                              /* scheme */
205
#if defined(CURL_DISABLE_LDAP) || !defined(HAVE_LDAP_SSL)
206
  ZERO_NULL,
207
#else
208
  &Curl_protocol_ldap,
209
#endif
210
  CURLPROTO_LDAPS,                      /* protocol */
211
  CURLPROTO_LDAP,                       /* family */
212
  PROTOPT_SSL,                          /* flags */
213
  PORT_LDAPS,                           /* defport */
214
};
215
216
const struct Curl_scheme Curl_scheme_mqtt = {
217
  "mqtt",                             /* scheme */
218
#ifdef CURL_DISABLE_MQTT
219
  ZERO_NULL,
220
#else
221
  &Curl_protocol_mqtt,
222
#endif
223
  CURLPROTO_MQTT,                     /* protocol */
224
  CURLPROTO_MQTT,                     /* family */
225
  PROTOPT_NONE,                       /* flags */
226
  PORT_MQTT,                          /* defport */
227
};
228
229
const struct Curl_scheme Curl_scheme_mqtts = {
230
  "mqtts",                            /* scheme */
231
#if defined(CURL_DISABLE_MQTT) || !defined(USE_SSL)
232
  ZERO_NULL,
233
#else
234
  &Curl_protocol_mqtts,
235
#endif
236
  CURLPROTO_MQTTS,                    /* protocol */
237
  CURLPROTO_MQTT,                     /* family */
238
  PROTOPT_SSL,                        /* flags */
239
  PORT_MQTTS,                         /* defport */
240
};
241
242
const struct Curl_scheme Curl_scheme_pop3 = {
243
  "pop3",                           /* scheme */
244
#ifdef CURL_DISABLE_POP3
245
  ZERO_NULL,
246
#else
247
  &Curl_protocol_pop3,
248
#endif
249
  CURLPROTO_POP3,                   /* protocol */
250
  CURLPROTO_POP3,                   /* family */
251
  PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
252
  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE,
253
  PORT_POP3,                        /* defport */
254
};
255
256
const struct Curl_scheme Curl_scheme_pop3s = {
257
  "pop3s",                          /* scheme */
258
#if defined(CURL_DISABLE_POP3) || !defined(USE_SSL)
259
  ZERO_NULL,
260
#else
261
  &Curl_protocol_pop3,
262
#endif
263
  CURLPROTO_POP3S,                  /* protocol */
264
  CURLPROTO_POP3,                   /* family */
265
  PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
266
  PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE,
267
  PORT_POP3S,                       /* defport */
268
};
269
270
const struct Curl_scheme Curl_scheme_rtsp = {
271
  "rtsp",                               /* scheme */
272
#ifdef CURL_DISABLE_RTSP
273
  ZERO_NULL,
274
#else
275
  &Curl_protocol_rtsp,
276
#endif
277
  CURLPROTO_RTSP,                       /* protocol */
278
  CURLPROTO_RTSP,                       /* family */
279
  PROTOPT_CONN_REUSE,                   /* flags */
280
  PORT_RTSP,                            /* defport */
281
};
282
283
const struct Curl_scheme Curl_scheme_sftp = {
284
  "sftp",                               /* scheme */
285
#ifndef USE_SSH
286
  NULL,
287
#else
288
  &Curl_protocol_sftp,
289
#endif
290
  CURLPROTO_SFTP,                       /* protocol */
291
  CURLPROTO_SFTP,                       /* family */
292
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
293
  PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE,
294
  PORT_SSH                              /* defport */
295
};
296
297
const struct Curl_scheme Curl_scheme_scp = {
298
  "scp",                                /* scheme */
299
#ifndef USE_SSH
300
  NULL,
301
#else
302
  &Curl_protocol_scp,
303
#endif
304
  CURLPROTO_SCP,                        /* protocol */
305
  CURLPROTO_SCP,                        /* family */
306
  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */
307
  PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE,
308
  PORT_SSH,                             /* defport */
309
};
310
311
const struct Curl_scheme Curl_scheme_smb = {
312
  "smb",                                /* scheme */
313
#if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE)
314
  &Curl_protocol_smb,
315
#else
316
  ZERO_NULL,
317
#endif
318
  CURLPROTO_SMB,                        /* protocol */
319
  CURLPROTO_SMB,                        /* family */
320
  PROTOPT_NONE,                         /* flags */
321
  PORT_SMB,                             /* defport */
322
};
323
324
const struct Curl_scheme Curl_scheme_smbs = {
325
  "smbs",                               /* scheme */
326
#if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE) && defined(USE_SSL)
327
  &Curl_protocol_smb,
328
#else
329
  ZERO_NULL,
330
#endif
331
  CURLPROTO_SMBS,                       /* protocol */
332
  CURLPROTO_SMB,                        /* family */
333
  PROTOPT_SSL,                          /* flags */
334
  PORT_SMBS,                            /* defport */
335
};
336
337
const struct Curl_scheme Curl_scheme_smtp = {
338
  "smtp",                           /* scheme */
339
#ifdef CURL_DISABLE_SMTP
340
  ZERO_NULL,
341
#else
342
  &Curl_protocol_smtp,
343
#endif
344
  CURLPROTO_SMTP,                   /* protocol */
345
  CURLPROTO_SMTP,                   /* family */
346
  PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
347
  PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE,
348
  PORT_SMTP,                        /* defport */
349
};
350
351
const struct Curl_scheme Curl_scheme_smtps = {
352
  "smtps",                          /* scheme */
353
#if defined(CURL_DISABLE_SMTP) || !defined(USE_SSL)
354
  ZERO_NULL,
355
#else
356
  &Curl_protocol_smtp,
357
#endif
358
  CURLPROTO_SMTPS,                  /* protocol */
359
  CURLPROTO_SMTP,                   /* family */
360
  PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
361
  PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE,
362
  PORT_SMTPS,                       /* defport */
363
};
364
365
const struct Curl_scheme Curl_scheme_socks = {
366
  "socks",                          /* scheme */
367
  ZERO_NULL,
368
  CURLPROTO_SOCKS,                  /* protocol */
369
  CURLPROTO_SOCKS,                  /* family */
370
  PROTOPT_NO_TRANSFER,              /* flags */
371
  PORT_SOCKS,                       /* defport */
372
};
373
374
const struct Curl_scheme Curl_scheme_socks4 = {
375
  "socks4",                         /* scheme */
376
  ZERO_NULL,
377
  CURLPROTO_SOCKS,                  /* protocol */
378
  CURLPROTO_SOCKS,                  /* family */
379
  PROTOPT_NO_TRANSFER,              /* flags */
380
  PORT_SOCKS,                       /* defport */
381
};
382
383
const struct Curl_scheme Curl_scheme_socks4a = {
384
  "socks4a",                        /* scheme */
385
  ZERO_NULL,
386
  CURLPROTO_SOCKS,                  /* protocol */
387
  CURLPROTO_SOCKS,                  /* family */
388
  PROTOPT_NO_TRANSFER,              /* flags */
389
  PORT_SOCKS,                       /* defport */
390
};
391
392
const struct Curl_scheme Curl_scheme_socks5 = {
393
  "socks5",                         /* scheme */
394
  ZERO_NULL,
395
  CURLPROTO_SOCKS,                  /* protocol */
396
  CURLPROTO_SOCKS,                  /* family */
397
  PROTOPT_NO_TRANSFER,              /* flags */
398
  PORT_SOCKS,                       /* defport */
399
};
400
401
const struct Curl_scheme Curl_scheme_socks5h = {
402
  "socks5h",                         /* scheme */
403
  ZERO_NULL,
404
  CURLPROTO_SOCKS,                  /* protocol */
405
  CURLPROTO_SOCKS,                  /* family */
406
  PROTOPT_NO_TRANSFER,              /* flags */
407
  PORT_SOCKS,                       /* defport */
408
};
409
410
const struct Curl_scheme Curl_scheme_telnet = {
411
  "telnet",                             /* scheme */
412
#ifdef CURL_DISABLE_TELNET
413
  ZERO_NULL,
414
#else
415
  &Curl_protocol_telnet,
416
#endif
417
  CURLPROTO_TELNET,                     /* protocol */
418
  CURLPROTO_TELNET,                     /* family */
419
  PROTOPT_NONE | PROTOPT_NOURLQUERY,    /* flags */
420
  PORT_TELNET,                          /* defport */
421
};
422
423
const struct Curl_scheme Curl_scheme_tftp = {
424
  "tftp",                               /* scheme */
425
#ifdef CURL_DISABLE_TFTP
426
  ZERO_NULL,
427
#else
428
  &Curl_protocol_tftp,
429
#endif
430
  CURLPROTO_TFTP,                       /* protocol */
431
  CURLPROTO_TFTP,                       /* family */
432
  PROTOPT_NOTCPPROXY | PROTOPT_NOURLQUERY, /* flags */
433
  PORT_TFTP,                            /* defport */
434
};
435
436
const struct Curl_scheme Curl_scheme_ws = {
437
  "ws",                                 /* scheme */
438
#if defined(CURL_DISABLE_WEBSOCKETS) || defined(CURL_DISABLE_HTTP)
439
  ZERO_NULL,
440
#else
441
  &Curl_protocol_ws,
442
#endif
443
  CURLPROTO_WS,                         /* protocol */
444
  CURLPROTO_HTTP,                       /* family */
445
  PROTOPT_CREDSPERREQUEST |             /* flags */
446
  PROTOPT_USERPWDCTRL | PROTOPT_HTTP_PROXY_TUNNEL,
447
  PORT_HTTP                             /* defport */
448
};
449
450
const struct Curl_scheme Curl_scheme_wss = {
451
  "wss",                                /* scheme */
452
#if defined(CURL_DISABLE_WEBSOCKETS) || defined(CURL_DISABLE_HTTP) || \
453
  !defined(USE_SSL)
454
  ZERO_NULL,
455
#else
456
  &Curl_protocol_ws,
457
#endif
458
  CURLPROTO_WSS,                        /* protocol */
459
  CURLPROTO_HTTP,                       /* family */
460
  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
461
  PROTOPT_USERPWDCTRL | PROTOPT_HTTP_PROXY_TUNNEL,
462
  PORT_HTTPS                            /* defport */
463
};
464
465
/* Returns a struct scheme pointer if the name is a known scheme. Check the
466
   ->run struct field for non-NULL to figure out if an implementation is
467
   present. */
468
const struct Curl_scheme *Curl_getn_scheme(const char *scheme, size_t len)
469
0
{
470
  /* table generated by schemetable.c:
471
     1. gcc schemetable.c && ./a.out
472
     2. check how small the table gets
473
     3. tweak the hash algorithm, then rerun from 1
474
     4. when the table is good enough
475
     5. copy the table into this source code
476
     6. make sure this function uses the same hash function that worked for
477
     schemetable.c
478
     */
479
0
  static const struct Curl_scheme * const all_schemes[59] = { NULL,
480
0
    &Curl_scheme_pop3, NULL,
481
0
    &Curl_scheme_smtps,
482
0
    &Curl_scheme_socks,
483
0
    &Curl_scheme_socks4,
484
0
    &Curl_scheme_socks5, NULL, NULL,
485
0
    &Curl_scheme_gophers,
486
0
    &Curl_scheme_ws,
487
0
    &Curl_scheme_sftp,
488
0
    &Curl_scheme_socks4a,
489
0
    &Curl_scheme_scp,
490
0
    &Curl_scheme_rtsp,
491
0
    &Curl_scheme_dict, NULL, NULL,
492
0
    &Curl_scheme_gopher, NULL, NULL, NULL,
493
0
    &Curl_scheme_wss, NULL,
494
0
    &Curl_scheme_smb, NULL,
495
0
    &Curl_scheme_ldap,
496
0
    &Curl_scheme_ldaps,
497
0
    &Curl_scheme_imap, NULL, NULL, NULL,
498
0
    &Curl_scheme_imaps,
499
0
    &Curl_scheme_https,
500
0
    &Curl_scheme_tftp,
501
0
    &Curl_scheme_telnet, NULL, NULL, NULL,
502
0
    &Curl_scheme_file,
503
0
    &Curl_scheme_smtp, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
504
0
    &Curl_scheme_ftp,
505
0
    &Curl_scheme_mqtt, NULL,
506
0
    &Curl_scheme_socks5h,
507
0
    &Curl_scheme_http,
508
0
    &Curl_scheme_pop3s, NULL,
509
0
    &Curl_scheme_mqtts, NULL,
510
0
    &Curl_scheme_smbs,
511
0
    &Curl_scheme_ftps,
512
0
  };
513
514
0
  if(len && (len <= 7)) {
515
0
    const char *s = scheme;
516
0
    size_t l = len;
517
0
    const struct Curl_scheme *h;
518
0
    unsigned int c = 443;
519
0
    while(l) {
520
0
      c <<= 5;
521
0
      c += (unsigned int)Curl_raw_tolower(*s);
522
0
      s++;
523
0
      l--;
524
0
    }
525
526
0
    h = all_schemes[c % 59];
527
0
    if(h && curl_strnequal(scheme, h->name, len) && !h->name[len])
528
0
      return h;
529
0
  }
530
0
  return NULL;
531
0
}
532
533
const struct Curl_scheme *Curl_get_scheme(const char *scheme)
534
0
{
535
0
  return Curl_getn_scheme(scheme, strlen(scheme));
536
0
}