• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2019, 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.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 #include <curl/curl.h>
26 #include "urldata.h"
27 #include "vtls/vtls.h"
28 #include "http2.h"
29 #include "ssh.h"
30 #include "quic.h"
31 #include "curl_printf.h"
32 
33 #ifdef USE_ARES
34 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
35      (defined(WIN32) || defined(__SYMBIAN32__))
36 #    define CARES_STATICLIB
37 #  endif
38 #  include <ares.h>
39 #endif
40 
41 #ifdef USE_LIBIDN2
42 #include <idn2.h>
43 #endif
44 
45 #ifdef USE_LIBPSL
46 #include <libpsl.h>
47 #endif
48 
49 #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
50 #include <iconv.h>
51 #endif
52 
53 #ifdef USE_LIBRTMP
54 #include <librtmp/rtmp.h>
55 #endif
56 
57 #ifdef HAVE_ZLIB_H
58 #include <zlib.h>
59 #ifdef __SYMBIAN32__
60 /* zlib pollutes the namespace with this definition */
61 #undef WIN32
62 #endif
63 #endif
64 
65 #ifdef HAVE_BROTLI
66 #include <brotli/decode.h>
67 #endif
68 
69 void Curl_version_init(void);
70 
71 /* For thread safety purposes this function is called by global_init so that
72    the static data in both version functions is initialized. */
Curl_version_init(void)73 void Curl_version_init(void)
74 {
75   curl_version();
76   curl_version_info(CURLVERSION_NOW);
77 }
78 
79 #ifdef HAVE_BROTLI
brotli_version(char * buf,size_t bufsz)80 static size_t brotli_version(char *buf, size_t bufsz)
81 {
82   uint32_t brotli_version = BrotliDecoderVersion();
83   unsigned int major = brotli_version >> 24;
84   unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
85   unsigned int patch = brotli_version & 0x00000FFF;
86 
87   return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
88 }
89 #endif
90 
curl_version(void)91 char *curl_version(void)
92 {
93   static bool initialized;
94   static char version[250];
95   char *ptr = version;
96   size_t len;
97   size_t left = sizeof(version);
98 
99   if(initialized)
100     return version;
101 
102   strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION);
103   len = strlen(ptr);
104   left -= len;
105   ptr += len;
106 
107   len = Curl_ssl_version(ptr + 1, left - 1);
108 
109   if(len > 0) {
110     *ptr = ' ';
111     left -= ++len;
112     ptr += len;
113   }
114 
115 #ifdef HAVE_LIBZ
116   len = msnprintf(ptr, left, " zlib/%s", zlibVersion());
117   left -= len;
118   ptr += len;
119 #endif
120 #ifdef HAVE_BROTLI
121   len = msnprintf(ptr, left, "%s", " brotli/");
122   left -= len;
123   ptr += len;
124   len = brotli_version(ptr, left);
125   left -= len;
126   ptr += len;
127 #endif
128 #ifdef USE_ARES
129   /* this function is only present in c-ares, not in the original ares */
130   len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL));
131   left -= len;
132   ptr += len;
133 #endif
134 #ifdef USE_LIBIDN2
135   if(idn2_check_version(IDN2_VERSION)) {
136     len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
137     left -= len;
138     ptr += len;
139   }
140 #endif
141 #ifdef USE_LIBPSL
142   len = msnprintf(ptr, left, " libpsl/%s", psl_get_version());
143   left -= len;
144   ptr += len;
145 #endif
146 #ifdef USE_WIN32_IDN
147   len = msnprintf(ptr, left, " WinIDN");
148   left -= len;
149   ptr += len;
150 #endif
151 #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
152 #ifdef _LIBICONV_VERSION
153   len = msnprintf(ptr, left, " iconv/%d.%d",
154                   _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
155 #else
156   /* version unknown */
157   len = msnprintf(ptr, left, " iconv");
158 #endif /* _LIBICONV_VERSION */
159   left -= len;
160   ptr += len;
161 #endif
162 #ifdef USE_SSH
163   if(left) {
164     *ptr++=' ';
165     left--;
166   }
167   len = Curl_ssh_version(ptr, left);
168   left -= len;
169   ptr += len;
170 #endif
171 #ifdef USE_NGHTTP2
172   len = Curl_http2_ver(ptr, left);
173   left -= len;
174   ptr += len;
175 #endif
176 #ifdef ENABLE_QUIC
177   len = Curl_quic_ver(ptr, left);
178   left -= len;
179   ptr += len;
180 #endif
181 #ifdef USE_LIBRTMP
182   {
183     char suff[2];
184     if(RTMP_LIB_VERSION & 0xff) {
185       suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1;
186       suff[1] = '\0';
187     }
188     else
189       suff[0] = '\0';
190 
191     msnprintf(ptr, left, " librtmp/%d.%d%s",
192               RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
193               suff);
194 /*
195   If another lib version is added below this one, this code would
196   also have to do:
197 
198     len = what msnprintf() returned
199 
200     left -= len;
201     ptr += len;
202 */
203   }
204 #endif
205 
206   /* Silent scan-build even if librtmp is not enabled. */
207   (void) left;
208   (void) ptr;
209 
210   initialized = true;
211   return version;
212 }
213 
214 /* data for curl_version_info
215 
216    Keep the list sorted alphabetically. It is also written so that each
217    protocol line has its own #if line to make things easier on the eye.
218  */
219 
220 static const char * const protocols[] = {
221 #ifndef CURL_DISABLE_DICT
222   "dict",
223 #endif
224 #ifndef CURL_DISABLE_FILE
225   "file",
226 #endif
227 #ifndef CURL_DISABLE_FTP
228   "ftp",
229 #endif
230 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
231   "ftps",
232 #endif
233 #ifndef CURL_DISABLE_GOPHER
234   "gopher",
235 #endif
236 #ifndef CURL_DISABLE_HTTP
237   "http",
238 #endif
239 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
240   "https",
241 #endif
242 #ifndef CURL_DISABLE_IMAP
243   "imap",
244 #endif
245 #if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
246   "imaps",
247 #endif
248 #ifndef CURL_DISABLE_LDAP
249   "ldap",
250 #if !defined(CURL_DISABLE_LDAPS) && \
251     ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
252      (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
253   "ldaps",
254 #endif
255 #endif
256 #ifndef CURL_DISABLE_POP3
257   "pop3",
258 #endif
259 #if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
260   "pop3s",
261 #endif
262 #ifdef USE_LIBRTMP
263   "rtmp",
264 #endif
265 #ifndef CURL_DISABLE_RTSP
266   "rtsp",
267 #endif
268 #if defined(USE_SSH)
269   "scp",
270   "sftp",
271 #endif
272 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
273    (CURL_SIZEOF_CURL_OFF_T > 4) && \
274    (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
275   "smb",
276 #  ifdef USE_SSL
277   "smbs",
278 #  endif
279 #endif
280 #ifndef CURL_DISABLE_SMTP
281   "smtp",
282 #endif
283 #if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
284   "smtps",
285 #endif
286 #ifndef CURL_DISABLE_TELNET
287   "telnet",
288 #endif
289 #ifndef CURL_DISABLE_TFTP
290   "tftp",
291 #endif
292 
293   NULL
294 };
295 
296 static curl_version_info_data version_info = {
297   CURLVERSION_NOW,
298   LIBCURL_VERSION,
299   LIBCURL_VERSION_NUM,
300   OS, /* as found by configure or set by hand at build-time */
301   0 /* features is 0 by default */
302 #ifdef ENABLE_IPV6
303   | CURL_VERSION_IPV6
304 #endif
305 #ifdef USE_SSL
306   | CURL_VERSION_SSL
307 #endif
308 #ifdef USE_NTLM
309   | CURL_VERSION_NTLM
310 #endif
311 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
312   defined(NTLM_WB_ENABLED)
313   | CURL_VERSION_NTLM_WB
314 #endif
315 #ifdef USE_SPNEGO
316   | CURL_VERSION_SPNEGO
317 #endif
318 #ifdef USE_KERBEROS5
319   | CURL_VERSION_KERBEROS5
320 #endif
321 #ifdef HAVE_GSSAPI
322   | CURL_VERSION_GSSAPI
323 #endif
324 #ifdef USE_WINDOWS_SSPI
325   | CURL_VERSION_SSPI
326 #endif
327 #ifdef HAVE_LIBZ
328   | CURL_VERSION_LIBZ
329 #endif
330 #ifdef DEBUGBUILD
331   | CURL_VERSION_DEBUG
332 #endif
333 #ifdef CURLDEBUG
334   | CURL_VERSION_CURLDEBUG
335 #endif
336 #ifdef CURLRES_ASYNCH
337   | CURL_VERSION_ASYNCHDNS
338 #endif
339 #if (CURL_SIZEOF_CURL_OFF_T > 4) && \
340     ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
341   | CURL_VERSION_LARGEFILE
342 #endif
343 #if defined(CURL_DOES_CONVERSIONS)
344   | CURL_VERSION_CONV
345 #endif
346 #if defined(USE_TLS_SRP)
347   | CURL_VERSION_TLSAUTH_SRP
348 #endif
349 #if defined(USE_NGHTTP2)
350   | CURL_VERSION_HTTP2
351 #endif
352 #if defined(ENABLE_QUIC)
353   | CURL_VERSION_HTTP3
354 #endif
355 #if defined(USE_UNIX_SOCKETS)
356   | CURL_VERSION_UNIX_SOCKETS
357 #endif
358 #if defined(USE_LIBPSL)
359   | CURL_VERSION_PSL
360 #endif
361 #if defined(CURL_WITH_MULTI_SSL)
362   | CURL_VERSION_MULTI_SSL
363 #endif
364 #if defined(HAVE_BROTLI)
365   | CURL_VERSION_BROTLI
366 #endif
367 #if defined(USE_ALTSVC)
368   | CURL_VERSION_ALTSVC
369 #endif
370 #ifdef USE_ESNI
371   | CURL_VERSION_ESNI
372 #endif
373   ,
374   NULL, /* ssl_version */
375   0,    /* ssl_version_num, this is kept at zero */
376   NULL, /* zlib_version */
377   protocols,
378   NULL, /* c-ares version */
379   0,    /* c-ares version numerical */
380   NULL, /* libidn version */
381   0,    /* iconv version */
382   NULL, /* ssh lib version */
383   0,    /* brotli_ver_num */
384   NULL, /* brotli version */
385   0,    /* nghttp2 version number */
386   NULL, /* nghttp2 version string */
387   NULL  /* quic library string */
388 };
389 
curl_version_info(CURLversion stamp)390 curl_version_info_data *curl_version_info(CURLversion stamp)
391 {
392   static bool initialized;
393 #if defined(USE_SSH)
394   static char ssh_buffer[80];
395 #endif
396 #ifdef USE_SSL
397 #ifdef CURL_WITH_MULTI_SSL
398   static char ssl_buffer[200];
399 #else
400   static char ssl_buffer[80];
401 #endif
402 #endif
403 #ifdef HAVE_BROTLI
404   static char brotli_buffer[80];
405 #endif
406 
407   if(initialized)
408     return &version_info;
409 
410 #ifdef USE_SSL
411   Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
412   version_info.ssl_version = ssl_buffer;
413   if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
414     version_info.features |= CURL_VERSION_HTTPS_PROXY;
415   else
416     version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
417 #endif
418 
419 #ifdef HAVE_LIBZ
420   version_info.libz_version = zlibVersion();
421   /* libz left NULL if non-existing */
422 #endif
423 #ifdef USE_ARES
424   {
425     int aresnum;
426     version_info.ares = ares_version(&aresnum);
427     version_info.ares_num = aresnum;
428   }
429 #endif
430 #ifdef USE_LIBIDN2
431   /* This returns a version string if we use the given version or later,
432      otherwise it returns NULL */
433   version_info.libidn = idn2_check_version(IDN2_VERSION);
434   if(version_info.libidn)
435     version_info.features |= CURL_VERSION_IDN;
436 #elif defined(USE_WIN32_IDN)
437   version_info.features |= CURL_VERSION_IDN;
438 #endif
439 
440 #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
441 #ifdef _LIBICONV_VERSION
442   version_info.iconv_ver_num = _LIBICONV_VERSION;
443 #else
444   /* version unknown */
445   version_info.iconv_ver_num = -1;
446 #endif /* _LIBICONV_VERSION */
447 #endif
448 
449 #if defined(USE_SSH)
450   Curl_ssh_version(ssh_buffer, sizeof(ssh_buffer));
451   version_info.libssh_version = ssh_buffer;
452 #endif
453 
454 #ifdef HAVE_BROTLI
455   version_info.brotli_ver_num = BrotliDecoderVersion();
456   brotli_version(brotli_buffer, sizeof(brotli_buffer));
457   version_info.brotli_version = brotli_buffer;
458 #endif
459 
460 #ifdef USE_NGHTTP2
461   {
462     nghttp2_info *h2 = nghttp2_version(0);
463     version_info.nghttp2_ver_num = h2->version_num;
464     version_info.nghttp2_version = h2->version_str;
465   }
466 #endif
467 
468 #ifdef ENABLE_QUIC
469   {
470     static char quicbuffer[80];
471     Curl_quic_ver(quicbuffer, sizeof(quicbuffer));
472     version_info.quic_version = quicbuffer;
473   }
474 #endif
475 
476   (void)stamp; /* avoid compiler warnings, we don't use this */
477 
478   initialized = true;
479   return &version_info;
480 }
481