1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, 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 snprintf(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 = snprintf(ptr, left, " zlib/%s", zlibVersion()); 130 left -= len; 131 ptr += len; 132 #endif 133 #ifdef HAVE_BROTLI 134 len = snprintf(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 = snprintf(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 = snprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL)); 150 left -= len; 151 ptr += len; 152 } 153 #endif 154 #ifdef USE_LIBPSL 155 len = snprintf(ptr, left, " libpsl/%s", psl_get_version()); 156 left -= len; 157 ptr += len; 158 #endif 159 #ifdef USE_WIN32_IDN 160 len = snprintf(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 = snprintf(ptr, left, " iconv/%d.%d", 167 _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255); 168 #else 169 /* version unknown */ 170 len = snprintf(ptr, left, " iconv"); 171 #endif /* _LIBICONV_VERSION */ 172 left -= len; 173 ptr += len; 174 #endif 175 #ifdef USE_LIBSSH2 176 len = snprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION); 177 left -= len; 178 ptr += len; 179 #endif 180 #ifdef USE_LIBSSH 181 len = snprintf(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 snprintf(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 snprintf() returned 208 209 left -= len; 210 ptr += len; 211 */ 212 } 213 #endif 214 215 initialized = true; 216 return version; 217 } 218 219 /* data for curl_version_info 220 221 Keep the list sorted alphabetically. It is also written so that each 222 protocol line has its own #if line to make things easier on the eye. 223 */ 224 225 static const char * const protocols[] = { 226 #ifndef CURL_DISABLE_DICT 227 "dict", 228 #endif 229 #ifndef CURL_DISABLE_FILE 230 "file", 231 #endif 232 #ifndef CURL_DISABLE_FTP 233 "ftp", 234 #endif 235 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) 236 "ftps", 237 #endif 238 #ifndef CURL_DISABLE_GOPHER 239 "gopher", 240 #endif 241 #ifndef CURL_DISABLE_HTTP 242 "http", 243 #endif 244 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) 245 "https", 246 #endif 247 #ifndef CURL_DISABLE_IMAP 248 "imap", 249 #endif 250 #if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) 251 "imaps", 252 #endif 253 #ifndef CURL_DISABLE_LDAP 254 "ldap", 255 #if !defined(CURL_DISABLE_LDAPS) && \ 256 ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ 257 (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) 258 "ldaps", 259 #endif 260 #endif 261 #ifndef CURL_DISABLE_POP3 262 "pop3", 263 #endif 264 #if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) 265 "pop3s", 266 #endif 267 #ifdef USE_LIBRTMP 268 "rtmp", 269 #endif 270 #ifndef CURL_DISABLE_RTSP 271 "rtsp", 272 #endif 273 #if defined(USE_LIBSSH) || defined(USE_LIBSSH2) 274 "scp", 275 "sftp", 276 #endif 277 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ 278 (CURL_SIZEOF_CURL_OFF_T > 4) && \ 279 (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) 280 "smb", 281 # ifdef USE_SSL 282 "smbs", 283 # endif 284 #endif 285 #ifndef CURL_DISABLE_SMTP 286 "smtp", 287 #endif 288 #if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) 289 "smtps", 290 #endif 291 #ifndef CURL_DISABLE_TELNET 292 "telnet", 293 #endif 294 #ifndef CURL_DISABLE_TFTP 295 "tftp", 296 #endif 297 298 NULL 299 }; 300 301 static curl_version_info_data version_info = { 302 CURLVERSION_NOW, 303 LIBCURL_VERSION, 304 LIBCURL_VERSION_NUM, 305 OS, /* as found by configure or set by hand at build-time */ 306 0 /* features is 0 by default */ 307 #ifdef ENABLE_IPV6 308 | CURL_VERSION_IPV6 309 #endif 310 #ifdef USE_SSL 311 | CURL_VERSION_SSL 312 #endif 313 #ifdef USE_NTLM 314 | CURL_VERSION_NTLM 315 #endif 316 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ 317 defined(NTLM_WB_ENABLED) 318 | CURL_VERSION_NTLM_WB 319 #endif 320 #ifdef USE_SPNEGO 321 | CURL_VERSION_SPNEGO 322 #endif 323 #ifdef USE_KERBEROS5 324 | CURL_VERSION_KERBEROS5 325 #endif 326 #ifdef HAVE_GSSAPI 327 | CURL_VERSION_GSSAPI 328 #endif 329 #ifdef USE_WINDOWS_SSPI 330 | CURL_VERSION_SSPI 331 #endif 332 #ifdef HAVE_LIBZ 333 | CURL_VERSION_LIBZ 334 #endif 335 #ifdef DEBUGBUILD 336 | CURL_VERSION_DEBUG 337 #endif 338 #ifdef CURLDEBUG 339 | CURL_VERSION_CURLDEBUG 340 #endif 341 #ifdef CURLRES_ASYNCH 342 | CURL_VERSION_ASYNCHDNS 343 #endif 344 #if (CURL_SIZEOF_CURL_OFF_T > 4) && \ 345 ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) 346 | CURL_VERSION_LARGEFILE 347 #endif 348 #if defined(CURL_DOES_CONVERSIONS) 349 | CURL_VERSION_CONV 350 #endif 351 #if defined(USE_TLS_SRP) 352 | CURL_VERSION_TLSAUTH_SRP 353 #endif 354 #if defined(USE_NGHTTP2) 355 | CURL_VERSION_HTTP2 356 #endif 357 #if defined(USE_UNIX_SOCKETS) 358 | CURL_VERSION_UNIX_SOCKETS 359 #endif 360 #if defined(USE_LIBPSL) 361 | CURL_VERSION_PSL 362 #endif 363 #if defined(CURL_WITH_MULTI_SSL) 364 | CURL_VERSION_MULTI_SSL 365 #endif 366 #if defined(HAVE_BROTLI) 367 | CURL_VERSION_BROTLI 368 #endif 369 , 370 NULL, /* ssl_version */ 371 0, /* ssl_version_num, this is kept at zero */ 372 NULL, /* zlib_version */ 373 protocols, 374 NULL, /* c-ares version */ 375 0, /* c-ares version numerical */ 376 NULL, /* libidn version */ 377 0, /* iconv version */ 378 NULL, /* ssh lib version */ 379 0, /* brotli_ver_num */ 380 NULL, /* brotli version */ 381 }; 382 383 curl_version_info_data *curl_version_info(CURLversion stamp) 384 { 385 static bool initialized; 386 #if defined(USE_LIBSSH) || defined(USE_LIBSSH2) 387 static char ssh_buffer[80]; 388 #endif 389 #ifdef USE_SSL 390 static char ssl_buffer[80]; 391 #endif 392 #ifdef HAVE_BROTLI 393 static char brotli_buffer[80]; 394 #endif 395 396 if(initialized) 397 return &version_info; 398 399 #ifdef USE_SSL 400 Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); 401 version_info.ssl_version = ssl_buffer; 402 if(Curl_ssl->support_https_proxy) 403 version_info.features |= CURL_VERSION_HTTPS_PROXY; 404 else 405 version_info.features &= ~CURL_VERSION_HTTPS_PROXY; 406 #endif 407 408 #ifdef HAVE_LIBZ 409 version_info.libz_version = zlibVersion(); 410 /* libz left NULL if non-existing */ 411 #endif 412 #ifdef USE_ARES 413 { 414 int aresnum; 415 version_info.ares = ares_version(&aresnum); 416 version_info.ares_num = aresnum; 417 } 418 #endif 419 #ifdef USE_LIBIDN2 420 /* This returns a version string if we use the given version or later, 421 otherwise it returns NULL */ 422 version_info.libidn = idn2_check_version(IDN2_VERSION); 423 if(version_info.libidn) 424 version_info.features |= CURL_VERSION_IDN; 425 #elif defined(USE_WIN32_IDN) 426 version_info.features |= CURL_VERSION_IDN; 427 #endif 428 429 #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) 430 #ifdef _LIBICONV_VERSION 431 version_info.iconv_ver_num = _LIBICONV_VERSION; 432 #else 433 /* version unknown */ 434 version_info.iconv_ver_num = -1; 435 #endif /* _LIBICONV_VERSION */ 436 #endif 437 438 #if defined(USE_LIBSSH2) 439 snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION); 440 version_info.libssh_version = ssh_buffer; 441 #elif defined(USE_LIBSSH) 442 snprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION); 443 version_info.libssh_version = ssh_buffer; 444 #endif 445 446 #ifdef HAVE_BROTLI 447 version_info.brotli_ver_num = BrotliDecoderVersion(); 448 brotli_version(brotli_buffer, sizeof brotli_buffer); 449 version_info.brotli_version = brotli_buffer; 450 #endif 451 452 (void)stamp; /* avoid compiler warnings, we don't use this */ 453 454 initialized = true; 455 return &version_info; 456 } 457