--- a/Cargo.toml +++ b/Cargo.toml @@ -1,17 +1,8 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - +# Vendored from crates.io libssh2-sys 0.3.3; see PROVENANCE.md. [package] name = "libssh2-sys" version = "0.3.3" +publish = false authors = [ "Alex Crichton ", "Wez Furlong ", @@ -50,12 +41,6 @@ [build-dependencies.cc] version = "1.0.25" -[build-dependencies.pkg-config] -version = "0.3.11" - -[target.'cfg(target_env = "msvc")'.build-dependencies.vcpkg] -version = "0.2" - [target."cfg(unix)".dependencies.openssl-sys] version = "0.9.35" --- a/build.rs +++ b/build.rs @@ -1,42 +1,19 @@ extern crate cc; -extern crate pkg_config; - -#[cfg(target_env = "msvc")] -extern crate vcpkg; use std::env; use std::fs; -use std::path::{Path, PathBuf}; -use std::process::Command; +use std::path::PathBuf; fn main() { - let zlib_ng_compat = env::var("CARGO_FEATURE_ZLIB_NG_COMPAT").is_ok(); - - if !zlib_ng_compat && try_vcpkg() { - return; + // This distribution contains reviewed security backports that an + // arbitrary system libssh2 may lack. Always compile this source tree. + println!("cargo:rerun-if-env-changed=LIBSSH2_SYS_USE_PKG_CONFIG"); + if env::var_os("LIBSSH2_SYS_USE_PKG_CONFIG").is_some() { + panic!("This distribution requires its patched bundled libssh2; unset LIBSSH2_SYS_USE_PKG_CONFIG"); } - - // The system copy of libssh2 is not used by default because it - // can lead to having two copies of libssl loaded at once. - // See https://github.com/alexcrichton/ssh2-rs/pull/88 - println!("cargo:rerun-if-env-changed=LIBSSH2_SYS_USE_PKG_CONFIG"); - if env::var("LIBSSH2_SYS_USE_PKG_CONFIG").is_ok() { - if zlib_ng_compat { - panic!("LIBSSH2_SYS_USE_PKG_CONFIG set, but cannot use zlib-ng-compat with system libssh2"); - } - if let Ok(lib) = pkg_config::find_library("libssh2") { - for path in &lib.include_paths { - println!("cargo:include={}", path.display()); - } - return; - } - } - - if !Path::new("libssh2/.git").exists() { - let _ = Command::new("git") - .args(&["submodule", "update", "--init"]) - .status(); - } + println!("cargo:rerun-if-changed=libssh2/src"); + println!("cargo:rerun-if-changed=libssh2/include"); + println!("cargo:rerun-if-changed=libssh2/libssh2.pc.in"); let target = env::var("TARGET").unwrap(); let profile = env::var("PROFILE").unwrap(); @@ -201,45 +178,3 @@ } } -#[cfg(not(target_env = "msvc"))] -fn try_vcpkg() -> bool { - false -} - -#[cfg(target_env = "msvc")] -fn try_vcpkg() -> bool { - vcpkg::Config::new() - .emit_includes(true) - .probe("libssh2") - .map(|_| { - // found libssh2 which depends on openssl and zlib - vcpkg::Config::new() - .lib_name("libssl") - .lib_name("libcrypto") - .probe("openssl") - .or_else(|_| { - // openssl 1.1 was not found, try openssl 1.0 - vcpkg::Config::new() - .lib_name("libeay32") - .lib_name("ssleay32") - .probe("openssl") - }) - .expect( - "configured libssh2 from vcpkg but could not \ - find openssl libraries that it depends on", - ); - - vcpkg::Config::new() - .lib_names("zlib", "zlib1") - .probe("zlib") - .expect( - "configured libssh2 from vcpkg but could not \ - find the zlib library that it depends on", - ); - - println!("cargo:rustc-link-lib=crypt32"); - println!("cargo:rustc-link-lib=gdi32"); - println!("cargo:rustc-link-lib=user32"); - }) - .is_ok() -} --- a/libssh2/src/userauth.c +++ b/libssh2/src/userauth.c @@ -80,6 +80,12 @@ memset(&session->userauth_list_packet_requirev_state, 0, sizeof(session->userauth_list_packet_requirev_state)); + if(username_len > UINT32_MAX - 27) { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "username_len out of bounds"); + return NULL; + } + session->userauth_list_data_len = username_len + 27; s = session->userauth_list_data = @@ -307,6 +313,11 @@ * 40 = packet_type(1) + username_len(4) + service_len(4) + * service(14)"ssh-connection" + method_len(4) + method(8)"password" + * chgpwdbool(1) + password_len(4) */ + if(username_len > UINT32_MAX - 40) { + return _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "username_len out of bounds"); + } + session->userauth_pswd_data_len = username_len + 40; session->userauth_pswd_data0 = @@ -447,7 +458,7 @@ } /* basic data_len + newpw_len(4) */ - if(username_len + password_len + 44 <= UINT_MAX) { + if(username_len <= UINT32_MAX - password_len - 44) { session->userauth_pswd_data_len = username_len + password_len + 44; s = session->userauth_pswd_data = --- a/libssh2/src/sftp.c +++ b/libssh2/src/sftp.c @@ -1279,6 +1279,7 @@ "got HANDLE FXOK")); LIBSSH2_FREE(session, data); + data = NULL; /* silly situation, but check for a HANDLE */ rc = sftp_packet_require(sftp, SSH_FXP_HANDLE, --- a/libssh2/src/openssl.c +++ b/libssh2/src/openssl.c @@ -1042,13 +1042,15 @@ const int aadlen = (is_aesgcm && IS_FIRST(firstlast)) ? 4 : 0; /* size of AT, if present */ const int authenticationtag = IS_LAST(firstlast) ? authlen : 0; - /* length to encrypt */ - const int cryptlen = (unsigned int)blocksize - aadlen - authenticationtag; + unsigned int cryptlen; /* length to encrypt */ (void)algo; - assert(blocksize <= sizeof(buf)); - assert(cryptlen >= 0); + if(blocksize > sizeof(buf) || + blocksize < (size_t)(aadlen + authenticationtag)) + return 1; + + cryptlen = (unsigned int)blocksize - aadlen - authenticationtag; #if LIBSSH2_AES_GCM /* First block */ --- a/libssh2/src/transport.c +++ b/libssh2/src/transport.c @@ -242,6 +242,13 @@ unsigned char *decrypt_buffer; int blocksize = session->remote.crypt->blocksize; + if(p->total_num < mac_len + 4 + (size_t)blocksize) { + LIBSSH2_FREE(session, p->payload); + p->payload = NULL; + return LIBSSH2_ERROR_DECRYPT; + } + decrypt_size = (ssize_t)(p->total_num - mac_len - 4); + rc = decrypt(session, p->payload + 4, first_block, blocksize, FIRST_BLOCK); if(rc) { @@ -249,7 +256,6 @@ } /* we need buffer for decrypt */ - decrypt_size = p->total_num - mac_len - 4; decrypt_buffer = LIBSSH2_ALLOC(session, decrypt_size); if(!decrypt_buffer) { return LIBSSH2_ERROR_ALLOC; --- a/libssh2/src/publickey.c +++ b/libssh2/src/publickey.c @@ -972,6 +972,8 @@ goto err_exit; } list = newlist; + memset(&list[keys], 0, + (max_keys - keys + 1) * sizeof(list[keys])); } if(pkey->version == 1) { unsigned long comment_len; @@ -988,6 +990,13 @@ } if(comment_len) { + if(pkey->listFetch_s + comment_len > + pkey->listFetch_data + pkey->listFetch_data_len) { + _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL, + "ListFetch data too short"); + goto err_exit; + } + list[keys].num_attrs = 1; list[keys].attrs = LIBSSH2_ALLOC(session, @@ -1114,6 +1123,11 @@ } if(list[keys].num_attrs) { + if(list[keys].num_attrs > 1024) { + _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY, + "Too many publickey attributes"); + goto err_exit; + } list[keys].attrs = LIBSSH2_ALLOC(session, list[keys].num_attrs * @@ -1188,10 +1202,9 @@ } /* To be FREEd in libssh2_publickey_list_free() */ list[keys].packet = pkey->listFetch_data; + pkey->listFetch_data = NULL; + keys++; - - list[keys].packet = NULL; /* Terminate the list */ - pkey->listFetch_data = NULL; break; default: /* Unknown/Unexpected */ @@ -1230,11 +1243,13 @@ session = pkey->channel->session; - while(p->packet) { + while(p->attrs || p->packet) { if(p->attrs) { LIBSSH2_FREE(session, p->attrs); } - LIBSSH2_FREE(session, p->packet); + if(p->packet) { + LIBSSH2_FREE(session, p->packet); + } p++; }