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