From 0291716536332c64ad8d2c6105fc2bac81e1a9cb Mon Sep 17 00:00:00 2001 From: Vitalii Yarmus Date: Fri, 29 Oct 2021 15:51:37 +0300 Subject: [PATCH] RE: updated library for ssh tunneling --- reverse_engineering/node_modules/.bin/semver | 1 - .../node_modules/bcrypt-pbkdf/CONTRIBUTING.md | 13 + .../node_modules/bcrypt-pbkdf/LICENSE | 66 + .../node_modules/bcrypt-pbkdf/README.md | 45 + .../node_modules/bcrypt-pbkdf/index.js | 556 ++ .../node_modules/bcrypt-pbkdf/package.json | 44 + .../{streamsearch => cpu-features}/LICENSE | 36 +- .../node_modules/cpu-features/README.md | 60 + .../node_modules/cpu-features/binding.gyp | 91 + .../node_modules/cpu-features/build/Makefile | 334 + .../Release/.deps/Release/cpufeatures.node.d | 1 + .../Release/obj.target/build_deps.stamp.d | 1 + .../Release/obj.target/config_deps.stamp.d | 1 + .../Release/obj.target/cpufeatures.node.d | 1 + .../obj.target/cpufeatures/src/binding.o.d | 72 + .../deps/cpu_features/build/Makefile.d | 1 + .../cpu_features/build/libcpu_features.a.d | 1 + .../build/Release/cpufeatures.node | Bin 0 -> 40392 bytes .../build/Release/obj.target/build_deps.stamp | 0 .../Release/obj.target/config_deps.stamp | 0 .../build/Release/obj.target/cpufeatures.node | Bin 0 -> 40392 bytes .../obj.target/cpufeatures/src/binding.o | Bin 0 -> 15904 bytes .../cpu-features/build/binding.Makefile | 6 + .../cpu-features/build/build_deps.target.mk | 38 + .../cpu-features/build/config.gypi | 204 + .../cpu-features/build/config_deps.target.mk | 38 + .../cpu-features/build/cpufeatures.target.mk | 169 + .../deps/cpu_features/.clang-format | 4 + .../cpu_features/.github/workflows/Dockerfile | 5 + .../.github/workflows/clang_format.yml | 24 + .../cpu-features/deps/cpu_features/.npmignore | 4 + .../deps/cpu_features/.travis.yml | 121 + .../deps/cpu_features/CMakeLists.txt | 256 + .../deps/cpu_features/CONTRIBUTING.md | 23 + .../cpu-features/deps/cpu_features/LICENSE | 230 + .../cpu-features/deps/cpu_features/README.md | 199 + .../cpu-features/deps/cpu_features/WORKSPACE | 7 + .../deps/cpu_features/appveyor.yml | 24 + .../deps/cpu_features/build/CMakeCache.txt | 385 ++ .../CMakeFiles/3.10.2/CMakeCCompiler.cmake | 73 + .../3.10.2/CMakeDetermineCompilerABI_C.bin | Bin 0 -> 8248 bytes .../build/CMakeFiles/3.10.2/CMakeSystem.cmake | 15 + .../3.10.2/CompilerIdC/CMakeCCompilerId.c | 598 ++ .../build/CMakeFiles/3.10.2/CompilerIdC/a.out | Bin 0 -> 8408 bytes .../CMakeDirectoryInformation.cmake | 16 + .../build/CMakeFiles/CMakeOutput.log | 260 + .../CpuFeaturesTargets-release.cmake | 28 + .../CpuFeatures/CpuFeaturesTargets.cmake | 103 + .../build/CMakeFiles/Makefile.cmake | 112 + .../cpu_features/build/CMakeFiles/Makefile2 | 219 + .../build/CMakeFiles/TargetDirectories.txt | 10 + .../build/CMakeFiles/cmake.check_cache | 1 + .../cpu_features.dir/C.includecache | 54 + .../cpu_features.dir/DependInfo.cmake | 27 + .../CMakeFiles/cpu_features.dir/build.make | 120 + .../cpu_features.dir/cmake_clean.cmake | 10 + .../cpu_features.dir/cmake_clean_target.cmake | 3 + .../cpu_features.dir/depend.internal | 10 + .../CMakeFiles/cpu_features.dir/depend.make | 10 + .../CMakeFiles/cpu_features.dir/flags.make | 10 + .../CMakeFiles/cpu_features.dir/link.txt | 2 + .../CMakeFiles/cpu_features.dir/progress.make | 3 + .../cpu_features.dir/src/cpuinfo_x86.c.o | Bin 0 -> 39088 bytes .../build/CMakeFiles/feature_tests.bin | Bin 0 -> 8208 bytes .../build/CMakeFiles/feature_tests.c | 34 + .../list_cpu_features.dir/C.includecache | 82 + .../list_cpu_features.dir/DependInfo.cmake | 27 + .../list_cpu_features.dir/build.make | 114 + .../list_cpu_features.dir/cmake_clean.cmake | 10 + .../list_cpu_features.dir/depend.internal | 13 + .../list_cpu_features.dir/depend.make | 13 + .../list_cpu_features.dir/flags.make | 10 + .../CMakeFiles/list_cpu_features.dir/link.txt | 1 + .../list_cpu_features.dir/progress.make | 3 + .../src/utils/list_cpu_features.c.o | Bin 0 -> 14304 bytes .../build/CMakeFiles/progress.marks | 1 + .../C.includecache | 72 + .../DependInfo.cmake | 30 + .../build.make | 131 + .../cmake_clean.cmake | 9 + .../depend.internal | 15 + .../depend.make | 15 + .../flags.make | 10 + .../progress.make | 3 + .../src/hwcaps.c.o | Bin 0 -> 4144 bytes .../src/unix_features_aggregator.c.o | Bin 0 -> 1880 bytes .../build/CMakeFiles/utils.dir/C.includecache | 76 + .../CMakeFiles/utils.dir/DependInfo.cmake | 29 + .../build/CMakeFiles/utils.dir/build.make | 157 + .../CMakeFiles/utils.dir/cmake_clean.cmake | 10 + .../CMakeFiles/utils.dir/depend.internal | 17 + .../build/CMakeFiles/utils.dir/depend.make | 17 + .../build/CMakeFiles/utils.dir/flags.make | 10 + .../build/CMakeFiles/utils.dir/progress.make | 4 + .../CMakeFiles/utils.dir/src/filesystem.c.o | Bin 0 -> 1976 bytes .../utils.dir/src/stack_line_reader.c.o | Bin 0 -> 2584 bytes .../CMakeFiles/utils.dir/src/string_view.c.o | Bin 0 -> 5720 bytes .../build/CpuFeaturesConfig.cmake | 3 + .../build/CpuFeaturesConfigVersion.cmake | 46 + .../deps/cpu_features/build/Makefile | 450 ++ .../cpu_features/build/cmake_install.cmake | 103 + .../deps/cpu_features/build/libcpu_features.a | Bin 0 -> 50632 bytes .../deps/cpu_features/build/list_cpu_features | Bin 0 -> 34400 bytes .../cmake/CpuFeaturesConfig.cmake.in | 3 + .../cmake/CpuFeaturesNdkCompatConfig.cmake.in | 3 + .../deps/cpu_features/cmake/README.md | 28 + .../cmake/googletest.CMakeLists.txt.in | 15 + .../include/cpu_features_cache_info.h | 54 + .../include/cpu_features_macros.h | 212 + .../cpu_features/include/cpuinfo_aarch64.h | 156 + .../deps/cpu_features/include/cpuinfo_arm.h | 121 + .../deps/cpu_features/include/cpuinfo_mips.h | 60 + .../deps/cpu_features/include/cpuinfo_ppc.h | 146 + .../deps/cpu_features/include/cpuinfo_x86.h | 231 + .../cpu_features/include/internal/bit_utils.h | 40 + .../cpu_features/include/internal/cpuid_x86.h | 36 + .../include/internal/filesystem.h | 39 + .../cpu_features/include/internal/hwcaps.h | 183 + .../include/internal/stack_line_reader.h | 49 + .../include/internal/string_view.h | 109 + .../internal/unix_features_aggregator.h | 73 + .../cpu_features/ndk_compat/CMakeLists.txt | 60 + .../deps/cpu_features/ndk_compat/README.md | 4 + .../cpu_features/ndk_compat/cpu-features.c | 205 + .../cpu_features/ndk_compat/cpu-features.h | 320 + .../cpu_features/ndk_compat/ndk-compat-test.c | 12 + .../cpu_features/scripts/run_integration.sh | 209 + .../cpu_features/scripts/test_integration.sh | 106 + .../deps/cpu_features/src/cpuinfo_aarch64.c | 198 + .../deps/cpu_features/src/cpuinfo_arm.c | 236 + .../deps/cpu_features/src/cpuinfo_mips.c | 90 + .../deps/cpu_features/src/cpuinfo_ppc.c | 189 + .../deps/cpu_features/src/cpuinfo_x86.c | 1694 ++++++ .../deps/cpu_features/src/filesystem.c | 62 + .../deps/cpu_features/src/hwcaps.c | 163 + .../deps/cpu_features/src/stack_line_reader.c | 132 + .../deps/cpu_features/src/string_view.c | 182 + .../src/unix_features_aggregator.c | 53 + .../src/utils/list_cpu_features.c | 438 ++ .../deps/cpu_features/test/CMakeLists.txt | 88 + .../deps/cpu_features/test/bit_utils_test.cc | 53 + .../cpu_features/test/cpuinfo_aarch64_test.cc | 171 + .../cpu_features/test/cpuinfo_arm_test.cc | 354 ++ .../cpu_features/test/cpuinfo_mips_test.cc | 126 + .../cpu_features/test/cpuinfo_ppc_test.cc | 119 + .../cpu_features/test/cpuinfo_x86_test.cc | 281 + .../test/filesystem_for_testing.cc | 103 + .../test/filesystem_for_testing.h | 61 + .../cpu_features/test/hwcaps_for_testing.cc | 46 + .../cpu_features/test/hwcaps_for_testing.h | 27 + .../test/stack_line_reader_test.cc | 132 + .../cpu_features/test/string_view_test.cc | 192 + .../test/unix_features_aggregator_test.cc | 105 + .../node_modules/cpu-features/lib/index.js | 3 + .../node_modules/cpu-features/package.json | 66 + .../node_modules/cpu-features/src/binding.cc | 153 + .../node_modules/nan/CHANGELOG.md | 541 ++ .../node_modules/nan/LICENSE.md | 13 + .../node_modules/nan/README.md | 456 ++ .../node_modules/nan/doc/asyncworker.md | 146 + .../node_modules/nan/doc/buffers.md | 54 + .../node_modules/nan/doc/callback.md | 76 + .../node_modules/nan/doc/converters.md | 41 + .../node_modules/nan/doc/errors.md | 226 + .../node_modules/nan/doc/json.md | 62 + .../node_modules/nan/doc/maybe_types.md | 583 ++ .../node_modules/nan/doc/methods.md | 664 ++ .../node_modules/nan/doc/new.md | 147 + .../node_modules/nan/doc/node_misc.md | 123 + .../node_modules/nan/doc/object_wrappers.md | 263 + .../node_modules/nan/doc/persistent.md | 296 + .../node_modules/nan/doc/scopes.md | 73 + .../node_modules/nan/doc/script.md | 58 + .../node_modules/nan/doc/string_bytes.md | 62 + .../node_modules/nan/doc/v8_internals.md | 199 + .../node_modules/nan/doc/v8_misc.md | 85 + .../node_modules/nan/include_dirs.js | 1 + reverse_engineering/node_modules/nan/nan.h | 2904 +++++++++ .../node_modules/nan/nan_callbacks.h | 88 + .../node_modules/nan/nan_callbacks_12_inl.h | 514 ++ .../nan/nan_callbacks_pre_12_inl.h | 520 ++ .../node_modules/nan/nan_converters.h | 72 + .../node_modules/nan/nan_converters_43_inl.h | 68 + .../nan/nan_converters_pre_43_inl.h | 42 + .../nan/nan_define_own_property_helper.h | 29 + .../nan/nan_implementation_12_inl.h | 430 ++ .../nan/nan_implementation_pre_12_inl.h | 263 + .../node_modules/nan/nan_json.h | 166 + .../node_modules/nan/nan_maybe_43_inl.h | 356 ++ .../node_modules/nan/nan_maybe_pre_43_inl.h | 268 + .../node_modules/nan/nan_new.h | 340 ++ .../node_modules/nan/nan_object_wrap.h | 156 + .../node_modules/nan/nan_persistent_12_inl.h | 132 + .../nan/nan_persistent_pre_12_inl.h | 242 + .../node_modules/nan/nan_private.h | 73 + .../node_modules/nan/nan_scriptorigin.h | 76 + .../node_modules/nan/nan_string_bytes.h | 305 + .../nan/nan_typedarray_contents.h | 96 + .../node_modules/nan/nan_weak.h | 437 ++ .../node_modules/nan/package.json | 99 + .../node_modules/nan/tools/1to2.js | 412 ++ .../node_modules/nan/tools/README.md | 14 + .../node_modules/nan/tools/package.json | 19 + .../node_modules/semver/CHANGELOG.md | 39 - .../node_modules/semver/LICENSE | 15 - .../node_modules/semver/README.md | 412 -- .../node_modules/semver/bin/semver | 160 - .../node_modules/semver/package.json | 32 - .../node_modules/semver/range.bnf | 16 - .../node_modules/semver/semver.js | 1483 ----- .../node_modules/ssh2-streams/.travis.yml | 17 - .../node_modules/ssh2-streams/README.md | 569 -- .../node_modules/ssh2-streams/index.js | 6 - .../ssh2-streams/lib/constants.js | 386 -- .../node_modules/ssh2-streams/lib/jsbn.js | 1186 ---- .../ssh2-streams/lib/keyParser.js | 239 - .../node_modules/ssh2-streams/lib/sftp.js | 2967 --------- .../node_modules/ssh2-streams/lib/ssh.js | 5403 ----------------- .../node_modules/ssh2-streams/lib/utils.js | 817 --- .../node_modules/ssh2-streams/package.json | 22 - .../ssh2-streams/test/fixtures/id_rsa | 27 - .../ssh2-streams/test/fixtures/id_rsa_enc | 30 - .../test/fixtures/ssh_host_rsa_key | 15 - .../ssh2-streams/test/test-durability-ssh.js | 169 - .../ssh2-streams/test/test-kexdh.js | 66 - .../ssh2-streams/test/test-keyparser.js | 2301 ------- .../ssh2-streams/test/test-packet60.js | 256 - .../ssh2-streams/test/test-sftp.js | 1274 ---- .../ssh2-streams/test/test-ssh.js | 143 - .../ssh2-streams/test/test-utils.js | 678 --- .../node_modules/ssh2-streams/test/test.js | 22 - .../node_modules/ssh2/.eslintignore | 4 + .../node_modules/ssh2/.eslintrc.js | 5 + .../ssh2/.github/workflows/ci.yml | 40 + .../ssh2/.github/workflows/lint.yml | 23 + .../node_modules/ssh2/.travis.yml | 18 - .../node_modules/ssh2/README.md | 1326 ++-- .../SFTPStream.md => ssh2/SFTP.md} | 102 +- .../node_modules/ssh2/examples/server-chat.js | 123 +- .../examples/sftp-server-download-only.js | 154 +- .../node_modules/ssh2/install.js | 20 + .../node_modules/ssh2/lib/Channel.js | 686 +-- .../node_modules/ssh2/lib/SFTPWrapper.js | 145 - .../node_modules/ssh2/lib/agent.js | 1449 +++-- .../node_modules/ssh2/lib/client.js | 2929 +++++---- .../node_modules/ssh2/lib/http-agents.js | 84 + .../node_modules/ssh2/lib/index.js | 43 + .../node_modules/ssh2/lib/keepalivemgr.js | 76 - .../ssh2/lib/protocol/Protocol.js | 2076 +++++++ .../node_modules/ssh2/lib/protocol/SFTP.js | 3778 ++++++++++++ .../ssh2/lib/protocol/constants.js | 344 ++ .../node_modules/ssh2/lib/protocol/crypto.js | 1607 +++++ .../ssh2/lib/protocol/crypto/binding.gyp | 14 + .../ssh2/lib/protocol/crypto/build/Makefile | 324 + .../.deps/Release/obj.target/sshcrypto.node.d | 1 + .../obj.target/sshcrypto/src/binding.o.d | 117 + .../Release/.deps/Release/sshcrypto.node.d | 1 + .../build/Release/obj.target/sshcrypto.node | Bin 0 -> 86400 bytes .../obj.target/sshcrypto/src/binding.o | Bin 0 -> 142480 bytes .../crypto/build/Release/sshcrypto.node | Bin 0 -> 86400 bytes .../protocol/crypto/build/binding.Makefile | 6 + .../lib/protocol/crypto/build/config.gypi | 205 + .../protocol/crypto/build/sshcrypto.target.mk | 161 + .../ssh2/lib/protocol/crypto/poly1305.js | 43 + .../ssh2/lib/protocol/crypto/src/binding.cc | 2003 ++++++ .../ssh2/lib/protocol/handlers.js | 16 + .../ssh2/lib/protocol/handlers.misc.js | 1214 ++++ .../node_modules/ssh2/lib/protocol/kex.js | 1831 ++++++ .../ssh2/lib/protocol/keyParser.js | 1481 +++++ .../ssh2/lib/protocol/node-fs-compat.js | 115 + .../node_modules/ssh2/lib/protocol/utils.js | 356 ++ .../node_modules/ssh2/lib/protocol/zlib.js | 255 + .../node_modules/ssh2/lib/server.js | 2241 +++---- .../node_modules/ssh2/lib/utils.js | 335 +- .../node_modules/ssh2/package.json | 92 +- .../node_modules/ssh2/test/common.js | 316 + .../ssh2/test/fixtures/https_cert.pem | 33 + .../ssh2/test/fixtures/https_key.pem | 52 + .../test/fixtures/keyParser/openssh_new_dsa | 21 + .../fixtures/keyParser/openssh_new_dsa.pub | 1 + .../keyParser/openssh_new_dsa.pub.result | 7 + .../fixtures/keyParser/openssh_new_dsa.result | 7 + .../fixtures/keyParser/openssh_new_dsa_enc | 22 + .../keyParser/openssh_new_dsa_enc.pub | 1 + .../keyParser/openssh_new_dsa_enc.pub.result | 7 + .../keyParser/openssh_new_dsa_enc.result | 7 + .../keyParser/openssh_new_dsa_enc_gcm | 23 + .../keyParser/openssh_new_dsa_enc_gcm.pub | 1 + .../openssh_new_dsa_enc_gcm.pub.result | 7 + .../keyParser/openssh_new_dsa_enc_gcm.result | 7 + .../test/fixtures/keyParser/openssh_new_ecdsa | 9 + .../fixtures/keyParser/openssh_new_ecdsa.pub | 1 + .../keyParser/openssh_new_ecdsa.pub.result | 7 + .../keyParser/openssh_new_ecdsa.result | 7 + .../fixtures/keyParser/openssh_new_ecdsa_enc | 10 + .../keyParser/openssh_new_ecdsa_enc.pub | 1 + .../openssh_new_ecdsa_enc.pub.result | 8 + .../keyParser/openssh_new_ecdsa_enc.result | 7 + .../keyParser/openssh_new_ecdsa_enc_gcm | 10 + .../keyParser/openssh_new_ecdsa_enc_gcm.pub | 1 + .../openssh_new_ecdsa_enc_gcm.pub.result | 8 + .../openssh_new_ecdsa_enc_gcm.result | 7 + .../fixtures/keyParser/openssh_new_ed25519 | 7 + .../keyParser/openssh_new_ed25519.pub | 1 + .../keyParser/openssh_new_ed25519.pub.result | 7 + .../keyParser/openssh_new_ed25519.result | 7 + .../test/fixtures/keyParser/openssh_new_rsa | 27 + .../fixtures/keyParser/openssh_new_rsa.pub | 1 + .../keyParser/openssh_new_rsa.pub.result | 7 + .../fixtures/keyParser/openssh_new_rsa.result | 7 + .../fixtures/keyParser/openssh_new_rsa_enc | 28 + .../keyParser/openssh_new_rsa_enc.pub | 1 + .../keyParser/openssh_new_rsa_enc.pub.result | 8 + .../keyParser/openssh_new_rsa_enc.result | 7 + .../keyParser/openssh_new_rsa_enc_gcm | 29 + .../keyParser/openssh_new_rsa_enc_gcm.pub | 1 + .../openssh_new_rsa_enc_gcm.pub.result | 8 + .../keyParser/openssh_new_rsa_enc_gcm.result | 7 + .../test/fixtures/keyParser/openssh_old_dsa | 12 + .../fixtures/keyParser/openssh_old_dsa.pub | 1 + .../keyParser/openssh_old_dsa.pub.result | 7 + .../fixtures/keyParser/openssh_old_dsa.result | 7 + .../fixtures/keyParser/openssh_old_dsa_enc | 15 + .../keyParser/openssh_old_dsa_enc.pub | 1 + .../keyParser/openssh_old_dsa_enc.pub.result | 8 + .../keyParser/openssh_old_dsa_enc.result | 7 + .../test/fixtures/keyParser/openssh_old_ecdsa | 5 + .../fixtures/keyParser/openssh_old_ecdsa.pub | 1 + .../keyParser/openssh_old_ecdsa.pub.result | 7 + .../keyParser/openssh_old_ecdsa.result | 7 + .../fixtures/keyParser/openssh_old_ecdsa_enc | 8 + .../keyParser/openssh_old_ecdsa_enc.pub | 1 + .../openssh_old_ecdsa_enc.pub.result | 8 + .../keyParser/openssh_old_ecdsa_enc.result | 7 + .../test/fixtures/keyParser/openssh_old_rsa | 27 + .../fixtures/keyParser/openssh_old_rsa.pub | 1 + .../keyParser/openssh_old_rsa.pub.result | 7 + .../fixtures/keyParser/openssh_old_rsa.result | 7 + .../fixtures/keyParser/openssh_old_rsa_enc | 30 + .../keyParser/openssh_old_rsa_enc.pub | 1 + .../keyParser/openssh_old_rsa_enc.pub.result | 8 + .../keyParser/openssh_old_rsa_enc.result | 7 + .../keyParser/openssh_old_rsa_enc_aes256 | 54 + .../keyParser/openssh_old_rsa_enc_aes256.pub | 1 + .../openssh_old_rsa_enc_aes256.pub.result | 6 + .../openssh_old_rsa_enc_aes256.result | 6 + .../test/fixtures/keyParser/ppk_dsa_enc} | 0 .../fixtures/keyParser/ppk_dsa_enc.result | 7 + .../ssh2/test/fixtures/keyParser/ppk_rsa | 26 + .../test/fixtures/keyParser/ppk_rsa.result | 7 + .../test/fixtures/keyParser/ppk_rsa_enc} | 0 .../fixtures/keyParser/ppk_rsa_enc.result | 7 + .../test/fixtures/keyParser/rfc4716_rsa.pub | 9 + .../fixtures/keyParser/rfc4716_rsa.pub.result | 7 + .../test/fixtures/keyParser/rfc4716_rsa2.pub | 10 + .../keyParser/rfc4716_rsa2.pub.result | 7 + .../test/fixtures/keyParser/rfc4716_rsa3.pub | 11 + .../keyParser/rfc4716_rsa3.pub.result | 7 + .../test/fixtures/keyParser/rfc4716_rsa4.pub | 11 + .../keyParser/rfc4716_rsa4.pub.result | 7 + .../test/fixtures/keyParser/rfc4716_rsa5.pub | 8 + .../keyParser/rfc4716_rsa5.pub.result | 7 + .../test/fixtures/keyParser/rfc4716_rsa6.pub | 13 + .../keyParser/rfc4716_rsa6.pub.result | 7 + .../ssh2/test/fixtures/openssh_new_rsa | 27 + .../ssh2/test/test-client-server.js | 1902 ------ .../node_modules/ssh2/test/test-exec.js | 578 ++ .../ssh2/test/test-integration-openssh.js | 481 ++ .../ssh2/test/test-misc-client-server.js | 1428 +++++ .../node_modules/ssh2/test/test-openssh.js | 692 +-- .../ssh2/test/test-protocol-crypto.js | 609 ++ .../ssh2/test/test-protocol-keyparser.js | 145 + .../ssh2/test/test-server-hostkeys.js | 136 + .../node_modules/ssh2/test/test-sftp.js | 782 +++ .../node_modules/ssh2/test/test-shell.js | 109 + .../ssh2/test/test-userauth-agent-openssh.js | 109 + .../ssh2/test/test-userauth-agent.js | 170 + .../node_modules/ssh2/test/test-userauth.js | 608 ++ .../node_modules/ssh2/test/test.js | 34 +- .../node_modules/streamsearch/README.md | 87 - .../node_modules/streamsearch/lib/sbmh.js | 213 - .../node_modules/streamsearch/package.json | 14 - .../node_modules/tunnel-ssh/.eslintignore | 8 +- .../node_modules/tunnel-ssh/.travis.yml | 4 + .../{ssh2-streams => tunnel-ssh}/LICENSE | 40 +- .../node_modules/tunnel-ssh/README.md | 278 +- .../tunnel-ssh/examples/default.js | 52 +- .../tunnel-ssh/examples/keepAlive.js | 70 +- .../tunnel-ssh/examples/keepAlive_error.js | 70 +- .../tunnel-ssh/examples/loginError.js | 30 - .../tunnel-ssh/examples/server/index.js | 72 +- .../node_modules/tunnel-ssh/index.js | 213 +- .../node_modules/tunnel-ssh/lib/config.js | 106 +- .../node_modules/tunnel-ssh/package.json | 73 +- .../node_modules/tunnel-ssh/rewrite.js | 138 - .../tunnel-ssh/test/config-spec.js | 112 +- .../node_modules/tunnel-ssh/test/main-spec.js | 74 +- .../tunnel-ssh/test/server/index.js | 72 +- .../node_modules/tweetnacl/.npmignore | 4 + .../node_modules/tweetnacl/AUTHORS.md | 28 + .../node_modules/tweetnacl/CHANGELOG.md | 221 + .../node_modules/tweetnacl/LICENSE | 24 + .../tweetnacl/PULL_REQUEST_TEMPLATE.md | 20 + .../node_modules/tweetnacl/README.md | 459 ++ .../node_modules/tweetnacl/nacl-fast.js | 2388 ++++++++ .../node_modules/tweetnacl/nacl-fast.min.js | 2 + .../node_modules/tweetnacl/nacl.d.ts | 98 + .../node_modules/tweetnacl/nacl.js | 1175 ++++ .../node_modules/tweetnacl/nacl.min.js | 1 + .../node_modules/tweetnacl/package.json | 85 + reverse_engineering/package-lock.json | 67 +- reverse_engineering/package.json | 2 +- 412 files changed, 60207 insertions(+), 26186 deletions(-) delete mode 120000 reverse_engineering/node_modules/.bin/semver create mode 100644 reverse_engineering/node_modules/bcrypt-pbkdf/CONTRIBUTING.md create mode 100644 reverse_engineering/node_modules/bcrypt-pbkdf/LICENSE create mode 100644 reverse_engineering/node_modules/bcrypt-pbkdf/README.md create mode 100644 reverse_engineering/node_modules/bcrypt-pbkdf/index.js create mode 100644 reverse_engineering/node_modules/bcrypt-pbkdf/package.json rename reverse_engineering/node_modules/{streamsearch => cpu-features}/LICENSE (98%) create mode 100644 reverse_engineering/node_modules/cpu-features/README.md create mode 100644 reverse_engineering/node_modules/cpu-features/binding.gyp create mode 100644 reverse_engineering/node_modules/cpu-features/build/Makefile create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/cpufeatures.node.d create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/build_deps.stamp.d create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/config_deps.stamp.d create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures.node.d create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile.d create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a.d create mode 100755 reverse_engineering/node_modules/cpu-features/build/Release/cpufeatures.node create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/obj.target/build_deps.stamp create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/obj.target/config_deps.stamp create mode 100755 reverse_engineering/node_modules/cpu-features/build/Release/obj.target/cpufeatures.node create mode 100644 reverse_engineering/node_modules/cpu-features/build/Release/obj.target/cpufeatures/src/binding.o create mode 100644 reverse_engineering/node_modules/cpu-features/build/binding.Makefile create mode 100644 reverse_engineering/node_modules/cpu-features/build/build_deps.target.mk create mode 100644 reverse_engineering/node_modules/cpu-features/build/config.gypi create mode 100644 reverse_engineering/node_modules/cpu-features/build/config_deps.target.mk create mode 100644 reverse_engineering/node_modules/cpu-features/build/cpufeatures.target.mk create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/.clang-format create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/.github/workflows/Dockerfile create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/.github/workflows/clang_format.yml create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/.npmignore create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/.travis.yml create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/CMakeLists.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/CONTRIBUTING.md create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/LICENSE create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/README.md create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/WORKSPACE create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/appveyor.yml create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeCache.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeCCompiler.cmake create mode 100755 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeSystem.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/CMakeCCompilerId.c create mode 100755 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/a.out create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeOutput.log create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets-release.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile2 create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/TargetDirectories.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cmake.check_cache create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/C.includecache create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/DependInfo.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/build.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean_target.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.internal create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/flags.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/link.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/progress.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o create mode 100755 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.bin create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/C.includecache create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/DependInfo.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/build.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/cmake_clean.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.internal create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/flags.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/link.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/progress.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/progress.marks create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/C.includecache create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/DependInfo.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/build.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/cmake_clean.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.internal create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/flags.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/progress.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/C.includecache create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/DependInfo.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/build.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/cmake_clean.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.internal create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/flags.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/progress.make create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/filesystem.c.o create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/stack_line_reader.c.o create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/string_view.c.o create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfig.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfigVersion.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/cmake_install.cmake create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a create mode 100755 reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/list_cpu_features create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesConfig.cmake.in create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/README.md create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/googletest.CMakeLists.txt.in create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_aarch64.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_arm.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_mips.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_ppc.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/bit_utils.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/cpuid_x86.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/filesystem.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/hwcaps.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/stack_line_reader.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/string_view.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/unix_features_aggregator.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/CMakeLists.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/README.md create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/ndk-compat-test.c create mode 100755 reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/run_integration.sh create mode 100755 reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/test_integration.sh create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_aarch64.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_arm.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_mips.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_ppc.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/CMakeLists.txt create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/bit_utils_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_aarch64_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_arm_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_mips_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_ppc_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_x86_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.h create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/stack_line_reader_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/string_view_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/unix_features_aggregator_test.cc create mode 100644 reverse_engineering/node_modules/cpu-features/lib/index.js create mode 100644 reverse_engineering/node_modules/cpu-features/package.json create mode 100644 reverse_engineering/node_modules/cpu-features/src/binding.cc create mode 100644 reverse_engineering/node_modules/nan/CHANGELOG.md create mode 100644 reverse_engineering/node_modules/nan/LICENSE.md create mode 100644 reverse_engineering/node_modules/nan/README.md create mode 100644 reverse_engineering/node_modules/nan/doc/asyncworker.md create mode 100644 reverse_engineering/node_modules/nan/doc/buffers.md create mode 100644 reverse_engineering/node_modules/nan/doc/callback.md create mode 100644 reverse_engineering/node_modules/nan/doc/converters.md create mode 100644 reverse_engineering/node_modules/nan/doc/errors.md create mode 100644 reverse_engineering/node_modules/nan/doc/json.md create mode 100644 reverse_engineering/node_modules/nan/doc/maybe_types.md create mode 100644 reverse_engineering/node_modules/nan/doc/methods.md create mode 100644 reverse_engineering/node_modules/nan/doc/new.md create mode 100644 reverse_engineering/node_modules/nan/doc/node_misc.md create mode 100644 reverse_engineering/node_modules/nan/doc/object_wrappers.md create mode 100644 reverse_engineering/node_modules/nan/doc/persistent.md create mode 100644 reverse_engineering/node_modules/nan/doc/scopes.md create mode 100644 reverse_engineering/node_modules/nan/doc/script.md create mode 100644 reverse_engineering/node_modules/nan/doc/string_bytes.md create mode 100644 reverse_engineering/node_modules/nan/doc/v8_internals.md create mode 100644 reverse_engineering/node_modules/nan/doc/v8_misc.md create mode 100644 reverse_engineering/node_modules/nan/include_dirs.js create mode 100644 reverse_engineering/node_modules/nan/nan.h create mode 100644 reverse_engineering/node_modules/nan/nan_callbacks.h create mode 100644 reverse_engineering/node_modules/nan/nan_callbacks_12_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_callbacks_pre_12_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_converters.h create mode 100644 reverse_engineering/node_modules/nan/nan_converters_43_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_converters_pre_43_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_define_own_property_helper.h create mode 100644 reverse_engineering/node_modules/nan/nan_implementation_12_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_implementation_pre_12_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_json.h create mode 100644 reverse_engineering/node_modules/nan/nan_maybe_43_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_maybe_pre_43_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_new.h create mode 100644 reverse_engineering/node_modules/nan/nan_object_wrap.h create mode 100644 reverse_engineering/node_modules/nan/nan_persistent_12_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_persistent_pre_12_inl.h create mode 100644 reverse_engineering/node_modules/nan/nan_private.h create mode 100644 reverse_engineering/node_modules/nan/nan_scriptorigin.h create mode 100644 reverse_engineering/node_modules/nan/nan_string_bytes.h create mode 100644 reverse_engineering/node_modules/nan/nan_typedarray_contents.h create mode 100644 reverse_engineering/node_modules/nan/nan_weak.h create mode 100644 reverse_engineering/node_modules/nan/package.json create mode 100755 reverse_engineering/node_modules/nan/tools/1to2.js create mode 100644 reverse_engineering/node_modules/nan/tools/README.md create mode 100644 reverse_engineering/node_modules/nan/tools/package.json delete mode 100644 reverse_engineering/node_modules/semver/CHANGELOG.md delete mode 100644 reverse_engineering/node_modules/semver/LICENSE delete mode 100644 reverse_engineering/node_modules/semver/README.md delete mode 100755 reverse_engineering/node_modules/semver/bin/semver delete mode 100644 reverse_engineering/node_modules/semver/package.json delete mode 100644 reverse_engineering/node_modules/semver/range.bnf delete mode 100644 reverse_engineering/node_modules/semver/semver.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/.travis.yml delete mode 100644 reverse_engineering/node_modules/ssh2-streams/README.md delete mode 100644 reverse_engineering/node_modules/ssh2-streams/index.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/lib/constants.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/lib/jsbn.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/lib/keyParser.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/lib/sftp.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/lib/ssh.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/lib/utils.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/package.json delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa_enc delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/fixtures/ssh_host_rsa_key delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-durability-ssh.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-kexdh.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-keyparser.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-packet60.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-sftp.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-ssh.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test-utils.js delete mode 100644 reverse_engineering/node_modules/ssh2-streams/test/test.js create mode 100644 reverse_engineering/node_modules/ssh2/.eslintignore create mode 100644 reverse_engineering/node_modules/ssh2/.eslintrc.js create mode 100644 reverse_engineering/node_modules/ssh2/.github/workflows/ci.yml create mode 100644 reverse_engineering/node_modules/ssh2/.github/workflows/lint.yml delete mode 100644 reverse_engineering/node_modules/ssh2/.travis.yml rename reverse_engineering/node_modules/{ssh2-streams/SFTPStream.md => ssh2/SFTP.md} (50%) create mode 100644 reverse_engineering/node_modules/ssh2/install.js delete mode 100644 reverse_engineering/node_modules/ssh2/lib/SFTPWrapper.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/http-agents.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/index.js delete mode 100644 reverse_engineering/node_modules/ssh2/lib/keepalivemgr.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/Protocol.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/SFTP.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/constants.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/binding.gyp create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Makefile create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto.node.d create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d create mode 100755 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto.node create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto/src/binding.o create mode 100755 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/sshcrypto.node create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/binding.Makefile create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/config.gypi create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/sshcrypto.target.mk create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/poly1305.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/crypto/src/binding.cc create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/handlers.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/handlers.misc.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/kex.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/keyParser.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/node-fs-compat.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/utils.js create mode 100644 reverse_engineering/node_modules/ssh2/lib/protocol/zlib.js create mode 100644 reverse_engineering/node_modules/ssh2/test/common.js create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/https_cert.pem create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/https_key.pem create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519 create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256 create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.result rename reverse_engineering/node_modules/{ssh2-streams/test/fixtures/encrypted-dsa.ppk => ssh2/test/fixtures/keyParser/ppk_dsa_enc} (100%) create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa.result rename reverse_engineering/node_modules/{ssh2-streams/test/fixtures/encrypted-rsa.ppk => ssh2/test/fixtures/keyParser/ppk_rsa_enc} (100%) create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub.result create mode 100644 reverse_engineering/node_modules/ssh2/test/fixtures/openssh_new_rsa delete mode 100644 reverse_engineering/node_modules/ssh2/test/test-client-server.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-exec.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-integration-openssh.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-misc-client-server.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-protocol-crypto.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-protocol-keyparser.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-server-hostkeys.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-sftp.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-shell.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-userauth-agent-openssh.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-userauth-agent.js create mode 100644 reverse_engineering/node_modules/ssh2/test/test-userauth.js delete mode 100644 reverse_engineering/node_modules/streamsearch/README.md delete mode 100644 reverse_engineering/node_modules/streamsearch/lib/sbmh.js delete mode 100644 reverse_engineering/node_modules/streamsearch/package.json create mode 100644 reverse_engineering/node_modules/tunnel-ssh/.travis.yml rename reverse_engineering/node_modules/{ssh2-streams => tunnel-ssh}/LICENSE (54%) delete mode 100644 reverse_engineering/node_modules/tunnel-ssh/examples/loginError.js delete mode 100644 reverse_engineering/node_modules/tunnel-ssh/rewrite.js create mode 100644 reverse_engineering/node_modules/tweetnacl/.npmignore create mode 100644 reverse_engineering/node_modules/tweetnacl/AUTHORS.md create mode 100644 reverse_engineering/node_modules/tweetnacl/CHANGELOG.md create mode 100644 reverse_engineering/node_modules/tweetnacl/LICENSE create mode 100644 reverse_engineering/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md create mode 100644 reverse_engineering/node_modules/tweetnacl/README.md create mode 100644 reverse_engineering/node_modules/tweetnacl/nacl-fast.js create mode 100644 reverse_engineering/node_modules/tweetnacl/nacl-fast.min.js create mode 100644 reverse_engineering/node_modules/tweetnacl/nacl.d.ts create mode 100644 reverse_engineering/node_modules/tweetnacl/nacl.js create mode 100644 reverse_engineering/node_modules/tweetnacl/nacl.min.js create mode 100644 reverse_engineering/node_modules/tweetnacl/package.json diff --git a/reverse_engineering/node_modules/.bin/semver b/reverse_engineering/node_modules/.bin/semver deleted file mode 120000 index 317eb29..0000000 --- a/reverse_engineering/node_modules/.bin/semver +++ /dev/null @@ -1 +0,0 @@ -../semver/bin/semver \ No newline at end of file diff --git a/reverse_engineering/node_modules/bcrypt-pbkdf/CONTRIBUTING.md b/reverse_engineering/node_modules/bcrypt-pbkdf/CONTRIBUTING.md new file mode 100644 index 0000000..401d34e --- /dev/null +++ b/reverse_engineering/node_modules/bcrypt-pbkdf/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing + +This repository uses [cr.joyent.us](https://cr.joyent.us) (Gerrit) for new +changes. Anyone can submit changes. To get started, see the [cr.joyent.us user +guide](https://github.com/joyent/joyent-gerrit/blob/master/docs/user/README.md). +This repo does not use GitHub pull requests. + +See the [Joyent Engineering +Guidelines](https://github.com/joyent/eng/blob/master/docs/index.md) for general +best practices expected in this repository. + +If you're changing something non-trivial or user-facing, you may want to submit +an issue first. diff --git a/reverse_engineering/node_modules/bcrypt-pbkdf/LICENSE b/reverse_engineering/node_modules/bcrypt-pbkdf/LICENSE new file mode 100644 index 0000000..fc58d2a --- /dev/null +++ b/reverse_engineering/node_modules/bcrypt-pbkdf/LICENSE @@ -0,0 +1,66 @@ +The Blowfish portions are under the following license: + +Blowfish block cipher for OpenBSD +Copyright 1997 Niels Provos +All rights reserved. + +Implementation advice by David Mazieres . + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +The bcrypt_pbkdf portions are under the following license: + +Copyright (c) 2013 Ted Unangst + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + + +Performance improvements (Javascript-specific): + +Copyright 2016, Joyent Inc +Author: Alex Wilson + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/reverse_engineering/node_modules/bcrypt-pbkdf/README.md b/reverse_engineering/node_modules/bcrypt-pbkdf/README.md new file mode 100644 index 0000000..7551f33 --- /dev/null +++ b/reverse_engineering/node_modules/bcrypt-pbkdf/README.md @@ -0,0 +1,45 @@ +Port of the OpenBSD `bcrypt_pbkdf` function to pure Javascript. `npm`-ified +version of [Devi Mandiri's port](https://github.com/devi/tmp/blob/master/js/bcrypt_pbkdf.js), +with some minor performance improvements. The code is copied verbatim (and +un-styled) from Devi's work. + +This product includes software developed by Niels Provos. + +## API + +### `bcrypt_pbkdf.pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds)` + +Derive a cryptographic key of arbitrary length from a given password and salt, +using the OpenBSD `bcrypt_pbkdf` function. This is a combination of Blowfish and +SHA-512. + +See [this article](http://www.tedunangst.com/flak/post/bcrypt-pbkdf) for +further information. + +Parameters: + + * `pass`, a Uint8Array of length `passlen` + * `passlen`, an integer Number + * `salt`, a Uint8Array of length `saltlen` + * `saltlen`, an integer Number + * `key`, a Uint8Array of length `keylen`, will be filled with output + * `keylen`, an integer Number + * `rounds`, an integer Number, number of rounds of the PBKDF to run + +### `bcrypt_pbkdf.hash(sha2pass, sha2salt, out)` + +Calculate a Blowfish hash, given SHA2-512 output of a password and salt. Used as +part of the inner round function in the PBKDF. + +Parameters: + + * `sha2pass`, a Uint8Array of length 64 + * `sha2salt`, a Uint8Array of length 64 + * `out`, a Uint8Array of length 32, will be filled with output + +## License + +This source form is a 1:1 port from the OpenBSD `blowfish.c` and `bcrypt_pbkdf.c`. +As a result, it retains the original copyright and license. The two files are +under slightly different (but compatible) licenses, and are here combined in +one file. For each of the full license texts see `LICENSE`. diff --git a/reverse_engineering/node_modules/bcrypt-pbkdf/index.js b/reverse_engineering/node_modules/bcrypt-pbkdf/index.js new file mode 100644 index 0000000..b1b5ad4 --- /dev/null +++ b/reverse_engineering/node_modules/bcrypt-pbkdf/index.js @@ -0,0 +1,556 @@ +'use strict'; + +var crypto_hash_sha512 = require('tweetnacl').lowlevel.crypto_hash; + +/* + * This file is a 1:1 port from the OpenBSD blowfish.c and bcrypt_pbkdf.c. As a + * result, it retains the original copyright and license. The two files are + * under slightly different (but compatible) licenses, and are here combined in + * one file. + * + * Credit for the actual porting work goes to: + * Devi Mandiri + */ + +/* + * The Blowfish portions are under the following license: + * + * Blowfish block cipher for OpenBSD + * Copyright 1997 Niels Provos + * All rights reserved. + * + * Implementation advice by David Mazieres . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The bcrypt_pbkdf portions are under the following license: + * + * Copyright (c) 2013 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Performance improvements (Javascript-specific): + * + * Copyright 2016, Joyent Inc + * Author: Alex Wilson + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +// Ported from OpenBSD bcrypt_pbkdf.c v1.9 + +var BLF_J = 0; + +var Blowfish = function() { + this.S = [ + new Uint32Array([ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a]), + new Uint32Array([ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7]), + new Uint32Array([ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0]), + new Uint32Array([ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]) + ]; + this.P = new Uint32Array([ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b]); +}; + +function F(S, x8, i) { + return (((S[0][x8[i+3]] + + S[1][x8[i+2]]) ^ + S[2][x8[i+1]]) + + S[3][x8[i]]); +}; + +Blowfish.prototype.encipher = function(x, x8) { + if (x8 === undefined) { + x8 = new Uint8Array(x.buffer); + if (x.byteOffset !== 0) + x8 = x8.subarray(x.byteOffset); + } + x[0] ^= this.P[0]; + for (var i = 1; i < 16; i += 2) { + x[1] ^= F(this.S, x8, 0) ^ this.P[i]; + x[0] ^= F(this.S, x8, 4) ^ this.P[i+1]; + } + var t = x[0]; + x[0] = x[1] ^ this.P[17]; + x[1] = t; +}; + +Blowfish.prototype.decipher = function(x) { + var x8 = new Uint8Array(x.buffer); + if (x.byteOffset !== 0) + x8 = x8.subarray(x.byteOffset); + x[0] ^= this.P[17]; + for (var i = 16; i > 0; i -= 2) { + x[1] ^= F(this.S, x8, 0) ^ this.P[i]; + x[0] ^= F(this.S, x8, 4) ^ this.P[i-1]; + } + var t = x[0]; + x[0] = x[1] ^ this.P[0]; + x[1] = t; +}; + +function stream2word(data, databytes){ + var i, temp = 0; + for (i = 0; i < 4; i++, BLF_J++) { + if (BLF_J >= databytes) BLF_J = 0; + temp = (temp << 8) | data[BLF_J]; + } + return temp; +}; + +Blowfish.prototype.expand0state = function(key, keybytes) { + var d = new Uint32Array(2), i, k; + var d8 = new Uint8Array(d.buffer); + + for (i = 0, BLF_J = 0; i < 18; i++) { + this.P[i] ^= stream2word(key, keybytes); + } + BLF_J = 0; + + for (i = 0; i < 18; i += 2) { + this.encipher(d, d8); + this.P[i] = d[0]; + this.P[i+1] = d[1]; + } + + for (i = 0; i < 4; i++) { + for (k = 0; k < 256; k += 2) { + this.encipher(d, d8); + this.S[i][k] = d[0]; + this.S[i][k+1] = d[1]; + } + } +}; + +Blowfish.prototype.expandstate = function(data, databytes, key, keybytes) { + var d = new Uint32Array(2), i, k; + + for (i = 0, BLF_J = 0; i < 18; i++) { + this.P[i] ^= stream2word(key, keybytes); + } + + for (i = 0, BLF_J = 0; i < 18; i += 2) { + d[0] ^= stream2word(data, databytes); + d[1] ^= stream2word(data, databytes); + this.encipher(d); + this.P[i] = d[0]; + this.P[i+1] = d[1]; + } + + for (i = 0; i < 4; i++) { + for (k = 0; k < 256; k += 2) { + d[0] ^= stream2word(data, databytes); + d[1] ^= stream2word(data, databytes); + this.encipher(d); + this.S[i][k] = d[0]; + this.S[i][k+1] = d[1]; + } + } + BLF_J = 0; +}; + +Blowfish.prototype.enc = function(data, blocks) { + for (var i = 0; i < blocks; i++) { + this.encipher(data.subarray(i*2)); + } +}; + +Blowfish.prototype.dec = function(data, blocks) { + for (var i = 0; i < blocks; i++) { + this.decipher(data.subarray(i*2)); + } +}; + +var BCRYPT_BLOCKS = 8, + BCRYPT_HASHSIZE = 32; + +function bcrypt_hash(sha2pass, sha2salt, out) { + var state = new Blowfish(), + cdata = new Uint32Array(BCRYPT_BLOCKS), i, + ciphertext = new Uint8Array([79,120,121,99,104,114,111,109,97,116,105, + 99,66,108,111,119,102,105,115,104,83,119,97,116,68,121,110,97,109, + 105,116,101]); //"OxychromaticBlowfishSwatDynamite" + + state.expandstate(sha2salt, 64, sha2pass, 64); + for (i = 0; i < 64; i++) { + state.expand0state(sha2salt, 64); + state.expand0state(sha2pass, 64); + } + + for (i = 0; i < BCRYPT_BLOCKS; i++) + cdata[i] = stream2word(ciphertext, ciphertext.byteLength); + for (i = 0; i < 64; i++) + state.enc(cdata, cdata.byteLength / 8); + + for (i = 0; i < BCRYPT_BLOCKS; i++) { + out[4*i+3] = cdata[i] >>> 24; + out[4*i+2] = cdata[i] >>> 16; + out[4*i+1] = cdata[i] >>> 8; + out[4*i+0] = cdata[i]; + } +}; + +function bcrypt_pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds) { + var sha2pass = new Uint8Array(64), + sha2salt = new Uint8Array(64), + out = new Uint8Array(BCRYPT_HASHSIZE), + tmpout = new Uint8Array(BCRYPT_HASHSIZE), + countsalt = new Uint8Array(saltlen+4), + i, j, amt, stride, dest, count, + origkeylen = keylen; + + if (rounds < 1) + return -1; + if (passlen === 0 || saltlen === 0 || keylen === 0 || + keylen > (out.byteLength * out.byteLength) || saltlen > (1<<20)) + return -1; + + stride = Math.floor((keylen + out.byteLength - 1) / out.byteLength); + amt = Math.floor((keylen + stride - 1) / stride); + + for (i = 0; i < saltlen; i++) + countsalt[i] = salt[i]; + + crypto_hash_sha512(sha2pass, pass, passlen); + + for (count = 1; keylen > 0; count++) { + countsalt[saltlen+0] = count >>> 24; + countsalt[saltlen+1] = count >>> 16; + countsalt[saltlen+2] = count >>> 8; + countsalt[saltlen+3] = count; + + crypto_hash_sha512(sha2salt, countsalt, saltlen + 4); + bcrypt_hash(sha2pass, sha2salt, tmpout); + for (i = out.byteLength; i--;) + out[i] = tmpout[i]; + + for (i = 1; i < rounds; i++) { + crypto_hash_sha512(sha2salt, tmpout, tmpout.byteLength); + bcrypt_hash(sha2pass, sha2salt, tmpout); + for (j = 0; j < out.byteLength; j++) + out[j] ^= tmpout[j]; + } + + amt = Math.min(amt, keylen); + for (i = 0; i < amt; i++) { + dest = i * stride + (count - 1); + if (dest >= origkeylen) + break; + key[dest] = out[i]; + } + keylen -= i; + } + + return 0; +}; + +module.exports = { + BLOCKS: BCRYPT_BLOCKS, + HASHSIZE: BCRYPT_HASHSIZE, + hash: bcrypt_hash, + pbkdf: bcrypt_pbkdf +}; diff --git a/reverse_engineering/node_modules/bcrypt-pbkdf/package.json b/reverse_engineering/node_modules/bcrypt-pbkdf/package.json new file mode 100644 index 0000000..b5a2e4c --- /dev/null +++ b/reverse_engineering/node_modules/bcrypt-pbkdf/package.json @@ -0,0 +1,44 @@ +{ + "_from": "bcrypt-pbkdf@^1.0.2", + "_id": "bcrypt-pbkdf@1.0.2", + "_inBundle": false, + "_integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "_location": "/bcrypt-pbkdf", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "bcrypt-pbkdf@^1.0.2", + "name": "bcrypt-pbkdf", + "escapedName": "bcrypt-pbkdf", + "rawSpec": "^1.0.2", + "saveSpec": null, + "fetchSpec": "^1.0.2" + }, + "_requiredBy": [ + "/ssh2" + ], + "_resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "_shasum": "a4301d389b6a43f9b67ff3ca11a3f6637e360e9e", + "_spec": "bcrypt-pbkdf@^1.0.2", + "_where": "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/ssh2", + "bugs": { + "url": "https://github.com/joyent/node-bcrypt-pbkdf/issues" + }, + "bundleDependencies": false, + "dependencies": { + "tweetnacl": "^0.14.3" + }, + "deprecated": false, + "description": "Port of the OpenBSD bcrypt_pbkdf function to pure JS", + "devDependencies": {}, + "homepage": "https://github.com/joyent/node-bcrypt-pbkdf#readme", + "license": "BSD-3-Clause", + "main": "index.js", + "name": "bcrypt-pbkdf", + "repository": { + "type": "git", + "url": "git://github.com/joyent/node-bcrypt-pbkdf.git" + }, + "version": "1.0.2" +} diff --git a/reverse_engineering/node_modules/streamsearch/LICENSE b/reverse_engineering/node_modules/cpu-features/LICENSE similarity index 98% rename from reverse_engineering/node_modules/streamsearch/LICENSE rename to reverse_engineering/node_modules/cpu-features/LICENSE index 290762e..9ea90e0 100644 --- a/reverse_engineering/node_modules/streamsearch/LICENSE +++ b/reverse_engineering/node_modules/cpu-features/LICENSE @@ -1,19 +1,19 @@ -Copyright Brian White. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +Copyright Brian White. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/reverse_engineering/node_modules/cpu-features/README.md b/reverse_engineering/node_modules/cpu-features/README.md new file mode 100644 index 0000000..c3b1244 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/README.md @@ -0,0 +1,60 @@ + +Description +=========== + +A simple [node.js](https://nodejs.org) binding to [cpu_features](https://github.com/google/cpu_features) for obtaining information about installed CPU(s). + + +Requirements +============ + +* [node.js](http://nodejs.org/) -- v8.0.0 or newer +* An appropriate build environment -- see [node-gyp's documentation](https://github.com/nodejs/node-gyp/blob/master/README.md) +* CMake -- any modern version (v3.14+ required for Windows and must be available in %PATH%) + + +Install +======= + + npm install cpu-features + + +Example +======= + +```js + // Generally it's a good idea to just call this once and + // reuse the result since `cpu-features` does not cache + // the result itself. + const features = require('cpu-features')(); + + console.log(features); + // example output: + // { arch: 'x86', + // brand: 'Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz', + // family: 6, + // model: 58, + // stepping: 9, + // uarch: 'INTEL_IVB', + // flags: + // { fpu: true, + // tsc: true, + // cx8: true, + // clfsh: true, + // mmx: true, + // aes: true, + // erms: true, + // f16c: true, + // sse: true, + // sse2: true, + // sse3: true, + // ssse3: true, + // sse4_1: true, + // sse4_2: true, + // avx: true, + // pclmulqdq: true, + // cx16: true, + // popcnt: true, + // rdrnd: true, + // ss: true } } +``` diff --git a/reverse_engineering/node_modules/cpu-features/binding.gyp b/reverse_engineering/node_modules/cpu-features/binding.gyp new file mode 100644 index 0000000..58e26fd --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/binding.gyp @@ -0,0 +1,91 @@ +{ + 'targets': [ + { + 'target_name': 'cpufeatures', + 'dependencies': [ 'build_deps' ], + 'include_dirs': [ + 'deps/cpu_features/include', + 'src', + "> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 1,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,build_deps.target.mk)))),) + include build_deps.target.mk +endif +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,config_deps.target.mk)))),) + include config_deps.target.mk +endif +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,cpufeatures.target.mk)))),) + include cpufeatures.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = cd $(srcdir); /usr/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/build/config.gypi -I/usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/home/vitalii/.cache/node-gyp/14.17.6/include/node/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/vitalii/.cache/node-gyp/14.17.6" "-Dnode_gyp_dir=/usr/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/home/vitalii/.cache/node-gyp/14.17.6/<(target_arch)/node.lib" "-Dmodule_root_dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features" "-Dnode_engine=v8" binding.gyp +Makefile: $(srcdir)/../../../../../../.cache/node-gyp/14.17.6/include/node/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../../usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/cpufeatures.node.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/cpufeatures.node.d new file mode 100644 index 0000000..34c83d2 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/cpufeatures.node.d @@ -0,0 +1 @@ +cmd_Release/cpufeatures.node := rm -rf "Release/cpufeatures.node" && cp -af "Release/obj.target/cpufeatures.node" "Release/cpufeatures.node" diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/build_deps.stamp.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/build_deps.stamp.d new file mode 100644 index 0000000..3b4e8b5 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/build_deps.stamp.d @@ -0,0 +1 @@ +cmd_Release/obj.target/build_deps.stamp := touch Release/obj.target/build_deps.stamp diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/config_deps.stamp.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/config_deps.stamp.d new file mode 100644 index 0000000..b1b2243 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/config_deps.stamp.d @@ -0,0 +1 @@ +cmd_Release/obj.target/config_deps.stamp := touch Release/obj.target/config_deps.stamp diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures.node.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures.node.d new file mode 100644 index 0000000..8e9bc39 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures.node.d @@ -0,0 +1 @@ +cmd_Release/obj.target/cpufeatures.node := g++ -shared -pthread -rdynamic -m64 -Wl,-soname=cpufeatures.node -o Release/obj.target/cpufeatures.node -Wl,--start-group Release/obj.target/cpufeatures/src/binding.o -Wl,--end-group /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d new file mode 100644 index 0000000..a79a929 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d @@ -0,0 +1,72 @@ +cmd_Release/obj.target/cpufeatures/src/binding.o := g++ '-DNODE_GYP_MODULE_NAME=cpufeatures' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D__STDC_FORMAT_MACROS' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DBUILDING_NODE_EXTENSION' -I/home/vitalii/.cache/node-gyp/14.17.6/include/node -I/home/vitalii/.cache/node-gyp/14.17.6/src -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/config -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/openssl/include -I/home/vitalii/.cache/node-gyp/14.17.6/deps/uv/include -I/home/vitalii/.cache/node-gyp/14.17.6/deps/zlib -I/home/vitalii/.cache/node-gyp/14.17.6/deps/v8/include -I../deps/cpu_features/include -I../src -I../../nan -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O2 -O3 -fno-omit-frame-pointer -fno-rtti -fno-exceptions -std=gnu++1y -MMD -MF ./Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d.raw -c -o Release/obj.target/cpufeatures/src/binding.o ../src/binding.cc +Release/obj.target/cpufeatures/src/binding.o: ../src/binding.cc \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/cppgc/common.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-internal.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-platform.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_buffer.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h \ + ../../nan/nan.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/errno.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/unix.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/threadpool.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/linux.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_object_wrap.h \ + ../../nan/nan_callbacks.h ../../nan/nan_callbacks_12_inl.h \ + ../../nan/nan_maybe_43_inl.h ../../nan/nan_converters.h \ + ../../nan/nan_converters_43_inl.h ../../nan/nan_new.h \ + ../../nan/nan_implementation_12_inl.h ../../nan/nan_persistent_12_inl.h \ + ../../nan/nan_weak.h ../../nan/nan_object_wrap.h ../../nan/nan_private.h \ + ../../nan/nan_typedarray_contents.h ../../nan/nan_json.h \ + ../../nan/nan_scriptorigin.h \ + ../deps/cpu_features/include/cpu_features_macros.h \ + ../deps/cpu_features/include/cpuinfo_x86.h \ + ../deps/cpu_features/include/cpu_features_cache_info.h \ + ../deps/cpu_features/include/cpu_features_macros.h +../src/binding.cc: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/cppgc/common.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-internal.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-platform.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_buffer.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h: +../../nan/nan.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/errno.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/unix.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/threadpool.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/linux.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_object_wrap.h: +../../nan/nan_callbacks.h: +../../nan/nan_callbacks_12_inl.h: +../../nan/nan_maybe_43_inl.h: +../../nan/nan_converters.h: +../../nan/nan_converters_43_inl.h: +../../nan/nan_new.h: +../../nan/nan_implementation_12_inl.h: +../../nan/nan_persistent_12_inl.h: +../../nan/nan_weak.h: +../../nan/nan_object_wrap.h: +../../nan/nan_private.h: +../../nan/nan_typedarray_contents.h: +../../nan/nan_json.h: +../../nan/nan_scriptorigin.h: +../deps/cpu_features/include/cpu_features_macros.h: +../deps/cpu_features/include/cpuinfo_x86.h: +../deps/cpu_features/include/cpu_features_cache_info.h: +../deps/cpu_features/include/cpu_features_macros.h: diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile.d new file mode 100644 index 0000000..27c19f1 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile.d @@ -0,0 +1 @@ +cmd_/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile := LD_LIBRARY_PATH=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/build/Release/lib.host:/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/build/Release/lib.target:$$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build; cmake "-DCMAKE_BUILD_TYPE=Release" "-DBUILD_PIC=ON" -B/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build -H/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a.d b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a.d new file mode 100644 index 0000000..0a36f63 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/build/Release/.deps/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a.d @@ -0,0 +1 @@ +cmd_/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a := LD_LIBRARY_PATH=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/build/Release/lib.host:/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/build/Release/lib.target:$$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build; cmake --build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build --config Release diff --git a/reverse_engineering/node_modules/cpu-features/build/Release/cpufeatures.node b/reverse_engineering/node_modules/cpu-features/build/Release/cpufeatures.node new file mode 100755 index 0000000000000000000000000000000000000000..a72e99bd08c85a16915f84da676e04b4a4c93c40 GIT binary patch literal 40392 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 + PRIVATE $ + ) + target_compile_definitions(${TARGET_NAME} + PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024 + ) +endmacro() + +set(PROCESSOR_IS_MIPS FALSE) +set(PROCESSOR_IS_ARM FALSE) +set(PROCESSOR_IS_AARCH64 FALSE) +set(PROCESSOR_IS_X86 FALSE) +set(PROCESSOR_IS_POWER FALSE) + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(PROCESSOR_IS_MIPS TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") + set(PROCESSOR_IS_ARM TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + set(PROCESSOR_IS_AARCH64 TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)") + set(PROCESSOR_IS_X86 TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") + set(PROCESSOR_IS_POWER TRUE) +endif() + +macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h) + if(PROCESSOR_IS_MIPS) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_mips.c) + elseif(PROCESSOR_IS_ARM) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_arm.c) + elseif(PROCESSOR_IS_AARCH64) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_aarch64.c) + elseif(PROCESSOR_IS_X86) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_x86.c) + elseif(PROCESSOR_IS_POWER) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_ppc.c) + else() + message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}") + endif() +endmacro() + +# +# library : utils +# + +add_library(utils OBJECT + ${PROJECT_SOURCE_DIR}/include/internal/bit_utils.h + ${PROJECT_SOURCE_DIR}/include/internal/filesystem.h + ${PROJECT_SOURCE_DIR}/include/internal/stack_line_reader.h + ${PROJECT_SOURCE_DIR}/include/internal/string_view.h + ${PROJECT_SOURCE_DIR}/src/filesystem.c + ${PROJECT_SOURCE_DIR}/src/stack_line_reader.c + ${PROJECT_SOURCE_DIR}/src/string_view.c +) +set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) +setup_include_and_definitions(utils) + +# +# library : unix_based_hardware_detection +# + +if(UNIX) + add_library(unix_based_hardware_detection OBJECT + ${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h + ${PROJECT_SOURCE_DIR}/include/internal/unix_features_aggregator.h + ${PROJECT_SOURCE_DIR}/src/hwcaps.c + ${PROJECT_SOURCE_DIR}/src/unix_features_aggregator.c + ) + setup_include_and_definitions(unix_based_hardware_detection) + check_include_file(dlfcn.h HAVE_DLFCN_H) + if(HAVE_DLFCN_H) + target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H) + endif() + check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL) + if(HAVE_STRONG_GETAUXVAL) + target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL) + endif() + set_property(TARGET unix_based_hardware_detection PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) +endif() + +# +# library : cpu_features +# +set (CPU_FEATURES_HDRS) +set (CPU_FEATURES_SRCS) +add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS) +list(APPEND CPU_FEATURES_SRCS $) +if(NOT PROCESSOR_IS_X86 AND UNIX) + list(APPEND CPU_FEATURES_SRCS $) +endif() +add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS}) +set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}") +setup_include_and_definitions(cpu_features) +target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS}) +set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) +target_include_directories(cpu_features + PUBLIC $ +) +add_library(CpuFeature::cpu_features ALIAS cpu_features) + +# +# program : list_cpu_features +# + +add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c) +target_link_libraries(list_cpu_features PRIVATE cpu_features) +add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features) + +# +# ndk_compat +# + +if(ANDROID) +add_subdirectory(ndk_compat) +endif() + +# +# tests +# + +include(CTest) +if(BUILD_TESTING) + # Automatically incorporate googletest into the CMake Project if target not + # found. + enable_language(CXX) + + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11 + + if(NOT TARGET gtest OR NOT TARGET gmock_main) + # Download and unpack googletest at configure time. + configure_file( + cmake/googletest.CMakeLists.txt.in + googletest-download/CMakeLists.txt + ) + + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download) + + if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") + endif() + + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download) + + if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") + endif() + + # Prevent overriding the parent project's compiler/linker settings on + # Windows. + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + + # Add googletest directly to our build. This defines the gtest and + # gtest_main targets. + add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src + ${CMAKE_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) + endif() + + add_subdirectory(test) +endif() + +# +# Install cpu_features and list_cpu_features +# + +include(GNUInstallDirs) +install(TARGETS cpu_features list_cpu_features + EXPORT CpuFeaturesTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) +install(EXPORT CpuFeaturesTargets + NAMESPACE CpuFeatures:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures + COMPONENT Devel +) +include(CMakePackageConfigHelpers) +configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in + "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) +write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" + COMPATIBILITY SameMajorVersion +) +install( + FILES + "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" + "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" + COMPONENT Devel +) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/CONTRIBUTING.md b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/CONTRIBUTING.md new file mode 100644 index 0000000..c980350 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/LICENSE b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/LICENSE new file mode 100644 index 0000000..a7043c6 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/LICENSE @@ -0,0 +1,230 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- +For files in the `ndk_compat` folder: +-------------------------------------------------------------------------------- + +Copyright (C) 2010 The Android Open Source Project +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/README.md b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/README.md new file mode 100644 index 0000000..8a34168 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/README.md @@ -0,0 +1,199 @@ +# cpu_features [![Build Status](https://travis-ci.org/google/cpu_features.svg?branch=master)](https://travis-ci.org/google/cpu_features) [![Build status](https://ci.appveyor.com/api/projects/status/46d1owsj7n8dsylq/branch/master?svg=true)](https://ci.appveyor.com/project/gchatelet/cpu-features/branch/master) + +A cross-platform C library to retrieve CPU features (such as available +instructions) at runtime. + +## Table of Contents + +- [Design Rationale](#rationale) +- [Code samples](#codesample) +- [Running sample code](#usagesample) +- [What's supported](#support) +- [Android NDK's drop in replacement](#ndk) +- [License](#license) +- [Build with cmake](#cmake) + + +## Design Rationale + +- **Simple to use.** See the snippets below for examples. +- **Extensible.** Easy to add missing features or architectures. +- **Compatible with old compilers** and available on many architectures so it + can be used widely. To ensure that cpu_features works on as many platforms + as possible, we implemented it in a highly portable version of C: C99. +- **Sandbox-compatible.** The library uses a variety of strategies to cope + with sandboxed environments or when `cpuid` is unavailable. This is useful + when running integration tests in hermetic environments. +- **Thread safe, no memory allocation, and raises no exceptions.** + cpu_features is suitable for implementing fundamental libc functions like + `malloc`, `memcpy`, and `memcmp`. +- **Unit tested.** + + +## Code samples + +**Note:** For C++ code, the library functions are defined in the `CpuFeatures` namespace. + +### Checking features at runtime + +Here's a simple example that executes a codepath if the CPU supports both the +AES and the SSE4.2 instruction sets: + +```c +#include "cpuinfo_x86.h" + +// For C++, add `using namespace CpuFeatures;` +static const X86Features features = GetX86Info().features; + +void Compute(void) { + if (features.aes && features.sse4_2) { + // Run optimized code. + } else { + // Run standard code. + } +} +``` + +### Caching for faster evaluation of complex checks + +If you wish, you can read all the features at once into a global variable, and +then query for the specific features you care about. Below, we store all the ARM +features and then check whether AES and NEON are supported. + +```c +#include +#include "cpuinfo_arm.h" + +// For C++, add `using namespace CpuFeatures;` +static const ArmFeatures features = GetArmInfo().features; +static const bool has_aes_and_neon = features.aes && features.neon; + +// use has_aes_and_neon. +``` + +This is a good approach to take if you're checking for combinations of features +when using a compiler that is slow to extract individual bits from bit-packed +structures. + +### Checking compile time flags + +The following code determines whether the compiler was told to use the AVX +instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly. + +```c +#include +#include "cpuinfo_x86.h" + +// For C++, add `using namespace CpuFeatures;` +static const X86Features features = GetX86Info().features; +static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx; + +// use has_avx. +``` + +`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to +use AVX and 0 otherwise, combining compile time and runtime knowledge. + +### Rejecting poor hardware implementations based on microarchitecture + +On x86, the first incarnation of a feature in a microarchitecture might not be +the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve +the underlying microarchitecture so you can decide whether to use it. + +Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction +set—but only if it's not Sandy Bridge. + +```c +#include +#include "cpuinfo_x86.h" + +// For C++, add `using namespace CpuFeatures;` +static const X86Info info = GetX86Info(); +static const X86Microarchitecture uarch = GetX86Microarchitecture(&info); +static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB; + +// use has_fast_avx. +``` + +This feature is currently available only for x86 microarchitectures. + + +### Running sample code + +Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library. + +```shell + % ./build/list_cpu_features +arch : x86 +brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz +family : 6 (0x06) +model : 45 (0x2D) +stepping : 7 (0x07) +uarch : INTEL_SNB +flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 +``` + +```shell +% ./build/list_cpu_features --json +{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]} +``` + + +## What's supported + +| | x86³ | ARM | AArch64 | MIPS⁴ | POWER | +|---------|:----:|:-------:|:-------:|:------:|:-------:| +| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | +| iOS | N/A | not yet | not yet | N/A | N/A | +| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | +| MacOs | yes² | N/A | not yet | N/A | no | +| Windows | yes² | not yet | not yet | N/A | N/A | + +1. **Features revealed from Linux.** We gather data from several sources + depending on availability: + + from glibc's + [getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html) + + by parsing `/proc/self/auxv` + + by parsing `/proc/cpuinfo` +2. **Features revealed from CPU.** features are retrieved by using the `cpuid` + instruction. +3. **Microarchitecture detection.** On x86 some features are not always + implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the + microarchitecture allows the client to reject particular microarchitectures. +4. All flavors of Mips are supported, little and big endian as well as 32/64 + bits. + + +## Android NDK's drop in replacement + +[cpu_features](https://github.com/google/cpu_features) is now officially +supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h) +, see [ndk_compat](ndk_compat) folder for details. + + +## License + +The cpu_features library is licensed under the terms of the Apache license. +See [LICENSE](LICENSE) for more information. + + +## Build with CMake + +Please check the [CMake build instructions](cmake/README.md). + + +### Quickstart with `Ninja` + + - build `list_cpu_features` +``` + cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release + ninja -C/tmp/cpu_features + /tmp/cpu_features/list_cpu_features --json +``` + + - run tests +``` + cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON + ninja -C/tmp/cpu_features + ninja -C/tmp/cpu_features test +``` diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/WORKSPACE b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/WORKSPACE new file mode 100644 index 0000000..8ea8a8b --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/WORKSPACE @@ -0,0 +1,7 @@ +# ===== googletest ===== + +git_repository( + name = "com_google_googletest", + remote = "https://github.com/google/googletest.git", + commit = "c3f65335b79f47b05629e79a54685d899bc53b93", +) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/appveyor.yml b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/appveyor.yml new file mode 100644 index 0000000..f18635a --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/appveyor.yml @@ -0,0 +1,24 @@ +version: '{build}' +shallow_clone: true + +platform: x64 + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + CMAKE_GENERATOR: "Visual Studio 15 2017 Win64" + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + CMAKE_GENERATOR: "Visual Studio 14 2015 Win64" + +matrix: + fast_finish: true + +before_build: + - cmake --version + - cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -H. -Bcmake_build -G "%CMAKE_GENERATOR%" + +build_script: + - cmake --build cmake_build --config Debug --target ALL_BUILD + +test_script: + - cmake --build cmake_build --config Debug --target RUN_TESTS diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeCache.txt b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeCache.txt new file mode 100644 index 0000000..9023803 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeCache.txt @@ -0,0 +1,385 @@ +# This is the CMakeCache file. +# For build in directory: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Build with Position Independant Code. +BUILD_PIC:BOOL=ON + +//Build library as shared. +BUILD_SHARED_LIBS:BOOL=OFF + +//Build the testing tree. +BUILD_TESTING:BOOL=OFF + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or +// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. +CMAKE_BUILD_TYPE:STRING=Release + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//C compiler +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//A wrapper around 'ar' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-7 + +//A wrapper around 'ranlib' adding the appropriate '--plugin' option +// for the GCC compiler +CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-7 + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release builds for minimum +// size. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during release builds with debug info. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF + +//User executables (bin) +CMAKE_INSTALL_BINDIR:PATH=bin + +//Read-only architecture-independent data (DATAROOTDIR) +CMAKE_INSTALL_DATADIR:PATH= + +//Read-only architecture-independent data root (share) +CMAKE_INSTALL_DATAROOTDIR:PATH=share + +//Documentation root (DATAROOTDIR/doc/PROJECT_NAME) +CMAKE_INSTALL_DOCDIR:PATH= + +//C header files (include) +CMAKE_INSTALL_INCLUDEDIR:PATH=include + +//Info documentation (DATAROOTDIR/info) +CMAKE_INSTALL_INFODIR:PATH= + +//Object code libraries (lib) +CMAKE_INSTALL_LIBDIR:PATH=lib + +//Program executables (libexec) +CMAKE_INSTALL_LIBEXECDIR:PATH=libexec + +//Locale-dependent data (DATAROOTDIR/locale) +CMAKE_INSTALL_LOCALEDIR:PATH= + +//Modifiable single-machine data (var) +CMAKE_INSTALL_LOCALSTATEDIR:PATH=var + +//Man documentation (DATAROOTDIR/man) +CMAKE_INSTALL_MANDIR:PATH= + +//C header files for non-gcc (/usr/include) +CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Run-time variable data (LOCALSTATEDIR/run) +CMAKE_INSTALL_RUNSTATEDIR:PATH= + +//System admin executables (sbin) +CMAKE_INSTALL_SBINDIR:PATH=sbin + +//Modifiable architecture-independent data (com) +CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com + +//Read-only single-machine data (etc) +CMAKE_INSTALL_SYSCONFDIR:PATH=etc + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=CpuFeatures + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +CpuFeatures_BINARY_DIR:STATIC=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +//Value Computed by CMake +CpuFeatures_SOURCE_DIR:STATIC=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +//Dependencies for the target +cpu_features_LIB_DEPENDS:STATIC=general;dl; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=10 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features +//ADVANCED property for variable: CMAKE_INSTALL_BINDIR +CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_DATADIR +CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR +CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR +CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR +CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_INFODIR +CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR +CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR +CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR +CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR +CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_MANDIR +CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR +CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR +CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR +CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR +CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1 +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR +CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.10 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 +//Have include dlfcn.h +HAVE_DLFCN_H:INTERNAL=1 +//Have symbol getauxval +HAVE_STRONG_GETAUXVAL:INTERNAL=1 +//CMAKE_INSTALL_PREFIX during last run +_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=/usr/local + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeCCompiler.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeCCompiler.cmake new file mode 100644 index 0000000..9e0e71d --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeCCompiler.cmake @@ -0,0 +1,73 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "7.5.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_SIMULATE_VERSION "") + + + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-7") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..b1860a3dd40b90b19fab68ce7a4bf1a8fee6135d GIT binary patch literal 8248 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 literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeSystem.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeSystem.cmake new file mode 100644 index 0000000..6ab2d72 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-5.4.0-89-generic") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "5.4.0-89-generic") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-5.4.0-89-generic") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "5.4.0-89-generic") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/CMakeCCompilerId.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000..722faa8 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,598 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__FUJITSU) || defined(__FCC_VERSION) || defined(__fcc_version) +# define COMPILER_ID "Fujitsu" + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__ARMCC_VERSION) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXE) || defined(__CRAYXC) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + + +#if !defined(__STDC__) +# if defined(_MSC_VER) && !defined(__clang__) +# define C_DIALECT "90" +# else +# define C_DIALECT +# endif +#elif __STDC_VERSION__ >= 201000L +# define C_DIALECT "11" +#elif __STDC_VERSION__ >= 199901L +# define C_DIALECT "99" +#else +# define C_DIALECT "90" +#endif +const char* info_language_dialect_default = + "INFO" ":" "dialect_default[" C_DIALECT "]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXE) || defined(__CRAYXC) + require += info_cray[argc]; +#endif + require += info_language_dialect_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/a.out b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/a.out new file mode 100755 index 0000000000000000000000000000000000000000..11b7df452ad29dfd7bf1d9b188856c9e33182403 GIT binary patch literal 8408 zcmeHMZ;Vt|6~D8?!t!Tl2MTn7M#f4FRCd^=A*#)EvO{L4@?ab`%r1OW& zywQb-l59&d&~1tO0b?|pm>6Tf=!aVUV3zPl<0puTMQsyeKv$)@wH3D&7|*%y{AS;K zJ7|q2e&HrF=ic8v=iKwoJNM4HXTI3o*HaS+D72vZq~g)OS_f&DiEFE*L!@1`sfG0Y zh+3oO(|Df7ocVT#(5%yDL^Wug;6b7+*H+^Ie)@>;fx<$jVw!Mx$rX**^9-;uB|?3eZK=a;b94=RtVHla$^1ZnXF8Wn4p>8JmK@3CvLb0Z ztW_DcJ&t$b;{bV&{fGBlT%DqwQKL4B?TCBC>plsd8QB-W!-Cg^BU%zT#$g}+%>~W^ zjXwOZf=7J#0#Uf$hd(6vwFYNhHiMrB?YaxcGxOY(3+MPkn|9&YGdwrr!rkYJF@CGg zI8%FRQA8OpPTDo)E5`W6x(lkj^-BbmANvY@H>_=^-VdlZd=~4pyxm*6de|ua))>Dr zy>FmzqV@wa+nA^y*JRi4h_Sq4m}K5-Slh)jyS__<1I9${w}=|sXN=NKdlfCcgNL+q z{b2d}aI|6V3wnvc3%u&=nB-H;II(p|tJ!dmETrB6wr7cPX4kK2G*w?Nm!}N+x?KAXjRS1XNjB`=3#5{s zhuH`JFiafWE1kGyl#17X+I@$4j58~~PC{q8ZyD!|z?FvARKrgu1KoEBpSTZxq8iQ$ z;#bIHWm4Mk+Ps>InuFEZ@35JU|6 zW?ncu`+nZNK+nywq@#zu;BA4*sp!Qq>fO_`cSk&zIhsl*^M~lP9K?)6J@e*gllej_ zmp#<%v~5x8Y(=MeP-%&yY0DnYiflue=xMk!#qa%Za{9bRAJXOQZM7<%>iw61_om3q`_43VlBBxdo2zSAnr`V9k;R zb!P($!i@88{Lk)`%b#EdY1R2@9hztUG2+)}TPWNUYW!5g;?LEcR8Otm`S=s-^zqE{ zUGzCZe04<8SoS&k43WJrGZ+hnPt|nR&#x(wMUKqp3BE@2NuKWrg<&dH z=5>VDzf^04norF)LT%#<`a|vcP+Kh291E@Q2t|mG_&Y*%`rKtdDDs2*d}8Q9d*Fcw z9(dq^|Az;V=OM2{P6fI|jB1o*NUlpNA^97wfyf`%2tUqP&a=58kL2@~8|MFZubkuY zIXM)Oa~YDXNxG?Cm-$7^Oznh2)MBBHLRSa{LC!ZRd7YT8W@G|(MC5_xx~QPeS7hRmALZaixl>c7hkNJ5%8{wpjx8ZtK#*Q zI*f~*?#-dfe)QrE>SUEb3sN?MI)ayfsTxI~yC#BkQ^x*w!L;r}m3{5SDchI7W&V1M^$e6Aldq6gUtbNzXa@M`wo@43FG^(<9s99UT3K6-wn=a@82>$qapU^;+_uD`Zu#EhFMB)(JbuHl$R^@APjn9pTorH(g$~p0{ zituGs;=e=VKIJsDM2|n-vV=$Gva1t>FRfXra2|r?G~;S^f6bGLuWEdy^4B}QLpb|k zT7J-y!heZqnBuC<7w03wkGd=FLO&G!{yNJg!dZ`hzg!hPpOJO-9f#KZrRee3S>9uu zp4YF3ucZ;O*-cgx{-_&}{`d8|bI-k2;%C22N<3^9{!WdrR1sg@N5%7Y!7dIDN8@U? zEN0pnGtPyv0u{v)IddeP8?w@7!p`Ljrd1qMd_ztr?PMalt#x}_btW#!rA#ZIw~m>~ zteromhVxb?X(o!9%rO#ijZEUSJ*=Jm*7M2EPPvHpCdfR~?Aagd?>4*lbeUA0^U5TY z+4bz6SbuM)cSe^138I_4*=>jhqier1clYh>i1nF!dwQPk9xw-D9ev%bRTmHAg`&3p zUzZD$3Cp%1GFxwKZ}$`&P3Cfnip1-!Fq(-%&K$L}39df&?j^27Dr*)C$%IN}hjS*% z23UmcVpln{C{xhvP@y18=!&NnPFvZLqBTMe_tqAOoywkYBiBQ#7CF6TRqsP-{ZjmJ zY~fl4RU-<=GPX5D)XqC}6unfI%B@FLG@G-N(O5@slWmR2Xe3*V4i!^W+fF4^lt-gh zVN^vE$Fii)p?2Px!J?W?1}4qrlWB_uR8;#XdNge-{)&#|sADI`=$qq_ICJ{7MU$fv zfujkM$H)ig-H^|LMg#}Jd5Uohb=>mE`#{%$QK(3}~C+C%bu z*MR)%(g8)mmycO~cE}@BIY<~^0U(cj6BPFuV$sd-zr%#`-2(E+OF?l@gZEaE0Ua2FzT%TdehmtHA&)UA=V$Kq@w*JV42}^6SQq-f;giSx8PuP~`JeyW zB9CQG%I_!Wt5`^A#5d-7wjc7y-$0-A@%z{Ru}>cN1kgHG?rQKGpo`SuoLj=Ca-YEe zjDCKML9dW(gG(Ougc&JFfR9*o!x;2ULOJ%Ze&v3`Mp2s-`w^dz!+ZQP@h}VIagUi~ zqo}p(@7XWNgWjYmw|pi4lm(h+MRgByfd51t#;`u}vu2U^^ZQo<$zxZd+PeP9pHKaOwM?v_7GsXn)UpK`40%yQ0HUH&aufbSpf=9m8` D$)0nc literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeDirectoryInformation.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..45e30c8 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeOutput.log b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeOutput.log new file mode 100644 index 0000000..85f08a1 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeOutput.log @@ -0,0 +1,260 @@ +The system is: Linux - 5.4.0-89-generic - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /usr/bin/cc +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + +The C compiler identification is GNU, found in "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/3.10.2/CompilerIdC/a.out" + +Determining if the C compiler works passed with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_bde3c/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_bde3c.dir/build.make CMakeFiles/cmTC_bde3c.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_bde3c.dir/testCCompiler.c.o +/usr/bin/cc -o CMakeFiles/cmTC_bde3c.dir/testCCompiler.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp/testCCompiler.c +Linking C executable cmTC_bde3c +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_bde3c.dir/link.txt --verbose=1 +/usr/bin/cc -rdynamic CMakeFiles/cmTC_bde3c.dir/testCCompiler.c.o -o cmTC_bde3c +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_747ea/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_747ea.dir/build.make CMakeFiles/cmTC_747ea.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o +/usr/bin/cc -o CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.10/Modules/CMakeCCompilerABI.c +Linking C executable cmTC_747ea +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_747ea.dir/link.txt --verbose=1 +/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o -o cmTC_747ea +Using built-in specs. +COLLECT_GCC=/usr/bin/cc +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper +OFFLOAD_TARGET_NAMES=nvptx-none +OFFLOAD_TARGET_DEFAULT=1 +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu +Thread model: posix +gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_747ea' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/cc8HSR1W.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_747ea /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o +COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_747ea' '-mtune=generic' '-march=x86-64' +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:"/usr/bin/make" "cmTC_747ea/fast"] + ignore line: [make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp'] + ignore line: [/usr/bin/make -f CMakeFiles/cmTC_747ea.dir/build.make CMakeFiles/cmTC_747ea.dir/build] + ignore line: [make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp'] + ignore line: [Building C object CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -o CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-3.10/Modules/CMakeCCompilerABI.c] + ignore line: [Linking C executable cmTC_747ea] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_747ea.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v -rdynamic CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o -o cmTC_747ea ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper] + ignore line: [OFFLOAD_TARGET_NAMES=nvptx-none] + ignore line: [OFFLOAD_TARGET_DEFAULT=1] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/7/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/7/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-rdynamic' '-o' 'cmTC_747ea' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/7/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper -plugin-opt=-fresolution=/tmp/cc8HSR1W.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o cmTC_747ea /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/7 -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/7/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/cc8HSR1W.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTC_747ea] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-linux-gnu/7] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/7] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/7/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/7/../../..] + arg [CMakeFiles/cmTC_747ea.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--push-state] ==> ignore + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--pop-state] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o] ==> ignore + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/7] ==> [/usr/lib/gcc/x86_64-linux-gnu/7] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/7/../../..] ==> [/usr/lib] + implicit libs: [gcc;gcc_s;c;gcc;gcc_s] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + + + +Detecting C [-std=c11] compiler features compiled with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_2b6c4/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_2b6c4.dir/build.make CMakeFiles/cmTC_2b6c4.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_2b6c4.dir/feature_tests.c.o +/usr/bin/cc -std=c11 -o CMakeFiles/cmTC_2b6c4.dir/feature_tests.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_2b6c4 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_2b6c4.dir/link.txt --verbose=1 +/usr/bin/cc -rdynamic CMakeFiles/cmTC_2b6c4.dir/feature_tests.c.o -o cmTC_2b6c4 +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:1c_restrict + Feature record: C_FEATURE:1c_static_assert + Feature record: C_FEATURE:1c_variadic_macros + + +Detecting C [-std=c99] compiler features compiled with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_343ba/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_343ba.dir/build.make CMakeFiles/cmTC_343ba.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_343ba.dir/feature_tests.c.o +/usr/bin/cc -std=c99 -o CMakeFiles/cmTC_343ba.dir/feature_tests.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_343ba +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_343ba.dir/link.txt --verbose=1 +/usr/bin/cc -rdynamic CMakeFiles/cmTC_343ba.dir/feature_tests.c.o -o cmTC_343ba +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:1c_restrict + Feature record: C_FEATURE:0c_static_assert + Feature record: C_FEATURE:1c_variadic_macros + + +Detecting C [-std=c90] compiler features compiled with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_02132/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_02132.dir/build.make CMakeFiles/cmTC_02132.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_02132.dir/feature_tests.c.o +/usr/bin/cc -std=c90 -o CMakeFiles/cmTC_02132.dir/feature_tests.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c +Linking C executable cmTC_02132 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_02132.dir/link.txt --verbose=1 +/usr/bin/cc -rdynamic CMakeFiles/cmTC_02132.dir/feature_tests.c.o -o cmTC_02132 +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + + + Feature record: C_FEATURE:1c_function_prototypes + Feature record: C_FEATURE:0c_restrict + Feature record: C_FEATURE:0c_static_assert + Feature record: C_FEATURE:0c_variadic_macros +Determining if the include file dlfcn.h exists passed with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_fbaa4/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_fbaa4.dir/build.make CMakeFiles/cmTC_fbaa4.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_fbaa4.dir/CheckIncludeFile.c.o +/usr/bin/cc -o CMakeFiles/cmTC_fbaa4.dir/CheckIncludeFile.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp/CheckIncludeFile.c +Linking C executable cmTC_fbaa4 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_fbaa4.dir/link.txt --verbose=1 +/usr/bin/cc -rdynamic CMakeFiles/cmTC_fbaa4.dir/CheckIncludeFile.c.o -o cmTC_fbaa4 +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + + +Determining if the getauxval exist passed with the following output: +Change Dir: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp + +Run Build Command:"/usr/bin/make" "cmTC_c1d21/fast" +make[1]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +/usr/bin/make -f CMakeFiles/cmTC_c1d21.dir/build.make CMakeFiles/cmTC_c1d21.dir/build +make[2]: Entering directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +Building C object CMakeFiles/cmTC_c1d21.dir/CheckSymbolExists.c.o +/usr/bin/cc -o CMakeFiles/cmTC_c1d21.dir/CheckSymbolExists.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp/CheckSymbolExists.c +Linking C executable cmTC_c1d21 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_c1d21.dir/link.txt --verbose=1 +/usr/bin/cc -rdynamic CMakeFiles/cmTC_c1d21.dir/CheckSymbolExists.c.o -o cmTC_c1d21 +make[2]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' +make[1]: Leaving directory '/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp' + +File /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/CMakeTmp/CheckSymbolExists.c: +/* */ +#include + +int main(int argc, char** argv) +{ + (void)argv; +#ifndef getauxval + return ((int*)(&getauxval))[argc]; +#else + (void)argc; + return 0; +#endif +} + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets-release.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets-release.cmake new file mode 100644 index 0000000..b49552b --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets-release.cmake @@ -0,0 +1,28 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "CpuFeatures::cpu_features" for configuration "Release" +set_property(TARGET CpuFeatures::cpu_features APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(CpuFeatures::cpu_features PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libcpu_features.a" + ) + +list(APPEND _IMPORT_CHECK_TARGETS CpuFeatures::cpu_features ) +list(APPEND _IMPORT_CHECK_FILES_FOR_CpuFeatures::cpu_features "${_IMPORT_PREFIX}/lib/libcpu_features.a" ) + +# Import target "CpuFeatures::list_cpu_features" for configuration "Release" +set_property(TARGET CpuFeatures::list_cpu_features APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(CpuFeatures::list_cpu_features PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/list_cpu_features" + ) + +list(APPEND _IMPORT_CHECK_TARGETS CpuFeatures::list_cpu_features ) +list(APPEND _IMPORT_CHECK_FILES_FOR_CpuFeatures::list_cpu_features "${_IMPORT_PREFIX}/bin/list_cpu_features" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake new file mode 100644 index 0000000..dce3177 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake @@ -0,0 +1,103 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget CpuFeatures::cpu_features CpuFeatures::list_cpu_features) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + unset(_targetsDefined) + unset(_targetsNotDefined) + unset(_expectedTargets) + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target CpuFeatures::cpu_features +add_library(CpuFeatures::cpu_features STATIC IMPORTED) + +set_target_properties(CpuFeatures::cpu_features PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "STACK_LINE_READER_BUFFER_SIZE=1024" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include/cpu_features" + INTERFACE_LINK_LIBRARIES "dl" +) + +# Create imported target CpuFeatures::list_cpu_features +add_executable(CpuFeatures::list_cpu_features IMPORTED) + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") +endif() + +# Load information for each installed configuration. +get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(GLOB CONFIG_FILES "${_DIR}/CpuFeaturesTargets-*.cmake") +foreach(f ${CONFIG_FILES}) + include(${f}) +endforeach() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000..502d6ab --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,112 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# The generator used is: +set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +set(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/3.10.2/CMakeCCompiler.cmake" + "CMakeFiles/3.10.2/CMakeSystem.cmake" + "CMakeFiles/feature_tests.c" + "../cmake/CpuFeaturesConfig.cmake.in" + "/usr/share/cmake-3.10/Modules/BasicConfigVersion-SameMajorVersion.cmake.in" + "/usr/share/cmake-3.10/Modules/CMakeCCompiler.cmake.in" + "/usr/share/cmake-3.10/Modules/CMakeCCompilerABI.c" + "/usr/share/cmake-3.10/Modules/CMakeCInformation.cmake" + "/usr/share/cmake-3.10/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake-3.10/Modules/CMakeCompilerIdDetection.cmake" + "/usr/share/cmake-3.10/Modules/CMakeConfigurableFile.in" + "/usr/share/cmake-3.10/Modules/CMakeDetermineCCompiler.cmake" + "/usr/share/cmake-3.10/Modules/CMakeDetermineCompileFeatures.cmake" + "/usr/share/cmake-3.10/Modules/CMakeDetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/CMakeDetermineCompilerABI.cmake" + "/usr/share/cmake-3.10/Modules/CMakeDetermineCompilerId.cmake" + "/usr/share/cmake-3.10/Modules/CMakeDetermineSystem.cmake" + "/usr/share/cmake-3.10/Modules/CMakeFindBinUtils.cmake" + "/usr/share/cmake-3.10/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake-3.10/Modules/CMakeLanguageInformation.cmake" + "/usr/share/cmake-3.10/Modules/CMakePackageConfigHelpers.cmake" + "/usr/share/cmake-3.10/Modules/CMakeParseImplicitLinkInfo.cmake" + "/usr/share/cmake-3.10/Modules/CMakeSystem.cmake.in" + "/usr/share/cmake-3.10/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake-3.10/Modules/CMakeSystemSpecificInitialize.cmake" + "/usr/share/cmake-3.10/Modules/CMakeTestCCompiler.cmake" + "/usr/share/cmake-3.10/Modules/CMakeTestCompilerCommon.cmake" + "/usr/share/cmake-3.10/Modules/CMakeUnixFindMake.cmake" + "/usr/share/cmake-3.10/Modules/CTest.cmake" + "/usr/share/cmake-3.10/Modules/CTestUseLaunchers.cmake" + "/usr/share/cmake-3.10/Modules/CheckIncludeFile.c.in" + "/usr/share/cmake-3.10/Modules/CheckIncludeFile.cmake" + "/usr/share/cmake-3.10/Modules/CheckSymbolExists.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/ADSP-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Borland-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Clang-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Cray-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/GHS-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/GNU-C-FeatureTests.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/GNU-C.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/GNU-FindBinUtils.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/GNU.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/HP-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/IAR-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Intel-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/MIPSpro-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/MSVC-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/PGI-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/PathScale-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/SCO-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/TI-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/Watcom-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/XL-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + "/usr/share/cmake-3.10/Modules/GNUInstallDirs.cmake" + "/usr/share/cmake-3.10/Modules/Internal/FeatureTesting.cmake" + "/usr/share/cmake-3.10/Modules/Platform/Linux-GNU-C.cmake" + "/usr/share/cmake-3.10/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake-3.10/Modules/Platform/Linux.cmake" + "/usr/share/cmake-3.10/Modules/Platform/UnixPaths.cmake" + "/usr/share/cmake-3.10/Modules/WriteBasicConfigVersionFile.cmake" + ) + +# The corresponding makefile is: +set(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +set(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/3.10.2/CMakeSystem.cmake" + "CMakeFiles/3.10.2/CMakeCCompiler.cmake" + "CMakeFiles/3.10.2/CMakeCCompiler.cmake" + "CpuFeaturesConfig.cmake" + "CpuFeaturesConfigVersion.cmake" + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +set(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/unix_based_hardware_detection.dir/DependInfo.cmake" + "CMakeFiles/utils.dir/DependInfo.cmake" + "CMakeFiles/list_cpu_features.dir/DependInfo.cmake" + "CMakeFiles/cpu_features.dir/DependInfo.cmake" + ) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile2 b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile2 new file mode 100644 index 0000000..552add0 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Makefile2 @@ -0,0 +1,219 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# The main recursive all target +all: + +.PHONY : all + +# The main recursive preinstall target +preinstall: + +.PHONY : preinstall + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +#============================================================================= +# Target rules for target CMakeFiles/unix_based_hardware_detection.dir + +# All Build rule for target. +CMakeFiles/unix_based_hardware_detection.dir/all: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/depend + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=5,6 "Built target unix_based_hardware_detection" +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/all + +# Include target in all. +all: CMakeFiles/unix_based_hardware_detection.dir/all + +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/unix_based_hardware_detection.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 2 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/unix_based_hardware_detection.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 0 +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/rule + +# Convenience name for target. +unix_based_hardware_detection: CMakeFiles/unix_based_hardware_detection.dir/rule + +.PHONY : unix_based_hardware_detection + +# clean rule for target. +CMakeFiles/unix_based_hardware_detection.dir/clean: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/clean +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/clean + +# clean rule for target. +clean: CMakeFiles/unix_based_hardware_detection.dir/clean + +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/utils.dir + +# All Build rule for target. +CMakeFiles/utils.dir/all: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/depend + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=7,8,9 "Built target utils" +.PHONY : CMakeFiles/utils.dir/all + +# Include target in all. +all: CMakeFiles/utils.dir/all + +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/utils.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 3 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/utils.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 0 +.PHONY : CMakeFiles/utils.dir/rule + +# Convenience name for target. +utils: CMakeFiles/utils.dir/rule + +.PHONY : utils + +# clean rule for target. +CMakeFiles/utils.dir/clean: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/clean +.PHONY : CMakeFiles/utils.dir/clean + +# clean rule for target. +clean: CMakeFiles/utils.dir/clean + +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/list_cpu_features.dir + +# All Build rule for target. +CMakeFiles/list_cpu_features.dir/all: CMakeFiles/cpu_features.dir/all + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/depend + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=3,4 "Built target list_cpu_features" +.PHONY : CMakeFiles/list_cpu_features.dir/all + +# Include target in all. +all: CMakeFiles/list_cpu_features.dir/all + +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/list_cpu_features.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 7 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/list_cpu_features.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 0 +.PHONY : CMakeFiles/list_cpu_features.dir/rule + +# Convenience name for target. +list_cpu_features: CMakeFiles/list_cpu_features.dir/rule + +.PHONY : list_cpu_features + +# clean rule for target. +CMakeFiles/list_cpu_features.dir/clean: + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/clean +.PHONY : CMakeFiles/list_cpu_features.dir/clean + +# clean rule for target. +clean: CMakeFiles/list_cpu_features.dir/clean + +.PHONY : clean + +#============================================================================= +# Target rules for target CMakeFiles/cpu_features.dir + +# All Build rule for target. +CMakeFiles/cpu_features.dir/all: CMakeFiles/utils.dir/all + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/depend + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/build + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=1,2 "Built target cpu_features" +.PHONY : CMakeFiles/cpu_features.dir/all + +# Include target in all. +all: CMakeFiles/cpu_features.dir/all + +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/cpu_features.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 5 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/cpu_features.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 0 +.PHONY : CMakeFiles/cpu_features.dir/rule + +# Convenience name for target. +cpu_features: CMakeFiles/cpu_features.dir/rule + +.PHONY : cpu_features + +# clean rule for target. +CMakeFiles/cpu_features.dir/clean: + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/clean +.PHONY : CMakeFiles/cpu_features.dir/clean + +# clean rule for target. +clean: CMakeFiles/cpu_features.dir/clean + +.PHONY : clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/TargetDirectories.txt b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..ea3b259 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,10 @@ +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/install/strip.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/install/local.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/install.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_install_components.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/rebuild_cache.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/edit_cache.dir diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cmake.check_cache b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/C.includecache b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/C.includecache new file mode 100644 index 0000000..e68cd4d --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/C.includecache @@ -0,0 +1,54 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/cpu_features_macros.h + +../include/cpuinfo_x86.h +cpu_features_cache_info.h +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/internal/bit_utils.h +assert.h +- +stdbool.h +- +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +../include/internal/cpuid_x86.h +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c +cpuinfo_x86.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.h +stdbool.h +- +string.h +- +internal/bit_utils.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/bit_utils.h +internal/cpuid_x86.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/cpuid_x86.h +cpuid.h +- +immintrin.h +- +intrin.h +- + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/DependInfo.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/DependInfo.cmake new file mode 100644 index 0000000..009a086 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/DependInfo.cmake @@ -0,0 +1,27 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "STACK_LINE_READER_BUFFER_SIZE=1024" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + "../include/internal" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/build.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/build.make new file mode 100644 index 0000000..c6b1e95 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/build.make @@ -0,0 +1,120 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +# Include any dependencies generated for this target. +include CMakeFiles/cpu_features.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/cpu_features.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/cpu_features.dir/flags.make + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: CMakeFiles/cpu_features.dir/flags.make +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../src/cpuinfo_x86.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c > CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.i + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c -o CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.s + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.requires: + +.PHONY : CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.requires + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.provides: CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.requires + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.provides.build +.PHONY : CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.provides + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.provides.build: CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o + + +# Object files for target cpu_features +cpu_features_OBJECTS = \ +"CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o" + +# External object files for target cpu_features +cpu_features_EXTERNAL_OBJECTS = \ +"/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/filesystem.c.o" \ +"/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/stack_line_reader.c.o" \ +"/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/string_view.c.o" + +libcpu_features.a: CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o +libcpu_features.a: CMakeFiles/utils.dir/src/filesystem.c.o +libcpu_features.a: CMakeFiles/utils.dir/src/stack_line_reader.c.o +libcpu_features.a: CMakeFiles/utils.dir/src/string_view.c.o +libcpu_features.a: CMakeFiles/cpu_features.dir/build.make +libcpu_features.a: CMakeFiles/cpu_features.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C static library libcpu_features.a" + $(CMAKE_COMMAND) -P CMakeFiles/cpu_features.dir/cmake_clean_target.cmake + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/cpu_features.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/cpu_features.dir/build: libcpu_features.a + +.PHONY : CMakeFiles/cpu_features.dir/build + +CMakeFiles/cpu_features.dir/requires: CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o.requires + +.PHONY : CMakeFiles/cpu_features.dir/requires + +CMakeFiles/cpu_features.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/cpu_features.dir/cmake_clean.cmake +.PHONY : CMakeFiles/cpu_features.dir/clean + +CMakeFiles/cpu_features.dir/depend: + cd /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/cpu_features.dir/depend + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean.cmake new file mode 100644 index 0000000..cc9cffc --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o" + "libcpu_features.pdb" + "libcpu_features.a" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/cpu_features.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean_target.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean_target.cmake new file mode 100644 index 0000000..1116c85 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/cmake_clean_target.cmake @@ -0,0 +1,3 @@ +file(REMOVE_RECURSE + "libcpu_features.a" +) diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.internal b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.internal new file mode 100644 index 0000000..0776651 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.internal @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o + ../include/cpu_features_cache_info.h + ../include/cpu_features_macros.h + ../include/cpuinfo_x86.h + ../include/internal/bit_utils.h + ../include/internal/cpuid_x86.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.make new file mode 100644 index 0000000..86cd1ca --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/depend.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../include/cpu_features_cache_info.h +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../include/cpu_features_macros.h +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../include/cpuinfo_x86.h +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../include/internal/bit_utils.h +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../include/internal/cpuid_x86.h +CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o: ../src/cpuinfo_x86.c + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/flags.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/flags.make new file mode 100644 index 0000000..a90c334 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# compile C with /usr/bin/cc +C_FLAGS = -O3 -DNDEBUG -fPIC -std=gnu99 + +C_DEFINES = -DSTACK_LINE_READER_BUFFER_SIZE=1024 + +C_INCLUDES = -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/link.txt b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/link.txt new file mode 100644 index 0000000..ef08f1e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/link.txt @@ -0,0 +1,2 @@ +/usr/bin/ar qc libcpu_features.a CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o CMakeFiles/utils.dir/src/filesystem.c.o CMakeFiles/utils.dir/src/stack_line_reader.c.o CMakeFiles/utils.dir/src/string_view.c.o +/usr/bin/ranlib libcpu_features.a diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/progress.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/progress.make new file mode 100644 index 0000000..abadeb0 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 1 +CMAKE_PROGRESS_2 = 2 + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o new file mode 100644 index 0000000000000000000000000000000000000000..d38d48025e9998e6ddf660cd2d0e3c72139bbd79 GIT binary patch literal 39088 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 e-RkXv{qL-`tSf1uzx<8uPQ(%&h literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.bin b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.bin new file mode 100755 index 0000000000000000000000000000000000000000..927e47d74c7e87a6043b3d7ae4593b7fa0afb516 GIT binary patch literal 8208 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 literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c new file mode 100644 index 0000000..83e86dd --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/feature_tests.c @@ -0,0 +1,34 @@ + + const char features[] = {"\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 +"1" +#else +"0" +#endif +"c_function_prototypes\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +"1" +#else +"0" +#endif +"c_restrict\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L +"1" +#else +"0" +#endif +"c_static_assert\n" +"C_FEATURE:" +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +"1" +#else +"0" +#endif +"c_variadic_macros\n" + +}; + +int main(int argc, char** argv) { (void)argv; return features[argc]; } diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/C.includecache b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/C.includecache new file mode 100644 index 0000000..01530ef --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/C.includecache @@ -0,0 +1,82 @@ +#IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/cpu_features_macros.h + +../include/cpuinfo_aarch64.h +cpu_features_cache_info.h +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/cpuinfo_arm.h +stdint.h +- +cpu_features_cache_info.h +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/cpuinfo_mips.h +cpu_features_cache_info.h +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/cpuinfo_ppc.h +cpu_features_cache_info.h +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h +internal/hwcaps.h +../include/internal/hwcaps.h + +../include/cpuinfo_x86.h +cpu_features_cache_info.h +../include/cpu_features_cache_info.h +cpu_features_macros.h +../include/cpu_features_macros.h + +../include/internal/hwcaps.h +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c +assert.h +- +stdarg.h +- +stdbool.h +- +stdint.h +- +stdio.h +- +stdlib.h +- +string.h +- +cpu_features_macros.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/cpu_features_macros.h +cpuinfo_x86.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/cpuinfo_x86.h +cpuinfo_arm.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/cpuinfo_arm.h +cpuinfo_aarch64.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/cpuinfo_aarch64.h +cpuinfo_mips.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/cpuinfo_mips.h +cpuinfo_ppc.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/cpuinfo_ppc.h + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/DependInfo.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/DependInfo.cmake new file mode 100644 index 0000000..7678b17 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/DependInfo.cmake @@ -0,0 +1,27 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "STACK_LINE_READER_BUFFER_SIZE=1024" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/cpu_features.dir/DependInfo.cmake" + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/build.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/build.make new file mode 100644 index 0000000..2f4657e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/build.make @@ -0,0 +1,114 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +# Include any dependencies generated for this target. +include CMakeFiles/list_cpu_features.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/list_cpu_features.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/list_cpu_features.dir/flags.make + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: CMakeFiles/list_cpu_features.dir/flags.make +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../src/utils/list_cpu_features.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c > CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.i + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c -o CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.s + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.requires: + +.PHONY : CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.requires + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.provides: CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.requires + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.provides.build +.PHONY : CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.provides + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.provides.build: CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o + + +# Object files for target list_cpu_features +list_cpu_features_OBJECTS = \ +"CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o" + +# External object files for target list_cpu_features +list_cpu_features_EXTERNAL_OBJECTS = + +list_cpu_features: CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o +list_cpu_features: CMakeFiles/list_cpu_features.dir/build.make +list_cpu_features: libcpu_features.a +list_cpu_features: CMakeFiles/list_cpu_features.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable list_cpu_features" + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/list_cpu_features.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/list_cpu_features.dir/build: list_cpu_features + +.PHONY : CMakeFiles/list_cpu_features.dir/build + +CMakeFiles/list_cpu_features.dir/requires: CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o.requires + +.PHONY : CMakeFiles/list_cpu_features.dir/requires + +CMakeFiles/list_cpu_features.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/list_cpu_features.dir/cmake_clean.cmake +.PHONY : CMakeFiles/list_cpu_features.dir/clean + +CMakeFiles/list_cpu_features.dir/depend: + cd /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/list_cpu_features.dir/depend + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/cmake_clean.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/cmake_clean.cmake new file mode 100644 index 0000000..2a77615 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o" + "list_cpu_features.pdb" + "list_cpu_features" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/list_cpu_features.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.internal b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.internal new file mode 100644 index 0000000..727d3fa --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.internal @@ -0,0 +1,13 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o + ../include/cpu_features_cache_info.h + ../include/cpu_features_macros.h + ../include/cpuinfo_aarch64.h + ../include/cpuinfo_arm.h + ../include/cpuinfo_mips.h + ../include/cpuinfo_ppc.h + ../include/cpuinfo_x86.h + ../include/internal/hwcaps.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.make new file mode 100644 index 0000000..6047430 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/depend.make @@ -0,0 +1,13 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpu_features_cache_info.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpu_features_macros.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpuinfo_aarch64.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpuinfo_arm.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpuinfo_mips.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpuinfo_ppc.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/cpuinfo_x86.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../include/internal/hwcaps.h +CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o: ../src/utils/list_cpu_features.c + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/flags.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/flags.make new file mode 100644 index 0000000..10e1264 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# compile C with /usr/bin/cc +C_FLAGS = -O3 -DNDEBUG -std=gnu99 + +C_DEFINES = -DSTACK_LINE_READER_BUFFER_SIZE=1024 + +C_INCLUDES = -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/link.txt b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/link.txt new file mode 100644 index 0000000..db897b0 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/link.txt @@ -0,0 +1 @@ +/usr/bin/cc -O3 -DNDEBUG -rdynamic CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o -o list_cpu_features libcpu_features.a -ldl diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/progress.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/progress.make new file mode 100644 index 0000000..8c8fb6f --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 3 +CMAKE_PROGRESS_2 = 4 + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o new file mode 100644 index 0000000000000000000000000000000000000000..2d4a87a764819a0249df2051bdffba9cb99c3add GIT binary patch literal 14304 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 dm*JDKdu_^X%@IDGt^P1>3=q=dnSI#n|2H|Wl@]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/cpu_features_macros.h + +../include/internal/filesystem.h +stddef.h +- +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +../include/internal/hwcaps.h +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +../include/internal/string_view.h +stdbool.h +- +stddef.h +- +string.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +../include/internal/unix_features_aggregator.h +ctype.h +- +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h +internal/hwcaps.h +../include/internal/internal/hwcaps.h +internal/string_view.h +../include/internal/internal/string_view.h + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c +internal/hwcaps.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/hwcaps.h +stdlib.h +- +string.h +- +cpu_features_macros.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpu_features_macros.h +internal/filesystem.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/filesystem.h +internal/string_view.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/string_view.h +stdio.h +- +sys/auxv.h +- +dlfcn.h +- + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c +internal/unix_features_aggregator.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/unix_features_aggregator.h +internal/string_view.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/string_view.h + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/DependInfo.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/DependInfo.cmake new file mode 100644 index 0000000..5902958 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/DependInfo.cmake @@ -0,0 +1,30 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "HAVE_DLFCN_H" + "HAVE_STRONG_GETAUXVAL" + "STACK_LINE_READER_BUFFER_SIZE=1024" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + "../include/internal" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/build.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/build.make new file mode 100644 index 0000000..1a213af --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/build.make @@ -0,0 +1,131 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +# Include any dependencies generated for this target. +include CMakeFiles/unix_based_hardware_detection.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/unix_based_hardware_detection.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/unix_based_hardware_detection.dir/flags.make + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: CMakeFiles/unix_based_hardware_detection.dir/flags.make +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: ../src/hwcaps.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c > CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.i + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c -o CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.s + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.requires: + +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.requires + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.provides: CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.requires + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.provides.build +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.provides + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.provides.build: CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o + + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: CMakeFiles/unix_based_hardware_detection.dir/flags.make +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: ../src/unix_features_aggregator.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c > CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.i + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c -o CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.s + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.requires: + +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.requires + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.provides: CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.requires + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.provides.build +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.provides + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.provides.build: CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o + + +unix_based_hardware_detection: CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o +unix_based_hardware_detection: CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o +unix_based_hardware_detection: CMakeFiles/unix_based_hardware_detection.dir/build.make + +.PHONY : unix_based_hardware_detection + +# Rule to build all files generated by this target. +CMakeFiles/unix_based_hardware_detection.dir/build: unix_based_hardware_detection + +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/build + +CMakeFiles/unix_based_hardware_detection.dir/requires: CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o.requires +CMakeFiles/unix_based_hardware_detection.dir/requires: CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o.requires + +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/requires + +CMakeFiles/unix_based_hardware_detection.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/unix_based_hardware_detection.dir/cmake_clean.cmake +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/clean + +CMakeFiles/unix_based_hardware_detection.dir/depend: + cd /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/unix_based_hardware_detection.dir/depend + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/cmake_clean.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/cmake_clean.cmake new file mode 100644 index 0000000..ef5ea11 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/cmake_clean.cmake @@ -0,0 +1,9 @@ +file(REMOVE_RECURSE + "CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o" + "CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/unix_based_hardware_detection.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.internal b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.internal new file mode 100644 index 0000000..98b05eb --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.internal @@ -0,0 +1,15 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o + ../include/cpu_features_macros.h + ../include/internal/filesystem.h + ../include/internal/hwcaps.h + ../include/internal/string_view.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o + ../include/cpu_features_macros.h + ../include/internal/hwcaps.h + ../include/internal/string_view.h + ../include/internal/unix_features_aggregator.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.make new file mode 100644 index 0000000..6a9140e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/depend.make @@ -0,0 +1,15 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: ../include/cpu_features_macros.h +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: ../include/internal/filesystem.h +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: ../include/internal/hwcaps.h +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: ../include/internal/string_view.h +CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o: ../src/hwcaps.c + +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: ../include/cpu_features_macros.h +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: ../include/internal/hwcaps.h +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: ../include/internal/string_view.h +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: ../include/internal/unix_features_aggregator.h +CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o: ../src/unix_features_aggregator.c + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/flags.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/flags.make new file mode 100644 index 0000000..f412b08 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# compile C with /usr/bin/cc +C_FLAGS = -O3 -DNDEBUG -fPIC -std=gnu99 + +C_DEFINES = -DHAVE_DLFCN_H -DHAVE_STRONG_GETAUXVAL -DSTACK_LINE_READER_BUFFER_SIZE=1024 + +C_INCLUDES = -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/progress.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/progress.make new file mode 100644 index 0000000..3a86673 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/progress.make @@ -0,0 +1,3 @@ +CMAKE_PROGRESS_1 = 5 +CMAKE_PROGRESS_2 = 6 + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o new file mode 100644 index 0000000000000000000000000000000000000000..96d46359c778815a6723f05e3fbcdfc7442bc6fb GIT binary patch literal 4144 zcmbtWUu;uV7(ZJFn=tO}5X}Nj*67u23Z)g5#RqNIZo5kgo2)|;2i@Iv#|qurw70S; z!pK^(n{GIRiI19S2oHo9Ib>OOZa}Sb9s4LZXlCO_S8bQS8-hX zk@|T+ymRuD8;oeoA-N%qX$f&}7RL=h+<6|?+Rxqio5kIjS_otZA@EgdC^t-?Ki@09 z-N-r6ZT>YU1ELH%gQ(FG_C2x=`|>)Q3_R zN^z9>hOmFO}jTb%A8D z1dBepK$c(;mos4qryg6p0D#rDzJ0#%f|c*&QoWq1hPDZ04=WDHK44l8z9Vy0PVa<` z+-A7l@2B9*8Ok7pSO@+r=7Q!;xoJ9|*+qHkBiMgH--k-|J*_0Kp=y39r%z!N^E;L0 zr2?yclvO}DtGTnZYk~jCB{`K1WDUguZ&J`Slp5+R&n>hDeVdJ!cVzCU<~ieooXYJB z6c>$sppZKX6sVbta=H!lpyWd?UVkWlEnqZAtLF~TLVF$;48P&+vcp^5iHK|93wrZ)d*9d9%`(JQ2_VlMljg)h{ z>p7Qu%eE9zi!JJ?5}+D=uhk(vPmzn}xUmbdn`%ul%qQ>!AsT4WR`*-Cyn2(iJh z)Ubi4Qo}}Q4U4vHq`C-0z(#6{@HG@E=Vx`1KAxoOh5Ts^0NVzay+|7lyE1rp8GN`5 z{$?5cWEuQJz%kD_76JyXH_Y>J)sf$poiO8=pm##Pg}GGz-}N^8i}YrnisL#NJK{W?~dq)!v0u%+*(q`ob--8PT=1SA$Q^A!SPHP zJk4t648$e4IDQF17>Hvpa{PA$VHEnevHBPK-z?yw|Db@2 z{&fMzKH+iSWB5~mtrze=1$~j9^_UT);*D zTLfJ6zq<@RCE#LxPcpoahtq<-$ire8{Yz!^o%m2N&_62?UH8)a3eL|l;!2K>7+OEf zM#7qhxs=eOn#<6~4B{Hp42`(@lS$%A#BkvnNE)8!iEAJ>GNO-y#%RpYUF|!2w$MWZ z)X-QT4i6=?5uFA9ACnVo@f9fif_MSLagFg|t%}dyO|XF~Uar7q`$LwXvOdA@7slaV zHvEH)<4L#>XKD!1@pS1=9o6MJIB$jveg0Q_57=USJQKv>X7LNZHGIwIm%s?^-J&tb zUS^NyjW|#j2cK0zrW@>b;9oxfUS==$B)W(*`_s%HpE&<~jsLSs)o%~Jj4=3fVg1mS z+w=P2a}>q~h}5%&T4E21|HHTsx{o&)*d~RwL)^{+-Nl74IBy)P1EG}t6w7}>sd4JmdGTd;vjC#7e_lLrn5i?KB z&_1C6N$Q1Ma!Sn_Na>OLW1_6|CzGi}T1ksB zIiakj6MZtD9h}t8Dw1jp74)$+;r=t4u1}6>P*OVEtxg;4S}4X0nCNM4KT<7*mOggb~9)!e}9v)AAI{7lJTjeJLuk!D8)cNSJleX{jIms2+SzD!l)WI*@`wZd>z%$ zC%}A;?_{`pqg#PoL)`Fg%7L2yn%_=yp=N|0r||x*PLSHXKiB&mn3J031SeR7+s`oP zE]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + +../include/cpu_features_macros.h + +../include/internal/filesystem.h +stddef.h +- +stdint.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +../include/internal/stack_line_reader.h +stdbool.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h +internal/string_view.h +../include/internal/internal/string_view.h + +../include/internal/string_view.h +stdbool.h +- +stddef.h +- +string.h +- +cpu_features_macros.h +../include/internal/cpu_features_macros.h + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c +internal/filesystem.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/filesystem.h +errno.h +- +fcntl.h +- +stdlib.h +- +sys/stat.h +- +sys/types.h +- +io.h +- +unistd.h +- + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c +internal/stack_line_reader.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/stack_line_reader.h +assert.h +- +errno.h +- +stdio.h +- +internal/filesystem.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/filesystem.h + +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c +internal/string_view.h +/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/internal/string_view.h +assert.h +- +ctype.h +- +string.h +- + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/DependInfo.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/DependInfo.cmake new file mode 100644 index 0000000..da67850 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/DependInfo.cmake @@ -0,0 +1,29 @@ +# The set of languages for which implicit dependencies are needed: +set(CMAKE_DEPENDS_LANGUAGES + "C" + ) +# The set of files for implicit dependencies of each language: +set(CMAKE_DEPENDS_CHECK_C + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/filesystem.c.o" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/stack_line_reader.c.o" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c" "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/string_view.c.o" + ) +set(CMAKE_C_COMPILER_ID "GNU") + +# Preprocessor definitions for this target. +set(CMAKE_TARGET_DEFINITIONS_C + "STACK_LINE_READER_BUFFER_SIZE=1024" + ) + +# The include file search paths: +set(CMAKE_C_TARGET_INCLUDE_PATH + "../include" + "../include/internal" + ) + +# Targets to which this target links. +set(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# Fortran module output directory. +set(CMAKE_Fortran_TARGET_MODULE_DIR "") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/build.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/build.make new file mode 100644 index 0000000..643aa4b --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/build.make @@ -0,0 +1,157 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Delete rule output on recipe failure. +.DELETE_ON_ERROR: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +# Include any dependencies generated for this target. +include CMakeFiles/utils.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/utils.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/utils.dir/flags.make + +CMakeFiles/utils.dir/src/filesystem.c.o: CMakeFiles/utils.dir/flags.make +CMakeFiles/utils.dir/src/filesystem.c.o: ../src/filesystem.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/utils.dir/src/filesystem.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/utils.dir/src/filesystem.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c + +CMakeFiles/utils.dir/src/filesystem.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/utils.dir/src/filesystem.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c > CMakeFiles/utils.dir/src/filesystem.c.i + +CMakeFiles/utils.dir/src/filesystem.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/utils.dir/src/filesystem.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c -o CMakeFiles/utils.dir/src/filesystem.c.s + +CMakeFiles/utils.dir/src/filesystem.c.o.requires: + +.PHONY : CMakeFiles/utils.dir/src/filesystem.c.o.requires + +CMakeFiles/utils.dir/src/filesystem.c.o.provides: CMakeFiles/utils.dir/src/filesystem.c.o.requires + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/filesystem.c.o.provides.build +.PHONY : CMakeFiles/utils.dir/src/filesystem.c.o.provides + +CMakeFiles/utils.dir/src/filesystem.c.o.provides.build: CMakeFiles/utils.dir/src/filesystem.c.o + + +CMakeFiles/utils.dir/src/stack_line_reader.c.o: CMakeFiles/utils.dir/flags.make +CMakeFiles/utils.dir/src/stack_line_reader.c.o: ../src/stack_line_reader.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building C object CMakeFiles/utils.dir/src/stack_line_reader.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/utils.dir/src/stack_line_reader.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c + +CMakeFiles/utils.dir/src/stack_line_reader.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/utils.dir/src/stack_line_reader.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c > CMakeFiles/utils.dir/src/stack_line_reader.c.i + +CMakeFiles/utils.dir/src/stack_line_reader.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/utils.dir/src/stack_line_reader.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c -o CMakeFiles/utils.dir/src/stack_line_reader.c.s + +CMakeFiles/utils.dir/src/stack_line_reader.c.o.requires: + +.PHONY : CMakeFiles/utils.dir/src/stack_line_reader.c.o.requires + +CMakeFiles/utils.dir/src/stack_line_reader.c.o.provides: CMakeFiles/utils.dir/src/stack_line_reader.c.o.requires + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/stack_line_reader.c.o.provides.build +.PHONY : CMakeFiles/utils.dir/src/stack_line_reader.c.o.provides + +CMakeFiles/utils.dir/src/stack_line_reader.c.o.provides.build: CMakeFiles/utils.dir/src/stack_line_reader.c.o + + +CMakeFiles/utils.dir/src/string_view.c.o: CMakeFiles/utils.dir/flags.make +CMakeFiles/utils.dir/src/string_view.c.o: ../src/string_view.c + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building C object CMakeFiles/utils.dir/src/string_view.c.o" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/utils.dir/src/string_view.c.o -c /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c + +CMakeFiles/utils.dir/src/string_view.c.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/utils.dir/src/string_view.c.i" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c > CMakeFiles/utils.dir/src/string_view.c.i + +CMakeFiles/utils.dir/src/string_view.c.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/utils.dir/src/string_view.c.s" + /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c -o CMakeFiles/utils.dir/src/string_view.c.s + +CMakeFiles/utils.dir/src/string_view.c.o.requires: + +.PHONY : CMakeFiles/utils.dir/src/string_view.c.o.requires + +CMakeFiles/utils.dir/src/string_view.c.o.provides: CMakeFiles/utils.dir/src/string_view.c.o.requires + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/string_view.c.o.provides.build +.PHONY : CMakeFiles/utils.dir/src/string_view.c.o.provides + +CMakeFiles/utils.dir/src/string_view.c.o.provides.build: CMakeFiles/utils.dir/src/string_view.c.o + + +utils: CMakeFiles/utils.dir/src/filesystem.c.o +utils: CMakeFiles/utils.dir/src/stack_line_reader.c.o +utils: CMakeFiles/utils.dir/src/string_view.c.o +utils: CMakeFiles/utils.dir/build.make + +.PHONY : utils + +# Rule to build all files generated by this target. +CMakeFiles/utils.dir/build: utils + +.PHONY : CMakeFiles/utils.dir/build + +CMakeFiles/utils.dir/requires: CMakeFiles/utils.dir/src/filesystem.c.o.requires +CMakeFiles/utils.dir/requires: CMakeFiles/utils.dir/src/stack_line_reader.c.o.requires +CMakeFiles/utils.dir/requires: CMakeFiles/utils.dir/src/string_view.c.o.requires + +.PHONY : CMakeFiles/utils.dir/requires + +CMakeFiles/utils.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/utils.dir/cmake_clean.cmake +.PHONY : CMakeFiles/utils.dir/clean + +CMakeFiles/utils.dir/depend: + cd /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/utils.dir/depend + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/cmake_clean.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/cmake_clean.cmake new file mode 100644 index 0000000..de49fdf --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +file(REMOVE_RECURSE + "CMakeFiles/utils.dir/src/filesystem.c.o" + "CMakeFiles/utils.dir/src/stack_line_reader.c.o" + "CMakeFiles/utils.dir/src/string_view.c.o" +) + +# Per-language clean rules from dependency scanning. +foreach(lang C) + include(CMakeFiles/utils.dir/cmake_clean_${lang}.cmake OPTIONAL) +endforeach() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.internal b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.internal new file mode 100644 index 0000000..15c4029 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.internal @@ -0,0 +1,17 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/utils.dir/src/filesystem.c.o + ../include/cpu_features_macros.h + ../include/internal/filesystem.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c +CMakeFiles/utils.dir/src/stack_line_reader.c.o + ../include/cpu_features_macros.h + ../include/internal/filesystem.h + ../include/internal/stack_line_reader.h + ../include/internal/string_view.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c +CMakeFiles/utils.dir/src/string_view.c.o + ../include/cpu_features_macros.h + ../include/internal/string_view.h + /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.make new file mode 100644 index 0000000..49618e4 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/depend.make @@ -0,0 +1,17 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +CMakeFiles/utils.dir/src/filesystem.c.o: ../include/cpu_features_macros.h +CMakeFiles/utils.dir/src/filesystem.c.o: ../include/internal/filesystem.h +CMakeFiles/utils.dir/src/filesystem.c.o: ../src/filesystem.c + +CMakeFiles/utils.dir/src/stack_line_reader.c.o: ../include/cpu_features_macros.h +CMakeFiles/utils.dir/src/stack_line_reader.c.o: ../include/internal/filesystem.h +CMakeFiles/utils.dir/src/stack_line_reader.c.o: ../include/internal/stack_line_reader.h +CMakeFiles/utils.dir/src/stack_line_reader.c.o: ../include/internal/string_view.h +CMakeFiles/utils.dir/src/stack_line_reader.c.o: ../src/stack_line_reader.c + +CMakeFiles/utils.dir/src/string_view.c.o: ../include/cpu_features_macros.h +CMakeFiles/utils.dir/src/string_view.c.o: ../include/internal/string_view.h +CMakeFiles/utils.dir/src/string_view.c.o: ../src/string_view.c + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/flags.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/flags.make new file mode 100644 index 0000000..a90c334 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/flags.make @@ -0,0 +1,10 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# compile C with /usr/bin/cc +C_FLAGS = -O3 -DNDEBUG -fPIC -std=gnu99 + +C_DEFINES = -DSTACK_LINE_READER_BUFFER_SIZE=1024 + +C_INCLUDES = -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/progress.make b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/progress.make new file mode 100644 index 0000000..cd5d6f7 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/progress.make @@ -0,0 +1,4 @@ +CMAKE_PROGRESS_1 = 7 +CMAKE_PROGRESS_2 = 8 +CMAKE_PROGRESS_3 = 9 + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/filesystem.c.o b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/filesystem.c.o new file mode 100644 index 0000000000000000000000000000000000000000..36b9cec2f5113b3537a638cda97f29a96bbc9a80 GIT binary patch literal 1976 zcmb_c-D}fO6hHl#t8Po{7ZfHesK^u-TKt-Okfz<*IEs~Rg^3#>>oPjlHls;l6VX9+ z5K!2I5B@1W3iD4;@Kpry3q%m{VRN37+}ma$^FjQTn{)2(ob$W4=jP_&L@^%@g@7Xj zH=sM?EWnFs*Uva^2Ku27%F~LytF*tyzQp50;{YEi)*g+vj;DX7Un=%Dm-w}3Z(Hw` z_N$ov_U`=lk`y0$(vm*pAR-Yrkxw0|h}8%KE{KGfAcso0;3_J{F(%I~izHp8-zY)1-$SQU~vAt4JfNMH#6wu2sKN72qQ--%^~#M5wANIr>- z3*u%}7KYnBlR~O04Ce$9H8Gw=t-pcJBnsd6f^s5(Ck7C~Ul1aw6od#I3ZhY^_W+*% z<8D|$_n2otPVbOAgM)hI$8{uv_{jtK67r; zT+_{U)6(lw1#+vcyslZTrf#aGRlSkNAgG06DJvJ%Qa(RDF{94N+2Vu>s;W1e4MVLN z70p^U8em}lK7m}#Fm*?vLf*dEl&&p0p(Z-C&!hA}&`BM^v9ssmG?576`*3i6nMi~` z|GrB*d>nnAFMId_4=*x4jFtw6!W_fK3&EkGT8eUw)32FXoeHv>?Gljzo zzWxO-i9TPS+c6L4P5teiczj;RDZ0nRdEYT7#uB%9BD1`IoTl$XQ2!G|BKZ4C{im-N zujl;_TpRP~+fUeFmhK+a`s+#8-+QDW!N|un@qo#77`op<^|NgMcRHD_7%Q6dv12W14hrN{}KI(LGow1-ir{2&fS9I($uH#obp7gp}VAj@rf{mef7y+1l3 zLL%pXN9bPU!aC@GhG_YlEP$gry{WmmR&xQJZff}(?lNuSK9{h(V{|-rjFw{If=VZ2 zQG?#m=tbOqc20dwol{S3L=Jv{B%r<@HG132Dnfq)ytR(yU17}WEq8Urz^qP(WAPh0a0$-=8DKRXi*hD~$iYc0nFVOe zZRc?)kL7srzO!GW-vd8hKXdUiTOAK+hroex5+t<{JxTal-)sl8{1$I7OQyM9Hd@5EnF#>Nl1C_5bZ409uJ_9O``MFR(h2EuDlMilVJ z_?pc1>!8QD{Y(&yq!j%qn3P6VLrF>guuqjn&-YJCW6eFm&-O~AswBf2_#~yUJ{T+j zWJvN+0c8e*Re&;*tP3bL$g}TO_@?^Eubtg1goL`jIK<)RcaabtRu>78JzY@D<9WOu zj}Yni%v|$PQ2RZ6WbT1|LtM;R{{YirV6XjR0?-YAzX$$l4}7Bs{!R)GI}&XqAd*?OjX9?Ij02iJ397N!2j3>GV`;+MHICM#>}; zryFV8avC+eZcaJ1V&#pQqWv}`T(Fn2g^5M0*30FnZJ$opsuib~!-;B_btIfFmTXeC z%jN1@HkpCCQSb)fZF>L@3}ppD5X6UI2>f#dK@i^uL*Tz42;$E(fEShH5@_MS;=v;x z{7Vn+_3y{`1>)cLB@gc9FEejKaGAR>WZZ|#d`^`5nX+TegLZ1JUKCc%E?J5L2T7C# z%dvXKR z_s8E2uZaDh^nzfcFN)AdJT_b4pUeM}f0oDl-P;^k^Cksb^iROAfYGi07x;mSy0HKF z>nh?!|FI7L-T;vkyrJiKq4;+PWBu`%*WY`9$QF_Uxx>CYAJI2~JPby+_)DDstHP0M GfBau)yP1pt literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/string_view.c.o b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/utils.dir/src/string_view.c.o new file mode 100644 index 0000000000000000000000000000000000000000..31672b01e1de8a1a968c11328636c03174a949af GIT binary patch literal 5720 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 literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfig.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfig.cmake new file mode 100644 index 0000000..e0bf10e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfig.cmake @@ -0,0 +1,3 @@ +# CpuFeatures CMake configuration file + +include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesTargets.cmake") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfigVersion.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfigVersion.cmake new file mode 100644 index 0000000..9b9ee14 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfigVersion.cmake @@ -0,0 +1,46 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "0.5.0") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("0.5.0" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + else() + set(CVF_VERSION_MAJOR "0.5.0") + endif() + + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile new file mode 100644 index 0000000..a317f13 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/Makefile @@ -0,0 +1,450 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.10 + +# Default target executed when no arguments are given to make. +default_target: all + +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + + +# A target that is always out of date. +cmake_force: + +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Devel\" \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components + +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache + +.PHONY : rebuild_cache/fast + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..." + /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache + +.PHONY : edit_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/progress.marks + $(MAKE) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean + +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named unix_based_hardware_detection + +# Build rule for target. +unix_based_hardware_detection: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 unix_based_hardware_detection +.PHONY : unix_based_hardware_detection + +# fast build rule for target. +unix_based_hardware_detection/fast: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/build +.PHONY : unix_based_hardware_detection/fast + +#============================================================================= +# Target rules for targets named utils + +# Build rule for target. +utils: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 utils +.PHONY : utils + +# fast build rule for target. +utils/fast: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/build +.PHONY : utils/fast + +#============================================================================= +# Target rules for targets named list_cpu_features + +# Build rule for target. +list_cpu_features: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 list_cpu_features +.PHONY : list_cpu_features + +# fast build rule for target. +list_cpu_features/fast: + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/build +.PHONY : list_cpu_features/fast + +#============================================================================= +# Target rules for targets named cpu_features + +# Build rule for target. +cpu_features: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 cpu_features +.PHONY : cpu_features + +# fast build rule for target. +cpu_features/fast: + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/build +.PHONY : cpu_features/fast + +src/cpuinfo_x86.o: src/cpuinfo_x86.c.o + +.PHONY : src/cpuinfo_x86.o + +# target to build an object file +src/cpuinfo_x86.c.o: + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.o +.PHONY : src/cpuinfo_x86.c.o + +src/cpuinfo_x86.i: src/cpuinfo_x86.c.i + +.PHONY : src/cpuinfo_x86.i + +# target to preprocess a source file +src/cpuinfo_x86.c.i: + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.i +.PHONY : src/cpuinfo_x86.c.i + +src/cpuinfo_x86.s: src/cpuinfo_x86.c.s + +.PHONY : src/cpuinfo_x86.s + +# target to generate assembly for a file +src/cpuinfo_x86.c.s: + $(MAKE) -f CMakeFiles/cpu_features.dir/build.make CMakeFiles/cpu_features.dir/src/cpuinfo_x86.c.s +.PHONY : src/cpuinfo_x86.c.s + +src/filesystem.o: src/filesystem.c.o + +.PHONY : src/filesystem.o + +# target to build an object file +src/filesystem.c.o: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/filesystem.c.o +.PHONY : src/filesystem.c.o + +src/filesystem.i: src/filesystem.c.i + +.PHONY : src/filesystem.i + +# target to preprocess a source file +src/filesystem.c.i: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/filesystem.c.i +.PHONY : src/filesystem.c.i + +src/filesystem.s: src/filesystem.c.s + +.PHONY : src/filesystem.s + +# target to generate assembly for a file +src/filesystem.c.s: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/filesystem.c.s +.PHONY : src/filesystem.c.s + +src/hwcaps.o: src/hwcaps.c.o + +.PHONY : src/hwcaps.o + +# target to build an object file +src/hwcaps.c.o: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.o +.PHONY : src/hwcaps.c.o + +src/hwcaps.i: src/hwcaps.c.i + +.PHONY : src/hwcaps.i + +# target to preprocess a source file +src/hwcaps.c.i: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.i +.PHONY : src/hwcaps.c.i + +src/hwcaps.s: src/hwcaps.c.s + +.PHONY : src/hwcaps.s + +# target to generate assembly for a file +src/hwcaps.c.s: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/hwcaps.c.s +.PHONY : src/hwcaps.c.s + +src/stack_line_reader.o: src/stack_line_reader.c.o + +.PHONY : src/stack_line_reader.o + +# target to build an object file +src/stack_line_reader.c.o: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/stack_line_reader.c.o +.PHONY : src/stack_line_reader.c.o + +src/stack_line_reader.i: src/stack_line_reader.c.i + +.PHONY : src/stack_line_reader.i + +# target to preprocess a source file +src/stack_line_reader.c.i: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/stack_line_reader.c.i +.PHONY : src/stack_line_reader.c.i + +src/stack_line_reader.s: src/stack_line_reader.c.s + +.PHONY : src/stack_line_reader.s + +# target to generate assembly for a file +src/stack_line_reader.c.s: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/stack_line_reader.c.s +.PHONY : src/stack_line_reader.c.s + +src/string_view.o: src/string_view.c.o + +.PHONY : src/string_view.o + +# target to build an object file +src/string_view.c.o: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/string_view.c.o +.PHONY : src/string_view.c.o + +src/string_view.i: src/string_view.c.i + +.PHONY : src/string_view.i + +# target to preprocess a source file +src/string_view.c.i: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/string_view.c.i +.PHONY : src/string_view.c.i + +src/string_view.s: src/string_view.c.s + +.PHONY : src/string_view.s + +# target to generate assembly for a file +src/string_view.c.s: + $(MAKE) -f CMakeFiles/utils.dir/build.make CMakeFiles/utils.dir/src/string_view.c.s +.PHONY : src/string_view.c.s + +src/unix_features_aggregator.o: src/unix_features_aggregator.c.o + +.PHONY : src/unix_features_aggregator.o + +# target to build an object file +src/unix_features_aggregator.c.o: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.o +.PHONY : src/unix_features_aggregator.c.o + +src/unix_features_aggregator.i: src/unix_features_aggregator.c.i + +.PHONY : src/unix_features_aggregator.i + +# target to preprocess a source file +src/unix_features_aggregator.c.i: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.i +.PHONY : src/unix_features_aggregator.c.i + +src/unix_features_aggregator.s: src/unix_features_aggregator.c.s + +.PHONY : src/unix_features_aggregator.s + +# target to generate assembly for a file +src/unix_features_aggregator.c.s: + $(MAKE) -f CMakeFiles/unix_based_hardware_detection.dir/build.make CMakeFiles/unix_based_hardware_detection.dir/src/unix_features_aggregator.c.s +.PHONY : src/unix_features_aggregator.c.s + +src/utils/list_cpu_features.o: src/utils/list_cpu_features.c.o + +.PHONY : src/utils/list_cpu_features.o + +# target to build an object file +src/utils/list_cpu_features.c.o: + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.o +.PHONY : src/utils/list_cpu_features.c.o + +src/utils/list_cpu_features.i: src/utils/list_cpu_features.c.i + +.PHONY : src/utils/list_cpu_features.i + +# target to preprocess a source file +src/utils/list_cpu_features.c.i: + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.i +.PHONY : src/utils/list_cpu_features.c.i + +src/utils/list_cpu_features.s: src/utils/list_cpu_features.c.s + +.PHONY : src/utils/list_cpu_features.s + +# target to generate assembly for a file +src/utils/list_cpu_features.c.s: + $(MAKE) -f CMakeFiles/list_cpu_features.dir/build.make CMakeFiles/list_cpu_features.dir/src/utils/list_cpu_features.c.s +.PHONY : src/utils/list_cpu_features.c.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... install/strip" + @echo "... install/local" + @echo "... install" + @echo "... list_install_components" + @echo "... unix_based_hardware_detection" + @echo "... utils" + @echo "... rebuild_cache" + @echo "... list_cpu_features" + @echo "... cpu_features" + @echo "... edit_cache" + @echo "... src/cpuinfo_x86.o" + @echo "... src/cpuinfo_x86.i" + @echo "... src/cpuinfo_x86.s" + @echo "... src/filesystem.o" + @echo "... src/filesystem.i" + @echo "... src/filesystem.s" + @echo "... src/hwcaps.o" + @echo "... src/hwcaps.i" + @echo "... src/hwcaps.s" + @echo "... src/stack_line_reader.o" + @echo "... src/stack_line_reader.i" + @echo "... src/stack_line_reader.s" + @echo "... src/string_view.o" + @echo "... src/string_view.i" + @echo "... src/string_view.s" + @echo "... src/unix_features_aggregator.o" + @echo "... src/unix_features_aggregator.i" + @echo "... src/unix_features_aggregator.s" + @echo "... src/utils/list_cpu_features.o" + @echo "... src/utils/list_cpu_features.i" + @echo "... src/utils/list_cpu_features.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/cmake_install.cmake b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/cmake_install.cmake new file mode 100644 index 0000000..0e9cf62 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/cmake_install.cmake @@ -0,0 +1,103 @@ +# Install script for directory: /home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Release") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a") +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/include/cpu_features" TYPE FILE FILES + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h" + ) +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/list_cpu_features" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/list_cpu_features") + file(RPATH_CHECK + FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/list_cpu_features" + RPATH "") + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/list_cpu_features") + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/list_cpu_features" AND + NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/list_cpu_features") + if(CMAKE_INSTALL_DO_STRIP) + execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/list_cpu_features") + endif() + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xDevelx" OR NOT CMAKE_INSTALL_COMPONENT) + if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake") + file(DIFFERENT EXPORT_FILE_CHANGED FILES + "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake") + if(EXPORT_FILE_CHANGED) + file(GLOB OLD_CONFIG_FILES "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures/CpuFeaturesTargets-*.cmake") + if(OLD_CONFIG_FILES) + message(STATUS "Old export file \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake\" will be replaced. Removing files [${OLD_CONFIG_FILES}].") + file(REMOVE ${OLD_CONFIG_FILES}) + endif() + endif() + endif() + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures" TYPE FILE FILES "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets.cmake") + if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$") + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures" TYPE FILE FILES "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CMakeFiles/Export/lib/cmake/CpuFeatures/CpuFeaturesTargets-release.cmake") + endif() +endif() + +if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xDevelx" OR NOT CMAKE_INSTALL_COMPONENT) + file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/CpuFeatures" TYPE FILE FILES + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfig.cmake" + "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/CpuFeaturesConfigVersion.cmake" + ) +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/build/libcpu_features.a new file mode 100644 index 0000000000000000000000000000000000000000..0a21a36ba64e5dd24d63309a2ef2a66baea8bbb4 GIT binary patch literal 50632 zcmeI54|r77wdhYsAPHb5mZ-7PIxW*SC_+La#2V`inUE6+kecwP5=}xfF)8_HGJ)7e z4V^@DZb(g^Y307sTYAM?{Nz2km8YmwX9x-^ttp_Ug*=I3> zweQ|{zkZ+l%bc_KZ?C=9{(tt_XL9CiS!IpoRo@vu!)|q{O3?JHN4q_9_Dqr}9j|HH zWKD~K(`S9wozOJ-*)XVS_<1Vh@A+gmH0M?1v}m~=@6znsQ*+8pZ|1D*vhpfVUR`Cq zh{~Kbzq-7!9?Mwm^^|*?8$H_G>YAFRnX~3Jmeo}hdK;_j?j}(s)m%>*$~NWHHP>o`HW#tj8 zu%N85$x~3@1Z}X=v!JDNzbQ2{Q>ZN+|3FUu+%Zv6Fz!tkrF};Wg(TIq)4d_TQ+S=4O-s-UjrWZa+rR3@ zTYBJ--SF#yBX;98J$^us|6o~PWl!3xwy6HT%IUUi+eIqZ64zqA`$qJ;7P*R^n*yFi zg}U*HzWPKJ7}mRs9jO(1SIjq3AVxRZ9ZP|x`E}!+Gy3CQIQ1*K4zs#5#(^h5{z_Y2kt0s;E^;KM zVPLX@szWzw9C4Ml<*%i^3dcU(NOBl2SK4X;81elSfb%}ObgN!z5GqRJLXNyiaxbJZI9mV_QklmvL0PM zItt8Nxq37Y^w}PI?sAYQ&w5dh`f&89>$y>IX``;KP7rcEj~58n3tA!^e~bPcP5?4SAbfrYb+k2@hWZg!mC3;-B6-@+vRRY28K!@RE70ZfT+fHdAp+%(%^Xm zo~O1u{1iSw=Mg$%<6?X&oKaOPbhUPf(~VxoS~x>+Jq5Rz!EF@mH-iHdgv%icpQT_N z=!0OQP}}Qpn89fjbecgOPQz87K*@u3+Xm^w*6r{UpK`ez<2BX*!|fI!CnyUeRALbt zBP?RWgEGw-YR%!<7CC!(WnZ!gIZ;ixt}%SfQcP49UT!f z$~4!DnCan1FCm&}6|K31Xq;8lbqUcJtLT*$Q77i?d6`$1f#Vl0E*6a-jb*?OqM;69 z7h0)##9+fg0E2CKtwp6%$R*$L|L(peSC2Z zNUfp1BAVc(Fru=rFs;3p5M^4cFCiN0fg%In0ntzo)L^h#$Lcs}4(x$fTIB${p2s*j zD@nPNAF298yIbZ6*`r^v$l)zWa6E~gFZKP4MNZVBMITlc=5Hm)h2|0`=InVnLfWh& zWS&K3n-Hbu5vHZeDHb_XWjML>BWjUxEoH4jsc$dJiOCK!3IjI^G9Jh=w!3~C3wg*f zUK##(kcd=>(qPXO6XJtmMCB;ctmR#XcAvvZ7Ij;yP)xHjf9V!EEJv6NN`ghm(!Q1p z%8?IMqgX)K^YX%DhoVTMFIwbMRXIyz{0!uH)lg$V%g7lJuNcECEGmQLK#L)}b5Uq3 zRSGo5n2Q?25yqmdVQ0{y7(^ePQwwWHL$Z@vYWNQpIkWQA>0VaK6Jg{;_N{BM;ng4) zp;GvjW^ou%>`2%VLsNq2TGxjWrK%RC!AhpfvIe3r2{ocBUC%j1*`;)7S`v!){PmL3 zEE^jxEzPdaD=#fQCfHyiCpt*;ilYjKRj%w!Li8&j%12MQj{MiNN{13l0~p;^;rTaiWWm;puf!Wp%K zL@kEx{QE$TXH;J7{XvytJUtOcR1Up1tLXhHgedFF-@Sw=8-3rrgeV(&=igUr zz?xS!?)pJAIO~c|WL^Suj6QMwvuJXPQd3>FK@F(G=)unrRXXT05WU1C#cKYBOH12> ztuNYX^t4)bGsm(|vC7{EqL;`kBNRU@&C84MjyVbEckR5d}pdQ701}IjI)kA_@VE*583>s7w}7&8d{>af_U2 zOj%79x%-6aoHTz<+N(KfdvenD=cK)tlXh;n0wQeJI<>TOqSp;+;EWgtY<$Gw-Wl$f z!Ddv9Lk9?+e83ntJpVm2U4Hk97}$ydRmZDQkMaA!&{*S*z{!ce!Pvm?m8*}8Lf?a3 z9T#k>`Cf@yeRR|Y;q6hzY2VJM93v;j_Ef-S%%A8o?n`tTi;`SMbF#~~Bg*#FPTN!4 zAyu3UlI8hcp6v2{I^NcP+lkRpw{h+zY*mq49WJ1_zc_4n`3A4Gb^HL9Yr45dBsYli zjGRQ1xNMi_XrMIt_!A;=rQCnix8g1#?hEQSxv1_H5$NWf- z>K`2h6>iw1{6So~YrebrNs<0>NZ(!XewyF+G3<3YVaOQ$l&&l0M}4+ywXIm*Ga>sR z`aoj5?U#O^|1uE|+m4#DpW3wqwh?{D;(Z^FS+z^=7W-sfF+CvK4uYDt6?P(3`K_?O zW(ni`r0Cm<7dACKfrar&ks2S*!k7a!9%m#qj6+Hdsi*{D2I26S23OVm2MZ$vCWR?H=eB zuo+$fmhoJQ=d}IcD@NZdu!{>Dy|2P~83yivz#ce%4+Bdfa1PG*VPJ`t_8y#C(Z5(r z8->#%^rvbfbrJdtA%P#xw`1VD5I79y0t_sK04866f%y>F4`&?%`FP01!(2S%;K7ZD zY&>M);buHc!-E|UDR^kYLn9vU!9xQc>hbV>Jk;T#77sOen1hEEcyQstiHBS9@Ettd zf`@9&_Drv6AKNn!a`_HL*`Dz_ZgKhk5|tD6p6}oV-(ZyQNK|~k?U^FStx@OVPh7pHug>K=OxgOrD{wg4H~5Cg3mP>g z>H`PInid+ssE8aFI2db2-eblzcAADU1OEduV44EUQF~0e6jQEA7I=&qw!7m8QTAQP zRt%axN=BzejZ&%m-Ntqlf$|=V4ICL4e;TePXy*~I<1*D`xxv1$J9r^}m+hH+$IY1i z5v*9KVbK2W7?Wq43EXH4v8>x&CeOjNbHSDyE&L2DfTzN72j=D7*uX)m>U>jKE?C7} zpe#OS11V4%wFk;=3h1WR`N2$xGDVw_3(Uxc7i9(W@Le;q0E_*u(#*Y%pQ53^M438n zhfWd&xj^gKbqZaO0l3UwfDY(_`ht#^6Tb_}kndQ8S=$dCD*iPLrbhW)@dNSOF;$W8 zpjk;!TT$H^9iU8uZWsSS{Ag>XdTb~xG_<)GU{%@NP7{iQwIYUURM%Y1c#8 zW#roPjS)zfn`rBJAP$~Vt=@sNzVhVJc5NF-;^f)_5n9K7m+>FAj#{|nh*|OuoLB2FFk7|uS8W{?PzZ<@+N#7Yhkf`cCs{of-0jB+b$0a#zgqsi=Ui2;ig3 z0r==z06w}9fbX-e0=SUI6?IpUqoreytvw#Dd~ihv`)%&dHI6p$xI2p+4|L``?ss=W zBZv!Z+MZj41oq7q?CST!7y>CcnrT)ogtl%6nY7UkzjvbXcHq>wz|mNze>4`ZPQF%$ zcbu(b2)3T#S+2|2>k1r-b@|W74!;RVtS_;>A-Og@0UpP}`T+6-HD|6ef>unU(mtd( zZpiha+kofoZn(xzgG;{M4Hy3uk#l3GvE6vZcXZt9gGWI9>LW+AaWFQ5m z74zMNsk$J!y9*TA+AH8fpJSYG1>XB|j&a&;47rW>U4au<2L@wZfuTu(;UxbE_zuHo zFc#`51?B^s5+T}u0X`$K`1cV;L2gb5hTN@Wdejco?3VfX6%LoNU574bH%_^YlWxNgSN6crn82}6 zS7`+r7@{hH0@sOfOt8wnFT!!baJ|uQ91Dh4h}ckzG>Gt*g7No=@KwQZqX;LPVd&*w zfv;kK(I&*Fupxa1ZL5!-h7v<-22RF6+KUNC>v zI1o>w>XUJ%>RXT;2?~72=yw|jQQ+9sfsEd?d}T2HdmLb!`oq6 zH1E6dhEDI^=I}$U8(SP};N&*eiEoFv;Ts-p5QeGx0i3Guf2G}ljT8F1$kcX6KZOV3 zEGERZZH`yLzZ3`5C`_o34ky$H++C(NH>?LbK>)rfgvM+g_>>-3bbo+QR-yO%S#!LV zS-IYttR=Sge?#WBb$CGr6z_%LOj}2#8QKS-G}}+X4q8bK7BqD@2UVKadAu0mWly~! zfy?6X06du$V}3Z<)b!`K1*-$5)noW58^eDT;a>mn01$b70RATM zRNGH!>KOJztf-N#xXu`UQalNVi`B3Tw#kh@h>-+S=W~P6?-ZS zh?6l<{pNUp-YYut5Om~O5c#a09O}2Xh%Ol##=(C4IeW0$?f*0SF?LgR=!EUd z7xm-e-@@}VSc?7UFJ6YHn!O^lMjAc_Pi}GN#P{jVwukn>oJ`wL#yQx)`i_gaM zAHo*<5VqKlV)kL{!(t!87W)vk*oUyiK7=jyA#AY^Vbwk^L$Ujt*CE?8FkFOrB`nM< zVPReg3-d}?m{-EWyb>1XWf;e&P=MRmJ-$&G-)}49dlbg^^P%xgTgJit;xEE*0|PtE z^7{8heSA?L|49A8H+r@0p=V)bCa>pTjQ4-Y@r;@N!hKN#U(~=CHSk3Zd{F~m)W8=t z@I?*$HV;W@C@>N72J7(0%8uC;_o+X0}Dqg97WnG=b z%d5R*HFryyhWdu`I&V;ANd`(vOAr#}HO-YYdCKeSDoR4eN;1IT&_udQmO~{<|H_7$ z)zAp=KjYkLX3Ett1p;gSVf-h!f>{F3a2x95Yzv2Z#Z^U1#o zmCi{>e0a>9gybJb=Ox&?W9B5JtQk8uA@#v=u7pfq>}?6_qsMF+pOEQFNOdKo%t^3= zC?uJa5I1K6>R(H`_Ta-5a4GP?uYjQY4?IAA9vtIJNcKf9NJt%%Jw72Bh$|s(-UN}4 z0h9rkkIF)MaR>9_4(25x}Ot{%yv8 zNBla*@li19{|e*ya2ENO7=MTOIL7}%{Jc1a4#$a~4k6)tpZHP6KP3KV#y=sB4~JD3 zE%Fho?N%Z94dd4k|6h!Mjkwv)p~!C$H~U41-#{F{r>DAf;y+a( z_-`VP-}P7Bt;GLHh2YO2ZjOUceq2oE2qP!emV$BOOtAXR% zkh@1CaO@wbXEQCt<$Bjoya#WJ!HG35oc9uMz#C<7VtoteKNI(VOJGf|Q_m4!f4#}& zTJy7rZ~hH;S|wB5j69n<3I> zh_o3ZZH7pjA<|}uv>768hDe(((x!{F=^|~qNSiLwri--cB5k@zn=aC(i?lOE+L zahadT6#Xk83$k37(Iy}2$MQPp)-#9kZFCFR!}ww1zoL1N=l^^JekIM1Tz+N*{tM!= z9dUOkRH6ZmHI#Y zMu@BJwVSRVSP$4<6|tt=Cc1t|UPPDBK852xt<=9);kXwe`5}elbyD&(3cp<8(X>!S zyZA4=Qht)cvCB(7Md8>bB~Mp4b}`Ab6^>m=@X{A&u2z5xQ@u>QXeAE{@O z!lx*Fio&t$N%?ezW7m^BTjAeSc%j0vOG^22g{LUIN#Ro!?o;@63V%f5*!86T#}tlL zBKgw_N3Z043ZJgB6C&LWO55yh!1N3SXq~a)mEec$31HDBP!T+#8bp@DYW7PvMU#{0@ab zt?*?E?^AfO!uKj1_o}4bLkho3;b#8- zA&%F2bW(pRalA&Oll&>-c0oh@GU5)#kKm#P9A3-NNj)zSr^|AX|C~5AV~~4^X}a*=W2A4f0H=QvFId!gYxMVG{pB3cQgJrah!|LNj>|C<6MDG@^^?Am^jD}5y!EK zPRbu8j$;a)9h_^95iFiBXlSzLk;~!jZf;EiqBHqLJuZZ_DzKZx-#;>RRtYdrz@%4ldE(O;e}s4{<2A%H7=LlRsXvqPM~TaQ4w?Te#+vd@Ccitz z5b+|W=YG<&l<_-=7c<^B(X?C2_!-hK_p7Ac z$4I`4$v;56hVc<9Zv*3R6ZbNHHR)+#d;;xrwK8ra-p2UHRNi*R-y+`0_%)lnX-_Mi@7L$^z~)7=MQ3#l#Fr>0ta> z;^y<#ke(NaPh;{g5tq+XF&aO8#LefhAw4^ZXEHsn6VGD&4dPD5_Y#-SeK8t8Zxh#< z{C?u*bK6jU-XUJVBKiMKAZSP#&0IRiSb*BZ)QB3_!h=&~xfTed>rva#vdcQNsRxR zcrxQp5}(ZYQ^f6zKTX`h__M@Q82^~o=hGN}iR4om?<1bU_)g-PjK5Aii}5#zI~hMp z`EfJuC$2O8&&2Z?e~0uJFn)-55#vXRFJ=6G(qGK@65^$drxLGV{6o@T#khQ~T*LS% z$u}^51?l%Pevx8Y_%hP7oADCj{fw6r-^cjf#0MB(LHq#Y^~47mZz6t}@m0i!82=&h6O2DV z{50b};%6Cui1-NOUBoXi{xEUz#Rr=EasGdVcnn>ae@Q%%@yCcK zG5%}f$&5cqd@|!t5w|n`G;s&x&k|2z`~~9E7=MX)D&u{`GZ^1VJd^R)iDxnX25~3j zdx^Ulf19|@_%YZ8z;#(P?M|>OO3yJ#~FC@N$@g>A} zF}{rWZpKT9_cLBjd>`X?6CYrF1@Qxn*ApLPyovZ>##a#^V*H21PcZ%f@zad^h@WNr zA>t#9cM-q9_`}5Izo^N1{t@CabRQ=9qr~GF|2grAjQ^5&BIAz{Ph$Mn#FH6+lK5oC zpCWE&{AuFy`;RjJiS%3`g~>ZVn%l#k5 zClmKFZYSQtxPy2r<0-`37?=5PXFQeUI~mU)zJ~Ek;ysLK5$|RE0M)}<#@!^pj`4Pq zU(fgu@ePcxBfgPw`F{_a7+*?uH#1&Ld<)~H#J4hDL3|tIRmA;_4-wzN_zB{>7#A-x zfc3y`##>0fpYc}W`xw7K^)tYDJINnld<)4BGQN@cVa6xYdS-}mKgpk9d@b2M&GeJ5nZjyH}F7uzl_-V@jG{y%=Pb%XFh-WZ9NIaAA!^E=~m;Kzy_z304&A9A8 zI^$xqvrzJd4! z#^rSi{-s|yInQq*`54AG6OUtj3-O7JZzZ0{_%`B6jQfcvGroiPWX5}`KJARJCGKFn zm3Ru{^8Y)hF+M&>8 zFJfG-qn0urL-kh7cpULk#)pW@|7Vi@Y8~+^Cf|0w+5c)7_Y!Ylyo$J&@nYgFj294Z zW!z1?jqyz4?Tk+&-pRO~_!`EOi1#oaN4%Hu3)h+Tu$J-D#Md!?nD~0e2Z(QAd^hop zjQfdiVtfnn&5Um(zJ>91#J4iuLwplzf5b?8&A0R%$ct7zAjPD>WztAto z=~m(~ai)FAHxZ9xd_D1rjQ0{xWW1Aj663AJlNoOyKAG_f;&#TD5_d43PdtTjC-G^F zXAnxcV_cFel_*%yO#Md#th4^~LHxl2#_&VYn8Sf#!iSc&g zn;CB*zJ>7`;#(OnCBBXEBI16=b>cf1&mz8y@l@iw8FvuxXFQqsKE@{!A7ES~et_|_ zH< zQpWAXiy2QMUdnhJ@e0N-q?&fC7(Y$ChVjG18yFuT?qz&8@fODY#9JBPLcERfjl|m- zUq`%?@gCx97;h)u!*~nvUdC&PuVuWH_&Uamh_7c{C%%F4EaDp(PbI#Iaro6n;q2x~ zd^ZsLqI6m0k^R$7;R41kD= zcOve%P5c((5XSj3W11(yk2d;sFql&KOvBXJ6%X`CDScDBlwbyB4{M zT*fDh3iFJ!I{a2HYQ7A9!#Sw;3f(xCZya%3G`}k~yNX?R_I-|5U`Kohwga*?8S@4X z$G7s%>D&Z+RYG#Mc;mEq-=7=f!O`PP@qX;3CelP4yo0(M--o>>8s0(uU<|zU+Bf#L zgw(2plB(?j6vkyezRPhsOl?sP9q~bq8z; zeE7T%NW=HVgyT4L!tsT`QNI(;=wuE&;14H{a|_BBpfEVuR&C%9CvO={_|Cey=BwzN zN)|SF>gM7r?jyaW&ePafS6@<7UtZ>|uCLSTLEfSuyQaR$BQ%tw&k}dLr>sImHG&88 ziE{$F82I4yBj3sKb%fxM<7H9uYJ}jpe5;8Cw}D^EyA+P|n&fukI3MCiI-NX{J1Jbu zxUA>Tzn1y`w_d?4+u?&_D$<&Tre2UR9q%iV)-3Y7@-37OuMKD?j>7Vq6KTz|kL36X zb*L`Vn&odzk82LpnW`!Uzf6A}Eu=Cn5wV`zzKzZZpgDvi`%`208h^(QT9u9DA6Sr$@cvuGxtMJ0M=ePp18O%!E_q#JuL~#!FcD`p$>q zD7UXXl!QLxS*-p(*J8YiFUm766t=x6B6Q=7t>d>Kk>B;dF^%5!g3!?QG=`qXN*+Q3 z9e(5GdoRmd{mCd)qwT@-h~Bexz5r)y621IQk$`9(tQ1UL-HW2~j92vXJ!Z7wLpxis ztIanu9P^DDM_i=~eqTE=-x$=5N6`GTJ8{+Ex-0birp8;k@s64+n=t}e=z0N*_q@ot z@n_ROd4C72a(-?yp|07V1HV@76XhPB1TO^b(YqcoOY1{(W>nO&JR`}GwkHqr5_czL z269#8NTi&Yzgw$!i3ECw-}_Z4p3rgA8Sj^LV>{%J$}dFJoONeJ>r+8M}zdY?Z^FYl-770Pt8mh-!w#PSVm zP-d|fv^H6&K8=^5QH|?A9UUEh7Y?6ixdyEe`FBfjj+SdSI|_m;g^!%$X5eH4YpoyS zTC6*IPJ(?6uEic43%>{A8#m_h@d+s|<;O_!CXA^Bl%HUqCzois6UNj7f)!w%L^*VG z3aYuoG5e3OX2Y*vscSYn6$I-IxeSZ?1C|FLtZVM@onqnmk0S8LBJjQld>{hX%=ZJ= zRM&Y*aQ)Juddo#T~<^51J6ZK3t(FXB_pit)J0&Sx3RkJ z?#0!fRiLoK)3UHKyQ-|wvXoOq=6O5~a~tbn6DER=g8DG=!L?wmrxt!A$)n-@H98nv zmNnl)f|?xfZRHy7-xRK{?M^6MT|35NM+Jxaas4j!n7>nCa&_$}-^;<}$Kv<`hg`Lr zrEt}*9fiSRG>M3ChB$_}ox=a#EWlm)PuLHGBrDf@9i zfg2RZ(1C_+5JXy2%I`mZ)|wJ_j$v{uSqZb7*hu=UHRX-7XOhV0SX0tF^f1#-k#i@^ z6%#eRJgpn&%~b}he-fq+EQ9r#Q`?GfSnm_ZWqr!N5$rYH z^m}jo84zkiwfaqOi`V{m-_wnL+(iPNy77uo*x|SJ`fn(Y%@}Y`9SW|5&04Nh z>Ni+EV+4x_Yg$&mo1l6}bX)dY&;o8)ygw5QwHDHEd&WI`RH<*X__TKjjc;rJpQ6-f zL?QBw9mnnF8qzqW8-G@c*Re-8Ue=Ah-rD(H)1Y)1Z5G`2qThASofBnme(m@*W<A531#XEW<5Mp{*VFnCW-r#XJRfJ-YE%Y93oVwr0L@ zR5wmOkF${AY5Sp{!R98EvU$ewJ488s$5MSC+g9m;Loud!)Lu*GK^9VYZ!jZ;nr^+{ z_F{kANAWASck91w`)I7~q5Hvv@7R*#TY6r=ae{lTu3|B6ApbYu`01Y0?;D9 zb5m9Kl z{1tbd-=1%r%{ShI5t*sO{Y$b)rsM6DZUl~J$$6k-kFEVB(Fi+r<1HbSWw*6&3bu>1 zsCVT%;>>E+yFi~(0We{7igqp^$TvRBH%FV4wHk3+uDB!m7sUE z;tl7gn9mfZ^_lW3&$ws1=G5*Q{)k7p0OCJ^kkkfPL@rH z&okiXIE_Vdmb}3NKD9;rwjF-9^>6(#$|TG*IR0Cdc3|?J?nV@tkH1B^I3X^lZ!Y@g z!mmFJc+eo5;3_)nF(A zIK>@pGT7=Rc~Pg|#oDeAzX6JSzVaP>Q&9%;LBIEz6XrKI=O;9bISRk93BLf!e(p18 zf;%BI`y!0xOvKp|9L{LUJv-=M6QkojyV({M)|yA*@D8*2UwJQ%_ebh)Zi+Ugtc3f` zO^k~CTqTZDhE8_j71!Jl1m8D^(-PAX7w&luuEEuNeKDqh&4-VgXQ`+>0{=d6)Z-*U z`JCsUBFO)QFEzk~k+;_InzO8LtnEc6hUV{0aH`OZZ- zz7`T6BzZZ;RuGr(IFxpO0z6#(;BRfBUHMKjIX+(_K1dBC>j&Sd7*5X_lDAU^#kj(< z!Z-*ge>HHlTR>exj1#OY%OakBiYv4wfxq2k{vuVREeUm7Bm9#t*p?`-in!;I*OYTl zb6HK3hGMl1k<7sMOry7HNwv2sl0?|Okx)tG{>vqj&w(AFNYS6UHFL>*n@edfYOJnZ zQdRBsG&Pi!!=6$}x%b`%Pswt8G8id01!eGi+6DDZutl}fv!JRn)6n-VdOZ~+PPg3|wg=3vd zc|UPH;eLbU^4)=GSFH#64nLlst7-n>e1^i+eEvw`YW>USny5#WpNIe)o^YKe^O>#i zuPVGs;i{hd6|UO-XN6Bv^!!HQxPL9}{!Zblp3@3f>-kEWKQUU(Pcd<<|M80cdlY#! zKZe3pyYih1s2|rR5Mxd zcqJvgE=Wv|OefFytV{Y;Q71P{kzDpJN>AM|s6wXKS%j>ADTsTv*p;0U(76;Re{cn4 z5Ze#a%Jj1RFq)YFqG_E{kQx@(%XpoXSfZO|Y=WXf379Y2@zj|%-TA2Zbpj9J^rc!OB7H2>niqeS6{Jv|Sy=TrjOz_^` z{`32MJh0B*YwfkyT6^v1*>iICU4_nt2_};yu0-itiLlCam15%wmb-WaflbPj(r}+F zO_D|dPhvDR-KGXeRj*+#T7;>bo`{h0pTPiBMQbVKPsP7xcSTst6^?!U&X) zY;9>|C_)R1i10~nM@y2>q^1*@@^$ijojjiiPjGe-itYIyV=@WnxjnWsNQgYU1C0(&T^oNbd+HO4f z{YPj0WjxYI29=NbbmI8wNv5t*(=KPk&hzS|RORx{G|7@WM@mv96aRUD3jh}ZE(Xv= zZO8(ktaN<~@NE{0-Leop{KoP0wRin^yLz_ojsD zPb~gh;J^O%z{XqC3f{7h+tHj~xc{TS{QLLLe>&+q2R9!Jmwu`P+@74?Ok8 zJFoohCo@+cIJ$Y|6=~zHd1%bfK3w(fX_N00%{iu+$F4$1wi~a6Squ0ZTohO;4 zq@__3i})EmT{~^mUv*G+U+b0X5gp5hpo0 z7L|A@PrDWT8B(TXY2gW+{tCkJpby<9=&AxUg7L^<;r5IEe=V0YblYWIf*PDekU_n{ zAin_oWKSs#y3 z;2#e^WN>@9nbK!Sx5V+!ZZ3adu__?M%UcAL$|d|G$|Yeutft{_uH_rsC8AX(z>=LHIvllscCNaNVQ05BgEa> zD%GxUt@pU4+uE92AnmjzugU%*6PL~x|e0@OJXf#jK3pGFct0+HJCg!=k%G^5fw zi}3b~DINNF2NUZY(OxUfBt?=s_24-Z9fO}&+Ha#eVM;j0Nx zAUweEn+PYDg`Z^jQo_kq;cX1Ro^Wzecnibx2`ATtI~jfr;pCEV3&Up;PE93T$?)$G zPOb@;M)TKh0nRS9eB;`|B>NXEEtI5Zsd+q428VVa!wwdE1Tpgzha@d4la|3^{c&xHFV3NIuP3@n^dy@aU+M+5}k_Ql# zmEGY82(og)UWO(=i=Z~!Jf(}VCzsAVzwjysJwfO3t?Ym`V zPv|#fxo^%Qn6QI-RjBbyB$6ATDqnf?E^l5!`}?x5BUA2y*_L&V4=pZB9V}cBJ5879Jq`bW5@+6dB_3WM5e- z3e}Y#tEM1i$i6!=LVb`fd+*4U+ArfZt?>sjJR}%Ae?{w<219pDhmD~nOv1{{BTBUV zvTr5Ei#f@}b2;%`Nj%*L+P@wC80Z#TXXLvcJMODI^Kif1GbfZr9Nt|fbJuI&Fh4)f z))g^#?Lr(3;~=chWs&Ye6N!x7l;U4BJU?Om%R5$)?AN}47oML7mLG!U$bXurNWQWp zDg%o8pk0zy-pt!%_)TI(O@p@{ygTlo{ND!=9-#Kzz78o%kV3h4Y(nbFo5Rg4QzsD0 zmrMCpA|6_y$yb7ui$uPgk&1j*>GFMk3ztg%K*R7q8-IyI6_hA87yekq_1WqqdV~ zn-uNNKVrEdp2kw!vE=3g1_$U=4&Z(#!W%A~a22f930a@`_vt*^*njouD#?_8S zl=FUYUp=sCwd|XG2W9L%wJW8)9P>_!>>V1Guin|ZNS?M+HVvZOtC{5FG6bPl(b#Iu z#{;r&qcyWeo;9DDXC5!@VVhR6QjuyNZ_8-UkT<_TURk*d&e{vTAqQ^MpN^!d^@rI* z_ANqF3bcQUI{0iQs{_028}|vKviI{T>t@T|u!U(;#=T2Kzig2en zu*IR&CGBDBO0p;PQ=VgbXsRa1iTOh7**R#wCLKAUlNeQN&8m(U;^!#LJ<8PNArpKO z%9tWaSOkQxW<_mhnRcTnAsV3lbMB2w35`OIXMn;NPURmb<;RbVkM{c)vDW!&zUNBi z7|Hxot|Vd74JpTE?~A6;zvJ2FdZp_l@_i8q#M-_e)43Hr@L6i(@E$~lUib`+?7OTC z#{5ptEdcRcSvJNHKTchn1ewcflqk6nRfiG2e3s2*v)} zhl;7S`RA-cLSgQK==jPSiL#&=WT%pjMVuX)>}vBbQc6>S+A@xejq=M1Ry;SLo$qV^ z)P5=mjTb{fkv9TW8Hka*B7X;#Rl7_@-ov)ytB*L9qD-f9!Ql$ns$5F~Ep*G-vuG%p z6?oAJPnPY}o|MJD3GbP^UxF8kyvHFS2%sYL5k(nh>sJ&Zd7h~M(4BBlC=K(8&tolB zyA~Riva|b?-e31$3lSJ6Zh;LBpTk-XsBj?DDu=J!TIukuveum1nL;h64$xrkcCZZN z=8)0oyykmmf#AP0QtWr4L(y;{E30tx&;AN!kmPA+iu|*GM`LCNOgyy$YgoP>yIt+` z{u_s=jPQW0OnwjP=JEOH>j`_<6Q;TQ4J=P(?-$Ut7cr-QwN3Wl7yy&Se(D8eoBSB^ zIF)aKlCvk@g7$;nl5aJ4|2Ud)3&s35RXY9lZBAu%CRow!ryipAtlVCTZtDFo#XFn= zy3MI1-w1)Sa_OFY8;v%|Ag`}-`WM`O4ZK~Qbg$DijCBDPP~CZuTjU*vY1vG}-JQhm zw|7F~GjIzk=dZFdiuyuw5`><79IMYCLF=CUN_tR{mHaxfK1BODG79Syv^3dg7vtrq z?Py4^gI86v2Qk^-!3RrwW|6;Q2z{g+B4a-M@p5&{bSfR%F;h-8ci&6-nJ+gXR_w0~ z$o>i&H9V&>bv5!iloo4|@)os1@_>!Gli5|IyjtWdfn9ssKgA?s?w-f2`VxiDWmd_R ztcfePWJ2yX**|%2o+P0o$VxiI!LL(IP_W0woC*ruULng$N2$5{1e$x1mqZ;x4B0zn ze=qqGY?a8^zl==1wDkByRV5V$f20O*9M7B|CRuy zj_=%t0IhQ@v%UA1z>1VNKz|Z3r*h#Q#=r`ZLi1&j@^X=HvFcwtx}3TD9gJ#fWerfw z-!p`q>M+u4VXEe=!{%tQQkE&)+!+81ls;5W_7lSGr#afGJlW5Z`v^04-yW6Uf>^P? zS5ob#X+~zI4zXO5iy#da!}b#(?CB)3+Re6qfanosKP^M~iW%b{*?%#l7O}>bL7M!1 z)R@SACoG1#AUDs^gOF7_$^|P7+?~6 zZAfKJrIR#5S`Vb5(Vzf1AnajeL?mUq6@hAhk@8ZJ?|M!9UKy2s17f1#6#2Jrqgm14 zTZybNKMm$PeG@Ra&bSO}po7#q(Ro+|S&3Fk%u27!f;Vk zcXvX|2t(aO7{!LVM`y#P*iaYFq{p9b8rRj~jP?}IE$Y=9xG0xF)GN%YKR|#g>Oa0# zlvjuvV-R&W6V(tEwfbvCflJT%N^4-K+1*gg@D3A7?#d9!_${bu_ub{9P_{OBVrQYPR=<6oKbu`+D_xvab; z2mfYK0&?(>MR`e18G$mY{c9(O~L@`8D55L-Ex1&iEG?dGk4 zuApa}9K_?{=F{~}?jlb^VeSVGr3TM^SS97i{!OW}5|+Im4$Dd*7E#^_q;}fp^0b#X z2PYvO3}bWXJz42y2}%fh$vb36)H~+xN6tsC%`cG68ux6md%rZ9?|tw*HuUVp10Jm> zBs}j?K;uEJxv89<0?Vx#xr9ujn)nr~i3V$Gt$FoJxqETnB`XuG%8Rw;h9EtiX5dlN z>PzbB4w!oakfiKnPePjyMxYs5i;(oBz<}NCY%b?dC`k>BwxqpFJl8@vQK9 zlDYc|$cEDrWvo+E&G&94&Atofpndp~ufiRbhsU1e35e3ey8|V1n#Vh=vk9vNR;NC_ zgVbOij|WCrMBy(foYrLxaQrVk9OfZaE~V!nBvBicE^8OkWM!+h7a`DX9DPbfpX2C& ziVkx0BNhFWqcqhaZw3>))k-rJP_~5($u!9Tr3ocmhiAZ;Z#$7cu5ZJSV*1eY6)G55K?1pg;l|hIIN0A= z_RZ4qQ90sFDCs&TUH$4Nltcf}Dy0I(CLRllB9uO_aoN1QFVWoyd4KX$(u%>lo99A)WS)v7JtP)svFfq)P_GfIY z?1DQsEHUnV*bzPlx512Go}1e+Kd(DCcY@w-8Qez4aR(b`^T}W}_8zfCIj_;8X_|Qdke4D^GLQ$A%>JoNU_0o}9nRX59 zw?}5RkO3OjFHdS6#Jm`{@xKW^qoHE54@5<>{`6=ZR?+o3^{jWsVHHv<^{i!aScOzu zl$EvAtT?PfYHYQ^Sikz@>|%-bZ?JV=99GflVg@h|{94Bfmm5YD)&Ii`|0Y<^VMdIb3I0`lZqZy~wZ*tQ;+P>C zp`o^l0=BuRY(D?Wt$Itcyw-rv&vHnTNYLSpE#tS3s&%hcR zd-X$$4N{3hi@yzVMDj90zD|3Ijui@H+B=DrWmAXCD|D<76l1j+Sci{ki?3q^qLcax zSYu_0F7Nwe>UNJT} zlxqG%AZ=iV89iXZ_rbURCA{^KV#WSZb<*9kX@I>#=3x1&?ZuAv$65YIkl$bWac;nS z8hc$fbQxs;`PO9Ng_)$g@vfNEN9AQNi>dm-dRIo8`KJMIU>r-wwxgukPxY<9Hlp`% zn)h_V`hNUO>0qL^fK|=khn+|*e;@YObU2Mq8hL#*v1xI7*;I?u8$wzfzme;3dZg2) z(}<+SsY_{b8aA{zJsfCpYU^5@h8zuk5+${1-uJ_MB&YD3)(&uW;$@)B(8_QmvH(gt z*E?wY)jU2?4GQSj8N4@e9J{T@_Yn=dt}pK{$U$pby_4;`jxVs_<)%!$DXH1tR9;lO zP-n;l$(z4Ic{*hUJH}`@^*#}g(!)lvQm(Nv`o(rkcPVL484RjY+JH!hn_|; zLQk6SM1NEJBkPNz3nF0^I^r#8?r0yhf1Z1aw$6)`2nrj)zBz3<>bA^>QTp6~FZs2r z)xPm-gxGa_5@g!)+=4Jv05kCJjI6vZqYWy5mV?JJ3WP1x?P2joYv$(9sjJY-QmN*x zI~PzlpxyPI*j?Wop&n%Jx)Zgvd80Lz`VV*z&7jtm54jJ!lFZOhj7nP(s>n z%5F=0i@5CGL$4uMa43nfB&%8SRS|2wL)QflrLdGyDyfljcUgacda?C9#f|Y;8@xkb zI?@ImX(8w!{zD1S3YDt7CcF0oZq}{#;0KA`q1Tu#q*Uc-4jxQaHMBq}OB@wEn4%`$ zrlz#^sEWye2Vj7z3Yty(RK6^guT2yJPcn>81!T^?*a!Nh~Pu z!Ia>kQE4YIn~}i8(J1JMW_n_(|c+2FU-3?(9nqAr_X)h^Z@4?rC z?#B4qNvcQ zbJoG?s96o2OzY?V9sm#J!S9HxWZ%P98fWp7;3W2gDF)bHHLViSht+5emL}?e3)(i7 zM(?1d0R5$kW+J*>jbPsY?RL-0enV4j86xM@wosoJ`o`Hb+Z61q-jNs*XugyZ$jvgI549_ zf2X78K5Hi;j-GPsT|G|gosJ$wvoJE*DOi9Q4_+|@kmm!Ph@z>`aV zQZZI}J9vCl@WT{aAd-UF$-B|&8D;JcVe1*c<=T}u?7_dK*aKgrg!hBQ-p8Z*Ms_JY z20zDPeE^%_xz11xv`4k5N`-#pIHHL4p#yLI;n!NHbvmYeivyE?R!Bx(WskB`+3o#s z)aHYSAb#_qLwJMOJCpz}54~fUg{De&f!-wqj&S8$Zs|FK&q4JSEc=X~z<%B~C zIh2p>!H*^ehf?gp(D}jegupOj9{`3@;HNB%2Q(xiIq)T5IEDUyPD!xlL@<fdiVb9EZ5S6PrEo6|v4!2Jv_j%{hPbX)1)d`zNEY;zm+NG^v2l zNm0~6=p|9KkkE^x=t4p-jiQSP9Un!VK#yDy9G-&Z9NwOY(u*BR|LdVBS^_i}8WqKt zFnmlDFJ-t|rf|Ai^c#pK{IHZ6nGnUx7@nx&-pDePzuesQ1s0~>NG+Onj^r_Wk8kou zOy-9I{}@Dajy-rdxlnn}q3nkjQ{g&076CT+&K@|EviS_vwYfVDKXMi-?-VM3b|?ps z<3f8doEbbaktPI;%PFiao<^3>Q>aNE#E*h_--ES3DfGd+kw}rUUshf$Qr;{I9<_MC z7-h#Biub&ORWX=QhxmIeFwxT|d%|WUS_62QzJ3?&2)$C}DUP=g`v5)`GsYDtZA?4n-NRRR$c&L1H*OF?ejU%5xow2*pZiV|c7@ z)WJMWvtGumjWz4#3?CQOv4Y_-C$41ph0*jI86Hztp$tUR>=+1G>&HlPDZH0YyrMhY zL?cfY8-v0-F)XU@DboX;?0?Q0fY+6$toI>sC=au@LmYSyqZ2rW>bq#DzH@h%l`1Fp zy2!LH>j1}x5Qct@UBJ%gta}l!pbkYNEAr8RdY8keN^@X6&;tg%DMZT5-SjIxt>|6{ zHowes>->CA?fgZahWRVZUB4ol!`$rw4+Osfbf&qxR>j@~mTUeY^pKXEXhCzrg(PxH zC(pEsTd=m- z|0~)tHB)WZiQAUXYRBO};`cKw#s2k+m+&;TRm9dv;ludlmUd3OXXcsj-G?z5+fY5& zTT)J81MB~?4J@|4Fh9Krlk;TEYS?IT(9;3omm2UXT6`3|Z+<=y<;R#XQI{SZy4ZkU zV!$UEaGie0)9DAU)1Pe6k9B}fKX9FX;5z-lb^3wp^aI!F2d>kfWYCXkN2edSPCsy+ ze&9O&z;*h8>+}QH=}$E1$26$Z4_v1oxK2NCoqpgt{lInlf$Q`q81!SMqSFstrysaZ zKX9FX;5z-lb^3wp^qUO&vGt+T4_v1oxK2NCoqpgt{lInlfot{CGL)LXIuDtjMt5QA zH8@kR!I^pu&eUsgre1?H^%|V17dZ7#CV;lFw|FDy-*2n^yEg;2K+GtKHnhk9z*(V27I{z zw;S;32K*ueo?yU_rt9th#DMQL;J-KEKQ-V!1Ae8peBQ`J^S$)<6`0R^@!^j+{e6s< zAN_r-p}l-;NPokC_ZjeQ2E5yV8{5YXhV-ip_+$f~Xu!h;|Gs9xpETeP8t{zYzW~h(14ES>f{O1PzUIX5xl~2F-6e(}h4?g(Q$5$_5pTd|yVVPa|sz^EI zoc4G2@si+IiJ>Xa;(5CJsK=6fK&;=L%4w%^%Ap*$M<)D*zRDn9{cihV*-IY)iT+W? zme}uGCwHOg&^Kbhf#_M63Gc??V^;1~d~V8uZ&5Y3j+Um@NS9A-yZjny>Z}?|R!+y% zoS7BVq^UD<=d@X_u}D+fBzz4}T1{VEl4`3O>l-#mjm=>-d;noT!ePLj&qpE?c0?i{Abc2bAD|pCAGBLu zjzq5eQzY^!!t(+BFGV7o01vzvi98B?^s=_9HSTLHQ`;;nn_I|+wwp&=*tJAOui@y7 zI?G0jY7a{;t7~3wA?qxS?luyVEf{ZQj8p{1xUjjkvC3n?SH$oQF-ujOg{6=$-BmS~ z=2}Zj1HKPt@whuY*`w*_-E&>P_-iCGcL4j5uSFv12=4%12FL#?}uJM7(RO#upV#}xX^vgTan0lfc1D$foMw*ej6Zo z{}X9~_j`!1=C~EI1^x3sM4n`u60X70k02aV!+^&}p z{*=f6in@Oapa5{?(h2$bNv$pz z=skeP3^o>{yzgk*lh)>M;(Fizv;O!J{>{R;^c=>6ctB~Hn)FmnoalsWX<8Y>7<;rh z#VdGzN~1XCjmJm4dEgZRUGN#xh0J~~$Cys|xzhT$PU4A| zSJ1W_(t9~BLc#aXge2pimD7W~1a*K4z(1>BM&7IwXd{4B!0>VS954vz2lN5919|~H zfDS+%paLKR@&H+YOh77t-bV}p1_AwmKEQTBFQ5m|0jL910AxTOAPbNQNCgbz9l#J^ z5YP|k18fKM0(t-)fI2`0KnCOivH+QYRKPG^1_?SNiD51<232dDtZfIL7JAQO-Z82%Xf0fT^kKp$W`pcl{s=m69K zDgZJd50C}O1f&9nVN(b&2}KH{eV8e zc0ezn2SE1I-(3%*tRcW4pdZi&*be9g^Z+^lb$|+h49Ejy0WtxpfMLi90R{p6fIh%> zKrf&NU|h>h0O0}y@j~Di0Wtv-c^V!aB|Mi%coxCeQ`I*n=?ySRyediWdC^yCB~M$m zRNav$RX5bO)k%$w9g@4Xu}!MYom(x{Hdf81+bn5a71r77TB;iw+Z%4HxlLN#Sf4A^ z;S;m1o<^y)rp=9|JR~%f7)++cx)1+}hl;C_3Afs|G}K&#scH)^!lf zq}!a_nYBEuuHg}Uu2xNH5lO4pa|(=5lh!rxNIfhSG}xz!3i<1r@ZnrF*XnvtRl^#= z)6(2h-QDCp$Qno2^p?7cXe}9jVq?iH5>7kHZIGx8m<%ZbuBa5(-!i0q^iaa zo`{I29?l~Q((|M?xV>#n2Py)2+v=($)gU})ty>Kr*Rn~e7Q((aA`uV5UaaZpJ82zQ zcRYo#|4<~7lmvN)F-{=t#TY&vA&plygo6ls5Yk2C0bQosmrACN4AUiJQ&P8>QZk4> z2~he3o)w6JU-9`R$%=I14?G%)JW0Ii84J@huQ!ibpV}#1ck#UM%(7liWXkUV$nY7x z+AA*X@ksP8=n3efSB~i-8a;bY2QRb1k)BZjybCZ0zPI5!$)28ZPl7!?)0K@ zot_DbJw0{tn1nw7kr`4t#*O$w7I*66i=*_CF;0jZ0<1#)eCur43!}2-F$wFU`4*2^ zgt)4wV$2euA9Bck`nBJn zJa0--`anwJ17k*~=YeKV&jJs4ktaVrmFbxd5!42Uw_~2+_Hcg|!Jo&XWoF#!96`q` zq&^pkT#CG^{j1WcF3CO%(#9eUFWRt6#(g&DXWwd%*$esH-i1+nuTS5WnDA6wbMtB6 zQtE`P`2*NvAX{-|0k)F-eUZq!M9{W}99?^0z6*f&Iq&pcn|tuNJGm*yaxTTpW97+zzLcK>mN5|jM-8cwM8ad zWU9yFbX#k@I%N8`LXHeMDB3sIHy-%L1K)Vy8xMTrfp0wU|A7Z8=>Z#;g@=53Ac=6S znjAeph@Q*oN?NLh;(1-1=W&Tjmc-inVvdV*J!p+imq`EYOr)9cUcPw1>)Y&-=>=U} zVjb7Q*D~Vwp>)nq>ma&l?|?4j-U82t=TQqw7i*Lg42wN~aCPi?ijq!nMS>opzca)o z?54kdpo^2E`q`QkbiwxpetIE3urtybj&J7~Be8U1lkjN7_?Pqa&pDpNQvdZgac-PZ z@`b$Ozs1A3JY2}b#xiAkR)1rccYb;sIR<}2K z+AUXQ&&kf2F{_*aXqS5W=xF=Z)6YH!jM5V&R8pLJN|eS)PsXLE zOM$rbv(GV8Cw6JG<(0qV+<)S}XV|r<`R&(_t&h#4Sk8`@1Z$y?LA|{NYGWS3Ek*)!NDNgCD%(I;H1mO=}+EfVYryLmN9yUG;}i~vwbIu zxi~%b7L_i#M?II*$>q@g3tc1mb3NlfPkMnpl&ier9?$-6@JlGKvHd^DBsJ>EHcw3ox1rVzox ziHv^s`Gl8&Zqae7$O6#gor9N7dmM54^$jEFtr>xS2k3Nep|QMYSh>y~_wF7+&QC_5 zKLvWc^A&fFz`vi-&p!X~=m`8{;fHwVE=~kJp8sbszn$&q`Jl%;?{P7cgZ{`XN1TgD zpTnklH=c|51Ne>3nKYgcd7hBN$Biqw32QmMl*b@_=W6cf^lewE%xpgo(V-FKd@=%k6c%>mALBWb6G69V>=4meoZom3 z(go2R9iq{2S-7|fY`B-E>EMYnhuU^!-0%7&8{`<#7I{S&PQx> zRkh=nspiI(2DisulYQ0PtMlSBv4bgHRjsX68`!&f8>HG+9P#L?X>V-YfGipeKYP`C zbgb|Vy)@{;yN0lAZDC`JXG83SNe%9#w+h)=kOgHc$_wP|tKbP9%jFsIqZs3GxfU+9 z7ZOYK>ev~c(GxrQ;h;8~IB=4Vmi+G=R zhmPvW{18y%S*0B{Ne{3i_!Bo$1_VJqHBvHfRrTT2TgGSZ!PK^xzo5M%R zs{i4+qx^tX^~hE_%{68ZI~0_in0n4*N$FhJSSIqGddRDu_OCd+RDWKqUcTXAQ}wu6 zJ&TmxwxQ8ewHl$PRSoMzjEzMtQg&0b$DM7@FPh=0TEnq5P3_sM+v{;YczunOO;}wO zUKhx&+0X=eYUpWIQ`Wg#+vpWv#>NpB(pudORg{6pS{gi3Hajjh8`11F%|PiTRw3s(6WvqV%iQ4?p zeGC4;^`tg4;u#zl;Z{R_vA-cgVXqJ)a1s8yA-{NT7h!&($f<@xub}?IkYDVhicst) z3VvhxALaQ){aJW}5n(dlFA(`HBErMpAte8a{NlMzgfAHQjr!?}Bij68pGJhD{|GU{ zZvx+o2rcb-H;eA)v^1(5Mt*^da6j0nh$6pu?(O(*=6@e~sqKmUVt=TU=RZM(!zJ3M z&@1YZ_BDt_8m^e*y?@Gw%e`J?+yEov4^G^ZL7dIk9eA|y-b7tf;> zohMhJQTrah!97PAn;J+pJt#7Y1&Y<9W84q*Dv!1O!LeZKPg$*uFc=O cLB$k9gA;lM@Awh&Uv{U;aYium(3t=K0cGL6FaQ7m literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesConfig.cmake.in b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesConfig.cmake.in new file mode 100644 index 0000000..e0bf10e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesConfig.cmake.in @@ -0,0 +1,3 @@ +# CpuFeatures CMake configuration file + +include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesTargets.cmake") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in new file mode 100644 index 0000000..5a53ffd --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in @@ -0,0 +1,3 @@ +# CpuFeaturesNdkCompat CMake configuration file + +include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesNdkCompatTargets.cmake") diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/README.md b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/README.md new file mode 100644 index 0000000..b6baeaa --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/README.md @@ -0,0 +1,28 @@ +# CMake build instructions + +## Recommended usage : Incorporating cpu_features into a CMake project + + For API / ABI compatibility reasons, it is recommended to build and use + cpu_features in a subdirectory of your project or as an embedded dependency. + + This is similar to the recommended usage of the googletest framework + ( https://github.com/google/googletest/blob/master/googletest/README.md ) + + Build and use step-by-step + + + 1- Download cpu_features and copy it in a sub-directory in your project. + or add cpu_features as a git-submodule in your project + + 2- You can then use the cmake command `add_subdirectory()` to include + cpu_features directly and use the `cpu_features` target in your project. + + 3- Add the `cpu_features` target to the `target_link_libraries()` section of + your executable or of your library. + +## Enabling tests + + CMake default options for cpu_features is Release built type with tests + disabled. To enable testing set cmake `BUILD_TESTING` variable to `ON`, + [.travis.yml](../.travis.yml) and [appveyor.yml](../appveyor.yml) have up to + date examples. diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/googletest.CMakeLists.txt.in b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/googletest.CMakeLists.txt.in new file mode 100644 index 0000000..d60a33e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/cmake/googletest.CMakeLists.txt.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG master + SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) \ No newline at end of file diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h new file mode 100644 index 0000000..b7cc046 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_cache_info.h @@ -0,0 +1,54 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_ + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef enum { + CPU_FEATURE_CACHE_NULL = 0, + CPU_FEATURE_CACHE_DATA = 1, + CPU_FEATURE_CACHE_INSTRUCTION = 2, + CPU_FEATURE_CACHE_UNIFIED = 3, + CPU_FEATURE_CACHE_TLB = 4, + CPU_FEATURE_CACHE_DTLB = 5, + CPU_FEATURE_CACHE_STLB = 6, + CPU_FEATURE_CACHE_PREFETCH = 7 +} CacheType; + +typedef struct { + int level; + CacheType cache_type; + int cache_size; // Cache size in bytes + int ways; // Associativity, 0 undefined, 0xFF fully associative + int line_size; // Cache line size in bytes + int tlb_entries; // number of entries for TLB + int partitioning; // number of lines per sector +} CacheLevelInfo; + +// Increase this value if more cache levels are needed. +#ifndef CPU_FEATURES_MAX_CACHE_LEVEL +#define CPU_FEATURES_MAX_CACHE_LEVEL 10 +#endif +typedef struct { + int size; + CacheLevelInfo levels[CPU_FEATURES_MAX_CACHE_LEVEL]; +} CacheInfo; + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h new file mode 100644 index 0000000..fae9f70 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpu_features_macros.h @@ -0,0 +1,212 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ +#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ + +//////////////////////////////////////////////////////////////////////////////// +// Architectures +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__pnacl__) || defined(__CLR_VER) +#define CPU_FEATURES_ARCH_VM +#endif + +#if (defined(_M_IX86) || defined(__i386__)) && !defined(CPU_FEATURES_ARCH_VM) +#define CPU_FEATURES_ARCH_X86_32 +#endif + +#if (defined(_M_X64) || defined(__x86_64__)) && !defined(CPU_FEATURES_ARCH_VM) +#define CPU_FEATURES_ARCH_X86_64 +#endif + +#if defined(CPU_FEATURES_ARCH_X86_32) || defined(CPU_FEATURES_ARCH_X86_64) +#define CPU_FEATURES_ARCH_X86 +#endif + +#if (defined(__arm__) || defined(_M_ARM)) +#define CPU_FEATURES_ARCH_ARM +#endif + +#if defined(__aarch64__) +#define CPU_FEATURES_ARCH_AARCH64 +#endif + +#if (defined(CPU_FEATURES_ARCH_AARCH64) || defined(CPU_FEATURES_ARCH_ARM)) +#define CPU_FEATURES_ARCH_ANY_ARM +#endif + +#if defined(__mips64) +#define CPU_FEATURES_ARCH_MIPS64 +#endif + +#if defined(__mips__) && !defined(__mips64) // mips64 also declares __mips__ +#define CPU_FEATURES_ARCH_MIPS32 +#endif + +#if defined(CPU_FEATURES_ARCH_MIPS32) || defined(CPU_FEATURES_ARCH_MIPS64) +#define CPU_FEATURES_ARCH_MIPS +#endif + +#if defined(__powerpc__) +#define CPU_FEATURES_ARCH_PPC +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Os +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__linux__) +#define CPU_FEATURES_OS_LINUX_OR_ANDROID +#endif + +#if defined(__ANDROID__) +#define CPU_FEATURES_OS_ANDROID +#endif + +#if (defined(_WIN64) || defined(_WIN32)) +#define CPU_FEATURES_OS_WINDOWS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Compilers +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__clang__) +#define CPU_FEATURES_COMPILER_CLANG +#endif + +#if defined(__GNUC__) && !defined(__clang__) +#define CPU_FEATURES_COMPILER_GCC +#endif + +#if defined(_MSC_VER) +#define CPU_FEATURES_COMPILER_MSC +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cpp +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__cplusplus) +#define CPU_FEATURES_START_CPP_NAMESPACE \ + namespace cpu_features { \ + extern "C" { +#define CPU_FEATURES_END_CPP_NAMESPACE \ + } \ + } +#else +#define CPU_FEATURES_START_CPP_NAMESPACE +#define CPU_FEATURES_END_CPP_NAMESPACE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Compiler flags +//////////////////////////////////////////////////////////////////////////////// + +// Use the following to check if a feature is known to be available at +// compile time. See README.md for an example. +#if defined(CPU_FEATURES_ARCH_X86) + +#if defined(__AES__) +#define CPU_FEATURES_COMPILED_X86_AES 1 +#else +#define CPU_FEATURES_COMPILED_X86_AES 0 +#endif // defined(__AES__) + +#if defined(__F16C__) +#define CPU_FEATURES_COMPILED_X86_F16C 1 +#else +#define CPU_FEATURES_COMPILED_X86_F16C 0 +#endif // defined(__F16C__) + +#if defined(__BMI__) +#define CPU_FEATURES_COMPILED_X86_BMI 1 +#else +#define CPU_FEATURES_COMPILED_X86_BMI 0 +#endif // defined(__BMI__) + +#if defined(__BMI2__) +#define CPU_FEATURES_COMPILED_X86_BMI2 1 +#else +#define CPU_FEATURES_COMPILED_X86_BMI2 0 +#endif // defined(__BMI2__) + +#if (defined(__SSE__) || (_M_IX86_FP >= 1)) +#define CPU_FEATURES_COMPILED_X86_SSE 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE 0 +#endif + +#if (defined(__SSE2__) || (_M_IX86_FP >= 2)) +#define CPU_FEATURES_COMPILED_X86_SSE2 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE2 0 +#endif + +#if defined(__SSE3__) +#define CPU_FEATURES_COMPILED_X86_SSE3 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE3 0 +#endif // defined(__SSE3__) + +#if defined(__SSSE3__) +#define CPU_FEATURES_COMPILED_X86_SSSE3 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSSE3 0 +#endif // defined(__SSSE3__) + +#if defined(__SSE4_1__) +#define CPU_FEATURES_COMPILED_X86_SSE4_1 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE4_1 0 +#endif // defined(__SSE4_1__) + +#if defined(__SSE4_2__) +#define CPU_FEATURES_COMPILED_X86_SSE4_2 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE4_2 0 +#endif // defined(__SSE4_2__) + +#if defined(__AVX__) +#define CPU_FEATURES_COMPILED_X86_AVX 1 +#else +#define CPU_FEATURES_COMPILED_X86_AVX 0 +#endif // defined(__AVX__) + +#if defined(__AVX2__) +#define CPU_FEATURES_COMPILED_X86_AVX2 1 +#else +#define CPU_FEATURES_COMPILED_X86_AVX2 0 +#endif // defined(__AVX2__) + +#endif // defined(CPU_FEATURES_ARCH_X86) + +#if defined(CPU_FEATURES_ARCH_ANY_ARM) +#if defined(__ARM_NEON__) +#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1 +#else +#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0 +#endif // defined(__ARM_NEON__) +#endif // defined(CPU_FEATURES_ARCH_ANY_ARM) + +#if defined(CPU_FEATURES_ARCH_MIPS) +#if defined(__mips_msa) +#define CPU_FEATURES_COMPILED_MIPS_MSA 1 +#else +#define CPU_FEATURES_COMPILED_MIPS_MSA 0 +#endif // defined(__mips_msa) +#endif // defined(CPU_FEATURES_ARCH_MIPS) + +#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_aarch64.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_aarch64.h new file mode 100644 index 0000000..bc2a5dc --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_aarch64.h @@ -0,0 +1,156 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + int fp : 1; // Floating-point. + int asimd : 1; // Advanced SIMD. + int evtstrm : 1; // Generic timer generated events. + int aes : 1; // Hardware-accelerated Advanced Encryption Standard. + int pmull : 1; // Polynomial multiply long. + int sha1 : 1; // Hardware-accelerated SHA1. + int sha2 : 1; // Hardware-accelerated SHA2-256. + int crc32 : 1; // Hardware-accelerated CRC-32. + int atomics : 1; // Armv8.1 atomic instructions. + int fphp : 1; // Half-precision floating point support. + int asimdhp : 1; // Advanced SIMD half-precision support. + int cpuid : 1; // Access to certain ID registers. + int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract. + int jscvt : 1; // Support for JavaScript conversion. + int fcma : 1; // Floating point complex numbers. + int lrcpc : 1; // Support for weaker release consistency. + int dcpop : 1; // Data persistence writeback. + int sha3 : 1; // Hardware-accelerated SHA3. + int sm3 : 1; // Hardware-accelerated SM3. + int sm4 : 1; // Hardware-accelerated SM4. + int asimddp : 1; // Dot product instruction. + int sha512 : 1; // Hardware-accelerated SHA512. + int sve : 1; // Scalable Vector Extension. + int asimdfhm : 1; // Additional half-precision instructions. + int dit : 1; // Data independent timing. + int uscat : 1; // Unaligned atomics support. + int ilrcpc : 1; // Additional support for weaker release consistency. + int flagm : 1; // Flag manipulation instructions. + int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit. + int sb : 1; // Speculation barrier. + int paca : 1; // Address authentication. + int pacg : 1; // Generic authentication. + int dcpodp : 1; // Data cache clean to point of persistence. + int sve2 : 1; // Scalable Vector Extension (version 2). + int sveaes : 1; // SVE AES instructions. + int svepmull : 1; // SVE polynomial multiply long instructions. + int svebitperm : 1; // SVE bit permute instructions. + int svesha3 : 1; // SVE SHA3 instructions. + int svesm4 : 1; // SVE SM4 instructions. + int flagm2 : 1; // Additional flag manipulation instructions. + int frint : 1; // Floating point to integer rounding. + int svei8mm : 1; // SVE Int8 matrix multiplication instructions. + int svef32mm : 1; // SVE FP32 matrix multiplication instruction. + int svef64mm : 1; // SVE FP64 matrix multiplication instructions. + int svebf16 : 1; // SVE BFloat16 instructions. + int i8mm : 1; // Int8 matrix multiplication instructions. + int bf16 : 1; // BFloat16 instructions. + int dgh : 1; // Data Gathering Hint instruction. + int rng : 1; // True random number generator support. + int bti : 1; // Branch target identification. + + // Make sure to update Aarch64FeaturesEnum below if you add a field here. +} Aarch64Features; + +typedef struct { + Aarch64Features features; + int implementer; + int variant; + int part; + int revision; +} Aarch64Info; + +Aarch64Info GetAarch64Info(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum { + AARCH64_FP, + AARCH64_ASIMD, + AARCH64_EVTSTRM, + AARCH64_AES, + AARCH64_PMULL, + AARCH64_SHA1, + AARCH64_SHA2, + AARCH64_CRC32, + AARCH64_ATOMICS, + AARCH64_FPHP, + AARCH64_ASIMDHP, + AARCH64_CPUID, + AARCH64_ASIMDRDM, + AARCH64_JSCVT, + AARCH64_FCMA, + AARCH64_LRCPC, + AARCH64_DCPOP, + AARCH64_SHA3, + AARCH64_SM3, + AARCH64_SM4, + AARCH64_ASIMDDP, + AARCH64_SHA512, + AARCH64_SVE, + AARCH64_ASIMDFHM, + AARCH64_DIT, + AARCH64_USCAT, + AARCH64_ILRCPC, + AARCH64_FLAGM, + AARCH64_SSBS, + AARCH64_SB, + AARCH64_PACA, + AARCH64_PACG, + AARCH64_DCPODP, + AARCH64_SVE2, + AARCH64_SVEAES, + AARCH64_SVEPMULL, + AARCH64_SVEBITPERM, + AARCH64_SVESHA3, + AARCH64_SVESM4, + AARCH64_FLAGM2, + AARCH64_FRINT, + AARCH64_SVEI8MM, + AARCH64_SVEF32MM, + AARCH64_SVEF64MM, + AARCH64_SVEBF16, + AARCH64_I8MM, + AARCH64_BF16, + AARCH64_DGH, + AARCH64_RNG, + AARCH64_BTI, + AARCH64_LAST_, +} Aarch64FeaturesEnum; + +int GetAarch64FeaturesEnumValue(const Aarch64Features* features, + Aarch64FeaturesEnum value); + +const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_AARCH64) +#error "Including cpuinfo_aarch64.h from a non-aarch64 target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_arm.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_arm.h new file mode 100644 index 0000000..97a105c --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_arm.h @@ -0,0 +1,121 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ + +#include // uint32_t + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + int swp : 1; // SWP instruction (atomic read-modify-write) + int half : 1; // Half-word loads and stores + int thumb : 1; // Thumb (16-bit instruction set) + int _26bit : 1; // "26 Bit" Model (Processor status register folded into + // program counter) + int fastmult : 1; // 32x32->64-bit multiplication + int fpa : 1; // Floating point accelerator + int vfp : 1; // Vector Floating Point. + int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all + // others above) + int java : 1; // Jazelle (Java bytecode accelerator) + int iwmmxt : 1; // Intel Wireless MMX Technology. + int crunch : 1; // MaverickCrunch coprocessor + int thumbee : 1; // ThumbEE + int neon : 1; // Advanced SIMD. + int vfpv3 : 1; // VFP version 3 + int vfpv3d16 : 1; // VFP version 3 with 16 D-registers + int tls : 1; // TLS register + int vfpv4 : 1; // VFP version 4 with fast context switching + int idiva : 1; // SDIV and UDIV hardware division in ARM mode. + int idivt : 1; // SDIV and UDIV hardware division in Thumb mode. + int vfpd32 : 1; // VFP with 32 D-registers + int lpae : 1; // Large Physical Address Extension (>4GB physical memory on + // 32-bit architecture) + int evtstrm : 1; // kernel event stream using generic architected timer + int aes : 1; // Hardware-accelerated Advanced Encryption Standard. + int pmull : 1; // Polynomial multiply long. + int sha1 : 1; // Hardware-accelerated SHA1. + int sha2 : 1; // Hardware-accelerated SHA2-256. + int crc32 : 1; // Hardware-accelerated CRC-32. + + // Make sure to update ArmFeaturesEnum below if you add a field here. +} ArmFeatures; + +typedef struct { + ArmFeatures features; + int implementer; + int architecture; + int variant; + int part; + int revision; +} ArmInfo; + +// TODO(user): Add macros to know which features are present at compile +// time. + +ArmInfo GetArmInfo(void); + +// Compute CpuId from ArmInfo. +uint32_t GetArmCpuId(const ArmInfo* const info); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum { + ARM_SWP, + ARM_HALF, + ARM_THUMB, + ARM_26BIT, + ARM_FASTMULT, + ARM_FPA, + ARM_VFP, + ARM_EDSP, + ARM_JAVA, + ARM_IWMMXT, + ARM_CRUNCH, + ARM_THUMBEE, + ARM_NEON, + ARM_VFPV3, + ARM_VFPV3D16, + ARM_TLS, + ARM_VFPV4, + ARM_IDIVA, + ARM_IDIVT, + ARM_VFPD32, + ARM_LPAE, + ARM_EVTSTRM, + ARM_AES, + ARM_PMULL, + ARM_SHA1, + ARM_SHA2, + ARM_CRC32, + ARM_LAST_, +} ArmFeaturesEnum; + +int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value); + +const char* GetArmFeaturesEnumName(ArmFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_ARM) +#error "Including cpuinfo_arm.h from a non-arm target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_mips.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_mips.h new file mode 100644 index 0000000..642fd9e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_mips.h @@ -0,0 +1,60 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + int msa : 1; // MIPS SIMD Architecture + // https://www.mips.com/products/architectures/ase/simd/ + int eva : 1; // Enhanced Virtual Addressing + // https://www.mips.com/products/architectures/mips64/ + int r6 : 1; // True if is release 6 of the processor. + + // Make sure to update MipsFeaturesEnum below if you add a field here. +} MipsFeatures; + +typedef struct { + MipsFeatures features; +} MipsInfo; + +MipsInfo GetMipsInfo(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum { + MIPS_MSA, + MIPS_EVA, + MIPS_R6, + MIPS_LAST_, +} MipsFeaturesEnum; + +int GetMipsFeaturesEnumValue(const MipsFeatures* features, + MipsFeaturesEnum value); + +const char* GetMipsFeaturesEnumName(MipsFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_MIPS) +#error "Including cpuinfo_mips.h from a non-mips target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_ppc.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_ppc.h new file mode 100644 index 0000000..f691194 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_ppc.h @@ -0,0 +1,146 @@ +// Copyright 2018 IBM +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" +#include "internal/hwcaps.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + int ppc32 : 1; + int ppc64 : 1; + int ppc601 : 1; + int altivec : 1; + int fpu : 1; + int mmu : 1; + int mac_4xx : 1; + int unifiedcache : 1; + int spe : 1; + int efpsingle : 1; + int efpdouble : 1; + int no_tb : 1; + int power4 : 1; + int power5 : 1; + int power5plus : 1; + int cell : 1; + int booke : 1; + int smt : 1; + int icachesnoop : 1; + int arch205 : 1; + int pa6t : 1; + int dfp : 1; + int power6ext : 1; + int arch206 : 1; + int vsx : 1; + int pseries_perfmon_compat : 1; + int truele : 1; + int ppcle : 1; + int arch207 : 1; + int htm : 1; + int dscr : 1; + int ebb : 1; + int isel : 1; + int tar : 1; + int vcrypto : 1; + int htm_nosc : 1; + int arch300 : 1; + int ieee128 : 1; + int darn : 1; + int scv : 1; + int htm_no_suspend : 1; + + // Make sure to update PPCFeaturesEnum below if you add a field here. +} PPCFeatures; + +typedef struct { + PPCFeatures features; +} PPCInfo; + +// This function is guaranteed to be malloc, memset and memcpy free. +PPCInfo GetPPCInfo(void); + +typedef struct { + char platform[64]; // 0 terminated string + char model[64]; // 0 terminated string + char machine[64]; // 0 terminated string + char cpu[64]; // 0 terminated string + PlatformType type; +} PPCPlatformStrings; + +PPCPlatformStrings GetPPCPlatformStrings(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum { + PPC_32, /* 32 bit mode execution */ + PPC_64, /* 64 bit mode execution */ + PPC_601_INSTR, /* Old POWER ISA */ + PPC_HAS_ALTIVEC, /* SIMD Unit*/ + PPC_HAS_FPU, /* Floating Point Unit */ + PPC_HAS_MMU, /* Memory management unit */ + PPC_HAS_4xxMAC, + PPC_UNIFIED_CACHE, /* Unified instruction and data cache */ + PPC_HAS_SPE, /* Signal processing extention unit */ + PPC_HAS_EFP_SINGLE, /* SPE single precision fpu */ + PPC_HAS_EFP_DOUBLE, /* SPE double precision fpu */ + PPC_NO_TB, /* No timebase */ + PPC_POWER4, + PPC_POWER5, + PPC_POWER5_PLUS, + PPC_CELL, /* Cell broadband engine */ + PPC_BOOKE, /* Embedded ISA */ + PPC_SMT, /* Simultaneous multi-threading */ + PPC_ICACHE_SNOOP, + PPC_ARCH_2_05, /* ISA 2.05 - POWER6 */ + PPC_PA6T, /* PA Semi 6T core ISA */ + PPC_HAS_DFP, /* Decimal floating point unit */ + PPC_POWER6_EXT, + PPC_ARCH_2_06, /* ISA 2.06 - POWER7 */ + PPC_HAS_VSX, /* Vector-scalar extension */ + PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance + monitoring events */ + PPC_TRUE_LE, + PPC_PPC_LE, + PPC_ARCH_2_07, /* ISA 2.07 - POWER8 */ + PPC_HTM, /* Hardware Transactional Memory */ + PPC_DSCR, /* Data stream control register */ + PPC_EBB, /* Event base branching */ + PPC_ISEL, /* Integer select instructions */ + PPC_TAR, /* Target address register */ + PPC_VEC_CRYPTO, /* Vector cryptography instructions */ + PPC_HTM_NOSC, /* Transactions aborted when syscall made*/ + PPC_ARCH_3_00, /* ISA 3.00 - POWER9 */ + PPC_HAS_IEEE128, /* VSX IEEE Binary Float 128-bit */ + PPC_DARN, /* Deliver a random number instruction */ + PPC_SCV, /* scv syscall */ + PPC_HTM_NO_SUSPEND, /* TM w/out suspended state */ + PPC_LAST_, +} PPCFeaturesEnum; + +int GetPPCFeaturesEnumValue(const PPCFeatures* features, PPCFeaturesEnum value); + +const char* GetPPCFeaturesEnumName(PPCFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_PPC) +#error "Including cpuinfo_ppc.h from a non-ppc target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h new file mode 100644 index 0000000..c21a46a --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/cpuinfo_x86.h @@ -0,0 +1,231 @@ +// Copyright 2017 Google Inc. +// Copyright 2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features. +// The field names are based on the short name provided in the wikipedia tables. +typedef struct { + int fpu : 1; + int tsc : 1; + int cx8 : 1; + int clfsh : 1; + int mmx : 1; + int aes : 1; + int erms : 1; + int f16c : 1; + int fma4 : 1; + int fma3 : 1; + int vaes : 1; + int vpclmulqdq : 1; + int bmi1 : 1; + int hle : 1; + int bmi2 : 1; + int rtm : 1; + int rdseed : 1; + int clflushopt : 1; + int clwb : 1; + + int sse : 1; + int sse2 : 1; + int sse3 : 1; + int ssse3 : 1; + int sse4_1 : 1; + int sse4_2 : 1; + int sse4a : 1; + + int avx : 1; + int avx2 : 1; + + int avx512f : 1; + int avx512cd : 1; + int avx512er : 1; + int avx512pf : 1; + int avx512bw : 1; + int avx512dq : 1; + int avx512vl : 1; + int avx512ifma : 1; + int avx512vbmi : 1; + int avx512vbmi2 : 1; + int avx512vnni : 1; + int avx512bitalg : 1; + int avx512vpopcntdq : 1; + int avx512_4vnniw : 1; + int avx512_4vbmi2 : 1; + int avx512_second_fma : 1; + int avx512_4fmaps : 1; + int avx512_bf16 : 1; + int avx512_vp2intersect : 1; + int amx_bf16 : 1; + int amx_tile : 1; + int amx_int8 : 1; + + int pclmulqdq : 1; + int smx : 1; + int sgx : 1; + int cx16 : 1; // aka. CMPXCHG16B + int sha : 1; + int popcnt : 1; + int movbe : 1; + int rdrnd : 1; + + int dca : 1; + int ss : 1; + // Make sure to update X86FeaturesEnum below if you add a field here. +} X86Features; + +typedef struct { + X86Features features; + int family; + int model; + int stepping; + char vendor[13]; // 0 terminated string +} X86Info; + +// Calls cpuid and returns an initialized X86info. +// This function is guaranteed to be malloc, memset and memcpy free. +X86Info GetX86Info(void); + +// Returns cache hierarchy informations. +// Can call cpuid multiple times. +// Only works on Intel CPU at the moment. +// This function is guaranteed to be malloc, memset and memcpy free. +CacheInfo GetX86CacheInfo(void); + +typedef enum { + X86_UNKNOWN, + INTEL_CORE, // CORE + INTEL_PNR, // PENRYN + INTEL_NHM, // NEHALEM + INTEL_ATOM_BNL, // BONNELL + INTEL_WSM, // WESTMERE + INTEL_SNB, // SANDYBRIDGE + INTEL_IVB, // IVYBRIDGE + INTEL_ATOM_SMT, // SILVERMONT + INTEL_HSW, // HASWELL + INTEL_BDW, // BROADWELL + INTEL_SKL, // SKYLAKE + INTEL_ATOM_GMT, // GOLDMONT + INTEL_KBL, // KABY LAKE + INTEL_CFL, // COFFEE LAKE + INTEL_WHL, // WHISKEY LAKE + INTEL_CNL, // CANNON LAKE + INTEL_ICL, // ICE LAKE + INTEL_TGL, // TIGER LAKE + INTEL_SPR, // SAPPHIRE RAPIDS + AMD_HAMMER, // K8 + AMD_K10, // K10 + AMD_BOBCAT, // K14 + AMD_BULLDOZER, // K15 + AMD_JAGUAR, // K16 + AMD_ZEN, // K17 +} X86Microarchitecture; + +// Returns the underlying microarchitecture by looking at X86Info's vendor, +// family and model. +X86Microarchitecture GetX86Microarchitecture(const X86Info* info); + +// Calls cpuid and fills the brand_string. +// - brand_string *must* be of size 49 (beware of array decaying). +// - brand_string will be zero terminated. +// - This function calls memcpy. +void FillX86BrandString(char brand_string[49]); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum { + X86_FPU, + X86_TSC, + X86_CX8, + X86_CLFSH, + X86_MMX, + X86_AES, + X86_ERMS, + X86_F16C, + X86_FMA4, + X86_FMA3, + X86_VAES, + X86_VPCLMULQDQ, + X86_BMI1, + X86_HLE, + X86_BMI2, + X86_RTM, + X86_RDSEED, + X86_CLFLUSHOPT, + X86_CLWB, + X86_SSE, + X86_SSE2, + X86_SSE3, + X86_SSSE3, + X86_SSE4_1, + X86_SSE4_2, + X86_SSE4A, + X86_AVX, + X86_AVX2, + X86_AVX512F, + X86_AVX512CD, + X86_AVX512ER, + X86_AVX512PF, + X86_AVX512BW, + X86_AVX512DQ, + X86_AVX512VL, + X86_AVX512IFMA, + X86_AVX512VBMI, + X86_AVX512VBMI2, + X86_AVX512VNNI, + X86_AVX512BITALG, + X86_AVX512VPOPCNTDQ, + X86_AVX512_4VNNIW, + X86_AVX512_4VBMI2, + X86_AVX512_SECOND_FMA, + X86_AVX512_4FMAPS, + X86_AVX512_BF16, + X86_AVX512_VP2INTERSECT, + X86_AMX_BF16, + X86_AMX_TILE, + X86_AMX_INT8, + X86_PCLMULQDQ, + X86_SMX, + X86_SGX, + X86_CX16, + X86_SHA, + X86_POPCNT, + X86_MOVBE, + X86_RDRND, + X86_DCA, + X86_SS, + X86_LAST_, +} X86FeaturesEnum; + +int GetX86FeaturesEnumValue(const X86Features* features, X86FeaturesEnum value); + +const char* GetX86FeaturesEnumName(X86FeaturesEnum); + +const char* GetX86MicroarchitectureName(X86Microarchitecture); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_X86) +#error "Including cpuinfo_x86.h from a non-x86 target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/bit_utils.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/bit_utils.h new file mode 100644 index 0000000..ae313b5 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/bit_utils.h @@ -0,0 +1,40 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ + +#include +#include +#include + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +inline static bool IsBitSet(uint32_t reg, uint32_t bit) { + return (reg >> bit) & 0x1; +} + +inline static uint32_t ExtractBitRange(uint32_t reg, uint32_t msb, + uint32_t lsb) { + const uint64_t bits = msb - lsb + 1ULL; + const uint64_t mask = (1ULL << bits) - 1ULL; + assert(msb >= lsb); + return (reg >> lsb) & mask; +} + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/cpuid_x86.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/cpuid_x86.h new file mode 100644 index 0000000..754ca38 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/cpuid_x86.h @@ -0,0 +1,36 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ + +#include + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +// A struct to hold the result of a call to cpuid. +typedef struct { + uint32_t eax, ebx, ecx, edx; +} Leaf; + +Leaf CpuIdEx(uint32_t leaf_id, int ecx); + +// Returns the eax value of the XCR0 register. +uint32_t GetXCR0Eax(void); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/filesystem.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/filesystem.h new file mode 100644 index 0000000..d9cdafc --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/filesystem.h @@ -0,0 +1,39 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An interface for the filesystem that allows mocking the filesystem in +// unittests. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ + +#include +#include + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +// Same as linux "open(filename, O_RDONLY)", retries automatically on EINTR. +int CpuFeatures_OpenFile(const char* filename); + +// Same as linux "read(file_descriptor, buffer, buffer_size)", retries +// automatically on EINTR. +int CpuFeatures_ReadFile(int file_descriptor, void* buffer, size_t buffer_size); + +// Same as linux "close(file_descriptor)". +void CpuFeatures_CloseFile(int file_descriptor); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/hwcaps.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/hwcaps.h new file mode 100644 index 0000000..8716eb8 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/hwcaps.h @@ -0,0 +1,183 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Interface to retrieve hardware capabilities. It relies on Linux's getauxval +// or `/proc/self/auxval` under the hood. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ + +#include + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +// To avoid depending on the linux kernel we reproduce the architecture specific +// constants here. + +// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h +#define AARCH64_HWCAP_FP (1UL << 0) +#define AARCH64_HWCAP_ASIMD (1UL << 1) +#define AARCH64_HWCAP_EVTSTRM (1UL << 2) +#define AARCH64_HWCAP_AES (1UL << 3) +#define AARCH64_HWCAP_PMULL (1UL << 4) +#define AARCH64_HWCAP_SHA1 (1UL << 5) +#define AARCH64_HWCAP_SHA2 (1UL << 6) +#define AARCH64_HWCAP_CRC32 (1UL << 7) +#define AARCH64_HWCAP_ATOMICS (1UL << 8) +#define AARCH64_HWCAP_FPHP (1UL << 9) +#define AARCH64_HWCAP_ASIMDHP (1UL << 10) +#define AARCH64_HWCAP_CPUID (1UL << 11) +#define AARCH64_HWCAP_ASIMDRDM (1UL << 12) +#define AARCH64_HWCAP_JSCVT (1UL << 13) +#define AARCH64_HWCAP_FCMA (1UL << 14) +#define AARCH64_HWCAP_LRCPC (1UL << 15) +#define AARCH64_HWCAP_DCPOP (1UL << 16) +#define AARCH64_HWCAP_SHA3 (1UL << 17) +#define AARCH64_HWCAP_SM3 (1UL << 18) +#define AARCH64_HWCAP_SM4 (1UL << 19) +#define AARCH64_HWCAP_ASIMDDP (1UL << 20) +#define AARCH64_HWCAP_SHA512 (1UL << 21) +#define AARCH64_HWCAP_SVE (1UL << 22) +#define AARCH64_HWCAP_ASIMDFHM (1UL << 23) +#define AARCH64_HWCAP_DIT (1UL << 24) +#define AARCH64_HWCAP_USCAT (1UL << 25) +#define AARCH64_HWCAP_ILRCPC (1UL << 26) +#define AARCH64_HWCAP_FLAGM (1UL << 27) +#define AARCH64_HWCAP_SSBS (1UL << 28) +#define AARCH64_HWCAP_SB (1UL << 29) +#define AARCH64_HWCAP_PACA (1UL << 30) +#define AARCH64_HWCAP_PACG (1UL << 31) + +#define AARCH64_HWCAP2_DCPODP (1UL << 0) +#define AARCH64_HWCAP2_SVE2 (1UL << 1) +#define AARCH64_HWCAP2_SVEAES (1UL << 2) +#define AARCH64_HWCAP2_SVEPMULL (1UL << 3) +#define AARCH64_HWCAP2_SVEBITPERM (1UL << 4) +#define AARCH64_HWCAP2_SVESHA3 (1UL << 5) +#define AARCH64_HWCAP2_SVESM4 (1UL << 6) +#define AARCH64_HWCAP2_FLAGM2 (1UL << 7) +#define AARCH64_HWCAP2_FRINT (1UL << 8) +#define AARCH64_HWCAP2_SVEI8MM (1UL << 9) +#define AARCH64_HWCAP2_SVEF32MM (1UL << 10) +#define AARCH64_HWCAP2_SVEF64MM (1UL << 11) +#define AARCH64_HWCAP2_SVEBF16 (1UL << 12) +#define AARCH64_HWCAP2_I8MM (1UL << 13) +#define AARCH64_HWCAP2_BF16 (1UL << 14) +#define AARCH64_HWCAP2_DGH (1UL << 15) +#define AARCH64_HWCAP2_RNG (1UL << 16) +#define AARCH64_HWCAP2_BTI (1UL << 17) + +// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h +#define ARM_HWCAP_SWP (1UL << 0) +#define ARM_HWCAP_HALF (1UL << 1) +#define ARM_HWCAP_THUMB (1UL << 2) +#define ARM_HWCAP_26BIT (1UL << 3) +#define ARM_HWCAP_FAST_MULT (1UL << 4) +#define ARM_HWCAP_FPA (1UL << 5) +#define ARM_HWCAP_VFP (1UL << 6) +#define ARM_HWCAP_EDSP (1UL << 7) +#define ARM_HWCAP_JAVA (1UL << 8) +#define ARM_HWCAP_IWMMXT (1UL << 9) +#define ARM_HWCAP_CRUNCH (1UL << 10) +#define ARM_HWCAP_THUMBEE (1UL << 11) +#define ARM_HWCAP_NEON (1UL << 12) +#define ARM_HWCAP_VFPV3 (1UL << 13) +#define ARM_HWCAP_VFPV3D16 (1UL << 14) +#define ARM_HWCAP_TLS (1UL << 15) +#define ARM_HWCAP_VFPV4 (1UL << 16) +#define ARM_HWCAP_IDIVA (1UL << 17) +#define ARM_HWCAP_IDIVT (1UL << 18) +#define ARM_HWCAP_VFPD32 (1UL << 19) +#define ARM_HWCAP_LPAE (1UL << 20) +#define ARM_HWCAP_EVTSTRM (1UL << 21) +#define ARM_HWCAP2_AES (1UL << 0) +#define ARM_HWCAP2_PMULL (1UL << 1) +#define ARM_HWCAP2_SHA1 (1UL << 2) +#define ARM_HWCAP2_SHA2 (1UL << 3) +#define ARM_HWCAP2_CRC32 (1UL << 4) + +// http://elixir.free-electrons.com/linux/latest/source/arch/mips/include/uapi/asm/hwcap.h +#define MIPS_HWCAP_R6 (1UL << 0) +#define MIPS_HWCAP_MSA (1UL << 1) +#define MIPS_HWCAP_CRC32 (1UL << 2) + +// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h +#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H +/* in AT_HWCAP */ +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 +#define PPC_FEATURE_POWER4 0x00080000 +#define PPC_FEATURE_POWER5 0x00040000 +#define PPC_FEATURE_POWER5_PLUS 0x00020000 +#define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_PA6T 0x00000800 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 +#define PPC_FEATURE_ARCH_2_06 0x00000100 +#define PPC_FEATURE_HAS_VSX 0x00000080 + +#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040 + +/* Reserved - do not use 0x00000004 */ +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + +/* in AT_HWCAP2 */ +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 +#define PPC_FEATURE2_VEC_CRYPTO 0x02000000 +#define PPC_FEATURE2_HTM_NOSC 0x01000000 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_DARN 0x00200000 +#define PPC_FEATURE2_SCV 0x00100000 +#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 +#endif + +typedef struct { + unsigned long hwcaps; + unsigned long hwcaps2; +} HardwareCapabilities; + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); + +typedef struct { + char platform[64]; // 0 terminated string + char base_platform[64]; // 0 terminated string +} PlatformType; + +PlatformType CpuFeatures_GetPlatformType(void); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/stack_line_reader.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/stack_line_reader.h new file mode 100644 index 0000000..c540f6b --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/stack_line_reader.h @@ -0,0 +1,49 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Reads a file line by line and stores the data on the stack. This allows +// parsing files in one go without allocating. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ + +#include + +#include "cpu_features_macros.h" +#include "internal/string_view.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + char buffer[STACK_LINE_READER_BUFFER_SIZE]; + StringView view; + int fd; + bool skip_mode; +} StackLineReader; + +// Initializes a StackLineReader. +void StackLineReader_Initialize(StackLineReader* reader, int fd); + +typedef struct { + StringView line; // A view of the line. + bool eof; // Nothing more to read, we reached EOF. + bool full_line; // If false the line was truncated to + // STACK_LINE_READER_BUFFER_SIZE. +} LineResult; + +// Reads the file pointed to by fd and tries to read a full line. +LineResult StackLineReader_NextLine(StackLineReader* reader); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/string_view.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/string_view.h new file mode 100644 index 0000000..5044dc8 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/string_view.h @@ -0,0 +1,109 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// A view over a piece of string. The view is not 0 terminated. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ + +#include +#include +#include + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + const char* ptr; + size_t size; +} StringView; + +#ifdef __cplusplus +static const StringView kEmptyStringView = {NULL, 0}; +#else +static const StringView kEmptyStringView; +#endif + +// Returns a StringView from the provided string. +// Passing NULL is valid only if size is 0. +static inline StringView view(const char* str, const size_t size) { + StringView view; + view.ptr = str; + view.size = size; + return view; +} + +static inline StringView str(const char* str) { return view(str, strlen(str)); } + +// Returns the index of the first occurrence of c in view or -1 if not found. +int CpuFeatures_StringView_IndexOfChar(const StringView view, char c); + +// Returns the index of the first occurrence of sub_view in view or -1 if not +// found. +int CpuFeatures_StringView_IndexOf(const StringView view, + const StringView sub_view); + +// Returns whether a is equal to b (same content). +bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b); + +// Returns whether a starts with b. +bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b); + +// Removes count characters from the beginning of view or kEmptyStringView if +// count if greater than view.size. +StringView CpuFeatures_StringView_PopFront(const StringView str_view, + size_t count); + +// Removes count characters from the end of view or kEmptyStringView if count if +// greater than view.size. +StringView CpuFeatures_StringView_PopBack(const StringView str_view, + size_t count); + +// Keeps the count first characters of view or view if count if greater than +// view.size. +StringView CpuFeatures_StringView_KeepFront(const StringView str_view, + size_t count); + +// Retrieves the first character of view. If view is empty the behavior is +// undefined. +char CpuFeatures_StringView_Front(const StringView view); + +// Retrieves the last character of view. If view is empty the behavior is +// undefined. +char CpuFeatures_StringView_Back(const StringView view); + +// Removes leading and tailing space characters. +StringView CpuFeatures_StringView_TrimWhitespace(StringView view); + +// Convert StringView to positive integer. e.g. "42", "0x2a". +// Returns -1 on error. +int CpuFeatures_StringView_ParsePositiveNumber(const StringView view); + +// Copies src StringView to dst buffer. +void CpuFeatures_StringView_CopyString(const StringView src, char* dst, + size_t dst_size); + +// Checks if line contains the specified whitespace separated word. +bool CpuFeatures_StringView_HasWord(const StringView line, + const char* const word); + +// Get key/value from line. key and value are separated by ": ". +// key and value are cleaned up from leading and trailing whitespaces. +bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line, + StringView* key, + StringView* value); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/unix_features_aggregator.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/unix_features_aggregator.h new file mode 100644 index 0000000..c20f154 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/include/internal/unix_features_aggregator.h @@ -0,0 +1,73 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// CapabilityConfig provides a way to map cpu features to hardware caps and +// /proc/cpuinfo flags. We then provide functions to update capabilities from +// either source. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_ + +#include +#include + +#include "cpu_features_macros.h" +#include "internal/hwcaps.h" +#include "internal/string_view.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +// Use the following macro to declare setter functions to be used in +// CapabilityConfig. +#define DECLARE_SETTER(FeatureType, FeatureName) \ + static void set_##FeatureName(void* const features, bool value) { \ + ((FeatureType*)features)->FeatureName = value; \ + } + +// Use the following macro to declare getter functions to be used in +// CapabilityConfig. +#define DECLARE_GETTER(FeatureType, FeatureName) \ + static int get_##FeatureName(void* const features) { \ + return ((FeatureType*)features)->FeatureName; \ + } + +#define DECLARE_SETTER_AND_GETTER(FeatureType, FeatureName) \ + DECLARE_SETTER(FeatureType, FeatureName) \ + DECLARE_GETTER(FeatureType, FeatureName) + +// Describes the relationship between hardware caps and /proc/cpuinfo flags. +typedef struct { + const HardwareCapabilities hwcaps_mask; + const char* const proc_cpuinfo_flag; + void (*set_bit)(void* const, bool); // setter for the corresponding bit. + int (*get_bit)(void* const); // getter for the corresponding bit. +} CapabilityConfig; + +// For every config, looks into flags_line for the presence of the +// corresponding proc_cpuinfo_flag, calls `set_bit` accordingly. +// Note: features is a pointer to the underlying Feature struct. +void CpuFeatures_SetFromFlags(const size_t configs_size, + const CapabilityConfig* configs, + const StringView flags_line, + void* const features); + +// For every config, looks into hwcaps for the presence of the feature. Calls +// `set_bit` with true if the hardware capability is found. +// Note: features is a pointer to the underlying Feature struct. +void CpuFeatures_OverrideFromHwCaps(const size_t configs_size, + const CapabilityConfig* configs, + const HardwareCapabilities hwcaps, + void* const features); + +CPU_FEATURES_END_CPP_NAMESPACE +#endif // CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/CMakeLists.txt b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/CMakeLists.txt new file mode 100644 index 0000000..186708a --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/CMakeLists.txt @@ -0,0 +1,60 @@ + +# +# library : NDK compat +# +find_package(Threads REQUIRED) +set (NDK_COMPAT_HDRS cpu-features.h) +set (NDK_COMPAT_SRCS + cpu-features.c + $ + $ +) +# Note that following `add_cpu_features_headers_and_sources` will use +# NDK_COMPAT_SRCS in lieu of NDK_COMPAT_HDRS because we don't want cpu_features +# headers to be installed alongside ndk_compat. +add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS) +add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS}) +setup_include_and_definitions(ndk_compat) +target_include_directories(ndk_compat PUBLIC $) +target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) +set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}") + +include(GNUInstallDirs) +install(TARGETS ndk_compat + EXPORT CpuFeaturesNdkCompatTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ndk_compat + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) +install(EXPORT CpuFeaturesNdkCompatTargets + NAMESPACE CpuFeatures:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat + COMPONENT Devel +) +include(CMakePackageConfigHelpers) +configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/CpuFeaturesNdkCompatConfig.cmake.in + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) +write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake" + COMPATIBILITY SameMajorVersion +) +install( + FILES + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake" + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat" + COMPONENT Devel +) + +# +# program : NDK compat test program +# +if(ENABLE_TESTING) + add_executable(ndk-compat-test ndk-compat-test.c) + target_link_libraries(ndk-compat-test PRIVATE ndk_compat) +endif() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/README.md b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/README.md new file mode 100644 index 0000000..38c8393 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/README.md @@ -0,0 +1,4 @@ +Provides a header compatible with [android's NDK cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h). + +It is intended to be a drop in replacement for this header and help users +transition from the NDK to [Google's cpu_features library](https://github.com/google/cpu_features). diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.c new file mode 100644 index 0000000..27ff7bb --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.c @@ -0,0 +1,205 @@ +#include "cpu-features.h" + +#include + +#include "cpu_features_macros.h" +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" + +#if defined(CPU_FEATURES_ARCH_ARM) +#include "cpuinfo_arm.h" +#elif defined(CPU_FEATURES_ARCH_X86) +#include "cpuinfo_x86.h" +#elif defined(CPU_FEATURES_ARCH_MIPS) +#include "cpuinfo_mips.h" +#elif defined(CPU_FEATURES_ARCH_AARCH64) +#include "cpuinfo_aarch64.h" +#endif + +static pthread_once_t g_once; +static int g_inited; +static uint64_t g_cpuFeatures; +static int g_cpuCount; + +#ifdef CPU_FEATURES_ARCH_ARM +static uint32_t g_cpuIdArm; +#endif + +static void set_cpu_mask_bit(uint32_t index, uint32_t* cpu_mask) { + *cpu_mask |= 1UL << index; +} + +// Examples of valid inputs: "31", "4-31" +static void parse_cpu_mask(const StringView text, uint32_t* cpu_mask) { + int separator_index = CpuFeatures_StringView_IndexOfChar(text, '-'); + if (separator_index < 0) { // A single cpu index + int cpu_index = CpuFeatures_StringView_ParsePositiveNumber(text); + if (cpu_index < 0) return; + set_cpu_mask_bit(cpu_index, cpu_mask); + } else { + int cpu_index_a = CpuFeatures_StringView_ParsePositiveNumber( + CpuFeatures_StringView_KeepFront(text, separator_index)); + int cpu_index_b = CpuFeatures_StringView_ParsePositiveNumber( + CpuFeatures_StringView_PopFront(text, separator_index + 1)); + int i; + if (cpu_index_a < 0 || cpu_index_b < 0) return; + for (i = cpu_index_a; i <= cpu_index_b; ++i) { + if (i < 32) { + set_cpu_mask_bit(i, cpu_mask); + } + } + } +} + +// Format specification from +// https://www.kernel.org/doc/Documentation/cputopology.txt +// Examples of valid inputs: "31", "2,4-31,32-63", "0-1,3" +static void parse_cpu_mask_line(const LineResult result, uint32_t* cpu_mask) { + if (!result.full_line || result.eof) return; + StringView line = result.line; + for (; line.size > 0;) { + int next_entry_index = CpuFeatures_StringView_IndexOfChar(line, ','); + if (next_entry_index < 0) { + parse_cpu_mask(line, cpu_mask); + break; + } + StringView entry = CpuFeatures_StringView_KeepFront(line, next_entry_index); + parse_cpu_mask(entry, cpu_mask); + line = CpuFeatures_StringView_PopFront(line, next_entry_index + 1); + } +} + +static void update_cpu_mask_from_file(const char* filename, + uint32_t* cpu_mask) { + const int fd = CpuFeatures_OpenFile(filename); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + parse_cpu_mask_line(StackLineReader_NextLine(&reader), cpu_mask); + CpuFeatures_CloseFile(fd); + } +} + +static int get_cpu_count(void) { + uint32_t cpu_mask = 0; + update_cpu_mask_from_file("/sys/devices/system/cpu/present", &cpu_mask); + update_cpu_mask_from_file("/sys/devices/system/cpu/possible", &cpu_mask); + return __builtin_popcount(cpu_mask); +} + +static void android_cpuInit(void) { + g_cpuFeatures = 0; + g_cpuCount = 1; + g_inited = 1; + + g_cpuCount = get_cpu_count(); + if (g_cpuCount == 0) { + g_cpuCount = 1; + } +#if defined(CPU_FEATURES_ARCH_ARM) + ArmInfo info = GetArmInfo(); + if (info.architecture == 7) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; + if (info.features.vfpv3) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; + if (info.features.neon) { + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON; + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_D32; + } + if (info.features.vfpv3d16) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FP16; + if (info.features.idiva) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM; + if (info.features.idivt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2; + if (info.features.iwmmxt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt; + if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES; + if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL; + if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1; + if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2; + if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32; + if (info.architecture >= 6) + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; + if (info.features.vfp) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2; + if (info.features.vfpv4) { + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FMA; + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA; + } + g_cpuIdArm = GetArmCpuId(&info); +#elif defined(CPU_FEATURES_ARCH_X86) + X86Info info = GetX86Info(); + if (info.features.ssse3) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3; + if (info.features.popcnt) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT; + if (info.features.movbe) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE; + if (info.features.sse4_1) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1; + if (info.features.sse4_2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2; + if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI; + if (info.features.avx) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX; + if (info.features.rdrnd) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND; + if (info.features.avx2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2; + if (info.features.sha) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI; +#elif defined(CPU_FEATURES_ARCH_MIPS) + MipsInfo info = GetMipsInfo(); + if (info.features.r6) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6; + if (info.features.msa) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA; +#elif defined(CPU_FEATURES_ARCH_AARCH64) + Aarch64Info info = GetAarch64Info(); + if (info.features.fp) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP; + if (info.features.asimd) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD; + if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES; + if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL; + if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1; + if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2; + if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32; +#endif +} + +AndroidCpuFamily android_getCpuFamily(void) { +#if defined(CPU_FEATURES_ARCH_ARM) + return ANDROID_CPU_FAMILY_ARM; +#elif defined(CPU_FEATURES_ARCH_X86_32) + return ANDROID_CPU_FAMILY_X86; +#elif defined(CPU_FEATURES_ARCH_MIPS64) + return ANDROID_CPU_FAMILY_MIPS64; +#elif defined(CPU_FEATURES_ARCH_MIPS32) + return ANDROID_CPU_FAMILY_MIPS; +#elif defined(CPU_FEATURES_ARCH_AARCH64) + return ANDROID_CPU_FAMILY_ARM64; +#elif defined(CPU_FEATURES_ARCH_X86_64) + return ANDROID_CPU_FAMILY_X86_64; +#else + return ANDROID_CPU_FAMILY_UNKNOWN; +#endif +} + +uint64_t android_getCpuFeatures(void) { + pthread_once(&g_once, android_cpuInit); + return g_cpuFeatures; +} + +int android_getCpuCount(void) { + pthread_once(&g_once, android_cpuInit); + return g_cpuCount; +} + +static void android_cpuInitDummy(void) { g_inited = 1; } + +int android_setCpu(int cpu_count, uint64_t cpu_features) { + /* Fail if the library was already initialized. */ + if (g_inited) return 0; + g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count); + g_cpuFeatures = cpu_features; + pthread_once(&g_once, android_cpuInitDummy); + return 1; +} + +#ifdef CPU_FEATURES_ARCH_ARM + +uint32_t android_getCpuIdArm(void) { + pthread_once(&g_once, android_cpuInit); + return g_cpuIdArm; +} + +int android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id) { + if (!android_setCpu(cpu_count, cpu_features)) return 0; + g_cpuIdArm = cpu_id; + return 1; +} + +#endif // CPU_FEATURES_ARCH_ARM diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.h new file mode 100644 index 0000000..51bea53 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/cpu-features.h @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef GOOGLE_CPU_FEATURES_H +#define GOOGLE_CPU_FEATURES_H +#include +#include + +__BEGIN_DECLS + +/* A list of valid values returned by android_getCpuFamily(). + * They describe the CPU Architecture of the current process. + */ +typedef enum { + ANDROID_CPU_FAMILY_UNKNOWN = 0, + ANDROID_CPU_FAMILY_ARM, + ANDROID_CPU_FAMILY_X86, + ANDROID_CPU_FAMILY_MIPS, + ANDROID_CPU_FAMILY_ARM64, + ANDROID_CPU_FAMILY_X86_64, + ANDROID_CPU_FAMILY_MIPS64, + ANDROID_CPU_FAMILY_MAX /* do not remove */ +} AndroidCpuFamily; + +/* Return the CPU family of the current process. + * + * Note that this matches the bitness of the current process. I.e. when + * running a 32-bit binary on a 64-bit capable CPU, this will return the + * 32-bit CPU family value. + */ +extern AndroidCpuFamily android_getCpuFamily(void); + +/* Return a bitmap describing a set of optional CPU features that are + * supported by the current device's CPU. The exact bit-flags returned + * depend on the value returned by android_getCpuFamily(). See the + * documentation for the ANDROID_CPU_*_FEATURE_* flags below for details. + */ +extern uint64_t android_getCpuFeatures(void); + +/* The list of feature flags for ANDROID_CPU_FAMILY_ARM that can be + * recognized by the library (see note below for 64-bit ARM). Value details + * are: + * + * VFPv2: + * CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs + * support these instructions. VFPv2 is a subset of VFPv3 so this will + * be set whenever VFPv3 is set too. + * + * ARMv7: + * CPU supports the ARMv7-A basic instruction set. + * This feature is mandated by the 'armeabi-v7a' ABI. + * + * VFPv3: + * CPU supports the VFPv3-D16 instruction set, providing hardware FPU + * support for single and double precision floating point registers. + * Note that only 16 FPU registers are available by default, unless + * the D32 bit is set too. This feature is also mandated by the + * 'armeabi-v7a' ABI. + * + * VFP_D32: + * CPU VFP optional extension that provides 32 FPU registers, + * instead of 16. Note that ARM mandates this feature is the 'NEON' + * feature is implemented by the CPU. + * + * NEON: + * CPU FPU supports "ARM Advanced SIMD" instructions, also known as + * NEON. Note that this mandates the VFP_D32 feature as well, per the + * ARM Architecture specification. + * + * VFP_FP16: + * Half-width floating precision VFP extension. If set, the CPU + * supports instructions to perform floating-point operations on + * 16-bit registers. This is part of the VFPv4 specification, but + * not mandated by any Android ABI. + * + * VFP_FMA: + * Fused multiply-accumulate VFP instructions extension. Also part of + * the VFPv4 specification, but not mandated by any Android ABI. + * + * NEON_FMA: + * Fused multiply-accumulate NEON instructions extension. Optional + * extension from the VFPv4 specification, but not mandated by any + * Android ABI. + * + * IDIV_ARM: + * Integer division available in ARM mode. Only available + * on recent CPUs (e.g. Cortex-A15). + * + * IDIV_THUMB2: + * Integer division available in Thumb-2 mode. Only available + * on recent CPUs (e.g. Cortex-A15). + * + * iWMMXt: + * Optional extension that adds MMX registers and operations to an + * ARM CPU. This is only available on a few XScale-based CPU designs + * sold by Marvell. Pretty rare in practice. + * + * AES: + * CPU supports AES instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * CRC32: + * CPU supports CRC32 instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * SHA2: + * CPU supports SHA2 instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * SHA1: + * CPU supports SHA1 instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * PMULL: + * CPU supports 64-bit PMULL and PMULL2 instructions. These + * instructions are only available for 32-bit applications + * running on ARMv8 CPU. + * + * If you want to tell the compiler to generate code that targets one of + * the feature set above, you should probably use one of the following + * flags (for more details, see technical note at the end of this file): + * + * -mfpu=vfp + * -mfpu=vfpv2 + * These are equivalent and tell GCC to use VFPv2 instructions for + * floating-point operations. Use this if you want your code to + * run on *some* ARMv6 devices, and any ARMv7-A device supported + * by Android. + * + * Generated code requires VFPv2 feature. + * + * -mfpu=vfpv3-d16 + * Tell GCC to use VFPv3 instructions (using only 16 FPU registers). + * This should be generic code that runs on any CPU that supports the + * 'armeabi-v7a' Android ABI. Note that no ARMv6 CPU supports this. + * + * Generated code requires VFPv3 feature. + * + * -mfpu=vfpv3 + * Tell GCC to use VFPv3 instructions with 32 FPU registers. + * Generated code requires VFPv3|VFP_D32 features. + * + * -mfpu=neon + * Tell GCC to use VFPv3 instructions with 32 FPU registers, and + * also support NEON intrinsics (see ). + * Generated code requires VFPv3|VFP_D32|NEON features. + * + * -mfpu=vfpv4-d16 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA features. + * + * -mfpu=vfpv4 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32 features. + * + * -mfpu=neon-vfpv4 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|NEON|NEON_FMA + * features. + * + * -mcpu=cortex-a7 + * -mcpu=cortex-a15 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32| + * NEON|NEON_FMA|IDIV_ARM|IDIV_THUMB2 + * This flag implies -mfpu=neon-vfpv4. + * + * -mcpu=iwmmxt + * Allows the use of iWMMXt instrinsics with GCC. + * + * IMPORTANT NOTE: These flags should only be tested when + * android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM, i.e. this is a + * 32-bit process. + * + * When running a 64-bit ARM process on an ARMv8 CPU, + * android_getCpuFeatures() will return a different set of bitflags + */ +enum { + ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0), + ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1), + ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2), + ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3), + ANDROID_CPU_ARM_FEATURE_VFPv2 = (1 << 4), + ANDROID_CPU_ARM_FEATURE_VFP_D32 = (1 << 5), + ANDROID_CPU_ARM_FEATURE_VFP_FP16 = (1 << 6), + ANDROID_CPU_ARM_FEATURE_VFP_FMA = (1 << 7), + ANDROID_CPU_ARM_FEATURE_NEON_FMA = (1 << 8), + ANDROID_CPU_ARM_FEATURE_IDIV_ARM = (1 << 9), + ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10), + ANDROID_CPU_ARM_FEATURE_iWMMXt = (1 << 11), + ANDROID_CPU_ARM_FEATURE_AES = (1 << 12), + ANDROID_CPU_ARM_FEATURE_PMULL = (1 << 13), + ANDROID_CPU_ARM_FEATURE_SHA1 = (1 << 14), + ANDROID_CPU_ARM_FEATURE_SHA2 = (1 << 15), + ANDROID_CPU_ARM_FEATURE_CRC32 = (1 << 16), +}; + +/* The bit flags corresponding to the output of android_getCpuFeatures() + * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM64. Value details + * are: + * + * FP: + * CPU has Floating-point unit. + * + * ASIMD: + * CPU has Advanced SIMD unit. + * + * AES: + * CPU supports AES instructions. + * + * CRC32: + * CPU supports CRC32 instructions. + * + * SHA2: + * CPU supports SHA2 instructions. + * + * SHA1: + * CPU supports SHA1 instructions. + * + * PMULL: + * CPU supports 64-bit PMULL and PMULL2 instructions. + */ +enum { + ANDROID_CPU_ARM64_FEATURE_FP = (1 << 0), + ANDROID_CPU_ARM64_FEATURE_ASIMD = (1 << 1), + ANDROID_CPU_ARM64_FEATURE_AES = (1 << 2), + ANDROID_CPU_ARM64_FEATURE_PMULL = (1 << 3), + ANDROID_CPU_ARM64_FEATURE_SHA1 = (1 << 4), + ANDROID_CPU_ARM64_FEATURE_SHA2 = (1 << 5), + ANDROID_CPU_ARM64_FEATURE_CRC32 = (1 << 6), +}; + +/* The bit flags corresponding to the output of android_getCpuFeatures() + * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_X86 or + * ANDROID_CPU_FAMILY_X86_64. + */ +enum { + ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0), + ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1), + ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2), + ANDROID_CPU_X86_FEATURE_SSE4_1 = (1 << 3), + ANDROID_CPU_X86_FEATURE_SSE4_2 = (1 << 4), + ANDROID_CPU_X86_FEATURE_AES_NI = (1 << 5), + ANDROID_CPU_X86_FEATURE_AVX = (1 << 6), + ANDROID_CPU_X86_FEATURE_RDRAND = (1 << 7), + ANDROID_CPU_X86_FEATURE_AVX2 = (1 << 8), + ANDROID_CPU_X86_FEATURE_SHA_NI = (1 << 9), +}; + +/* The bit flags corresponding to the output of android_getCpuFeatures() + * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_MIPS + * or ANDROID_CPU_FAMILY_MIPS64. Values are: + * + * R6: + * CPU executes MIPS Release 6 instructions natively, and + * supports obsoleted R1..R5 instructions only via kernel traps. + * + * MSA: + * CPU supports Mips SIMD Architecture instructions. + */ +enum { + ANDROID_CPU_MIPS_FEATURE_R6 = (1 << 0), + ANDROID_CPU_MIPS_FEATURE_MSA = (1 << 1), +}; + +/* Return the number of CPU cores detected on this device. + * Please note the current implementation supports up to 32 cpus. + */ +extern int android_getCpuCount(void); + +/* The following is used to force the CPU count and features + * mask in sandboxed processes. Under 4.1 and higher, these processes + * cannot access /proc, which is the only way to get information from + * the kernel about the current hardware (at least on ARM). + * + * It _must_ be called only once, and before any android_getCpuXXX + * function, any other case will fail. + * + * This function return 1 on success, and 0 on failure. + */ +extern int android_setCpu(int cpu_count, uint64_t cpu_features); + +#ifdef __arm__ + +/* Retrieve the ARM 32-bit CPUID value from the kernel. + * Note that this cannot work on sandboxed processes under 4.1 and + * higher, unless you called android_setCpuArm() before. + */ +extern uint32_t android_getCpuIdArm(void); + +/* An ARM-specific variant of android_setCpu() that also allows you + * to set the ARM CPUID field. + */ +extern int android_setCpuArm(int cpu_count, uint64_t cpu_features, + uint32_t cpu_id); + +#endif + +__END_DECLS +#endif /* GOOGLE_CPU_FEATURES_H */ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/ndk-compat-test.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/ndk-compat-test.c new file mode 100644 index 0000000..e4005d4 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/ndk_compat/ndk-compat-test.c @@ -0,0 +1,12 @@ +#include + +#include "cpu-features.h" + +int main() { + printf("android_getCpuFamily()=%d\n", android_getCpuFamily()); + printf("android_getCpuFeatures()=0x%08llx\n", android_getCpuFeatures()); + printf("android_getCpuCount()=%d\n", android_getCpuCount()); +#ifdef __arm__ + printf("android_getCpuIdArm()=0x%04x\n", android_getCpuIdArm()); +#endif //__arm__ +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/run_integration.sh b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/run_integration.sh new file mode 100755 index 0000000..fd88d60 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/run_integration.sh @@ -0,0 +1,209 @@ +#!/usr/bin/env bash + +readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.." +readonly ARCHIVE_FOLDER=~/cpu_features_archives +readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu +readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON" + +function extract() { + case $1 in + *.tar.bz2) tar xjf "$1" ;; + *.tar.xz) tar xJf "$1" ;; + *.tar.gz) tar xzf "$1" ;; + *) + echo "don't know how to extract '$1'..." + exit 1 + esac +} + +function unpackifnotexists() { + mkdir -p "${ARCHIVE_FOLDER}" + cd "${ARCHIVE_FOLDER}" || exit + local URL=$1 + local RELATIVE_FOLDER=$2 + local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}" + if [[ ! -d "${DESTINATION}" ]] ; then + local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///') + test -f "${ARCHIVE_NAME}" || wget -q "${URL}" + extract "${ARCHIVE_NAME}" + rm -f "${ARCHIVE_NAME}" + fi +} + +function installqemuifneeded() { + local VERSION=${QEMU_VERSION:=2.11.1} + local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el} + local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')} + + if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then + echo "qemu ${VERSION} up to date!" + return 0 + fi + + echo "VERSION: ${VERSION}" + echo "TARGETS: ${TARGETS}" + + rm -rf ${QEMU_INSTALL} + + # Checking for a tarball before downloading makes testing easier :-) + local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz" + local QEMU_FOLDER="qemu-${VERSION}" + unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER} + cd ${QEMU_FOLDER} || exit + + ./configure \ + --prefix="${QEMU_INSTALL}" \ + --target-list="${TARGETS}" \ + --disable-docs \ + --disable-sdl \ + --disable-gtk \ + --disable-gnutls \ + --disable-gcrypt \ + --disable-nettle \ + --disable-curses \ + --static + + make -j4 + make install + + echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build +} + +function assert_defined(){ + local VALUE=${1} + : "${VALUE?"${1} needs to be defined"}" +} + +function integrate() { + cd "${PROJECT_FOLDER}" + case "${OS}" in + "Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD" + CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe" + DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe + ;; + *) CMAKE_BUILD_ARGS="--target all" + CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test" + DEMO=${BUILD_DIR}/list_cpu_features + ;; + esac + + # Generating CMake configuration + cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}" + + # Building + cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS} + + # Running tests if needed + if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then + return + fi + RUN_CMD="" + if [[ -n "${QEMU_ARCH}" ]]; then + installqemuifneeded + RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}" + fi + for test_binary in ${CMAKE_TEST_FILES}; do + ${RUN_CMD} ${test_binary} + done + ${RUN_CMD} ${DEMO} +} + +function expand_linaro_config() { + assert_defined TARGET + local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11 + + local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz + local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}" + unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" + + local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz + local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET} + unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}" + + local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER} + local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSROOT=${SYSROOT_FOLDER}) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=${GCC_FOLDER}/bin/${TARGET}-gcc) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=${GCC_FOLDER}/bin/${TARGET}-g++) + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY) + + QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) + QEMU_ARGS+=(-E LD_LIBRARY_PATH=/lib) +} + +function expand_codescape_config() { + assert_defined TARGET + local DATE=2017.10-08 + local CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz + local GCC_URL=${CODESCAPE_URL} + local GCC_RELATIVE_FOLDER="mips-mti-linux-gnu/${DATE}" + unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" + + local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} + local MIPS_FLAGS="" + local LIBC_FOLDER_SUFFIX="" + local FLAVOUR="" + case "${TARGET}" in + "mips32") MIPS_FLAGS="-EB -mabi=32"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; + "mips32el") MIPS_FLAGS="-EL -mabi=32"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; + "mips64") MIPS_FLAGS="-EB -mabi=64"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; + "mips64el") MIPS_FLAGS="-EL -mabi=64"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; + *) echo 'unknown mips platform'; exit 1;; + esac + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER}) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}") + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}") + + local SYSROOT_FOLDER=${GCC_FOLDER}/sysroot/${FLAVOUR} + + # Keeping only the sysroot of interest to save on travis cache. + if [[ "${CONTINUOUS_INTEGRATION}" = "true" ]]; then + for folder in ${GCC_FOLDER}/sysroot/*; do + if [[ "${folder}" != "${SYSROOT_FOLDER}" ]]; then + rm -rf ${folder} + fi + done + fi + + local LIBC_FOLDER=${GCC_FOLDER}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_FOLDER_SUFFIX} + QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) + QEMU_ARGS+=(-E LD_PRELOAD=${LIBC_FOLDER}/libstdc++.so.6:${LIBC_FOLDER}/libgcc_s.so.1) +} + +function expand_environment_and_integrate() { + assert_defined PROJECT_FOLDER + assert_defined TARGET + + BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}" + mkdir -p "${BUILD_DIR}" + + declare -a CONFIG_NAMES=() + declare -a QEMU_ARGS=() + declare -a CMAKE_ADDITIONAL_ARGS=() + + case ${TOOLCHAIN} in + LINARO) expand_linaro_config ;; + CODESCAPE) expand_codescape_config ;; + NATIVE) QEMU_ARCH="" ;; + *) echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;; + esac + integrate +} + +if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then + QEMU_ARCHES=${QEMU_ARCH} + expand_environment_and_integrate +fi diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/test_integration.sh b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/test_integration.sh new file mode 100755 index 0000000..d1c61b0 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/scripts/test_integration.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash + +source "$(dirname -- "$0")"/run_integration.sh + +# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems +function set_aarch64-linux-gnu() { + TOOLCHAIN=LINARO + TARGET=aarch64-linux-gnu + QEMU_ARCH=aarch64 +} + +# Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_arm-linux-gnueabihf() { + TOOLCHAIN=LINARO + TARGET=arm-linux-gnueabihf + QEMU_ARCH=arm +} + +# Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems +function set_armv8l-linux-gnueabihf() { + TOOLCHAIN=LINARO + TARGET=armv8l-linux-gnueabihf + QEMU_ARCH=arm +} + +# Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_arm-linux-gnueabi() { + TOOLCHAIN=LINARO + TARGET=arm-linux-gnueabi + QEMU_ARCH=arm +} + +# Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems +function set_aarch64_be-linux-gnu() { + TOOLCHAIN=LINARO + TARGET=aarch64_be-linux-gnu + QEMU_ARCH=DISABLED +} + +# Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_armeb-linux-gnueabihf() { + TOOLCHAIN=LINARO + TARGET=armeb-linux-gnueabihf + QEMU_ARCH=DISABLED +} + +# Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_armeb-linux-gnueabi() { + TOOLCHAIN=LINARO + TARGET=armeb-linux-gnueabi + QEMU_ARCH=DISABLED +} + +function set_mips32() { + TOOLCHAIN=CODESCAPE + TARGET=mips32 + QEMU_ARCH=mips +} + +function set_mips32el() { + TOOLCHAIN=CODESCAPE + TARGET=mips32el + QEMU_ARCH=mipsel +} + +function set_mips64() { + TOOLCHAIN=CODESCAPE + TARGET=mips64 + QEMU_ARCH=mips64 +} + +function set_mips64el() { + TOOLCHAIN=CODESCAPE + TARGET=mips64el + QEMU_ARCH=mips64el +} + +function set_native() { + TOOLCHAIN=NATIVE + TARGET=native + QEMU_ARCH="" +} + +ENVIRONMENTS=" + set_aarch64-linux-gnu + set_arm-linux-gnueabihf + set_armv8l-linux-gnueabihf + set_arm-linux-gnueabi + set_aarch64_be-linux-gnu + set_armeb-linux-gnueabihf + set_armeb-linux-gnueabi + set_mips32 + set_mips32el + set_mips64 + set_mips64el + set_native +" + +set -e + +CMAKE_GENERATOR="Ninja" + +for SET_ENVIRONMENT in ${ENVIRONMENTS}; do + ${SET_ENVIRONMENT} + expand_environment_and_integrate +done diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_aarch64.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_aarch64.c new file mode 100644 index 0000000..1e60652 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_aarch64.c @@ -0,0 +1,198 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_aarch64.h" + +#include +#include + +#include "internal/filesystem.h" +#include "internal/hwcaps.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include "internal/unix_features_aggregator.h" + +DECLARE_SETTER_AND_GETTER(Aarch64Features, fp) +DECLARE_SETTER_AND_GETTER(Aarch64Features, asimd) +DECLARE_SETTER_AND_GETTER(Aarch64Features, evtstrm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, aes) +DECLARE_SETTER_AND_GETTER(Aarch64Features, pmull) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sha1) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sha2) +DECLARE_SETTER_AND_GETTER(Aarch64Features, crc32) +DECLARE_SETTER_AND_GETTER(Aarch64Features, atomics) +DECLARE_SETTER_AND_GETTER(Aarch64Features, fphp) +DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdhp) +DECLARE_SETTER_AND_GETTER(Aarch64Features, cpuid) +DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdrdm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, jscvt) +DECLARE_SETTER_AND_GETTER(Aarch64Features, fcma) +DECLARE_SETTER_AND_GETTER(Aarch64Features, lrcpc) +DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpop) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sha3) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sm3) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sm4) +DECLARE_SETTER_AND_GETTER(Aarch64Features, asimddp) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sha512) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sve) +DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdfhm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, dit) +DECLARE_SETTER_AND_GETTER(Aarch64Features, uscat) +DECLARE_SETTER_AND_GETTER(Aarch64Features, ilrcpc) +DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, ssbs) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sb) +DECLARE_SETTER_AND_GETTER(Aarch64Features, paca) +DECLARE_SETTER_AND_GETTER(Aarch64Features, pacg) +DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpodp) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sve2) +DECLARE_SETTER_AND_GETTER(Aarch64Features, sveaes) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svepmull) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svebitperm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svesha3) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svesm4) +DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm2) +DECLARE_SETTER_AND_GETTER(Aarch64Features, frint) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svei8mm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svef32mm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svef64mm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, svebf16) +DECLARE_SETTER_AND_GETTER(Aarch64Features, i8mm) +DECLARE_SETTER_AND_GETTER(Aarch64Features, bf16) +DECLARE_SETTER_AND_GETTER(Aarch64Features, dgh) +DECLARE_SETTER_AND_GETTER(Aarch64Features, rng) +DECLARE_SETTER_AND_GETTER(Aarch64Features, bti) + +static const CapabilityConfig kConfigs[] = { + // clang-format off + [AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp, &get_fp}, + [AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd, &get_asimd}, + [AARCH64_EVTSTRM] = {{AARCH64_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, + [AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes, &get_aes}, + [AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull, &get_pmull}, + [AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1, &get_sha1}, + [AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2, &get_sha2}, + [AARCH64_CRC32] = {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32, &get_crc32}, + [AARCH64_ATOMICS] = {{AARCH64_HWCAP_ATOMICS, 0}, "atomics", &set_atomics, &get_atomics}, + [AARCH64_FPHP] = {{AARCH64_HWCAP_FPHP, 0}, "fphp", &set_fphp, &get_fphp}, + [AARCH64_ASIMDHP] = {{AARCH64_HWCAP_ASIMDHP, 0}, "asimdhp", &set_asimdhp, &get_asimdhp}, + [AARCH64_CPUID] = {{AARCH64_HWCAP_CPUID, 0}, "cpuid", &set_cpuid, &get_cpuid}, + [AARCH64_ASIMDRDM] = {{AARCH64_HWCAP_ASIMDRDM, 0}, "asimdrdm", &set_asimdrdm, &get_asimdrdm}, + [AARCH64_JSCVT] = {{AARCH64_HWCAP_JSCVT, 0}, "jscvt", &set_jscvt, &get_jscvt}, + [AARCH64_FCMA] = {{AARCH64_HWCAP_FCMA, 0}, "fcma", &set_fcma, &get_fcma}, + [AARCH64_LRCPC] = {{AARCH64_HWCAP_LRCPC, 0}, "lrcpc", &set_lrcpc, &get_lrcpc}, + [AARCH64_DCPOP] = {{AARCH64_HWCAP_DCPOP, 0}, "dcpop", &set_dcpop, &get_dcpop}, + [AARCH64_SHA3] = {{AARCH64_HWCAP_SHA3, 0}, "sha3", &set_sha3, &get_sha3}, + [AARCH64_SM3] = {{AARCH64_HWCAP_SM3, 0}, "sm3", &set_sm3, &get_sm3}, + [AARCH64_SM4] = {{AARCH64_HWCAP_SM4, 0}, "sm4", &set_sm4, &get_sm4}, + [AARCH64_ASIMDDP] = {{AARCH64_HWCAP_ASIMDDP, 0}, "asimddp", &set_asimddp, &get_asimddp}, + [AARCH64_SHA512] = {{AARCH64_HWCAP_SHA512, 0}, "sha512", &set_sha512, &get_sha512}, + [AARCH64_SVE] = {{AARCH64_HWCAP_SVE, 0}, "sve", &set_sve, &get_sve}, + [AARCH64_ASIMDFHM] = {{AARCH64_HWCAP_ASIMDFHM, 0}, "asimdfhm", &set_asimdfhm, &get_asimdfhm}, + [AARCH64_DIT] = {{AARCH64_HWCAP_DIT, 0}, "dit", &set_dit, &get_dit}, + [AARCH64_USCAT] = {{AARCH64_HWCAP_USCAT, 0}, "uscat", &set_uscat, &get_uscat}, + [AARCH64_ILRCPC] = {{AARCH64_HWCAP_ILRCPC, 0}, "ilrcpc", &set_ilrcpc, &get_ilrcpc}, + [AARCH64_FLAGM] = {{AARCH64_HWCAP_FLAGM, 0}, "flagm", &set_flagm, &get_flagm}, + [AARCH64_SSBS] = {{AARCH64_HWCAP_SSBS, 0}, "ssbs", &set_ssbs, &get_ssbs}, + [AARCH64_SB] = {{AARCH64_HWCAP_SB, 0}, "sb", &set_sb, &get_sb}, + [AARCH64_PACA] = {{AARCH64_HWCAP_PACA, 0}, "paca", &set_paca, &get_paca}, + [AARCH64_PACG] = {{AARCH64_HWCAP_PACG, 0}, "pacg", &set_pacg, &get_pacg}, + [AARCH64_DCPODP] = {{0, AARCH64_HWCAP2_DCPODP}, "dcpodp", &set_dcpodp, &get_dcpodp}, + [AARCH64_SVE2] = {{0, AARCH64_HWCAP2_SVE2}, "sve2", &set_sve2, &get_sve2}, + [AARCH64_SVEAES] = {{0, AARCH64_HWCAP2_SVEAES}, "sveaes", &set_sveaes, &get_sveaes}, + [AARCH64_SVEPMULL] = {{0, AARCH64_HWCAP2_SVEPMULL}, "svepmull", &set_svepmull, &get_svepmull}, + [AARCH64_SVEBITPERM] = {{0, AARCH64_HWCAP2_SVEBITPERM}, "svebitperm", &set_svebitperm, &get_svebitperm}, + [AARCH64_SVESHA3] = {{0, AARCH64_HWCAP2_SVESHA3}, "svesha3", &set_svesha3, &get_svesha3}, + [AARCH64_SVESM4] = {{0, AARCH64_HWCAP2_SVESM4}, "svesm4", &set_svesm4, &get_svesm4}, + [AARCH64_FLAGM2] = {{0, AARCH64_HWCAP2_FLAGM2}, "flagm2", &set_flagm2, &get_flagm2}, + [AARCH64_FRINT] = {{0, AARCH64_HWCAP2_FRINT}, "frint", &set_frint, &get_frint}, + [AARCH64_SVEI8MM] = {{0, AARCH64_HWCAP2_SVEI8MM}, "svei8mm", &set_svei8mm, &get_svei8mm}, + [AARCH64_SVEF32MM] = {{0, AARCH64_HWCAP2_SVEF32MM}, "svef32mm", &set_svef32mm, &get_svef32mm}, + [AARCH64_SVEF64MM] = {{0, AARCH64_HWCAP2_SVEF64MM}, "svef64mm", &set_svef64mm, &get_svef64mm}, + [AARCH64_SVEBF16] = {{0, AARCH64_HWCAP2_SVEBF16}, "svebf16", &set_svebf16, &get_svebf16}, + [AARCH64_I8MM] = {{0, AARCH64_HWCAP2_I8MM}, "i8mm", &set_i8mm, &get_i8mm}, + [AARCH64_BF16] = {{0, AARCH64_HWCAP2_BF16}, "bf16", &set_bf16, &get_bf16}, + [AARCH64_DGH] = {{0, AARCH64_HWCAP2_DGH}, "dgh", &set_dgh, &get_dgh}, + [AARCH64_RNG] = {{0, AARCH64_HWCAP2_RNG}, "rng", &set_rng, &get_rng}, + [AARCH64_BTI] = {{0, AARCH64_HWCAP2_BTI}, "bti", &set_bti, &get_bti}, + // clang-format on +}; + +static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); + +static bool HandleAarch64Line(const LineResult result, + Aarch64Info* const info) { + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { + if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { + CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) { + info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) { + info->variant = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) { + info->part = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) { + info->revision = CpuFeatures_StringView_ParsePositiveNumber(value); + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(Aarch64Info* const info) { + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) { + if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const Aarch64Info kEmptyAarch64Info; + +Aarch64Info GetAarch64Info(void) { + assert(kConfigsSize == AARCH64_LAST_); + + // capabilities are fetched from both getauxval and /proc/cpuinfo so we can + // have some information if the executable is sandboxed (aka no access to + // /proc/cpuinfo). + Aarch64Info info = kEmptyAarch64Info; + + FillProcCpuInfoData(&info); + CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, + CpuFeatures_GetHardwareCapabilities(), + &info.features); + + return info; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetAarch64FeaturesEnumValue(const Aarch64Features* features, + Aarch64FeaturesEnum value) { + if (value >= kConfigsSize) return false; + return kConfigs[value].get_bit((Aarch64Features*)features); +} + +const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) { + if (value >= kConfigsSize) return "unknown feature"; + return kConfigs[value].proc_cpuinfo_flag; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_arm.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_arm.c new file mode 100644 index 0000000..ba27971 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_arm.c @@ -0,0 +1,236 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_arm.h" + +#include +#include + +#include "internal/bit_utils.h" +#include "internal/filesystem.h" +#include "internal/hwcaps.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include "internal/unix_features_aggregator.h" + +DECLARE_SETTER_AND_GETTER(ArmFeatures, swp) +DECLARE_SETTER_AND_GETTER(ArmFeatures, half) +DECLARE_SETTER_AND_GETTER(ArmFeatures, thumb) +DECLARE_SETTER_AND_GETTER(ArmFeatures, _26bit) +DECLARE_SETTER_AND_GETTER(ArmFeatures, fastmult) +DECLARE_SETTER_AND_GETTER(ArmFeatures, fpa) +DECLARE_SETTER_AND_GETTER(ArmFeatures, vfp) +DECLARE_SETTER_AND_GETTER(ArmFeatures, edsp) +DECLARE_SETTER_AND_GETTER(ArmFeatures, java) +DECLARE_SETTER_AND_GETTER(ArmFeatures, iwmmxt) +DECLARE_SETTER_AND_GETTER(ArmFeatures, crunch) +DECLARE_SETTER_AND_GETTER(ArmFeatures, thumbee) +DECLARE_SETTER_AND_GETTER(ArmFeatures, neon) +DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3) +DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3d16) +DECLARE_SETTER_AND_GETTER(ArmFeatures, tls) +DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv4) +DECLARE_SETTER_AND_GETTER(ArmFeatures, idiva) +DECLARE_SETTER_AND_GETTER(ArmFeatures, idivt) +DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpd32) +DECLARE_SETTER_AND_GETTER(ArmFeatures, lpae) +DECLARE_SETTER_AND_GETTER(ArmFeatures, evtstrm) +DECLARE_SETTER_AND_GETTER(ArmFeatures, aes) +DECLARE_SETTER_AND_GETTER(ArmFeatures, pmull) +DECLARE_SETTER_AND_GETTER(ArmFeatures, sha1) +DECLARE_SETTER_AND_GETTER(ArmFeatures, sha2) +DECLARE_SETTER_AND_GETTER(ArmFeatures, crc32) + +static const CapabilityConfig kConfigs[] = { + // clang-format off + [ARM_SWP] = {{ARM_HWCAP_SWP, 0}, "swp", &set_swp, &get_swp}, + [ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half, &get_half}, + [ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb, &get_thumb}, + [ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit, &get__26bit}, + [ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult, &get_fastmult}, + [ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa, &get_fpa}, + [ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp, &get_vfp}, + [ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp, &get_edsp}, + [ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java, &get_java}, + [ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt, &get_iwmmxt}, + [ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch, &get_crunch}, + [ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee, &get_thumbee}, + [ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon, &get_neon}, + [ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3, &get_vfpv3}, + [ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16, &get_vfpv3d16}, + [ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls, &get_tls}, + [ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4, &get_vfpv4}, + [ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva, &get_idiva}, + [ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt, &get_idivt}, + [ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32, &get_vfpd32}, + [ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae, &get_lpae}, + [ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, + [ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes, &get_aes}, + [ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull, &get_pmull}, + [ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1, &get_sha1}, + [ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2, &get_sha2}, + [ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32, &get_crc32}, + // clang-format on +}; + +static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); + +typedef struct { + bool processor_reports_armv6; + bool hardware_reports_goldfish; +} ProcCpuInfoData; + +static int IndexOfNonDigit(StringView str) { + size_t index = 0; + while (str.size && isdigit(CpuFeatures_StringView_Front(str))) { + str = CpuFeatures_StringView_PopFront(str, 1); + ++index; + } + return index; +} + +static bool HandleArmLine(const LineResult result, ArmInfo* const info, + ProcCpuInfoData* const proc_info) { + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { + if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { + CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) { + info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) { + info->variant = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) { + info->part = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) { + info->revision = CpuFeatures_StringView_ParsePositiveNumber(value); + } else if (CpuFeatures_StringView_IsEquals(key, str("CPU architecture"))) { + // CPU architecture is a number that may be followed by letters. e.g. + // "6TEJ", "7". + const StringView digits = + CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value)); + info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits); + } else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) || + CpuFeatures_StringView_IsEquals(key, str("model name"))) { + // Android reports this in a non-Linux standard "Processor" but sometimes + // also in "model name", Linux reports it only in "model name" + // see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases + proc_info->processor_reports_armv6 = + CpuFeatures_StringView_IndexOf(value, str("(v6l)")) >= 0; + } else if (CpuFeatures_StringView_IsEquals(key, str("Hardware"))) { + proc_info->hardware_reports_goldfish = + CpuFeatures_StringView_IsEquals(value, str("Goldfish")); + } + } + return !result.eof; +} + +uint32_t GetArmCpuId(const ArmInfo* const info) { + return (ExtractBitRange(info->implementer, 7, 0) << 24) | + (ExtractBitRange(info->variant, 3, 0) << 20) | + (ExtractBitRange(info->part, 11, 0) << 4) | + (ExtractBitRange(info->revision, 3, 0) << 0); +} + +static void FixErrors(ArmInfo* const info, + ProcCpuInfoData* const proc_cpu_info_data) { + // Fixing Samsung kernel reporting invalid cpu architecture. + // http://code.google.com/p/android/issues/detail?id=10812 + if (proc_cpu_info_data->processor_reports_armv6 && info->architecture >= 7) { + info->architecture = 6; + } + + // Handle kernel configuration bugs that prevent the correct reporting of CPU + // features. + switch (GetArmCpuId(info)) { + case 0x4100C080: + // Special case: The emulator-specific Android 4.2 kernel fails to report + // support for the 32-bit ARM IDIV instruction. Technically, this is a + // feature of the virtual CPU implemented by the emulator. Note that it + // could also support Thumb IDIV in the future, and this will have to be + // slightly updated. + if (info->architecture >= 7 && + proc_cpu_info_data->hardware_reports_goldfish) { + info->features.idiva = true; + } + break; + case 0x511004D0: + // https://crbug.com/341598. + info->features.neon = false; + break; + case 0x510006F2: + case 0x510006F3: + // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report + // IDIV support. + info->features.idiva = true; + info->features.idivt = true; + break; + } + + // Propagate cpu features. + if (info->features.vfpv4) info->features.vfpv3 = true; + if (info->features.neon) info->features.vfpv3 = true; + if (info->features.vfpv3) info->features.vfp = true; +} + +static void FillProcCpuInfoData(ArmInfo* const info, + ProcCpuInfoData* proc_cpu_info_data) { + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) { + if (!HandleArmLine(StackLineReader_NextLine(&reader), info, + proc_cpu_info_data)) { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const ArmInfo kEmptyArmInfo; + +static const ProcCpuInfoData kEmptyProcCpuInfoData; + +ArmInfo GetArmInfo(void) { + // capabilities are fetched from both getauxval and /proc/cpuinfo so we can + // have some information if the executable is sandboxed (aka no access to + // /proc/cpuinfo). + ArmInfo info = kEmptyArmInfo; + ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData; + + FillProcCpuInfoData(&info, &proc_cpu_info_data); + CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, + CpuFeatures_GetHardwareCapabilities(), + &info.features); + + FixErrors(&info, &proc_cpu_info_data); + + return info; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetArmFeaturesEnumValue(const ArmFeatures* features, + ArmFeaturesEnum value) { + if (value >= kConfigsSize) return false; + return kConfigs[value].get_bit((ArmFeatures*)features); +} + +const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) { + if (value >= kConfigsSize) return "unknown feature"; + return kConfigs[value].proc_cpuinfo_flag; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_mips.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_mips.c new file mode 100644 index 0000000..1b2df9e --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_mips.c @@ -0,0 +1,90 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_mips.h" + +#include + +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include "internal/unix_features_aggregator.h" + +DECLARE_SETTER_AND_GETTER(MipsFeatures, msa) +DECLARE_SETTER_AND_GETTER(MipsFeatures, eva) +DECLARE_SETTER_AND_GETTER(MipsFeatures, r6) + +static const CapabilityConfig kConfigs[] = { + [MIPS_MSA] = {{MIPS_HWCAP_MSA, 0}, "msa", &set_msa, &get_msa}, + [MIPS_EVA] = {{0, 0}, "eva", &set_eva, &get_eva}, + [MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6, &get_r6}, +}; +static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); + +static bool HandleMipsLine(const LineResult result, + MipsFeatures* const features) { + StringView key, value; + // See tests for an example. + if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) { + if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) { + CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, features); + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(MipsFeatures* const features) { + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) { + if (!HandleMipsLine(StackLineReader_NextLine(&reader), features)) { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const MipsInfo kEmptyMipsInfo; + +MipsInfo GetMipsInfo(void) { + assert(kConfigsSize == MIPS_LAST_); + + // capabilities are fetched from both getauxval and /proc/cpuinfo so we can + // have some information if the executable is sandboxed (aka no access to + // /proc/cpuinfo). + MipsInfo info = kEmptyMipsInfo; + + FillProcCpuInfoData(&info.features); + CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, + CpuFeatures_GetHardwareCapabilities(), + &info.features); + return info; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetMipsFeaturesEnumValue(const MipsFeatures* features, + MipsFeaturesEnum value) { + if (value >= kConfigsSize) return false; + return kConfigs[value].get_bit((MipsFeatures*)features); +} + +const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) { + if (value >= kConfigsSize) return "unknown feature"; + return kConfigs[value].proc_cpuinfo_flag; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_ppc.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_ppc.c new file mode 100644 index 0000000..4353099 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_ppc.c @@ -0,0 +1,189 @@ +// Copyright 2018 IBM. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_ppc.h" + +#include +#include +#include + +#include "internal/bit_utils.h" +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include "internal/unix_features_aggregator.h" + +DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc32) +DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc64) +DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc601) +DECLARE_SETTER_AND_GETTER(PPCFeatures, altivec) +DECLARE_SETTER_AND_GETTER(PPCFeatures, fpu) +DECLARE_SETTER_AND_GETTER(PPCFeatures, mmu) +DECLARE_SETTER_AND_GETTER(PPCFeatures, mac_4xx) +DECLARE_SETTER_AND_GETTER(PPCFeatures, unifiedcache) +DECLARE_SETTER_AND_GETTER(PPCFeatures, spe) +DECLARE_SETTER_AND_GETTER(PPCFeatures, efpsingle) +DECLARE_SETTER_AND_GETTER(PPCFeatures, efpdouble) +DECLARE_SETTER_AND_GETTER(PPCFeatures, no_tb) +DECLARE_SETTER_AND_GETTER(PPCFeatures, power4) +DECLARE_SETTER_AND_GETTER(PPCFeatures, power5) +DECLARE_SETTER_AND_GETTER(PPCFeatures, power5plus) +DECLARE_SETTER_AND_GETTER(PPCFeatures, cell) +DECLARE_SETTER_AND_GETTER(PPCFeatures, booke) +DECLARE_SETTER_AND_GETTER(PPCFeatures, smt) +DECLARE_SETTER_AND_GETTER(PPCFeatures, icachesnoop) +DECLARE_SETTER_AND_GETTER(PPCFeatures, arch205) +DECLARE_SETTER_AND_GETTER(PPCFeatures, pa6t) +DECLARE_SETTER_AND_GETTER(PPCFeatures, dfp) +DECLARE_SETTER_AND_GETTER(PPCFeatures, power6ext) +DECLARE_SETTER_AND_GETTER(PPCFeatures, arch206) +DECLARE_SETTER_AND_GETTER(PPCFeatures, vsx) +DECLARE_SETTER_AND_GETTER(PPCFeatures, pseries_perfmon_compat) +DECLARE_SETTER_AND_GETTER(PPCFeatures, truele) +DECLARE_SETTER_AND_GETTER(PPCFeatures, ppcle) +DECLARE_SETTER_AND_GETTER(PPCFeatures, arch207) +DECLARE_SETTER_AND_GETTER(PPCFeatures, htm) +DECLARE_SETTER_AND_GETTER(PPCFeatures, dscr) +DECLARE_SETTER_AND_GETTER(PPCFeatures, ebb) +DECLARE_SETTER_AND_GETTER(PPCFeatures, isel) +DECLARE_SETTER_AND_GETTER(PPCFeatures, tar) +DECLARE_SETTER_AND_GETTER(PPCFeatures, vcrypto) +DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_nosc) +DECLARE_SETTER_AND_GETTER(PPCFeatures, arch300) +DECLARE_SETTER_AND_GETTER(PPCFeatures, ieee128) +DECLARE_SETTER_AND_GETTER(PPCFeatures, darn) +DECLARE_SETTER_AND_GETTER(PPCFeatures, scv) +DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_no_suspend) + +static const CapabilityConfig kConfigs[] = { + // clang-format off + [PPC_32] = {{PPC_FEATURE_32, 0}, "ppc32", &set_ppc32, &get_ppc32}, + [PPC_64] = {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64, &get_ppc64}, + [PPC_601_INSTR] = {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601, &get_ppc601}, + [PPC_HAS_ALTIVEC] = {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec, &get_altivec}, + [PPC_HAS_FPU] = {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu, &get_fpu}, + [PPC_HAS_MMU] = {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu, &get_mmu}, + [PPC_HAS_4xxMAC] = {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx, &get_mac_4xx}, + [PPC_UNIFIED_CACHE] = {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache, &get_unifiedcache}, + [PPC_HAS_SPE] = {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe, &get_spe}, + [PPC_HAS_EFP_SINGLE] = {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle, &get_efpsingle}, + [PPC_HAS_EFP_DOUBLE] = {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble, &get_efpdouble}, + [PPC_NO_TB] = {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb, &get_no_tb}, + [PPC_POWER4] = {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4, &get_power4}, + [PPC_POWER5] = {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5, &get_power5}, + [PPC_POWER5_PLUS] = {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus, &get_power5plus}, + [PPC_CELL] = {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell, &get_cell}, + [PPC_BOOKE] = {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke, &get_booke}, + [PPC_SMT] = {{PPC_FEATURE_SMT, 0}, "smt", &set_smt, &get_smt}, + [PPC_ICACHE_SNOOP] = {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop, &get_icachesnoop}, + [PPC_ARCH_2_05] = {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205, &get_arch205}, + [PPC_PA6T] = {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t, &get_pa6t}, + [PPC_HAS_DFP] = {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp, &get_dfp}, + [PPC_POWER6_EXT] = {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext, &get_power6ext}, + [PPC_ARCH_2_06] = {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206, &get_arch206}, + [PPC_HAS_VSX] = {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx, &get_vsx}, + [PPC_PSERIES_PERFMON_COMPAT] = {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0}, "archpmu", &set_pseries_perfmon_compat, &get_pseries_perfmon_compat}, + [PPC_TRUE_LE] = {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele, &get_truele}, + [PPC_PPC_LE] = {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle, &get_ppcle}, + [PPC_ARCH_2_07] = {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207, &get_arch207}, + [PPC_HTM] = {{0, PPC_FEATURE2_HTM}, "htm", &set_htm, &get_htm}, + [PPC_DSCR] = {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr, &get_dscr}, + [PPC_EBB] = {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb, &get_ebb}, + [PPC_ISEL] = {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel, &get_isel}, + [PPC_TAR] = {{0, PPC_FEATURE2_TAR}, "tar", &set_tar, &get_tar}, + [PPC_VEC_CRYPTO] = {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto, &get_vcrypto}, + [PPC_HTM_NOSC] = {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc, &get_htm_nosc}, + [PPC_ARCH_3_00] = {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300, &get_arch300}, + [PPC_HAS_IEEE128] = {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128, &get_ieee128}, + [PPC_DARN] = {{0, PPC_FEATURE2_DARN}, "darn", &set_darn, &get_darn}, + [PPC_SCV] = {{0, PPC_FEATURE2_SCV}, "scv", &set_scv, &get_scv}, + [PPC_HTM_NO_SUSPEND] = {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend, &get_htm_no_suspend}, + // clang-format on +}; +static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); + +static bool HandlePPCLine(const LineResult result, + PPCPlatformStrings* const strings) { + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { + if (CpuFeatures_StringView_HasWord(key, "platform")) { + CpuFeatures_StringView_CopyString(value, strings->platform, + sizeof(strings->platform)); + } else if (CpuFeatures_StringView_IsEquals(key, str("model"))) { + CpuFeatures_StringView_CopyString(value, strings->model, + sizeof(strings->platform)); + } else if (CpuFeatures_StringView_IsEquals(key, str("machine"))) { + CpuFeatures_StringView_CopyString(value, strings->machine, + sizeof(strings->platform)); + } else if (CpuFeatures_StringView_IsEquals(key, str("cpu"))) { + CpuFeatures_StringView_CopyString(value, strings->cpu, + sizeof(strings->platform)); + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(PPCPlatformStrings* const strings) { + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) { + if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings)) { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const PPCInfo kEmptyPPCInfo; + +PPCInfo GetPPCInfo(void) { + /* + * On Power feature flags aren't currently in cpuinfo so we only look at + * the auxilary vector. + */ + PPCInfo info = kEmptyPPCInfo; + + CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, + CpuFeatures_GetHardwareCapabilities(), + &info.features); + return info; +} + +static const PPCPlatformStrings kEmptyPPCPlatformStrings; + +PPCPlatformStrings GetPPCPlatformStrings(void) { + PPCPlatformStrings strings = kEmptyPPCPlatformStrings; + + FillProcCpuInfoData(&strings); + strings.type = CpuFeatures_GetPlatformType(); + return strings; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetPPCFeaturesEnumValue(const PPCFeatures* features, + PPCFeaturesEnum value) { + if (value >= kConfigsSize) return false; + return kConfigs[value].get_bit((PPCFeatures*)features); +} + +const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) { + if (value >= kConfigsSize) return "unknown feature"; + return kConfigs[value].proc_cpuinfo_flag; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c new file mode 100644 index 0000000..d5edd30 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/cpuinfo_x86.c @@ -0,0 +1,1694 @@ +// Copyright 2017 Google Inc. +// Copyright 2020 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_x86.h" + +#include +#include + +#include "internal/bit_utils.h" +#include "internal/cpuid_x86.h" + +#if !defined(CPU_FEATURES_ARCH_X86) +#error "Cannot compile cpuinfo_x86 on a non x86 platform." +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Definitions for CpuId and GetXCR0Eax. +//////////////////////////////////////////////////////////////////////////////// + +#if defined(CPU_FEATURES_MOCK_CPUID_X86) +// Implementation will be provided by test/cpuinfo_x86_test.cc. +#elif defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC) + +#include + +Leaf CpuIdEx(uint32_t leaf_id, int ecx) { + Leaf leaf; + __cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx); + return leaf; +} + +uint32_t GetXCR0Eax(void) { + uint32_t eax, edx; + /* named form of xgetbv not supported on OSX, so must use byte form, see: + https://github.com/asmjit/asmjit/issues/78 + */ + __asm(".byte 0x0F, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0)); + return eax; +} + +#elif defined(CPU_FEATURES_COMPILER_MSC) + +#include +#include // For __cpuidex() + +Leaf CpuIdEx(uint32_t leaf_id, int ecx) { + Leaf leaf; + int data[4]; + __cpuidex(data, leaf_id, ecx); + leaf.eax = data[0]; + leaf.ebx = data[1]; + leaf.ecx = data[2]; + leaf.edx = data[3]; + return leaf; +} + +uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); } + +#else +#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC." +#endif + +static Leaf CpuId(uint32_t leaf_id) { return CpuIdEx(leaf_id, 0); } + +static const Leaf kEmptyLeaf; + +static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) { + if (leaf_id <= max_cpuid_leaf) { + return CpuIdEx(leaf_id, ecx); + } else { + return kEmptyLeaf; + } +} + +static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) { + return SafeCpuIdEx(max_cpuid_leaf, leaf_id, 0); +} + +#define MASK_XMM 0x2 +#define MASK_YMM 0x4 +#define MASK_MASKREG 0x20 +#define MASK_ZMM0_15 0x40 +#define MASK_ZMM16_31 0x80 +#define MASK_XTILECFG 0x20000 +#define MASK_XTILEDATA 0x40000 + +static bool HasMask(uint32_t value, uint32_t mask) { + return (value & mask) == mask; +} + +// Checks that operating system saves and restores xmm registers during context +// switches. +static bool HasXmmOsXSave(uint32_t xcr0_eax) { + return HasMask(xcr0_eax, MASK_XMM); +} + +// Checks that operating system saves and restores ymm registers during context +// switches. +static bool HasYmmOsXSave(uint32_t xcr0_eax) { + return HasMask(xcr0_eax, MASK_XMM | MASK_YMM); +} + +// Checks that operating system saves and restores zmm registers during context +// switches. +static bool HasZmmOsXSave(uint32_t xcr0_eax) { + return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | + MASK_ZMM16_31); +} + +// Checks that operating system saves and restores AMX/TMUL state during context +// switches. +static bool HasTmmOsXSave(uint32_t xcr0_eax) { + return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | + MASK_ZMM16_31 | MASK_XTILECFG | MASK_XTILEDATA); +} + +static bool HasSecondFMA(uint32_t model) { + // Skylake server + if (model == 0x55) { + char proc_name[49] = {0}; + FillX86BrandString(proc_name); + // detect Xeon + if (proc_name[9] == 'X') { + // detect Silver or Bronze + if (proc_name[17] == 'S' || proc_name[17] == 'B') return false; + // detect Gold 5_20 and below, except for Gold 53__ + if (proc_name[17] == 'G' && proc_name[22] == '5') + return ((proc_name[23] == '3') || + (proc_name[24] == '2' && proc_name[25] == '2')); + // detect Xeon W 210x + if (proc_name[17] == 'W' && proc_name[21] == '0') return false; + // detect Xeon D 2xxx + if (proc_name[17] == 'D' && proc_name[19] == '2' && proc_name[20] == '1') + return false; + } + return true; + } + // Cannon Lake client + if (model == 0x66) return false; + // Ice Lake client + if (model == 0x7d || model == 0x7e) return false; + // This is the right default... + return true; +} + +static void SetVendor(const Leaf leaf, char* const vendor) { + *(uint32_t*)(vendor) = leaf.ebx; + *(uint32_t*)(vendor + 4) = leaf.edx; + *(uint32_t*)(vendor + 8) = leaf.ecx; + vendor[12] = '\0'; +} + +static int IsVendor(const Leaf leaf, const char* const name) { + const uint32_t ebx = *(const uint32_t*)(name); + const uint32_t edx = *(const uint32_t*)(name + 4); + const uint32_t ecx = *(const uint32_t*)(name + 8); + return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx; +} + +static const CacheLevelInfo kEmptyCacheLevelInfo; + +static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) { + const int UNDEF = -1; + const int KiB = 1024; + const int MiB = 1024 * KiB; + switch (reg) { + case 0x01: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x02: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 2, + .partitioning = 0}; + case 0x03: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0x04: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0x05: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x06: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 8 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x08: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x09: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 32 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0A: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * KiB, + .ways = 2, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0B: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 4, + .partitioning = 0}; + case 0x0C: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0D: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0E: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 24 * KiB, + .ways = 6, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x1D: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 128 * KiB, + .ways = 2, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x21: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x22: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x23: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x24: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x25: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x29: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x2C: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 32 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x30: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 32 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x40: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = UNDEF, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x41: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 128 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x42: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x43: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x44: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x45: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x46: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x47: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x48: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 3 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x49: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case (0x49 | (1 << 8)): + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4A: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 6 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4B: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4C: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 12 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4D: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4E: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 6 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4F: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x50: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0x51: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0x52: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 256, + .partitioning = 0}; + case 0x55: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 7, + .partitioning = 0}; + case 0x56: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0x57: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0x59: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0x5A: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x5B: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0x5C: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0x5D: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 256, + .partitioning = 0}; + case 0x60: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x61: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 48, + .partitioning = 0}; + case 0x63: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 4, + .partitioning = 0}; + case 0x66: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x67: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x68: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 32 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x70: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 12 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x71: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 16 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x72: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 32 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x76: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0x78: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x79: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 128 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7A: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7B: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7C: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7D: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x7F: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 2, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x80: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x82: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x83: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x84: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x85: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x86: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x87: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xA0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_DTLB, + .cache_size = 4 * KiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0xB0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0xB1: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0xB2: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0xB3: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0xB4: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 256, + .partitioning = 0}; + case 0xB5: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0xB6: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0xBA: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0xC0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0xC1: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_STLB, + .cache_size = 4 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = 1024, + .partitioning = 0}; + case 0xC2: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_DTLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0xC3: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_STLB, + .cache_size = 4 * KiB, + .ways = 6, + .line_size = UNDEF, + .tlb_entries = 1536, + .partitioning = 0}; + case 0xCA: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_STLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 512, + .partitioning = 0}; + case 0xD0: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD1: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD2: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD6: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD7: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD8: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xDC: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * 1536 * KiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xDD: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 3 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xDE: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 6 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xE2: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xE3: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xE4: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xEA: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 12 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xEB: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 18 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xEC: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 24 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xF0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_PREFETCH, + .cache_size = 64 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xF1: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_PREFETCH, + .cache_size = 128 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xFF: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_NULL, + .cache_size = UNDEF, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + default: + return kEmptyCacheLevelInfo; + } +} + +static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg) { + for (int i = 0; i < 4; ++i) { + result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8); + } +} + +static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) { + Leaf leaf = SafeCpuId(max_cpuid_leaf, 2); + uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx}; + for (int i = 0; i < 4; ++i) { + if (registers[i] & (1U << 31)) { + continue; // register does not contains valid information + } + uint32_t bytes[4]; + GetByteArrayFromRegister(bytes, registers[i]); + for (int j = 0; j < 4; ++j) { + if (bytes[j] == 0xFF) + break; // leaf 4 should be used to fetch cache information + info->levels[info->size] = GetCacheLevelInfo(bytes[j]); + } + info->size++; + } +} + +static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) { + info->size = 0; + for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) { + const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id); + CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0); + if (cache_type == CPU_FEATURE_CACHE_NULL) { + info->levels[cache_id] = kEmptyCacheLevelInfo; + continue; + } + int level = ExtractBitRange(leaf.eax, 7, 5); + int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1; + int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1; + int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1; + int tlb_entries = leaf.ecx + 1; + int cache_size = (ways * partitioning * line_size * (tlb_entries)); + info->levels[cache_id] = (CacheLevelInfo){.level = level, + .cache_type = cache_type, + .cache_size = cache_size, + .ways = ways, + .line_size = line_size, + .tlb_entries = tlb_entries, + .partitioning = partitioning}; + info->size++; + } +} + +// Internal structure to hold the OS support for vector operations. +// Avoid to recompute them since each call to cpuid is ~100 cycles. +typedef struct { + bool have_sse; + bool have_avx; + bool have_avx512; + bool have_amx; +} OsSupport; + +// Reference https://en.wikipedia.org/wiki/CPUID. +static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, + OsSupport* os_support) { + const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1); + const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7); + const Leaf leaf_7_1 = SafeCpuIdEx(max_cpuid_leaf, 7, 1); + + const bool have_xsave = IsBitSet(leaf_1.ecx, 26); + const bool have_osxsave = IsBitSet(leaf_1.ecx, 27); + const uint32_t xcr0_eax = (have_xsave && have_osxsave) ? GetXCR0Eax() : 0; + os_support->have_sse = HasXmmOsXSave(xcr0_eax); + os_support->have_avx = HasYmmOsXSave(xcr0_eax); + os_support->have_avx512 = HasZmmOsXSave(xcr0_eax); + os_support->have_amx = HasTmmOsXSave(xcr0_eax); + + const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8); + const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20); + const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4); + const uint32_t extended_model = ExtractBitRange(leaf_1.eax, 19, 16); + + X86Features* const features = &info->features; + + info->family = extended_family + family; + info->model = (extended_model << 4) + model; + info->stepping = ExtractBitRange(leaf_1.eax, 3, 0); + + features->fpu = IsBitSet(leaf_1.edx, 0); + features->tsc = IsBitSet(leaf_1.edx, 4); + features->cx8 = IsBitSet(leaf_1.edx, 8); + features->clfsh = IsBitSet(leaf_1.edx, 19); + features->mmx = IsBitSet(leaf_1.edx, 23); + features->ss = IsBitSet(leaf_1.edx, 27); + features->pclmulqdq = IsBitSet(leaf_1.ecx, 1); + features->smx = IsBitSet(leaf_1.ecx, 6); + features->cx16 = IsBitSet(leaf_1.ecx, 13); + features->dca = IsBitSet(leaf_1.ecx, 18); + features->movbe = IsBitSet(leaf_1.ecx, 22); + features->popcnt = IsBitSet(leaf_1.ecx, 23); + features->aes = IsBitSet(leaf_1.ecx, 25); + features->f16c = IsBitSet(leaf_1.ecx, 29); + features->rdrnd = IsBitSet(leaf_1.ecx, 30); + features->sgx = IsBitSet(leaf_7.ebx, 2); + features->bmi1 = IsBitSet(leaf_7.ebx, 3); + features->hle = IsBitSet(leaf_7.ebx, 4); + features->bmi2 = IsBitSet(leaf_7.ebx, 8); + features->erms = IsBitSet(leaf_7.ebx, 9); + features->rtm = IsBitSet(leaf_7.ebx, 11); + features->rdseed = IsBitSet(leaf_7.ebx, 18); + features->clflushopt = IsBitSet(leaf_7.ebx, 23); + features->clwb = IsBitSet(leaf_7.ebx, 24); + features->sha = IsBitSet(leaf_7.ebx, 29); + features->vaes = IsBitSet(leaf_7.ecx, 9); + features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10); + + if (os_support->have_sse) { + features->sse = IsBitSet(leaf_1.edx, 25); + features->sse2 = IsBitSet(leaf_1.edx, 26); + features->sse3 = IsBitSet(leaf_1.ecx, 0); + features->ssse3 = IsBitSet(leaf_1.ecx, 9); + features->sse4_1 = IsBitSet(leaf_1.ecx, 19); + features->sse4_2 = IsBitSet(leaf_1.ecx, 20); + } + + if (os_support->have_avx) { + features->fma3 = IsBitSet(leaf_1.ecx, 12); + features->avx = IsBitSet(leaf_1.ecx, 28); + features->avx2 = IsBitSet(leaf_7.ebx, 5); + } + + if (os_support->have_avx512) { + features->avx512f = IsBitSet(leaf_7.ebx, 16); + features->avx512cd = IsBitSet(leaf_7.ebx, 28); + features->avx512er = IsBitSet(leaf_7.ebx, 27); + features->avx512pf = IsBitSet(leaf_7.ebx, 26); + features->avx512bw = IsBitSet(leaf_7.ebx, 30); + features->avx512dq = IsBitSet(leaf_7.ebx, 17); + features->avx512vl = IsBitSet(leaf_7.ebx, 31); + features->avx512ifma = IsBitSet(leaf_7.ebx, 21); + features->avx512vbmi = IsBitSet(leaf_7.ecx, 1); + features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6); + features->avx512vnni = IsBitSet(leaf_7.ecx, 11); + features->avx512bitalg = IsBitSet(leaf_7.ecx, 12); + features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14); + features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2); + features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3); + features->avx512_second_fma = HasSecondFMA(info->model); + features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3); + features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5); + features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8); + } + + if (os_support->have_amx) { + features->amx_bf16 = IsBitSet(leaf_7.edx, 22); + features->amx_tile = IsBitSet(leaf_7.edx, 24); + features->amx_int8 = IsBitSet(leaf_7.edx, 25); + } +} + +// Reference +// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented. +static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) { + const Leaf leaf_80000000 = CpuId(0x80000000); + const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax; + const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001); + + X86Features* const features = &info->features; + + if (os_support.have_sse) { + features->sse4a = IsBitSet(leaf_80000001.ecx, 6); + } + + if (os_support.have_avx) { + features->fma4 = IsBitSet(leaf_80000001.ecx, 16); + } +} + +static const X86Info kEmptyX86Info; +static const OsSupport kEmptyOsSupport; +static const CacheInfo kEmptyCacheInfo; + +X86Info GetX86Info(void) { + X86Info info = kEmptyX86Info; + OsSupport os_support = kEmptyOsSupport; + const Leaf leaf_0 = CpuId(0); + const bool is_intel = IsVendor(leaf_0, "GenuineIntel"); + const bool is_amd = IsVendor(leaf_0, "AuthenticAMD"); + SetVendor(leaf_0, info.vendor); + if (is_intel || is_amd) { + const uint32_t max_cpuid_leaf = leaf_0.eax; + ParseCpuId(max_cpuid_leaf, &info, &os_support); + } + if (is_amd) { + ParseExtraAMDCpuId(&info, os_support); + } + return info; +} + +CacheInfo GetX86CacheInfo(void) { + CacheInfo info = kEmptyCacheInfo; + const Leaf leaf_0 = CpuId(0); + const uint32_t max_cpuid_leaf = leaf_0.eax; + if (IsVendor(leaf_0, "GenuineIntel")) { + ParseLeaf2(max_cpuid_leaf, &info); + ParseLeaf4(max_cpuid_leaf, &info); + } + return info; +} + +#define CPUID(FAMILY, MODEL) ((((FAMILY)&0xFF) << 8) | ((MODEL)&0xFF)) + +X86Microarchitecture GetX86Microarchitecture(const X86Info* info) { + if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) { + switch (CPUID(info->family, info->model)) { + case CPUID(0x06, 0x35): + case CPUID(0x06, 0x36): + // https://en.wikipedia.org/wiki/Bonnell_(microarchitecture) + return INTEL_ATOM_BNL; + case CPUID(0x06, 0x37): + case CPUID(0x06, 0x4C): + // https://en.wikipedia.org/wiki/Silvermont + return INTEL_ATOM_SMT; + case CPUID(0x06, 0x5C): + // https://en.wikipedia.org/wiki/Goldmont + return INTEL_ATOM_GMT; + case CPUID(0x06, 0x0F): + case CPUID(0x06, 0x16): + // https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture) + return INTEL_CORE; + case CPUID(0x06, 0x17): + case CPUID(0x06, 0x1D): + // https://en.wikipedia.org/wiki/Penryn_(microarchitecture) + return INTEL_PNR; + case CPUID(0x06, 0x1A): + case CPUID(0x06, 0x1E): + case CPUID(0x06, 0x1F): + case CPUID(0x06, 0x2E): + // https://en.wikipedia.org/wiki/Nehalem_(microarchitecture) + return INTEL_NHM; + case CPUID(0x06, 0x25): + case CPUID(0x06, 0x2C): + case CPUID(0x06, 0x2F): + // https://en.wikipedia.org/wiki/Westmere_(microarchitecture) + return INTEL_WSM; + case CPUID(0x06, 0x2A): + case CPUID(0x06, 0x2D): + // https://en.wikipedia.org/wiki/Sandy_Bridge#Models_and_steppings + return INTEL_SNB; + case CPUID(0x06, 0x3A): + case CPUID(0x06, 0x3E): + // https://en.wikipedia.org/wiki/Ivy_Bridge_(microarchitecture)#Models_and_steppings + return INTEL_IVB; + case CPUID(0x06, 0x3C): + case CPUID(0x06, 0x3F): + case CPUID(0x06, 0x45): + case CPUID(0x06, 0x46): + // https://en.wikipedia.org/wiki/Haswell_(microarchitecture) + return INTEL_HSW; + case CPUID(0x06, 0x3D): + case CPUID(0x06, 0x47): + case CPUID(0x06, 0x4F): + case CPUID(0x06, 0x56): + // https://en.wikipedia.org/wiki/Broadwell_(microarchitecture) + return INTEL_BDW; + case CPUID(0x06, 0x4E): + case CPUID(0x06, 0x55): + case CPUID(0x06, 0x5E): + // https://en.wikipedia.org/wiki/Skylake_(microarchitecture) + return INTEL_SKL; + case CPUID(0x06, 0x66): + // https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture) + return INTEL_CNL; + case CPUID(0x06, 0x7D): // client + case CPUID(0x06, 0x7E): // client + case CPUID(0x06, 0x9D): // NNP-I + case CPUID(0x06, 0x6A): // server + case CPUID(0x06, 0x6C): // server + // https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor) + return INTEL_ICL; + case CPUID(0x06, 0x8C): + case CPUID(0x06, 0x8D): + // https://en.wikipedia.org/wiki/Tiger_Lake_(microarchitecture) + return INTEL_TGL; + case CPUID(0x06, 0x8F): + // https://en.wikipedia.org/wiki/Sapphire_Rapids + return INTEL_SPR; + case CPUID(0x06, 0x8E): + switch (info->stepping) { + case 9: + return INTEL_KBL; // https://en.wikipedia.org/wiki/Kaby_Lake + case 10: + return INTEL_CFL; // https://en.wikipedia.org/wiki/Coffee_Lake + case 11: + return INTEL_WHL; // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture) + default: + return X86_UNKNOWN; + } + case CPUID(0x06, 0x9E): + if (info->stepping > 9) { + // https://en.wikipedia.org/wiki/Coffee_Lake + return INTEL_CFL; + } else { + // https://en.wikipedia.org/wiki/Kaby_Lake + return INTEL_KBL; + } + default: + return X86_UNKNOWN; + } + } + if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) { + switch (info->family) { + // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures + case 0x0F: + return AMD_HAMMER; + case 0x10: + return AMD_K10; + case 0x14: + return AMD_BOBCAT; + case 0x15: + return AMD_BULLDOZER; + case 0x16: + return AMD_JAGUAR; + case 0x17: + return AMD_ZEN; + default: + return X86_UNKNOWN; + } + } + return X86_UNKNOWN; +} + +static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id, + char* buffer) { + const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id); + // We allow calling memcpy from SetString which is only called when requesting + // X86BrandString. + memcpy(buffer, &leaf, sizeof(Leaf)); +} + +void FillX86BrandString(char brand_string[49]) { + const Leaf leaf_ext_0 = CpuId(0x80000000); + const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax; + SetString(max_cpuid_leaf_ext, 0x80000002, brand_string); + SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16); + SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32); + brand_string[48] = '\0'; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetX86FeaturesEnumValue(const X86Features* features, + X86FeaturesEnum value) { + switch (value) { + case X86_FPU: + return features->fpu; + case X86_TSC: + return features->tsc; + case X86_CX8: + return features->cx8; + case X86_CLFSH: + return features->clfsh; + case X86_MMX: + return features->mmx; + case X86_AES: + return features->aes; + case X86_ERMS: + return features->erms; + case X86_F16C: + return features->f16c; + case X86_FMA4: + return features->fma4; + case X86_FMA3: + return features->fma3; + case X86_VAES: + return features->vaes; + case X86_VPCLMULQDQ: + return features->vpclmulqdq; + case X86_BMI1: + return features->bmi1; + case X86_HLE: + return features->hle; + case X86_BMI2: + return features->bmi2; + case X86_RTM: + return features->rtm; + case X86_RDSEED: + return features->rdseed; + case X86_CLFLUSHOPT: + return features->clflushopt; + case X86_CLWB: + return features->clwb; + case X86_SSE: + return features->sse; + case X86_SSE2: + return features->sse2; + case X86_SSE3: + return features->sse3; + case X86_SSSE3: + return features->ssse3; + case X86_SSE4_1: + return features->sse4_1; + case X86_SSE4_2: + return features->sse4_2; + case X86_SSE4A: + return features->sse4a; + case X86_AVX: + return features->avx; + case X86_AVX2: + return features->avx2; + case X86_AVX512F: + return features->avx512f; + case X86_AVX512CD: + return features->avx512cd; + case X86_AVX512ER: + return features->avx512er; + case X86_AVX512PF: + return features->avx512pf; + case X86_AVX512BW: + return features->avx512bw; + case X86_AVX512DQ: + return features->avx512dq; + case X86_AVX512VL: + return features->avx512vl; + case X86_AVX512IFMA: + return features->avx512ifma; + case X86_AVX512VBMI: + return features->avx512vbmi; + case X86_AVX512VBMI2: + return features->avx512vbmi2; + case X86_AVX512VNNI: + return features->avx512vnni; + case X86_AVX512BITALG: + return features->avx512bitalg; + case X86_AVX512VPOPCNTDQ: + return features->avx512vpopcntdq; + case X86_AVX512_4VNNIW: + return features->avx512_4vnniw; + case X86_AVX512_4VBMI2: + return features->avx512_4vbmi2; + case X86_AVX512_SECOND_FMA: + return features->avx512_second_fma; + case X86_AVX512_4FMAPS: + return features->avx512_4fmaps; + case X86_AVX512_BF16: + return features->avx512_bf16; + case X86_AVX512_VP2INTERSECT: + return features->avx512_vp2intersect; + case X86_AMX_BF16: + return features->amx_bf16; + case X86_AMX_TILE: + return features->amx_tile; + case X86_AMX_INT8: + return features->amx_int8; + case X86_PCLMULQDQ: + return features->pclmulqdq; + case X86_SMX: + return features->smx; + case X86_SGX: + return features->sgx; + case X86_CX16: + return features->cx16; + case X86_SHA: + return features->sha; + case X86_POPCNT: + return features->popcnt; + case X86_MOVBE: + return features->movbe; + case X86_RDRND: + return features->rdrnd; + case X86_DCA: + return features->dca; + case X86_SS: + return features->ss; + case X86_LAST_: + break; + } + return false; +} + +const char* GetX86FeaturesEnumName(X86FeaturesEnum value) { + switch (value) { + case X86_FPU: + return "fpu"; + case X86_TSC: + return "tsc"; + case X86_CX8: + return "cx8"; + case X86_CLFSH: + return "clfsh"; + case X86_MMX: + return "mmx"; + case X86_AES: + return "aes"; + case X86_ERMS: + return "erms"; + case X86_F16C: + return "f16c"; + case X86_FMA4: + return "fma4"; + case X86_FMA3: + return "fma3"; + case X86_VAES: + return "vaes"; + case X86_VPCLMULQDQ: + return "vpclmulqdq"; + case X86_BMI1: + return "bmi1"; + case X86_HLE: + return "hle"; + case X86_BMI2: + return "bmi2"; + case X86_RTM: + return "rtm"; + case X86_RDSEED: + return "rdseed"; + case X86_CLFLUSHOPT: + return "clflushopt"; + case X86_CLWB: + return "clwb"; + case X86_SSE: + return "sse"; + case X86_SSE2: + return "sse2"; + case X86_SSE3: + return "sse3"; + case X86_SSSE3: + return "ssse3"; + case X86_SSE4_1: + return "sse4_1"; + case X86_SSE4_2: + return "sse4_2"; + case X86_SSE4A: + return "sse4a"; + case X86_AVX: + return "avx"; + case X86_AVX2: + return "avx2"; + case X86_AVX512F: + return "avx512f"; + case X86_AVX512CD: + return "avx512cd"; + case X86_AVX512ER: + return "avx512er"; + case X86_AVX512PF: + return "avx512pf"; + case X86_AVX512BW: + return "avx512bw"; + case X86_AVX512DQ: + return "avx512dq"; + case X86_AVX512VL: + return "avx512vl"; + case X86_AVX512IFMA: + return "avx512ifma"; + case X86_AVX512VBMI: + return "avx512vbmi"; + case X86_AVX512VBMI2: + return "avx512vbmi2"; + case X86_AVX512VNNI: + return "avx512vnni"; + case X86_AVX512BITALG: + return "avx512bitalg"; + case X86_AVX512VPOPCNTDQ: + return "avx512vpopcntdq"; + case X86_AVX512_4VNNIW: + return "avx512_4vnniw"; + case X86_AVX512_4VBMI2: + return "avx512_4vbmi2"; + case X86_AVX512_SECOND_FMA: + return "avx512_second_fma"; + case X86_AVX512_4FMAPS: + return "avx512_4fmaps"; + case X86_AVX512_BF16: + return "avx512_bf16"; + case X86_AVX512_VP2INTERSECT: + return "avx512_vp2intersect"; + case X86_AMX_BF16: + return "amx_bf16"; + case X86_AMX_TILE: + return "amx_tile"; + case X86_AMX_INT8: + return "amx_int8"; + case X86_PCLMULQDQ: + return "pclmulqdq"; + case X86_SMX: + return "smx"; + case X86_SGX: + return "sgx"; + case X86_CX16: + return "cx16"; + case X86_SHA: + return "sha"; + case X86_POPCNT: + return "popcnt"; + case X86_MOVBE: + return "movbe"; + case X86_RDRND: + return "rdrnd"; + case X86_DCA: + return "dca"; + case X86_SS: + return "ss"; + case X86_LAST_: + break; + } + return "unknown_feature"; +} + +const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) { + switch (uarch) { + case X86_UNKNOWN: + return "X86_UNKNOWN"; + case INTEL_CORE: + return "INTEL_CORE"; + case INTEL_PNR: + return "INTEL_PNR"; + case INTEL_NHM: + return "INTEL_NHM"; + case INTEL_ATOM_BNL: + return "INTEL_ATOM_BNL"; + case INTEL_WSM: + return "INTEL_WSM"; + case INTEL_SNB: + return "INTEL_SNB"; + case INTEL_IVB: + return "INTEL_IVB"; + case INTEL_ATOM_SMT: + return "INTEL_ATOM_SMT"; + case INTEL_HSW: + return "INTEL_HSW"; + case INTEL_BDW: + return "INTEL_BDW"; + case INTEL_SKL: + return "INTEL_SKL"; + case INTEL_ATOM_GMT: + return "INTEL_ATOM_GMT"; + case INTEL_KBL: + return "INTEL_KBL"; + case INTEL_CFL: + return "INTEL_CFL"; + case INTEL_WHL: + return "INTEL_WHL"; + case INTEL_CNL: + return "INTEL_CNL"; + case INTEL_ICL: + return "INTEL_ICL"; + case INTEL_TGL: + return "INTEL_TGL"; + case INTEL_SPR: + return "INTEL_SPR"; + case AMD_HAMMER: + return "AMD_HAMMER"; + case AMD_K10: + return "AMD_K10"; + case AMD_BOBCAT: + return "AMD_BOBCAT"; + case AMD_BULLDOZER: + return "AMD_BULLDOZER"; + case AMD_JAGUAR: + return "AMD_JAGUAR"; + case AMD_ZEN: + return "AMD_ZEN"; + } + return "unknown microarchitecture"; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c new file mode 100644 index 0000000..2f7083b --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/filesystem.c @@ -0,0 +1,62 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/filesystem.h" + +#include +#include +#include +#include +#include + +#if defined(CPU_FEATURES_MOCK_FILESYSTEM) +// Implementation will be provided by test/filesystem_for_testing.cc. +#elif defined(_MSC_VER) +#include +int CpuFeatures_OpenFile(const char* filename) { + int fd = -1; + _sopen_s(&fd, filename, _O_RDONLY, _SH_DENYWR, _S_IREAD); + return fd; +} + +void CpuFeatures_CloseFile(int file_descriptor) { _close(file_descriptor); } + +int CpuFeatures_ReadFile(int file_descriptor, void* buffer, + size_t buffer_size) { + return _read(file_descriptor, buffer, (unsigned int)buffer_size); +} + +#else +#include + +int CpuFeatures_OpenFile(const char* filename) { + int result; + do { + result = open(filename, O_RDONLY); + } while (result == -1L && errno == EINTR); + return result; +} + +void CpuFeatures_CloseFile(int file_descriptor) { close(file_descriptor); } + +int CpuFeatures_ReadFile(int file_descriptor, void* buffer, + size_t buffer_size) { + int result; + do { + result = read(file_descriptor, buffer, buffer_size); + } while (result == -1L && errno == EINTR); + return result; +} + +#endif diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c new file mode 100644 index 0000000..920e2f3 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/hwcaps.c @@ -0,0 +1,163 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/hwcaps.h" + +#include +#include + +#include "cpu_features_macros.h" +#include "internal/filesystem.h" +#include "internal/string_view.h" + +#if defined(NDEBUG) +#define D(...) +#else +#include +#define D(...) \ + do { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } while (0) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Implementation of GetElfHwcapFromGetauxval +//////////////////////////////////////////////////////////////////////////////// + +#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL) +// Implementation will be provided by test/hwcaps_for_testing.cc. +#elif defined(HAVE_STRONG_GETAUXVAL) +#include +static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { + return getauxval(hwcap_type); +} +#elif defined(HAVE_DLFCN_H) +// On Android we probe the system's C library for a 'getauxval' function and +// call it if it exits, or return 0 for failure. This function is available +// since API level 20. +// +// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge +// case where some NDK developers use headers for a platform that is newer than +// the one really targetted by their application. This is typically done to use +// newer native APIs only when running on more recent Android versions, and +// requires careful symbol management. +// +// Note that getauxval() can't really be re-implemented here, because its +// implementation does not parse /proc/self/auxv. Instead it depends on values +// that are passed by the kernel at process-init time to the C runtime +// initialization layer. + +#include +#define AT_HWCAP 16 +#define AT_HWCAP2 26 +#define AT_PLATFORM 15 +#define AT_BASE_PLATFORM 24 + +typedef unsigned long getauxval_func_t(unsigned long); + +static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) { + uint32_t ret = 0; + void *libc_handle = NULL; + getauxval_func_t *func = NULL; + + dlerror(); // Cleaning error state before calling dlopen. + libc_handle = dlopen("libc.so", RTLD_NOW); + if (!libc_handle) { + D("Could not dlopen() C library: %s\n", dlerror()); + return 0; + } + func = (getauxval_func_t *)dlsym(libc_handle, "getauxval"); + if (!func) { + D("Could not find getauxval() in C library\n"); + } else { + // Note: getauxval() returns 0 on failure. Doesn't touch errno. + ret = (uint32_t)(*func)(hwcap_type); + } + dlclose(libc_handle); + return ret; +} +#else +#error "This platform does not provide hardware capabilities." +#endif + +// Implementation of GetHardwareCapabilities for OS that provide +// GetElfHwcapFromGetauxval(). + +// Fallback when getauxval is not available, retrieves hwcaps from +// "/proc/self/auxv". +static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) { + struct { + uint32_t tag; + uint32_t value; + } entry; + uint32_t result = 0; + const char filepath[] = "/proc/self/auxv"; + const int fd = CpuFeatures_OpenFile(filepath); + if (fd < 0) { + D("Could not open %s\n", filepath); + return 0; + } + for (;;) { + const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry); + if (ret < 0) { + D("Error while reading %s\n", filepath); + break; + } + // Detect end of list. + if (ret == 0 || (entry.tag == 0 && entry.value == 0)) { + break; + } + if (entry.tag == hwcap_type) { + result = entry.value; + break; + } + } + CpuFeatures_CloseFile(fd); + return result; +} + +// Retrieves hardware capabilities by first trying to call getauxval, if not +// available falls back to reading "/proc/self/auxv". +static unsigned long GetHardwareCapabilitiesFor(uint32_t type) { + unsigned long hwcaps = GetElfHwcapFromGetauxval(type); + if (!hwcaps) { + D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); + hwcaps = GetElfHwcapFromProcSelfAuxv(type); + } + return hwcaps; +} + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { + HardwareCapabilities capabilities; + capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP); + capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2); + return capabilities; +} + +PlatformType kEmptyPlatformType; + +PlatformType CpuFeatures_GetPlatformType(void) { + PlatformType type = kEmptyPlatformType; + char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM); + char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); + + if (platform != NULL) + CpuFeatures_StringView_CopyString(str(platform), type.platform, + sizeof(type.platform)); + if (base_platform != NULL) + CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform, + sizeof(type.base_platform)); + return type; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c new file mode 100644 index 0000000..dd29781 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/stack_line_reader.c @@ -0,0 +1,132 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/stack_line_reader.h" + +#include +#include +#include + +#include "internal/filesystem.h" + +void StackLineReader_Initialize(StackLineReader* reader, int fd) { + reader->view.ptr = reader->buffer; + reader->view.size = 0; + reader->skip_mode = false; + reader->fd = fd; +} + +// Replaces the content of buffer with bytes from the file. +static int LoadFullBuffer(StackLineReader* reader) { + const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer, + STACK_LINE_READER_BUFFER_SIZE); + assert(read >= 0); + reader->view.ptr = reader->buffer; + reader->view.size = read; + return read; +} + +// Appends with bytes from the file to buffer, filling the remaining space. +static int LoadMore(StackLineReader* reader) { + char* const ptr = reader->buffer + reader->view.size; + const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size; + const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read); + assert(read >= 0); + assert(read <= (int)size_to_read); + reader->view.size += read; + return read; +} + +static int IndexOfEol(StackLineReader* reader) { + return CpuFeatures_StringView_IndexOfChar(reader->view, '\n'); +} + +// Relocate buffer's pending bytes at the beginning of the array and fills the +// remaining space with bytes from the file. +static int BringToFrontAndLoadMore(StackLineReader* reader) { + if (reader->view.size && reader->view.ptr != reader->buffer) { + memmove(reader->buffer, reader->view.ptr, reader->view.size); + } + reader->view.ptr = reader->buffer; + return LoadMore(reader); +} + +// Loads chunks of buffer size from disks until it contains a newline character +// or end of file. +static void SkipToNextLine(StackLineReader* reader) { + for (;;) { + const int read = LoadFullBuffer(reader); + if (read == 0) { + break; + } else { + const int eol_index = IndexOfEol(reader); + if (eol_index >= 0) { + reader->view = + CpuFeatures_StringView_PopFront(reader->view, eol_index + 1); + break; + } + } + } +} + +static LineResult CreateLineResult(bool eof, bool full_line, StringView view) { + LineResult result; + result.eof = eof; + result.full_line = full_line; + result.line = view; + return result; +} + +// Helper methods to provide clearer semantic in StackLineReader_NextLine. +static LineResult CreateEOFLineResult(StringView view) { + return CreateLineResult(true, true, view); +} + +static LineResult CreateTruncatedLineResult(StringView view) { + return CreateLineResult(false, false, view); +} + +static LineResult CreateValidLineResult(StringView view) { + return CreateLineResult(false, true, view); +} + +LineResult StackLineReader_NextLine(StackLineReader* reader) { + if (reader->skip_mode) { + SkipToNextLine(reader); + reader->skip_mode = false; + } + { + const bool can_load_more = + reader->view.size < STACK_LINE_READER_BUFFER_SIZE; + int eol_index = IndexOfEol(reader); + if (eol_index < 0 && can_load_more) { + const int read = BringToFrontAndLoadMore(reader); + if (read == 0) { + return CreateEOFLineResult(reader->view); + } + eol_index = IndexOfEol(reader); + } + if (eol_index < 0) { + reader->skip_mode = true; + return CreateTruncatedLineResult(reader->view); + } + { + StringView line = + CpuFeatures_StringView_KeepFront(reader->view, eol_index); + reader->view = + CpuFeatures_StringView_PopFront(reader->view, eol_index + 1); + return CreateValidLineResult(line); + } + } +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c new file mode 100644 index 0000000..856731c --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/string_view.c @@ -0,0 +1,182 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/string_view.h" + +#include +#include +#include + +int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) { + if (view.ptr && view.size) { + const char* const found = (const char*)memchr(view.ptr, c, view.size); + if (found) { + return (int)(found - view.ptr); + } + } + return -1; +} + +int CpuFeatures_StringView_IndexOf(const StringView view, + const StringView sub_view) { + if (sub_view.size) { + StringView remainder = view; + while (remainder.size >= sub_view.size) { + const int found_index = + CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]); + if (found_index < 0) break; + remainder = CpuFeatures_StringView_PopFront(remainder, found_index); + if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) { + return (int)(remainder.ptr - view.ptr); + } + remainder = CpuFeatures_StringView_PopFront(remainder, 1); + } + } + return -1; +} + +bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) { + if (a.size == b.size) { + return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0; + } + return false; +} + +bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) { + return a.ptr && b.ptr && b.size && a.size >= b.size + ? memcmp(a.ptr, b.ptr, b.size) == 0 + : false; +} + +StringView CpuFeatures_StringView_PopFront(const StringView str_view, + size_t count) { + if (count > str_view.size) { + return kEmptyStringView; + } + return view(str_view.ptr + count, str_view.size - count); +} + +StringView CpuFeatures_StringView_PopBack(const StringView str_view, + size_t count) { + if (count > str_view.size) { + return kEmptyStringView; + } + return view(str_view.ptr, str_view.size - count); +} + +StringView CpuFeatures_StringView_KeepFront(const StringView str_view, + size_t count) { + return count <= str_view.size ? view(str_view.ptr, count) : str_view; +} + +char CpuFeatures_StringView_Front(const StringView view) { + assert(view.size); + assert(view.ptr); + return view.ptr[0]; +} + +char CpuFeatures_StringView_Back(const StringView view) { + assert(view.size); + return view.ptr[view.size - 1]; +} + +StringView CpuFeatures_StringView_TrimWhitespace(StringView view) { + while (view.size && isspace(CpuFeatures_StringView_Front(view))) + view = CpuFeatures_StringView_PopFront(view, 1); + while (view.size && isspace(CpuFeatures_StringView_Back(view))) + view = CpuFeatures_StringView_PopBack(view, 1); + return view; +} + +static int HexValue(const char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return -1; +} + +// Returns -1 if view contains non digits. +static int ParsePositiveNumberWithBase(const StringView view, int base) { + int result = 0; + StringView remainder = view; + for (; remainder.size; + remainder = CpuFeatures_StringView_PopFront(remainder, 1)) { + const int value = HexValue(CpuFeatures_StringView_Front(remainder)); + if (value < 0 || value >= base) return -1; + result = (result * base) + value; + } + return result; +} + +int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) { + if (view.size) { + const StringView hex_prefix = str("0x"); + if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) { + const StringView span_no_prefix = + CpuFeatures_StringView_PopFront(view, hex_prefix.size); + return ParsePositiveNumberWithBase(span_no_prefix, 16); + } + return ParsePositiveNumberWithBase(view, 10); + } + return -1; +} + +void CpuFeatures_StringView_CopyString(const StringView src, char* dst, + size_t dst_size) { + if (dst_size > 0) { + const size_t max_copy_size = dst_size - 1; + const size_t copy_size = + src.size > max_copy_size ? max_copy_size : src.size; + memcpy(dst, src.ptr, copy_size); + dst[copy_size] = '\0'; + } +} + +bool CpuFeatures_StringView_HasWord(const StringView line, + const char* const word_str) { + const StringView word = str(word_str); + StringView remainder = line; + for (;;) { + const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word); + if (index_of_word < 0) { + return false; + } else { + const StringView before = + CpuFeatures_StringView_KeepFront(line, index_of_word); + const StringView after = + CpuFeatures_StringView_PopFront(line, index_of_word + word.size); + const bool valid_before = + before.size == 0 || CpuFeatures_StringView_Back(before) == ' '; + const bool valid_after = + after.size == 0 || CpuFeatures_StringView_Front(after) == ' '; + if (valid_before && valid_after) return true; + remainder = + CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size); + } + } + return false; +} + +bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line, + StringView* key, + StringView* value) { + const StringView sep = str(": "); + const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep); + if (index_of_separator < 0) return false; + *value = CpuFeatures_StringView_TrimWhitespace( + CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size)); + *key = CpuFeatures_StringView_TrimWhitespace( + CpuFeatures_StringView_KeepFront(line, index_of_separator)); + return true; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c new file mode 100644 index 0000000..2f51ae4 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/unix_features_aggregator.c @@ -0,0 +1,53 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/unix_features_aggregator.h" + +#include "internal/string_view.h" + +void CpuFeatures_SetFromFlags(const size_t configs_size, + const CapabilityConfig* configs, + const StringView flags_line, + void* const features) { + size_t i = 0; + for (; i < configs_size; ++i) { + const CapabilityConfig config = configs[i]; + config.set_bit(features, CpuFeatures_StringView_HasWord( + flags_line, config.proc_cpuinfo_flag)); + } +} + +static bool IsSet(const uint32_t mask, const uint32_t value) { + if (mask == 0) return false; + return (value & mask) == mask; +} + +static bool IsHwCapsSet(const HardwareCapabilities hwcaps_mask, + const HardwareCapabilities hwcaps) { + return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) || + IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2); +} + +void CpuFeatures_OverrideFromHwCaps(const size_t configs_size, + const CapabilityConfig* configs, + const HardwareCapabilities hwcaps, + void* const features) { + size_t i = 0; + for (; i < configs_size; ++i) { + const CapabilityConfig* config = &configs[i]; + if (IsHwCapsSet(config->hwcaps_mask, hwcaps)) { + config->set_bit(features, true); + } + } +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c new file mode 100644 index 0000000..0783648 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/src/utils/list_cpu_features.c @@ -0,0 +1,438 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This program dumps current host data to the standard output. +// Output can be text or json if the `--json` flag is passed. + +#include +#include +#include +#include +#include +#include +#include + +#include "cpu_features_macros.h" + +#if defined(CPU_FEATURES_ARCH_X86) +#include "cpuinfo_x86.h" +#elif defined(CPU_FEATURES_ARCH_ARM) +#include "cpuinfo_arm.h" +#elif defined(CPU_FEATURES_ARCH_AARCH64) +#include "cpuinfo_aarch64.h" +#elif defined(CPU_FEATURES_ARCH_MIPS) +#include "cpuinfo_mips.h" +#elif defined(CPU_FEATURES_ARCH_PPC) +#include "cpuinfo_ppc.h" +#endif + +// Design principles +// ----------------- +// We build a tree structure containing all the data to be displayed. +// Then depending on the output type (text or json) we walk the tree and display +// the data accordingly. + +// We use a bump allocator to allocate strings and nodes of the tree, +// Memory is not intented to be reclaimed. +typedef struct { + char* ptr; + size_t size; +} BumpAllocator; + +char gGlobalBuffer[64 * 1024]; +BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer, + .size = sizeof(gGlobalBuffer)}; + +static void internal_error() { + fputs("internal error\n", stderr); + exit(EXIT_FAILURE); +} + +#define ALIGN 8 + +static void assertAligned() { + if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error(); +} + +static void BA_Align() { + while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) { + --gBumpAllocator.size; + ++gBumpAllocator.ptr; + } + assertAligned(); +} + +// Update the available memory left in the BumpAllocator. +static void* BA_Bump(size_t size) { + assertAligned(); + // Align size to next 8B boundary. + size = (size + ALIGN - 1) / ALIGN * ALIGN; + if (gBumpAllocator.size < size) internal_error(); + void* ptr = gBumpAllocator.ptr; + gBumpAllocator.size -= size; + gBumpAllocator.ptr += size; + return ptr; +} + +// The type of the nodes in the tree. +typedef enum { + NT_INVALID, + NT_INT, + NT_MAP, + NT_MAP_ENTRY, + NT_ARRAY, + NT_ARRAY_ELEMENT, + NT_STRING, +} NodeType; + +// The node in the tree. +typedef struct Node { + NodeType type; + unsigned integer; + const char* string; + struct Node* value; + struct Node* next; +} Node; + +// Creates an initialized Node. +static Node* BA_CreateNode(NodeType type) { + Node* tv = (Node*)BA_Bump(sizeof(Node)); + assert(tv); + *tv = (Node){.type = type}; + return tv; +} + +// Adds an integer node. +static Node* CreateInt(int value) { + Node* tv = BA_CreateNode(NT_INT); + tv->integer = value; + return tv; +} + +// Adds a string node. +// `value` must outlive the tree. +static Node* CreateConstantString(const char* value) { + Node* tv = BA_CreateNode(NT_STRING); + tv->string = value; + return tv; +} + +// Adds a map node. +static Node* CreateMap() { return BA_CreateNode(NT_MAP); } + +// Adds an array node. +static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); } + +// Adds a formatted string node. +static Node* CreatePrintfString(const char* format, ...) { + va_list arglist; + va_start(arglist, format); + char* const ptr = gBumpAllocator.ptr; + const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist); + va_end(arglist); + if (written < 0 || written >= (int)gBumpAllocator.size) internal_error(); + return CreateConstantString((char*)BA_Bump(written)); +} + +// Adds a string node. +static Node* CreateString(const char* value) { + return CreatePrintfString("%s", value); +} + +// Adds a map entry node. +static void AddMapEntry(Node* map, const char* key, Node* value) { + assert(map && map->type == NT_MAP); + Node* current = map; + while (current->next) current = current->next; + current->next = (Node*)BA_Bump(sizeof(Node)); + *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value}; +} + +// Adds an array element node. +static void AddArrayElement(Node* array, Node* value) { + assert(array && array->type == NT_ARRAY); + Node* current = array; + while (current->next) current = current->next; + current->next = (Node*)BA_Bump(sizeof(Node)); + *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value}; +} + +static int cmp(const void* p1, const void* p2) { + return strcmp(*(const char* const*)p1, *(const char* const*)p2); +} + +#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \ + static void AddFlags(Node* map, const FeatureType* features) { \ + size_t i; \ + const char* ptrs[LastEnum] = {0}; \ + size_t count = 0; \ + for (i = 0; i < LastEnum; ++i) { \ + if (HasFeature(features, i)) { \ + ptrs[count] = FeatureName(i); \ + ++count; \ + } \ + } \ + qsort((void*)ptrs, count, sizeof(char*), cmp); \ + Node* const array = CreateArray(); \ + for (i = 0; i < count; ++i) \ + AddArrayElement(array, CreateConstantString(ptrs[i])); \ + AddMapEntry(map, "flags", array); \ + } + +#if defined(CPU_FEATURES_ARCH_X86) +DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features, + X86_LAST_) +#elif defined(CPU_FEATURES_ARCH_ARM) +DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures, + ARM_LAST_) +#elif defined(CPU_FEATURES_ARCH_AARCH64) +DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName, + Aarch64Features, AARCH64_LAST_) +#elif defined(CPU_FEATURES_ARCH_MIPS) +DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName, + MipsFeatures, MIPS_LAST_) +#elif defined(CPU_FEATURES_ARCH_PPC) +DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures, + PPC_LAST_) +#endif + +// Prints a json string with characters escaping. +static void printJsonString(const char* str) { + putchar('"'); + for (; str && *str; ++str) { + switch (*str) { + case '\"': + case '\\': + case '/': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + putchar('\\'); + } + putchar(*str); + } + putchar('"'); +} + +// Walks a Node and print it as json. +static void printJson(const Node* current) { + assert(current); + switch (current->type) { + case NT_INVALID: + break; + case NT_INT: + printf("%d", current->integer); + break; + case NT_STRING: + printJsonString(current->string); + break; + case NT_ARRAY: + putchar('['); + if (current->next) printJson(current->next); + putchar(']'); + break; + case NT_MAP: + putchar('{'); + if (current->next) printJson(current->next); + putchar('}'); + break; + case NT_MAP_ENTRY: + printf("\"%s\":", current->string); + printJson(current->value); + if (current->next) { + putchar(','); + printJson(current->next); + } + break; + case NT_ARRAY_ELEMENT: + printJson(current->value); + if (current->next) { + putchar(','); + printJson(current->next); + } + break; + } +} + +// Walks a Node and print it as text. +static void printTextField(const Node* current) { + switch (current->type) { + case NT_INVALID: + break; + case NT_INT: + printf("%3d (0x%02X)", current->integer, current->integer); + break; + case NT_STRING: + fputs(current->string, stdout); + break; + case NT_ARRAY: + if (current->next) printTextField(current->next); + break; + case NT_MAP: + if (current->next) { + printf("{"); + printJson(current->next); + printf("}"); + } + break; + case NT_MAP_ENTRY: + printf("%-15s : ", current->string); + printTextField(current->value); + if (current->next) { + putchar('\n'); + printTextField(current->next); + } + break; + case NT_ARRAY_ELEMENT: + printTextField(current->value); + if (current->next) { + putchar(','); + printTextField(current->next); + } + break; + } +} + +static void printTextRoot(const Node* current) { + if (current->type == NT_MAP && current->next) printTextField(current->next); +} + +static void showUsage(const char* name) { + printf( + "\n" + "Usage: %s [options]\n" + " Options:\n" + " -h | --help Show help message.\n" + " -j | --json Format output as json instead of plain text.\n" + "\n", + name); +} + +static Node* GetCacheTypeString(CacheType cache_type) { + switch (cache_type) { + case CPU_FEATURE_CACHE_NULL: + return CreateConstantString("null"); + case CPU_FEATURE_CACHE_DATA: + return CreateConstantString("data"); + case CPU_FEATURE_CACHE_INSTRUCTION: + return CreateConstantString("instruction"); + case CPU_FEATURE_CACHE_UNIFIED: + return CreateConstantString("unified"); + case CPU_FEATURE_CACHE_TLB: + return CreateConstantString("tlb"); + case CPU_FEATURE_CACHE_DTLB: + return CreateConstantString("dtlb"); + case CPU_FEATURE_CACHE_STLB: + return CreateConstantString("stlb"); + case CPU_FEATURE_CACHE_PREFETCH: + return CreateConstantString("prefetch"); + } +} + +static void AddCacheInfo(Node* root, const CacheInfo* cache_info) { + Node* array = CreateArray(); + for (int i = 0; i < cache_info->size; ++i) { + CacheLevelInfo info = cache_info->levels[i]; + Node* map = CreateMap(); + AddMapEntry(map, "level", CreateInt(info.level)); + AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type)); + AddMapEntry(map, "cache_size", CreateInt(info.cache_size)); + AddMapEntry(map, "ways", CreateInt(info.ways)); + AddMapEntry(map, "line_size", CreateInt(info.line_size)); + AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries)); + AddMapEntry(map, "partitioning", CreateInt(info.partitioning)); + AddArrayElement(array, map); + } + AddMapEntry(root, "cache_info", array); +} + +static Node* CreateTree() { + Node* root = CreateMap(); +#if defined(CPU_FEATURES_ARCH_X86) + char brand_string[49]; + const X86Info info = GetX86Info(); + const CacheInfo cache_info = GetX86CacheInfo(); + FillX86BrandString(brand_string); + AddMapEntry(root, "arch", CreateString("x86")); + AddMapEntry(root, "brand", CreateString(brand_string)); + AddMapEntry(root, "family", CreateInt(info.family)); + AddMapEntry(root, "model", CreateInt(info.model)); + AddMapEntry(root, "stepping", CreateInt(info.stepping)); + AddMapEntry(root, "uarch", + CreateString( + GetX86MicroarchitectureName(GetX86Microarchitecture(&info)))); + AddFlags(root, &info.features); + AddCacheInfo(root, &cache_info); +#elif defined(CPU_FEATURES_ARCH_ARM) + const ArmInfo info = GetArmInfo(); + AddMapEntry(root, "arch", CreateString("ARM")); + AddMapEntry(root, "implementer", CreateInt(info.implementer)); + AddMapEntry(root, "architecture", CreateInt(info.architecture)); + AddMapEntry(root, "variant", CreateInt(info.variant)); + AddMapEntry(root, "part", CreateInt(info.part)); + AddMapEntry(root, "revision", CreateInt(info.revision)); + AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_AARCH64) + const Aarch64Info info = GetAarch64Info(); + AddMapEntry(root, "arch", CreateString("aarch64")); + AddMapEntry(root, "implementer", CreateInt(info.implementer)); + AddMapEntry(root, "variant", CreateInt(info.variant)); + AddMapEntry(root, "part", CreateInt(info.part)); + AddMapEntry(root, "revision", CreateInt(info.revision)); + AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_MIPS) + const MipsInfo info = GetMipsInfo(); + AddMapEntry(root, "arch", CreateString("mips")); + AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_PPC) + const PPCInfo info = GetPPCInfo(); + const PPCPlatformStrings strings = GetPPCPlatformStrings(); + AddMapEntry(root, "arch", CreateString("ppc")); + AddMapEntry(root, "platform", CreateString(strings.platform)); + AddMapEntry(root, "model", CreateString(strings.model)); + AddMapEntry(root, "machine", CreateString(strings.machine)); + AddMapEntry(root, "cpu", CreateString(strings.cpu)); + AddMapEntry(root, "instruction", CreateString(strings.type.platform)); + AddMapEntry(root, "microarchitecture", + CreateString(strings.type.base_platform)); + AddFlags(root, &info.features); +#endif + return root; +} + +int main(int argc, char** argv) { + BA_Align(); + const Node* const root = CreateTree(); + bool outputJson = false; + int i = 1; + for (; i < argc; ++i) { + const char* arg = argv[i]; + if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) { + outputJson = true; + } else { + showUsage(argv[0]); + if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) + return EXIT_SUCCESS; + return EXIT_FAILURE; + } + } + if (outputJson) + printJson(root); + else + printTextRoot(root); + putchar('\n'); + return EXIT_SUCCESS; +} diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/CMakeLists.txt b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/CMakeLists.txt new file mode 100644 index 0000000..eb67ac0 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/CMakeLists.txt @@ -0,0 +1,88 @@ +# +# libraries for tests +# + +include_directories(../include) +add_definitions(-DCPU_FEATURES_TEST) + +##------------------------------------------------------------------------------ +add_library(string_view ../src/string_view.c) +##------------------------------------------------------------------------------ +add_library(filesystem_for_testing filesystem_for_testing.cc) +target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM) +##------------------------------------------------------------------------------ +add_library(hwcaps_for_testing hwcaps_for_testing.cc) +target_compile_definitions(hwcaps_for_testing PUBLIC CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL) +target_link_libraries(hwcaps_for_testing filesystem_for_testing) +##------------------------------------------------------------------------------ +add_library(stack_line_reader ../src/stack_line_reader.c) +target_compile_definitions(stack_line_reader PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024) +target_link_libraries(stack_line_reader string_view) +##------------------------------------------------------------------------------ +add_library(stack_line_reader_for_test ../src/stack_line_reader.c) +target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16) +target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing) +##------------------------------------------------------------------------------ +add_library(all_libraries ../src/stack_line_reader.c ../src/unix_features_aggregator.c) +target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view) + +# +# tests +# +link_libraries(gtest gmock_main) + +## bit_utils_test +add_executable(bit_utils_test bit_utils_test.cc) +target_link_libraries(bit_utils_test) +add_test(NAME bit_utils_test COMMAND bit_utils_test) +##------------------------------------------------------------------------------ +## string_view_test +add_executable(string_view_test string_view_test.cc ../src/string_view.c) +target_link_libraries(string_view_test string_view) +add_test(NAME string_view_test COMMAND string_view_test) +##------------------------------------------------------------------------------ +## stack_line_reader_test +add_executable(stack_line_reader_test stack_line_reader_test.cc) +target_link_libraries(stack_line_reader_test stack_line_reader_for_test) +add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test) +##------------------------------------------------------------------------------ +## unix_features_aggregator_test +add_executable(unix_features_aggregator_test unix_features_aggregator_test.cc) +target_link_libraries(unix_features_aggregator_test all_libraries) +add_test(NAME unix_features_aggregator_test COMMAND unix_features_aggregator_test) +##------------------------------------------------------------------------------ +## cpuinfo_x86_test +if(PROCESSOR_IS_X86) + add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c) + target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86) + target_link_libraries(cpuinfo_x86_test all_libraries) + add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_arm_test +if(PROCESSOR_IS_ARM) + add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/cpuinfo_arm.c) + target_link_libraries(cpuinfo_arm_test all_libraries) + add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_aarch64_test +if(PROCESSOR_IS_AARCH64) + add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/cpuinfo_aarch64.c) + target_link_libraries(cpuinfo_aarch64_test all_libraries) + add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_mips_test +if(PROCESSOR_IS_MIPS) + add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/cpuinfo_mips.c) + target_link_libraries(cpuinfo_mips_test all_libraries) + add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_ppc_test +if(PROCESSOR_IS_POWER) + add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/cpuinfo_ppc.c) + target_link_libraries(cpuinfo_ppc_test all_libraries) + add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test) +endif() diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/bit_utils_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/bit_utils_test.cc new file mode 100644 index 0000000..9c8c1bb --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/bit_utils_test.cc @@ -0,0 +1,53 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/bit_utils.h" + +#include "gtest/gtest.h" + +namespace cpu_features { +namespace { + +TEST(UtilsTest, IsBitSet) { + for (size_t bit_set = 0; bit_set < 32; ++bit_set) { + const uint32_t value = 1UL << bit_set; + for (uint32_t i = 0; i < 32; ++i) { + EXPECT_EQ(IsBitSet(value, i), i == bit_set); + } + } + + // testing 0, all bits should be 0. + for (uint32_t i = 0; i < 32; ++i) { + EXPECT_FALSE(IsBitSet(0, i)); + } + + // testing ~0, all bits should be 1. + for (uint32_t i = 0; i < 32; ++i) { + EXPECT_TRUE(IsBitSet(-1, i)); + } +} + +TEST(UtilsTest, ExtractBitRange) { + // Extracting all bits gives the same number. + EXPECT_EQ(ExtractBitRange(123, 31, 0), 123); + // Extracting 1 bit gives parity. + EXPECT_EQ(ExtractBitRange(123, 0, 0), 1); + EXPECT_EQ(ExtractBitRange(122, 0, 0), 0); + + EXPECT_EQ(ExtractBitRange(0xF0, 7, 4), 0xF); + EXPECT_EQ(ExtractBitRange(0x42 << 2, 10, 2), 0x42); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_aarch64_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_aarch64_test.cc new file mode 100644 index 0000000..10e037a --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_aarch64_test.cc @@ -0,0 +1,171 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_aarch64.h" + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" + +namespace cpu_features { +namespace { + +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpuinfoAarch64Test, FromHardwareCap) { + SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetAarch64Info(); + EXPECT_TRUE(info.features.fp); + EXPECT_FALSE(info.features.asimd); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_TRUE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); + EXPECT_FALSE(info.features.atomics); + EXPECT_FALSE(info.features.fphp); + EXPECT_FALSE(info.features.asimdhp); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.asimdrdm); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.lrcpc); + EXPECT_FALSE(info.features.dcpop); + EXPECT_FALSE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.asimddp); + EXPECT_FALSE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_FALSE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.ssbs); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); +} + +TEST(CpuinfoAarch64Test, FromHardwareCap2) { + SetHardwareCapabilities(AARCH64_HWCAP_FP, + AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetAarch64Info(); + EXPECT_TRUE(info.features.fp); + + EXPECT_TRUE(info.features.sve2); + EXPECT_TRUE(info.features.bti); + + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); +} + +TEST(CpuinfoAarch64Test, ARMCortexA53) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor : AArch64 Processor rev 3 (aarch64) +processor : 0 +processor : 1 +processor : 2 +processor : 3 +processor : 4 +processor : 5 +processor : 6 +processor : 7 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x41 +CPU architecture: AArch64 +CPU variant : 0x0 +CPU part : 0xd03 +CPU revision : 3)"); + const auto info = GetAarch64Info(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x0); + EXPECT_EQ(info.part, 0xd03); + EXPECT_EQ(info.revision, 3); + + EXPECT_TRUE(info.features.fp); + EXPECT_TRUE(info.features.asimd); + EXPECT_TRUE(info.features.evtstrm); + EXPECT_TRUE(info.features.aes); + EXPECT_TRUE(info.features.pmull); + EXPECT_TRUE(info.features.sha1); + EXPECT_TRUE(info.features.sha2); + EXPECT_TRUE(info.features.crc32); + + EXPECT_FALSE(info.features.atomics); + EXPECT_FALSE(info.features.fphp); + EXPECT_FALSE(info.features.asimdhp); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.asimdrdm); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.lrcpc); + EXPECT_FALSE(info.features.dcpop); + EXPECT_FALSE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.asimddp); + EXPECT_FALSE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_FALSE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.ssbs); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sve2); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); + EXPECT_FALSE(info.features.bti); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_arm_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_arm_test.cc new file mode 100644 index 0000000..5dc73e4 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_arm_test.cc @@ -0,0 +1,354 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_arm.h" + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" + +namespace cpu_features { +namespace { + +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpuinfoArmTest, FromHardwareCap) { + SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.vfp); // triggered by vfpv3 + EXPECT_TRUE(info.features.vfpv3); // triggered by neon + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.aes); + EXPECT_TRUE(info.features.crc32); + + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + + // check some random features with EnumValue(): + EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP)); + EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4)); + // out of bound EnumValue() check + EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0)); +} + +TEST(CpuinfoArmTest, ODroidFromCpuInfo) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv7 Processor rev 3 (v71) +BogoMIPS : 120.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x2 +CPU part : 0xc0f +CPU revision : 3)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x2); + EXPECT_EQ(info.part, 0xc0f); + EXPECT_EQ(info.revision, 3); + EXPECT_EQ(info.architecture, 7); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_FALSE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_TRUE(info.features.vfpv4); + EXPECT_TRUE(info.features.idiva); + EXPECT_TRUE(info.features.idivt); + EXPECT_TRUE(info.features.vfpd32); + EXPECT_TRUE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +// Linux test-case +TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv6-compatible processor rev 7 (v6l) +BogoMIPS : 697.95 +Features : half thumb fastmult vfp edsp java tls +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0xb76 +CPU revision : 7 + +Hardware : BCM2835 +Revision : 9000c1 +Serial : 000000006cd946f3)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x0); + EXPECT_EQ(info.part, 0xb76); + EXPECT_EQ(info.revision, 7); + EXPECT_EQ(info.architecture, 6); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_TRUE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_FALSE(info.features.neon); + EXPECT_FALSE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv7 Processor rev 1 (v7l) +BogoMIPS : 50.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x4 +CPU part : 0xc09 +CPU revision : 1 + +processor : 1 +model name : ARMv7 Processor rev 1 (v7l) +BogoMIPS : 50.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x4 +CPU part : 0xc09 +CPU revision : 1 + +Hardware : Marvell Armada 380/385 (Device Tree) +Revision : 0000 +Serial : 0000000000000000)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x4); + EXPECT_EQ(info.part, 0xc09); + EXPECT_EQ(info.revision, 1); + EXPECT_EQ(info.architecture, 7); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_FALSE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_TRUE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +// Android test-case +// http://code.google.com/p/android/issues/detail?id=10812 +TEST(CpuinfoArmTest, InvalidArmv7) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor : ARMv6-compatible processor rev 6 (v6l) +BogoMIPS : 199.47 +Features : swp half thumb fastmult vfp edsp java +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0xb76 +CPU revision : 6 + +Hardware : SPICA +Revision : 0020 +Serial : 33323613546d00ec )"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.architecture, 6); + + EXPECT_TRUE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_TRUE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_FALSE(info.features.neon); + EXPECT_FALSE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_FALSE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +// Android test-case +// https://crbug.com/341598. +TEST(CpuinfoArmTest, InvalidNeon) { + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor: ARMv7 Processory rev 0 (v71) +processor: 0 +BogoMIPS: 13.50 + +Processor: 1 +BogoMIPS: 13.50 + +Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt +CPU implementer : 0x51 +CPU architecture: 7 +CPU variant: 0x1 +CPU part: 0x04d +CPU revision: 0 + +Hardware: SAMSUNG M2 +Revision: 0010 +Serial: 00001e030000354e)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.swp); + EXPECT_FALSE(info.features.neon); +} + +// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV +// support. +TEST(CpuinfoArmTest, Nexus4_0x510006f2) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0x6f +CPU revision : 2)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.idiva); + EXPECT_TRUE(info.features.idivt); + + EXPECT_EQ(GetArmCpuId(&info), 0x510006f2); +} + +// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV +// support. +TEST(CpuinfoArmTest, Nexus4_0x510006f3) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0x6f +CPU revision : 3)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.idiva); + EXPECT_TRUE(info.features.idivt); + + EXPECT_EQ(GetArmCpuId(&info), 0x510006f3); +} + +// The emulator-specific Android 4.2 kernel fails to report support for the +// 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual +// CPU implemented by the emulator. +TEST(CpuinfoArmTest, EmulatorSpecificIdiv) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor : ARMv7 Processor rev 0 (v7l) +BogoMIPS : 629.14 +Features : swp half thumb fastmult vfp edsp neon vfpv3 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0xc08 +CPU revision : 0 + +Hardware : Goldfish +Revision : 0000 +Serial : 0000000000000000)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.idiva); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_mips_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_mips_test.cc new file mode 100644 index 0000000..fce9949 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_mips_test.cc @@ -0,0 +1,126 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_mips.h" + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" + +namespace cpu_features { + +namespace { + +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpuinfoMipsTest, FromHardwareCapBoth) { + SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetMipsInfo(); + EXPECT_TRUE(info.features.msa); + EXPECT_FALSE(info.features.eva); + EXPECT_TRUE(info.features.r6); +} + +TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) { + SetHardwareCapabilities(MIPS_HWCAP_MSA, 0); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetMipsInfo(); + EXPECT_TRUE(info.features.msa); + EXPECT_FALSE(info.features.eva); +} + +TEST(CpuinfoMipsTest, Ci40) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(system type : IMG Pistachio SoC (B0) +machine : IMG Marduk – Ci40 with cc2520 +processor : 0 +cpu model : MIPS interAptiv (multi) V2.0 FPU V0.0 +BogoMIPS : 363.72 +wait instruction : yes +microsecond timers : yes +tlb_entries : 64 +extra interrupt vector : yes +hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb] +isa : mips1 mips2 mips32r1 mips32r2 +ASEs implemented : mips16 dsp mt eva +shadow register sets : 1 +kscratch registers : 0 +package : 0 +core : 0 +VCED exceptions : not available +VCEI exceptions : not available +VPE : 0 +)"); + const auto info = GetMipsInfo(); + EXPECT_FALSE(info.features.msa); + EXPECT_TRUE(info.features.eva); +} + +TEST(CpuinfoMipsTest, AR7161) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(system type : Atheros AR7161 rev 2 +machine : NETGEAR WNDR3700/WNDR3800/WNDRMAC +processor : 0 +cpu model : MIPS 24Kc V7.4 +BogoMIPS : 452.19 +wait instruction : yes +microsecond timers : yes +tlb_entries : 16 +extra interrupt vector : yes +hardware watchpoint : yes, count: 4, address/irw mask: [0x0000, 0x0f98, 0x0f78, 0x0df8] +ASEs implemented : mips16 +shadow register sets : 1 +kscratch registers : 0 +core : 0 +VCED exceptions : not available +VCEI exceptions : not available +)"); + const auto info = GetMipsInfo(); + EXPECT_FALSE(info.features.msa); + EXPECT_FALSE(info.features.eva); +} + +TEST(CpuinfoMipsTest, Goldfish) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(system type : MIPS-Goldfish +Hardware : goldfish +Revison : 1 +processor : 0 +cpu model : MIPS 24Kc V0.0 FPU V0.0 +BogoMIPS : 1042.02 +wait instruction : yes +microsecond timers : yes +tlb_entries : 16 +extra interrupt vector : yes +hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8] +ASEs implemented : +shadow register sets : 1 +core : 0 +VCED exceptions : not available +VCEI exceptions : not available +)"); + const auto info = GetMipsInfo(); + EXPECT_FALSE(info.features.msa); + EXPECT_FALSE(info.features.eva); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_ppc_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_ppc_test.cc new file mode 100644 index 0000000..8f0cb65 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_ppc_test.cc @@ -0,0 +1,119 @@ +// Copyright 2018 IBM. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_ppc.h" + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" +#include "internal/string_view.h" + +namespace cpu_features { +namespace { + +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpustringsPPCTest, FromHardwareCap) { + SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX, + PPC_FEATURE2_ARCH_3_00); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetPPCInfo(); + EXPECT_TRUE(info.features.fpu); + EXPECT_FALSE(info.features.mmu); + EXPECT_TRUE(info.features.vsx); + EXPECT_TRUE(info.features.arch300); + EXPECT_FALSE(info.features.power4); + EXPECT_FALSE(info.features.altivec); + EXPECT_FALSE(info.features.vcrypto); + EXPECT_FALSE(info.features.htm); +} + +TEST(CpustringsPPCTest, Blade) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 14 +cpu : POWER7 (architected), altivec supported +clock : 3000.000000MHz +revision : 2.1 (pvr 003f 0201) + +processor : 15 +cpu : POWER7 (architected), altivec supported +clock : 3000.000000MHz +revision : 2.1 (pvr 003f 0201) + +timebase : 512000000 +platform : pSeries +model : IBM,8406-70Y +machine : CHRP IBM,8406-70Y)"); + SetPlatformTypes("power7", "power8"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "pSeries"); + ASSERT_STREQ(strings.model, "IBM,8406-70Y"); + ASSERT_STREQ(strings.machine, "CHRP IBM,8406-70Y"); + ASSERT_STREQ(strings.cpu, "POWER7 (architected), altivec supported"); + ASSERT_STREQ(strings.type.platform, "power7"); + ASSERT_STREQ(strings.type.base_platform, "power8"); +} + +TEST(CpustringsPPCTest, Firestone) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 126 +cpu : POWER8 (raw), altivec supported +clock : 2061.000000MHz +revision : 2.0 (pvr 004d 0200) + +processor : 127 +cpu : POWER8 (raw), altivec supported +clock : 2061.000000MHz +revision : 2.0 (pvr 004d 0200) + +timebase : 512000000 +platform : PowerNV +model : 8335-GTA +machine : PowerNV 8335-GTA +firmware : OPAL v3)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "PowerNV"); + ASSERT_STREQ(strings.model, "8335-GTA"); + ASSERT_STREQ(strings.machine, "PowerNV 8335-GTA"); + ASSERT_STREQ(strings.cpu, "POWER8 (raw), altivec supported"); +} + +TEST(CpustringsPPCTest, w8) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 143 +cpu : POWER9, altivec supported +clock : 2300.000000MHz +revision : 2.2 (pvr 004e 1202) + +timebase : 512000000 +platform : PowerNV +model : 0000000000000000 +machine : PowerNV 0000000000000000 +firmware : OPAL +MMU : Radix)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "PowerNV"); + ASSERT_STREQ(strings.model, "0000000000000000"); + ASSERT_STREQ(strings.machine, "PowerNV 0000000000000000"); + ASSERT_STREQ(strings.cpu, "POWER9, altivec supported"); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_x86_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_x86_test.cc new file mode 100644 index 0000000..e11a0ba --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/cpuinfo_x86_test.cc @@ -0,0 +1,281 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpuinfo_x86.h" + +#include +#include +#include + +#include "gtest/gtest.h" +#include "internal/cpuid_x86.h" + +namespace cpu_features { + +class FakeCpu { + public: + Leaf CpuIdEx(uint32_t leaf_id, int ecx) const { + const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx)); + if (itr != cpuid_leaves_.end()) { + return itr->second; + } + return {0, 0, 0, 0}; + } + + uint32_t GetXCR0Eax() const { return xcr0_eax_; } + + void SetLeaves(std::map, Leaf> configuration) { + cpuid_leaves_ = std::move(configuration); + } + + void SetOsBackupsExtendedRegisters(bool os_backups_extended_registers) { + xcr0_eax_ = os_backups_extended_registers ? -1 : 0; + } + + private: + std::map, Leaf> cpuid_leaves_; + uint32_t xcr0_eax_; +}; + +auto* g_fake_cpu = new FakeCpu(); + +extern "C" Leaf CpuIdEx(uint32_t leaf_id, int ecx) { + return g_fake_cpu->CpuIdEx(leaf_id, ecx); +} + +extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); } + +namespace { + +TEST(CpuidX86Test, SandyBridge) { + g_fake_cpu->SetOsBackupsExtendedRegisters(true); + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x02A); + EXPECT_EQ(info.stepping, 0x06); + // Leaf 7 is zeroed out so none of the Leaf 7 flags are set. + const auto features = info.features; + EXPECT_FALSE(features.erms); + EXPECT_FALSE(features.avx2); + EXPECT_FALSE(features.avx512f); + EXPECT_FALSE(features.avx512cd); + EXPECT_FALSE(features.avx512er); + EXPECT_FALSE(features.avx512pf); + EXPECT_FALSE(features.avx512bw); + EXPECT_FALSE(features.avx512dq); + EXPECT_FALSE(features.avx512vl); + EXPECT_FALSE(features.avx512ifma); + EXPECT_FALSE(features.avx512vbmi); + EXPECT_FALSE(features.avx512vbmi2); + EXPECT_FALSE(features.avx512vnni); + EXPECT_FALSE(features.avx512bitalg); + EXPECT_FALSE(features.avx512vpopcntdq); + EXPECT_FALSE(features.avx512_4vnniw); + EXPECT_FALSE(features.avx512_4fmaps); + // All old cpu features should be set. + EXPECT_TRUE(features.aes); + EXPECT_TRUE(features.ssse3); + EXPECT_TRUE(features.sse4_1); + EXPECT_TRUE(features.sse4_2); + EXPECT_TRUE(features.avx); + EXPECT_FALSE(features.sha); + EXPECT_TRUE(features.popcnt); + EXPECT_FALSE(features.movbe); + EXPECT_FALSE(features.rdrnd); +} + +const int KiB = 1024; +const int MiB = 1024 * KiB; + +TEST(CpuidX86Test, SandyBridgeTestOsSupport) { + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + }); + // avx is disabled if os does not support backing up ymm registers. + g_fake_cpu->SetOsBackupsExtendedRegisters(false); + EXPECT_FALSE(GetX86Info().features.avx); + // avx is disabled if os does not support backing up ymm registers. + g_fake_cpu->SetOsBackupsExtendedRegisters(true); + EXPECT_TRUE(GetX86Info().features.avx); +} + +TEST(CpuidX86Test, SkyLake) { + g_fake_cpu->SetOsBackupsExtendedRegisters(true); + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x04E); + EXPECT_EQ(info.stepping, 0x03); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL); +} + +TEST(CpuidX86Test, Branding) { + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}}, + {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}}, + {{0x80000004, 0}, Leaf{0x352E3220, 0x7A484730, 0x00000000, 0x00000000}}, + }); + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz"); +} + +TEST(CpuidX86Test, KabyLakeCache) { + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 2}, Leaf{0x1C004143, 0x00C0003F, 0x000003FF, 0x00000000}}, + {{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000002}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}}, + {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}}, + }); + const auto info = GetX86CacheInfo(); + EXPECT_EQ(info.size, 4); + EXPECT_EQ(info.levels[0].level, 1); + EXPECT_EQ(info.levels[0].cache_type, 1); + EXPECT_EQ(info.levels[0].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[0].ways, 8); + EXPECT_EQ(info.levels[0].line_size, 64); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 1); + + EXPECT_EQ(info.levels[1].level, 1); + EXPECT_EQ(info.levels[1].cache_type, 2); + EXPECT_EQ(info.levels[1].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[1].ways, 8); + EXPECT_EQ(info.levels[1].line_size, 64); + EXPECT_EQ(info.levels[1].tlb_entries, 64); + EXPECT_EQ(info.levels[1].partitioning, 1); + + EXPECT_EQ(info.levels[2].level, 2); + EXPECT_EQ(info.levels[2].cache_type, 3); + EXPECT_EQ(info.levels[2].cache_size, 256 * KiB); + EXPECT_EQ(info.levels[2].ways, 4); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, 1024); + EXPECT_EQ(info.levels[2].partitioning, 1); + + EXPECT_EQ(info.levels[3].level, 3); + EXPECT_EQ(info.levels[3].cache_type, 3); + EXPECT_EQ(info.levels[3].cache_size, 6 * MiB); + EXPECT_EQ(info.levels[3].ways, 12); + EXPECT_EQ(info.levels[3].line_size, 64); + EXPECT_EQ(info.levels[3].tlb_entries, 8192); + EXPECT_EQ(info.levels[3].partitioning, 1); +} + +TEST(CpuidX86Test, HSWCache) { + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 2}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}}, + {{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000006}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}}, + {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}}, + }); + const auto info = GetX86CacheInfo(); + EXPECT_EQ(info.size, 4); + EXPECT_EQ(info.levels[0].level, 1); + EXPECT_EQ(info.levels[0].cache_type, 1); + EXPECT_EQ(info.levels[0].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[0].ways, 8); + EXPECT_EQ(info.levels[0].line_size, 64); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 1); + + EXPECT_EQ(info.levels[1].level, 1); + EXPECT_EQ(info.levels[1].cache_type, 2); + EXPECT_EQ(info.levels[1].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[1].ways, 8); + EXPECT_EQ(info.levels[1].line_size, 64); + EXPECT_EQ(info.levels[1].tlb_entries, 64); + EXPECT_EQ(info.levels[1].partitioning, 1); + + EXPECT_EQ(info.levels[2].level, 2); + EXPECT_EQ(info.levels[2].cache_type, 3); + EXPECT_EQ(info.levels[2].cache_size, 256 * KiB); + EXPECT_EQ(info.levels[2].ways, 8); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, 512); + EXPECT_EQ(info.levels[2].partitioning, 1); + + EXPECT_EQ(info.levels[3].level, 3); + EXPECT_EQ(info.levels[3].cache_type, 3); + EXPECT_EQ(info.levels[3].cache_size, 6 * MiB); + EXPECT_EQ(info.levels[3].ways, 12); + EXPECT_EQ(info.levels[3].line_size, 64); + EXPECT_EQ(info.levels[3].tlb_entries, 8192); + EXPECT_EQ(info.levels[3].partitioning, 1); +} +// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt +TEST(CpuidX86Test, AMD_K15) { + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00630F81, 0x10000000, 0x0FEBBFFF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x372D3841, 0x4B303736, 0x64615220}}, + {{0x80000003, 0}, Leaf{0x206E6F65, 0x202C3752, 0x43203031, 0x75706D6F}}, + {{0x80000004, 0}, Leaf{0x43206574, 0x7365726F, 0x2B433420, 0x00204736}}, + {{0x80000005, 0}, Leaf{0xFF40FF18, 0xFF40FF30, 0x10040140, 0x60030140}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x15); + EXPECT_EQ(info.model, 0x38); + EXPECT_EQ(info.stepping, 0x01); + EXPECT_EQ(GetX86Microarchitecture(&info), + X86Microarchitecture::AMD_BULLDOZER); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G "); +} + +// TODO(user): test what happens when xsave/osxsave are not present. +// TODO(user): test what happens when xmm/ymm/zmm os support are not +// present. + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.cc new file mode 100644 index 0000000..0a11416 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.cc @@ -0,0 +1,103 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "filesystem_for_testing.h" + +#include +#include +#include +#include +#include + +namespace cpu_features { + +FakeFile::FakeFile(int file_descriptor, const char* content) + : file_descriptor_(file_descriptor), content_(content) {} + +FakeFile::~FakeFile() { assert(!opened_); } + +void FakeFile::Open() { + assert(!opened_); + opened_ = true; +} + +void FakeFile::Close() { + assert(opened_); + opened_ = false; +} + +int FakeFile::Read(int fd, void* buf, size_t count) { + assert(count < INT_MAX); + assert(fd == file_descriptor_); + const size_t remainder = content_.size() - head_index_; + const size_t read = count > remainder ? remainder : count; + memcpy(buf, content_.data() + head_index_, read); + head_index_ += read; + assert(read < INT_MAX); + return (int)read; +} + +void FakeFilesystem::Reset() { files_.clear(); } + +FakeFile* FakeFilesystem::CreateFile(const std::string& filename, + const char* content) { + auto& file = files_[filename]; + file = + std::unique_ptr(new FakeFile(next_file_descriptor_++, content)); + return file.get(); +} + +FakeFile* FakeFilesystem::FindFileOrNull(const std::string& filename) const { + const auto itr = files_.find(filename); + return itr == files_.end() ? nullptr : itr->second.get(); +} + +FakeFile* FakeFilesystem::FindFileOrDie(const int file_descriptor) const { + for (const auto& filename_file_pair : files_) { + FakeFile* const file_ptr = filename_file_pair.second.get(); + if (file_ptr->GetFileDescriptor() == file_descriptor) { + return file_ptr; + } + } + assert(false); + return nullptr; +} + +static FakeFilesystem* kFilesystem = new FakeFilesystem(); + +FakeFilesystem& GetEmptyFilesystem() { + kFilesystem->Reset(); + return *kFilesystem; +} + +extern "C" int CpuFeatures_OpenFile(const char* filename) { + auto* const file = kFilesystem->FindFileOrNull(filename); + if (file) { + file->Open(); + return file->GetFileDescriptor(); + } + return -1; +} + +extern "C" void CpuFeatures_CloseFile(int file_descriptor) { + kFilesystem->FindFileOrDie(file_descriptor)->Close(); +} + +extern "C" int CpuFeatures_ReadFile(int file_descriptor, void* buffer, + size_t buffer_size) { + return kFilesystem->FindFileOrDie(file_descriptor) + ->Read(file_descriptor, buffer, buffer_size); +} + +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.h new file mode 100644 index 0000000..7474b5f --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/filesystem_for_testing.h @@ -0,0 +1,61 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Implements a fake filesystem, useful for tests. +#ifndef CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_ +#define CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_ + +#include +#include +#include + +#include "internal/filesystem.h" + +namespace cpu_features { + +class FakeFile { + public: + explicit FakeFile(int file_descriptor, const char* content); + ~FakeFile(); + + void Open(); + void Close(); + int Read(int fd, void* buf, size_t count); + + int GetFileDescriptor() const { return file_descriptor_; } + + private: + const int file_descriptor_; + const std::string content_; + bool opened_ = false; + size_t head_index_ = 0; +}; + +class FakeFilesystem { + public: + void Reset(); + FakeFile* CreateFile(const std::string& filename, const char* content); + FakeFile* FindFileOrDie(const int file_descriptor) const; + FakeFile* FindFileOrNull(const std::string& filename) const; + + private: + int next_file_descriptor_ = 0; + std::unordered_map> files_; +}; + +FakeFilesystem& GetEmptyFilesystem(); + +} // namespace cpu_features + +#endif // CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.cc new file mode 100644 index 0000000..39a8472 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.cc @@ -0,0 +1,46 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "hwcaps_for_testing.h" + +#include + +#include "internal/string_view.h" + +namespace cpu_features { + +namespace { +static auto* const g_hardware_capabilities = new HardwareCapabilities(); +static auto* const g_platform_types = new PlatformType(); +} // namespace + +void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) { + g_hardware_capabilities->hwcaps = hwcaps; + g_hardware_capabilities->hwcaps2 = hwcaps2; +} + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { + return *g_hardware_capabilities; +} + +void SetPlatformTypes(const char* platform, const char* base_platform) { + CpuFeatures_StringView_CopyString(str(platform), g_platform_types->platform, + sizeof(g_platform_types->platform)); + CpuFeatures_StringView_CopyString(str(base_platform), + g_platform_types->base_platform, + sizeof(g_platform_types->base_platform)); +} + +PlatformType CpuFeatures_GetPlatformType(void) { return *g_platform_types; } +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.h b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.h new file mode 100644 index 0000000..0d03777 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/hwcaps_for_testing.h @@ -0,0 +1,27 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_ +#define CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_ + +#include "internal/hwcaps.h" + +namespace cpu_features { + +void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2); +void SetPlatformTypes(const char *platform, const char *base_platform); + +} // namespace cpu_features + +#endif // CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_ diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/stack_line_reader_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/stack_line_reader_test.cc new file mode 100644 index 0000000..629122a --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/stack_line_reader_test.cc @@ -0,0 +1,132 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/stack_line_reader.h" + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" + +namespace cpu_features { + +bool operator==(const StringView& a, const StringView& b) { + return CpuFeatures_StringView_IsEquals(a, b); +} + +namespace { + +std::string ToString(StringView view) { return {view.ptr, view.size}; } + +TEST(StackLineReaderTest, Empty) { + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", ""); + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("")); + } +} + +TEST(StackLineReaderTest, ManySmallLines) { + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", "a\nb\nc"); + + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("a")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("b")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("c")); + } +} + +TEST(StackLineReaderTest, TruncatedLine) { + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", R"(First +Second +More than 16 characters, this will be truncated. +last)"); + + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("First")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("Second")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_FALSE(result.full_line); + EXPECT_EQ(result.line, str("More than 16 cha")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("last")); + } +} + +TEST(StackLineReaderTest, TruncatedLines) { + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", R"(More than 16 characters +Another line that is too long)"); + + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_FALSE(result.full_line); + EXPECT_EQ(result.line, str("More than 16 cha")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_FALSE(result.full_line); + EXPECT_EQ(result.line, str("Another line tha")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("")); + } +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/string_view_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/string_view_test.cc new file mode 100644 index 0000000..962f417 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/string_view_test.cc @@ -0,0 +1,192 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/string_view.h" + +#include "gtest/gtest.h" + +namespace cpu_features { + +bool operator==(const StringView& a, const StringView& b) { + return CpuFeatures_StringView_IsEquals(a, b); +} + +namespace { + +TEST(StringViewTest, Empty) { + EXPECT_EQ(kEmptyStringView.ptr, nullptr); + EXPECT_EQ(kEmptyStringView.size, 0); +} + +TEST(StringViewTest, Build) { + const auto view = str("test"); + EXPECT_EQ(view.ptr[0], 't'); + EXPECT_EQ(view.size, 4); +} + +TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) { + // Found. + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1); + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0); + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1); + // Not found. + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1); + // Empty. + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(kEmptyStringView, 'z'), -1); +} + +TEST(StringViewTest, CpuFeatures_StringView_IndexOf) { + // Found. + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1); + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0); + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4); + // Not found. + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1); + // Empty. + EXPECT_EQ(CpuFeatures_StringView_IndexOf(kEmptyStringView, str("aa")), -1); + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("aa"), kEmptyStringView), -1); +} + +TEST(StringViewTest, CpuFeatures_StringView_StartsWith) { + EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te"))); + EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test"))); + EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st"))); + EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est"))); + EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str(""))); + EXPECT_FALSE( + CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView)); + EXPECT_FALSE( + CpuFeatures_StringView_StartsWith(kEmptyStringView, str("test"))); +} + +TEST(StringViewTest, CpuFeatures_StringView_IsEquals) { + EXPECT_TRUE( + CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView)); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str(""))); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView)); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test"))); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView)); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a"))); +} + +TEST(StringViewTest, CpuFeatures_StringView_PopFront) { + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 2), str("st")); + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 0), str("test")); + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 4), str("")); + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str("")); +} + +TEST(StringViewTest, CpuFeatures_StringView_PopBack) { + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te")); + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test")); + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str("")); + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str("")); +} + +TEST(StringViewTest, CpuFeatures_StringView_KeepFront) { + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te")); + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str("")); + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test")); + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test")); +} + +TEST(StringViewTest, CpuFeatures_StringView_Front) { + EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a'); + EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a'); +} + +TEST(StringViewTest, CpuFeatures_StringView_Back) { + EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e'); + EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a'); +} + +TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) { + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")), + str("first middle last")); + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")), + str("first middle last")); + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")), + str("first middle last")); + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")), + str("first middle last")); +} + +TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) { + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794); + + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1); +} + +TEST(StringViewTest, CpuFeatures_StringView_CopyString) { + char buf[4]; + buf[0] = 'X'; + + // Empty + CpuFeatures_StringView_CopyString(str(""), buf, sizeof(buf)); + EXPECT_STREQ(buf, ""); + + // Less + CpuFeatures_StringView_CopyString(str("a"), buf, sizeof(buf)); + EXPECT_STREQ(buf, "a"); + + // exact + CpuFeatures_StringView_CopyString(str("abc"), buf, sizeof(buf)); + EXPECT_STREQ(buf, "abc"); + + // More + CpuFeatures_StringView_CopyString(str("abcd"), buf, sizeof(buf)); + EXPECT_STREQ(buf, "abc"); +} + +TEST(StringViewTest, CpuFeatures_StringView_HasWord) { + // Find flags at beginning, middle and end. + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first middle last"), "first")); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first middle last"), "middle")); + EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last")); + // Do not match partial flags + EXPECT_FALSE( + CpuFeatures_StringView_HasWord(str("first middle last"), "irst")); + EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid")); + EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las")); +} + +TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue) { + const StringView line = str(" key : first middle last "); + StringView key, value; + EXPECT_TRUE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)); + EXPECT_EQ(key, str("key")); + EXPECT_EQ(value, str("first middle last")); +} + +TEST(StringViewTest, FailingGetAttributeKeyValue) { + const StringView line = str("key first middle last"); + StringView key, value; + EXPECT_FALSE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/unix_features_aggregator_test.cc b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/unix_features_aggregator_test.cc new file mode 100644 index 0000000..20d146c --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/deps/cpu_features/test/unix_features_aggregator_test.cc @@ -0,0 +1,105 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/unix_features_aggregator.h" + +#include + +#include "gtest/gtest.h" + +namespace cpu_features { + +namespace { + +struct Features { + bool a = false; + bool b = false; + bool c = false; +}; + +enum eFeatures { TEST_a, TEST_b, TEST_c }; + +DECLARE_SETTER_AND_GETTER(Features, a) +DECLARE_SETTER_AND_GETTER(Features, b) +DECLARE_SETTER_AND_GETTER(Features, c) + +class LinuxFeatureAggregatorTest : public testing::Test { + public: + const std::array kConfigs = { + {{{0b0001, 0b0000}, "a", &set_a, &get_a}, + {{0b0010, 0b0000}, "b", &set_b, &get_b}, + {{0b0000, 0b1100}, "c", &set_c, &get_c}}}; +}; + +TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty) { + Features features; + CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str(""), + &features); + EXPECT_FALSE(features.a); + EXPECT_FALSE(features.b); + EXPECT_FALSE(features.c); + + EXPECT_FALSE(kConfigs[TEST_a].get_bit(&features)); +} + +TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) { + Features features; + CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a c b"), + &features); + EXPECT_TRUE(features.a); + EXPECT_TRUE(features.b); + EXPECT_TRUE(features.c); + + EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features)); +} + +TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) { + Features features; + CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a"), + &features); + EXPECT_TRUE(features.a); + EXPECT_FALSE(features.b); + EXPECT_FALSE(features.c); + + EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features)); + EXPECT_FALSE(kConfigs[TEST_b].get_bit(&features)); + EXPECT_FALSE(kConfigs[TEST_c].get_bit(&features)); +} + +TEST_F(LinuxFeatureAggregatorTest, FromHwcapsNone) { + HardwareCapabilities capability; + capability.hwcaps = 0; // matches none + capability.hwcaps2 = 0; // matches none + Features features; + CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability, + &features); + EXPECT_FALSE(features.a); + EXPECT_FALSE(features.b); + EXPECT_FALSE(features.c); +} + +TEST_F(LinuxFeatureAggregatorTest, FromHwcapsSet) { + HardwareCapabilities capability; + capability.hwcaps = 0b0010; // matches b but not a + capability.hwcaps2 = 0b1111; // matches c + Features features; + CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability, + &features); + EXPECT_FALSE(features.a); + EXPECT_TRUE(features.b); + EXPECT_TRUE(features.c); +} + +} // namespace +} // namespace cpu_features diff --git a/reverse_engineering/node_modules/cpu-features/lib/index.js b/reverse_engineering/node_modules/cpu-features/lib/index.js new file mode 100644 index 0000000..f1856cd --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/lib/index.js @@ -0,0 +1,3 @@ +const binding = require('../build/Release/cpufeatures.node'); + +module.exports = binding.getCPUInfo; diff --git a/reverse_engineering/node_modules/cpu-features/package.json b/reverse_engineering/node_modules/cpu-features/package.json new file mode 100644 index 0000000..b17d68b --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/package.json @@ -0,0 +1,66 @@ +{ + "_from": "cpu-features@0.0.2", + "_id": "cpu-features@0.0.2", + "_inBundle": false, + "_integrity": "sha512-/2yieBqvMcRj8McNzkycjW2v3OIUOibBfd2dLEJ0nWts8NobAxwiyw9phVNS6oDL8x8tz9F7uNVFEVpJncQpeA==", + "_location": "/cpu-features", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "cpu-features@0.0.2", + "name": "cpu-features", + "escapedName": "cpu-features", + "rawSpec": "0.0.2", + "saveSpec": null, + "fetchSpec": "0.0.2" + }, + "_requiredBy": [ + "/ssh2" + ], + "_resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.2.tgz", + "_shasum": "9f636156f1155fd04bdbaa028bb3c2fbef3cea7a", + "_spec": "cpu-features@0.0.2", + "_where": "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/ssh2", + "author": { + "name": "Brian White", + "email": "mscdex@mscdex.net" + }, + "bugs": { + "url": "https://github.com/mscdex/cpu-features/issues" + }, + "bundleDependencies": false, + "dependencies": { + "nan": "^2.14.1" + }, + "deprecated": false, + "description": "A simple binding to Google's cpu_features library for obtaining information about installed CPU(s)", + "engines": { + "node": ">=8.0.0" + }, + "gypfile": true, + "homepage": "https://github.com/mscdex/cpu-features#readme", + "keywords": [ + "cpu", + "detect", + "detection", + "features" + ], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/mscdex/cpu-features/raw/master/LICENSE" + } + ], + "main": "./lib/index", + "name": "cpu-features", + "repository": { + "type": "git", + "url": "git+https://github.com/mscdex/cpu-features.git" + }, + "scripts": { + "install": "node-gyp rebuild", + "test": "node test/test.js" + }, + "version": "0.0.2" +} diff --git a/reverse_engineering/node_modules/cpu-features/src/binding.cc b/reverse_engineering/node_modules/cpu-features/src/binding.cc new file mode 100644 index 0000000..8626714 --- /dev/null +++ b/reverse_engineering/node_modules/cpu-features/src/binding.cc @@ -0,0 +1,153 @@ +#include +#include +#include +#include // isspace + +#include "cpu_features_macros.h" + +#if defined(CPU_FEATURES_ARCH_X86) +# include "cpuinfo_x86.h" +# define GetFeatureName GetX86FeaturesEnumName +# define GetFeatureValue GetX86FeaturesEnumValue +# define FeatureType X86Features +# define FeatureEnumType X86FeaturesEnum +# define LastFeature X86_LAST_ +#elif defined(CPU_FEATURES_ARCH_ARM) +# include "cpuinfo_arm.h" +# define GetFeatureName GetArmFeaturesEnumName +# define GetFeatureValue GetArmFeaturesEnumValue +# define FeatureType ArmFeatures +# define FeatureEnumType ArmFeaturesEnum +# define LastFeature ARM_LAST_ +#elif defined(CPU_FEATURES_ARCH_AARCH64) +# include "cpuinfo_aarch64.h" +# define GetFeatureName GetAarch64FeaturesEnumName +# define GetFeatureValue GetAarch64FeaturesEnumValue +# define FeatureType Aarch64Features +# define FeatureEnumType Aarch64FeaturesEnum +# define LastFeature AARCH64_LAST_ +#elif defined(CPU_FEATURES_ARCH_MIPS) +# include "cpuinfo_mips.h" +# define GetFeatureName GetMipsFeaturesEnumName +# define GetFeatureValue GetMipsFeaturesEnumValue +# define FeatureType MipsFeatures +# define FeatureEnumType MipsFeaturesEnum +# define LastFeature MIPS_LAST_ +#elif defined(CPU_FEATURES_ARCH_PPC) +# include "cpuinfo_ppc.h" +# define GetFeatureName GetPPCFeaturesEnumName +# define GetFeatureValue GetPPCFeaturesEnumValue +# define FeatureType PPCFeatures +# define FeatureEnumType PPCFeaturesEnum +# define LastFeature PPC_LAST_ +#endif + +#define SET_FLAG(key) \ +Nan::Set(ret, Nan::New(key).ToLocalChecked(), Nan::New(true)) + +#define SET_STR(key, val) \ +Nan::Set(ret, \ + Nan::New(key).ToLocalChecked(), \ + Nan::New(trim(val)).ToLocalChecked()) + +#define SET_NUM(key, val) \ +Nan::Set(ret, Nan::New(key).ToLocalChecked(), Nan::New(val)) + +#define SET_VAL(key, val) \ +Nan::Set(ret, Nan::New(key).ToLocalChecked(), val) + +using namespace node; +using namespace v8; +using namespace cpu_features; +using namespace std; + +static inline void ltrim(string& s) { + s.erase(s.begin(), find_if(s.begin(), s.end(), [](int ch) { + return !isspace(ch); + })); +} + +static inline void rtrim(string& s) { + s.erase(find_if(s.rbegin(), s.rend(), [](int ch) { + return !isspace(ch); + }).base(), s.end()); +} + +static inline string trim(const char* str) { + string ret = str; + ltrim(ret); + rtrim(ret); + return ret; +} + +#if defined(LastFeature) +Local GenerateFlags(const FeatureType* features) { + const auto ret = Nan::New(); + for (size_t i = 0; i < LastFeature; ++i) { + const auto enum_val = static_cast(i); + if (GetFeatureValue(features, enum_val)) + SET_FLAG(GetFeatureName(enum_val)); + } + return ret; +} +#endif + +NAN_METHOD(GetCPUInfo) { + const auto ret = Nan::New(); +#if defined(CPU_FEATURES_ARCH_X86) + char brand_string[49]; + const X86Info details = GetX86Info(); + FillX86BrandString(brand_string); + SET_STR("arch", "x86"); + SET_STR("brand", brand_string); + SET_NUM("family", details.family); + SET_NUM("model", details.model); + SET_NUM("stepping", details.stepping); + SET_STR("uarch", + GetX86MicroarchitectureName(GetX86Microarchitecture(&details))); + SET_VAL("flags", GenerateFlags(&details.features)); +#elif defined(CPU_FEATURES_ARCH_ARM) + const ArmInfo details = GetArmInfo(); + SET_STR("arch", "arm"); + SET_NUM("implementer", details.implementer); + SET_NUM("architecture", details.architecture); + SET_NUM("variant", details.variant); + SET_NUM("part", details.part); + SET_NUM("revision", details.revision); + SET_VAL("flags", GenerateFlags(&details.features)); +#elif defined(CPU_FEATURES_ARCH_AARCH64) + const Aarch64Info details = GetAarch64Info(); + SET_STR("arch", "aarch64"); + SET_NUM("implementer", details.implementer); + SET_NUM("variant", details.variant); + SET_NUM("part", details.part); + SET_NUM("revision", details.revision); + SET_VAL("flags", GenerateFlags(&details.features)); +#elif defined(CPU_FEATURES_ARCH_MIPS) + const MipsInfo details = GetMipsInfo(); + SET_STR("arch", "mips"); + SET_VAL("flags", GenerateFlags(&details.features)); +#elif defined(CPU_FEATURES_ARCH_PPC) + const PPCInfo details = GetPPCInfo(); + const PPCPlatformStrings strings = GetPPCPlatformStrings(); + SET_STR("arch", "ppc"); + SET_STR("platform", strings.platform); + SET_STR("model", strings.model); + SET_STR("machine", strings.machine); + SET_STR("cpu", strings.cpu); + SET_STR("instruction set", strings.type.platform); + SET_STR("microarchitecture", strings.type.base_platform); + SET_VAL("flags", GenerateFlags(&details.features)); +#else + SET_STR("arch", "unknown"); + SET_VAL("flags", Nan::New()); +#endif + info.GetReturnValue().Set(ret); +} + +NAN_MODULE_INIT(init) { + Nan::Set(target, Nan::New("getCPUInfo").ToLocalChecked(), + Nan::GetFunction(Nan::New(GetCPUInfo)).ToLocalChecked()); +} + +NODE_MODULE(cpufeatures, init) diff --git a/reverse_engineering/node_modules/nan/CHANGELOG.md b/reverse_engineering/node_modules/nan/CHANGELOG.md new file mode 100644 index 0000000..2838f1a --- /dev/null +++ b/reverse_engineering/node_modules/nan/CHANGELOG.md @@ -0,0 +1,541 @@ +# NAN ChangeLog + +**Version 2.15.0: current Node 16.6.1, Node 0.12: 0.12.18, Node 0.10: 0.10.48, iojs: 3.3.1** + +### 2.15.0 Aug 4 2021 + + - Feature: add ScriptOrigin (#918) d09debf9eeedcb7ca4073e84ffe5fbb455ecb709 + +### 2.14.2 Oct 13 2020 + + - Bugfix: fix gcc 8 function cast warning (#899) 35f0fab205574b2cbda04e6347c8b2db755e124f + +### 2.14.1 Apr 21 2020 + + - Bugfix: use GetBackingStore() instead of GetContents() (#888) 2c023bd447661a61071da318b0ff4003c3858d39 + +### 2.14.0 May 16 2019 + + - Feature: Add missing methods to Nan::Maybe (#852) 4e962489fb84a184035b9fa74f245f650249aca6 + +### 2.13.2 Mar 24 2019 + + - Bugfix: remove usage of deprecated `IsNearDeath` (#842) fbaf42252af279c3d867c6b193571f9711c39847 + +### 2.13.1 Mar 14 2019 + + - Bugfix: check V8 version directly instead of inferring from NMV (#840) 12f9df9f393285de8fb4a8cd01478dc4fe3b089d + +### 2.13.0 Mar 13 2019 + + - Feature: add support for node master (#831) 113c0282072e7ff4f9dfc98b432fd894b798c2c + +### 2.12.1 Dec 18 2018 + + - Bugfix: Fix build breakage with Node.js 10.0.0-10.9.0. (#833) 625e90e8fef8d39ffa7247250a76a100b2487474 + +### 2.12.0 Dec 16 2018 + + - Bugfix: Add scope.Escape() to Call() (#817) 2e5ed4fc3a8ac80a6ef1f2a55099ab3ac8800dc6 + - Bugfix: Fix Node.js v10.12.0 deprecation warnings. 509859cc23b1770376b56550a027840a2ce0f73d + - Feature: Allow SetWeak() for non-object persistent handles. (#824) e6ef6a48e7e671fe3e4b7dddaa8912a3f8262ecd + +### 2.11.1 Sep 29 2018 + + - Fix: adapt to V8 7.0 24a22c3b25eeeec2016c6ec239bdd6169e985447 + +### 2.11.0 Aug 25 2018 + + - Removal: remove `FunctionCallbackInfo::Callee` for nodejs `>= 10` 1a56c0a6efd4fac944cb46c30912a8e023bda7d4 + - Bugfix: Fix `AsyncProgressWorkerBase::WorkProgress` sends invalid data b0c764d1dab11e9f8b37ffb81e2560a4498aad5e + - Feature: Introduce `GetCurrentEventLoop` b4911b0bb1f6d47d860e10ec014d941c51efac5e + - Feature: Add `NAN_MODULE_WORKER_ENABLED` macro as a replacement for `NAN_MODULE` b058fb047d18a58250e66ae831444441c1f2ac7a + +### 2.10.0 Mar 16 2018 + + - Deprecation: Deprecate `MakeCallback` 5e92b19a59e194241d6a658bd6ff7bfbda372950 + - Feature: add `Nan::Call` overload 4482e1242fe124d166fc1a5b2be3c1cc849fe452 + - Feature: add more `Nan::Call` overloads 8584e63e6d04c7d2eb8c4a664e4ef57d70bf672b + - Feature: Fix deprecation warnings for Node 10 1caf258243b0602ed56922bde74f1c91b0cbcb6a + +### 2.9.2 Feb 22 2018 + + - Bugfix: Bandaid for async hooks 212bd2f849be14ef1b02fc85010b053daa24252b + +### 2.9.1 Feb 22 2018 + + - Bugfix: Avoid deprecation warnings in deprecated `Nan::Callback::operator()` 372b14d91289df4604b0f81780709708c45a9aa4 + - Bugfix: Avoid deprecation warnings in `Nan::JSON` 3bc294bce0b7d0a3ee4559926303e5ed4866fda2 + +### 2.9.0 Feb 22 2018 + + - Deprecation: Deprecate legacy `Callback::Call` 6dd5fa690af61ca3523004b433304c581b3ea309 + - Feature: introduce `AsyncResource` class 90c0a179c0d8cb5fd26f1a7d2b1d6231eb402d48o + - Feature: Add context aware `Nan::Callback::Call` functions 7169e09fb088418b6e388222e88b4c13f07ebaee + - Feature: Make `AsyncWorker` context aware 066ba21a6fb9e2b5230c9ed3a6fc51f1211736a4 + - Feature: add `Callback` overload to `Nan::Call` 5328daf66e202658c1dc0d916c3aaba99b3cc606 + - Bugfix: fix warning: suggest parentheses around `&&` within `||` b2bb63d68b8ae623a526b542764e1ac82319cb2c + - Bugfix: Fix compilation on io.js 3 d06114dba0a522fb436f0c5f47b994210968cd7b + +### 2.8.0 Nov 15 2017 + + - Deprecation: Deprecate `Nan::ForceSet` in favor of `Nan::DefineOwnProperty()` 95cbb976d6fbbba88ba0f86dd188223a8591b4e7 + - Feature: Add `Nan::AsyncProgressQueueWorker` a976636ecc2ef617d1b061ce4a6edf39923691cb + - Feature: Add `Nan::DefineOwnProperty()` 95cbb976d6fbbba88ba0f86dd188223a8591b4e7 + - Bugfix: Fix compiling on io.js 1 & 2 82705a64503ce60c62e98df5bd02972bba090900 + - Bugfix: Use DefineOwnProperty instead of ForceSet 95cbb976d6fbbba88ba0f86dd188223a8591b4e7 + +### 2.7.0 Aug 30 2017 + + - Feature: Add `Nan::To()` overload. b93280670c9f6da42ed4cf6cbf085ffdd87bd65b + - Bugfix: Fix ternary in `Nan::MaybeLocal::FromMaybe()`. 79a26f7d362e756a9524e672a82c3d603b542867 + +### 2.6.2 Apr 12 2017 + + - Bugfix: Fix v8::JSON::Parse() deprecation warning. 87f6a3c65815fa062296a994cc863e2fa124867d + +### 2.6.1 Apr 6 2017 + + - Bugfix: nan_json.h: fix build breakage in Node 6 ac8d47dc3c10bfbf3f15a6b951633120c0ee6d51 + +### 2.6.0 Apr 6 2017 + + - Feature: nan: add support for JSON::Parse & Stringify b533226c629cce70e1932a873bb6f849044a56c5 + +### 2.5.1 Jan 23 2017 + + - Bugfix: Fix disappearing handle for private value 6a80995694f162ef63dbc9948fbefd45d4485aa0 + - Bugfix: Add missing scopes a93b8bae6bc7d32a170db6e89228b7f60ee57112 + - Bugfix: Use string::data instead of string::front in NewOneByteString d5f920371e67e1f3b268295daee6e83af86b6e50 + +### 2.5.0 Dec 21 2016 + + - Feature: Support Private accessors a86255cb357e8ad8ccbf1f6a4a901c921e39a178 + - Bugfix: Abort in delete operators that shouldn't be called 0fe38215ff8581703967dfd26c12793feb960018 + +### 2.4.0 Jul 10 2016 + + - Feature: Rewrite Callback to add Callback::Reset c4cf44d61f8275cd5f7b0c911d7a806d4004f649 + - Feature: AsyncProgressWorker: add template types for .send 1242c9a11a7ed481c8f08ec06316385cacc513d0 + - Bugfix: Add constness to old Persistent comparison operators bd43cb9982c7639605d60fd073efe8cae165d9b2 + +### 2.3.5 May 31 2016 + + - Bugfix: Replace NAN_INLINE with 'inline' keyword. 71819d8725f822990f439479c9aba3b240804909 + +### 2.3.4 May 31 2016 + + - Bugfix: Remove V8 deprecation warnings 0592fb0a47f3a1c7763087ebea8e1138829f24f9 + - Bugfix: Fix new versions not to use WeakCallbackInfo::IsFirstPass 615c19d9e03d4be2049c10db0151edbc3b229246 + - Bugfix: Make ObjectWrap::handle() const d19af99595587fe7a26bd850af6595c2a7145afc + - Bugfix: Fix compilation errors related to 0592fb0a47f3a1c7763087ebea8e1138829f24f9 e9191c525b94f652718325e28610a1adcf90fed8 + +### 2.3.3 May 4 2016 + + - Bugfix: Refactor SetMethod() to deal with v8::Templates (#566) b9083cf6d5de6ebe6bcb49c7502fbb7c0d9ddda8 + +### 2.3.2 Apr 27 2016 + + - Bugfix: Fix compilation on outdated versions due to Handle removal f8b7c875d04d425a41dfd4f3f8345bc3a11e6c52 + +### 2.3.1 Apr 27 2016 + + - Bugfix: Don't use deprecated v8::Template::Set() in SetMethod a90951e9ea70fa1b3836af4b925322919159100e + +### 2.3.0 Apr 27 2016 + + - Feature: added Signal() for invoking async callbacks without sending data from AsyncProgressWorker d8adba45f20e077d00561b20199133620c990b38 + - Bugfix: Don't use deprecated v8::Template::Set() 00dacf0a4b86027415867fa7f1059acc499dcece + +### 2.2.1 Mar 29 2016 + + - Bugfix: Use NewFromUnsigned in ReturnValue::Set(uint32_t i) for pre_12 3a18f9bdce29826e0e4c217854bc476918241a58 + - Performance: Remove unneeeded nullptr checks b715ef44887931c94f0d1605b3b1a4156eebece9 + +### 2.2.0 Jan 9 2016 + + - Feature: Add Function::Call wrapper 4c157474dacf284d125c324177b45aa5dabc08c6 + - Feature: Rename GC*logueCallback to GCCallback for > 4.0 3603435109f981606d300eb88004ca101283acec + - Bugfix: Fix Global::Pass for old versions 367e82a60fbaa52716232cc89db1cc3f685d77d9 + - Bugfix: Remove weird MaybeLocal wrapping of what already is a MaybeLocal 23b4590db10c2ba66aee2338aebe9751c4cb190b + +### 2.1.0 Oct 8 2015 + + - Deprecation: Deprecate NanErrnoException in favor of ErrnoException 0af1ca4cf8b3f0f65ed31bc63a663ab3319da55c + - Feature: added helper class for accessing contents of typedarrays 17b51294c801e534479d5463697a73462d0ca555 + - Feature: [Maybe types] Add MakeMaybe(...) 48d7b53d9702b0c7a060e69ea10fea8fb48d814d + - Feature: new: allow utf16 string with length 66ac6e65c8ab9394ef588adfc59131b3b9d8347b + - Feature: Introduce SetCallHandler and SetCallAsFunctionHandler 7764a9a115d60ba10dc24d86feb0fbc9b4f75537 + - Bugfix: Enable creating Locals from Globals under Node 0.10. 9bf9b8b190821af889790fdc18ace57257e4f9ff + - Bugfix: Fix issue #462 where PropertyCallbackInfo data is not stored safely. 55f50adedd543098526c7b9f4fffd607d3f9861f + +### 2.0.9 Sep 8 2015 + + - Bugfix: EscapableHandleScope in Nan::NewBuffer for Node 0.8 and 0.10 b1654d7 + +### 2.0.8 Aug 28 2015 + + - Work around duplicate linking bug in clang 11902da + +### 2.0.7 Aug 26 2015 + + - Build: Repackage + +### 2.0.6 Aug 26 2015 + + - Bugfix: Properly handle null callback in FunctionTemplate factory 6e99cb1 + - Bugfix: Remove unused static std::map instances 525bddc + - Bugfix: Make better use of maybe versions of APIs bfba85b + - Bugfix: Fix shadowing issues with handle in ObjectWrap 0a9072d + +### 2.0.5 Aug 10 2015 + + - Bugfix: Reimplement weak callback in ObjectWrap 98d38c1 + - Bugfix: Make sure callback classes are not assignable, copyable or movable 81f9b1d + +### 2.0.4 Aug 6 2015 + + - Build: Repackage + +### 2.0.3 Aug 6 2015 + + - Bugfix: Don't use clang++ / g++ syntax extension. 231450e + +### 2.0.2 Aug 6 2015 + + - Build: Repackage + +### 2.0.1 Aug 6 2015 + + - Bugfix: Add workaround for missing REPLACE_INVALID_UTF8 60d6687 + - Bugfix: Reimplement ObjectWrap from scratch to prevent memory leaks 6484601 + - Bugfix: Fix Persistent leak in FunctionCallbackInfo and PropertyCallbackInfo 641ef5f + - Bugfix: Add missing overload for Nan::NewInstance that takes argc/argv 29450ed + +### 2.0.0 Jul 31 2015 + + - Change: Renamed identifiers with leading underscores b5932b4 + - Change: Replaced NanObjectWrapHandle with class NanObjectWrap 464f1e1 + - Change: Replace NanScope and NanEscpableScope macros with classes 47751c4 + - Change: Rename NanNewBufferHandle to NanNewBuffer 6745f99 + - Change: Rename NanBufferUse to NanNewBuffer 3e8b0a5 + - Change: Rename NanNewBuffer to NanCopyBuffer d6af78d + - Change: Remove Nan prefix from all names 72d1f67 + - Change: Update Buffer API for new upstream changes d5d3291 + - Change: Rename Scope and EscapableScope to HandleScope and EscapableHandleScope 21a7a6a + - Change: Get rid of Handles e6c0daf + - Feature: Support io.js 3 with V8 4.4 + - Feature: Introduce NanPersistent 7fed696 + - Feature: Introduce NanGlobal 4408da1 + - Feature: Added NanTryCatch 10f1ca4 + - Feature: Update for V8 v4.3 4b6404a + - Feature: Introduce NanNewOneByteString c543d32 + - Feature: Introduce namespace Nan 67ed1b1 + - Removal: Remove NanLocker and NanUnlocker dd6e401 + - Removal: Remove string converters, except NanUtf8String, which now follows the node implementation b5d00a9 + - Removal: Remove NanReturn* macros d90a25c + - Removal: Remove HasInstance e8f84fe + + +### 1.9.0 Jul 31 2015 + + - Feature: Added `NanFatalException` 81d4a2c + - Feature: Added more error types 4265f06 + - Feature: Added dereference and function call operators to NanCallback c4b2ed0 + - Feature: Added indexed GetFromPersistent and SaveToPersistent edd510c + - Feature: Added more overloads of SaveToPersistent and GetFromPersistent 8b1cef6 + - Feature: Added NanErrnoException dd87d9e + - Correctness: Prevent assign, copy, and move for classes that do not support it 1f55c59, 4b808cb, c96d9b2, fba4a29, 3357130 + - Deprecation: Deprecate `NanGetPointerSafe` and `NanSetPointerSafe` 81d4a2c + - Deprecation: Deprecate `NanBooleanOptionValue` and `NanUInt32OptionValue` 0ad254b + +### 1.8.4 Apr 26 2015 + + - Build: Repackage + +### 1.8.3 Apr 26 2015 + + - Bugfix: Include missing header 1af8648 + +### 1.8.2 Apr 23 2015 + + - Build: Repackage + +### 1.8.1 Apr 23 2015 + + - Bugfix: NanObjectWrapHandle should take a pointer 155f1d3 + +### 1.8.0 Apr 23 2015 + + - Feature: Allow primitives with NanReturnValue 2e4475e + - Feature: Added comparison operators to NanCallback 55b075e + - Feature: Backport thread local storage 15bb7fa + - Removal: Remove support for signatures with arguments 8a2069d + - Correcteness: Replaced NanObjectWrapHandle macro with function 0bc6d59 + +### 1.7.0 Feb 28 2015 + + - Feature: Made NanCallback::Call accept optional target 8d54da7 + - Feature: Support atom-shell 0.21 0b7f1bb + +### 1.6.2 Feb 6 2015 + + - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639 + +### 1.6.1 Jan 23 2015 + + - Build: version bump + +### 1.5.3 Jan 23 2015 + + - Build: repackage + +### 1.6.0 Jan 23 2015 + + - Deprecated `NanNewContextHandle` in favor of `NanNew` 49259af + - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179 + - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9 + +### 1.5.2 Jan 23 2015 + + - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4 + - Bugfix: Readded missing String constructors 18d828f + - Bugfix: Add overload handling NanNew(..) 5ef813b + - Bugfix: Fix uv_work_cb versioning 997e4ae + - Bugfix: Add function factory and test 4eca89c + - Bugfix: Add object template factory and test cdcb951 + - Correctness: Lifted an io.js related typedef c9490be + - Correctness: Make explicit downcasts of String lengths 00074e6 + - Windows: Limit the scope of disabled warning C4530 83d7deb + +### 1.5.1 Jan 15 2015 + + - Build: version bump + +### 1.4.3 Jan 15 2015 + + - Build: version bump + +### 1.4.2 Jan 15 2015 + + - Feature: Support io.js 0dbc5e8 + +### 1.5.0 Jan 14 2015 + + - Feature: Support io.js b003843 + - Correctness: Improved NanNew internals 9cd4f6a + - Feature: Implement progress to NanAsyncWorker 8d6a160 + +### 1.4.1 Nov 8 2014 + + - Bugfix: Handle DEBUG definition correctly + - Bugfix: Accept int as Boolean + +### 1.4.0 Nov 1 2014 + + - Feature: Added NAN_GC_CALLBACK 6a5c245 + - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8 + - Correctness: Added constness to references in NanHasInstance 02c61cd + - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6 + - Windoze: Shut Visual Studio up when compiling 8d558c1 + - License: Switch to plain MIT from custom hacked MIT license 11de983 + - Build: Added test target to Makefile e232e46 + - Performance: Removed superfluous scope in NanAsyncWorker f4b7821 + - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208 + - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450 + +### 1.3.0 Aug 2 2014 + + - Added NanNew(std::string) + - Added NanNew(std::string&) + - Added NanAsciiString helper class + - Added NanUtf8String helper class + - Added NanUcs2String helper class + - Deprecated NanRawString() + - Deprecated NanCString() + - Added NanGetIsolateData(v8::Isolate *isolate) + - Added NanMakeCallback(v8::Handle target, v8::Handle func, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, v8::Handle symbol, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, const char* method, int argc, v8::Handle* argv) + - Added NanSetTemplate(v8::Handle templ, v8::Handle name , v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetPrototypeTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetInstanceTemplate(v8::Local templ, const char *name, v8::Handle value) + - Added NanSetInstanceTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + +### 1.2.0 Jun 5 2014 + + - Add NanSetPrototypeTemplate + - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class, + introduced _NanWeakCallbackDispatcher + - Removed -Wno-unused-local-typedefs from test builds + - Made test builds Windows compatible ('Sleep()') + +### 1.1.2 May 28 2014 + + - Release to fix more stuff-ups in 1.1.1 + +### 1.1.1 May 28 2014 + + - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 + +### 1.1.0 May 25 2014 + + - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead + - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), + (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, + v8::String::ExternalAsciiStringResource* + - Deprecate NanSymbol() + - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker + +### 1.0.0 May 4 2014 + + - Heavy API changes for V8 3.25 / Node 0.11.13 + - Use cpplint.py + - Removed NanInitPersistent + - Removed NanPersistentToLocal + - Removed NanFromV8String + - Removed NanMakeWeak + - Removed NanNewLocal + - Removed NAN_WEAK_CALLBACK_OBJECT + - Removed NAN_WEAK_CALLBACK_DATA + - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions + - Introduce NanUndefined, NanNull, NanTrue and NanFalse + - Introduce NanEscapableScope and NanEscapeScope + - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) + - Introduce NanMakeCallback for node::MakeCallback + - Introduce NanSetTemplate + - Introduce NanGetCurrentContext + - Introduce NanCompileScript and NanRunScript + - Introduce NanAdjustExternalMemory + - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback + - Introduce NanGetHeapStatistics + - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() + +### 0.8.0 Jan 9 2014 + + - NanDispose -> NanDisposePersistent, deprecate NanDispose + - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() + +### 0.7.1 Jan 9 2014 + + - Fixes to work against debug builds of Node + - Safer NanPersistentToLocal (avoid reinterpret_cast) + - Speed up common NanRawString case by only extracting flattened string when necessary + +### 0.7.0 Dec 17 2013 + + - New no-arg form of NanCallback() constructor. + - NanCallback#Call takes Handle rather than Local + - Removed deprecated NanCallback#Run method, use NanCallback#Call instead + - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS + - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() + - Introduce NanRawString() for char* (or appropriate void*) from v8::String + (replacement for NanFromV8String) + - Introduce NanCString() for null-terminated char* from v8::String + +### 0.6.0 Nov 21 2013 + + - Introduce NanNewLocal(v8::Handle value) for use in place of + v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 + +### 0.5.2 Nov 16 2013 + + - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public + +### 0.5.1 Nov 12 2013 + + - Use node::MakeCallback() instead of direct v8::Function::Call() + +### 0.5.0 Nov 11 2013 + + - Added @TooTallNate as collaborator + - New, much simpler, "include_dirs" for binding.gyp + - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros + +### 0.4.4 Nov 2 2013 + + - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ + +### 0.4.3 Nov 2 2013 + + - Include node_object_wrap.h, removed from node.h for Node 0.11.8. + +### 0.4.2 Nov 2 2013 + + - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for + Node 0.11.8 release. + +### 0.4.1 Sep 16 2013 + + - Added explicit `#include ` as it was removed from node.h for v0.11.8 + +### 0.4.0 Sep 2 2013 + + - Added NAN_INLINE and NAN_DEPRECATED and made use of them + - Added NanError, NanTypeError and NanRangeError + - Cleaned up code + +### 0.3.2 Aug 30 2013 + + - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent + in NanAsyncWorker + +### 0.3.1 Aug 20 2013 + + - fix "not all control paths return a value" compile warning on some platforms + +### 0.3.0 Aug 19 2013 + + - Made NAN work with NPM + - Lots of fixes to NanFromV8String, pulling in features from new Node core + - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API + - Added optional error number argument for NanThrowError() + - Added NanInitPersistent() + - Added NanReturnNull() and NanReturnEmptyString() + - Added NanLocker and NanUnlocker + - Added missing scopes + - Made sure to clear disposed Persistent handles + - Changed NanAsyncWorker to allocate error messages on the heap + - Changed NanThrowError(Local) to NanThrowError(Handle) + - Fixed leak in NanAsyncWorker when errmsg is used + +### 0.2.2 Aug 5 2013 + + - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() + +### 0.2.1 Aug 5 2013 + + - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for + NanFromV8String() + +### 0.2.0 Aug 5 2013 + + - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, + NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY + - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, + _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, + _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, + _NAN_PROPERTY_QUERY_ARGS + - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer + - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, + NAN_WEAK_CALLBACK_DATA, NanMakeWeak + - Renamed THROW_ERROR to _NAN_THROW_ERROR + - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) + - Added NanBufferUse(char*, uint32_t) + - Added NanNewContextHandle(v8::ExtensionConfiguration*, + v8::Handle, v8::Handle) + - Fixed broken NanCallback#GetFunction() + - Added optional encoding and size arguments to NanFromV8String() + - Added NanGetPointerSafe() and NanSetPointerSafe() + - Added initial test suite (to be expanded) + - Allow NanUInt32OptionValue to convert any Number object + +### 0.1.0 Jul 21 2013 + + - Added `NAN_GETTER`, `NAN_SETTER` + - Added `NanThrowError` with single Local argument + - Added `NanNewBufferHandle` with single uint32_t argument + - Added `NanHasInstance(Persistent&, Handle)` + - Added `Local NanCallback#GetFunction()` + - Added `NanCallback#Call(int, Local[])` + - Deprecated `NanCallback#Run(int, Local[])` in favour of Call diff --git a/reverse_engineering/node_modules/nan/LICENSE.md b/reverse_engineering/node_modules/nan/LICENSE.md new file mode 100644 index 0000000..dddd13d --- /dev/null +++ b/reverse_engineering/node_modules/nan/LICENSE.md @@ -0,0 +1,13 @@ +The MIT License (MIT) +===================== + +Copyright (c) 2018 NAN contributors +----------------------------------- + +*NAN contributors listed at * + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/reverse_engineering/node_modules/nan/README.md b/reverse_engineering/node_modules/nan/README.md new file mode 100644 index 0000000..8988a09 --- /dev/null +++ b/reverse_engineering/node_modules/nan/README.md @@ -0,0 +1,456 @@ +Native Abstractions for Node.js +=============================== + +**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 and 16.** + +***Current version: 2.15.0*** + +*(See [CHANGELOG.md](https://github.com/nodejs/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* + +[![NPM](https://nodei.co/npm/nan.png?downloads=true&downloadRank=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6&height=3)](https://nodei.co/npm/nan/) + +[![Build Status](https://api.travis-ci.com/nodejs/nan.svg?branch=master)](https://travis-ci.com/nodejs/nan) +[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) + +Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.12 to 4.0, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. + +This project also contains some helper utilities that make addon development a bit more pleasant. + + * **[News & Updates](#news)** + * **[Usage](#usage)** + * **[Example](#example)** + * **[API](#api)** + * **[Tests](#tests)** + * **[Known issues](#issues)** + * **[Governance & Contributing](#governance)** + + + +## News & Updates + + + +## Usage + +Simply add **NAN** as a dependency in the *package.json* of your Node addon: + +``` bash +$ npm install --save nan +``` + +Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: + +``` python +"include_dirs" : [ + "` when compiling your addon. + + + +## Example + +Just getting started with Nan? Take a look at the **[Node Add-on Examples](https://github.com/nodejs/node-addon-examples)**. + +Refer to a [quick-start **Nan** Boilerplate](https://github.com/fcanas/node-native-boilerplate) for a ready-to-go project that utilizes basic Nan functionality. + +For a simpler example, see the **[async pi estimation example](https://github.com/nodejs/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. + +Yet another example is **[nan-example-eol](https://github.com/CodeCharmLtd/nan-example-eol)**. It shows newline detection implemented as a native addon. + +Also take a look at our comprehensive **[C++ test suite](https://github.com/nodejs/nan/tree/master/test/cpp)** which has a plethora of code snippets for your pasting pleasure. + + + +## API + +Additional to the NAN documentation below, please consult: + +* [The V8 Getting Started * Guide](https://v8.dev/docs/embed) +* [V8 API Documentation](https://v8docs.nodesource.com/) +* [Node Add-on Documentation](https://nodejs.org/api/addons.html) + + + +### JavaScript-accessible methods + +A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information. + +In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type. + +* **Method argument types** + - Nan::FunctionCallbackInfo + - Nan::PropertyCallbackInfo + - Nan::ReturnValue +* **Method declarations** + - Method declaration + - Getter declaration + - Setter declaration + - Property getter declaration + - Property setter declaration + - Property enumerator declaration + - Property deleter declaration + - Property query declaration + - Index getter declaration + - Index setter declaration + - Index enumerator declaration + - Index deleter declaration + - Index query declaration +* Method and template helpers + - Nan::SetMethod() + - Nan::SetPrototypeMethod() + - Nan::SetAccessor() + - Nan::SetNamedPropertyHandler() + - Nan::SetIndexedPropertyHandler() + - Nan::SetTemplate() + - Nan::SetPrototypeTemplate() + - Nan::SetInstanceTemplate() + - Nan::SetCallHandler() + - Nan::SetCallAsFunctionHandler() + +### Scopes + +A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works. + +A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope. + +The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these. + + - Nan::HandleScope + - Nan::EscapableHandleScope + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection). + +### Persistent references + +An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed. + +Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported. + + - Nan::PersistentBase & v8::PersistentBase + - Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + - Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + - Nan::Persistent + - Nan::Global + - Nan::WeakCallbackInfo + - Nan::WeakCallbackType + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles). + +### New + +NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8. + + - Nan::New() + - Nan::Undefined() + - Nan::Null() + - Nan::True() + - Nan::False() + - Nan::EmptyString() + + +### Converters + +NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN. + + - Nan::To() + +### Maybe Types + +The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_. + +* **Maybe Types** + - Nan::MaybeLocal + - Nan::Maybe + - Nan::Nothing + - Nan::Just +* **Maybe Helpers** + - Nan::Call() + - Nan::ToDetailString() + - Nan::ToArrayIndex() + - Nan::Equals() + - Nan::NewInstance() + - Nan::GetFunction() + - Nan::Set() + - Nan::DefineOwnProperty() + - Nan::ForceSet() + - Nan::Get() + - Nan::GetPropertyAttributes() + - Nan::Has() + - Nan::Delete() + - Nan::GetPropertyNames() + - Nan::GetOwnPropertyNames() + - Nan::SetPrototype() + - Nan::ObjectProtoToString() + - Nan::HasOwnProperty() + - Nan::HasRealNamedProperty() + - Nan::HasRealIndexedProperty() + - Nan::HasRealNamedCallbackProperty() + - Nan::GetRealNamedPropertyInPrototypeChain() + - Nan::GetRealNamedProperty() + - Nan::CallAsFunction() + - Nan::CallAsConstructor() + - Nan::GetSourceLine() + - Nan::GetLineNumber() + - Nan::GetStartColumn() + - Nan::GetEndColumn() + - Nan::CloneElementAt() + - Nan::HasPrivate() + - Nan::GetPrivate() + - Nan::SetPrivate() + - Nan::DeletePrivate() + - Nan::MakeMaybe() + +### Script + +NAN provides `v8::Script` helpers as the API has changed over the supported versions of V8. + + - Nan::CompileScript() + - Nan::RunScript() + - Nan::ScriptOrigin + + +### JSON + +The _JSON_ object provides the C++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object. + + - Nan::JSON.Parse + - Nan::JSON.Stringify + +Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-8.16/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments. + +### Errors + +NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information. + + - Nan::Error() + - Nan::RangeError() + - Nan::ReferenceError() + - Nan::SyntaxError() + - Nan::TypeError() + - Nan::ThrowError() + - Nan::ThrowRangeError() + - Nan::ThrowReferenceError() + - Nan::ThrowSyntaxError() + - Nan::ThrowTypeError() + - Nan::FatalException() + - Nan::ErrnoException() + - Nan::TryCatch + + +### Buffers + +NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility. + + - Nan::NewBuffer() + - Nan::CopyBuffer() + - Nan::FreeCallback() + +### Nan::Callback + +`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution. + + - Nan::Callback + +### Asynchronous work helpers + +`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier. + + - Nan::AsyncWorker + - Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + - Nan::AsyncProgressQueueWorker + - Nan::AsyncQueueWorker + +### Strings & Bytes + +Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing. + + - Nan::Encoding + - Nan::Encode() + - Nan::DecodeBytes() + - Nan::DecodeWrite() + + +### Object Wrappers + +The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects. + + - Nan::ObjectWrap + + +### V8 internals + +The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods. + + - NAN_GC_CALLBACK() + - Nan::AddGCEpilogueCallback() + - Nan::RemoveGCEpilogueCallback() + - Nan::AddGCPrologueCallback() + - Nan::RemoveGCPrologueCallback() + - Nan::GetHeapStatistics() + - Nan::SetCounterFunction() + - Nan::SetCreateHistogramFunction() + - Nan::SetAddHistogramSampleFunction() + - Nan::IdleNotification() + - Nan::LowMemoryNotification() + - Nan::ContextDisposedNotification() + - Nan::GetInternalFieldPointer() + - Nan::SetInternalFieldPointer() + - Nan::AdjustExternalMemory() + + +### Miscellaneous V8 Helpers + + - Nan::Utf8String + - Nan::GetCurrentContext() + - Nan::SetIsolateData() + - Nan::GetIsolateData() + - Nan::TypedArrayContents + + +### Miscellaneous Node Helpers + + - Nan::AsyncResource + - Nan::MakeCallback() + - NAN_MODULE_INIT() + - Nan::Export() + + + + + + +### Tests + +To run the NAN tests do: + +``` sh +npm install +npm run-script rebuild-tests +npm test +``` + +Or just: + +``` sh +npm install +make test +``` + + + +## Known issues + +### Compiling against Node.js 0.12 on OSX + +With new enough compilers available on OSX, the versions of V8 headers corresponding to Node.js 0.12 +do not compile anymore. The error looks something like: + +``` +❯ CXX(target) Release/obj.target/accessors/cpp/accessors.o +In file included from ../cpp/accessors.cpp:9: +In file included from ../../nan.h:51: +In file included from /Users/ofrobots/.node-gyp/0.12.18/include/node/node.h:61: +/Users/ofrobots/.node-gyp/0.12.18/include/node/v8.h:5800:54: error: 'CreateHandle' is a protected member of 'v8::HandleScope' + return Handle(reinterpret_cast(HandleScope::CreateHandle( + ~~~~~~~~~~~~~^~~~~~~~~~~~ +``` + +This can be worked around by patching your local versions of v8.h corresponding to Node 0.12 to make +`v8::Handle` a friend of `v8::HandleScope`. Since neither Node.js not V8 support this release line anymore +this patch cannot be released by either project in an official release. + +For this reason, we do not test against Node.js 0.12 on OSX in this project's CI. If you need to support +that configuration, you will need to either get an older compiler, or apply a source patch to the version +of V8 headers as a workaround. + + + +## Governance & Contributing + +NAN is governed by the [Node.js Addon API Working Group](https://github.com/nodejs/CTC/blob/master/WORKING_GROUPS.md#addon-api) + +### Addon API Working Group (WG) + +The NAN project is jointly governed by a Working Group which is responsible for high-level guidance of the project. + +Members of the WG are also known as Collaborators, there is no distinction between the two, unlike other Node.js projects. + +The WG has final authority over this project including: + +* Technical direction +* Project governance and process (including this policy) +* Contribution policy +* GitHub repository hosting +* Maintaining the list of additional Collaborators + +For the current list of WG members, see the project [README.md](./README.md#collaborators). + +Individuals making significant and valuable contributions are made members of the WG and given commit-access to the project. These individuals are identified by the WG and their addition to the WG is discussed via GitHub and requires unanimous consensus amongst those WG members participating in the discussion with a quorum of 50% of WG members required for acceptance of the vote. + +_Note:_ If you make a significant contribution and are not considered for commit-access log an issue or contact a WG member directly. + +For the current list of WG members / Collaborators, see the project [README.md](./README.md#collaborators). + +### Consensus Seeking Process + +The WG follows a [Consensus Seeking](https://en.wikipedia.org/wiki/Consensus-seeking_decision-making) decision making model. + +Modifications of the contents of the NAN repository are made on a collaborative basis. Anybody with a GitHub account may propose a modification via pull request and it will be considered by the WG. All pull requests must be reviewed and accepted by a WG member with sufficient expertise who is able to take full responsibility for the change. In the case of pull requests proposed by an existing WG member, an additional WG member is required for sign-off. Consensus should be sought if additional WG members participate and there is disagreement around a particular modification. + +If a change proposal cannot reach a consensus, a WG member can call for a vote amongst the members of the WG. Simple majority wins. + + + +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + + + +### WG Members / Collaborators + + + + + + + + + + +
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
David SiegelGitHub/agnatTwitter/@agnat
Michael Ira KrufkyGitHub/mkrufkyTwitter/@mkrufky
+ +## Licence & copyright + +Copyright (c) 2018 NAN WG Members / Collaborators (listed above). + +Native Abstractions for Node.js is licensed under an MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/reverse_engineering/node_modules/nan/doc/asyncworker.md b/reverse_engineering/node_modules/nan/doc/asyncworker.md new file mode 100644 index 0000000..04231f8 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/asyncworker.md @@ -0,0 +1,146 @@ +## Asynchronous work helpers + +`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier. + + - Nan::AsyncWorker + - Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + - Nan::AsyncProgressQueueWorker + - Nan::AsyncQueueWorker + + +### Nan::AsyncWorker + +`Nan::AsyncWorker` is an _abstract_ class that you can subclass to have much of the annoying asynchronous queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the asynchronous work is in progress. + +This class internally handles the details of creating an [`AsyncResource`][AsyncResource], and running the callback in the +correct async context. To be able to identify the async resources created by this class in async-hooks, provide a +`resource_name` to the constructor. It is recommended that the module name be used as a prefix to the `resource_name` to avoid +collisions in the names. For more details see [`AsyncResource`][AsyncResource] documentation. The `resource_name` needs to stay valid for the lifetime of the worker instance. + +Definition: + +```c++ +class AsyncWorker { + public: + explicit AsyncWorker(Callback *callback_, const char* resource_name = "nan:AsyncWorker"); + + virtual ~AsyncWorker(); + + virtual void WorkComplete(); + + void SaveToPersistent(const char *key, const v8::Local &value); + + void SaveToPersistent(const v8::Local &key, + const v8::Local &value); + + void SaveToPersistent(uint32_t index, + const v8::Local &value); + + v8::Local GetFromPersistent(const char *key) const; + + v8::Local GetFromPersistent(const v8::Local &key) const; + + v8::Local GetFromPersistent(uint32_t index) const; + + virtual void Execute() = 0; + + uv_work_t request; + + virtual void Destroy(); + + protected: + Persistent persistentHandle; + + Callback *callback; + + virtual void HandleOKCallback(); + + virtual void HandleErrorCallback(); + + void SetErrorMessage(const char *msg); + + const char* ErrorMessage(); +}; +``` + + +### Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + +`Nan::AsyncProgressWorkerBase` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript. + +Previously the definition of `Nan::AsyncProgressWorker` only allowed sending `const char` data. Now extending `Nan::AsyncProgressWorker` will yield an instance of the implicit `Nan::AsyncProgressWorkerBase` template with type `` for compatibility. + +`Nan::AsyncProgressWorkerBase` & `Nan::AsyncProgressWorker` is intended for best-effort delivery of nonessential progress messages, e.g. a progress bar. The last event sent before the main thread is woken will be delivered. + +Definition: + +```c++ +template +class AsyncProgressWorkerBase : public AsyncWorker { + public: + explicit AsyncProgressWorkerBase(Callback *callback_, const char* resource_name = ...); + + virtual ~AsyncProgressWorkerBase(); + + void WorkProgress(); + + class ExecutionProgress { + public: + void Signal() const; + void Send(const T* data, size_t count) const; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + + virtual void HandleProgressCallback(const T *data, size_t count) = 0; + + virtual void Destroy(); +}; + +typedef AsyncProgressWorkerBase AsyncProgressWorker; +``` + + +### Nan::AsyncProgressQueueWorker + +`Nan::AsyncProgressQueueWorker` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript. + +`Nan::AsyncProgressQueueWorker` behaves exactly the same as `Nan::AsyncProgressWorker`, except all events are queued and delivered to the main thread. + +Definition: + +```c++ +template +class AsyncProgressQueueWorker : public AsyncWorker { + public: + explicit AsyncProgressQueueWorker(Callback *callback_, const char* resource_name = "nan:AsyncProgressQueueWorker"); + + virtual ~AsyncProgressQueueWorker(); + + void WorkProgress(); + + class ExecutionProgress { + public: + void Send(const T* data, size_t count) const; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + + virtual void HandleProgressCallback(const T *data, size_t count) = 0; + + virtual void Destroy(); +}; +``` + + +### Nan::AsyncQueueWorker + +`Nan::AsyncQueueWorker` will run a `Nan::AsyncWorker` asynchronously via libuv. Both the `execute` and `after_work` steps are taken care of for you. Most of the logic for this is embedded in `Nan::AsyncWorker`. + +Definition: + +```c++ +void AsyncQueueWorker(AsyncWorker *); +``` + +[AsyncResource]: node_misc.md#api_nan_asyncresource diff --git a/reverse_engineering/node_modules/nan/doc/buffers.md b/reverse_engineering/node_modules/nan/doc/buffers.md new file mode 100644 index 0000000..8d8d25c --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/buffers.md @@ -0,0 +1,54 @@ +## Buffers + +NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility. + + - Nan::NewBuffer() + - Nan::CopyBuffer() + - Nan::FreeCallback() + + +### Nan::NewBuffer() + +Allocate a new `node::Buffer` object with the specified size and optional data. Calls `node::Buffer::New()`. + +Note that when creating a `Buffer` using `Nan::NewBuffer()` and an existing `char*`, it is assumed that the ownership of the pointer is being transferred to the new `Buffer` for management. +When a `node::Buffer` instance is garbage collected and a `FreeCallback` has not been specified, `data` will be disposed of via a call to `free()`. +You _must not_ free the memory space manually once you have created a `Buffer` in this way. + +Signature: + +```c++ +Nan::MaybeLocal Nan::NewBuffer(uint32_t size) +Nan::MaybeLocal Nan::NewBuffer(char* data, uint32_t size) +Nan::MaybeLocal Nan::NewBuffer(char *data, + size_t length, + Nan::FreeCallback callback, + void *hint) +``` + + + +### Nan::CopyBuffer() + +Similar to [`Nan::NewBuffer()`](#api_nan_new_buffer) except that an implicit memcpy will occur within Node. Calls `node::Buffer::Copy()`. + +Management of the `char*` is left to the user, you should manually free the memory space if necessary as the new `Buffer` will have its own copy. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CopyBuffer(const char *data, uint32_t size) +``` + + + +### Nan::FreeCallback() + +A free callback that can be provided to [`Nan::NewBuffer()`](#api_nan_new_buffer). +The supplied callback will be invoked when the `Buffer` undergoes garbage collection. + +Signature: + +```c++ +typedef void (*FreeCallback)(char *data, void *hint); +``` diff --git a/reverse_engineering/node_modules/nan/doc/callback.md b/reverse_engineering/node_modules/nan/doc/callback.md new file mode 100644 index 0000000..f7af0bf --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/callback.md @@ -0,0 +1,76 @@ +## Nan::Callback + +`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution. + + - Nan::Callback + + +### Nan::Callback + +```c++ +class Callback { + public: + Callback(); + + explicit Callback(const v8::Local &fn); + + ~Callback(); + + bool operator==(const Callback &other) const; + + bool operator!=(const Callback &other) const; + + v8::Local operator*() const; + + MaybeLocal operator()(AsyncResource* async_resource, + v8::Local target, + int argc = 0, + v8::Local argv[] = 0) const; + + MaybeLocal operator()(AsyncResource* async_resource, + int argc = 0, + v8::Local argv[] = 0) const; + + void SetFunction(const v8::Local &fn); + + v8::Local GetFunction() const; + + bool IsEmpty() const; + + void Reset(const v8::Local &fn); + + void Reset(); + + MaybeLocal Call(v8::Local target, + int argc, + v8::Local argv[], + AsyncResource* async_resource) const; + MaybeLocal Call(int argc, + v8::Local argv[], + AsyncResource* async_resource) const; + + // Deprecated versions. Use the versions that accept an async_resource instead + // as they run the callback in the correct async context as specified by the + // resource. If you want to call a synchronous JS function (i.e. on a + // non-empty JS stack), you can use Nan::Call instead. + v8::Local operator()(v8::Local target, + int argc = 0, + v8::Local argv[] = 0) const; + + v8::Local operator()(int argc = 0, + v8::Local argv[] = 0) const; + v8::Local Call(v8::Local target, + int argc, + v8::Local argv[]) const; + + v8::Local Call(int argc, v8::Local argv[]) const; +}; +``` + +Example usage: + +```c++ +v8::Local function; +Nan::Callback callback(function); +callback.Call(0, 0); +``` diff --git a/reverse_engineering/node_modules/nan/doc/converters.md b/reverse_engineering/node_modules/nan/doc/converters.md new file mode 100644 index 0000000..d20861b --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/converters.md @@ -0,0 +1,41 @@ +## Converters + +NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN. + + - Nan::To() + + +### Nan::To() + +Converts a `v8::Local` to a different subtype of `v8::Value` or to a native data type. Returns a `Nan::MaybeLocal<>` or a `Nan::Maybe<>` accordingly. + +See [maybe_types.md](./maybe_types.md) for more information on `Nan::Maybe` types. + +Signatures: + +```c++ +// V8 types +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); + +// Native types +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +``` + +### Example + +```c++ +v8::Local val; +Nan::MaybeLocal str = Nan::To(val); +Nan::Maybe d = Nan::To(val); +``` + diff --git a/reverse_engineering/node_modules/nan/doc/errors.md b/reverse_engineering/node_modules/nan/doc/errors.md new file mode 100644 index 0000000..843435b --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/errors.md @@ -0,0 +1,226 @@ +## Errors + +NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information. + + - Nan::Error() + - Nan::RangeError() + - Nan::ReferenceError() + - Nan::SyntaxError() + - Nan::TypeError() + - Nan::ThrowError() + - Nan::ThrowRangeError() + - Nan::ThrowReferenceError() + - Nan::ThrowSyntaxError() + - Nan::ThrowTypeError() + - Nan::FatalException() + - Nan::ErrnoException() + - Nan::TryCatch + + + +### Nan::Error() + +Create a new Error object using the [v8::Exception](https://v8docs.nodesource.com/node-8.16/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::Error(const char *msg); +v8::Local Nan::Error(v8::Local msg); +``` + + + +### Nan::RangeError() + +Create a new RangeError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.16/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an RangeError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::RangeError(const char *msg); +v8::Local Nan::RangeError(v8::Local msg); +``` + + + +### Nan::ReferenceError() + +Create a new ReferenceError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.16/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an ReferenceError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::ReferenceError(const char *msg); +v8::Local Nan::ReferenceError(v8::Local msg); +``` + + + +### Nan::SyntaxError() + +Create a new SyntaxError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.16/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an SyntaxError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::SyntaxError(const char *msg); +v8::Local Nan::SyntaxError(v8::Local msg); +``` + + + +### Nan::TypeError() + +Create a new TypeError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.16/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an TypeError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::TypeError(const char *msg); +v8::Local Nan::TypeError(v8::Local msg); +``` + + + +### Nan::ThrowError() + +Throw an Error object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new Error object will be created. + +Signature: + +```c++ +void Nan::ThrowError(const char *msg); +void Nan::ThrowError(v8::Local msg); +void Nan::ThrowError(v8::Local error); +``` + + + +### Nan::ThrowRangeError() + +Throw an RangeError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new RangeError object will be created. + +Signature: + +```c++ +void Nan::ThrowRangeError(const char *msg); +void Nan::ThrowRangeError(v8::Local msg); +void Nan::ThrowRangeError(v8::Local error); +``` + + + +### Nan::ThrowReferenceError() + +Throw an ReferenceError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new ReferenceError object will be created. + +Signature: + +```c++ +void Nan::ThrowReferenceError(const char *msg); +void Nan::ThrowReferenceError(v8::Local msg); +void Nan::ThrowReferenceError(v8::Local error); +``` + + + +### Nan::ThrowSyntaxError() + +Throw an SyntaxError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new SyntaxError object will be created. + +Signature: + +```c++ +void Nan::ThrowSyntaxError(const char *msg); +void Nan::ThrowSyntaxError(v8::Local msg); +void Nan::ThrowSyntaxError(v8::Local error); +``` + + + +### Nan::ThrowTypeError() + +Throw an TypeError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new TypeError object will be created. + +Signature: + +```c++ +void Nan::ThrowTypeError(const char *msg); +void Nan::ThrowTypeError(v8::Local msg); +void Nan::ThrowTypeError(v8::Local error); +``` + + +### Nan::FatalException() + +Replaces `node::FatalException()` which has a different API across supported versions of Node. For use with [`Nan::TryCatch`](#api_nan_try_catch). + +Signature: + +```c++ +void Nan::FatalException(const Nan::TryCatch& try_catch); +``` + + +### Nan::ErrnoException() + +Replaces `node::ErrnoException()` which has a different API across supported versions of Node. + +Signature: + +```c++ +v8::Local Nan::ErrnoException(int errorno, + const char* syscall = NULL, + const char* message = NULL, + const char* path = NULL); +``` + + + +### Nan::TryCatch + +A simple wrapper around [`v8::TryCatch`](https://v8docs.nodesource.com/node-8.16/d4/dc6/classv8_1_1_try_catch.html) compatible with all supported versions of V8. Can be used as a direct replacement in most cases. See also [`Nan::FatalException()`](#api_nan_fatal_exception) for an internal use compatible with `node::FatalException`. + +Signature: + +```c++ +class Nan::TryCatch { + public: + Nan::TryCatch(); + + bool HasCaught() const; + + bool CanContinue() const; + + v8::Local ReThrow(); + + v8::Local Exception() const; + + // Nan::MaybeLocal for older versions of V8 + v8::MaybeLocal StackTrace() const; + + v8::Local Message() const; + + void Reset(); + + void SetVerbose(bool value); + + void SetCaptureMessage(bool value); +}; +``` + diff --git a/reverse_engineering/node_modules/nan/doc/json.md b/reverse_engineering/node_modules/nan/doc/json.md new file mode 100644 index 0000000..55beb26 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/json.md @@ -0,0 +1,62 @@ +## JSON + +The _JSON_ object provides the C++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object. + + - Nan::JSON.Parse + - Nan::JSON.Stringify + +Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-8.16/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments. + + + +### Nan::JSON.Parse + +A simple wrapper around [`v8::JSON::Parse`](https://v8docs.nodesource.com/node-8.16/da/d6f/classv8_1_1_j_s_o_n.html#a936310d2540fb630ed37d3ee3ffe4504). + +Definition: + +```c++ +Nan::MaybeLocal Nan::JSON::Parse(v8::Local json_string); +``` + +Use `JSON.Parse(json_string)` to parse a string into a `v8::Value`. + +Example: + +```c++ +v8::Local json_string = Nan::New("{ \"JSON\": \"object\" }").ToLocalChecked(); + +Nan::JSON NanJSON; +Nan::MaybeLocal result = NanJSON.Parse(json_string); +if (!result.IsEmpty()) { + v8::Local val = result.ToLocalChecked(); +} +``` + + + +### Nan::JSON.Stringify + +A simple wrapper around [`v8::JSON::Stringify`](https://v8docs.nodesource.com/node-8.16/da/d6f/classv8_1_1_j_s_o_n.html#a44b255c3531489ce43f6110209138860). + +Definition: + +```c++ +Nan::MaybeLocal Nan::JSON::Stringify(v8::Local json_object, v8::Local gap = v8::Local()); +``` + +Use `JSON.Stringify(value)` to stringify a `v8::Object`. + +Example: + +```c++ +// using `v8::Local val` from the `JSON::Parse` example +v8::Local obj = Nan::To(val).ToLocalChecked(); + +Nan::JSON NanJSON; +Nan::MaybeLocal result = NanJSON.Stringify(obj); +if (!result.IsEmpty()) { + v8::Local stringified = result.ToLocalChecked(); +} +``` + diff --git a/reverse_engineering/node_modules/nan/doc/maybe_types.md b/reverse_engineering/node_modules/nan/doc/maybe_types.md new file mode 100644 index 0000000..142851a --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/maybe_types.md @@ -0,0 +1,583 @@ +## Maybe Types + +The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_. + +* **Maybe Types** + - Nan::MaybeLocal + - Nan::Maybe + - Nan::Nothing + - Nan::Just +* **Maybe Helpers** + - Nan::Call() + - Nan::ToDetailString() + - Nan::ToArrayIndex() + - Nan::Equals() + - Nan::NewInstance() + - Nan::GetFunction() + - Nan::Set() + - Nan::DefineOwnProperty() + - Nan::ForceSet() + - Nan::Get() + - Nan::GetPropertyAttributes() + - Nan::Has() + - Nan::Delete() + - Nan::GetPropertyNames() + - Nan::GetOwnPropertyNames() + - Nan::SetPrototype() + - Nan::ObjectProtoToString() + - Nan::HasOwnProperty() + - Nan::HasRealNamedProperty() + - Nan::HasRealIndexedProperty() + - Nan::HasRealNamedCallbackProperty() + - Nan::GetRealNamedPropertyInPrototypeChain() + - Nan::GetRealNamedProperty() + - Nan::CallAsFunction() + - Nan::CallAsConstructor() + - Nan::GetSourceLine() + - Nan::GetLineNumber() + - Nan::GetStartColumn() + - Nan::GetEndColumn() + - Nan::CloneElementAt() + - Nan::HasPrivate() + - Nan::GetPrivate() + - Nan::SetPrivate() + - Nan::DeletePrivate() + - Nan::MakeMaybe() + + +### Nan::MaybeLocal + +A `Nan::MaybeLocal` is a wrapper around [`v8::Local`](https://v8docs.nodesource.com/node-8.16/de/deb/classv8_1_1_local.html) that enforces a check that determines whether the `v8::Local` is empty before it can be used. + +If an API method returns a `Nan::MaybeLocal`, the API method can potentially fail either because an exception is thrown, or because an exception is pending, e.g. because a previous API call threw an exception that hasn't been caught yet, or because a `v8::TerminateExecution` exception was thrown. In that case, an empty `Nan::MaybeLocal` is returned. + +Definition: + +```c++ +template class Nan::MaybeLocal { + public: + MaybeLocal(); + + template MaybeLocal(v8::Local that); + + bool IsEmpty() const; + + template bool ToLocal(v8::Local *out); + + // Will crash if the MaybeLocal<> is empty. + v8::Local ToLocalChecked(); + + template v8::Local FromMaybe(v8::Local default_value) const; +}; +``` + +See the documentation for [`v8::MaybeLocal`](https://v8docs.nodesource.com/node-8.16/d8/d7d/classv8_1_1_maybe_local.html) for further details. + + +### Nan::Maybe + +A simple `Nan::Maybe` type, representing an object which may or may not have a value, see https://hackage.haskell.org/package/base/docs/Data-Maybe.html. + +If an API method returns a `Nan::Maybe<>`, the API method can potentially fail either because an exception is thrown, or because an exception is pending, e.g. because a previous API call threw an exception that hasn't been caught yet, or because a `v8::TerminateExecution` exception was thrown. In that case, a "Nothing" value is returned. + +Definition: + +```c++ +template class Nan::Maybe { + public: + bool IsNothing() const; + bool IsJust() const; + + // Will crash if the Maybe<> is nothing. + T FromJust(); + + T FromMaybe(const T& default_value); + + bool operator==(const Maybe &other); + + bool operator!=(const Maybe &other); +}; +``` + +See the documentation for [`v8::Maybe`](https://v8docs.nodesource.com/node-8.16/d9/d4b/classv8_1_1_maybe.html) for further details. + + +### Nan::Nothing + +Construct an empty `Nan::Maybe` type representing _nothing_. + +```c++ +template Nan::Maybe Nan::Nothing(); +``` + + +### Nan::Just + +Construct a `Nan::Maybe` type representing _just_ a value. + +```c++ +template Nan::Maybe Nan::Just(const T &t); +``` + + +### Nan::Call() + +A helper method for calling a synchronous [`v8::Function#Call()`](https://v8docs.nodesource.com/node-8.16/d5/d54/classv8_1_1_function.html#a9c3d0e4e13ddd7721fce238aa5b94a11) in a way compatible across supported versions of V8. + +For asynchronous callbacks, use Nan::Callback::Call along with an AsyncResource. + +Signature: + +```c++ +Nan::MaybeLocal Nan::Call(v8::Local fun, v8::Local recv, int argc, v8::Local argv[]); +Nan::MaybeLocal Nan::Call(const Nan::Callback& callback, v8::Local recv, + int argc, v8::Local argv[]); +Nan::MaybeLocal Nan::Call(const Nan::Callback& callback, int argc, v8::Local argv[]); +``` + + + +### Nan::ToDetailString() + +A helper method for calling [`v8::Value#ToDetailString()`](https://v8docs.nodesource.com/node-8.16/dc/d0a/classv8_1_1_value.html#a2f9770296dc2c8d274bc8cc0dca243e5) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::ToDetailString(v8::Local val); +``` + + + +### Nan::ToArrayIndex() + +A helper method for calling [`v8::Value#ToArrayIndex()`](https://v8docs.nodesource.com/node-8.16/dc/d0a/classv8_1_1_value.html#acc5bbef3c805ec458470c0fcd6f13493) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::ToArrayIndex(v8::Local val); +``` + + + +### Nan::Equals() + +A helper method for calling [`v8::Value#Equals()`](https://v8docs.nodesource.com/node-8.16/dc/d0a/classv8_1_1_value.html#a08fba1d776a59bbf6864b25f9152c64b) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Equals(v8::Local a, v8::Local(b)); +``` + + + +### Nan::NewInstance() + +A helper method for calling [`v8::Function#NewInstance()`](https://v8docs.nodesource.com/node-8.16/d5/d54/classv8_1_1_function.html#ae477558b10c14b76ed00e8dbab44ce5b) and [`v8::ObjectTemplate#NewInstance()`](https://v8docs.nodesource.com/node-8.16/db/d5f/classv8_1_1_object_template.html#ad605a7543cfbc5dab54cdb0883d14ae4) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::NewInstance(v8::Local h); +Nan::MaybeLocal Nan::NewInstance(v8::Local h, int argc, v8::Local argv[]); +Nan::MaybeLocal Nan::NewInstance(v8::Local h); +``` + + + +### Nan::GetFunction() + +A helper method for calling [`v8::FunctionTemplate#GetFunction()`](https://v8docs.nodesource.com/node-8.16/d8/d83/classv8_1_1_function_template.html#a56d904662a86eca78da37d9bb0ed3705) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetFunction(v8::Local t); +``` + + + +### Nan::Set() + +A helper method for calling [`v8::Object#Set()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a67604ea3734f170c66026064ea808f20) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Set(v8::Local obj, + v8::Local key, + v8::Local value) +Nan::Maybe Nan::Set(v8::Local obj, + uint32_t index, + v8::Local value); +``` + + + +### Nan::DefineOwnProperty() + +A helper method for calling [`v8::Object#DefineOwnProperty()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a6f76b2ed605cb8f9185b92de0033a820) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::DefineOwnProperty(v8::Local obj, + v8::Local key, + v8::Local value, + v8::PropertyAttribute attribs = v8::None); +``` + + + +### Nan::ForceSet() + +Deprecated, use Nan::DefineOwnProperty(). + +A helper method for calling [`v8::Object#ForceSet()`](https://v8docs.nodesource.com/node-0.12/db/d85/classv8_1_1_object.html#acfbdfd7427b516ebdb5c47c4df5ed96c) in a way compatible across supported versions of V8. + +Signature: + +```c++ +NAN_DEPRECATED Nan::Maybe Nan::ForceSet(v8::Local obj, + v8::Local key, + v8::Local value, + v8::PropertyAttribute attribs = v8::None); +``` + + + +### Nan::Get() + +A helper method for calling [`v8::Object#Get()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a2565f03e736694f6b1e1cf22a0b4eac2) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::Get(v8::Local obj, + v8::Local key); +Nan::MaybeLocal Nan::Get(v8::Local obj, uint32_t index); +``` + + + +### Nan::GetPropertyAttributes() + +A helper method for calling [`v8::Object#GetPropertyAttributes()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a9b898894da3d1db2714fd9325a54fe57) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetPropertyAttributes( + v8::Local obj, + v8::Local key); +``` + + + +### Nan::Has() + +A helper method for calling [`v8::Object#Has()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ab3c3d89ea7c2f9afd08965bd7299a41d) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Has(v8::Local obj, v8::Local key); +Nan::Maybe Nan::Has(v8::Local obj, uint32_t index); +``` + + + +### Nan::Delete() + +A helper method for calling [`v8::Object#Delete()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a48e4a19b2cedff867eecc73ddb7d377f) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Delete(v8::Local obj, + v8::Local key); +Nan::Maybe Nan::Delete(v8::Local obj, uint32_t index); +``` + + + +### Nan::GetPropertyNames() + +A helper method for calling [`v8::Object#GetPropertyNames()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#aced885270cfd2c956367b5eedc7fbfe8) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetPropertyNames(v8::Local obj); +``` + + + +### Nan::GetOwnPropertyNames() + +A helper method for calling [`v8::Object#GetOwnPropertyNames()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a79a6e4d66049b9aa648ed4dfdb23e6eb) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetOwnPropertyNames(v8::Local obj); +``` + + + +### Nan::SetPrototype() + +A helper method for calling [`v8::Object#SetPrototype()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a442706b22fceda6e6d1f632122a9a9f4) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::SetPrototype(v8::Local obj, + v8::Local prototype); +``` + + + +### Nan::ObjectProtoToString() + +A helper method for calling [`v8::Object#ObjectProtoToString()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ab7a92b4dcf822bef72f6c0ac6fea1f0b) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::ObjectProtoToString(v8::Local obj); +``` + + + +### Nan::HasOwnProperty() + +A helper method for calling [`v8::Object#HasOwnProperty()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ab7b7245442ca6de1e1c145ea3fd653ff) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasOwnProperty(v8::Local obj, + v8::Local key); +``` + + + +### Nan::HasRealNamedProperty() + +A helper method for calling [`v8::Object#HasRealNamedProperty()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ad8b80a59c9eb3c1e6c3cd6c84571f767) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasRealNamedProperty(v8::Local obj, + v8::Local key); +``` + + + +### Nan::HasRealIndexedProperty() + +A helper method for calling [`v8::Object#HasRealIndexedProperty()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#af94fc1135a5e74a2193fb72c3a1b9855) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasRealIndexedProperty(v8::Local obj, + uint32_t index); +``` + + + +### Nan::HasRealNamedCallbackProperty() + +A helper method for calling [`v8::Object#HasRealNamedCallbackProperty()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#af743b7ea132b89f84d34d164d0668811) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasRealNamedCallbackProperty( + v8::Local obj, + v8::Local key); +``` + + + +### Nan::GetRealNamedPropertyInPrototypeChain() + +A helper method for calling [`v8::Object#GetRealNamedPropertyInPrototypeChain()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a8700b1862e6b4783716964ba4d5e6172) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetRealNamedPropertyInPrototypeChain( + v8::Local obj, + v8::Local key); +``` + + + +### Nan::GetRealNamedProperty() + +A helper method for calling [`v8::Object#GetRealNamedProperty()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a84471a824576a5994fdd0ffcbf99ccc0) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetRealNamedProperty(v8::Local obj, + v8::Local key); +``` + + + +### Nan::CallAsFunction() + +A helper method for calling [`v8::Object#CallAsFunction()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ad3ffc36f3dfc3592ce2a96bc047ee2cd) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CallAsFunction(v8::Local obj, + v8::Local recv, + int argc, + v8::Local argv[]); +``` + + + +### Nan::CallAsConstructor() + +A helper method for calling [`v8::Object#CallAsConstructor()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a50d571de50d0b0dfb28795619d07a01b) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CallAsConstructor(v8::Local obj, + int argc, + v8::Local argv[]); +``` + + + +### Nan::GetSourceLine() + +A helper method for calling [`v8::Message#GetSourceLine()`](https://v8docs.nodesource.com/node-8.16/d9/d28/classv8_1_1_message.html#a849f7a6c41549d83d8159825efccd23a) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetSourceLine(v8::Local msg); +``` + + + +### Nan::GetLineNumber() + +A helper method for calling [`v8::Message#GetLineNumber()`](https://v8docs.nodesource.com/node-8.16/d9/d28/classv8_1_1_message.html#adbe46c10a88a6565f2732a2d2adf99b9) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetLineNumber(v8::Local msg); +``` + + + +### Nan::GetStartColumn() + +A helper method for calling [`v8::Message#GetStartColumn()`](https://v8docs.nodesource.com/node-8.16/d9/d28/classv8_1_1_message.html#a60ede616ba3822d712e44c7a74487ba6) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetStartColumn(v8::Local msg); +``` + + + +### Nan::GetEndColumn() + +A helper method for calling [`v8::Message#GetEndColumn()`](https://v8docs.nodesource.com/node-8.16/d9/d28/classv8_1_1_message.html#aaa004cf19e529da980bc19fcb76d93be) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetEndColumn(v8::Local msg); +``` + + + +### Nan::CloneElementAt() + +A helper method for calling [`v8::Array#CloneElementAt()`](https://v8docs.nodesource.com/node-4.8/d3/d32/classv8_1_1_array.html#a1d3a878d4c1c7cae974dd50a1639245e) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CloneElementAt(v8::Local array, uint32_t index); +``` + + +### Nan::HasPrivate() + +A helper method for calling [`v8::Object#HasPrivate()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#af68a0b98066cfdeb8f943e98a40ba08d) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasPrivate(v8::Local object, v8::Local key); +``` + + +### Nan::GetPrivate() + +A helper method for calling [`v8::Object#GetPrivate()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a169f2da506acbec34deadd9149a1925a) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetPrivate(v8::Local object, v8::Local key); +``` + + +### Nan::SetPrivate() + +A helper method for calling [`v8::Object#SetPrivate()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ace1769b0f3b86bfe9fda1010916360ee) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::SetPrivate(v8::Local object, v8::Local key, v8::Local value); +``` + + +### Nan::DeletePrivate() + +A helper method for calling [`v8::Object#DeletePrivate()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a138bb32a304f3982be02ad499693b8fd) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::DeletePrivate(v8::Local object, v8::Local key); +``` + + +### Nan::MakeMaybe() + +Wraps a `v8::Local<>` in a `Nan::MaybeLocal<>`. When called with a `Nan::MaybeLocal<>` it just returns its argument. This is useful in generic template code that builds on NAN. + +Synopsis: + +```c++ + MaybeLocal someNumber = MakeMaybe(New(3.141592654)); + MaybeLocal someString = MakeMaybe(New("probably")); +``` + +Signature: + +```c++ +template class MaybeMaybe> +Nan::MaybeLocal Nan::MakeMaybe(MaybeMaybe v); +``` diff --git a/reverse_engineering/node_modules/nan/doc/methods.md b/reverse_engineering/node_modules/nan/doc/methods.md new file mode 100644 index 0000000..9642d02 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/methods.md @@ -0,0 +1,664 @@ +## JavaScript-accessible methods + +A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information. + +In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type. + +* **Method argument types** + - Nan::FunctionCallbackInfo + - Nan::PropertyCallbackInfo + - Nan::ReturnValue +* **Method declarations** + - Method declaration + - Getter declaration + - Setter declaration + - Property getter declaration + - Property setter declaration + - Property enumerator declaration + - Property deleter declaration + - Property query declaration + - Index getter declaration + - Index setter declaration + - Index enumerator declaration + - Index deleter declaration + - Index query declaration +* Method and template helpers + - Nan::SetMethod() + - Nan::SetPrototypeMethod() + - Nan::SetAccessor() + - Nan::SetNamedPropertyHandler() + - Nan::SetIndexedPropertyHandler() + - Nan::SetTemplate() + - Nan::SetPrototypeTemplate() + - Nan::SetInstanceTemplate() + - Nan::SetCallHandler() + - Nan::SetCallAsFunctionHandler() + + +### Nan::FunctionCallbackInfo + +`Nan::FunctionCallbackInfo` should be used in place of [`v8::FunctionCallbackInfo`](https://v8docs.nodesource.com/node-8.16/dd/d0d/classv8_1_1_function_callback_info.html), even with older versions of Node where `v8::FunctionCallbackInfo` does not exist. + +Definition: + +```c++ +template class FunctionCallbackInfo { + public: + ReturnValue GetReturnValue() const; + v8::Local Callee(); // NOTE: Not available in NodeJS >= 10.0.0 + v8::Local Data(); + v8::Local Holder(); + bool IsConstructCall(); + int Length() const; + v8::Local operator[](int i) const; + v8::Local This() const; + v8::Isolate *GetIsolate() const; +}; +``` + +See the [`v8::FunctionCallbackInfo`](https://v8docs.nodesource.com/node-8.16/dd/d0d/classv8_1_1_function_callback_info.html) documentation for usage details on these. See [`Nan::ReturnValue`](#api_nan_return_value) for further information on how to set a return value from methods. + +**Note:** `FunctionCallbackInfo::Callee` is removed in Node.js after `10.0.0` because it is was deprecated in V8. Consider using `info.Data()` to pass any information you need. + + +### Nan::PropertyCallbackInfo + +`Nan::PropertyCallbackInfo` should be used in place of [`v8::PropertyCallbackInfo`](https://v8docs.nodesource.com/node-8.16/d7/dc5/classv8_1_1_property_callback_info.html), even with older versions of Node where `v8::PropertyCallbackInfo` does not exist. + +Definition: + +```c++ +template class PropertyCallbackInfo : public PropertyCallbackInfoBase { + public: + ReturnValue GetReturnValue() const; + v8::Isolate* GetIsolate() const; + v8::Local Data() const; + v8::Local This() const; + v8::Local Holder() const; +}; +``` + +See the [`v8::PropertyCallbackInfo`](https://v8docs.nodesource.com/node-8.16/d7/dc5/classv8_1_1_property_callback_info.html) documentation for usage details on these. See [`Nan::ReturnValue`](#api_nan_return_value) for further information on how to set a return value from property accessor methods. + + +### Nan::ReturnValue + +`Nan::ReturnValue` is used in place of [`v8::ReturnValue`](https://v8docs.nodesource.com/node-8.16/da/da7/classv8_1_1_return_value.html) on both [`Nan::FunctionCallbackInfo`](#api_nan_function_callback_info) and [`Nan::PropertyCallbackInfo`](#api_nan_property_callback_info) as the return type of `GetReturnValue()`. + +Example usage: + +```c++ +void EmptyArray(const Nan::FunctionCallbackInfo& info) { + info.GetReturnValue().Set(Nan::New()); +} +``` + +Definition: + +```c++ +template class ReturnValue { + public: + // Handle setters + template void Set(const v8::Local &handle); + template void Set(const Nan::Global &handle); + + // Fast primitive setters + void Set(bool value); + void Set(double i); + void Set(int32_t i); + void Set(uint32_t i); + + // Fast JS primitive setters + void SetNull(); + void SetUndefined(); + void SetEmptyString(); + + // Convenience getter for isolate + v8::Isolate *GetIsolate() const; +}; +``` + +See the documentation on [`v8::ReturnValue`](https://v8docs.nodesource.com/node-8.16/da/da7/classv8_1_1_return_value.html) for further information on this. + + +### Method declaration + +JavaScript-accessible methods should be declared with the following signature to form a `Nan::FunctionCallback`: + +```c++ +typedef void(*FunctionCallback)(const FunctionCallbackInfo&); +``` + +Example: + +```c++ +void MethodName(const Nan::FunctionCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a method as one is implicitly created for you. + +**Example usage** + +```c++ +// .h: +class Foo : public Nan::ObjectWrap { + ... + + static void Bar(const Nan::FunctionCallbackInfo& info); + static void Baz(const Nan::FunctionCallbackInfo& info); +} + + +// .cc: +void Foo::Bar(const Nan::FunctionCallbackInfo& info) { + ... +} + +void Foo::Baz(const Nan::FunctionCallbackInfo& info) { + ... +} +``` + +A helper macro `NAN_METHOD(methodname)` exists, compatible with NAN v1 method declarations. + +**Example usage with `NAN_METHOD(methodname)`** + +```c++ +// .h: +class Foo : public Nan::ObjectWrap { + ... + + static NAN_METHOD(Bar); + static NAN_METHOD(Baz); +} + + +// .cc: +NAN_METHOD(Foo::Bar) { + ... +} + +NAN_METHOD(Foo::Baz) { + ... +} +``` + +Use [`Nan::SetPrototypeMethod`](#api_nan_set_prototype_method) to attach a method to a JavaScript function prototype or [`Nan::SetMethod`](#api_nan_set_method) to attach a method directly on a JavaScript object. + + +### Getter declaration + +JavaScript-accessible getters should be declared with the following signature to form a `Nan::GetterCallback`: + +```c++ +typedef void(*GetterCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void GetterName(v8::Local property, + const Nan::PropertyCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a getter as one is implicitly created for you. + +A helper macro `NAN_GETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on [Accessors](https://developers.google.com/v8/embed#accesssors). + + +### Setter declaration + +JavaScript-accessible setters should be declared with the following signature to form a Nan::SetterCallback: + +```c++ +typedef void(*SetterCallback)(v8::Local, + v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void SetterName(v8::Local property, + v8::Local value, + const Nan::PropertyCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a setter as one is implicitly created for you. + +A helper macro `NAN_SETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on [Accessors](https://developers.google.com/v8/embed#accesssors). + + +### Property getter declaration + +JavaScript-accessible property getters should be declared with the following signature to form a Nan::PropertyGetterCallback: + +```c++ +typedef void(*PropertyGetterCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyGetterName(v8::Local property, + const Nan::PropertyCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a property getter as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_GETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property setter declaration + +JavaScript-accessible property setters should be declared with the following signature to form a Nan::PropertySetterCallback: + +```c++ +typedef void(*PropertySetterCallback)(v8::Local, + v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertySetterName(v8::Local property, + v8::Local value, + const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property setter as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_SETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property enumerator declaration + +JavaScript-accessible property enumerators should be declared with the following signature to form a Nan::PropertyEnumeratorCallback: + +```c++ +typedef void(*PropertyEnumeratorCallback)(const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyEnumeratorName(const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property enumerator as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_ENUMERATOR(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property deleter declaration + +JavaScript-accessible property deleters should be declared with the following signature to form a Nan::PropertyDeleterCallback: + +```c++ +typedef void(*PropertyDeleterCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyDeleterName(v8::Local property, + const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property deleter as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_DELETER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property query declaration + +JavaScript-accessible property query methods should be declared with the following signature to form a Nan::PropertyQueryCallback: + +```c++ +typedef void(*PropertyQueryCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyQueryName(v8::Local property, + const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property query method as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_QUERY(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index getter declaration + +JavaScript-accessible index getter methods should be declared with the following signature to form a Nan::IndexGetterCallback: + +```c++ +typedef void(*IndexGetterCallback)(uint32_t, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexGetterName(uint32_t index, const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index getter as one is implicitly created for you. + +A helper macro `NAN_INDEX_GETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index setter declaration + +JavaScript-accessible index setter methods should be declared with the following signature to form a Nan::IndexSetterCallback: + +```c++ +typedef void(*IndexSetterCallback)(uint32_t, + v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexSetterName(uint32_t index, + v8::Local value, + const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index setter as one is implicitly created for you. + +A helper macro `NAN_INDEX_SETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index enumerator declaration + +JavaScript-accessible index enumerator methods should be declared with the following signature to form a Nan::IndexEnumeratorCallback: + +```c++ +typedef void(*IndexEnumeratorCallback)(const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexEnumeratorName(const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index enumerator as one is implicitly created for you. + +A helper macro `NAN_INDEX_ENUMERATOR(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index deleter declaration + +JavaScript-accessible index deleter methods should be declared with the following signature to form a Nan::IndexDeleterCallback: + +```c++ +typedef void(*IndexDeleterCallback)(uint32_t, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexDeleterName(uint32_t index, const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index deleter as one is implicitly created for you. + +A helper macro `NAN_INDEX_DELETER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index query declaration + +JavaScript-accessible index query methods should be declared with the following signature to form a Nan::IndexQueryCallback: + +```c++ +typedef void(*IndexQueryCallback)(uint32_t, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexQueryName(uint32_t index, const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index query method as one is implicitly created for you. + +A helper macro `NAN_INDEX_QUERY(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Nan::SetMethod() + +Sets a method with a given name directly on a JavaScript object where the method has the `Nan::FunctionCallback` signature (see Method declaration). + +Signature: + +```c++ +void Nan::SetMethod(v8::Local recv, + const char *name, + Nan::FunctionCallback callback, + v8::Local data = v8::Local()) +void Nan::SetMethod(v8::Local templ, + const char *name, + Nan::FunctionCallback callback, + v8::Local data = v8::Local()) +``` + + +### Nan::SetPrototypeMethod() + +Sets a method with a given name on a `FunctionTemplate`'s prototype where the method has the `Nan::FunctionCallback` signature (see Method declaration). + +Signature: + +```c++ +void Nan::SetPrototypeMethod(v8::Local recv, + const char* name, + Nan::FunctionCallback callback, + v8::Local data = v8::Local()) +``` + + +### Nan::SetAccessor() + +Sets getters and setters for a property with a given name on an `ObjectTemplate` or a plain `Object`. Accepts getters with the `Nan::GetterCallback` signature (see Getter declaration) and setters with the `Nan::SetterCallback` signature (see Setter declaration). + +Signature: + +```c++ +void SetAccessor(v8::Local tpl, + v8::Local name, + Nan::GetterCallback getter, + Nan::SetterCallback setter = 0, + v8::Local data = v8::Local(), + v8::AccessControl settings = v8::DEFAULT, + v8::PropertyAttribute attribute = v8::None, + imp::Sig signature = imp::Sig()); +bool SetAccessor(v8::Local obj, + v8::Local name, + Nan::GetterCallback getter, + Nan::SetterCallback setter = 0, + v8::Local data = v8::Local(), + v8::AccessControl settings = v8::DEFAULT, + v8::PropertyAttribute attribute = v8::None) +``` + +See the V8 [`ObjectTemplate#SetAccessor()`](https://v8docs.nodesource.com/node-8.16/db/d5f/classv8_1_1_object_template.html#aca0ed196f8a9adb1f68b1aadb6c9cd77) and [`Object#SetAccessor()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ae91b3b56b357f285288c89fbddc46d1b) for further information about how to use `Nan::SetAccessor()`. + + +### Nan::SetNamedPropertyHandler() + +Sets named property getters, setters, query, deleter and enumerator methods on an `ObjectTemplate`. Accepts: + +* Property getters with the `Nan::PropertyGetterCallback` signature (see Property getter declaration) +* Property setters with the `Nan::PropertySetterCallback` signature (see Property setter declaration) +* Property query methods with the `Nan::PropertyQueryCallback` signature (see Property query declaration) +* Property deleters with the `Nan::PropertyDeleterCallback` signature (see Property deleter declaration) +* Property enumerators with the `Nan::PropertyEnumeratorCallback` signature (see Property enumerator declaration) + +Signature: + +```c++ +void SetNamedPropertyHandler(v8::Local tpl, + Nan::PropertyGetterCallback getter, + Nan::PropertySetterCallback setter = 0, + Nan::PropertyQueryCallback query = 0, + Nan::PropertyDeleterCallback deleter = 0, + Nan::PropertyEnumeratorCallback enumerator = 0, + v8::Local data = v8::Local()) +``` + +See the V8 [`ObjectTemplate#SetNamedPropertyHandler()`](https://v8docs.nodesource.com/node-8.16/db/d5f/classv8_1_1_object_template.html#a33b3ebd7de641f6cc6414b7de01fc1c7) for further information about how to use `Nan::SetNamedPropertyHandler()`. + + +### Nan::SetIndexedPropertyHandler() + +Sets indexed property getters, setters, query, deleter and enumerator methods on an `ObjectTemplate`. Accepts: + +* Indexed property getters with the `Nan::IndexGetterCallback` signature (see Index getter declaration) +* Indexed property setters with the `Nan::IndexSetterCallback` signature (see Index setter declaration) +* Indexed property query methods with the `Nan::IndexQueryCallback` signature (see Index query declaration) +* Indexed property deleters with the `Nan::IndexDeleterCallback` signature (see Index deleter declaration) +* Indexed property enumerators with the `Nan::IndexEnumeratorCallback` signature (see Index enumerator declaration) + +Signature: + +```c++ +void SetIndexedPropertyHandler(v8::Local tpl, + Nan::IndexGetterCallback getter, + Nan::IndexSetterCallback setter = 0, + Nan::IndexQueryCallback query = 0, + Nan::IndexDeleterCallback deleter = 0, + Nan::IndexEnumeratorCallback enumerator = 0, + v8::Local data = v8::Local()) +``` + +See the V8 [`ObjectTemplate#SetIndexedPropertyHandler()`](https://v8docs.nodesource.com/node-8.16/db/d5f/classv8_1_1_object_template.html#ac89f06d634add0e890452033f7d17ff1) for further information about how to use `Nan::SetIndexedPropertyHandler()`. + + +### Nan::SetTemplate() + +Adds properties on an `Object`'s or `Function`'s template. + +Signature: + +```c++ +void Nan::SetTemplate(v8::Local templ, + const char *name, + v8::Local value); +void Nan::SetTemplate(v8::Local templ, + v8::Local name, + v8::Local value, + v8::PropertyAttribute attributes) +``` + +Calls the `Template`'s [`Set()`](https://v8docs.nodesource.com/node-8.16/db/df7/classv8_1_1_template.html#ae3fbaff137557aa6a0233bc7e52214ac). + + +### Nan::SetPrototypeTemplate() + +Adds properties on an `Object`'s or `Function`'s prototype template. + +Signature: + +```c++ +void Nan::SetPrototypeTemplate(v8::Local templ, + const char *name, + v8::Local value); +void Nan::SetPrototypeTemplate(v8::Local templ, + v8::Local name, + v8::Local value, + v8::PropertyAttribute attributes) +``` + +Calls the `FunctionTemplate`'s _PrototypeTemplate's_ [`Set()`](https://v8docs.nodesource.com/node-8.16/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf). + + +### Nan::SetInstanceTemplate() + +Use to add instance properties on `FunctionTemplate`'s. + +Signature: + +```c++ +void Nan::SetInstanceTemplate(v8::Local templ, + const char *name, + v8::Local value); +void Nan::SetInstanceTemplate(v8::Local templ, + v8::Local name, + v8::Local value, + v8::PropertyAttribute attributes) +``` + +Calls the `FunctionTemplate`'s _InstanceTemplate's_ [`Set()`](https://v8docs.nodesource.com/node-8.16/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf). + + +### Nan::SetCallHandler() + +Set the call-handler callback for a `v8::FunctionTemplate`. +This callback is called whenever the function created from this FunctionTemplate is called. + +Signature: + +```c++ +void Nan::SetCallHandler(v8::Local templ, Nan::FunctionCallback callback, v8::Local data = v8::Local()) +``` + +Calls the `FunctionTemplate`'s [`SetCallHandler()`](https://v8docs.nodesource.com/node-8.16/d8/d83/classv8_1_1_function_template.html#ab7574b298db3c27fbc2ed465c08ea2f8). + + +### Nan::SetCallAsFunctionHandler() + +Sets the callback to be used when calling instances created from the `v8::ObjectTemplate` as a function. +If no callback is set, instances behave like normal JavaScript objects that cannot be called as a function. + +Signature: + +```c++ +void Nan::SetCallAsFunctionHandler(v8::Local templ, Nan::FunctionCallback callback, v8::Local data = v8::Local()) +``` + +Calls the `ObjectTemplate`'s [`SetCallAsFunctionHandler()`](https://v8docs.nodesource.com/node-8.16/db/d5f/classv8_1_1_object_template.html#a5e9612fc80bf6db8f2da199b9b0bd04e). + diff --git a/reverse_engineering/node_modules/nan/doc/new.md b/reverse_engineering/node_modules/nan/doc/new.md new file mode 100644 index 0000000..0f28a0e --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/new.md @@ -0,0 +1,147 @@ +## New + +NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8. + + - Nan::New() + - Nan::Undefined() + - Nan::Null() + - Nan::True() + - Nan::False() + - Nan::EmptyString() + + + +### Nan::New() + +`Nan::New()` should be used to instantiate new JavaScript objects. + +Refer to the specific V8 type in the [V8 documentation](https://v8docs.nodesource.com/node-8.16/d1/d83/classv8_1_1_data.html) for information on the types of arguments required for instantiation. + +Signatures: + +Return types are mostly omitted from the signatures for simplicity. In most cases the type will be contained within a `v8::Local`. The following types will be contained within a `Nan::MaybeLocal`: `v8::String`, `v8::Date`, `v8::RegExp`, `v8::Script`, `v8::UnboundScript`. + +Empty objects: + +```c++ +Nan::New(); +``` + +Generic single and multiple-argument: + +```c++ +Nan::New(A0 arg0); +Nan::New(A0 arg0, A1 arg1); +Nan::New(A0 arg0, A1 arg1, A2 arg2); +Nan::New(A0 arg0, A1 arg1, A2 arg2, A3 arg3); +``` + +For creating `v8::FunctionTemplate` and `v8::Function` objects: + +_The definition of `Nan::FunctionCallback` can be found in the [Method declaration](./methods.md#api_nan_method) documentation._ + +```c++ +Nan::New(Nan::FunctionCallback callback, + v8::Local data = v8::Local()); +Nan::New(Nan::FunctionCallback callback, + v8::Local data = v8::Local(), + A2 a2 = A2()); +``` + +Native number types: + +```c++ +v8::Local Nan::New(bool value); +v8::Local Nan::New(int32_t value); +v8::Local Nan::New(uint32_t value); +v8::Local Nan::New(double value); +``` + +String types: + +```c++ +Nan::MaybeLocal Nan::New(std::string const& value); +Nan::MaybeLocal Nan::New(const char * value, int length); +Nan::MaybeLocal Nan::New(const char * value); +Nan::MaybeLocal Nan::New(const uint16_t * value); +Nan::MaybeLocal Nan::New(const uint16_t * value, int length); +``` + +Specialized types: + +```c++ +v8::Local Nan::New(v8::String::ExternalStringResource * value); +v8::Local Nan::New(Nan::ExternalOneByteStringResource * value); +v8::Local Nan::New(v8::Local pattern, v8::RegExp::Flags flags); +``` + +Note that `Nan::ExternalOneByteStringResource` maps to [`v8::String::ExternalOneByteStringResource`](https://v8docs.nodesource.com/node-8.16/d9/db3/classv8_1_1_string_1_1_external_one_byte_string_resource.html), and `v8::String::ExternalAsciiStringResource` in older versions of V8. + + + +### Nan::Undefined() + +A helper method to reference the `v8::Undefined` object in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::Undefined() +``` + + +### Nan::Null() + +A helper method to reference the `v8::Null` object in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::Null() +``` + + +### Nan::True() + +A helper method to reference the `v8::Boolean` object representing the `true` value in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::True() +``` + + +### Nan::False() + +A helper method to reference the `v8::Boolean` object representing the `false` value in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::False() +``` + + +### Nan::EmptyString() + +Call [`v8::String::Empty`](https://v8docs.nodesource.com/node-8.16/d2/db3/classv8_1_1_string.html#a7c1bc8886115d7ee46f1d571dd6ebc6d) to reference the empty string in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::EmptyString() +``` + + + +### Nan::NewOneByteString() + +An implementation of [`v8::String::NewFromOneByte()`](https://v8docs.nodesource.com/node-8.16/d2/db3/classv8_1_1_string.html#a5264d50b96d2c896ce525a734dc10f09) provided for consistent availability and API across supported versions of V8. Allocates a new string from Latin-1 data. + +Signature: + +```c++ +Nan::MaybeLocal Nan::NewOneByteString(const uint8_t * value, + int length = -1) +``` diff --git a/reverse_engineering/node_modules/nan/doc/node_misc.md b/reverse_engineering/node_modules/nan/doc/node_misc.md new file mode 100644 index 0000000..17578e3 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/node_misc.md @@ -0,0 +1,123 @@ +## Miscellaneous Node Helpers + + - Nan::AsyncResource + - Nan::MakeCallback() + - NAN_MODULE_INIT() + - Nan::Export() + + +### Nan::AsyncResource + +This class is analogous to the `AsyncResource` JavaScript class exposed by Node's [async_hooks][] API. + +When calling back into JavaScript asynchronously, special care must be taken to ensure that the runtime can properly track +async hops. `Nan::AsyncResource` is a class that provides an RAII wrapper around `node::EmitAsyncInit`, `node::EmitAsyncDestroy`, +and `node::MakeCallback`. Using this mechanism to call back into JavaScript, as opposed to `Nan::MakeCallback` or +`v8::Function::Call` ensures that the callback is executed in the correct async context. This ensures that async mechanisms +such as domains and [async_hooks][] function correctly. + +Definition: + +```c++ +class AsyncResource { + public: + AsyncResource(v8::Local name, + v8::Local resource = New()); + AsyncResource(const char* name, + v8::Local resource = New()); + ~AsyncResource(); + + v8::MaybeLocal runInAsyncScope(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); + v8::MaybeLocal runInAsyncScope(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); + v8::MaybeLocal runInAsyncScope(v8::Local target, + const char* method, + int argc, + v8::Local* argv); +}; +``` + +* `name`: Identifier for the kind of resource that is being provided for diagnostics information exposed by the [async_hooks][] + API. This will be passed to the possible `init` hook as the `type`. To avoid name collisions with other modules we recommend + that the name include the name of the owning module as a prefix. For example `mysql` module could use something like + `mysql:batch-db-query-resource`. +* `resource`: An optional object associated with the async work that will be passed to the possible [async_hooks][] + `init` hook. If this parameter is omitted, or an empty handle is provided, this object will be created automatically. +* When calling JS on behalf of this resource, one can use `runInAsyncScope`. This will ensure that the callback runs in the + correct async execution context. +* `AsyncDestroy` is automatically called when an AsyncResource object is destroyed. + +For more details, see the Node [async_hooks][] documentation. You might also want to take a look at the documentation for the +[N-API counterpart][napi]. For example usage, see the `asyncresource.cpp` example in the `test/cpp` directory. + + +### Nan::MakeCallback() + +Deprecated wrappers around the legacy `node::MakeCallback()` APIs. Node.js 10+ +has deprecated these legacy APIs as they do not provide a mechanism to preserve +async context. + +We recommend that you use the `AsyncResource` class and `AsyncResource::runInAsyncScope` instead of using `Nan::MakeCallback` or +`v8::Function#Call()` directly. `AsyncResource` properly takes care of running the callback in the correct async execution +context – something that is essential for functionality like domains, async_hooks and async debugging. + +Signatures: + +```c++ +NAN_DEPRECATED +v8::Local Nan::MakeCallback(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); +NAN_DEPRECATED +v8::Local Nan::MakeCallback(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); +NAN_DEPRECATED +v8::Local Nan::MakeCallback(v8::Local target, + const char* method, + int argc, + v8::Local* argv); +``` + + + +### NAN_MODULE_INIT() + +Used to define the entry point function to a Node add-on. Creates a function with a given `name` that receives a `target` object representing the equivalent of the JavaScript `exports` object. + +See example below. + + +### Nan::Export() + +A simple helper to register a `v8::FunctionTemplate` from a JavaScript-accessible method (see [Methods](./methods.md)) as a property on an object. Can be used in a way similar to assigning properties to `module.exports` in JavaScript. + +Signature: + +```c++ +void Export(v8::Local target, const char *name, Nan::FunctionCallback f) +``` + +Also available as the shortcut `NAN_EXPORT` macro. + +Example: + +```c++ +NAN_METHOD(Foo) { + ... +} + +NAN_MODULE_INIT(Init) { + NAN_EXPORT(target, Foo); +} +``` + +[async_hooks]: https://nodejs.org/dist/latest-v9.x/docs/api/async_hooks.html +[napi]: https://nodejs.org/dist/latest-v9.x/docs/api/n-api.html#n_api_custom_asynchronous_operations diff --git a/reverse_engineering/node_modules/nan/doc/object_wrappers.md b/reverse_engineering/node_modules/nan/doc/object_wrappers.md new file mode 100644 index 0000000..07d8c05 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/object_wrappers.md @@ -0,0 +1,263 @@ +## Object Wrappers + +The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects. + + - Nan::ObjectWrap + + + +### Nan::ObjectWrap() + +A reimplementation of `node::ObjectWrap` that adds some API not present in older versions of Node. Should be preferred over `node::ObjectWrap` in all cases for consistency. + +Definition: + +```c++ +class ObjectWrap { + public: + ObjectWrap(); + + virtual ~ObjectWrap(); + + template + static inline T* Unwrap(v8::Local handle); + + inline v8::Local handle(); + + inline Nan::Persistent& persistent(); + + protected: + inline void Wrap(v8::Local handle); + + inline void MakeWeak(); + + /* Ref() marks the object as being attached to an event loop. + * Refed objects will not be garbage collected, even if + * all references are lost. + */ + virtual void Ref(); + + /* Unref() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" means an object that only has a + * persistent handle.) + * + * DO NOT CALL THIS FROM DESTRUCTOR + */ + virtual void Unref(); + + int refs_; // ro +}; +``` + +See the Node documentation on [Wrapping C++ Objects](https://nodejs.org/api/addons.html#addons_wrapping_c_objects) for more details. + +### This vs. Holder + +When calling `Unwrap`, it is important that the argument is indeed some JavaScript object which got wrapped by a `Wrap` call for this class or any derived class. +The `Signature` installed by [`Nan::SetPrototypeMethod()`](methods.md#api_nan_set_prototype_method) does ensure that `info.Holder()` is just such an instance. +In Node 0.12 and later, `info.This()` will also be of such a type, since otherwise the invocation will get rejected. +However, in Node 0.10 and before it was possible to invoke a method on a JavaScript object which just had the extension type in its prototype chain. +In such a situation, calling `Unwrap` on `info.This()` will likely lead to a failed assertion causing a crash, but could lead to even more serious corruption. + +On the other hand, calling `Unwrap` in an [accessor](methods.md#api_nan_set_accessor) should not use `Holder()` if the accessor is defined on the prototype. +So either define your accessors on the instance template, +or use `This()` after verifying that it is indeed a valid object. + +### Examples + +#### Basic + +```c++ +class MyObject : public Nan::ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + v8::Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("MyObject").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Nan::SetPrototypeMethod(tpl, "getHandle", GetHandle); + Nan::SetPrototypeMethod(tpl, "getValue", GetValue); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + Nan::Set(target, Nan::New("MyObject").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit MyObject(double value = 0) : value_(value) {} + ~MyObject() {} + + static NAN_METHOD(New) { + if (info.IsConstructCall()) { + double value = info[0]->IsUndefined() ? 0 : Nan::To(info[0]).FromJust(); + MyObject *obj = new MyObject(value); + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } else { + const int argc = 1; + v8::Local argv[argc] = {info[0]}; + v8::Local cons = Nan::New(constructor()); + info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked()); + } + } + + static NAN_METHOD(GetHandle) { + MyObject* obj = Nan::ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(obj->handle()); + } + + static NAN_METHOD(GetValue) { + MyObject* obj = Nan::ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(obj->value_); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + double value_; +}; + +NODE_MODULE(objectwrapper, MyObject::Init) +``` + +To use in Javascript: + +```Javascript +var objectwrapper = require('bindings')('objectwrapper'); + +var obj = new objectwrapper.MyObject(5); +console.log('Should be 5: ' + obj.getValue()); +``` + +#### Factory of wrapped objects + +```c++ +class MyFactoryObject : public Nan::ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + v8::Local tpl = Nan::New(New); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Nan::SetPrototypeMethod(tpl, "getValue", GetValue); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + } + + static NAN_METHOD(NewInstance) { + v8::Local cons = Nan::New(constructor()); + double value = info[0]->IsNumber() ? Nan::To(info[0]).FromJust() : 0; + const int argc = 1; + v8::Local argv[1] = {Nan::New(value)}; + info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked()); + } + + // Needed for the next example: + inline double value() const { + return value_; + } + + private: + explicit MyFactoryObject(double value = 0) : value_(value) {} + ~MyFactoryObject() {} + + static NAN_METHOD(New) { + if (info.IsConstructCall()) { + double value = info[0]->IsNumber() ? Nan::To(info[0]).FromJust() : 0; + MyFactoryObject * obj = new MyFactoryObject(value); + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } else { + const int argc = 1; + v8::Local argv[argc] = {info[0]}; + v8::Local cons = Nan::New(constructor()); + info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked()); + } + } + + static NAN_METHOD(GetValue) { + MyFactoryObject* obj = ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(obj->value_); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + double value_; +}; + +NAN_MODULE_INIT(Init) { + MyFactoryObject::Init(target); + Nan::Set(target, + Nan::New("newFactoryObjectInstance").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MyFactoryObject::NewInstance)).ToLocalChecked() + ); +} + +NODE_MODULE(wrappedobjectfactory, Init) +``` + +To use in Javascript: + +```Javascript +var wrappedobjectfactory = require('bindings')('wrappedobjectfactory'); + +var obj = wrappedobjectfactory.newFactoryObjectInstance(10); +console.log('Should be 10: ' + obj.getValue()); +``` + +#### Passing wrapped objects around + +Use the `MyFactoryObject` class above along with the following: + +```c++ +static NAN_METHOD(Sum) { + Nan::MaybeLocal maybe1 = Nan::To(info[0]); + Nan::MaybeLocal maybe2 = Nan::To(info[1]); + + // Quick check: + if (maybe1.IsEmpty() || maybe2.IsEmpty()) { + // return value is undefined by default + return; + } + + MyFactoryObject* obj1 = + Nan::ObjectWrap::Unwrap(maybe1.ToLocalChecked()); + MyFactoryObject* obj2 = + Nan::ObjectWrap::Unwrap(maybe2.ToLocalChecked()); + + info.GetReturnValue().Set(Nan::New(obj1->value() + obj2->value())); +} + +NAN_MODULE_INIT(Init) { + MyFactoryObject::Init(target); + Nan::Set(target, + Nan::New("newFactoryObjectInstance").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MyFactoryObject::NewInstance)).ToLocalChecked() + ); + Nan::Set(target, + Nan::New("sum").ToLocalChecked(), + Nan::GetFunction(Nan::New(Sum)).ToLocalChecked() + ); +} + +NODE_MODULE(myaddon, Init) +``` + +To use in Javascript: + +```Javascript +var myaddon = require('bindings')('myaddon'); + +var obj1 = myaddon.newFactoryObjectInstance(5); +var obj2 = myaddon.newFactoryObjectInstance(10); +console.log('sum of object values: ' + myaddon.sum(obj1, obj2)); +``` diff --git a/reverse_engineering/node_modules/nan/doc/persistent.md b/reverse_engineering/node_modules/nan/doc/persistent.md new file mode 100644 index 0000000..2e13f6b --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/persistent.md @@ -0,0 +1,296 @@ +## Persistent references + +An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed. + +Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported. + + - Nan::PersistentBase & v8::PersistentBase + - Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + - Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + - Nan::Persistent + - Nan::Global + - Nan::WeakCallbackInfo + - Nan::WeakCallbackType + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles). + + +### Nan::PersistentBase & v8::PersistentBase + +A persistent handle contains a reference to a storage cell in V8 which holds an object value and which is updated by the garbage collector whenever the object is moved. A new storage cell can be created using the constructor or `Nan::PersistentBase::Reset()`. Existing handles can be disposed using an argument-less `Nan::PersistentBase::Reset()`. + +Definition: + +_(note: this is implemented as `Nan::PersistentBase` for older versions of V8 and the native `v8::PersistentBase` is used for newer versions of V8)_ + +```c++ +template class PersistentBase { + public: + /** + * If non-empty, destroy the underlying storage cell + */ + void Reset(); + + /** + * If non-empty, destroy the underlying storage cell and create a new one with + * the contents of another if it is also non-empty + */ + template void Reset(const v8::Local &other); + + /** + * If non-empty, destroy the underlying storage cell and create a new one with + * the contents of another if it is also non-empty + */ + template void Reset(const PersistentBase &other); + + /** Returns true if the handle is empty. */ + bool IsEmpty() const; + + /** + * If non-empty, destroy the underlying storage cell + * IsEmpty() will return true after this call. + */ + void Empty(); + + template bool operator==(const PersistentBase &that); + + template bool operator==(const v8::Local &that); + + template bool operator!=(const PersistentBase &that); + + template bool operator!=(const v8::Local &that); + + /** + * Install a finalization callback on this object. + * NOTE: There is no guarantee as to *when* or even *if* the callback is + * invoked. The invocation is performed solely on a best effort basis. + * As always, GC-based finalization should *not* be relied upon for any + * critical form of resource management! At the moment you can either + * specify a parameter for the callback or the location of two internal + * fields in the dying object. + */ + template + void SetWeak(P *parameter, + typename WeakCallbackInfo

::Callback callback, + WeakCallbackType type); + + void ClearWeak(); + + /** + * Marks the reference to this object independent. Garbage collector is free + * to ignore any object groups containing this object. Weak callback for an + * independent handle should not assume that it will be preceded by a global + * GC prologue callback or followed by a global GC epilogue callback. + */ + void MarkIndependent() const; + + bool IsIndependent() const; + + /** Checks if the handle holds the only reference to an object. */ + bool IsNearDeath() const; + + /** Returns true if the handle's reference is weak. */ + bool IsWeak() const +}; +``` + +See the V8 documentation for [`PersistentBase`](https://v8docs.nodesource.com/node-8.16/d4/dca/classv8_1_1_persistent_base.html) for further information. + +**Tip:** To get a `v8::Local` reference to the original object back from a `PersistentBase` or `Persistent` object: + +```c++ +v8::Local object = Nan::New(persistent); +``` + + +### Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + +Default traits for `Nan::Persistent`. This class does not allow use of the a copy constructor or assignment operator. At present `kResetInDestructor` is not set, but that will change in a future version. + +Definition: + +_(note: this is implemented as `Nan::NonCopyablePersistentTraits` for older versions of V8 and the native `v8::NonCopyablePersistentTraits` is used for newer versions of V8)_ + +```c++ +template class NonCopyablePersistentTraits { + public: + typedef Persistent > NonCopyablePersistent; + + static const bool kResetInDestructor = false; + + template + static void Copy(const Persistent &source, + NonCopyablePersistent *dest); + + template static void Uncompilable(); +}; +``` + +See the V8 documentation for [`NonCopyablePersistentTraits`](https://v8docs.nodesource.com/node-8.16/de/d73/classv8_1_1_non_copyable_persistent_traits.html) for further information. + + +### Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + +A helper class of traits to allow copying and assignment of `Persistent`. This will clone the contents of storage cell, but not any of the flags, etc.. + +Definition: + +_(note: this is implemented as `Nan::CopyablePersistentTraits` for older versions of V8 and the native `v8::NonCopyablePersistentTraits` is used for newer versions of V8)_ + +```c++ +template +class CopyablePersistentTraits { + public: + typedef Persistent > CopyablePersistent; + + static const bool kResetInDestructor = true; + + template + static void Copy(const Persistent &source, + CopyablePersistent *dest); +}; +``` + +See the V8 documentation for [`CopyablePersistentTraits`](https://v8docs.nodesource.com/node-8.16/da/d5c/structv8_1_1_copyable_persistent_traits.html) for further information. + + +### Nan::Persistent + +A type of `PersistentBase` which allows copy and assignment. Copy, assignment and destructor behavior is controlled by the traits class `M`. + +Definition: + +```c++ +template > +class Persistent; + +template class Persistent : public PersistentBase { + public: + /** + * A Persistent with no storage cell. + */ + Persistent(); + + /** + * Construct a Persistent from a v8::Local. When the v8::Local is non-empty, a + * new storage cell is created pointing to the same object, and no flags are + * set. + */ + template Persistent(v8::Local that); + + /** + * Construct a Persistent from a Persistent. When the Persistent is non-empty, + * a new storage cell is created pointing to the same object, and no flags are + * set. + */ + Persistent(const Persistent &that); + + /** + * The copy constructors and assignment operator create a Persistent exactly + * as the Persistent constructor, but the Copy function from the traits class + * is called, allowing the setting of flags based on the copied Persistent. + */ + Persistent &operator=(const Persistent &that); + + template + Persistent &operator=(const Persistent &that); + + /** + * The destructor will dispose the Persistent based on the kResetInDestructor + * flags in the traits class. Since not calling dispose can result in a + * memory leak, it is recommended to always set this flag. + */ + ~Persistent(); +}; +``` + +See the V8 documentation for [`Persistent`](https://v8docs.nodesource.com/node-8.16/d2/d78/classv8_1_1_persistent.html) for further information. + + +### Nan::Global + +A type of `PersistentBase` which has move semantics. + +```c++ +template class Global : public PersistentBase { + public: + /** + * A Global with no storage cell. + */ + Global(); + + /** + * Construct a Global from a v8::Local. When the v8::Local is non-empty, a new + * storage cell is created pointing to the same object, and no flags are set. + */ + template Global(v8::Local that); + /** + * Construct a Global from a PersistentBase. When the Persistent is non-empty, + * a new storage cell is created pointing to the same object, and no flags are + * set. + */ + template Global(const PersistentBase &that); + + /** + * Pass allows returning globals from functions, etc. + */ + Global Pass(); +}; +``` + +See the V8 documentation for [`Global`](https://v8docs.nodesource.com/node-8.16/d5/d40/classv8_1_1_global.html) for further information. + + +### Nan::WeakCallbackInfo + +`Nan::WeakCallbackInfo` is used as an argument when setting a persistent reference as weak. You may need to free any external resources attached to the object. It is a mirror of `v8:WeakCallbackInfo` as found in newer versions of V8. + +Definition: + +```c++ +template class WeakCallbackInfo { + public: + typedef void (*Callback)(const WeakCallbackInfo& data); + + v8::Isolate *GetIsolate() const; + + /** + * Get the parameter that was associated with the weak handle. + */ + T *GetParameter() const; + + /** + * Get pointer from internal field, index can be 0 or 1. + */ + void *GetInternalField(int index) const; +}; +``` + +Example usage: + +```c++ +void weakCallback(const WeakCallbackInfo &data) { + int *parameter = data.GetParameter(); + delete parameter; +} + +Persistent obj; +int *data = new int(0); +obj.SetWeak(data, callback, WeakCallbackType::kParameter); +``` + +See the V8 documentation for [`WeakCallbackInfo`](https://v8docs.nodesource.com/node-8.16/d8/d06/classv8_1_1_weak_callback_info.html) for further information. + + +### Nan::WeakCallbackType + +Represents the type of a weak callback. +A weak callback of type `kParameter` makes the supplied parameter to `Nan::PersistentBase::SetWeak` available through `WeakCallbackInfo::GetParameter`. +A weak callback of type `kInternalFields` uses up to two internal fields at indices 0 and 1 on the `Nan::PersistentBase` being made weak. +Note that only `v8::Object`s and derivatives can have internal fields. + +Definition: + +```c++ +enum class WeakCallbackType { kParameter, kInternalFields }; +``` diff --git a/reverse_engineering/node_modules/nan/doc/scopes.md b/reverse_engineering/node_modules/nan/doc/scopes.md new file mode 100644 index 0000000..84000ee --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/scopes.md @@ -0,0 +1,73 @@ +## Scopes + +A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works. + +A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope. + +The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these. + + - Nan::HandleScope + - Nan::EscapableHandleScope + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection). + + +### Nan::HandleScope + +A simple wrapper around [`v8::HandleScope`](https://v8docs.nodesource.com/node-8.16/d3/d95/classv8_1_1_handle_scope.html). + +Definition: + +```c++ +class Nan::HandleScope { + public: + Nan::HandleScope(); + static int NumberOfHandles(); +}; +``` + +Allocate a new `Nan::HandleScope` whenever you are creating new V8 JavaScript objects. Note that an implicit `HandleScope` is created for you on JavaScript-accessible methods so you do not need to insert one yourself. + +Example: + +```c++ +// new object is created, it needs a new scope: +void Pointless() { + Nan::HandleScope scope; + v8::Local obj = Nan::New(); +} + +// JavaScript-accessible method already has a HandleScope +NAN_METHOD(Pointless2) { + v8::Local obj = Nan::New(); +} +``` + + +### Nan::EscapableHandleScope + +Similar to [`Nan::HandleScope`](#api_nan_handle_scope) but should be used in cases where a function needs to return a V8 JavaScript type that has been created within it. + +Definition: + +```c++ +class Nan::EscapableHandleScope { + public: + Nan::EscapableHandleScope(); + static int NumberOfHandles(); + template v8::Local Escape(v8::Local value); +} +``` + +Use `Escape(value)` to return the object. + +Example: + +```c++ +v8::Local EmptyObj() { + Nan::EscapableHandleScope scope; + v8::Local obj = Nan::New(); + return scope.Escape(obj); +} +``` + diff --git a/reverse_engineering/node_modules/nan/doc/script.md b/reverse_engineering/node_modules/nan/doc/script.md new file mode 100644 index 0000000..301c1b3 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/script.md @@ -0,0 +1,58 @@ +## Script + +NAN provides `v8::Script` helpers as the API has changed over the supported versions of V8. + + - Nan::CompileScript() + - Nan::RunScript() + - Nan::ScriptOrigin + + + +### Nan::CompileScript() + +A wrapper around [`v8::ScriptCompiler::Compile()`](https://v8docs.nodesource.com/node-8.16/da/da5/classv8_1_1_script_compiler.html#a93f5072a0db55d881b969e9fc98e564b). + +Note that `Nan::BoundScript` is an alias for `v8::Script`. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CompileScript( + v8::Local s, + const v8::ScriptOrigin& origin); +Nan::MaybeLocal Nan::CompileScript(v8::Local s); +``` + + + +### Nan::RunScript() + +Calls `script->Run()` or `script->BindToCurrentContext()->Run(Nan::GetCurrentContext())`. + +Note that `Nan::BoundScript` is an alias for `v8::Script` and `Nan::UnboundScript` is an alias for `v8::UnboundScript` where available and `v8::Script` on older versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::RunScript(v8::Local script) +Nan::MaybeLocal Nan::RunScript(v8::Local script) +``` + + +### Nan::ScriptOrigin + +A class transparently extending [`v8::ScriptOrigin`](https://v8docs.nodesource.com/node-16.0/db/d84/classv8_1_1_script_origin.html#pub-methods) +to provide backwards compatibility. Only the listed methods are guaranteed to +be available on all versions of Node. + +Declaration: + +```c++ +class Nan::ScriptOrigin : public v8::ScriptOrigin { + public: + ScriptOrigin(v8::Local name, v8::Local line = v8::Local(), v8::Local column = v8::Local()) + v8::Local ResourceName() const; + v8::Local ResourceLineOffset() const; + v8::Local ResourceColumnOffset() const; +} +``` diff --git a/reverse_engineering/node_modules/nan/doc/string_bytes.md b/reverse_engineering/node_modules/nan/doc/string_bytes.md new file mode 100644 index 0000000..7c1bd32 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/string_bytes.md @@ -0,0 +1,62 @@ +## Strings & Bytes + +Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing. + + - Nan::Encoding + - Nan::Encode() + - Nan::DecodeBytes() + - Nan::DecodeWrite() + + + +### Nan::Encoding + +An enum representing the supported encoding types. A copy of `node::encoding` that is consistent across versions of Node. + +Definition: + +```c++ +enum Nan::Encoding { ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER } +``` + + + +### Nan::Encode() + +A wrapper around `node::Encode()` that provides a consistent implementation across supported versions of Node. + +Signature: + +```c++ +v8::Local Nan::Encode(const void *buf, + size_t len, + enum Nan::Encoding encoding = BINARY); +``` + + + +### Nan::DecodeBytes() + +A wrapper around `node::DecodeBytes()` that provides a consistent implementation across supported versions of Node. + +Signature: + +```c++ +ssize_t Nan::DecodeBytes(v8::Local val, + enum Nan::Encoding encoding = BINARY); +``` + + + +### Nan::DecodeWrite() + +A wrapper around `node::DecodeWrite()` that provides a consistent implementation across supported versions of Node. + +Signature: + +```c++ +ssize_t Nan::DecodeWrite(char *buf, + size_t len, + v8::Local val, + enum Nan::Encoding encoding = BINARY); +``` diff --git a/reverse_engineering/node_modules/nan/doc/v8_internals.md b/reverse_engineering/node_modules/nan/doc/v8_internals.md new file mode 100644 index 0000000..08dd6d0 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/v8_internals.md @@ -0,0 +1,199 @@ +## V8 internals + +The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods. + + - NAN_GC_CALLBACK() + - Nan::AddGCEpilogueCallback() + - Nan::RemoveGCEpilogueCallback() + - Nan::AddGCPrologueCallback() + - Nan::RemoveGCPrologueCallback() + - Nan::GetHeapStatistics() + - Nan::SetCounterFunction() + - Nan::SetCreateHistogramFunction() + - Nan::SetAddHistogramSampleFunction() + - Nan::IdleNotification() + - Nan::LowMemoryNotification() + - Nan::ContextDisposedNotification() + - Nan::GetInternalFieldPointer() + - Nan::SetInternalFieldPointer() + - Nan::AdjustExternalMemory() + + + +### NAN_GC_CALLBACK(callbackname) + +Use `NAN_GC_CALLBACK` to declare your callbacks for `Nan::AddGCPrologueCallback()` and `Nan::AddGCEpilogueCallback()`. Your new method receives the arguments `v8::GCType type` and `v8::GCCallbackFlags flags`. + +```c++ +static Nan::Persistent callback; + +NAN_GC_CALLBACK(gcPrologueCallback) { + v8::Local argv[] = { Nan::New("prologue").ToLocalChecked() }; + Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(callback), 1, argv); +} + +NAN_METHOD(Hook) { + callback.Reset(To(args[0]).ToLocalChecked()); + Nan::AddGCPrologueCallback(gcPrologueCallback); + info.GetReturnValue().Set(info.Holder()); +} +``` + + +### Nan::AddGCEpilogueCallback() + +Signature: + +```c++ +void Nan::AddGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback, v8::GCType gc_type_filter = v8::kGCTypeAll) +``` + +Calls V8's [`AddGCEpilogueCallback()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a580f976e4290cead62c2fc4dd396be3e). + + +### Nan::RemoveGCEpilogueCallback() + +Signature: + +```c++ +void Nan::RemoveGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback) +``` + +Calls V8's [`RemoveGCEpilogueCallback()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#adca9294555a3908e9f23c7bb0f0f284c). + + +### Nan::AddGCPrologueCallback() + +Signature: + +```c++ +void Nan::AddGCPrologueCallback(v8::Isolate::GCPrologueCallback, v8::GCType gc_type_filter callback) +``` + +Calls V8's [`AddGCPrologueCallback()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a6dbef303603ebdb03da6998794ea05b8). + + +### Nan::RemoveGCPrologueCallback() + +Signature: + +```c++ +void Nan::RemoveGCPrologueCallback(v8::Isolate::GCPrologueCallback callback) +``` + +Calls V8's [`RemoveGCPrologueCallback()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a5f72c7cda21415ce062bbe5c58abe09e). + + +### Nan::GetHeapStatistics() + +Signature: + +```c++ +void Nan::GetHeapStatistics(v8::HeapStatistics *heap_statistics) +``` + +Calls V8's [`GetHeapStatistics()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a5593ac74687b713095c38987e5950b34). + + +### Nan::SetCounterFunction() + +Signature: + +```c++ +void Nan::SetCounterFunction(v8::CounterLookupCallback cb) +``` + +Calls V8's [`SetCounterFunction()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a045d7754e62fa0ec72ae6c259b29af94). + + +### Nan::SetCreateHistogramFunction() + +Signature: + +```c++ +void Nan::SetCreateHistogramFunction(v8::CreateHistogramCallback cb) +``` + +Calls V8's [`SetCreateHistogramFunction()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a542d67e85089cb3f92aadf032f99e732). + + +### Nan::SetAddHistogramSampleFunction() + +Signature: + +```c++ +void Nan::SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) +``` + +Calls V8's [`SetAddHistogramSampleFunction()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#aeb420b690bc2c216882d6fdd00ddd3ea). + + +### Nan::IdleNotification() + +Signature: + +```c++ +bool Nan::IdleNotification(int idle_time_in_ms) +``` + +Calls V8's [`IdleNotification()` or `IdleNotificationDeadline()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#ad6a2a02657f5425ad460060652a5a118) depending on V8 version. + + +### Nan::LowMemoryNotification() + +Signature: + +```c++ +void Nan::LowMemoryNotification() +``` + +Calls V8's [`LowMemoryNotification()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a24647f61d6b41f69668094bdcd6ea91f). + + +### Nan::ContextDisposedNotification() + +Signature: + +```c++ +void Nan::ContextDisposedNotification() +``` + +Calls V8's [`ContextDisposedNotification()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#ad7f5dc559866343fe6cd8db1f134d48b). + + +### Nan::GetInternalFieldPointer() + +Gets a pointer to the internal field with at `index` from a V8 `Object` handle. + +Signature: + +```c++ +void* Nan::GetInternalFieldPointer(v8::Local object, int index) +``` + +Calls the Object's [`GetAlignedPointerFromInternalField()` or `GetPointerFromInternalField()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#a580ea84afb26c005d6762eeb9e3c308f) depending on the version of V8. + + +### Nan::SetInternalFieldPointer() + +Sets the value of the internal field at `index` on a V8 `Object` handle. + +Signature: + +```c++ +void Nan::SetInternalFieldPointer(v8::Local object, int index, void* value) +``` + +Calls the Object's [`SetAlignedPointerInInternalField()` or `SetPointerInInternalField()`](https://v8docs.nodesource.com/node-8.16/db/d85/classv8_1_1_object.html#ab3c57184263cf29963ef0017bec82281) depending on the version of V8. + + +### Nan::AdjustExternalMemory() + +Signature: + +```c++ +int Nan::AdjustExternalMemory(int bytesChange) +``` + +Calls V8's [`AdjustAmountOfExternalAllocatedMemory()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#ae1a59cac60409d3922582c4af675473e). + diff --git a/reverse_engineering/node_modules/nan/doc/v8_misc.md b/reverse_engineering/node_modules/nan/doc/v8_misc.md new file mode 100644 index 0000000..1bd46d3 --- /dev/null +++ b/reverse_engineering/node_modules/nan/doc/v8_misc.md @@ -0,0 +1,85 @@ +## Miscellaneous V8 Helpers + + - Nan::Utf8String + - Nan::GetCurrentContext() + - Nan::SetIsolateData() + - Nan::GetIsolateData() + - Nan::TypedArrayContents + + + +### Nan::Utf8String + +Converts an object to a UTF-8-encoded character array. If conversion to a string fails (e.g. due to an exception in the toString() method of the object) then the length() method returns 0 and the * operator returns NULL. The underlying memory used for this object is managed by the object. + +An implementation of [`v8::String::Utf8Value`](https://v8docs.nodesource.com/node-8.16/d4/d1b/classv8_1_1_string_1_1_utf8_value.html) that is consistent across all supported versions of V8. + +Definition: + +```c++ +class Nan::Utf8String { + public: + Nan::Utf8String(v8::Local from); + + int length() const; + + char* operator*(); + const char* operator*() const; +}; +``` + + +### Nan::GetCurrentContext() + +A call to [`v8::Isolate::GetCurrent()->GetCurrentContext()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a81c7a1ed7001ae2a65e89107f75fd053) that works across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::GetCurrentContext() +``` + + +### Nan::SetIsolateData() + +A helper to provide a consistent API to [`v8::Isolate#SetData()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#a7acadfe7965997e9c386a05f098fbe36). + +Signature: + +```c++ +void Nan::SetIsolateData(v8::Isolate *isolate, T *data) +``` + + + +### Nan::GetIsolateData() + +A helper to provide a consistent API to [`v8::Isolate#GetData()`](https://v8docs.nodesource.com/node-8.16/d5/dda/classv8_1_1_isolate.html#aabd223436bc1100a787dadaa024c6257). + +Signature: + +```c++ +T *Nan::GetIsolateData(v8::Isolate *isolate) +``` + + +### Nan::TypedArrayContents + +A helper class for accessing the contents of an ArrayBufferView (aka a typedarray) from C++. If the input array is not a valid typedarray, then the data pointer of TypedArrayContents will default to `NULL` and the length will be 0. If the data pointer is not compatible with the alignment requirements of type, an assertion error will fail. + +Note that you must store a reference to the `array` object while you are accessing its contents. + +Definition: + +```c++ +template +class Nan::TypedArrayContents { + public: + TypedArrayContents(v8::Local array); + + size_t length() const; + + T* const operator*(); + const T* const operator*() const; +}; +``` diff --git a/reverse_engineering/node_modules/nan/include_dirs.js b/reverse_engineering/node_modules/nan/include_dirs.js new file mode 100644 index 0000000..4f1dfb4 --- /dev/null +++ b/reverse_engineering/node_modules/nan/include_dirs.js @@ -0,0 +1 @@ +console.log(require('path').relative('.', __dirname)); diff --git a/reverse_engineering/node_modules/nan/nan.h b/reverse_engineering/node_modules/nan/nan.h new file mode 100644 index 0000000..6c8356c --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan.h @@ -0,0 +1,2904 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors: + * - Rod Vagg + * - Benjamin Byholm + * - Trevor Norris + * - Nathan Rajlich + * - Brett Lawson + * - Ben Noordhuis + * - David Siegel + * - Michael Ira Krufky + * + * MIT License + * + * Version 2.15.0: current Node 16.6.1, Node 0.12: 0.12.18, Node 0.10: 0.10.48, iojs: 3.3.1 + * + * See https://github.com/nodejs/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H_ +#define NAN_H_ + +#include + +#define NODE_0_10_MODULE_VERSION 11 +#define NODE_0_12_MODULE_VERSION 14 +#define ATOM_0_21_MODULE_VERSION 41 +#define IOJS_1_0_MODULE_VERSION 42 +#define IOJS_1_1_MODULE_VERSION 43 +#define IOJS_2_0_MODULE_VERSION 44 +#define IOJS_3_0_MODULE_VERSION 45 +#define NODE_4_0_MODULE_VERSION 46 +#define NODE_5_0_MODULE_VERSION 47 +#define NODE_6_0_MODULE_VERSION 48 +#define NODE_7_0_MODULE_VERSION 51 +#define NODE_8_0_MODULE_VERSION 57 +#define NODE_9_0_MODULE_VERSION 59 +#define NODE_10_0_MODULE_VERSION 64 +#define NODE_11_0_MODULE_VERSION 67 +#define NODE_12_0_MODULE_VERSION 72 +#define NODE_13_0_MODULE_VERSION 79 +#define NODE_14_0_MODULE_VERSION 83 +#define NODE_15_0_MODULE_VERSION 88 +#define NODE_16_0_MODULE_VERSION 93 + +#ifdef _MSC_VER +# define NAN_HAS_CPLUSPLUS_11 (_MSC_VER >= 1800) +#else +# define NAN_HAS_CPLUSPLUS_11 (__cplusplus >= 201103L) +#endif + +#if NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION && !NAN_HAS_CPLUSPLUS_11 +# error This version of node/NAN/v8 requires a C++11 compiler +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_MSC_VER) +# pragma warning( push ) +# pragma warning( disable : 4530 ) +# include +# include +# include +# pragma warning( pop ) +#else +# include +# include +# include +#endif + +// uv helpers +#ifdef UV_VERSION_MAJOR +# ifndef UV_VERSION_PATCH +# define UV_VERSION_PATCH 0 +# endif +# define NAUV_UVVERSION ((UV_VERSION_MAJOR << 16) | \ + (UV_VERSION_MINOR << 8) | \ + (UV_VERSION_PATCH)) +#else +# define NAUV_UVVERSION 0x000b00 +#endif + +#if NAUV_UVVERSION < 0x000b0b +# ifdef WIN32 +# include +# else +# include +# endif +#endif + +namespace Nan { + +#define NAN_CONCAT(a, b) NAN_CONCAT_HELPER(a, b) +#define NAN_CONCAT_HELPER(a, b) a##b + +#define NAN_INLINE inline // TODO(bnoordhuis) Remove in v3.0.0. + +#if defined(__GNUC__) && \ + !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS) +# define NAN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) && \ + !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS) +# define NAN_DEPRECATED __declspec(deprecated) +#else +# define NAN_DEPRECATED +#endif + +#if NAN_HAS_CPLUSPLUS_11 +# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&) = delete; +# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&) = delete; +# define NAN_DISALLOW_MOVE(CLASS) \ + CLASS(CLASS&&) = delete; /* NOLINT(build/c++11) */ \ + void operator=(CLASS&&) = delete; +#else +# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&); +# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&); +# define NAN_DISALLOW_MOVE(CLASS) +#endif + +#define NAN_DISALLOW_ASSIGN_COPY(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_COPY(CLASS) + +#define NAN_DISALLOW_ASSIGN_MOVE(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define NAN_DISALLOW_COPY_MOVE(CLASS) \ + NAN_DISALLOW_COPY(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define NAN_DISALLOW_ASSIGN_COPY_MOVE(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_COPY(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define TYPE_CHECK(T, S) \ + while (false) { \ + *(static_cast(0)) = static_cast(0); \ + } + +//=== RegistrationFunction ===================================================== + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + typedef v8::Handle ADDON_REGISTER_FUNCTION_ARGS_TYPE; +#else + typedef v8::Local ADDON_REGISTER_FUNCTION_ARGS_TYPE; +#endif + +#define NAN_MODULE_INIT(name) \ + void name(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) + +#if NODE_MAJOR_VERSION >= 10 || \ + NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3 +#define NAN_MODULE_WORKER_ENABLED(module_name, registration) \ + extern "C" NODE_MODULE_EXPORT void \ + NAN_CONCAT(node_register_module_v, NODE_MODULE_VERSION)( \ + v8::Local exports, v8::Local module, \ + v8::Local context) \ + { \ + registration(exports); \ + } +#else +#define NAN_MODULE_WORKER_ENABLED(module_name, registration) \ + NODE_MODULE(module_name, registration) +#endif + +//=== CallbackInfo ============================================================= + +#include "nan_callbacks.h" // NOLINT(build/include) + +//============================================================================== + +#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION) +typedef v8::Script UnboundScript; +typedef v8::Script BoundScript; +#else +typedef v8::UnboundScript UnboundScript; +typedef v8::Script BoundScript; +#endif + +#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION) +typedef v8::String::ExternalAsciiStringResource + ExternalOneByteStringResource; +#else +typedef v8::String::ExternalOneByteStringResource + ExternalOneByteStringResource; +#endif + +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) +template +class NonCopyablePersistentTraits : + public v8::NonCopyablePersistentTraits {}; +template +class CopyablePersistentTraits : + public v8::CopyablePersistentTraits {}; + +template +class PersistentBase : + public v8::PersistentBase {}; + +template > +class Persistent; +#else +template class NonCopyablePersistentTraits; +template class PersistentBase; +template class WeakCallbackData; +template > +class Persistent; +#endif // NODE_MODULE_VERSION + +template +class Maybe { + public: + inline bool IsNothing() const { return !has_value_; } + inline bool IsJust() const { return has_value_; } + + inline T ToChecked() const { return FromJust(); } + inline void Check() const { FromJust(); } + + inline bool To(T* out) const { + if (IsJust()) *out = value_; + return IsJust(); + } + + inline T FromJust() const { +#if defined(V8_ENABLE_CHECKS) + assert(IsJust() && "FromJust is Nothing"); +#endif // V8_ENABLE_CHECKS + return value_; + } + + inline T FromMaybe(const T& default_value) const { + return has_value_ ? value_ : default_value; + } + + inline bool operator==(const Maybe &other) const { + return (IsJust() == other.IsJust()) && + (!IsJust() || FromJust() == other.FromJust()); + } + + inline bool operator!=(const Maybe &other) const { + return !operator==(other); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + // Allow implicit conversions from v8::Maybe to Nan::Maybe. + Maybe(const v8::Maybe& that) // NOLINT(runtime/explicit) + : has_value_(that.IsJust()) + , value_(that.FromMaybe(T())) {} +#endif + + private: + Maybe() : has_value_(false) {} + explicit Maybe(const T& t) : has_value_(true), value_(t) {} + bool has_value_; + T value_; + + template + friend Maybe Nothing(); + template + friend Maybe Just(const U& u); +}; + +template +inline Maybe Nothing() { + return Maybe(); +} + +template +inline Maybe Just(const T& t) { + return Maybe(t); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# include "nan_maybe_43_inl.h" // NOLINT(build/include) +#else +# include "nan_maybe_pre_43_inl.h" // NOLINT(build/include) +#endif + +#include "nan_converters.h" // NOLINT(build/include) +#include "nan_new.h" // NOLINT(build/include) + +#if NAUV_UVVERSION < 0x000b17 +#define NAUV_WORK_CB(func) \ + void func(uv_async_t *async, int) +#else +#define NAUV_WORK_CB(func) \ + void func(uv_async_t *async) +#endif + +#if NAUV_UVVERSION >= 0x000b0b + +typedef uv_key_t nauv_key_t; + +inline int nauv_key_create(nauv_key_t *key) { + return uv_key_create(key); +} + +inline void nauv_key_delete(nauv_key_t *key) { + uv_key_delete(key); +} + +inline void* nauv_key_get(nauv_key_t *key) { + return uv_key_get(key); +} + +inline void nauv_key_set(nauv_key_t *key, void *value) { + uv_key_set(key, value); +} + +#else + +/* Implement thread local storage for older versions of libuv. + * This is essentially a backport of libuv commit 5d2434bf + * written by Ben Noordhuis, adjusted for names and inline. + */ + +#ifndef WIN32 + +typedef pthread_key_t nauv_key_t; + +inline int nauv_key_create(nauv_key_t* key) { + return -pthread_key_create(key, NULL); +} + +inline void nauv_key_delete(nauv_key_t* key) { + if (pthread_key_delete(*key)) + abort(); +} + +inline void* nauv_key_get(nauv_key_t* key) { + return pthread_getspecific(*key); +} + +inline void nauv_key_set(nauv_key_t* key, void* value) { + if (pthread_setspecific(*key, value)) + abort(); +} + +#else + +typedef struct { + DWORD tls_index; +} nauv_key_t; + +inline int nauv_key_create(nauv_key_t* key) { + key->tls_index = TlsAlloc(); + if (key->tls_index == TLS_OUT_OF_INDEXES) + return UV_ENOMEM; + return 0; +} + +inline void nauv_key_delete(nauv_key_t* key) { + if (TlsFree(key->tls_index) == FALSE) + abort(); + key->tls_index = TLS_OUT_OF_INDEXES; +} + +inline void* nauv_key_get(nauv_key_t* key) { + void* value = TlsGetValue(key->tls_index); + if (value == NULL) + if (GetLastError() != ERROR_SUCCESS) + abort(); + return value; +} + +inline void nauv_key_set(nauv_key_t* key, void* value) { + if (TlsSetValue(key->tls_index, value) == FALSE) + abort(); +} + +#endif +#endif + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template +v8::Local New(v8::Handle); +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + typedef v8::WeakCallbackType WeakCallbackType; +#else +struct WeakCallbackType { + enum E {kParameter, kInternalFields}; + E type; + WeakCallbackType(E other) : type(other) {} // NOLINT(runtime/explicit) + inline bool operator==(E other) { return other == this->type; } + inline bool operator!=(E other) { return !operator==(other); } +}; +#endif + +template class WeakCallbackInfo; + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# include "nan_persistent_12_inl.h" // NOLINT(build/include) +#else +# include "nan_persistent_pre_12_inl.h" // NOLINT(build/include) +#endif + +namespace imp { + static const size_t kMaxLength = 0x3fffffff; + // v8::String::REPLACE_INVALID_UTF8 was introduced + // in node.js v0.10.29 and v0.8.27. +#if NODE_MAJOR_VERSION > 0 || \ + NODE_MINOR_VERSION > 10 || \ + NODE_MINOR_VERSION == 10 && NODE_PATCH_VERSION >= 29 || \ + NODE_MINOR_VERSION == 8 && NODE_PATCH_VERSION >= 27 + static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8; +#else + static const unsigned kReplaceInvalidUtf8 = 0; +#endif +} // end of namespace imp + +//=== HandleScope ============================================================== + +class HandleScope { + v8::HandleScope scope; + + public: +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + inline HandleScope() : scope(v8::Isolate::GetCurrent()) {} + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(v8::Isolate::GetCurrent()); + } +#else + inline HandleScope() : scope() {} + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(); + } +#endif + + private: + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + HandleScope(const HandleScope &); + void operator=(const HandleScope &); + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } +}; + +class EscapableHandleScope { + public: +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {} + + inline static int NumberOfHandles() { + return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent()); + } + + template + inline v8::Local Escape(v8::Local value) { + return scope.Escape(value); + } + + private: + v8::EscapableHandleScope scope; +#else + inline EscapableHandleScope() : scope() {} + + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(); + } + + template + inline v8::Local Escape(v8::Local value) { + return scope.Close(value); + } + + private: + v8::HandleScope scope; +#endif + + private: + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + EscapableHandleScope(const EscapableHandleScope &); + void operator=(const EscapableHandleScope &); + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } +}; + +//=== TryCatch ================================================================= + +class TryCatch { + v8::TryCatch try_catch_; + friend void FatalException(const TryCatch&); + + public: +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {} +#endif + + inline bool HasCaught() const { return try_catch_.HasCaught(); } + + inline bool CanContinue() const { return try_catch_.CanContinue(); } + + inline v8::Local ReThrow() { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + return New(try_catch_.ReThrow()); +#else + return try_catch_.ReThrow(); +#endif + } + + inline v8::Local Exception() const { + return try_catch_.Exception(); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline v8::MaybeLocal StackTrace() const { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(try_catch_.StackTrace(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } +#else + inline MaybeLocal StackTrace() const { + return try_catch_.StackTrace(); + } +#endif + + inline v8::Local Message() const { + return try_catch_.Message(); + } + + inline void Reset() { try_catch_.Reset(); } + + inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); } + + inline void SetCaptureMessage(bool value) { + try_catch_.SetCaptureMessage(value); + } +}; + +v8::Local MakeCallback(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); +v8::Local MakeCallback(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); +v8::Local MakeCallback(v8::Local target, + const char* method, + int argc, + v8::Local* argv); + +// === AsyncResource =========================================================== + +class AsyncResource { + public: + AsyncResource( + v8::Local name + , v8::Local resource = New()) { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + if (resource.IsEmpty()) { + resource = New(); + } + + context = node::EmitAsyncInit(isolate, resource, name); +#endif + } + + AsyncResource( + const char* name + , v8::Local resource = New()) { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + if (resource.IsEmpty()) { + resource = New(); + } + + v8::Local name_string = + New(name).ToLocalChecked(); + context = node::EmitAsyncInit(isolate, resource, name_string); +#endif + } + + ~AsyncResource() { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + node::EmitAsyncDestroy(isolate, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, func, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, symbol, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, method, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv, context); +#endif + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncResource) +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + node::async_context context; +#endif +}; + +inline uv_loop_t* GetCurrentEventLoop() { +#if NODE_MAJOR_VERSION >= 10 || \ + NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3 || \ + NODE_MAJOR_VERSION == 8 && NODE_MINOR_VERSION >= 10 + return node::GetCurrentEventLoop(v8::Isolate::GetCurrent()); +#else + return uv_default_loop(); +#endif +} + +//============ ================================================================= + +/* node 0.12 */ +#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION + inline + void SetCounterFunction(v8::CounterLookupCallback cb) { + v8::Isolate::GetCurrent()->SetCounterFunction(cb); + } + + inline + void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) { + v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb); + } + + inline + void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) { + v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline bool IdleNotification(int idle_time_in_ms) { + return v8::Isolate::GetCurrent()->IdleNotificationDeadline( + idle_time_in_ms * 0.001); + } +# else + inline bool IdleNotification(int idle_time_in_ms) { + return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms); + } +#endif + + inline void LowMemoryNotification() { + v8::Isolate::GetCurrent()->LowMemoryNotification(); + } + + inline void ContextDisposedNotification() { + v8::Isolate::GetCurrent()->ContextDisposedNotification(); + } +#else + inline + void SetCounterFunction(v8::CounterLookupCallback cb) { + v8::V8::SetCounterFunction(cb); + } + + inline + void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) { + v8::V8::SetCreateHistogramFunction(cb); + } + + inline + void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) { + v8::V8::SetAddHistogramSampleFunction(cb); + } + + inline bool IdleNotification(int idle_time_in_ms) { + return v8::V8::IdleNotification(idle_time_in_ms); + } + + inline void LowMemoryNotification() { + v8::V8::LowMemoryNotification(); + } + + inline void ContextDisposedNotification() { + v8::V8::ContextDisposedNotification(); + } +#endif + +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) // Node 0.12 + inline v8::Local Undefined() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::Undefined(v8::Isolate::GetCurrent()))); +# else + return v8::Undefined(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local Null() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::Null(v8::Isolate::GetCurrent()))); +# else + return v8::Null(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local True() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::True(v8::Isolate::GetCurrent()))); +# else + return v8::True(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local False() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::False(v8::Isolate::GetCurrent()))); +# else + return v8::False(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local EmptyString() { + return v8::String::Empty(v8::Isolate::GetCurrent()); + } + + inline int AdjustExternalMemory(int bc) { + return static_cast( + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); + } + + inline void SetTemplate( + v8::Local templ + , const char *name + , v8::Local value) { + templ->Set(v8::Isolate::GetCurrent(), name, value); + } + + inline void SetTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + inline v8::Local GetCurrentContext() { + return v8::Isolate::GetCurrent()->GetCurrentContext(); + } + + inline void* GetInternalFieldPointer( + v8::Local object + , int index) { + return object->GetAlignedPointerFromInternalField(index); + } + + inline void SetInternalFieldPointer( + v8::Local object + , int index + , void* value) { + object->SetAlignedPointerInInternalField(index, value); + } + +# define NAN_GC_CALLBACK(name) \ + void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags) + +#if NODE_MODULE_VERSION <= NODE_4_0_MODULE_VERSION + typedef v8::Isolate::GCEpilogueCallback GCEpilogueCallback; + typedef v8::Isolate::GCPrologueCallback GCPrologueCallback; +#else + typedef v8::Isolate::GCCallback GCEpilogueCallback; + typedef v8::Isolate::GCCallback GCPrologueCallback; +#endif + + inline void AddGCEpilogueCallback( + GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); + } + + inline void RemoveGCEpilogueCallback( + GCEpilogueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); + } + + inline void AddGCPrologueCallback( + GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); + } + + inline void RemoveGCPrologueCallback( + GCPrologueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); + } + + inline void GetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); + } + +# define X(NAME) \ + inline v8::Local NAME(const char *msg) { \ + EscapableHandleScope scope; \ + return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + v8::Local NAME(v8::Local msg) { \ + return v8::Exception::NAME(msg); \ + } \ + \ + inline void Throw ## NAME(const char *msg) { \ + HandleScope scope; \ + v8::Isolate::GetCurrent()->ThrowException( \ + v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline void Throw ## NAME(v8::Local msg) { \ + HandleScope scope; \ + v8::Isolate::GetCurrent()->ThrowException( \ + v8::Exception::NAME(msg)); \ + } + + X(Error) + X(RangeError) + X(ReferenceError) + X(SyntaxError) + X(TypeError) + +# undef X + + inline void ThrowError(v8::Local error) { + v8::Isolate::GetCurrent()->ThrowException(error); + } + + inline MaybeLocal NewBuffer( + char *data + , size_t length +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + , node::Buffer::FreeCallback callback +#else + , node::smalloc::FreeCallback callback +#endif + , void *hint + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(length <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New( + v8::Isolate::GetCurrent(), data, length, callback, hint); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), data, length, callback, + hint); +#endif + } + + inline MaybeLocal CopyBuffer( + const char *data + , uint32_t size + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::Copy( + v8::Isolate::GetCurrent(), data, size); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); +#endif + } + + inline MaybeLocal NewBuffer(uint32_t size) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New( + v8::Isolate::GetCurrent(), size); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), size); +#endif + } + + inline MaybeLocal NewBuffer( + char* data + , uint32_t size + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); +#else + return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); +#endif + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value, + v8::NewStringType::kNormal, length); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source source(s, origin); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source source(s); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(script->BindToCurrentContext() + ->Run(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(script->Run(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } +#else + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + EscapableHandleScope scope; + return scope.Escape(script->BindToCurrentContext()->Run()); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + return script->Run(); + } +#endif + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, func, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, symbol, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, method, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + inline void FatalException(const TryCatch& try_catch) { + node::FatalException(v8::Isolate::GetCurrent(), try_catch.try_catch_); + } + + inline v8::Local ErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return node::ErrnoException(v8::Isolate::GetCurrent(), errorno, syscall, + message, path); + } + + NAN_DEPRECATED inline v8::Local NanErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return ErrnoException(errorno, syscall, message, path); + } + + template + inline void SetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(0, data); + } + + template + inline T *GetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData(0)); + } + +class Utf8String { + public: + inline explicit Utf8String(v8::Local from) : + length_(0), str_(str_st_) { + HandleScope scope; + if (!from.IsEmpty()) { +#if NODE_MAJOR_VERSION >= 10 + v8::Local context = GetCurrentContext(); + v8::Local string = + from->ToString(context).FromMaybe(v8::Local()); +#else + v8::Local string = from->ToString(); +#endif + if (!string.IsEmpty()) { + size_t len = 3 * string->Length() + 1; + assert(len <= INT_MAX); + if (len > sizeof (str_st_)) { + str_ = static_cast(malloc(len)); + assert(str_ != 0); + } + const int flags = + v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8; +#if NODE_MAJOR_VERSION >= 11 + length_ = string->WriteUtf8(v8::Isolate::GetCurrent(), str_, + static_cast(len), 0, flags); +#else + // See https://github.com/nodejs/nan/issues/832. + // Disable the warning as there is no way around it. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + length_ = string->WriteUtf8(str_, static_cast(len), 0, flags); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif // NODE_MAJOR_VERSION < 11 + str_[length_] = '\0'; + } + } + } + + inline int length() const { + return length_; + } + + inline char* operator*() { return str_; } + inline const char* operator*() const { return str_; } + + inline ~Utf8String() { + if (str_ != str_st_) { + free(str_); + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String) + + int length_; + char *str_; + char str_st_[1024]; +}; + +#else // Node 0.8 and 0.10 + inline v8::Local Undefined() { + EscapableHandleScope scope; + return scope.Escape(New(v8::Undefined())); + } + + inline v8::Local Null() { + EscapableHandleScope scope; + return scope.Escape(New(v8::Null())); + } + + inline v8::Local True() { + EscapableHandleScope scope; + return scope.Escape(New(v8::True())); + } + + inline v8::Local False() { + EscapableHandleScope scope; + return scope.Escape(New(v8::False())); + } + + inline v8::Local EmptyString() { + return v8::String::Empty(); + } + + inline int AdjustExternalMemory(int bc) { + return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); + } + + inline void SetTemplate( + v8::Local templ + , const char *name + , v8::Local value) { + templ->Set(name, value); + } + + inline void SetTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + inline v8::Local GetCurrentContext() { + return v8::Context::GetCurrent(); + } + + inline void* GetInternalFieldPointer( + v8::Local object + , int index) { + return object->GetPointerFromInternalField(index); + } + + inline void SetInternalFieldPointer( + v8::Local object + , int index + , void* value) { + object->SetPointerInInternalField(index, value); + } + +# define NAN_GC_CALLBACK(name) \ + void name(v8::GCType type, v8::GCCallbackFlags flags) + + inline void AddGCEpilogueCallback( + v8::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); + } + inline void RemoveGCEpilogueCallback( + v8::GCEpilogueCallback callback) { + v8::V8::RemoveGCEpilogueCallback(callback); + } + inline void AddGCPrologueCallback( + v8::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCPrologueCallback(callback, gc_type_filter); + } + inline void RemoveGCPrologueCallback( + v8::GCPrologueCallback callback) { + v8::V8::RemoveGCPrologueCallback(callback); + } + inline void GetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::V8::GetHeapStatistics(heap_statistics); + } + +# define X(NAME) \ + inline v8::Local NAME(const char *msg) { \ + EscapableHandleScope scope; \ + return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + v8::Local NAME(v8::Local msg) { \ + return v8::Exception::NAME(msg); \ + } \ + \ + inline void Throw ## NAME(const char *msg) { \ + HandleScope scope; \ + v8::ThrowException(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + void Throw ## NAME(v8::Local errmsg) { \ + HandleScope scope; \ + v8::ThrowException(v8::Exception::NAME(errmsg)); \ + } + + X(Error) + X(RangeError) + X(ReferenceError) + X(SyntaxError) + X(TypeError) + +# undef X + + inline void ThrowError(v8::Local error) { + v8::ThrowException(error); + } + + inline MaybeLocal NewBuffer( + char *data + , size_t length + , node::Buffer::free_callback callback + , void *hint + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(length <= imp::kMaxLength && "too large buffer"); + return scope.Escape( + New(node::Buffer::New(data, length, callback, hint)->handle_)); + } + + inline MaybeLocal CopyBuffer( + const char *data + , uint32_t size + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION + return scope.Escape(New(node::Buffer::New(data, size)->handle_)); +#else + return scope.Escape( + New(node::Buffer::New(const_cast(data), size)->handle_)); +#endif + } + + inline MaybeLocal NewBuffer(uint32_t size) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + assert(size <= imp::kMaxLength && "too large buffer"); + return scope.Escape(New(node::Buffer::New(size)->handle_)); + } + + inline void FreeData(char *data, void *hint) { + (void) hint; // unused + delete[] data; + } + + inline MaybeLocal NewBuffer( + char* data + , uint32_t size + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); + return scope.Escape( + New(node::Buffer::New(data, size, FreeData, NULL)->handle_)); + } + +namespace imp { +inline void +widenString(std::vector *ws, const uint8_t *s, int l) { + size_t len = static_cast(l); + if (l < 0) { + len = strlen(reinterpret_cast(s)); + } + assert(len <= INT_MAX && "string too long"); + ws->resize(len); + std::copy(s, s + len, ws->begin()); // NOLINT(build/include_what_you_use) +} +} // end of namespace imp + + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + std::vector wideString; // NOLINT(build/include_what_you_use) + imp::widenString(&wideString, value, length); + return v8::String::New(wideString.data(), + static_cast(wideString.size())); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::Compile(s, const_cast(&origin)); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + return v8::Script::Compile(s); + } + + inline + MaybeLocal RunScript(v8::Local script) { + return script->Run(); + } + + inline v8::Local MakeCallback( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, func, argc, argv))); + } + + inline v8::Local MakeCallback( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, symbol, argc, argv))); + } + + inline v8::Local MakeCallback( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, method, argc, argv))); + } + + inline void FatalException(const TryCatch& try_catch) { + node::FatalException(const_cast(try_catch.try_catch_)); + } + + inline v8::Local ErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return node::ErrnoException(errorno, syscall, message, path); + } + + NAN_DEPRECATED inline v8::Local NanErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return ErrnoException(errorno, syscall, message, path); + } + + + template + inline void SetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(data); + } + + template + inline T *GetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData()); + } + +class Utf8String { + public: + inline explicit Utf8String(v8::Local from) : + length_(0), str_(str_st_) { + v8::HandleScope scope; + if (!from.IsEmpty()) { + v8::Local string = from->ToString(); + if (!string.IsEmpty()) { + size_t len = 3 * string->Length() + 1; + assert(len <= INT_MAX); + if (len > sizeof (str_st_)) { + str_ = static_cast(malloc(len)); + assert(str_ != 0); + } + const int flags = + v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8; + length_ = string->WriteUtf8(str_, static_cast(len), 0, flags); + str_[length_] = '\0'; + } + } + } + + inline int length() const { + return length_; + } + + inline char* operator*() { return str_; } + inline const char* operator*() const { return str_; } + + inline ~Utf8String() { + if (str_ != str_st_) { + free(str_); + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String) + + int length_; + char *str_; + char str_st_[1024]; +}; + +#endif // NODE_MODULE_VERSION + +typedef void (*FreeCallback)(char *data, void *hint); + +typedef const FunctionCallbackInfo& NAN_METHOD_ARGS_TYPE; +typedef void NAN_METHOD_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_GETTER_ARGS_TYPE; +typedef void NAN_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_SETTER_ARGS_TYPE; +typedef void NAN_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_GETTER_ARGS_TYPE; +typedef void NAN_PROPERTY_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_SETTER_ARGS_TYPE; +typedef void NAN_PROPERTY_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_ENUMERATOR_ARGS_TYPE; +typedef void NAN_PROPERTY_ENUMERATOR_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_DELETER_ARGS_TYPE; +typedef void NAN_PROPERTY_DELETER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_QUERY_ARGS_TYPE; +typedef void NAN_PROPERTY_QUERY_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_INDEX_GETTER_ARGS_TYPE; +typedef void NAN_INDEX_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_INDEX_SETTER_ARGS_TYPE; +typedef void NAN_INDEX_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_ENUMERATOR_ARGS_TYPE; +typedef void NAN_INDEX_ENUMERATOR_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_DELETER_ARGS_TYPE; +typedef void NAN_INDEX_DELETER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_QUERY_ARGS_TYPE; +typedef void NAN_INDEX_QUERY_RETURN_TYPE; + +#define NAN_METHOD(name) \ + Nan::NAN_METHOD_RETURN_TYPE name(Nan::NAN_METHOD_ARGS_TYPE info) +#define NAN_GETTER(name) \ + Nan::NAN_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_GETTER_ARGS_TYPE info) +#define NAN_SETTER(name) \ + Nan::NAN_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , Nan::NAN_SETTER_ARGS_TYPE info) +#define NAN_PROPERTY_GETTER(name) \ + Nan::NAN_PROPERTY_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info) +#define NAN_PROPERTY_SETTER(name) \ + Nan::NAN_PROPERTY_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info) +#define NAN_PROPERTY_ENUMERATOR(name) \ + Nan::NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name( \ + Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info) +#define NAN_PROPERTY_DELETER(name) \ + Nan::NAN_PROPERTY_DELETER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_DELETER_ARGS_TYPE info) +#define NAN_PROPERTY_QUERY(name) \ + Nan::NAN_PROPERTY_QUERY_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_QUERY_ARGS_TYPE info) +# define NAN_INDEX_GETTER(name) \ + Nan::NAN_INDEX_GETTER_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_GETTER_ARGS_TYPE info) +#define NAN_INDEX_SETTER(name) \ + Nan::NAN_INDEX_SETTER_RETURN_TYPE name( \ + uint32_t index \ + , v8::Local value \ + , Nan::NAN_INDEX_SETTER_ARGS_TYPE info) +#define NAN_INDEX_ENUMERATOR(name) \ + Nan::NAN_INDEX_ENUMERATOR_RETURN_TYPE \ + name(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info) +#define NAN_INDEX_DELETER(name) \ + Nan::NAN_INDEX_DELETER_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_DELETER_ARGS_TYPE info) +#define NAN_INDEX_QUERY(name) \ + Nan::NAN_INDEX_QUERY_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_QUERY_ARGS_TYPE info) + +class Callback { + public: + Callback() {} + + explicit Callback(const v8::Local &fn) : handle_(fn) {} + + ~Callback() { + handle_.Reset(); + } + + bool operator==(const Callback &other) const { + return handle_ == other.handle_; + } + + bool operator!=(const Callback &other) const { + return !operator==(other); + } + + inline + v8::Local operator*() const { return GetFunction(); } + + NAN_DEPRECATED inline v8::Local operator()( + v8::Local target + , int argc = 0 + , v8::Local argv[] = 0) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:operator()"); + return Call_(isolate, target, argc, argv, &async) + .FromMaybe(v8::Local()); +# else + return Call_(isolate, target, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + return Call_(target, argc, argv); +#endif // NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local operator()( + int argc = 0 + , v8::Local argv[] = 0) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:operator()"); + return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(), + argc, argv, &async) + .FromMaybe(v8::Local())); +# else + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif // NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + } + + inline MaybeLocal operator()( + AsyncResource* resource + , int argc = 0 + , v8::Local argv[] = 0) const { + return this->Call(argc, argv, resource); + } + + inline MaybeLocal operator()( + AsyncResource* resource + , v8::Local target + , int argc = 0 + , v8::Local argv[] = 0) const { + return this->Call(target, argc, argv, resource); + } + + // TODO(kkoopa): remove + inline void SetFunction(const v8::Local &fn) { + Reset(fn); + } + + inline void Reset(const v8::Local &fn) { + handle_.Reset(fn); + } + + inline void Reset() { + handle_.Reset(); + } + + inline v8::Local GetFunction() const { + return New(handle_); + } + + inline bool IsEmpty() const { + return handle_.IsEmpty(); + } + + // Deprecated: For async callbacks Use the versions that accept an + // AsyncResource. If this callback does not correspond to an async resource, + // that is, it is a synchronous function call on a non-empty JS stack, you + // should Nan::Call instead. + NAN_DEPRECATED inline v8::Local + Call(v8::Local target + , int argc + , v8::Local argv[]) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:Call"); + return Call_(isolate, target, argc, argv, &async) + .FromMaybe(v8::Local()); +# else + return Call_(isolate, target, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + return Call_(target, argc, argv); +#endif + } + + // Deprecated: For async callbacks Use the versions that accept an + // AsyncResource. If this callback does not correspond to an async resource, + // that is, it is a synchronous function call on a non-empty JS stack, you + // should Nan::Call instead. + NAN_DEPRECATED inline v8::Local + Call(int argc, v8::Local argv[]) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:Call"); + return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(), + argc, argv, &async) + .FromMaybe(v8::Local())); +# else + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif + } + + inline MaybeLocal + Call(v8::Local target + , int argc + , v8::Local argv[] + , AsyncResource* resource) const { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return Call_(isolate, target, argc, argv, resource); +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + return Call_(isolate, target, argc, argv); +#else + return Call_(target, argc, argv); +#endif + } + + inline MaybeLocal + Call(int argc, v8::Local argv[], AsyncResource* resource) const { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return Call(isolate->GetCurrentContext()->Global(), argc, argv, resource); +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback) + Persistent handle_; + +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + MaybeLocal Call_(v8::Isolate *isolate + , v8::Local target + , int argc + , v8::Local argv[] + , AsyncResource* resource) const { + EscapableHandleScope scope; + v8::Local func = New(handle_); + auto maybe = resource->runInAsyncScope(target, func, argc, argv); + v8::Local local; + if (!maybe.ToLocal(&local)) return MaybeLocal(); + return scope.Escape(local); + } +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Local Call_(v8::Isolate *isolate + , v8::Local target + , int argc + , v8::Local argv[]) const { + EscapableHandleScope scope; + + v8::Local callback = New(handle_); +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + return scope.Escape(New(node::MakeCallback( + isolate + , target + , callback + , argc + , argv + ))); +# else + return scope.Escape(node::MakeCallback( + isolate + , target + , callback + , argc + , argv + )); +# endif + } +#else + v8::Local Call_(v8::Local target + , int argc + , v8::Local argv[]) const { + EscapableHandleScope scope; + + v8::Local callback = New(handle_); + return scope.Escape(New(node::MakeCallback( + target + , callback + , argc + , argv + ))); + } +#endif +}; + +inline MaybeLocal Call( + const Nan::Callback& callback + , v8::Local recv + , int argc + , v8::Local argv[]) { + return Call(*callback, recv, argc, argv); +} + +inline MaybeLocal Call( + const Nan::Callback& callback + , int argc + , v8::Local argv[]) { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + Call(*callback, isolate->GetCurrentContext()->Global(), argc, argv) + .FromMaybe(v8::Local())); +#else + EscapableHandleScope scope; + return scope.Escape( + Call(*callback, v8::Context::GetCurrent()->Global(), argc, argv) + .FromMaybe(v8::Local())); +#endif +} + +inline MaybeLocal Call( + v8::Local symbol + , v8::Local recv + , int argc + , v8::Local argv[]) { + EscapableHandleScope scope; + v8::Local fn_v = + Get(recv, symbol).FromMaybe(v8::Local()); + if (fn_v.IsEmpty() || !fn_v->IsFunction()) return v8::Local(); + v8::Local fn = fn_v.As(); + return scope.Escape( + Call(fn, recv, argc, argv).FromMaybe(v8::Local())); +} + +inline MaybeLocal Call( + const char* method + , v8::Local recv + , int argc + , v8::Local argv[]) { + EscapableHandleScope scope; + v8::Local method_string = + New(method).ToLocalChecked(); + return scope.Escape( + Call(method_string, recv, argc, argv).FromMaybe(v8::Local())); +} + +/* abstract */ class AsyncWorker { + public: + explicit AsyncWorker(Callback *callback_, + const char* resource_name = "nan:AsyncWorker") + : callback(callback_), errmsg_(NULL) { + request.data = this; + + HandleScope scope; + v8::Local obj = New(); + persistentHandle.Reset(obj); + async_resource = new AsyncResource(resource_name, obj); + } + + virtual ~AsyncWorker() { + HandleScope scope; + + if (!persistentHandle.IsEmpty()) + persistentHandle.Reset(); + delete callback; + delete[] errmsg_; + delete async_resource; + } + + virtual void WorkComplete() { + HandleScope scope; + + if (errmsg_ == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + inline void SaveToPersistent( + const char *key, const v8::Local &value) { + HandleScope scope; + Set(New(persistentHandle), New(key).ToLocalChecked(), value).FromJust(); + } + + inline void SaveToPersistent( + const v8::Local &key, const v8::Local &value) { + HandleScope scope; + Set(New(persistentHandle), key, value).FromJust(); + } + + inline void SaveToPersistent( + uint32_t index, const v8::Local &value) { + HandleScope scope; + Set(New(persistentHandle), index, value).FromJust(); + } + + inline v8::Local GetFromPersistent(const char *key) const { + EscapableHandleScope scope; + return scope.Escape( + Get(New(persistentHandle), New(key).ToLocalChecked()) + .FromMaybe(v8::Local())); + } + + inline v8::Local + GetFromPersistent(const v8::Local &key) const { + EscapableHandleScope scope; + return scope.Escape( + Get(New(persistentHandle), key) + .FromMaybe(v8::Local())); + } + + inline v8::Local GetFromPersistent(uint32_t index) const { + EscapableHandleScope scope; + return scope.Escape( + Get(New(persistentHandle), index) + .FromMaybe(v8::Local())); + } + + virtual void Execute() = 0; + + uv_work_t request; + + virtual void Destroy() { + delete this; + } + + protected: + Persistent persistentHandle; + Callback *callback; + AsyncResource *async_resource; + + virtual void HandleOKCallback() { + HandleScope scope; + + callback->Call(0, NULL, async_resource); + } + + virtual void HandleErrorCallback() { + HandleScope scope; + + v8::Local argv[] = { + v8::Exception::Error(New(ErrorMessage()).ToLocalChecked()) + }; + callback->Call(1, argv, async_resource); + } + + void SetErrorMessage(const char *msg) { + delete[] errmsg_; + + size_t size = strlen(msg) + 1; + errmsg_ = new char[size]; + memcpy(errmsg_, msg, size); + } + + const char* ErrorMessage() const { + return errmsg_; + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncWorker) + char *errmsg_; +}; + +/* abstract */ class AsyncBareProgressWorkerBase : public AsyncWorker { + public: + explicit AsyncBareProgressWorkerBase( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressWorkerBase") + : AsyncWorker(callback_, resource_name) { + uv_async_init( + GetCurrentEventLoop() + , &async + , AsyncProgress_ + ); + async.data = this; + } + + virtual ~AsyncBareProgressWorkerBase() { + } + + virtual void WorkProgress() = 0; + + virtual void Destroy() { + uv_close(reinterpret_cast(&async), AsyncClose_); + } + + private: + inline static NAUV_WORK_CB(AsyncProgress_) { + AsyncBareProgressWorkerBase *worker = + static_cast(async->data); + worker->WorkProgress(); + } + + inline static void AsyncClose_(uv_handle_t* handle) { + AsyncBareProgressWorkerBase *worker = + static_cast(handle->data); + delete worker; + } + + protected: + uv_async_t async; +}; + +template +/* abstract */ +class AsyncBareProgressWorker : public AsyncBareProgressWorkerBase { + public: + explicit AsyncBareProgressWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressWorker") + : AsyncBareProgressWorkerBase(callback_, resource_name) { + uv_mutex_init(&async_lock); + } + + virtual ~AsyncBareProgressWorker() { + uv_mutex_destroy(&async_lock); + } + + class ExecutionProgress { + friend class AsyncBareProgressWorker; + public: + void Signal() const { + uv_mutex_lock(&that_->async_lock); + uv_async_send(&that_->async); + uv_mutex_unlock(&that_->async_lock); + } + + void Send(const T* data, size_t count) const { + that_->SendProgress_(data, count); + } + + private: + explicit ExecutionProgress(AsyncBareProgressWorker *that) : that_(that) {} + NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress) + AsyncBareProgressWorker* const that_; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + virtual void HandleProgressCallback(const T *data, size_t size) = 0; + + protected: + uv_mutex_t async_lock; + + private: + void Execute() /*final override*/ { + ExecutionProgress progress(this); + Execute(progress); + } + + virtual void SendProgress_(const T *data, size_t count) = 0; +}; + +template +/* abstract */ +class AsyncProgressWorkerBase : public AsyncBareProgressWorker { + public: + explicit AsyncProgressWorkerBase( + Callback *callback_, + const char* resource_name = "nan:AsyncProgressWorkerBase") + : AsyncBareProgressWorker(callback_, resource_name), asyncdata_(NULL), + asyncsize_(0) { + } + + virtual ~AsyncProgressWorkerBase() { + delete[] asyncdata_; + } + + void WorkProgress() { + uv_mutex_lock(&this->async_lock); + T *data = asyncdata_; + size_t size = asyncsize_; + asyncdata_ = NULL; + asyncsize_ = 0; + uv_mutex_unlock(&this->async_lock); + + // Don't send progress events after we've already completed. + if (this->callback) { + this->HandleProgressCallback(data, size); + } + delete[] data; + } + + private: + void SendProgress_(const T *data, size_t count) { + T *new_data = new T[count]; + std::copy(data, data + count, new_data); + + uv_mutex_lock(&this->async_lock); + T *old_data = asyncdata_; + asyncdata_ = new_data; + asyncsize_ = count; + uv_async_send(&this->async); + uv_mutex_unlock(&this->async_lock); + + delete[] old_data; + } + + T *asyncdata_; + size_t asyncsize_; +}; + +// This ensures compatibility to the previous un-templated AsyncProgressWorker +// class definition. +typedef AsyncProgressWorkerBase AsyncProgressWorker; + +template +/* abstract */ +class AsyncBareProgressQueueWorker : public AsyncBareProgressWorkerBase { + public: + explicit AsyncBareProgressQueueWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressQueueWorker") + : AsyncBareProgressWorkerBase(callback_, resource_name) { + } + + virtual ~AsyncBareProgressQueueWorker() { + } + + class ExecutionProgress { + friend class AsyncBareProgressQueueWorker; + public: + void Send(const T* data, size_t count) const { + that_->SendProgress_(data, count); + } + + private: + explicit ExecutionProgress(AsyncBareProgressQueueWorker *that) + : that_(that) {} + NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress) + AsyncBareProgressQueueWorker* const that_; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + virtual void HandleProgressCallback(const T *data, size_t size) = 0; + + private: + void Execute() /*final override*/ { + ExecutionProgress progress(this); + Execute(progress); + } + + virtual void SendProgress_(const T *data, size_t count) = 0; +}; + +template +/* abstract */ +class AsyncProgressQueueWorker : public AsyncBareProgressQueueWorker { + public: + explicit AsyncProgressQueueWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncProgressQueueWorker") + : AsyncBareProgressQueueWorker(callback_) { + uv_mutex_init(&async_lock); + } + + virtual ~AsyncProgressQueueWorker() { + uv_mutex_lock(&async_lock); + + while (!asyncdata_.empty()) { + std::pair &datapair = asyncdata_.front(); + T *data = datapair.first; + + asyncdata_.pop(); + + delete[] data; + } + + uv_mutex_unlock(&async_lock); + uv_mutex_destroy(&async_lock); + } + + void WorkComplete() { + WorkProgress(); + AsyncWorker::WorkComplete(); + } + + void WorkProgress() { + uv_mutex_lock(&async_lock); + + while (!asyncdata_.empty()) { + std::pair &datapair = asyncdata_.front(); + + T *data = datapair.first; + size_t size = datapair.second; + + asyncdata_.pop(); + uv_mutex_unlock(&async_lock); + + // Don't send progress events after we've already completed. + if (this->callback) { + this->HandleProgressCallback(data, size); + } + + delete[] data; + + uv_mutex_lock(&async_lock); + } + + uv_mutex_unlock(&async_lock); + } + + private: + void SendProgress_(const T *data, size_t count) { + T *new_data = new T[count]; + std::copy(data, data + count, new_data); + + uv_mutex_lock(&async_lock); + asyncdata_.push(std::pair(new_data, count)); + uv_mutex_unlock(&async_lock); + + uv_async_send(&this->async); + } + + uv_mutex_t async_lock; + std::queue > asyncdata_; +}; + +inline void AsyncExecute (uv_work_t* req) { + AsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +/* uv_after_work_cb has 1 argument before node-v0.9.4 and + * 2 arguments since node-v0.9.4 + * https://github.com/libuv/libuv/commit/92fb84b751e18f032c02609467f44bfe927b80c5 + */ +inline void AsyncExecuteComplete(uv_work_t *req) { + AsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + worker->Destroy(); +} +inline void AsyncExecuteComplete (uv_work_t* req, int status) { + AsyncExecuteComplete(req); +} + +inline void AsyncQueueWorker (AsyncWorker* worker) { + uv_queue_work( + GetCurrentEventLoop() + , &worker->request + , AsyncExecute + , AsyncExecuteComplete + ); +} + +namespace imp { + +inline +ExternalOneByteStringResource const* +GetExternalResource(v8::Local str) { +#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION + return str->GetExternalAsciiStringResource(); +#else + return str->GetExternalOneByteStringResource(); +#endif +} + +inline +bool +IsExternal(v8::Local str) { +#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION + return str->IsExternalAscii(); +#else + return str->IsExternalOneByte(); +#endif +} + +} // end of namespace imp + +enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; + +#if NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION +# include "nan_string_bytes.h" // NOLINT(build/include) +#endif + +inline v8::Local Encode( + const void *buf, size_t len, enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + node::encoding node_enc = static_cast(encoding); + + if (encoding == UCS2) { + return node::Encode( + isolate + , reinterpret_cast(buf) + , len / 2); + } else { + return node::Encode( + isolate + , reinterpret_cast(buf) + , len + , node_enc); + } +#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::Encode( + v8::Isolate::GetCurrent() + , buf, len + , static_cast(encoding)); +#else +# if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION + return node::Encode(buf, len, static_cast(encoding)); +# else + return imp::Encode(reinterpret_cast(buf), len, encoding); +# endif +#endif +} + +inline ssize_t DecodeBytes( + v8::Local val, enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::DecodeBytes( + v8::Isolate::GetCurrent() + , val + , static_cast(encoding)); +#else +# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION) + if (encoding == BUFFER) { + return node::DecodeBytes(val, node::BINARY); + } +# endif + return node::DecodeBytes(val, static_cast(encoding)); +#endif +} + +inline ssize_t DecodeWrite( + char *buf + , size_t len + , v8::Local val + , enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::DecodeWrite( + v8::Isolate::GetCurrent() + , buf + , len + , val + , static_cast(encoding)); +#else +# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION) + if (encoding == BUFFER) { + return node::DecodeWrite(buf, len, val, node::BINARY); + } +# endif + return node::DecodeWrite( + buf + , len + , val + , static_cast(encoding)); +#endif +} + +inline void SetPrototypeTemplate( + v8::Local templ + , const char *name + , v8::Local value +) { + HandleScope scope; + SetTemplate(templ->PrototypeTemplate(), name, value); +} + +inline void SetPrototypeTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes +) { + HandleScope scope; + SetTemplate(templ->PrototypeTemplate(), name, value, attributes); +} + +inline void SetInstanceTemplate( + v8::Local templ + , const char *name + , v8::Local value +) { + HandleScope scope; + SetTemplate(templ->InstanceTemplate(), name, value); +} + +inline void SetInstanceTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes +) { + HandleScope scope; + SetTemplate(templ->InstanceTemplate(), name, value, attributes); +} + +namespace imp { + +// Note(@agnat): Helper to distinguish different receiver types. The first +// version deals with receivers derived from v8::Template. The second version +// handles everything else. The final argument only serves as discriminator and +// is unused. +template +inline +void +SetMethodAux(T recv, + v8::Local name, + v8::Local tpl, + v8::Template *) { + recv->Set(name, tpl); +} + +template +inline +void +SetMethodAux(T recv, + v8::Local name, + v8::Local tpl, + ...) { + Set(recv, name, GetFunction(tpl).ToLocalChecked()); +} + +} // end of namespace imp + +template class HandleType> +inline void SetMethod( + HandleType recv + , const char *name + , FunctionCallback callback + , v8::Local data = v8::Local()) { + HandleScope scope; + v8::Local t = New(callback, data); + v8::Local fn_name = New(name).ToLocalChecked(); + t->SetClassName(fn_name); + // Note(@agnat): Pass an empty T* as discriminator. See note on + // SetMethodAux(...) above + imp::SetMethodAux(recv, fn_name, t, static_cast(0)); +} + +inline void SetPrototypeMethod( + v8::Local recv + , const char* name + , FunctionCallback callback + , v8::Local data = v8::Local()) { + HandleScope scope; + v8::Local t = New( + callback + , data + , New(recv)); + v8::Local fn_name = New(name).ToLocalChecked(); + recv->PrototypeTemplate()->Set(fn_name, t); + t->SetClassName(fn_name); +} + +//=== Accessors and Such ======================================================= + +inline void SetAccessor( + v8::Local tpl + , v8::Local name + , GetterCallback getter + , SetterCallback setter = 0 + , v8::Local data = v8::Local() + , v8::AccessControl settings = v8::DEFAULT + , v8::PropertyAttribute attribute = v8::None + , imp::Sig signature = imp::Sig()) { + HandleScope scope; + + imp::NativeGetter getter_ = + imp::GetterCallbackWrapper; + imp::NativeSetter setter_ = + setter ? imp::SetterCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kAccessorFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kGetterIndex + , New(reinterpret_cast(getter))); + + if (setter != 0) { + obj->SetInternalField( + imp::kSetterIndex + , New(reinterpret_cast(setter))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetAccessor( + name + , getter_ + , setter_ + , obj + , settings + , attribute + , signature); +} + +inline bool SetAccessor( + v8::Local obj + , v8::Local name + , GetterCallback getter + , SetterCallback setter = 0 + , v8::Local data = v8::Local() + , v8::AccessControl settings = v8::DEFAULT + , v8::PropertyAttribute attribute = v8::None) { + HandleScope scope; + + imp::NativeGetter getter_ = + imp::GetterCallbackWrapper; + imp::NativeSetter setter_ = + setter ? imp::SetterCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kAccessorFieldCount); + v8::Local dataobj = NewInstance(otpl).ToLocalChecked(); + + dataobj->SetInternalField( + imp::kGetterIndex + , New(reinterpret_cast(getter))); + + if (!data.IsEmpty()) { + dataobj->SetInternalField(imp::kDataIndex, data); + } + + if (setter) { + dataobj->SetInternalField( + imp::kSetterIndex + , New(reinterpret_cast(setter))); + } + +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + return obj->SetAccessor( + GetCurrentContext() + , name + , getter_ + , setter_ + , dataobj + , settings + , attribute).FromMaybe(false); +#else + return obj->SetAccessor( + name + , getter_ + , setter_ + , dataobj + , settings + , attribute); +#endif +} + +inline void SetNamedPropertyHandler( + v8::Local tpl + , PropertyGetterCallback getter + , PropertySetterCallback setter = 0 + , PropertyQueryCallback query = 0 + , PropertyDeleterCallback deleter = 0 + , PropertyEnumeratorCallback enumerator = 0 + , v8::Local data = v8::Local()) { + HandleScope scope; + + imp::NativePropertyGetter getter_ = + imp::PropertyGetterCallbackWrapper; + imp::NativePropertySetter setter_ = + setter ? imp::PropertySetterCallbackWrapper : 0; + imp::NativePropertyQuery query_ = + query ? imp::PropertyQueryCallbackWrapper : 0; + imp::NativePropertyDeleter *deleter_ = + deleter ? imp::PropertyDeleterCallbackWrapper : 0; + imp::NativePropertyEnumerator enumerator_ = + enumerator ? imp::PropertyEnumeratorCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kPropertyFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + obj->SetInternalField( + imp::kPropertyGetterIndex + , New(reinterpret_cast(getter))); + + if (setter) { + obj->SetInternalField( + imp::kPropertySetterIndex + , New(reinterpret_cast(setter))); + } + + if (query) { + obj->SetInternalField( + imp::kPropertyQueryIndex + , New(reinterpret_cast(query))); + } + + if (deleter) { + obj->SetInternalField( + imp::kPropertyDeleterIndex + , New(reinterpret_cast(deleter))); + } + + if (enumerator) { + obj->SetInternalField( + imp::kPropertyEnumeratorIndex + , New(reinterpret_cast(enumerator))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + tpl->SetHandler(v8::NamedPropertyHandlerConfiguration( + getter_, setter_, query_, deleter_, enumerator_, obj)); +#else + tpl->SetNamedPropertyHandler( + getter_ + , setter_ + , query_ + , deleter_ + , enumerator_ + , obj); +#endif +} + +inline void SetIndexedPropertyHandler( + v8::Local tpl + , IndexGetterCallback getter + , IndexSetterCallback setter = 0 + , IndexQueryCallback query = 0 + , IndexDeleterCallback deleter = 0 + , IndexEnumeratorCallback enumerator = 0 + , v8::Local data = v8::Local()) { + HandleScope scope; + + imp::NativeIndexGetter getter_ = + imp::IndexGetterCallbackWrapper; + imp::NativeIndexSetter setter_ = + setter ? imp::IndexSetterCallbackWrapper : 0; + imp::NativeIndexQuery query_ = + query ? imp::IndexQueryCallbackWrapper : 0; + imp::NativeIndexDeleter deleter_ = + deleter ? imp::IndexDeleterCallbackWrapper : 0; + imp::NativeIndexEnumerator enumerator_ = + enumerator ? imp::IndexEnumeratorCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kIndexPropertyFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + obj->SetInternalField( + imp::kIndexPropertyGetterIndex + , New(reinterpret_cast(getter))); + + if (setter) { + obj->SetInternalField( + imp::kIndexPropertySetterIndex + , New(reinterpret_cast(setter))); + } + + if (query) { + obj->SetInternalField( + imp::kIndexPropertyQueryIndex + , New(reinterpret_cast(query))); + } + + if (deleter) { + obj->SetInternalField( + imp::kIndexPropertyDeleterIndex + , New(reinterpret_cast(deleter))); + } + + if (enumerator) { + obj->SetInternalField( + imp::kIndexPropertyEnumeratorIndex + , New(reinterpret_cast(enumerator))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + tpl->SetHandler(v8::IndexedPropertyHandlerConfiguration( + getter_, setter_, query_, deleter_, enumerator_, obj)); +#else + tpl->SetIndexedPropertyHandler( + getter_ + , setter_ + , query_ + , deleter_ + , enumerator_ + , obj); +#endif +} + +inline void SetCallHandler( + v8::Local tpl + , FunctionCallback callback + , v8::Local data = v8::Local()) { + HandleScope scope; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , New(reinterpret_cast(callback))); + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj); +} + + +inline void SetCallAsFunctionHandler( + v8::Local tpl, + FunctionCallback callback, + v8::Local data = v8::Local()) { + HandleScope scope; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , New(reinterpret_cast(callback))); + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj); +} + +//=== Weak Persistent Handling ================================================= + +#include "nan_weak.h" // NOLINT(build/include) + +//=== ObjectWrap =============================================================== + +#include "nan_object_wrap.h" // NOLINT(build/include) + +//=== HiddenValue/Private ====================================================== + +#include "nan_private.h" // NOLINT(build/include) + +//=== Export ================================================================== + +inline +void +Export(ADDON_REGISTER_FUNCTION_ARGS_TYPE target, const char *name, + FunctionCallback f) { + HandleScope scope; + + Set(target, New(name).ToLocalChecked(), + GetFunction(New(f)).ToLocalChecked()); +} + +//=== Tap Reverse Binding ===================================================== + +struct Tap { + explicit Tap(v8::Local t) : t_() { + HandleScope scope; + + t_.Reset(To(t).ToLocalChecked()); + } + + ~Tap() { t_.Reset(); } // not sure if necessary + + inline void plan(int i) { + HandleScope scope; + v8::Local arg = New(i); + Call("plan", New(t_), 1, &arg); + } + + inline void ok(bool isOk, const char *msg = NULL) { + HandleScope scope; + v8::Local args[2]; + args[0] = New(isOk); + if (msg) args[1] = New(msg).ToLocalChecked(); + Call("ok", New(t_), msg ? 2 : 1, args); + } + + inline void pass(const char * msg = NULL) { + HandleScope scope; + v8::Local hmsg; + if (msg) hmsg = New(msg).ToLocalChecked(); + Call("pass", New(t_), msg ? 1 : 0, &hmsg); + } + + inline void end() { + HandleScope scope; + Call("end", New(t_), 0, NULL); + } + + private: + Persistent t_; +}; + +#define NAN_STRINGIZE2(x) #x +#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x) +#define NAN_TEST_EXPRESSION(expression) \ + ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression + +#define NAN_EXPORT(target, function) Export(target, #function, function) + +#undef TYPE_CHECK + +//=== Generic Maybefication =================================================== + +namespace imp { + +template struct Maybefier; + +template struct Maybefier > { + inline static MaybeLocal convert(v8::Local v) { + return v; + } +}; + +template struct Maybefier > { + inline static MaybeLocal convert(MaybeLocal v) { + return v; + } +}; + +} // end of namespace imp + +template class MaybeMaybe> +inline MaybeLocal +MakeMaybe(MaybeMaybe v) { + return imp::Maybefier >::convert(v); +} + +//=== TypedArrayContents ======================================================= + +#include "nan_typedarray_contents.h" // NOLINT(build/include) + +//=== JSON ===================================================================== + +#include "nan_json.h" // NOLINT(build/include) + +//=== ScriptOrigin ============================================================= + +#include "nan_scriptorigin.h" // NOLINT(build/include) + +} // end of namespace Nan + +#endif // NAN_H_ diff --git a/reverse_engineering/node_modules/nan/nan_callbacks.h b/reverse_engineering/node_modules/nan/nan_callbacks.h new file mode 100644 index 0000000..53ede84 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_callbacks.h @@ -0,0 +1,88 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_H_ +#define NAN_CALLBACKS_H_ + +template class FunctionCallbackInfo; +template class PropertyCallbackInfo; +template class Global; + +typedef void(*FunctionCallback)(const FunctionCallbackInfo&); +typedef void(*GetterCallback) + (v8::Local, const PropertyCallbackInfo&); +typedef void(*SetterCallback)( + v8::Local, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyGetterCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertySetterCallback)( + v8::Local, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyEnumeratorCallback) + (const PropertyCallbackInfo&); +typedef void(*PropertyDeleterCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyQueryCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*IndexGetterCallback)( + uint32_t, + const PropertyCallbackInfo&); +typedef void(*IndexSetterCallback)( + uint32_t, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*IndexEnumeratorCallback) + (const PropertyCallbackInfo&); +typedef void(*IndexDeleterCallback)( + uint32_t, + const PropertyCallbackInfo&); +typedef void(*IndexQueryCallback)( + uint32_t, + const PropertyCallbackInfo&); + +namespace imp { +typedef v8::Local Sig; + +static const int kDataIndex = 0; + +static const int kFunctionIndex = 1; +static const int kFunctionFieldCount = 2; + +static const int kGetterIndex = 1; +static const int kSetterIndex = 2; +static const int kAccessorFieldCount = 3; + +static const int kPropertyGetterIndex = 1; +static const int kPropertySetterIndex = 2; +static const int kPropertyEnumeratorIndex = 3; +static const int kPropertyDeleterIndex = 4; +static const int kPropertyQueryIndex = 5; +static const int kPropertyFieldCount = 6; + +static const int kIndexPropertyGetterIndex = 1; +static const int kIndexPropertySetterIndex = 2; +static const int kIndexPropertyEnumeratorIndex = 3; +static const int kIndexPropertyDeleterIndex = 4; +static const int kIndexPropertyQueryIndex = 5; +static const int kIndexPropertyFieldCount = 6; + +} // end of namespace imp + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# include "nan_callbacks_12_inl.h" // NOLINT(build/include) +#else +# include "nan_callbacks_pre_12_inl.h" // NOLINT(build/include) +#endif + +#endif // NAN_CALLBACKS_H_ diff --git a/reverse_engineering/node_modules/nan/nan_callbacks_12_inl.h b/reverse_engineering/node_modules/nan/nan_callbacks_12_inl.h new file mode 100644 index 0000000..c27b18d --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_callbacks_12_inl.h @@ -0,0 +1,514 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_12_INL_H_ +#define NAN_CALLBACKS_12_INL_H_ + +template +class ReturnValue { + v8::ReturnValue value_; + + public: + template + explicit inline ReturnValue(const v8::ReturnValue &value) : + value_(value) {} + template + explicit inline ReturnValue(const ReturnValue& that) + : value_(that.value_) { + TYPE_CHECK(T, S); + } + + // Handle setters + template inline void Set(const v8::Local &handle) { + TYPE_CHECK(T, S); + value_.Set(handle); + } + + template inline void Set(const Global &handle) { + TYPE_CHECK(T, S); +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && \ + (V8_MINOR_VERSION > 5 || (V8_MINOR_VERSION == 5 && \ + defined(V8_BUILD_NUMBER) && V8_BUILD_NUMBER >= 8)))) + value_.Set(handle); +#else + value_.Set(*reinterpret_cast*>(&handle)); + const_cast &>(handle).Reset(); +#endif + } + + // Fast primitive setters + inline void Set(bool value) { + TYPE_CHECK(T, v8::Boolean); + value_.Set(value); + } + + inline void Set(double i) { + TYPE_CHECK(T, v8::Number); + value_.Set(i); + } + + inline void Set(int32_t i) { + TYPE_CHECK(T, v8::Integer); + value_.Set(i); + } + + inline void Set(uint32_t i) { + TYPE_CHECK(T, v8::Integer); + value_.Set(i); + } + + // Fast JS primitive setters + inline void SetNull() { + TYPE_CHECK(T, v8::Primitive); + value_.SetNull(); + } + + inline void SetUndefined() { + TYPE_CHECK(T, v8::Primitive); + value_.SetUndefined(); + } + + inline void SetEmptyString() { + TYPE_CHECK(T, v8::String); + value_.SetEmptyString(); + } + + // Convenience getter for isolate + inline v8::Isolate *GetIsolate() const { + return value_.GetIsolate(); + } + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template + inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } +}; + +template +class FunctionCallbackInfo { + const v8::FunctionCallbackInfo &info_; + const v8::Local data_; + + public: + explicit inline FunctionCallbackInfo( + const v8::FunctionCallbackInfo &info + , v8::Local data) : + info_(info) + , data_(data) {} + + inline ReturnValue GetReturnValue() const { + return ReturnValue(info_.GetReturnValue()); + } + +#if NODE_MAJOR_VERSION < 10 + inline v8::Local Callee() const { return info_.Callee(); } +#endif + inline v8::Local Data() const { return data_; } + inline v8::Local Holder() const { return info_.Holder(); } + inline bool IsConstructCall() const { return info_.IsConstructCall(); } + inline int Length() const { return info_.Length(); } + inline v8::Local operator[](int i) const { return info_[i]; } + inline v8::Local This() const { return info_.This(); } + inline v8::Isolate *GetIsolate() const { return info_.GetIsolate(); } + + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + static const int kArgsLength = 7; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) +}; + +template +class PropertyCallbackInfo { + const v8::PropertyCallbackInfo &info_; + const v8::Local data_; + + public: + explicit inline PropertyCallbackInfo( + const v8::PropertyCallbackInfo &info + , const v8::Local data) : + info_(info) + , data_(data) {} + + inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } + inline v8::Local Data() const { return data_; } + inline v8::Local This() const { return info_.This(); } + inline v8::Local Holder() const { return info_.Holder(); } + inline ReturnValue GetReturnValue() const { + return ReturnValue(info_.GetReturnValue()); + } + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + static const int kArgsLength = 6; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfo) +}; + +namespace imp { +static +void FunctionCallbackWrapper(const v8::FunctionCallbackInfo &info) { + v8::Local obj = info.Data().As(); + FunctionCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kFunctionIndex).As()->Value())); + FunctionCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + callback(cbinfo); +} + +typedef void (*NativeFunction)(const v8::FunctionCallbackInfo &); + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +static +void GetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativeGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property.As(), value, cbinfo); +} + +typedef void (*NativeSetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); +#else +static +void GetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativeGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativeSetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); +#endif + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +static +void PropertyGetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativePropertyGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property.As(), value, cbinfo); +} + +typedef void (*NativePropertySetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void PropertyEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); +} + +typedef void (*NativePropertyEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (NativePropertyDeleter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertyQueryCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativePropertyQuery) + (v8::Local, const v8::PropertyCallbackInfo &); +#else +static +void PropertyGetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativePropertyGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativePropertySetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void PropertyEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); +} + +typedef void (*NativePropertyEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (NativePropertyDeleter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertyQueryCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativePropertyQuery) + (v8::Local, const v8::PropertyCallbackInfo &); +#endif + +static +void IndexGetterCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyGetterIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexGetter) + (uint32_t, const v8::PropertyCallbackInfo &); + +static +void IndexSetterCallbackWrapper( + uint32_t index + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexSetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertySetterIndex) + .As()->Value())); + callback(index, value, cbinfo); +} + +typedef void (*NativeIndexSetter)( + uint32_t + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void IndexEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexEnumeratorCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField( + kIndexPropertyEnumeratorIndex).As()->Value())); + callback(cbinfo); +} + +typedef void (*NativeIndexEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void IndexDeleterCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyDeleterIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexDeleter) + (uint32_t, const v8::PropertyCallbackInfo &); + +static +void IndexQueryCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyQueryIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexQuery) + (uint32_t, const v8::PropertyCallbackInfo &); +} // end of namespace imp + +#endif // NAN_CALLBACKS_12_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_callbacks_pre_12_inl.h b/reverse_engineering/node_modules/nan/nan_callbacks_pre_12_inl.h new file mode 100644 index 0000000..c9ba499 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_callbacks_pre_12_inl.h @@ -0,0 +1,520 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_PRE_12_INL_H_ +#define NAN_CALLBACKS_PRE_12_INL_H_ + +namespace imp { +template class ReturnValueImp; +} // end of namespace imp + +template +class ReturnValue { + v8::Isolate *isolate_; + v8::Persistent *value_; + friend class imp::ReturnValueImp; + + public: + template + explicit inline ReturnValue(v8::Isolate *isolate, v8::Persistent *p) : + isolate_(isolate), value_(p) {} + template + explicit inline ReturnValue(const ReturnValue& that) + : isolate_(that.isolate_), value_(that.value_) { + TYPE_CHECK(T, S); + } + + // Handle setters + template inline void Set(const v8::Local &handle) { + TYPE_CHECK(T, S); + value_->Dispose(); + *value_ = v8::Persistent::New(handle); + } + + template inline void Set(const Global &handle) { + TYPE_CHECK(T, S); + value_->Dispose(); + *value_ = v8::Persistent::New(handle.persistent); + const_cast &>(handle).Reset(); + } + + // Fast primitive setters + inline void Set(bool value) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Boolean); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Boolean::New(value)); + } + + inline void Set(double i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Number); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Number::New(i)); + } + + inline void Set(int32_t i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Integer); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Int32::New(i)); + } + + inline void Set(uint32_t i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Integer); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Uint32::NewFromUnsigned(i)); + } + + // Fast JS primitive setters + inline void SetNull() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Primitive); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Null()); + } + + inline void SetUndefined() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Primitive); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Undefined()); + } + + inline void SetEmptyString() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::String); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::String::Empty()); + } + + // Convenience getter for isolate + inline v8::Isolate *GetIsolate() const { + return isolate_; + } + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template + inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } +}; + +template +class FunctionCallbackInfo { + const v8::Arguments &args_; + v8::Local data_; + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline FunctionCallbackInfo( + const v8::Arguments &args + , v8::Local data) : + args_(args) + , data_(data) + , return_value_(args.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Undefined())) {} + + inline ~FunctionCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return ReturnValue(return_value_); + } + + inline v8::Local Callee() const { return args_.Callee(); } + inline v8::Local Data() const { return data_; } + inline v8::Local Holder() const { return args_.Holder(); } + inline bool IsConstructCall() const { return args_.IsConstructCall(); } + inline int Length() const { return args_.Length(); } + inline v8::Local operator[](int i) const { return args_[i]; } + inline v8::Local This() const { return args_.This(); } + inline v8::Isolate *GetIsolate() const { return args_.GetIsolate(); } + + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + static const int kArgsLength = 7; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) +}; + +template +class PropertyCallbackInfoBase { + const v8::AccessorInfo &info_; + const v8::Local data_; + + public: + explicit inline PropertyCallbackInfoBase( + const v8::AccessorInfo &info + , const v8::Local data) : + info_(info) + , data_(data) {} + + inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } + inline v8::Local Data() const { return data_; } + inline v8::Local This() const { return info_.This(); } + inline v8::Local Holder() const { return info_.Holder(); } + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + static const int kArgsLength = 6; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfoBase) +}; + +template +class PropertyCallbackInfo : public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Undefined())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { return return_value_; } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +namespace imp { +template +class ReturnValueImp : public ReturnValue { + public: + explicit ReturnValueImp(ReturnValue that) : + ReturnValue(that) {} + inline v8::Handle Value() { + return *ReturnValue::value_; + } +}; + +static +v8::Handle FunctionCallbackWrapper(const v8::Arguments &args) { + v8::Local obj = args.Data().As(); + FunctionCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kFunctionIndex).As()->Value())); + FunctionCallbackInfo + cbinfo(args, obj->GetInternalField(kDataIndex)); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeFunction)(const v8::Arguments &); + +static +v8::Handle GetterCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeGetter) + (v8::Local, const v8::AccessorInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativeSetter) + (v8::Local, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyGetterCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyGetter) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property, value, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertySetter) + (v8::Local, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyEnumeratorCallbackWrapper( + const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyEnumerator) + (const v8::AccessorInfo &); + +static +v8::Handle PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (NativePropertyDeleter) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyQueryCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyQuery) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle IndexGetterCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyGetterIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexGetter) + (uint32_t, const v8::AccessorInfo &); + +static +v8::Handle IndexSetterCallbackWrapper( + uint32_t index + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexSetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertySetterIndex) + .As()->Value())); + callback(index, value, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexSetter) + (uint32_t, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle IndexEnumeratorCallbackWrapper( + const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexEnumeratorCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexEnumerator) + (const v8::AccessorInfo &); + +static +v8::Handle IndexDeleterCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyDeleterIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexDeleter) + (uint32_t, const v8::AccessorInfo &); + +static +v8::Handle IndexQueryCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyQueryIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexQuery) + (uint32_t, const v8::AccessorInfo &); +} // end of namespace imp + +#endif // NAN_CALLBACKS_PRE_12_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_converters.h b/reverse_engineering/node_modules/nan/nan_converters.h new file mode 100644 index 0000000..c0b3272 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_converters.h @@ -0,0 +1,72 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_H_ +#define NAN_CONVERTERS_H_ + +namespace imp { +template struct ToFactoryBase { + typedef MaybeLocal return_t; +}; +template struct ValueFactoryBase { typedef Maybe return_t; }; + +template struct ToFactory; + +template<> +struct ToFactory : ToFactoryBase { + static inline return_t convert(v8::Local val) { + if (val.IsEmpty() || !val->IsFunction()) return MaybeLocal(); + return MaybeLocal(val.As()); + } +}; + +#define X(TYPE) \ + template<> \ + struct ToFactory : ToFactoryBase { \ + static inline return_t convert(v8::Local val); \ + }; + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE) \ + template<> \ + struct ToFactory : ValueFactoryBase { \ + static inline return_t convert(v8::Local val); \ + }; + +X(bool) +X(double) +X(int64_t) +X(uint32_t) +X(int32_t) + +#undef X +} // end of namespace imp + +template +inline +typename imp::ToFactory::return_t To(v8::Local val) { + return imp::ToFactory::convert(val); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# include "nan_converters_43_inl.h" +#else +# include "nan_converters_pre_43_inl.h" +#endif + +#endif // NAN_CONVERTERS_H_ diff --git a/reverse_engineering/node_modules/nan/nan_converters_43_inl.h b/reverse_engineering/node_modules/nan/nan_converters_43_inl.h new file mode 100644 index 0000000..41b72de --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_converters_43_inl.h @@ -0,0 +1,68 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_43_INL_H_ +#define NAN_CONVERTERS_43_INL_H_ + +#define X(TYPE) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::EscapableHandleScope scope(isolate); \ + return scope.Escape( \ + val->To ## TYPE(isolate->GetCurrentContext()) \ + .FromMaybe(v8::Local())); \ +} + +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) +// V8 <= 7.0 +#if V8_MAJOR_VERSION < 7 || (V8_MAJOR_VERSION == 7 && V8_MINOR_VERSION == 0) +X(Boolean) +#else +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::EscapableHandleScope scope(isolate); \ + return scope.Escape(val->ToBoolean(isolate)); \ +} +#endif + +#undef X + +#define X(TYPE, NAME) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::HandleScope scope(isolate); \ + return val->NAME ## Value(isolate->GetCurrentContext()); \ +} + +X(double, Number) +X(int64_t, Integer) +X(uint32_t, Uint32) +X(int32_t, Int32) +// V8 <= 7.0 +#if V8_MAJOR_VERSION < 7 || (V8_MAJOR_VERSION == 7 && V8_MINOR_VERSION == 0) +X(bool, Boolean) +#else +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::HandleScope scope(isolate); \ + return Just(val->BooleanValue(isolate)); \ +} +#endif + +#undef X + +#endif // NAN_CONVERTERS_43_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_converters_pre_43_inl.h b/reverse_engineering/node_modules/nan/nan_converters_pre_43_inl.h new file mode 100644 index 0000000..ae0518a --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_converters_pre_43_inl.h @@ -0,0 +1,42 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_PRE_43_INL_H_ +#define NAN_CONVERTERS_PRE_43_INL_H_ + +#define X(TYPE) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + return val->To ## TYPE(); \ +} + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE, NAME) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + return Just(val->NAME ## Value()); \ +} + +X(bool, Boolean) +X(double, Number) +X(int64_t, Integer) +X(uint32_t, Uint32) +X(int32_t, Int32) + +#undef X + +#endif // NAN_CONVERTERS_PRE_43_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_define_own_property_helper.h b/reverse_engineering/node_modules/nan/nan_define_own_property_helper.h new file mode 100644 index 0000000..d710ef2 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_define_own_property_helper.h @@ -0,0 +1,29 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_DEFINE_OWN_PROPERTY_HELPER_H_ +#define NAN_DEFINE_OWN_PROPERTY_HELPER_H_ + +namespace imp { + +inline Maybe DefineOwnPropertyHelper( + v8::PropertyAttribute current + , v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + return !(current & v8::DontDelete) || // configurable OR + (!(current & v8::ReadOnly) && // writable AND + !((attribs ^ current) & ~v8::ReadOnly)) // same excluding RO + ? Just(obj->ForceSet(key, value, attribs)) + : Nothing(); +} + +} // end of namespace imp + +#endif // NAN_DEFINE_OWN_PROPERTY_HELPER_H_ diff --git a/reverse_engineering/node_modules/nan/nan_implementation_12_inl.h b/reverse_engineering/node_modules/nan/nan_implementation_12_inl.h new file mode 100644 index 0000000..255293a --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_implementation_12_inl.h @@ -0,0 +1,430 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_IMPLEMENTATION_12_INL_H_ +#define NAN_IMPLEMENTATION_12_INL_H_ +//============================================================================== +// node v0.11 implementation +//============================================================================== + +namespace imp { + +//=== Array ==================================================================== + +Factory::return_t +Factory::New() { + return v8::Array::New(v8::Isolate::GetCurrent()); +} + +Factory::return_t +Factory::New(int length) { + return v8::Array::New(v8::Isolate::GetCurrent(), length); +} + +//=== Boolean ================================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::Boolean::New(v8::Isolate::GetCurrent(), value); +} + +//=== Boolean Object =========================================================== + +Factory::return_t +Factory::New(bool value) { +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + return v8::BooleanObject::New( + v8::Isolate::GetCurrent(), value).As(); +#else + return v8::BooleanObject::New(value).As(); +#endif +} + +//=== Context ================================================================== + +Factory::return_t +Factory::New( v8::ExtensionConfiguration* extensions + , v8::Local tmpl + , v8::Local obj) { + return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj); +} + +//=== Date ===================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(double value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(v8::Date::New(isolate->GetCurrentContext(), value) + .FromMaybe(v8::Local()).As()); +} +#else +Factory::return_t +Factory::New(double value) { + return v8::Date::New(v8::Isolate::GetCurrent(), value).As(); +} +#endif + +//=== External ================================================================= + +Factory::return_t +Factory::New(void * value) { + return v8::External::New(v8::Isolate::GetCurrent(), value); +} + +//=== Function ================================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(tpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(isolate, reinterpret_cast(callback))); + + v8::Local val = v8::Local::New(isolate, data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + +#if NODE_MAJOR_VERSION >= 10 + v8::Local context = isolate->GetCurrentContext(); + v8::Local function = + v8::Function::New(context, imp::FunctionCallbackWrapper, obj) + .ToLocalChecked(); +#else + v8::Local function = + v8::Function::New(isolate, imp::FunctionCallbackWrapper, obj); +#endif + + return scope.Escape(function); +} + +//=== Function Template ======================================================== + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data + , v8::Local signature) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + if (callback) { + v8::EscapableHandleScope scope(isolate); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(tpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(isolate, reinterpret_cast(callback))); + v8::Local val = v8::Local::New(isolate, data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + return scope.Escape(v8::FunctionTemplate::New( isolate + , imp::FunctionCallbackWrapper + , obj + , signature)); + } else { + return v8::FunctionTemplate::New(isolate, 0, data, signature); + } +} + +//=== Number =================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Number::New(v8::Isolate::GetCurrent(), value); +} + +//=== Number Object ============================================================ + +Factory::return_t +Factory::New(double value) { + return v8::NumberObject::New( v8::Isolate::GetCurrent() + , value).As(); +} + +//=== Integer, Int32 and Uint32 ================================================ + +template +typename IntegerFactory::return_t +IntegerFactory::New(int32_t value) { + return To(T::New(v8::Isolate::GetCurrent(), value)); +} + +template +typename IntegerFactory::return_t +IntegerFactory::New(uint32_t value) { + return To(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +Factory::return_t +Factory::New(int32_t value) { + return To( + v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +Factory::return_t +Factory::New(uint32_t value) { + return To( + v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +//=== Object =================================================================== + +Factory::return_t +Factory::New() { + return v8::Object::New(v8::Isolate::GetCurrent()); +} + +//=== Object Template ========================================================== + +Factory::return_t +Factory::New() { + return v8::ObjectTemplate::New(v8::Isolate::GetCurrent()); +} + +//=== RegExp =================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + v8::RegExp::New(isolate->GetCurrentContext(), pattern, flags) + .FromMaybe(v8::Local())); +} +#else +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); +} +#endif + +//=== Script =================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New( v8::Local source) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source src(source); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src) + .FromMaybe(v8::Local())); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source src(source, origin); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src) + .FromMaybe(v8::Local())); +} +#else +Factory::return_t +Factory::New( v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src); +} +#endif + +//=== Signature ================================================================ + +Factory::return_t +Factory::New(Factory::FTH receiver) { + return v8::Signature::New(v8::Isolate::GetCurrent(), receiver); +} + +//=== String =================================================================== + +Factory::return_t +Factory::New() { + return v8::String::Empty(v8::Isolate::GetCurrent()); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent(), value, v8::NewStringType::kNormal, length); +} + +Factory::return_t +Factory::New(std::string const& value) { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), + value.data(), v8::NewStringType::kNormal, static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value, + v8::NewStringType::kNormal, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternalTwoByte(v8::Isolate::GetCurrent(), value); +} + +Factory::return_t +Factory::New(ExternalOneByteStringResource * value) { + return v8::String::NewExternalOneByte(v8::Isolate::GetCurrent(), value); +} +#else +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); +} + +Factory::return_t +Factory::New( + std::string const& value) /* NOLINT(build/include_what_you_use) */ { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value.data(), + v8::String::kNormalString, + static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), value); +} + +Factory::return_t +Factory::New(ExternalOneByteStringResource * value) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), value); +} +#endif + +//=== String Object ============================================================ + +// See https://github.com/nodejs/nan/pull/811#discussion_r224594980. +// Disable the warning as there is no way around it. +// TODO(bnoordhuis) Use isolate-based version in Node.js v12. +Factory::return_t +Factory::New(v8::Local value) { +// V8 > 7.0 +#if V8_MAJOR_VERSION > 7 || (V8_MAJOR_VERSION == 7 && V8_MINOR_VERSION > 0) + return v8::StringObject::New(v8::Isolate::GetCurrent(), value) + .As(); +#else +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + return v8::StringObject::New(value).As(); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif +} + +//=== Unbound Script =========================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::CompileUnboundScript( + v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::CompileUnboundScript( + v8::Isolate::GetCurrent(), &src); +} +#else +Factory::return_t +Factory::New(v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src); +} +#endif + +} // end of namespace imp + +//=== Presistents and Handles ================================================== + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template +inline v8::Local New(v8::Handle h) { + return v8::Local::New(v8::Isolate::GetCurrent(), h); +} +#endif + +template +inline v8::Local New(v8::Persistent const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +template +inline v8::Local New(Persistent const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +template +inline v8::Local New(Global const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +#endif // NAN_IMPLEMENTATION_12_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_implementation_pre_12_inl.h b/reverse_engineering/node_modules/nan/nan_implementation_pre_12_inl.h new file mode 100644 index 0000000..1472421 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_implementation_pre_12_inl.h @@ -0,0 +1,263 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_ +#define NAN_IMPLEMENTATION_PRE_12_INL_H_ + +//============================================================================== +// node v0.10 implementation +//============================================================================== + +namespace imp { + +//=== Array ==================================================================== + +Factory::return_t +Factory::New() { + return v8::Array::New(); +} + +Factory::return_t +Factory::New(int length) { + return v8::Array::New(length); +} + +//=== Boolean ================================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::Boolean::New(value)->ToBoolean(); +} + +//=== Boolean Object =========================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::BooleanObject::New(value).As(); +} + +//=== Context ================================================================== + +Factory::return_t +Factory::New( v8::ExtensionConfiguration* extensions + , v8::Local tmpl + , v8::Local obj) { + v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); + v8::Local lctx = v8::Local::New(ctx); + ctx.Dispose(); + return lctx; +} + +//=== Date ===================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Date::New(value).As(); +} + +//=== External ================================================================= + +Factory::return_t +Factory::New(void * value) { + return v8::External::New(value); +} + +//=== Function ================================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data) { + v8::HandleScope scope; + + return scope.Close(Factory::New( + callback, data, v8::Local()) + ->GetFunction()); +} + + +//=== FunctionTemplate ========================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data + , v8::Local signature) { + if (callback) { + v8::HandleScope scope; + + v8::Local tpl = v8::ObjectTemplate::New(); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = tpl->NewInstance(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(reinterpret_cast(callback))); + + v8::Local val = v8::Local::New(data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find + // a way. Have at it though... + return scope.Close( + v8::FunctionTemplate::New(imp::FunctionCallbackWrapper + , obj + , signature)); + } else { + return v8::FunctionTemplate::New(0, data, signature); + } +} + +//=== Number =================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Number::New(value); +} + +//=== Number Object ============================================================ + +Factory::return_t +Factory::New(double value) { + return v8::NumberObject::New(value).As(); +} + +//=== Integer, Int32 and Uint32 ================================================ + +template +typename IntegerFactory::return_t +IntegerFactory::New(int32_t value) { + return To(T::New(value)); +} + +template +typename IntegerFactory::return_t +IntegerFactory::New(uint32_t value) { + return To(T::NewFromUnsigned(value)); +} + +Factory::return_t +Factory::New(int32_t value) { + return To(v8::Uint32::NewFromUnsigned(value)); +} + +Factory::return_t +Factory::New(uint32_t value) { + return To(v8::Uint32::NewFromUnsigned(value)); +} + + +//=== Object =================================================================== + +Factory::return_t +Factory::New() { + return v8::Object::New(); +} + +//=== Object Template ========================================================== + +Factory::return_t +Factory::New() { + return v8::ObjectTemplate::New(); +} + +//=== RegExp =================================================================== + +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); +} + +//=== Script =================================================================== + +Factory::return_t +Factory::New( v8::Local source) { + return v8::Script::New(source); +} +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + return v8::Script::New(source, const_cast(&origin)); +} + +//=== Signature ================================================================ + +Factory::return_t +Factory::New(Factory::FTH receiver) { + return v8::Signature::New(receiver); +} + +//=== String =================================================================== + +Factory::return_t +Factory::New() { + return v8::String::Empty(); +} + +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::New(value, length); +} + +Factory::return_t +Factory::New( + std::string const& value) /* NOLINT(build/include_what_you_use) */ { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::New(value.data(), static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::New(value, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternal(value); +} + +Factory::return_t +Factory::New(v8::String::ExternalAsciiStringResource * value) { + return v8::String::NewExternal(value); +} + +//=== String Object ============================================================ + +Factory::return_t +Factory::New(v8::Local value) { + return v8::StringObject::New(value).As(); +} + +} // end of namespace imp + +//=== Presistents and Handles ================================================== + +template +inline v8::Local New(v8::Handle h) { + return v8::Local::New(h); +} + +template +inline v8::Local New(v8::Persistent const& p) { + return v8::Local::New(p); +} + +template +inline v8::Local New(Persistent const& p) { + return v8::Local::New(p.persistent); +} + +template +inline v8::Local New(Global const& p) { + return v8::Local::New(p.persistent); +} + +#endif // NAN_IMPLEMENTATION_PRE_12_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_json.h b/reverse_engineering/node_modules/nan/nan_json.h new file mode 100644 index 0000000..33ac8ba --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_json.h @@ -0,0 +1,166 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_JSON_H_ +#define NAN_JSON_H_ + +#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION +#define NAN_JSON_H_NEED_PARSE 1 +#else +#define NAN_JSON_H_NEED_PARSE 0 +#endif // NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION + +#if NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION +#define NAN_JSON_H_NEED_STRINGIFY 0 +#else +#define NAN_JSON_H_NEED_STRINGIFY 1 +#endif // NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION + +class JSON { + public: + JSON() { +#if NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY + Nan::HandleScope scope; + + Nan::MaybeLocal maybe_global_json = Nan::Get( + Nan::GetCurrentContext()->Global(), + Nan::New("JSON").ToLocalChecked() + ); + + assert(!maybe_global_json.IsEmpty() && "global JSON is empty"); + v8::Local val_global_json = maybe_global_json.ToLocalChecked(); + + assert(val_global_json->IsObject() && "global JSON is not an object"); + Nan::MaybeLocal maybe_obj_global_json = + Nan::To(val_global_json); + + assert(!maybe_obj_global_json.IsEmpty() && "global JSON object is empty"); + v8::Local global_json = maybe_obj_global_json.ToLocalChecked(); + +#if NAN_JSON_H_NEED_PARSE + Nan::MaybeLocal maybe_parse_method = Nan::Get( + global_json, Nan::New("parse").ToLocalChecked() + ); + + assert(!maybe_parse_method.IsEmpty() && "JSON.parse is empty"); + v8::Local parse_method = maybe_parse_method.ToLocalChecked(); + + assert(parse_method->IsFunction() && "JSON.parse is not a function"); + parse_cb_.Reset(parse_method.As()); +#endif // NAN_JSON_H_NEED_PARSE + +#if NAN_JSON_H_NEED_STRINGIFY + Nan::MaybeLocal maybe_stringify_method = Nan::Get( + global_json, Nan::New("stringify").ToLocalChecked() + ); + + assert(!maybe_stringify_method.IsEmpty() && "JSON.stringify is empty"); + v8::Local stringify_method = + maybe_stringify_method.ToLocalChecked(); + + assert( + stringify_method->IsFunction() && "JSON.stringify is not a function" + ); + stringify_cb_.Reset(stringify_method.As()); +#endif // NAN_JSON_H_NEED_STRINGIFY +#endif // NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY + } + + inline + Nan::MaybeLocal Parse(v8::Local json_string) { + Nan::EscapableHandleScope scope; +#if NAN_JSON_H_NEED_PARSE + return scope.Escape(parse(json_string)); +#else + Nan::MaybeLocal result; +#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && \ + NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION + result = v8::JSON::Parse(json_string); +#else +#if NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION + v8::Local context_or_isolate = Nan::GetCurrentContext(); +#else + v8::Isolate* context_or_isolate = v8::Isolate::GetCurrent(); +#endif // NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION + result = v8::JSON::Parse(context_or_isolate, json_string); +#endif // NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && + // NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); +#endif // NAN_JSON_H_NEED_PARSE + } + + inline + Nan::MaybeLocal Stringify(v8::Local json_object) { + Nan::EscapableHandleScope scope; + Nan::MaybeLocal result = +#if NAN_JSON_H_NEED_STRINGIFY + Nan::To(stringify(json_object)); +#else + v8::JSON::Stringify(Nan::GetCurrentContext(), json_object); +#endif // NAN_JSON_H_NEED_STRINGIFY + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); + } + + inline + Nan::MaybeLocal Stringify(v8::Local json_object, + v8::Local gap) { + Nan::EscapableHandleScope scope; + Nan::MaybeLocal result = +#if NAN_JSON_H_NEED_STRINGIFY + Nan::To(stringify(json_object, gap)); +#else + v8::JSON::Stringify(Nan::GetCurrentContext(), json_object, gap); +#endif // NAN_JSON_H_NEED_STRINGIFY + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(JSON) +#if NAN_JSON_H_NEED_PARSE + Nan::Callback parse_cb_; +#endif // NAN_JSON_H_NEED_PARSE +#if NAN_JSON_H_NEED_STRINGIFY + Nan::Callback stringify_cb_; +#endif // NAN_JSON_H_NEED_STRINGIFY + +#if NAN_JSON_H_NEED_PARSE + inline v8::Local parse(v8::Local arg) { + assert(!parse_cb_.IsEmpty() && "parse_cb_ is empty"); + AsyncResource resource("nan:JSON.parse"); + return parse_cb_.Call(1, &arg, &resource).FromMaybe(v8::Local()); + } +#endif // NAN_JSON_H_NEED_PARSE + +#if NAN_JSON_H_NEED_STRINGIFY + inline v8::Local stringify(v8::Local arg) { + assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); + AsyncResource resource("nan:JSON.stringify"); + return stringify_cb_.Call(1, &arg, &resource) + .FromMaybe(v8::Local()); + } + + inline v8::Local stringify(v8::Local arg, + v8::Local gap) { + assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); + + v8::Local argv[] = { + arg, + Nan::Null(), + gap + }; + AsyncResource resource("nan:JSON.stringify"); + return stringify_cb_.Call(3, argv, &resource) + .FromMaybe(v8::Local()); + } +#endif // NAN_JSON_H_NEED_STRINGIFY +}; + +#endif // NAN_JSON_H_ diff --git a/reverse_engineering/node_modules/nan/nan_maybe_43_inl.h b/reverse_engineering/node_modules/nan/nan_maybe_43_inl.h new file mode 100644 index 0000000..c04ce30 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_maybe_43_inl.h @@ -0,0 +1,356 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_MAYBE_43_INL_H_ +#define NAN_MAYBE_43_INL_H_ + +template +using MaybeLocal = v8::MaybeLocal; + +inline +MaybeLocal ToDetailString(v8::Local val) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(val->ToDetailString(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal ToArrayIndex(v8::Local val) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(val->ToArrayIndex(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +Maybe Equals(v8::Local a, v8::Local(b)) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return a->Equals(isolate->GetCurrentContext(), b); +} + +inline +MaybeLocal NewInstance(v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal NewInstance( + v8::Local h + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext(), argc, argv) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal NewInstance(v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + + +inline MaybeLocal GetFunction( + v8::Local t) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(t->GetFunction(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe Set( + v8::Local obj + , v8::Local key + , v8::Local value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Set(isolate->GetCurrentContext(), key, value); +} + +inline Maybe Set( + v8::Local obj + , uint32_t index + , v8::Local value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Set(isolate->GetCurrentContext(), index, value); +} + +#if NODE_MODULE_VERSION < NODE_4_0_MODULE_VERSION +#include "nan_define_own_property_helper.h" // NOLINT(build/include) +#endif + +inline Maybe DefineOwnProperty( + v8::Local obj + , v8::Local key + , v8::Local value + , v8::PropertyAttribute attribs = v8::None) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); +#if NODE_MODULE_VERSION >= NODE_4_0_MODULE_VERSION + return obj->DefineOwnProperty(isolate->GetCurrentContext(), key, value, + attribs); +#else + Maybe maybeCurrent = + obj->GetPropertyAttributes(isolate->GetCurrentContext(), key); + if (maybeCurrent.IsNothing()) { + return Nothing(); + } + v8::PropertyAttribute current = maybeCurrent.FromJust(); + return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs); +#endif +} + +NAN_DEPRECATED inline Maybe ForceSet( + v8::Local obj + , v8::Local key + , v8::Local value + , v8::PropertyAttribute attribs = v8::None) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + return key->IsName() + ? obj->DefineOwnProperty(isolate->GetCurrentContext(), + key.As(), value, attribs) + : Nothing(); +#else + return obj->ForceSet(isolate->GetCurrentContext(), key, value, attribs); +#endif +} + +inline MaybeLocal Get( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->Get(isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal Get(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->Get(isolate->GetCurrentContext(), index) + .FromMaybe(v8::Local())); +} + +inline v8::PropertyAttribute GetPropertyAttributes( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->GetPropertyAttributes(isolate->GetCurrentContext(), key) + .FromJust(); +} + +inline Maybe Has( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Has(isolate->GetCurrentContext(), key); +} + +inline Maybe Has(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Has(isolate->GetCurrentContext(), index); +} + +inline Maybe Delete( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Delete(isolate->GetCurrentContext(), key); +} + +inline +Maybe Delete(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Delete(isolate->GetCurrentContext(), index); +} + +inline +MaybeLocal GetPropertyNames(v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetPropertyNames(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal GetOwnPropertyNames(v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetOwnPropertyNames(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe SetPrototype( + v8::Local obj + , v8::Local prototype) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->SetPrototype(isolate->GetCurrentContext(), prototype); +} + +inline MaybeLocal ObjectProtoToString( + v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->ObjectProtoToString(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe HasOwnProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasOwnProperty(isolate->GetCurrentContext(), key); +} + +inline Maybe HasRealNamedProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealNamedProperty(isolate->GetCurrentContext(), key); +} + +inline Maybe HasRealIndexedProperty( + v8::Local obj + , uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealIndexedProperty(isolate->GetCurrentContext(), index); +} + +inline Maybe HasRealNamedCallbackProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealNamedCallbackProperty(isolate->GetCurrentContext(), key); +} + +inline MaybeLocal GetRealNamedPropertyInPrototypeChain( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetRealNamedPropertyInPrototypeChain( + isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal GetRealNamedProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->GetRealNamedProperty(isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal CallAsFunction( + v8::Local obj + , v8::Local recv + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->CallAsFunction(isolate->GetCurrentContext(), recv, argc, argv) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal CallAsConstructor( + v8::Local obj + , int argc, v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->CallAsConstructor(isolate->GetCurrentContext(), argc, argv) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal GetSourceLine(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(msg->GetSourceLine(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe GetLineNumber(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetLineNumber(isolate->GetCurrentContext()); +} + +inline Maybe GetStartColumn(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetStartColumn(isolate->GetCurrentContext()); +} + +inline Maybe GetEndColumn(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetEndColumn(isolate->GetCurrentContext()); +} + +inline MaybeLocal CloneElementAt( + v8::Local array + , uint32_t index) { +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local elem; + v8::Local obj; + if (!array->Get(context, index).ToLocal(&elem)) { + return scope.Escape(obj); + } + if (!elem->ToObject(context).ToLocal(&obj)) { + return scope.Escape(v8::Local()); + } + return scope.Escape(obj->Clone()); +#else + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(array->CloneElementAt(isolate->GetCurrentContext(), index) + .FromMaybe(v8::Local())); +#endif +} + +inline MaybeLocal Call( + v8::Local fun + , v8::Local recv + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(fun->Call(isolate->GetCurrentContext(), recv, argc, argv) + .FromMaybe(v8::Local())); +} + +#endif // NAN_MAYBE_43_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_maybe_pre_43_inl.h b/reverse_engineering/node_modules/nan/nan_maybe_pre_43_inl.h new file mode 100644 index 0000000..83325ae --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_maybe_pre_43_inl.h @@ -0,0 +1,268 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_MAYBE_PRE_43_INL_H_ +#define NAN_MAYBE_PRE_43_INL_H_ + +template +class MaybeLocal { + public: + inline MaybeLocal() : val_(v8::Local()) {} + + template +# if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION + inline + MaybeLocal(v8::Local that) : val_(that) {} // NOLINT(runtime/explicit) +# else + inline + MaybeLocal(v8::Local that) : // NOLINT(runtime/explicit) + val_(*reinterpret_cast*>(&that)) {} +# endif + + inline bool IsEmpty() const { return val_.IsEmpty(); } + + template + inline bool ToLocal(v8::Local *out) const { + *out = val_; + return !IsEmpty(); + } + + inline v8::Local ToLocalChecked() const { +#if defined(V8_ENABLE_CHECKS) + assert(!IsEmpty() && "ToLocalChecked is Empty"); +#endif // V8_ENABLE_CHECKS + return val_; + } + + template + inline v8::Local FromMaybe(v8::Local default_value) const { + return IsEmpty() ? default_value : v8::Local(val_); + } + + private: + v8::Local val_; +}; + +inline +MaybeLocal ToDetailString(v8::Handle val) { + return MaybeLocal(val->ToDetailString()); +} + +inline +MaybeLocal ToArrayIndex(v8::Handle val) { + return MaybeLocal(val->ToArrayIndex()); +} + +inline +Maybe Equals(v8::Handle a, v8::Handle(b)) { + return Just(a->Equals(b)); +} + +inline +MaybeLocal NewInstance(v8::Handle h) { + return MaybeLocal(h->NewInstance()); +} + +inline +MaybeLocal NewInstance( + v8::Local h + , int argc + , v8::Local argv[]) { + return MaybeLocal(h->NewInstance(argc, argv)); +} + +inline +MaybeLocal NewInstance(v8::Handle h) { + return MaybeLocal(h->NewInstance()); +} + +inline +MaybeLocal GetFunction(v8::Handle t) { + return MaybeLocal(t->GetFunction()); +} + +inline Maybe Set( + v8::Handle obj + , v8::Handle key + , v8::Handle value) { + return Just(obj->Set(key, value)); +} + +inline Maybe Set( + v8::Handle obj + , uint32_t index + , v8::Handle value) { + return Just(obj->Set(index, value)); +} + +#include "nan_define_own_property_helper.h" // NOLINT(build/include) + +inline Maybe DefineOwnProperty( + v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + v8::PropertyAttribute current = obj->GetPropertyAttributes(key); + return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs); +} + +NAN_DEPRECATED inline Maybe ForceSet( + v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + return Just(obj->ForceSet(key, value, attribs)); +} + +inline MaybeLocal Get( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal(obj->Get(key)); +} + +inline MaybeLocal Get( + v8::Handle obj + , uint32_t index) { + return MaybeLocal(obj->Get(index)); +} + +inline Maybe GetPropertyAttributes( + v8::Handle obj + , v8::Handle key) { + return Just(obj->GetPropertyAttributes(key)); +} + +inline Maybe Has( + v8::Handle obj + , v8::Handle key) { + return Just(obj->Has(key)); +} + +inline Maybe Has( + v8::Handle obj + , uint32_t index) { + return Just(obj->Has(index)); +} + +inline Maybe Delete( + v8::Handle obj + , v8::Handle key) { + return Just(obj->Delete(key)); +} + +inline Maybe Delete( + v8::Handle obj + , uint32_t index) { + return Just(obj->Delete(index)); +} + +inline +MaybeLocal GetPropertyNames(v8::Handle obj) { + return MaybeLocal(obj->GetPropertyNames()); +} + +inline +MaybeLocal GetOwnPropertyNames(v8::Handle obj) { + return MaybeLocal(obj->GetOwnPropertyNames()); +} + +inline Maybe SetPrototype( + v8::Handle obj + , v8::Handle prototype) { + return Just(obj->SetPrototype(prototype)); +} + +inline MaybeLocal ObjectProtoToString( + v8::Handle obj) { + return MaybeLocal(obj->ObjectProtoToString()); +} + +inline Maybe HasOwnProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasOwnProperty(key)); +} + +inline Maybe HasRealNamedProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasRealNamedProperty(key)); +} + +inline Maybe HasRealIndexedProperty( + v8::Handle obj + , uint32_t index) { + return Just(obj->HasRealIndexedProperty(index)); +} + +inline Maybe HasRealNamedCallbackProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasRealNamedCallbackProperty(key)); +} + +inline MaybeLocal GetRealNamedPropertyInPrototypeChain( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal( + obj->GetRealNamedPropertyInPrototypeChain(key)); +} + +inline MaybeLocal GetRealNamedProperty( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal(obj->GetRealNamedProperty(key)); +} + +inline MaybeLocal CallAsFunction( + v8::Handle obj + , v8::Handle recv + , int argc + , v8::Handle argv[]) { + return MaybeLocal(obj->CallAsFunction(recv, argc, argv)); +} + +inline MaybeLocal CallAsConstructor( + v8::Handle obj + , int argc + , v8::Local argv[]) { + return MaybeLocal(obj->CallAsConstructor(argc, argv)); +} + +inline +MaybeLocal GetSourceLine(v8::Handle msg) { + return MaybeLocal(msg->GetSourceLine()); +} + +inline Maybe GetLineNumber(v8::Handle msg) { + return Just(msg->GetLineNumber()); +} + +inline Maybe GetStartColumn(v8::Handle msg) { + return Just(msg->GetStartColumn()); +} + +inline Maybe GetEndColumn(v8::Handle msg) { + return Just(msg->GetEndColumn()); +} + +inline MaybeLocal CloneElementAt( + v8::Handle array + , uint32_t index) { + return MaybeLocal(array->CloneElementAt(index)); +} + +inline MaybeLocal Call( + v8::Local fun + , v8::Local recv + , int argc + , v8::Local argv[]) { + return MaybeLocal(fun->Call(recv, argc, argv)); +} + +#endif // NAN_MAYBE_PRE_43_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_new.h b/reverse_engineering/node_modules/nan/nan_new.h new file mode 100644 index 0000000..cdf8bbe --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_new.h @@ -0,0 +1,340 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_NEW_H_ +#define NAN_NEW_H_ + +namespace imp { // scnr + +// TODO(agnat): Generalize +template v8::Local To(v8::Local i); + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template struct FactoryBase { + typedef v8::Local return_t; +}; + +template struct MaybeFactoryBase { + typedef MaybeLocal return_t; +}; + +template struct Factory; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); + static inline return_t New(int length); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(bool value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(bool value); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( v8::ExtensionConfiguration* extensions = NULL + , v8::Local tmpl = v8::Local() + , v8::Local obj = v8::Local()); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New(double value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(void *value); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( FunctionCallback callback + , v8::Local data = v8::Local()); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( FunctionCallback callback = NULL + , v8::Local data = v8::Local() + , v8::Local signature = v8::Local()); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(double value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(double value); +}; + +template +struct IntegerFactory : FactoryBase { + typedef typename FactoryBase::return_t return_t; + static inline return_t New(int32_t value); + static inline return_t New(uint32_t value); +}; + +template <> +struct Factory : IntegerFactory {}; + +template <> +struct Factory : IntegerFactory {}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(int32_t value); + static inline return_t New(uint32_t value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( + v8::Local pattern, v8::RegExp::Flags flags); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( v8::Local source); + static inline return_t New( v8::Local source + , v8::ScriptOrigin const& origin); +}; + +template <> +struct Factory : FactoryBase { + typedef v8::Local FTH; + static inline return_t New(FTH receiver = FTH()); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New(); + static inline return_t New(const char *value, int length = -1); + static inline return_t New(const uint16_t *value, int length = -1); + static inline return_t New(std::string const& value); + + static inline return_t New(v8::String::ExternalStringResource * value); + static inline return_t New(ExternalOneByteStringResource * value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(v8::Local value); +}; + +} // end of namespace imp + +#if (NODE_MODULE_VERSION >= 12) + +namespace imp { + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( v8::Local source); + static inline return_t New( v8::Local source + , v8::ScriptOrigin const& origin); +}; + +} // end of namespace imp + +# include "nan_implementation_12_inl.h" + +#else // NODE_MODULE_VERSION >= 12 + +# include "nan_implementation_pre_12_inl.h" + +#endif + +//=== API ====================================================================== + +template +typename imp::Factory::return_t +New() { + return imp::Factory::New(); +} + +template +typename imp::Factory::return_t +New(A0 arg0) { + return imp::Factory::New(arg0); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1) { + return imp::Factory::New(arg0, arg1); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1, A2 arg2) { + return imp::Factory::New(arg0, arg1, arg2); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1, A2 arg2, A3 arg3) { + return imp::Factory::New(arg0, arg1, arg2, arg3); +} + +// Note(agnat): When passing overloaded function pointers to template functions +// as generic arguments the compiler needs help in picking the right overload. +// These two functions handle New and New with +// all argument variations. + +// v8::Function and v8::FunctionTemplate with one or two arguments +template +typename imp::Factory::return_t +New( FunctionCallback callback + , v8::Local data = v8::Local()) { + return imp::Factory::New(callback, data); +} + +// v8::Function and v8::FunctionTemplate with three arguments +template +typename imp::Factory::return_t +New( FunctionCallback callback + , v8::Local data = v8::Local() + , A2 a2 = A2()) { + return imp::Factory::New(callback, data, a2); +} + +// Convenience + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template inline v8::Local New(v8::Handle h); +#endif + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +template + inline v8::Local New(v8::Persistent const& p); +#else +template inline v8::Local New(v8::Persistent const& p); +#endif +template +inline v8::Local New(Persistent const& p); +template +inline v8::Local New(Global const& p); + +inline +imp::Factory::return_t +New(bool value) { + return New(value); +} + +inline +imp::Factory::return_t +New(int32_t value) { + return New(value); +} + +inline +imp::Factory::return_t +New(uint32_t value) { + return New(value); +} + +inline +imp::Factory::return_t +New(double value) { + return New(value); +} + +inline +imp::Factory::return_t +New(std::string const& value) { // NOLINT(build/include_what_you_use) + return New(value); +} + +inline +imp::Factory::return_t +New(const char * value, int length) { + return New(value, length); +} + +inline +imp::Factory::return_t +New(const uint16_t * value, int length) { + return New(value, length); +} + +inline +imp::Factory::return_t +New(const char * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(const uint16_t * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(v8::String::ExternalStringResource * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(ExternalOneByteStringResource * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(v8::Local pattern, v8::RegExp::Flags flags) { + return New(pattern, flags); +} + +#endif // NAN_NEW_H_ diff --git a/reverse_engineering/node_modules/nan/nan_object_wrap.h b/reverse_engineering/node_modules/nan/nan_object_wrap.h new file mode 100644 index 0000000..78712f9 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_object_wrap.h @@ -0,0 +1,156 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_OBJECT_WRAP_H_ +#define NAN_OBJECT_WRAP_H_ + +class ObjectWrap { + public: + ObjectWrap() { + refs_ = 0; + } + + + virtual ~ObjectWrap() { + if (persistent().IsEmpty()) { + return; + } + + persistent().ClearWeak(); + persistent().Reset(); + } + + + template + static inline T* Unwrap(v8::Local object) { + assert(!object.IsEmpty()); + assert(object->InternalFieldCount() > 0); + // Cast to ObjectWrap before casting to T. A direct cast from void + // to T won't work right when T has more than one base class. + void* ptr = GetInternalFieldPointer(object, 0); + ObjectWrap* wrap = static_cast(ptr); + return static_cast(wrap); + } + + + inline v8::Local handle() const { + return New(handle_); + } + + + inline Persistent& persistent() { + return handle_; + } + + + protected: + inline void Wrap(v8::Local object) { + assert(persistent().IsEmpty()); + assert(object->InternalFieldCount() > 0); + SetInternalFieldPointer(object, 0, this); + persistent().Reset(object); + MakeWeak(); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + inline void MakeWeak() { + persistent().v8::PersistentBase::SetWeak( + this, WeakCallback, v8::WeakCallbackType::kParameter); +#if NODE_MAJOR_VERSION < 10 + // FIXME(bnoordhuis) Probably superfluous in older Node.js versions too. + persistent().MarkIndependent(); +#endif + } + +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + + inline void MakeWeak() { + persistent().v8::PersistentBase::SetWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + +#else + + inline void MakeWeak() { + persistent().persistent.MakeWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + +#endif + + /* Ref() marks the object as being attached to an event loop. + * Refed objects will not be garbage collected, even if + * all references are lost. + */ + virtual void Ref() { + assert(!persistent().IsEmpty()); + persistent().ClearWeak(); + refs_++; + } + + /* Unref() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" means an object that only has a + * persistent handle.) + * + * DO NOT CALL THIS FROM DESTRUCTOR + */ + virtual void Unref() { + assert(!persistent().IsEmpty()); + assert(!persistent().IsWeak()); + assert(refs_ > 0); + if (--refs_ == 0) + MakeWeak(); + } + + int refs_; // ro + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap) +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + static void + WeakCallback(v8::WeakCallbackInfo const& info) { + ObjectWrap* wrap = info.GetParameter(); + assert(wrap->refs_ == 0); + wrap->handle_.Reset(); + delete wrap; + } + +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + + static void + WeakCallback(v8::WeakCallbackData const& data) { + ObjectWrap* wrap = data.GetParameter(); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#else + + static void WeakCallback(v8::Persistent value, void *data) { + ObjectWrap *wrap = static_cast(data); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#endif + Persistent handle_; +}; + + +#endif // NAN_OBJECT_WRAP_H_ diff --git a/reverse_engineering/node_modules/nan/nan_persistent_12_inl.h b/reverse_engineering/node_modules/nan/nan_persistent_12_inl.h new file mode 100644 index 0000000..d9649e8 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_persistent_12_inl.h @@ -0,0 +1,132 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PERSISTENT_12_INL_H_ +#define NAN_PERSISTENT_12_INL_H_ + +template class Persistent : + public v8::Persistent { + public: + inline Persistent() : v8::Persistent() {} + + template inline Persistent(v8::Local that) : + v8::Persistent(v8::Isolate::GetCurrent(), that) {} + + template + inline + Persistent(const v8::Persistent &that) : // NOLINT(runtime/explicit) + v8::Persistent(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type); + + private: + inline T *operator*() const { return *PersistentBase::persistent; } + + template + inline void Copy(const Persistent &that) { + TYPE_CHECK(T, S); + + this->Reset(); + + if (!that.IsEmpty()) { + this->Reset(that); + M::Copy(that, this); + } + } +}; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +template +class Global : public v8::Global { + public: + inline Global() : v8::Global() {} + + template inline Global(v8::Local that) : + v8::Global(v8::Isolate::GetCurrent(), that) {} + + template + inline + Global(const v8::PersistentBase &that) : // NOLINT(runtime/explicit) + v8::Global(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + reinterpret_cast*>(this)->SetWeak( + parameter, callback, type); + } +}; +#else +template +class Global : public v8::UniquePersistent { + public: + inline Global() : v8::UniquePersistent() {} + + template inline Global(v8::Local that) : + v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} + + template + inline + Global(const v8::PersistentBase &that) : // NOLINT(runtime/explicit) + v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + reinterpret_cast*>(this)->SetWeak( + parameter, callback, type); + } +}; +#endif + +#endif // NAN_PERSISTENT_12_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_persistent_pre_12_inl.h b/reverse_engineering/node_modules/nan/nan_persistent_pre_12_inl.h new file mode 100644 index 0000000..4c9c59d --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_persistent_pre_12_inl.h @@ -0,0 +1,242 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PERSISTENT_PRE_12_INL_H_ +#define NAN_PERSISTENT_PRE_12_INL_H_ + +template +class PersistentBase { + v8::Persistent persistent; + template + friend v8::Local New(const PersistentBase &p); + template + friend v8::Local New(const Persistent &p); + template + friend v8::Local New(const Global &p); + template friend class ReturnValue; + + public: + inline PersistentBase() : + persistent() {} + + inline void Reset() { + persistent.Dispose(); + persistent.Clear(); + } + + template + inline void Reset(const v8::Local &other) { + TYPE_CHECK(T, S); + + if (!persistent.IsEmpty()) { + persistent.Dispose(); + } + + if (other.IsEmpty()) { + persistent.Clear(); + } else { + persistent = v8::Persistent::New(other); + } + } + + template + inline void Reset(const PersistentBase &other) { + TYPE_CHECK(T, S); + + if (!persistent.IsEmpty()) { + persistent.Dispose(); + } + + if (other.IsEmpty()) { + persistent.Clear(); + } else { + persistent = v8::Persistent::New(other.persistent); + } + } + + inline bool IsEmpty() const { return persistent.IsEmpty(); } + + inline void Empty() { persistent.Clear(); } + + template + inline bool operator==(const PersistentBase &that) const { + return this->persistent == that.persistent; + } + + template + inline bool operator==(const v8::Local &that) const { + return this->persistent == that; + } + + template + inline bool operator!=(const PersistentBase &that) const { + return !operator==(that); + } + + template + inline bool operator!=(const v8::Local &that) const { + return !operator==(that); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type); + + inline void ClearWeak() { persistent.ClearWeak(); } + + inline void MarkIndependent() { persistent.MarkIndependent(); } + + inline bool IsIndependent() const { return persistent.IsIndependent(); } + + inline bool IsNearDeath() const { return persistent.IsNearDeath(); } + + inline bool IsWeak() const { return persistent.IsWeak(); } + + private: + inline explicit PersistentBase(v8::Persistent that) : + persistent(that) { } + inline explicit PersistentBase(T *val) : persistent(val) {} + template friend class Persistent; + template friend class Global; + friend class ObjectWrap; +}; + +template +class NonCopyablePersistentTraits { + public: + typedef Persistent > + NonCopyablePersistent; + static const bool kResetInDestructor = false; + template + inline static void Copy(const Persistent &source, + NonCopyablePersistent *dest) { + Uncompilable(); + } + + template inline static void Uncompilable() { + TYPE_CHECK(O, v8::Primitive); + } +}; + +template +struct CopyablePersistentTraits { + typedef Persistent > CopyablePersistent; + static const bool kResetInDestructor = true; + template + static inline void Copy(const Persistent &source, + CopyablePersistent *dest) {} +}; + +template class Persistent : + public PersistentBase { + public: + inline Persistent() {} + + template inline Persistent(v8::Handle that) + : PersistentBase(v8::Persistent::New(that)) { + TYPE_CHECK(T, S); + } + + inline Persistent(const Persistent &that) : PersistentBase() { + Copy(that); + } + + template + inline Persistent(const Persistent &that) : + PersistentBase() { + Copy(that); + } + + inline Persistent &operator=(const Persistent &that) { + Copy(that); + return *this; + } + + template + inline Persistent &operator=(const Persistent &that) { + Copy(that); + return *this; + } + + inline ~Persistent() { + if (M::kResetInDestructor) this->Reset(); + } + + private: + inline T *operator*() const { return *PersistentBase::persistent; } + + template + inline void Copy(const Persistent &that) { + TYPE_CHECK(T, S); + + this->Reset(); + + if (!that.IsEmpty()) { + this->persistent = v8::Persistent::New(that.persistent); + M::Copy(that, this); + } + } +}; + +template +class Global : public PersistentBase { + struct RValue { + inline explicit RValue(Global* obj) : object(obj) {} + Global* object; + }; + + public: + inline Global() : PersistentBase(0) { } + + template + inline Global(v8::Local that) // NOLINT(runtime/explicit) + : PersistentBase(v8::Persistent::New(that)) { + TYPE_CHECK(T, S); + } + + template + inline Global(const PersistentBase &that) // NOLINT(runtime/explicit) + : PersistentBase(that) { + TYPE_CHECK(T, S); + } + /** + * Move constructor. + */ + inline Global(RValue rvalue) // NOLINT(runtime/explicit) + : PersistentBase(rvalue.object->persistent) { + rvalue.object->Reset(); + } + inline ~Global() { this->Reset(); } + /** + * Move via assignment. + */ + template + inline Global &operator=(Global rhs) { + TYPE_CHECK(T, S); + this->Reset(rhs.persistent); + rhs.Reset(); + return *this; + } + /** + * Cast operator for moves. + */ + inline operator RValue() { return RValue(this); } + /** + * Pass allows returning uniques from functions, etc. + */ + Global Pass() { return Global(RValue(this)); } + + private: + Global(Global &); + void operator=(Global &); + template friend class ReturnValue; +}; + +#endif // NAN_PERSISTENT_PRE_12_INL_H_ diff --git a/reverse_engineering/node_modules/nan/nan_private.h b/reverse_engineering/node_modules/nan/nan_private.h new file mode 100644 index 0000000..15f44cc --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_private.h @@ -0,0 +1,73 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PRIVATE_H_ +#define NAN_PRIVATE_H_ + +inline Maybe +HasPrivate(v8::Local object, v8::Local key) { + HandleScope scope; +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->HasPrivate(context, private_key); +#else + return Just(!object->GetHiddenValue(key).IsEmpty()); +#endif +} + +inline MaybeLocal +GetPrivate(v8::Local object, v8::Local key) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + v8::MaybeLocal v = object->GetPrivate(context, private_key); + return scope.Escape(v.ToLocalChecked()); +#else + EscapableHandleScope scope; + v8::Local v = object->GetHiddenValue(key); + if (v.IsEmpty()) { + v = Undefined(); + } + return scope.Escape(v); +#endif +} + +inline Maybe SetPrivate( + v8::Local object, + v8::Local key, + v8::Local value) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + HandleScope scope; + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->SetPrivate(context, private_key, value); +#else + return Just(object->SetHiddenValue(key, value)); +#endif +} + +inline Maybe DeletePrivate( + v8::Local object, + v8::Local key) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + HandleScope scope; + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->DeletePrivate(isolate->GetCurrentContext(), private_key); +#else + return Just(object->DeleteHiddenValue(key)); +#endif +} + +#endif // NAN_PRIVATE_H_ + diff --git a/reverse_engineering/node_modules/nan/nan_scriptorigin.h b/reverse_engineering/node_modules/nan/nan_scriptorigin.h new file mode 100644 index 0000000..ce79cdf --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_scriptorigin.h @@ -0,0 +1,76 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2021 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_SCRIPTORIGIN_H_ +#define NAN_SCRIPTORIGIN_H_ + +class ScriptOrigin : public v8::ScriptOrigin { + public: +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 9 || \ + (V8_MAJOR_VERSION == 9 && (defined(V8_MINOR_VERSION) && (V8_MINOR_VERSION > 0\ + || (V8_MINOR_VERSION == 0 && defined(V8_BUILD_NUMBER) \ + && V8_BUILD_NUMBER >= 1))))) + explicit ScriptOrigin(v8::Local name) : + v8::ScriptOrigin(v8::Isolate::GetCurrent(), name) {} + + ScriptOrigin(v8::Local name + , v8::Local line) : + v8::ScriptOrigin(v8::Isolate::GetCurrent() + , name + , To(line).FromMaybe(0)) {} + + ScriptOrigin(v8::Local name + , v8::Local line + , v8::Local column) : + v8::ScriptOrigin(v8::Isolate::GetCurrent() + , name + , To(line).FromMaybe(0) + , To(column).FromMaybe(0)) {} +#elif defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 8 || \ + (V8_MAJOR_VERSION == 8 && (defined(V8_MINOR_VERSION) && (V8_MINOR_VERSION > 9\ + || (V8_MINOR_VERSION == 9 && defined(V8_BUILD_NUMBER) \ + && V8_BUILD_NUMBER >= 45))))) + explicit ScriptOrigin(v8::Local name) : v8::ScriptOrigin(name) {} + + ScriptOrigin(v8::Local name + , v8::Local line) : + v8::ScriptOrigin(name, To(line).FromMaybe(0)) {} + + ScriptOrigin(v8::Local name + , v8::Local line + , v8::Local column) : + v8::ScriptOrigin(name + , To(line).FromMaybe(0) + , To(column).FromMaybe(0)) {} +#else + explicit ScriptOrigin(v8::Local name) : v8::ScriptOrigin(name) {} + + ScriptOrigin(v8::Local name + , v8::Local line) : v8::ScriptOrigin(name, line) {} + + ScriptOrigin(v8::Local name + , v8::Local line + , v8::Local column) : + v8::ScriptOrigin(name, line, column) {} +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 8 || \ + (V8_MAJOR_VERSION == 8 && (defined(V8_MINOR_VERSION) && (V8_MINOR_VERSION > 9\ + || (V8_MINOR_VERSION == 9 && defined(V8_BUILD_NUMBER) \ + && V8_BUILD_NUMBER >= 45))))) + v8::Local ResourceLineOffset() const { + return New(LineOffset()); + } + + v8::Local ResourceColumnOffset() const { + return New(ColumnOffset()); + } +#endif +}; + +#endif // NAN_SCRIPTORIGIN_H_ diff --git a/reverse_engineering/node_modules/nan/nan_string_bytes.h b/reverse_engineering/node_modules/nan/nan_string_bytes.h new file mode 100644 index 0000000..a2e6437 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_string_bytes.h @@ -0,0 +1,305 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef NAN_STRING_BYTES_H_ +#define NAN_STRING_BYTES_H_ + +// Decodes a v8::Local or Buffer to a raw char* + +namespace imp { + +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; + + +//// Base 64 //// + +#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) + + + +//// HEX //// + +static bool contains_non_ascii_slow(const char* buf, size_t len) { + for (size_t i = 0; i < len; ++i) { + if (buf[i] & 0x80) return true; + } + return false; +} + + +static bool contains_non_ascii(const char* src, size_t len) { + if (len < 16) { + return contains_non_ascii_slow(src, len); + } + + const unsigned bytes_per_word = sizeof(void*); + const unsigned align_mask = bytes_per_word - 1; + const unsigned unaligned = reinterpret_cast(src) & align_mask; + + if (unaligned > 0) { + const unsigned n = bytes_per_word - unaligned; + if (contains_non_ascii_slow(src, n)) return true; + src += n; + len -= n; + } + + +#if defined(__x86_64__) || defined(_WIN64) + const uintptr_t mask = 0x8080808080808080ll; +#else + const uintptr_t mask = 0x80808080l; +#endif + + const uintptr_t* srcw = reinterpret_cast(src); + + for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { + if (srcw[i] & mask) return true; + } + + const unsigned remainder = len & align_mask; + if (remainder > 0) { + const size_t offset = len - remainder; + if (contains_non_ascii_slow(src + offset, remainder)) return true; + } + + return false; +} + + +static void force_ascii_slow(const char* src, char* dst, size_t len) { + for (size_t i = 0; i < len; ++i) { + dst[i] = src[i] & 0x7f; + } +} + + +static void force_ascii(const char* src, char* dst, size_t len) { + if (len < 16) { + force_ascii_slow(src, dst, len); + return; + } + + const unsigned bytes_per_word = sizeof(void*); + const unsigned align_mask = bytes_per_word - 1; + const unsigned src_unalign = reinterpret_cast(src) & align_mask; + const unsigned dst_unalign = reinterpret_cast(dst) & align_mask; + + if (src_unalign > 0) { + if (src_unalign == dst_unalign) { + const unsigned unalign = bytes_per_word - src_unalign; + force_ascii_slow(src, dst, unalign); + src += unalign; + dst += unalign; + len -= src_unalign; + } else { + force_ascii_slow(src, dst, len); + return; + } + } + +#if defined(__x86_64__) || defined(_WIN64) + const uintptr_t mask = ~0x8080808080808080ll; +#else + const uintptr_t mask = ~0x80808080l; +#endif + + const uintptr_t* srcw = reinterpret_cast(src); + uintptr_t* dstw = reinterpret_cast(dst); + + for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { + dstw[i] = srcw[i] & mask; + } + + const unsigned remainder = len & align_mask; + if (remainder > 0) { + const size_t offset = len - remainder; + force_ascii_slow(src + offset, dst + offset, remainder); + } +} + + +static size_t base64_encode(const char* src, + size_t slen, + char* dst, + size_t dlen) { + // We know how much we'll write, just make sure that there's space. + assert(dlen >= base64_encoded_size(slen) && + "not enough space provided for base64 encode"); + + dlen = base64_encoded_size(slen); + + unsigned a; + unsigned b; + unsigned c; + unsigned i; + unsigned k; + unsigned n; + + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + i = 0; + k = 0; + n = slen / 3 * 3; + + while (i < n) { + a = src[i + 0] & 0xff; + b = src[i + 1] & 0xff; + c = src[i + 2] & 0xff; + + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[((a & 3) << 4) | (b >> 4)]; + dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)]; + dst[k + 3] = table[c & 0x3f]; + + i += 3; + k += 4; + } + + if (n != slen) { + switch (slen - n) { + case 1: + a = src[i + 0] & 0xff; + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[(a & 3) << 4]; + dst[k + 2] = '='; + dst[k + 3] = '='; + break; + + case 2: + a = src[i + 0] & 0xff; + b = src[i + 1] & 0xff; + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[((a & 3) << 4) | (b >> 4)]; + dst[k + 2] = table[(b & 0x0f) << 2]; + dst[k + 3] = '='; + break; + } + } + + return dlen; +} + + +static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) { + // We know how much we'll write, just make sure that there's space. + assert(dlen >= slen * 2 && + "not enough space provided for hex encode"); + + dlen = slen * 2; + for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) { + static const char hex[] = "0123456789abcdef"; + uint8_t val = static_cast(src[i]); + dst[k + 0] = hex[val >> 4]; + dst[k + 1] = hex[val & 15]; + } + + return dlen; +} + + + +static Local Encode(const char* buf, + size_t buflen, + enum Encoding encoding) { + assert(buflen <= node::Buffer::kMaxLength); + if (!buflen && encoding != BUFFER) + return New("").ToLocalChecked(); + + Local val; + switch (encoding) { + case BUFFER: + return CopyBuffer(buf, buflen).ToLocalChecked(); + + case ASCII: + if (contains_non_ascii(buf, buflen)) { + char* out = new char[buflen]; + force_ascii(buf, out, buflen); + val = New(out, buflen).ToLocalChecked(); + delete[] out; + } else { + val = New(buf, buflen).ToLocalChecked(); + } + break; + + case UTF8: + val = New(buf, buflen).ToLocalChecked(); + break; + + case BINARY: { + // TODO(isaacs) use ExternalTwoByteString? + const unsigned char *cbuf = reinterpret_cast(buf); + uint16_t * twobytebuf = new uint16_t[buflen]; + for (size_t i = 0; i < buflen; i++) { + // XXX is the following line platform independent? + twobytebuf[i] = cbuf[i]; + } + val = New(twobytebuf, buflen).ToLocalChecked(); + delete[] twobytebuf; + break; + } + + case BASE64: { + size_t dlen = base64_encoded_size(buflen); + char* dst = new char[dlen]; + + size_t written = base64_encode(buf, buflen, dst, dlen); + assert(written == dlen); + + val = New(dst, dlen).ToLocalChecked(); + delete[] dst; + break; + } + + case UCS2: { + const uint16_t* data = reinterpret_cast(buf); + val = New(data, buflen / 2).ToLocalChecked(); + break; + } + + case HEX: { + size_t dlen = buflen * 2; + char* dst = new char[dlen]; + size_t written = hex_encode(buf, buflen, dst, dlen); + assert(written == dlen); + + val = New(dst, dlen).ToLocalChecked(); + delete[] dst; + break; + } + + default: + assert(0 && "unknown encoding"); + break; + } + + return val; +} + +#undef base64_encoded_size + +} // end of namespace imp + +#endif // NAN_STRING_BYTES_H_ diff --git a/reverse_engineering/node_modules/nan/nan_typedarray_contents.h b/reverse_engineering/node_modules/nan/nan_typedarray_contents.h new file mode 100644 index 0000000..c6ac8a4 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_typedarray_contents.h @@ -0,0 +1,96 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_TYPEDARRAY_CONTENTS_H_ +#define NAN_TYPEDARRAY_CONTENTS_H_ + +template +class TypedArrayContents { + public: + inline explicit TypedArrayContents(v8::Local from) : + length_(0), data_(NULL) { + HandleScope scope; + + size_t length = 0; + void* data = NULL; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + if (from->IsArrayBufferView()) { + v8::Local array = + v8::Local::Cast(from); + + const size_t byte_length = array->ByteLength(); + const ptrdiff_t byte_offset = array->ByteOffset(); + v8::Local buffer = array->Buffer(); + + length = byte_length / sizeof(T); +// Actually it's 7.9 here but this would lead to ABI issues with Node.js 13 +// using 7.8 till 13.2.0. +#if (V8_MAJOR_VERSION >= 8) + data = static_cast(buffer->GetBackingStore()->Data()) + byte_offset; +#else + data = static_cast(buffer->GetContents().Data()) + byte_offset; +#endif + } + +#else + + if (from->IsObject() && !from->IsNull()) { + v8::Local array = v8::Local::Cast(from); + + MaybeLocal buffer = Get(array, + New("buffer").ToLocalChecked()); + MaybeLocal byte_length = Get(array, + New("byteLength").ToLocalChecked()); + MaybeLocal byte_offset = Get(array, + New("byteOffset").ToLocalChecked()); + + if (!buffer.IsEmpty() && + !byte_length.IsEmpty() && byte_length.ToLocalChecked()->IsUint32() && + !byte_offset.IsEmpty() && byte_offset.ToLocalChecked()->IsUint32()) { + data = array->GetIndexedPropertiesExternalArrayData(); + if(data) { + length = byte_length.ToLocalChecked()->Uint32Value() / sizeof(T); + } + } + } + +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1900 || __cplusplus >= 201103L + assert(reinterpret_cast(data) % alignof (T) == 0); +#elif defined(_MSC_VER) && _MSC_VER >= 1600 || defined(__GNUC__) + assert(reinterpret_cast(data) % __alignof(T) == 0); +#else + assert(reinterpret_cast(data) % sizeof (T) == 0); +#endif + + length_ = length; + data_ = static_cast(data); + } + + inline size_t length() const { return length_; } + inline T* operator*() { return data_; } + inline const T* operator*() const { return data_; } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(TypedArrayContents) + + //Disable heap allocation + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } + + size_t length_; + T* data_; +}; + +#endif // NAN_TYPEDARRAY_CONTENTS_H_ diff --git a/reverse_engineering/node_modules/nan/nan_weak.h b/reverse_engineering/node_modules/nan/nan_weak.h new file mode 100644 index 0000000..7e7ab07 --- /dev/null +++ b/reverse_engineering/node_modules/nan/nan_weak.h @@ -0,0 +1,437 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_WEAK_H_ +#define NAN_WEAK_H_ + +static const int kInternalFieldsInWeakCallback = 2; +static const int kNoInternalFieldIndex = -1; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::WeakCallbackInfo > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::PhantomCallbackData > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::PhantomCallbackData > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + v8::InternalFieldsCallbackData, void> const& +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# define NAN_WEAK_CALLBACK_DATA_TYPE_ \ + v8::WeakCallbackData > const& +# define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_ +#else +# define NAN_WEAK_CALLBACK_DATA_TYPE_ void * +# define NAN_WEAK_CALLBACK_SIG_ \ + v8::Persistent, NAN_WEAK_CALLBACK_DATA_TYPE_ +#endif + +template +class WeakCallbackInfo { + public: + typedef void (*Callback)(const WeakCallbackInfo& data); + WeakCallbackInfo( + Persistent *persistent + , Callback callback + , void *parameter + , void *field1 = 0 + , void *field2 = 0) : + callback_(callback), isolate_(0), parameter_(parameter) { + std::memcpy(&persistent_, persistent, sizeof (v8::Persistent)); + internal_fields_[0] = field1; + internal_fields_[1] = field2; + } + inline v8::Isolate *GetIsolate() const { return isolate_; } + inline T *GetParameter() const { return static_cast(parameter_); } + inline void *GetInternalField(int index) const { + assert((index == 0 || index == 1) && "internal field index out of bounds"); + if (index == 0) { + return internal_fields_[0]; + } else { + return internal_fields_[1]; + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo) + Callback callback_; + v8::Isolate *isolate_; + void *parameter_; + void *internal_fields_[kInternalFieldsInWeakCallback]; + v8::Persistent persistent_; + template friend class Persistent; + template friend class PersistentBase; +#if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION +# if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + template + static void invoke(NAN_WEAK_CALLBACK_SIG_ data); + template + static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); +# else + static void invoke(NAN_WEAK_CALLBACK_SIG_ data); + static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); +# endif +#else +# if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + template + static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); + template + static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); +# else + static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); + static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); +# endif + static WeakCallbackInfo *unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data); + static WeakCallbackInfo *unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data); +#endif +}; + + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + +template +template +void +WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrapparameter(data); + if (isFirstPass) { + cbinfo->persistent_.Reset(); + data.SetSecondPassCallback(invokeparameter); + } else { + cbinfo->callback_(*cbinfo); + delete cbinfo; + } +} + +template +template +void +WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwraptwofield(data); + if (isFirstPass) { + cbinfo->persistent_.Reset(); + data.SetSecondPassCallback(invoketwofield); + } else { + cbinfo->callback_(*cbinfo); + delete cbinfo; + } +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetParameter()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetInternalField(0)); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ +#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +# elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + +template +void +WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrapparameter(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +void +WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwraptwofield(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetParameter()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetInternalField1()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ +#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + +template +template +void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrap(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +template +WeakCallbackInfo *WeakCallbackInfo::unwrap( + NAN_WEAK_CALLBACK_DATA_TYPE_ data) { + void *parameter = data.GetParameter(); + WeakCallbackInfo *cbinfo = + static_cast*>(parameter); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_CALLBACK_SIG_ +#undef NAN_WEAK_CALLBACK_DATA_TYPE_ +#else + +template +void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrap(data); + cbinfo->persistent_.Dispose(); + cbinfo->persistent_.Clear(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrap( + NAN_WEAK_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data); + cbinfo->isolate_ = v8::Isolate::GetCurrent(); + return cbinfo; +} + +#undef NAN_WEAK_CALLBACK_SIG_ +#undef NAN_WEAK_CALLBACK_DATA_TYPE_ +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetWeak( + wcbd + , WeakCallbackInfo

::template invokeparameter + , type); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + self->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetWeak( + static_cast*>(0) + , WeakCallbackInfo

::template invoketwofield + , type); + } +} +#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetPhantom( + wcbd + , WeakCallbackInfo

::invokeparameter); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + self->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetPhantom( + static_cast*>(0) + , WeakCallbackInfo

::invoketwofield + , 0 + , count > 1 ? 1 : kNoInternalFieldIndex); + } +} +#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetPhantom( + wcbd + , WeakCallbackInfo

::invokeparameter); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + self->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetPhantom( + WeakCallbackInfo

::invoketwofield + , 0 + , count > 1 ? 1 : kNoInternalFieldIndex); + } +} +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + } +} +#else +template +template +inline void PersistentBase::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); + } +} +#endif + +#endif // NAN_WEAK_H_ diff --git a/reverse_engineering/node_modules/nan/package.json b/reverse_engineering/node_modules/nan/package.json new file mode 100644 index 0000000..e09b8a5 --- /dev/null +++ b/reverse_engineering/node_modules/nan/package.json @@ -0,0 +1,99 @@ +{ + "_from": "nan@^2.15.0", + "_id": "nan@2.15.0", + "_inBundle": false, + "_integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "_location": "/nan", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "nan@^2.15.0", + "name": "nan", + "escapedName": "nan", + "rawSpec": "^2.15.0", + "saveSpec": null, + "fetchSpec": "^2.15.0" + }, + "_requiredBy": [ + "/cpu-features", + "/ssh2" + ], + "_resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "_shasum": "3f34a473ff18e15c1b5626b62903b5ad6e665fee", + "_spec": "nan@^2.15.0", + "_where": "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/ssh2", + "bugs": { + "url": "https://github.com/nodejs/nan/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "Benjamin Byholm", + "email": "bbyholm@abo.fi", + "url": "https://github.com/kkoopa/" + }, + { + "name": "Trevor Norris", + "email": "trev.norris@gmail.com", + "url": "https://github.com/trevnorris" + }, + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "https://github.com/TooTallNate" + }, + { + "name": "Brett Lawson", + "email": "brett19@gmail.com", + "url": "https://github.com/brett19" + }, + { + "name": "Ben Noordhuis", + "email": "info@bnoordhuis.nl", + "url": "https://github.com/bnoordhuis" + }, + { + "name": "David Siegel", + "email": "david@artcom.de", + "url": "https://github.com/agnat" + }, + { + "name": "Michael Ira Krufky", + "email": "mkrufky@gmail.com", + "url": "https://github.com/mkrufky" + } + ], + "deprecated": false, + "description": "Native Abstractions for Node.js: C++ header for Node 0.8 -> 14 compatibility", + "devDependencies": { + "bindings": "~1.2.1", + "commander": "^2.8.1", + "glob": "^5.0.14", + "node-gyp": "~3.6.2", + "readable-stream": "^2.1.4", + "request": "=2.81.0", + "tap": "~0.7.1", + "xtend": "~4.0.0" + }, + "homepage": "https://github.com/nodejs/nan#readme", + "license": "MIT", + "main": "include_dirs.js", + "name": "nan", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/nan.git" + }, + "scripts": { + "docs": "doc/.build.sh", + "rebuild-tests": "node-gyp rebuild --msvs_version=2015 --directory test", + "test": "tap --gc --stderr test/js/*-test.js", + "test:worker": "node --experimental-worker test/tap-as-worker.js --gc --stderr test/js/*-test.js" + }, + "version": "2.15.0" +} diff --git a/reverse_engineering/node_modules/nan/tools/1to2.js b/reverse_engineering/node_modules/nan/tools/1to2.js new file mode 100755 index 0000000..6af2505 --- /dev/null +++ b/reverse_engineering/node_modules/nan/tools/1to2.js @@ -0,0 +1,412 @@ +#!/usr/bin/env node +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +var commander = require('commander'), + fs = require('fs'), + glob = require('glob'), + groups = [], + total = 0, + warning1 = '/* ERROR: Rewrite using Buffer */\n', + warning2 = '\\/\\* ERROR\\: Rewrite using Buffer \\*\\/\\n', + length, + i; + +fs.readFile(__dirname + '/package.json', 'utf8', function (err, data) { + if (err) { + throw err; + } + + commander + .version(JSON.parse(data).version) + .usage('[options] ') + .parse(process.argv); + + if (!process.argv.slice(2).length) { + commander.outputHelp(); + } +}); + +/* construct strings representing regular expressions + each expression contains a unique group allowing for identification of the match + the index of this key group, relative to the regular expression in question, + is indicated by the first array member */ + +/* simple substistutions, key group is the entire match, 0 */ +groups.push([0, [ + '_NAN_', + 'NODE_SET_METHOD', + 'NODE_SET_PROTOTYPE_METHOD', + 'NanAsciiString', + 'NanEscapeScope', + 'NanReturnValue', + 'NanUcs2String'].join('|')]); + +/* substitutions of parameterless macros, key group is 1 */ +groups.push([1, ['(', [ + 'NanEscapableScope', + 'NanReturnNull', + 'NanReturnUndefined', + 'NanScope'].join('|'), ')\\(\\)'].join('')]); + +/* replace TryCatch with NanTryCatch once, gobbling possible namespace, key group 2 */ +groups.push([2, '(?:(?:v8\\:\\:)?|(Nan)?)(TryCatch)']); + +/* NanNew("string") will likely not fail a ToLocalChecked(), key group 1 */ +groups.push([1, ['(NanNew)', '(\\("[^\\"]*"[^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]); + +/* Removed v8 APIs, warn that the code needs rewriting using node::Buffer, key group 2 */ +groups.push([2, ['(', warning2, ')?', '^.*?(', [ + 'GetIndexedPropertiesExternalArrayDataLength', + 'GetIndexedPropertiesExternalArrayData', + 'GetIndexedPropertiesExternalArrayDataType', + 'GetIndexedPropertiesPixelData', + 'GetIndexedPropertiesPixelDataLength', + 'HasIndexedPropertiesInExternalArrayData', + 'HasIndexedPropertiesInPixelData', + 'SetIndexedPropertiesToExternalArrayData', + 'SetIndexedPropertiesToPixelData'].join('|'), ')'].join('')]); + +/* No need for NanScope in V8-exposed methods, key group 2 */ +groups.push([2, ['((', [ + 'NAN_METHOD', + 'NAN_GETTER', + 'NAN_SETTER', + 'NAN_PROPERTY_GETTER', + 'NAN_PROPERTY_SETTER', + 'NAN_PROPERTY_ENUMERATOR', + 'NAN_PROPERTY_DELETER', + 'NAN_PROPERTY_QUERY', + 'NAN_INDEX_GETTER', + 'NAN_INDEX_SETTER', + 'NAN_INDEX_ENUMERATOR', + 'NAN_INDEX_DELETER', + 'NAN_INDEX_QUERY'].join('|'), ')\\([^\\)]*\\)\\s*\\{)\\s*NanScope\\(\\)\\s*;'].join('')]); + +/* v8::Value::ToXXXXXXX returns v8::MaybeLocal, key group 3 */ +groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->(', [ + 'Boolean', + 'Number', + 'String', + 'Object', + 'Integer', + 'Uint32', + 'Int32'].join('|'), ')\\('].join('')]); + +/* v8::Value::XXXXXXXValue returns v8::Maybe, key group 3 */ +groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->((?:', [ + 'Boolean', + 'Number', + 'Integer', + 'Uint32', + 'Int32'].join('|'), ')Value)\\('].join('')]); + +/* NAN_WEAK_CALLBACK macro was removed, write out callback definition, key group 1 */ +groups.push([1, '(NAN_WEAK_CALLBACK)\\(([^\\s\\)]+)\\)']); + +/* node::ObjectWrap and v8::Persistent have been replaced with Nan implementations, key group 1 */ +groups.push([1, ['(', [ + 'NanDisposePersistent', + 'NanObjectWrapHandle'].join('|'), ')\\s*\\(\\s*([^\\s\\)]+)'].join('')]); + +/* Since NanPersistent there is no need for NanMakeWeakPersistent, key group 1 */ +groups.push([1, '(NanMakeWeakPersistent)\\s*\\(\\s*([^\\s,]+)\\s*,\\s*']); + +/* Many methods of v8::Object and others now return v8::MaybeLocal, key group 3 */ +groups.push([3, ['([\\s])([^\\s]+)->(', [ + 'GetEndColumn', + 'GetFunction', + 'GetLineNumber', + 'NewInstance', + 'GetPropertyNames', + 'GetOwnPropertyNames', + 'GetSourceLine', + 'GetStartColumn', + 'ObjectProtoToString', + 'ToArrayIndex', + 'ToDetailString', + 'CallAsConstructor', + 'CallAsFunction', + 'CloneElementAt', + 'Delete', + 'ForceSet', + 'Get', + 'GetPropertyAttributes', + 'GetRealNamedProperty', + 'GetRealNamedPropertyInPrototypeChain', + 'Has', + 'HasOwnProperty', + 'HasRealIndexedProperty', + 'HasRealNamedCallbackProperty', + 'HasRealNamedProperty', + 'Set', + 'SetAccessor', + 'SetIndexedPropertyHandler', + 'SetNamedPropertyHandler', + 'SetPrototype'].join('|'), ')\\('].join('')]); + +/* You should get an error if any of these fail anyways, + or handle the error better, it is indicated either way, key group 2 */ +groups.push([2, ['NanNew(<(?:v8\\:\\:)?(', ['Date', 'String', 'RegExp'].join('|'), ')>)(\\([^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]); + +/* v8::Value::Equals now returns a v8::Maybe, key group 3 */ +groups.push([3, '([\\s\\(\\)])([^\\s\\(\\)]+)->(Equals)\\(([^\\s\\)]+)']); + +/* NanPersistent makes this unnecessary, key group 1 */ +groups.push([1, '(NanAssignPersistent)(?:]+>)?\\(([^,]+),\\s*']); + +/* args has been renamed to info, key group 2 */ +groups.push([2, '(\\W)(args)(\\W)']) + +/* node::ObjectWrap was replaced with NanObjectWrap, key group 2 */ +groups.push([2, '(\\W)(?:node\\:\\:)?(ObjectWrap)(\\W)']); + +/* v8::Persistent was replaced with NanPersistent, key group 2 */ +groups.push([2, '(\\W)(?:v8\\:\\:)?(Persistent)(\\W)']); + +/* counts the number of capturing groups in a well-formed regular expression, + ignoring non-capturing groups and escaped parentheses */ +function groupcount(s) { + var positive = s.match(/\((?!\?)/g), + negative = s.match(/\\\(/g); + return (positive ? positive.length : 0) - (negative ? negative.length : 0); +} + +/* compute the absolute position of each key group in the joined master RegExp */ +for (i = 1, length = groups.length; i < length; i++) { + total += groupcount(groups[i - 1][1]); + groups[i][0] += total; +} + +/* create the master RegExp, whis is the union of all the groups' expressions */ +master = new RegExp(groups.map(function (a) { return a[1]; }).join('|'), 'gm'); + +/* replacement function for String.replace, receives 21 arguments */ +function replace() { + /* simple expressions */ + switch (arguments[groups[0][0]]) { + case '_NAN_': + return 'NAN_'; + case 'NODE_SET_METHOD': + return 'NanSetMethod'; + case 'NODE_SET_PROTOTYPE_METHOD': + return 'NanSetPrototypeMethod'; + case 'NanAsciiString': + return 'NanUtf8String'; + case 'NanEscapeScope': + return 'scope.Escape'; + case 'NanReturnNull': + return 'info.GetReturnValue().SetNull'; + case 'NanReturnValue': + return 'info.GetReturnValue().Set'; + case 'NanUcs2String': + return 'v8::String::Value'; + default: + } + + /* macros without arguments */ + switch (arguments[groups[1][0]]) { + case 'NanEscapableScope': + return 'NanEscapableScope scope' + case 'NanReturnUndefined': + return 'return'; + case 'NanScope': + return 'NanScope scope'; + default: + } + + /* TryCatch, emulate negative backref */ + if (arguments[groups[2][0]] === 'TryCatch') { + return arguments[groups[2][0] - 1] ? arguments[0] : 'NanTryCatch'; + } + + /* NanNew("foo") --> NanNew("foo").ToLocalChecked() */ + if (arguments[groups[3][0]] === 'NanNew') { + return [arguments[0], '.ToLocalChecked()'].join(''); + } + + /* insert warning for removed functions as comment on new line above */ + switch (arguments[groups[4][0]]) { + case 'GetIndexedPropertiesExternalArrayData': + case 'GetIndexedPropertiesExternalArrayDataLength': + case 'GetIndexedPropertiesExternalArrayDataType': + case 'GetIndexedPropertiesPixelData': + case 'GetIndexedPropertiesPixelDataLength': + case 'HasIndexedPropertiesInExternalArrayData': + case 'HasIndexedPropertiesInPixelData': + case 'SetIndexedPropertiesToExternalArrayData': + case 'SetIndexedPropertiesToPixelData': + return arguments[groups[4][0] - 1] ? arguments[0] : [warning1, arguments[0]].join(''); + default: + } + + /* remove unnecessary NanScope() */ + switch (arguments[groups[5][0]]) { + case 'NAN_GETTER': + case 'NAN_METHOD': + case 'NAN_SETTER': + case 'NAN_INDEX_DELETER': + case 'NAN_INDEX_ENUMERATOR': + case 'NAN_INDEX_GETTER': + case 'NAN_INDEX_QUERY': + case 'NAN_INDEX_SETTER': + case 'NAN_PROPERTY_DELETER': + case 'NAN_PROPERTY_ENUMERATOR': + case 'NAN_PROPERTY_GETTER': + case 'NAN_PROPERTY_QUERY': + case 'NAN_PROPERTY_SETTER': + return arguments[groups[5][0] - 1]; + default: + } + + /* Value conversion */ + switch (arguments[groups[6][0]]) { + case 'Boolean': + case 'Int32': + case 'Integer': + case 'Number': + case 'Object': + case 'String': + case 'Uint32': + return [arguments[groups[6][0] - 2], 'NanTo(', arguments[groups[6][0] - 1]].join(''); + default: + } + + /* other value conversion */ + switch (arguments[groups[7][0]]) { + case 'BooleanValue': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'Int32Value': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'IntegerValue': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'Uint32Value': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + default: + } + + /* NAN_WEAK_CALLBACK */ + if (arguments[groups[8][0]] === 'NAN_WEAK_CALLBACK') { + return ['template\nvoid ', + arguments[groups[8][0] + 1], '(const NanWeakCallbackInfo &data)'].join(''); + } + + /* use methods on NAN classes instead */ + switch (arguments[groups[9][0]]) { + case 'NanDisposePersistent': + return [arguments[groups[9][0] + 1], '.Reset('].join(''); + case 'NanObjectWrapHandle': + return [arguments[groups[9][0] + 1], '->handle('].join(''); + default: + } + + /* use method on NanPersistent instead */ + if (arguments[groups[10][0]] === 'NanMakeWeakPersistent') { + return arguments[groups[10][0] + 1] + '.SetWeak('; + } + + /* These return Maybes, the upper ones take no arguments */ + switch (arguments[groups[11][0]]) { + case 'GetEndColumn': + case 'GetFunction': + case 'GetLineNumber': + case 'GetOwnPropertyNames': + case 'GetPropertyNames': + case 'GetSourceLine': + case 'GetStartColumn': + case 'NewInstance': + case 'ObjectProtoToString': + case 'ToArrayIndex': + case 'ToDetailString': + return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1]].join(''); + case 'CallAsConstructor': + case 'CallAsFunction': + case 'CloneElementAt': + case 'Delete': + case 'ForceSet': + case 'Get': + case 'GetPropertyAttributes': + case 'GetRealNamedProperty': + case 'GetRealNamedPropertyInPrototypeChain': + case 'Has': + case 'HasOwnProperty': + case 'HasRealIndexedProperty': + case 'HasRealNamedCallbackProperty': + case 'HasRealNamedProperty': + case 'Set': + case 'SetAccessor': + case 'SetIndexedPropertyHandler': + case 'SetNamedPropertyHandler': + case 'SetPrototype': + return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1], ', '].join(''); + default: + } + + /* Automatic ToLocalChecked(), take it or leave it */ + switch (arguments[groups[12][0]]) { + case 'Date': + case 'String': + case 'RegExp': + return ['NanNew', arguments[groups[12][0] - 1], arguments[groups[12][0] + 1], '.ToLocalChecked()'].join(''); + default: + } + + /* NanEquals is now required for uniformity */ + if (arguments[groups[13][0]] === 'Equals') { + return [arguments[groups[13][0] - 1], 'NanEquals(', arguments[groups[13][0] - 1], ', ', arguments[groups[13][0] + 1]].join(''); + } + + /* use method on replacement class instead */ + if (arguments[groups[14][0]] === 'NanAssignPersistent') { + return [arguments[groups[14][0] + 1], '.Reset('].join(''); + } + + /* args --> info */ + if (arguments[groups[15][0]] === 'args') { + return [arguments[groups[15][0] - 1], 'info', arguments[groups[15][0] + 1]].join(''); + } + + /* ObjectWrap --> NanObjectWrap */ + if (arguments[groups[16][0]] === 'ObjectWrap') { + return [arguments[groups[16][0] - 1], 'NanObjectWrap', arguments[groups[16][0] + 1]].join(''); + } + + /* Persistent --> NanPersistent */ + if (arguments[groups[17][0]] === 'Persistent') { + return [arguments[groups[17][0] - 1], 'NanPersistent', arguments[groups[17][0] + 1]].join(''); + } + + /* This should not happen. A switch is probably missing a case if it does. */ + throw 'Unhandled match: ' + arguments[0]; +} + +/* reads a file, runs replacement and writes it back */ +function processFile(file) { + fs.readFile(file, {encoding: 'utf8'}, function (err, data) { + if (err) { + throw err; + } + + /* run replacement twice, might need more runs */ + fs.writeFile(file, data.replace(master, replace).replace(master, replace), function (err) { + if (err) { + throw err; + } + }); + }); +} + +/* process file names from command line and process the identified files */ +for (i = 2, length = process.argv.length; i < length; i++) { + glob(process.argv[i], function (err, matches) { + if (err) { + throw err; + } + matches.forEach(processFile); + }); +} diff --git a/reverse_engineering/node_modules/nan/tools/README.md b/reverse_engineering/node_modules/nan/tools/README.md new file mode 100644 index 0000000..7f07e4b --- /dev/null +++ b/reverse_engineering/node_modules/nan/tools/README.md @@ -0,0 +1,14 @@ +1to2 naively converts source code files from NAN 1 to NAN 2. There will be erroneous conversions, +false positives and missed opportunities. The input files are rewritten in place. Make sure that +you have backups. You will have to manually review the changes afterwards and do some touchups. + +```sh +$ tools/1to2.js + + Usage: 1to2 [options] + + Options: + + -h, --help output usage information + -V, --version output the version number +``` diff --git a/reverse_engineering/node_modules/nan/tools/package.json b/reverse_engineering/node_modules/nan/tools/package.json new file mode 100644 index 0000000..2dcdd78 --- /dev/null +++ b/reverse_engineering/node_modules/nan/tools/package.json @@ -0,0 +1,19 @@ +{ + "name": "1to2", + "version": "1.0.0", + "description": "NAN 1 -> 2 Migration Script", + "main": "1to2.js", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/nan.git" + }, + "contributors": [ + "Benjamin Byholm (https://github.com/kkoopa/)", + "Mathias Küsel (https://github.com/mathiask88/)" + ], + "dependencies": { + "glob": "~5.0.10", + "commander": "~2.8.1" + }, + "license": "MIT" +} diff --git a/reverse_engineering/node_modules/semver/CHANGELOG.md b/reverse_engineering/node_modules/semver/CHANGELOG.md deleted file mode 100644 index 66304fd..0000000 --- a/reverse_engineering/node_modules/semver/CHANGELOG.md +++ /dev/null @@ -1,39 +0,0 @@ -# changes log - -## 5.7 - -* Add `minVersion` method - -## 5.6 - -* Move boolean `loose` param to an options object, with - backwards-compatibility protection. -* Add ability to opt out of special prerelease version handling with - the `includePrerelease` option flag. - -## 5.5 - -* Add version coercion capabilities - -## 5.4 - -* Add intersection checking - -## 5.3 - -* Add `minSatisfying` method - -## 5.2 - -* Add `prerelease(v)` that returns prerelease components - -## 5.1 - -* Add Backus-Naur for ranges -* Remove excessively cute inspection methods - -## 5.0 - -* Remove AMD/Browserified build artifacts -* Fix ltr and gtr when using the `*` range -* Fix for range `*` with a prerelease identifier diff --git a/reverse_engineering/node_modules/semver/LICENSE b/reverse_engineering/node_modules/semver/LICENSE deleted file mode 100644 index 19129e3..0000000 --- a/reverse_engineering/node_modules/semver/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/reverse_engineering/node_modules/semver/README.md b/reverse_engineering/node_modules/semver/README.md deleted file mode 100644 index f8dfa5a..0000000 --- a/reverse_engineering/node_modules/semver/README.md +++ /dev/null @@ -1,412 +0,0 @@ -semver(1) -- The semantic versioner for npm -=========================================== - -## Install - -```bash -npm install --save semver -```` - -## Usage - -As a node module: - -```js -const semver = require('semver') - -semver.valid('1.2.3') // '1.2.3' -semver.valid('a.b.c') // null -semver.clean(' =v1.2.3 ') // '1.2.3' -semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true -semver.gt('1.2.3', '9.8.7') // false -semver.lt('1.2.3', '9.8.7') // true -semver.minVersion('>=1.0.0') // '1.0.0' -semver.valid(semver.coerce('v2')) // '2.0.0' -semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' -``` - -As a command-line utility: - -``` -$ semver -h - -A JavaScript implementation of the https://semver.org/ specification -Copyright Isaac Z. Schlueter - -Usage: semver [options] [ [...]] -Prints valid versions sorted by SemVer precedence - -Options: --r --range - Print versions that match the specified range. - --i --increment [] - Increment a version by the specified level. Level can - be one of: major, minor, patch, premajor, preminor, - prepatch, or prerelease. Default level is 'patch'. - Only one version may be specified. - ---preid - Identifier to be used to prefix premajor, preminor, - prepatch or prerelease version increments. - --l --loose - Interpret versions and ranges loosely - --p --include-prerelease - Always include prerelease versions in range matching - --c --coerce - Coerce a string into SemVer if possible - (does not imply --loose) - -Program exits successfully if any valid version satisfies -all supplied ranges, and prints all satisfying versions. - -If no satisfying versions are found, then exits failure. - -Versions are printed in ascending order, so supplying -multiple versions to the utility will just sort them. -``` - -## Versions - -A "version" is described by the `v2.0.0` specification found at -. - -A leading `"="` or `"v"` character is stripped off and ignored. - -## Ranges - -A `version range` is a set of `comparators` which specify versions -that satisfy the range. - -A `comparator` is composed of an `operator` and a `version`. The set -of primitive `operators` is: - -* `<` Less than -* `<=` Less than or equal to -* `>` Greater than -* `>=` Greater than or equal to -* `=` Equal. If no operator is specified, then equality is assumed, - so this operator is optional, but MAY be included. - -For example, the comparator `>=1.2.7` would match the versions -`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` -or `1.1.0`. - -Comparators can be joined by whitespace to form a `comparator set`, -which is satisfied by the **intersection** of all of the comparators -it includes. - -A range is composed of one or more comparator sets, joined by `||`. A -version matches a range if and only if every comparator in at least -one of the `||`-separated comparator sets is satisfied by the version. - -For example, the range `>=1.2.7 <1.3.0` would match the versions -`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, -or `1.1.0`. - -The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, -`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. - -### Prerelease Tags - -If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then -it will only be allowed to satisfy comparator sets if at least one -comparator with the same `[major, minor, patch]` tuple also has a -prerelease tag. - -For example, the range `>1.2.3-alpha.3` would be allowed to match the -version `1.2.3-alpha.7`, but it would *not* be satisfied by -`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater -than" `1.2.3-alpha.3` according to the SemVer sort rules. The version -range only accepts prerelease tags on the `1.2.3` version. The -version `3.4.5` *would* satisfy the range, because it does not have a -prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. - -The purpose for this behavior is twofold. First, prerelease versions -frequently are updated very quickly, and contain many breaking changes -that are (by the author's design) not yet fit for public consumption. -Therefore, by default, they are excluded from range matching -semantics. - -Second, a user who has opted into using a prerelease version has -clearly indicated the intent to use *that specific* set of -alpha/beta/rc versions. By including a prerelease tag in the range, -the user is indicating that they are aware of the risk. However, it -is still not appropriate to assume that they have opted into taking a -similar risk on the *next* set of prerelease versions. - -Note that this behavior can be suppressed (treating all prerelease -versions as if they were normal versions, for the purpose of range -matching) by setting the `includePrerelease` flag on the options -object to any -[functions](https://github.com/npm/node-semver#functions) that do -range matching. - -#### Prerelease Identifiers - -The method `.inc` takes an additional `identifier` string argument that -will append the value of the string as a prerelease identifier: - -```javascript -semver.inc('1.2.3', 'prerelease', 'beta') -// '1.2.4-beta.0' -``` - -command-line example: - -```bash -$ semver 1.2.3 -i prerelease --preid beta -1.2.4-beta.0 -``` - -Which then can be used to increment further: - -```bash -$ semver 1.2.4-beta.0 -i prerelease -1.2.4-beta.1 -``` - -### Advanced Range Syntax - -Advanced range syntax desugars to primitive comparators in -deterministic ways. - -Advanced ranges may be combined in the same way as primitive -comparators using white space or `||`. - -#### Hyphen Ranges `X.Y.Z - A.B.C` - -Specifies an inclusive set. - -* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` - -If a partial version is provided as the first version in the inclusive -range, then the missing pieces are replaced with zeroes. - -* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` - -If a partial version is provided as the second version in the -inclusive range, then all versions that start with the supplied parts -of the tuple are accepted, but nothing that would be greater than the -provided tuple parts. - -* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` -* `1.2.3 - 2` := `>=1.2.3 <3.0.0` - -#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` - -Any of `X`, `x`, or `*` may be used to "stand in" for one of the -numeric values in the `[major, minor, patch]` tuple. - -* `*` := `>=0.0.0` (Any version satisfies) -* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) -* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) - -A partial version range is treated as an X-Range, so the special -character is in fact optional. - -* `""` (empty string) := `*` := `>=0.0.0` -* `1` := `1.x.x` := `>=1.0.0 <2.0.0` -* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` - -#### Tilde Ranges `~1.2.3` `~1.2` `~1` - -Allows patch-level changes if a minor version is specified on the -comparator. Allows minor-level changes if not. - -* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` -* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) -* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) -* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` -* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) -* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) -* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in - the `1.2.3` version will be allowed, if they are greater than or - equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but - `1.2.4-beta.2` would not, because it is a prerelease of a - different `[major, minor, patch]` tuple. - -#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` - -Allows changes that do not modify the left-most non-zero digit in the -`[major, minor, patch]` tuple. In other words, this allows patch and -minor updates for versions `1.0.0` and above, patch updates for -versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. - -Many authors treat a `0.x` version as if the `x` were the major -"breaking-change" indicator. - -Caret ranges are ideal when an author may make breaking changes -between `0.2.4` and `0.3.0` releases, which is a common practice. -However, it presumes that there will *not* be breaking changes between -`0.2.4` and `0.2.5`. It allows for changes that are presumed to be -additive (but non-breaking), according to commonly observed practices. - -* `^1.2.3` := `>=1.2.3 <2.0.0` -* `^0.2.3` := `>=0.2.3 <0.3.0` -* `^0.0.3` := `>=0.0.3 <0.0.4` -* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in - the `1.2.3` version will be allowed, if they are greater than or - equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but - `1.2.4-beta.2` would not, because it is a prerelease of a - different `[major, minor, patch]` tuple. -* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the - `0.0.3` version *only* will be allowed, if they are greater than or - equal to `beta`. So, `0.0.3-pr.2` would be allowed. - -When parsing caret ranges, a missing `patch` value desugars to the -number `0`, but will allow flexibility within that value, even if the -major and minor versions are both `0`. - -* `^1.2.x` := `>=1.2.0 <2.0.0` -* `^0.0.x` := `>=0.0.0 <0.1.0` -* `^0.0` := `>=0.0.0 <0.1.0` - -A missing `minor` and `patch` values will desugar to zero, but also -allow flexibility within those values, even if the major version is -zero. - -* `^1.x` := `>=1.0.0 <2.0.0` -* `^0.x` := `>=0.0.0 <1.0.0` - -### Range Grammar - -Putting all this together, here is a Backus-Naur grammar for ranges, -for the benefit of parser authors: - -```bnf -range-set ::= range ( logical-or range ) * -logical-or ::= ( ' ' ) * '||' ( ' ' ) * -range ::= hyphen | simple ( ' ' simple ) * | '' -hyphen ::= partial ' - ' partial -simple ::= primitive | partial | tilde | caret -primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial -partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? -xr ::= 'x' | 'X' | '*' | nr -nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * -tilde ::= '~' partial -caret ::= '^' partial -qualifier ::= ( '-' pre )? ( '+' build )? -pre ::= parts -build ::= parts -parts ::= part ( '.' part ) * -part ::= nr | [-0-9A-Za-z]+ -``` - -## Functions - -All methods and classes take a final `options` object argument. All -options in this object are `false` by default. The options supported -are: - -- `loose` Be more forgiving about not-quite-valid semver strings. - (Any resulting output will always be 100% strict compliant, of - course.) For backwards compatibility reasons, if the `options` - argument is a boolean value instead of an object, it is interpreted - to be the `loose` param. -- `includePrerelease` Set to suppress the [default - behavior](https://github.com/npm/node-semver#prerelease-tags) of - excluding prerelease tagged versions from ranges unless they are - explicitly opted into. - -Strict-mode Comparators and Ranges will be strict about the SemVer -strings that they parse. - -* `valid(v)`: Return the parsed version, or null if it's not valid. -* `inc(v, release)`: Return the version incremented by the release - type (`major`, `premajor`, `minor`, `preminor`, `patch`, - `prepatch`, or `prerelease`), or null if it's not valid - * `premajor` in one call will bump the version up to the next major - version and down to a prerelease of that major version. - `preminor`, and `prepatch` work the same way. - * If called from a non-prerelease version, the `prerelease` will work the - same as `prepatch`. It increments the patch version, then makes a - prerelease. If the input version is already a prerelease it simply - increments it. -* `prerelease(v)`: Returns an array of prerelease components, or null - if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` -* `major(v)`: Return the major version number. -* `minor(v)`: Return the minor version number. -* `patch(v)`: Return the patch version number. -* `intersects(r1, r2, loose)`: Return true if the two supplied ranges - or comparators intersect. -* `parse(v)`: Attempt to parse a string as a semantic version, returning either - a `SemVer` object or `null`. - -### Comparison - -* `gt(v1, v2)`: `v1 > v2` -* `gte(v1, v2)`: `v1 >= v2` -* `lt(v1, v2)`: `v1 < v2` -* `lte(v1, v2)`: `v1 <= v2` -* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, - even if they're not the exact same string. You already know how to - compare strings. -* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. -* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call - the corresponding function above. `"==="` and `"!=="` do simple - string comparison, but are included for completeness. Throws if an - invalid comparison string is provided. -* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if - `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. -* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions - in descending order when passed to `Array.sort()`. -* `diff(v1, v2)`: Returns difference between two versions by the release type - (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), - or null if the versions are the same. - -### Comparators - -* `intersects(comparator)`: Return true if the comparators intersect - -### Ranges - -* `validRange(range)`: Return the valid range or null if it's not valid -* `satisfies(version, range)`: Return true if the version satisfies the - range. -* `maxSatisfying(versions, range)`: Return the highest version in the list - that satisfies the range, or `null` if none of them do. -* `minSatisfying(versions, range)`: Return the lowest version in the list - that satisfies the range, or `null` if none of them do. -* `minVersion(range)`: Return the lowest version that can possibly match - the given range. -* `gtr(version, range)`: Return `true` if version is greater than all the - versions possible in the range. -* `ltr(version, range)`: Return `true` if version is less than all the - versions possible in the range. -* `outside(version, range, hilo)`: Return true if the version is outside - the bounds of the range in either the high or low direction. The - `hilo` argument must be either the string `'>'` or `'<'`. (This is - the function called by `gtr` and `ltr`.) -* `intersects(range)`: Return true if any of the ranges comparators intersect - -Note that, since ranges may be non-contiguous, a version might not be -greater than a range, less than a range, *or* satisfy a range! For -example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` -until `2.0.0`, so the version `1.2.10` would not be greater than the -range (because `2.0.1` satisfies, which is higher), nor less than the -range (since `1.2.8` satisfies, which is lower), and it also does not -satisfy the range. - -If you want to know if a version satisfies or does not satisfy a -range, use the `satisfies(version, range)` function. - -### Coercion - -* `coerce(version)`: Coerces a string to semver if possible - -This aims to provide a very forgiving translation of a non-semver string to -semver. It looks for the first digit in a string, and consumes all -remaining characters which satisfy at least a partial semver (e.g., `1`, -`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer -versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All -surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes -`3.4.0`). Only text which lacks digits will fail coercion (`version one` -is not valid). The maximum length for any semver component considered for -coercion is 16 characters; longer components will be ignored -(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any -semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value -components are invalid (`9999999999999999.4.7.4` is likely invalid). diff --git a/reverse_engineering/node_modules/semver/bin/semver b/reverse_engineering/node_modules/semver/bin/semver deleted file mode 100755 index 801e77f..0000000 --- a/reverse_engineering/node_modules/semver/bin/semver +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env node -// Standalone semver comparison program. -// Exits successfully and prints matching version(s) if -// any supplied version is valid and passes all tests. - -var argv = process.argv.slice(2) - -var versions = [] - -var range = [] - -var inc = null - -var version = require('../package.json').version - -var loose = false - -var includePrerelease = false - -var coerce = false - -var identifier - -var semver = require('../semver') - -var reverse = false - -var options = {} - -main() - -function main () { - if (!argv.length) return help() - while (argv.length) { - var a = argv.shift() - var indexOfEqualSign = a.indexOf('=') - if (indexOfEqualSign !== -1) { - a = a.slice(0, indexOfEqualSign) - argv.unshift(a.slice(indexOfEqualSign + 1)) - } - switch (a) { - case '-rv': case '-rev': case '--rev': case '--reverse': - reverse = true - break - case '-l': case '--loose': - loose = true - break - case '-p': case '--include-prerelease': - includePrerelease = true - break - case '-v': case '--version': - versions.push(argv.shift()) - break - case '-i': case '--inc': case '--increment': - switch (argv[0]) { - case 'major': case 'minor': case 'patch': case 'prerelease': - case 'premajor': case 'preminor': case 'prepatch': - inc = argv.shift() - break - default: - inc = 'patch' - break - } - break - case '--preid': - identifier = argv.shift() - break - case '-r': case '--range': - range.push(argv.shift()) - break - case '-c': case '--coerce': - coerce = true - break - case '-h': case '--help': case '-?': - return help() - default: - versions.push(a) - break - } - } - - var options = { loose: loose, includePrerelease: includePrerelease } - - versions = versions.map(function (v) { - return coerce ? (semver.coerce(v) || { version: v }).version : v - }).filter(function (v) { - return semver.valid(v) - }) - if (!versions.length) return fail() - if (inc && (versions.length !== 1 || range.length)) { return failInc() } - - for (var i = 0, l = range.length; i < l; i++) { - versions = versions.filter(function (v) { - return semver.satisfies(v, range[i], options) - }) - if (!versions.length) return fail() - } - return success(versions) -} - -function failInc () { - console.error('--inc can only be used on a single version with no range') - fail() -} - -function fail () { process.exit(1) } - -function success () { - var compare = reverse ? 'rcompare' : 'compare' - versions.sort(function (a, b) { - return semver[compare](a, b, options) - }).map(function (v) { - return semver.clean(v, options) - }).map(function (v) { - return inc ? semver.inc(v, inc, options, identifier) : v - }).forEach(function (v, i, _) { console.log(v) }) -} - -function help () { - console.log(['SemVer ' + version, - '', - 'A JavaScript implementation of the https://semver.org/ specification', - 'Copyright Isaac Z. Schlueter', - '', - 'Usage: semver [options] [ [...]]', - 'Prints valid versions sorted by SemVer precedence', - '', - 'Options:', - '-r --range ', - ' Print versions that match the specified range.', - '', - '-i --increment []', - ' Increment a version by the specified level. Level can', - ' be one of: major, minor, patch, premajor, preminor,', - " prepatch, or prerelease. Default level is 'patch'.", - ' Only one version may be specified.', - '', - '--preid ', - ' Identifier to be used to prefix premajor, preminor,', - ' prepatch or prerelease version increments.', - '', - '-l --loose', - ' Interpret versions and ranges loosely', - '', - '-p --include-prerelease', - ' Always include prerelease versions in range matching', - '', - '-c --coerce', - ' Coerce a string into SemVer if possible', - ' (does not imply --loose)', - '', - 'Program exits successfully if any valid version satisfies', - 'all supplied ranges, and prints all satisfying versions.', - '', - 'If no satisfying versions are found, then exits failure.', - '', - 'Versions are printed in ascending order, so supplying', - 'multiple versions to the utility will just sort them.' - ].join('\n')) -} diff --git a/reverse_engineering/node_modules/semver/package.json b/reverse_engineering/node_modules/semver/package.json deleted file mode 100644 index 31e12dd..0000000 --- a/reverse_engineering/node_modules/semver/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "semver", - "version": "5.7.1", - "description": "The semantic version parser used by npm.", - "main": "semver.js", - "scripts": { - "test": "tap", - "preversion": "npm test", - "postversion": "npm publish", - "postpublish": "git push origin --all; git push origin --tags" - }, - "devDependencies": { - "tap": "^13.0.0-rc.18" - }, - "license": "ISC", - "repository": "https://github.com/npm/node-semver", - "bin": { - "semver": "./bin/semver" - }, - "files": [ - "bin", - "range.bnf", - "semver.js" - ], - "tap": { - "check-coverage": true - } - -,"_resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" -,"_integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" -,"_from": "semver@5.7.1" -} \ No newline at end of file diff --git a/reverse_engineering/node_modules/semver/range.bnf b/reverse_engineering/node_modules/semver/range.bnf deleted file mode 100644 index d4c6ae0..0000000 --- a/reverse_engineering/node_modules/semver/range.bnf +++ /dev/null @@ -1,16 +0,0 @@ -range-set ::= range ( logical-or range ) * -logical-or ::= ( ' ' ) * '||' ( ' ' ) * -range ::= hyphen | simple ( ' ' simple ) * | '' -hyphen ::= partial ' - ' partial -simple ::= primitive | partial | tilde | caret -primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial -partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? -xr ::= 'x' | 'X' | '*' | nr -nr ::= '0' | [1-9] ( [0-9] ) * -tilde ::= '~' partial -caret ::= '^' partial -qualifier ::= ( '-' pre )? ( '+' build )? -pre ::= parts -build ::= parts -parts ::= part ( '.' part ) * -part ::= nr | [-0-9A-Za-z]+ diff --git a/reverse_engineering/node_modules/semver/semver.js b/reverse_engineering/node_modules/semver/semver.js deleted file mode 100644 index d315d5d..0000000 --- a/reverse_engineering/node_modules/semver/semver.js +++ /dev/null @@ -1,1483 +0,0 @@ -exports = module.exports = SemVer - -var debug -/* istanbul ignore next */ -if (typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG)) { - debug = function () { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift('SEMVER') - console.log.apply(console, args) - } -} else { - debug = function () {} -} - -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0' - -var MAX_LENGTH = 256 -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991 - -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16 - -// The actual regexps go on exports.re -var re = exports.re = [] -var src = exports.src = [] -var R = 0 - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -var NUMERICIDENTIFIER = R++ -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' -var NUMERICIDENTIFIERLOOSE = R++ -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -var NONNUMERICIDENTIFIER = R++ -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' - -// ## Main Version -// Three dot-separated numeric identifiers. - -var MAINVERSION = R++ -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')' - -var MAINVERSIONLOOSE = R++ -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')' - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -var PRERELEASEIDENTIFIER = R++ -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')' - -var PRERELEASEIDENTIFIERLOOSE = R++ -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')' - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -var PRERELEASE = R++ -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' - -var PRERELEASELOOSE = R++ -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -var BUILDIDENTIFIER = R++ -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -var BUILD = R++ -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -var FULL = R++ -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?' - -src[FULL] = '^' + FULLPLAIN + '$' - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?' - -var LOOSE = R++ -src[LOOSE] = '^' + LOOSEPLAIN + '$' - -var GTLT = R++ -src[GTLT] = '((?:<|>)?=?)' - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++ -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' -var XRANGEIDENTIFIER = R++ -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' - -var XRANGEPLAIN = R++ -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?' - -var XRANGEPLAINLOOSE = R++ -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?' - -var XRANGE = R++ -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' -var XRANGELOOSE = R++ -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' - -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -var COERCE = R++ -src[COERCE] = '(?:^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])' - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++ -src[LONETILDE] = '(?:~>?)' - -var TILDETRIM = R++ -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') -var tildeTrimReplace = '$1~' - -var TILDE = R++ -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' -var TILDELOOSE = R++ -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++ -src[LONECARET] = '(?:\\^)' - -var CARETTRIM = R++ -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') -var caretTrimReplace = '$1^' - -var CARET = R++ -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' -var CARETLOOSE = R++ -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++ -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' -var COMPARATOR = R++ -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++ -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' - -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') -var comparatorTrimReplace = '$1$2$3' - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++ -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$' - -var HYPHENRANGELOOSE = R++ -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$' - -// Star ranges basically just allow anything at all. -var STAR = R++ -src[STAR] = '(<|>)?=?\\s*\\*' - -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]) - if (!re[i]) { - re[i] = new RegExp(src[i]) - } -} - -exports.parse = parse -function parse (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (version instanceof SemVer) { - return version - } - - if (typeof version !== 'string') { - return null - } - - if (version.length > MAX_LENGTH) { - return null - } - - var r = options.loose ? re[LOOSE] : re[FULL] - if (!r.test(version)) { - return null - } - - try { - return new SemVer(version, options) - } catch (er) { - return null - } -} - -exports.valid = valid -function valid (version, options) { - var v = parse(version, options) - return v ? v.version : null -} - -exports.clean = clean -function clean (version, options) { - var s = parse(version.trim().replace(/^[=v]+/, ''), options) - return s ? s.version : null -} - -exports.SemVer = SemVer - -function SemVer (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - if (version instanceof SemVer) { - if (version.loose === options.loose) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version) - } - - if (version.length > MAX_LENGTH) { - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - } - - if (!(this instanceof SemVer)) { - return new SemVer(version, options) - } - - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose - - var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) - - if (!m) { - throw new TypeError('Invalid Version: ' + version) - } - - this.raw = version - - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map(function (id) { - if (/^[0-9]+$/.test(id)) { - var num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } - - this.build = m[5] ? m[5].split('.') : [] - this.format() -} - -SemVer.prototype.format = function () { - this.version = this.major + '.' + this.minor + '.' + this.patch - if (this.prerelease.length) { - this.version += '-' + this.prerelease.join('.') - } - return this.version -} - -SemVer.prototype.toString = function () { - return this.version -} - -SemVer.prototype.compare = function (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return this.compareMain(other) || this.comparePre(other) -} - -SemVer.prototype.compareMain = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) -} - -SemVer.prototype.comparePre = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } - - var i = 0 - do { - var a = this.prerelease[i] - var b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) -} - -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier) - this.inc('pre', identifier) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier) - } - this.inc('pre', identifier) - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0] - } else { - var i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0] - } - } else { - this.prerelease = [identifier, 0] - } - } - break - - default: - throw new Error('invalid increment argument: ' + release) - } - this.format() - this.raw = this.version - return this -} - -exports.inc = inc -function inc (version, release, loose, identifier) { - if (typeof (loose) === 'string') { - identifier = loose - loose = undefined - } - - try { - return new SemVer(version, loose).inc(release, identifier).version - } catch (er) { - return null - } -} - -exports.diff = diff -function diff (version1, version2) { - if (eq(version1, version2)) { - return null - } else { - var v1 = parse(version1) - var v2 = parse(version2) - var prefix = '' - if (v1.prerelease.length || v2.prerelease.length) { - prefix = 'pre' - var defaultResult = 'prerelease' - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return prefix + key - } - } - } - return defaultResult // may be undefined - } -} - -exports.compareIdentifiers = compareIdentifiers - -var numeric = /^[0-9]+$/ -function compareIdentifiers (a, b) { - var anum = numeric.test(a) - var bnum = numeric.test(b) - - if (anum && bnum) { - a = +a - b = +b - } - - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} - -exports.rcompareIdentifiers = rcompareIdentifiers -function rcompareIdentifiers (a, b) { - return compareIdentifiers(b, a) -} - -exports.major = major -function major (a, loose) { - return new SemVer(a, loose).major -} - -exports.minor = minor -function minor (a, loose) { - return new SemVer(a, loose).minor -} - -exports.patch = patch -function patch (a, loose) { - return new SemVer(a, loose).patch -} - -exports.compare = compare -function compare (a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)) -} - -exports.compareLoose = compareLoose -function compareLoose (a, b) { - return compare(a, b, true) -} - -exports.rcompare = rcompare -function rcompare (a, b, loose) { - return compare(b, a, loose) -} - -exports.sort = sort -function sort (list, loose) { - return list.sort(function (a, b) { - return exports.compare(a, b, loose) - }) -} - -exports.rsort = rsort -function rsort (list, loose) { - return list.sort(function (a, b) { - return exports.rcompare(a, b, loose) - }) -} - -exports.gt = gt -function gt (a, b, loose) { - return compare(a, b, loose) > 0 -} - -exports.lt = lt -function lt (a, b, loose) { - return compare(a, b, loose) < 0 -} - -exports.eq = eq -function eq (a, b, loose) { - return compare(a, b, loose) === 0 -} - -exports.neq = neq -function neq (a, b, loose) { - return compare(a, b, loose) !== 0 -} - -exports.gte = gte -function gte (a, b, loose) { - return compare(a, b, loose) >= 0 -} - -exports.lte = lte -function lte (a, b, loose) { - return compare(a, b, loose) <= 0 -} - -exports.cmp = cmp -function cmp (a, op, b, loose) { - switch (op) { - case '===': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a === b - - case '!==': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a !== b - - case '': - case '=': - case '==': - return eq(a, b, loose) - - case '!=': - return neq(a, b, loose) - - case '>': - return gt(a, b, loose) - - case '>=': - return gte(a, b, loose) - - case '<': - return lt(a, b, loose) - - case '<=': - return lte(a, b, loose) - - default: - throw new TypeError('Invalid operator: ' + op) - } -} - -exports.Comparator = Comparator -function Comparator (comp, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (comp instanceof Comparator) { - if (comp.loose === !!options.loose) { - return comp - } else { - comp = comp.value - } - } - - if (!(this instanceof Comparator)) { - return new Comparator(comp, options) - } - - debug('comparator', comp, options) - this.options = options - this.loose = !!options.loose - this.parse(comp) - - if (this.semver === ANY) { - this.value = '' - } else { - this.value = this.operator + this.semver.version - } - - debug('comp', this) -} - -var ANY = {} -Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] - var m = comp.match(r) - - if (!m) { - throw new TypeError('Invalid comparator: ' + comp) - } - - this.operator = m[1] - if (this.operator === '=') { - this.operator = '' - } - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY - } else { - this.semver = new SemVer(m[2], this.options.loose) - } -} - -Comparator.prototype.toString = function () { - return this.value -} - -Comparator.prototype.test = function (version) { - debug('Comparator.test', version, this.options.loose) - - if (this.semver === ANY) { - return true - } - - if (typeof version === 'string') { - version = new SemVer(version, this.options) - } - - return cmp(version, this.operator, this.semver, this.options) -} - -Comparator.prototype.intersects = function (comp, options) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required') - } - - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - var rangeTmp - - if (this.operator === '') { - rangeTmp = new Range(comp.value, options) - return satisfies(this.value, rangeTmp, options) - } else if (comp.operator === '') { - rangeTmp = new Range(this.value, options) - return satisfies(comp.semver, rangeTmp, options) - } - - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>') - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<') - var sameSemVer = this.semver.version === comp.semver.version - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<=') - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')) - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')) - - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan -} - -exports.Range = Range -function Range (range, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (range instanceof Range) { - if (range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease) { - return range - } else { - return new Range(range.raw, options) - } - } - - if (range instanceof Comparator) { - return new Range(range.value, options) - } - - if (!(this instanceof Range)) { - return new Range(range, options) - } - - this.options = options - this.loose = !!options.loose - this.includePrerelease = !!options.includePrerelease - - // First, split based on boolean or || - this.raw = range - this.set = range.split(/\s*\|\|\s*/).map(function (range) { - return this.parseRange(range.trim()) - }, this).filter(function (c) { - // throw out any that are not relevant for whatever reason - return c.length - }) - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range) - } - - this.format() -} - -Range.prototype.format = function () { - this.range = this.set.map(function (comps) { - return comps.join(' ').trim() - }).join('||').trim() - return this.range -} - -Range.prototype.toString = function () { - return this.range -} - -Range.prototype.parseRange = function (range) { - var loose = this.options.loose - range = range.trim() - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] - range = range.replace(hr, hyphenReplace) - debug('hyphen replace', range) - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, re[COMPARATORTRIM]) - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace) - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace) - - // normalize spaces - range = range.split(/\s+/).join(' ') - - // At this point, the range is completely trimmed and - // ready to be split into comparators. - - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] - var set = range.split(' ').map(function (comp) { - return parseComparator(comp, this.options) - }, this).join(' ').split(/\s+/) - if (this.options.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function (comp) { - return !!comp.match(compRe) - }) - } - set = set.map(function (comp) { - return new Comparator(comp, this.options) - }, this) - - return set -} - -Range.prototype.intersects = function (range, options) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required') - } - - return this.set.some(function (thisComparators) { - return thisComparators.every(function (thisComparator) { - return range.set.some(function (rangeComparators) { - return rangeComparators.every(function (rangeComparator) { - return thisComparator.intersects(rangeComparator, options) - }) - }) - }) - }) -} - -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators -function toComparators (range, options) { - return new Range(range, options).set.map(function (comp) { - return comp.map(function (c) { - return c.value - }).join(' ').trim().split(' ') - }) -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator (comp, options) { - debug('comp', comp, options) - comp = replaceCarets(comp, options) - debug('caret', comp) - comp = replaceTildes(comp, options) - debug('tildes', comp) - comp = replaceXRanges(comp, options) - debug('xrange', comp) - comp = replaceStars(comp, options) - debug('stars', comp) - return comp -} - -function isX (id) { - return !id || id.toLowerCase() === 'x' || id === '*' -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceTilde(comp, options) - }).join(' ') -} - -function replaceTilde (comp, options) { - var r = options.loose ? re[TILDELOOSE] : re[TILDE] - return comp.replace(r, function (_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else if (pr) { - debug('replaceTilde pr', pr) - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } else { - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - - debug('tilde return', ret) - return ret - }) -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceCaret(comp, options) - }).join(' ') -} - -function replaceCaret (comp, options) { - debug('caret', comp, options) - var r = options.loose ? re[CARETLOOSE] : re[CARET] - return comp.replace(r, function (_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - if (M === '0') { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else { - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' - } - } else if (pr) { - debug('replaceCaret pr', pr) - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + (+M + 1) + '.0.0' - } - } else { - debug('no pr') - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0' - } - } - - debug('caret return', ret) - return ret - }) -} - -function replaceXRanges (comp, options) { - debug('replaceXRanges', comp, options) - return comp.split(/\s+/).map(function (comp) { - return replaceXRange(comp, options) - }).join(' ') -} - -function replaceXRange (comp, options) { - comp = comp.trim() - var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] - return comp.replace(r, function (ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr) - var xM = isX(M) - var xm = xM || isX(m) - var xp = xm || isX(p) - var anyX = xp - - if (gtlt === '=' && anyX) { - gtlt = '' - } - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0' - } else { - // nothing is forbidden - ret = '*' - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0 - } - p = 0 - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>=' - if (xm) { - M = +M + 1 - m = 0 - p = 0 - } else { - m = +m + 1 - p = 0 - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<' - if (xm) { - M = +M + 1 - } else { - m = +m + 1 - } - } - - ret = gtlt + M + '.' + m + '.' + p - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } - - debug('xRange return', ret) - - return ret - }) -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars (comp, options) { - debug('replaceStars', comp, options) - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], '') -} - -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - if (isX(fM)) { - from = '' - } else if (isX(fm)) { - from = '>=' + fM + '.0.0' - } else if (isX(fp)) { - from = '>=' + fM + '.' + fm + '.0' - } else { - from = '>=' + from - } - - if (isX(tM)) { - to = '' - } else if (isX(tm)) { - to = '<' + (+tM + 1) + '.0.0' - } else if (isX(tp)) { - to = '<' + tM + '.' + (+tm + 1) + '.0' - } else if (tpr) { - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr - } else { - to = '<=' + to - } - - return (from + ' ' + to).trim() -} - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - version = new SemVer(version, this.options) - } - - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } - } - return false -} - -function testSet (set, version, options) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } - } - - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (i = 0; i < set.length; i++) { - debug(set[i].semver) - if (set[i].semver === ANY) { - continue - } - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false - } - - return true -} - -exports.satisfies = satisfies -function satisfies (version, range, options) { - try { - range = new Range(range, options) - } catch (er) { - return false - } - return range.test(version) -} - -exports.maxSatisfying = maxSatisfying -function maxSatisfying (versions, range, options) { - var max = null - var maxSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v - maxSV = new SemVer(max, options) - } - } - }) - return max -} - -exports.minSatisfying = minSatisfying -function minSatisfying (versions, range, options) { - var min = null - var minSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v - minSV = new SemVer(min, options) - } - } - }) - return min -} - -exports.minVersion = minVersion -function minVersion (range, loose) { - range = new Range(range, loose) - - var minver = new SemVer('0.0.0') - if (range.test(minver)) { - return minver - } - - minver = new SemVer('0.0.0-0') - if (range.test(minver)) { - return minver - } - - minver = null - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] - - comparators.forEach(function (comparator) { - // Clone to avoid manipulating the comparator's semver object. - var compver = new SemVer(comparator.semver.version) - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++ - } else { - compver.prerelease.push(0) - } - compver.raw = compver.format() - /* fallthrough */ - case '': - case '>=': - if (!minver || gt(minver, compver)) { - minver = compver - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error('Unexpected operation: ' + comparator.operator) - } - }) - } - - if (minver && range.test(minver)) { - return minver - } - - return null -} - -exports.validRange = validRange -function validRange (range, options) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, options).range || '*' - } catch (er) { - return null - } -} - -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr -function ltr (version, range, options) { - return outside(version, range, '<', options) -} - -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr -function gtr (version, range, options) { - return outside(version, range, '>', options) -} - -exports.outside = outside -function outside (version, range, hilo, options) { - version = new SemVer(version, options) - range = new Range(range, options) - - var gtfn, ltefn, ltfn, comp, ecomp - switch (hilo) { - case '>': - gtfn = gt - ltefn = lte - ltfn = lt - comp = '>' - ecomp = '>=' - break - case '<': - gtfn = lt - ltefn = gte - ltfn = gt - comp = '<' - ecomp = '<=' - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } - - // If it satisifes the range it is not outside - if (satisfies(version, range, options)) { - return false - } - - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. - - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] - - var high = null - var low = null - - comparators.forEach(function (comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator - low = low || comparator - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator - } - }) - - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } - - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -} - -exports.prerelease = prerelease -function prerelease (version, options) { - var parsed = parse(version, options) - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -} - -exports.intersects = intersects -function intersects (r1, r2, options) { - r1 = new Range(r1, options) - r2 = new Range(r2, options) - return r1.intersects(r2) -} - -exports.coerce = coerce -function coerce (version) { - if (version instanceof SemVer) { - return version - } - - if (typeof version !== 'string') { - return null - } - - var match = version.match(re[COERCE]) - - if (match == null) { - return null - } - - return parse(match[1] + - '.' + (match[2] || '0') + - '.' + (match[3] || '0')) -} diff --git a/reverse_engineering/node_modules/ssh2-streams/.travis.yml b/reverse_engineering/node_modules/ssh2-streams/.travis.yml deleted file mode 100644 index 4cec49d..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -sudo: false -language: cpp -notifications: - email: false -env: - matrix: - - TRAVIS_NODE_VERSION="0.10" - - TRAVIS_NODE_VERSION="0.12" - - TRAVIS_NODE_VERSION="4" - - TRAVIS_NODE_VERSION="6" - - TRAVIS_NODE_VERSION="7" -install: - - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - - node --version - - npm --version - - npm install -script: npm test diff --git a/reverse_engineering/node_modules/ssh2-streams/README.md b/reverse_engineering/node_modules/ssh2-streams/README.md deleted file mode 100644 index 01e8823..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/README.md +++ /dev/null @@ -1,569 +0,0 @@ -Description -=========== - -SSH2 and SFTP(v3) client/server protocol streams for [node.js](http://nodejs.org/). - -[![Build Status](https://travis-ci.org/mscdex/ssh2-streams.svg?branch=master)](https://travis-ci.org/mscdex/ssh2-streams) - - -Requirements -============ - -* [node.js](http://nodejs.org/) -- v0.10 or newer - - -Install -======= - - npm install ssh2-streams - - -API -=== - -`require('ssh2-streams').SSH2Stream` returns an **_SSH2Stream_** constructor. - -`require('ssh2-streams').SFTPStream` returns an [**_SFTPStream_**](SFTPStream.md) constructor. - -`require('ssh2-streams').utils` returns an _object_ of useful utility functions. - -`require('ssh2-streams').constants` returns an _object_ containing useful SSH protocol constants. - - -SSH2Stream events ------------------ - -**Client/Server events** - -* **header**(< _object_ >headerInfo) - Emitted when the protocol header is seen. `headerInfo` contains: - - * **greeting** - _string_ - (Client-only) An optional greeting message presented by the server. - - * **identRaw** - _string_ - The raw identification string sent by the remote party. - - * **versions** - _object_ - Contains various information parsed from `identRaw`: - - * **protocol** - _string_ - The protocol version (always `1.99` or `2.0`) supported by the remote party. - - * **software** - _string_ - The software name used by the remote party. - - * **comments** - _string_ - Any additional text that comes after the software name. - -* **GLOBAL_REQUEST**(< _string_ >reqName, < _boolean_ >wantReply, < _mixed_ >reqData) - -* **CHANNEL_DATA:\**(< _Buffer_ >data) - -* **CHANNEL_EXTENDED_DATA:\**(< _integer_ >type, < _Buffer_ >data) - -* **CHANNEL_WINDOW_ADJUST:\**(< _integer_ >bytesToAdd) - -* **CHANNEL_SUCCESS:\**() - -* **CHANNEL_FAILURE:\**() - -* **CHANNEL_EOF:\**() - -* **CHANNEL_CLOSE:\**() - -* **CHANNEL_OPEN_CONFIRMATION:\**(< _object_ >channelInfo) - `channelInfo` contains: - - * **recipient** - _integer_ - The local channel number. - - * **sender** - _integer_ - The remote party's channel number. - - * **window** - _integer_ - The initial window size for the channel. - - * **packetSize** - _integer_ - The maximum packet size for the channel. - -* **CHANNEL_OPEN_FAILURE:\**(< _object_ >failInfo) - `failInfo` contains: - - * **recipient** - _integer_ - The local channel number. - - * **reasonCode** - _integer_ - The reason code of the failure. - - * **reason** - _string_ - A text representation of the `reasonCode`. - - * **description** - _string_ - An optional description of the failure. - -* **DISCONNECT**(< _string_ >reason, < _integer_ >reasonCode, < _string_ >description) - -* **DEBUG**(< _string_ >message) - -* **NEWKEYS**() - -* **REQUEST_SUCCESS**([< _Buffer_ >resData]) - -* **REQUEST_FAILURE**() - - - -**Client-only events** - -* **fingerprint**(< _Buffer_ >hostKey, < _function_ >callback) - This event allows you to verify a host's key. If `callback` is called with `true`, the handshake continues. Otherwise a disconnection will occur if `callback` is called with `false`. The default behavior is to auto-allow any host key if there are no handlers for this event. - -* **SERVICE_ACCEPT**(< _string_ >serviceName) - -* **USERAUTH_PASSWD_CHANGEREQ**(< _string_ >message) - -* **USERAUTH_INFO_REQUEST**(< _string_ >name, < _string_ >instructions, < _string_ >lang, < _array_ >prompts) - -* **USERAUTH_PK_OK**() - -* **USERAUTH_SUCCESS**() - -* **USERAUTH_FAILURE**(< _array_ >methodsContinue, < _boolean_ >partialSuccess) - -* **USERAUTH_BANNER**(< _string_ >message) - -* **CHANNEL_OPEN**(< _object_ >channelInfo) - `channelInfo` contains: - - * **type** - _string_ - The channel type (e.g. `x11`, `forwarded-tcpip`). - - * **sender** - _integer_ - The remote party's channel number. - - * **window** - _integer_ - The initial window size for the channel. - - * **packetSize** - _integer_ - The maximum packet size for the channel. - - * **data** - _object_ - The properties available depend on `type`: - - * `x11`: - - * **srcIP** - _string_ - Source IP address of X11 connection request. - - * **srcPort** - _string_ - Source port of X11 connection request. - - * `forwarded-tcpip`: - - * **srcIP** - _string_ - Source IP address of incoming connection. - - * **srcPort** - _string_ - Source port of incoming connection. - - * **destIP** - _string_ - Destination IP address of incoming connection. - - * **destPort** - _string_ - Destination port of incoming connection. - - * `forwarded-streamlocal@openssh.com`: - - * **socketPath** - _string_ - Source socket path of incoming connection. - - * `auth-agent@openssh.com` has no extra data. - -* **CHANNEL_REQUEST:\**(< _object_ >reqInfo) - `reqInfo` properties depend on `reqInfo.request`: - - * `exit-status`: - - * **code** - _integer_ - The exit status code of the remote process. - - * `exit-signal`: - - * **signal** - _string_ - The signal name. - - * **coredump** - _boolean_ - Was the exit the result of a core dump? - - * **description** - _string_ - An optional error message. - - - -**Server-only events** - -* **SERVICE_REQUEST**(< _string_ >serviceName) - -* **USERAUTH_REQUEST**(< _string_ >username, < _string_ >serviceName, < _string_ >authMethod, < _mixed_ >authMethodData) - `authMethodData` depends on `authMethod`: - - * For `password`, it's a _string_ containing the password. - - * For `publickey`, it's an _object_ containing: - - * **keyAlgo** - _string_ - The public key algorithm. - - * **key** - _Buffer_ - The public key data. - - * **signature** - _mixed_ - If set, it is a _Buffer_ containing the signature to be verified. - - * **blob** - _mixed_ - If set, it is a _Buffer_ containing the data to sign. The resulting signature is what is compared to `signature`. - - * For `hostbased`, it's an _object_ including the properties from `publickey` but also: - - * **localHostname** - _string_ - The client's hostname to be verified. - - * **localUsername** - _string_ - The client's (local) username to be verified. - -* **USERAUTH_INFO_RESPONSE**(< _array_ >responses) - -* **GLOBAL_REQUEST**(< _string_ >reqName, < _boolean_ >wantReply, < _mixed_ >reqData) - `reqData` depends on `reqName`: - - * For `tcpip-forward`/`cancel-tcpip-forward`, it's an _object_ containing: - - * **bindAddr** - _string_ - The IP address to start/stop binding to. - - * **bindPort** - _string_ - The port to start/stop binding to. - - * For `streamlocal-forward@openssh.com`/`cancel-streamlocal-forward@openssh.com`, it's an _object_ containing: - - * **socketPath** - _string_ - The socket path to start/stop listening on. - - * For `no-more-sessions@openssh.com`, there is no `reqData`. - - * For any other requests, it's a _Buffer_ containing raw request-specific data *if* there is any extra data. - -* **CHANNEL_OPEN**(< _object_ >channelInfo) - `channelInfo` contains: - - * **type** - _string_ - The channel type (e.g. `session`, `direct-tcpip`). - - * **sender** - _integer_ - The remote party's channel number. - - * **window** - _integer_ - The initial window size for the channel. - - * **packetSize** - _integer_ - The maximum packet size for the channel. - - * **data** - _object_ - The properties available depend on `type`: - - * `direct-tcpip`: - - * **srcIP** - _string_ - Source IP address of outgoing connection. - - * **srcPort** - _string_ - Source port of outgoing connection. - - * **destIP** - _string_ - Destination IP address of outgoing connection. - - * **destPort** - _string_ - Destination port of outgoing connection. - - * `direct-streamlocal@openssh.com`: - - * **socketPath** - _string_ - Destination socket path of outgoing connection. - - * `session` has no extra data. - -* **CHANNEL_REQUEST:\**(< _object_ >reqInfo) - `reqInfo` properties depend on `reqInfo.request`: - - * `pty-req`: - - * **wantReply** - _boolean_ - The client is requesting a response to this request. - - * **term** - _string_ - The terminal type name. - - * **cols** - _integer_ - The number of columns. - - * **rows** - _integer_ - The number of rows. - - * **width** - _integer_ - The width in pixels. - - * **height** - _integer_ - The height in pixels. - - * **modes** - _object_ - The terminal modes. - - * `window-change`: - - * **cols** - _integer_ - The number of columns. - - * **rows** - _integer_ - The number of rows. - - * **width** - _integer_ - The width in pixels. - - * **height** - _integer_ - The height in pixels. - - * `x11-req`: - - * **wantReply** - _boolean_ - The client is requesting a response to this request. - - * **single** - _boolean_ - Whether only a single X11 connection should be allowed. - - * **protocol** - _string_ - The X11 authentication protocol to be used. - - * **cookie** - _string_ - The hex-encoded X11 authentication cookie. - - * **screen** - _integer_ - The screen number for incoming X11 connections. - - * `env`: - - * **wantReply** - _boolean_ - The client is requesting a response to this request. - - * **key** - _string_ - The environment variable name. - - * **val** - _string_ - The environment variable value. - - * `shell`: - - * **wantReply** - _boolean_ - The client is requesting a response to this request. - - * `exec`: - - * **wantReply** - _boolean_ - The client is requesting a response to this request. - - * **command** - _string_ - The command to be executed. - - * `subsystem`: - - * **wantReply** - _boolean_ - The client is requesting a response to this request. - - * **subsystem** - _string_ - The name of the subsystem. - - * `signal`: - - * **signal** - _string_ - The signal name (prefixed with `SIG`). - - * `xon-xoff`: - - * **clientControl** - _boolean_ - Client can/can't perform flow control (control-S/control-Q processing). - - * `auth-agent-req@openssh.com` has no `reqInfo`. - -SSH2Stream properties ---------------------- - -* **bytesSent** - _integer_ - The number of bytes sent since the last keying. This metric can be useful in determining when to call `rekey()`. - -* **bytesReceived** - _integer_ - The number of bytes received since the last keying. This metric can be useful in determining when to call `rekey()`. - - -SSH2Stream methods ------------------- - -* **(constructor)**(< _object_ >config) - Creates and returns a new SSH2Stream instance. SSH2Stream instances are Duplex streams. `config` can contain: - - * **server** - _boolean_ - Set to `true` to create an instance in server mode. **Default:** `false` - - * **hostKeys** - _object_ - If in server mode, an object keyed on host key format (see supported `serverHostKey` values in `algorithms` option below) with values being (decrypted) _Buffer_s or _string_s that contain PEM-encoded (OpenSSH format) host private key(s). **Default:** (none) - - * **greeting** - _string_ - If in server mode, an optional message to send to the user immediately upon connection, before the handshake. **Note:** Most clients usually ignore this. **Default:** (none) - - * **banner** - _string_ - If in server mode, an optional message to send to the user once, right before authentication begins. **Default:** (none) - - * **ident** - _string_ - A custom software name/version identifier. **Default:** `'ssh2js' + moduleVersion + 'srv'` (server mode) `'ssh2js' + moduleVersion` (client mode) - - * **maxPacketSize** - _string_ - This is the maximum packet size that will be accepted. It should be 35000 bytes or larger to be compatible with other SSH2 implementations. **Default:** `35000` - - * **highWaterMark** - _integer_ - This is the `highWaterMark` to use for the stream. **Default:** `32 * 1024` - - * **algorithms** - _object_ - This option allows you to explicitly override the default transport layer algorithms used for the connection. Each value must be an array of valid algorithms for that category. The order of the algorithms in the arrays are important, with the most favorable being first. Valid keys: - - * **kex** - _array_ - Key exchange algorithms. - - * Default values: - - 1. ecdh-sha2-nistp256 **(node v0.11.14 or newer)** - 2. ecdh-sha2-nistp384 **(node v0.11.14 or newer)** - 3. ecdh-sha2-nistp521 **(node v0.11.14 or newer)** - 4. diffie-hellman-group-exchange-sha256 **(node v0.11.12 or newer)** - 5. diffie-hellman-group14-sha1 - - * Supported values: - - * ecdh-sha2-nistp256 **(node v0.11.14 or newer)** - * ecdh-sha2-nistp384 **(node v0.11.14 or newer)** - * ecdh-sha2-nistp521 **(node v0.11.14 or newer)** - * diffie-hellman-group-exchange-sha256 **(node v0.11.12 or newer)** - * diffie-hellman-group14-sha1 - * diffie-hellman-group-exchange-sha1 **(node v0.11.12 or newer)** - * diffie-hellman-group1-sha1 - - * **cipher** - _array_ - Ciphers. - - * Default values: - - 1. aes128-ctr - 2. aes192-ctr - 3. aes256-ctr - 4. aes128-gcm **(node v0.11.12 or newer)** - 5. aes128-gcm@openssh.com **(node v0.11.12 or newer)** - 6. aes256-gcm **(node v0.11.12 or newer)** - 7. aes256-gcm@openssh.com **(node v0.11.12 or newer)** - - * Supported values: - - * aes128-ctr - * aes192-ctr - * aes256-ctr - * aes128-gcm **(node v0.11.12 or newer)** - * aes128-gcm@openssh.com **(node v0.11.12 or newer)** - * aes256-gcm **(node v0.11.12 or newer)** - * aes256-gcm@openssh.com **(node v0.11.12 or newer)** - * aes256-cbc - * aes192-cbc - * aes128-cbc - * blowfish-cbc - * 3des-cbc - * arcfour256 - * arcfour128 - * cast128-cbc - * arcfour - - * **serverHostKey** - _array_ - Server host key formats. In server mode, this list must agree with the host private keys set in the `hostKeys` config setting. - - * Default values: - - 1. ssh-rsa - 2. ecdsa-sha2-nistp256 **(node v5.2.0 or newer)** - 3. ecdsa-sha2-nistp384 **(node v5.2.0 or newer)** - 4. ecdsa-sha2-nistp521 **(node v5.2.0 or newer)** - - * Supported values: - - * ssh-rsa - * ecdsa-sha2-nistp256 **(node v5.2.0 or newer)** - * ecdsa-sha2-nistp384 **(node v5.2.0 or newer)** - * ecdsa-sha2-nistp521 **(node v5.2.0 or newer)** - * ssh-dss - - * **hmac** - _array_ - (H)MAC algorithms. - - * Default values: - - 1. hmac-sha2-256 - 2. hmac-sha2-512 - 3. hmac-sha1 - - * Supported values: - - * hmac-sha2-256 - * hmac-sha2-512 - * hmac-sha1 - * hmac-md5 - * hmac-sha2-256-96 - * hmac-sha2-512-96 - * hmac-ripemd160 - * hmac-sha1-96 - * hmac-md5-96 - - * **compress** - _array_ - Compression algorithms. - - * Default values: - - 1. none - 2. zlib@openssh.com - 3. zlib - - * Supported values: - - * none - * zlib@openssh.com - * zlib - - * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information. **Default:** (none) - - - -**Client/Server methods** - -* **ping**() - _boolean_ - Writes a dummy GLOBAL_REQUEST packet (specifically "keepalive@openssh.com") that requests a reply. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **disconnect**([< _integer_ >reasonCode]) - _boolean_ - Writes a disconnect packet and closes the stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **rekey**() - _boolean_ - Starts the re-keying process. Incoming/Outgoing packets are buffered until the re-keying process has finished. Returns `false` to indicate that no more packets should be written until the `NEWKEYS` event is seen. - -* **requestSuccess**([< _Buffer_ >data]) - _boolean_ - Writes a request success packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **requestFailure**() - _boolean_ - Writes a request failure packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelSuccess**() - _boolean_ - Writes a channel success packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelFailure**() - _boolean_ - Writes a channel failure packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelEOF**(< _integer_ >channel) - _boolean_ - Writes a channel EOF packet for the given `channel`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelClose**(< _integer_ >channel) - _boolean_ - Writes a channel close packet for the given `channel`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelWindowAdjust**(< _integer_ >channel, < _integer_ >amount) - _boolean_ - Writes a channel window adjust packet for the given `channel` where `amount` is the number of bytes to add to the channel window. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelData**(< _integer_ >channel, < _mixed_ >data) - _boolean_ - Writes a channel data packet for the given `channel` where `data` is a _Buffer_ or _string_. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelExtData**(< _integer_ >channel, < _mixed_ >data, < _integer_ >type) - _boolean_ - Writes a channel extended data packet for the given `channel` where `data is a _Buffer_ or _string_. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelOpenConfirm**(< _integer_ >remoteChannel, < _integer_ >localChannel, < _integer_ >initWindow, < _integer_ >maxPacket) - _boolean_ - Writes a channel open confirmation packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **channelOpenFail**(< _integer_ >remoteChannel, < _integer_ >reasonCode[, < _string_ >description]) - _boolean_ - Writes a channel open failure packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - - - -**Client-only methods** - -* **service**(< _string_ >serviceName) - _boolean_ - Writes a service request packet for `serviceName`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **tcpipForward**(< _string_ >bindAddr, < _integer_ >bindPort[, < _boolean_ >wantReply]) - _boolean_ - Writes a tcpip forward global request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **cancelTcpipForward**(< _string_ >bindAddr, < _integer_ >bindPort[, < _boolean_ >wantReply]) - _boolean_ - Writes a cancel tcpip forward global request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authPassword**(< _string_ >username, < _string_ >password) - _boolean_ - Writes a password userauth request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authPK**(< _string_ >username, < _object_ >pubKey[, < _function_ >cbSign]) - _boolean_ - Writes a publickey userauth request packet. `pubKey` is the object returned from using `utils.parseKey()` on a private or public key. If `cbSign` is not present, a pubkey check userauth packet is written. Otherwise `cbSign` is called with `(blob, callback)`, where `blob` is the data to sign with the private key and the resulting signature _Buffer_ is passed to `callback` as the first argument. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authHostbased**(< _string_ >username, < _object_ >pubKey, < _string_ >localHostname, < _string_ >localUsername, < _function_ >cbSign) - _boolean_ - Writes a hostbased userauth request packet. `pubKey` is the object returned from using `utils.parseKey()` on a private or public key. `cbSign` is called with `(blob, callback)`, where `blob` is the data to sign with the private key and the resulting signature _Buffer_ is passed to `callback` as the first argument. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authKeyboard**(< _string_ >username) - _boolean_ - Writes a keyboard-interactive userauth request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authNone**(< _string_ >username) - _boolean_ - Writes a "none" userauth request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authInfoRes**(< _array_ >responses) - _boolean_ - Writes a userauth info response packet. `responses` is an _array_ of zero or more strings corresponding to responses to prompts previously sent by the server. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **directTcpip**(< _integer_ >channel, < _integer_ >initWindow, < _integer_ >maxPacket, < _object_ >config) - _boolean_ - Writes a direct tcpip channel open packet. `config` must contain `srcIP`, `srcPort`, `dstIP`, and `dstPort`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **session**(< _integer_ >channel, < _integer_ >initWindow, < _integer_ >maxPacket) - _boolean_ - Writes a session channel open packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **openssh_agentForward**(< _integer_ >channel[, < _boolean_ >wantReply]) - _boolean_ - Writes an `auth-agent-req@openssh.com` channel request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **windowChange**(< _integer_ >channel, < _integer_ >rows, < _integer_ >cols, < _integer_ >height, < _integer_ >width) - _boolean_ - Writes a window change channel request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **pty**(< _integer_ >channel, < _integer_ >rows, < _integer_ >cols, < _integer_ >height, < _integer_ >width, < _string_ >terminalType, < _mixed_ >terminalModes[, < _boolean_ >wantReply]) - _boolean_ - Writes a pty channel request packet. If `terminalType` is falsey, `vt100` is used. `terminalModes` can be the raw bytes, an _object_ of the terminal modes to set, or a falsey value for no modes. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **env**(< _integer_ >channel, < _string_ >key, < _mixed_ >value[, < _boolean_ >wantReply]) - _boolean_ - Writes an env channel request packet. `value` can be a _string_ or _Buffer_. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **shell**(< _integer_ >channel[, < _boolean_ >wantReply]) - _boolean_ - Writes a shell channel request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **exec**(< _integer_ >channel, < _string_ >command[, < _boolean_ >wantReply]) - _boolean_ - Writes an exec channel request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **signal**(< _integer_ >channel, < _string_ >signalName) - _boolean_ - Writes a signal channel request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **x11Forward**(< _integer_ >channel, < _object_ >config[, < _boolean_ >wantReply]) - _boolean_ - Writes an X11 forward channel request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `config` can contain: - - * **single** - _boolean_ - `true` if only a single connection should be forwarded. - - * **protocol** - _string_ - The name of the X11 authentication method used (e.g. `MIT-MAGIC-COOKIE-1`). - - * **cookie** - _string_ - The X11 authentication cookie encoded in hexadecimal. - - * **screen** - _integer_ - The screen number to forward X11 connections for. - -* **subsystem**(< _integer_ >channel, < _string_ >name[, < _boolean_ >wantReply]) - _boolean_ - Writes a subsystem channel request packet. `name` is the name of the subsystem (e.g. `sftp` or `netconf`). `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **openssh_noMoreSessions**([< _boolean_ >wantReply]) - _boolean_ - Writes a no-more-sessions@openssh.com request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **openssh_streamLocalForward**(< _string_ >socketPath[, < _boolean_ >wantReply]) - _boolean_ - Writes a streamlocal-forward@openssh.com request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **openssh_cancelStreamLocalForward**(< _string_ >socketPath[, < _boolean_ >wantReply]) - _boolean_ - Writes a cancel-streamlocal-forward@openssh.com request packet. `wantReply` defaults to `true`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **openssh_directStreamLocal**(< _integer_ >channel, < _integer_ >initWindow, < _integer_ >maxPacket, < _object_ >config) - _boolean_ - Writes a direct-streamlocal@openssh.com channel open packet. `config` must contain `socketPath`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - - - -**Server-only methods** - -* **serviceAccept**(< _string_ >serviceName) - _boolean_ - Writes a service accept packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authFailure**([< _array_ >authMethods[, < _boolean_ >partialSuccess]]) - _boolean_ - Writes a userauth failure packet. `authMethods` is an _array_ of authentication methods that can continue. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authSuccess**() - _boolean_ - Writes a userauth success packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authPKOK**(< _string_ >keyAlgorithm, < _Buffer_ >keyData) - _boolean_ - Writes a userauth PK OK packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **authInfoReq**(< _string_ >name, < _string_ >instructions, < _array_ >prompts) - _boolean_ - Writes a userauth info request packet. `prompts` is an array of `{ prompt: 'Prompt text', echo: true }` objects (`prompt` being the prompt text and `echo` indicating whether the client's response to the prompt should be echoed to their display). Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **forwardedTcpip**(< _integer_ >channel, < _integer_ >initWindow, < _integer_ >maxPacket, < _object_ >info) - _boolean_ - Writes a forwarded tcpip channel open packet. `info` must contain `boundAddr`, `boundPort`, `remoteAddr`, and `remotePort`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **x11**(< _integer_ >channel, < _integer_ >initWindow, < _integer_ >maxPacket, < _object_ >info) - _boolean_ - Writes an X11 channel open packet. `info` must contain `originAddr` and `originPort`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **openssh_forwardedStreamLocal**(< _integer_ >channel, < _integer_ >initWindow, < _integer_ >maxPacket, < _object_ >info) - _boolean_ - Writes an forwarded-streamlocal@openssh.com channel open packet. `info` must contain `socketPath`. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **exitStatus**(< _integer_ >channel, < _integer_ >exitCode) - _boolean_ - Writes an exit status channel request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - -* **exitSignal**(< _integer_ >channel, < _string_ >signalName, < _boolean_ >coreDumped, < _string_ >errorMessage) - _boolean_ - Writes an exit signal channel request packet. Returns `false` if you should wait for the `continue` event before sending any more traffic. - - -Utility methods ---------------- - -* **parseKey**(< _mixed_ >keyData) - _object_ - Parses a private/public key in OpenSSH and RFC4716 formats. - -* **decryptKey**(< _object_ >privKeyInfo, < _string_ >passphrase) - _(void)_ - Takes a private key parsed with `parseKey()` and decrypts it with `passphrase`. The decrypted key data overwrites the original encrypted copy. - -* **genPublicKey**(< _object_ >privKeyInfo) - _object_ - Takes a private key parsed with `parseKey()` and generates the associated public key and returns the public key information in the same format as `parseKey()`. diff --git a/reverse_engineering/node_modules/ssh2-streams/index.js b/reverse_engineering/node_modules/ssh2-streams/index.js deleted file mode 100644 index ac17b72..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/index.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - SFTPStream: require('./lib/sftp'), - SSH2Stream: require('./lib/ssh'), - utils: require('./lib/utils'), - constants: require('./lib/constants') -}; \ No newline at end of file diff --git a/reverse_engineering/node_modules/ssh2-streams/lib/constants.js b/reverse_engineering/node_modules/ssh2-streams/lib/constants.js deleted file mode 100644 index 5feedb0..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/lib/constants.js +++ /dev/null @@ -1,386 +0,0 @@ -var semver = require('semver'); - -var i; -var keys; -var len; - -var MESSAGE = exports.MESSAGE = { - // Transport layer protocol -- generic (1-19) - DISCONNECT: 1, - IGNORE: 2, - UNIMPLEMENTED: 3, - DEBUG: 4, - SERVICE_REQUEST: 5, - SERVICE_ACCEPT: 6, - - // Transport layer protocol -- algorithm negotiation (20-29) - KEXINIT: 20, - NEWKEYS: 21, - - // Transport layer protocol -- key exchange method-specific (30-49) - - // User auth protocol -- generic (50-59) - USERAUTH_REQUEST: 50, - USERAUTH_FAILURE: 51, - USERAUTH_SUCCESS: 52, - USERAUTH_BANNER: 53, - - // User auth protocol -- user auth method-specific (60-79) - - // Connection protocol -- generic (80-89) - GLOBAL_REQUEST: 80, - REQUEST_SUCCESS: 81, - REQUEST_FAILURE: 82, - - // Connection protocol -- channel-related (90-127) - CHANNEL_OPEN: 90, - CHANNEL_OPEN_CONFIRMATION: 91, - CHANNEL_OPEN_FAILURE: 92, - CHANNEL_WINDOW_ADJUST: 93, - CHANNEL_DATA: 94, - CHANNEL_EXTENDED_DATA: 95, - CHANNEL_EOF: 96, - CHANNEL_CLOSE: 97, - CHANNEL_REQUEST: 98, - CHANNEL_SUCCESS: 99, - CHANNEL_FAILURE: 100 - - // Reserved for client protocols (128-191) - - // Local extensions (192-155) -}; -for (i = 0, keys = Object.keys(MESSAGE), len = keys.length; i < len; ++i) - MESSAGE[MESSAGE[keys[i]]] = keys[i]; -// context-specific message codes: -MESSAGE.KEXDH_INIT = 30; -MESSAGE.KEXDH_REPLY = 31; -MESSAGE.KEXDH_GEX_REQUEST = 34; -MESSAGE.KEXDH_GEX_GROUP = 31; -MESSAGE.KEXDH_GEX_INIT = 32; -MESSAGE.KEXDH_GEX_REPLY = 33; -MESSAGE.KEXECDH_INIT = 30; // included here for completeness -MESSAGE.KEXECDH_REPLY = 31; // included here for completeness -MESSAGE.USERAUTH_PASSWD_CHANGEREQ = 60; -MESSAGE.USERAUTH_PK_OK = 60; -MESSAGE.USERAUTH_INFO_REQUEST = 60; -MESSAGE.USERAUTH_INFO_RESPONSE = 61; - -var DYNAMIC_KEXDH_MESSAGE = exports.DYNAMIC_KEXDH_MESSAGE = {}; -DYNAMIC_KEXDH_MESSAGE[MESSAGE.KEXDH_GEX_GROUP] = 'KEXDH_GEX_GROUP'; -DYNAMIC_KEXDH_MESSAGE[MESSAGE.KEXDH_GEX_REPLY] = 'KEXDH_GEX_REPLY'; - -var KEXDH_MESSAGE = exports.KEXDH_MESSAGE = {}; -KEXDH_MESSAGE[MESSAGE.KEXDH_INIT] = 'KEXDH_INIT'; -KEXDH_MESSAGE[MESSAGE.KEXDH_REPLY] = 'KEXDH_REPLY'; - -var DISCONNECT_REASON = exports.DISCONNECT_REASON = { - HOST_NOT_ALLOWED_TO_CONNECT: 1, - PROTOCOL_ERROR: 2, - KEY_EXCHANGE_FAILED: 3, - RESERVED: 4, - MAC_ERROR: 5, - COMPRESSION_ERROR: 6, - SERVICE_NOT_AVAILABLE: 7, - PROTOCOL_VERSION_NOT_SUPPORTED: 8, - HOST_KEY_NOT_VERIFIABLE: 9, - CONNECTION_LOST: 10, - BY_APPLICATION: 11, - TOO_MANY_CONNECTIONS: 12, - AUTH_CANCELED_BY_USER: 13, - NO_MORE_AUTH_METHODS_AVAILABLE: 14, - ILLEGAL_USER_NAME: 15 -}; -for (i = 0, keys = Object.keys(DISCONNECT_REASON), len = keys.length; - i < len; - ++i) { - DISCONNECT_REASON[DISCONNECT_REASON[keys[i]]] = keys[i]; -} - -var CHANNEL_OPEN_FAILURE = exports.CHANNEL_OPEN_FAILURE = { - ADMINISTRATIVELY_PROHIBITED: 1, - CONNECT_FAILED: 2, - UNKNOWN_CHANNEL_TYPE: 3, - RESOURCE_SHORTAGE: 4 -}; -for (i = 0, keys = Object.keys(CHANNEL_OPEN_FAILURE), len = keys.length; - i < len; - ++i) { - CHANNEL_OPEN_FAILURE[CHANNEL_OPEN_FAILURE[keys[i]]] = keys[i]; -} - -var TERMINAL_MODE = exports.TERMINAL_MODE = { - TTY_OP_END: 0, // Indicates end of options. - VINTR: 1, // Interrupt character; 255 if none. Similarly for the - // other characters. Not all of these characters are - // supported on all systems. - VQUIT: 2, // The quit character (sends SIGQUIT signal on POSIX - // systems). - VERASE: 3, // Erase the character to left of the cursor. - VKILL: 4, // Kill the current input line. - VEOF: 5, // End-of-file character (sends EOF from the terminal). - VEOL: 6, // End-of-line character in addition to carriage return - // and/or linefeed. - VEOL2: 7, // Additional end-of-line character. - VSTART: 8, // Continues paused output (normally control-Q). - VSTOP: 9, // Pauses output (normally control-S). - VSUSP: 10, // Suspends the current program. - VDSUSP: 11, // Another suspend character. - VREPRINT: 12, // Reprints the current input line. - VWERASE: 13, // Erases a word left of cursor. - VLNEXT: 14, // Enter the next character typed literally, even if it - // is a special character - VFLUSH: 15, // Character to flush output. - VSWTCH: 16, // Switch to a different shell layer. - VSTATUS: 17, // Prints system status line (load, command, pid, etc). - VDISCARD: 18, // Toggles the flushing of terminal output. - IGNPAR: 30, // The ignore parity flag. The parameter SHOULD be 0 - // if this flag is FALSE, and 1 if it is TRUE. - PARMRK: 31, // Mark parity and framing errors. - INPCK: 32, // Enable checking of parity errors. - ISTRIP: 33, // Strip 8th bit off characters. - INLCR: 34, // Map NL into CR on input. - IGNCR: 35, // Ignore CR on input. - ICRNL: 36, // Map CR to NL on input. - IUCLC: 37, // Translate uppercase characters to lowercase. - IXON: 38, // Enable output flow control. - IXANY: 39, // Any char will restart after stop. - IXOFF: 40, // Enable input flow control. - IMAXBEL: 41, // Ring bell on input queue full. - ISIG: 50, // Enable signals INTR, QUIT, [D]SUSP. - ICANON: 51, // Canonicalize input lines. - XCASE: 52, // Enable input and output of uppercase characters by - // preceding their lowercase equivalents with "\". - ECHO: 53, // Enable echoing. - ECHOE: 54, // Visually erase chars. - ECHOK: 55, // Kill character discards current line. - ECHONL: 56, // Echo NL even if ECHO is off. - NOFLSH: 57, // Don't flush after interrupt. - TOSTOP: 58, // Stop background jobs from output. - IEXTEN: 59, // Enable extensions. - ECHOCTL: 60, // Echo control characters as ^(Char). - ECHOKE: 61, // Visual erase for line kill. - PENDIN: 62, // Retype pending input. - OPOST: 70, // Enable output processing. - OLCUC: 71, // Convert lowercase to uppercase. - ONLCR: 72, // Map NL to CR-NL. - OCRNL: 73, // Translate carriage return to newline (output). - ONOCR: 74, // Translate newline to carriage return-newline - // (output). - ONLRET: 75, // Newline performs a carriage return (output). - CS7: 90, // 7 bit mode. - CS8: 91, // 8 bit mode. - PARENB: 92, // Parity enable. - PARODD: 93, // Odd parity, else even. - TTY_OP_ISPEED: 128, // Specifies the input baud rate in bits per second. - TTY_OP_OSPEED: 129 // Specifies the output baud rate in bits per second. -}; -for (i = 0, keys = Object.keys(TERMINAL_MODE), len = keys.length; i < len; ++i) - TERMINAL_MODE[TERMINAL_MODE[keys[i]]] = keys[i]; - -var CHANNEL_EXTENDED_DATATYPE = exports.CHANNEL_EXTENDED_DATATYPE = { - STDERR: 1 -}; -for (i = 0, keys = Object.keys(CHANNEL_EXTENDED_DATATYPE), len = keys.length; - i < len; - ++i) { - CHANNEL_EXTENDED_DATATYPE[CHANNEL_EXTENDED_DATATYPE[keys[i]]] = keys[i]; -} - -exports.SIGNALS = ['ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT', - 'QUIT', 'SEGV', 'TERM', 'USR1', 'USR2', 'KILL', - 'PIPE']; - -var DEFAULT_KEX = [ - 'diffie-hellman-group14-sha1' // REQUIRED -]; -var SUPPORTED_KEX = [ - 'diffie-hellman-group1-sha1' // REQUIRED -]; -if (semver.gte(process.version, '0.11.12')) { - // https://tools.ietf.org/html/rfc4419#section-4 - DEFAULT_KEX = [ - 'diffie-hellman-group-exchange-sha256' - ].concat(DEFAULT_KEX); - SUPPORTED_KEX = [ - 'diffie-hellman-group-exchange-sha1' - ].concat(SUPPORTED_KEX); -} -if (semver.gte(process.version, '0.11.14')) { - // https://tools.ietf.org/html/rfc5656#section-10.1 - DEFAULT_KEX = [ - 'ecdh-sha2-nistp256', - 'ecdh-sha2-nistp384', - 'ecdh-sha2-nistp521' - ].concat(DEFAULT_KEX); -} -var KEX_BUF = new Buffer(DEFAULT_KEX.join(','), 'ascii'); -SUPPORTED_KEX = DEFAULT_KEX.concat(SUPPORTED_KEX); - -var DEFAULT_SERVER_HOST_KEY = [ - 'ssh-rsa' -]; -var SUPPORTED_SERVER_HOST_KEY = [ - 'ssh-dss' -]; -if (semver.gte(process.version, '5.2.0')) { - // ECDSA keys are only supported in v5.2.0+ because of a crypto change that - // made it possible to (efficiently) generate an ECDSA public key from a - // private key (commit nodejs/node#da5ac55c83eb2c09cfb3baf7875529e8f1113529) - DEFAULT_SERVER_HOST_KEY.push( - 'ecdsa-sha2-nistp256', - 'ecdsa-sha2-nistp384', - 'ecdsa-sha2-nistp521' - ); -} -var SERVER_HOST_KEY_BUF = new Buffer(DEFAULT_SERVER_HOST_KEY.join(','), - 'ascii'); -SUPPORTED_SERVER_HOST_KEY = DEFAULT_SERVER_HOST_KEY.concat( - SUPPORTED_SERVER_HOST_KEY -); - -var DEFAULT_CIPHER = []; -var SUPPORTED_CIPHER = [ - 'aes256-cbc', - 'aes192-cbc', - 'aes128-cbc', - 'blowfish-cbc', - '3des-cbc', - - // http://tools.ietf.org/html/rfc4345#section-4: - 'arcfour256', - 'arcfour128', - - 'cast128-cbc', - 'arcfour' -]; -if (semver.gte(process.version, '0.11.12')) { - // node v0.11.12 introduced support for setting AAD, which is needed for - // AES-GCM in SSH2 - DEFAULT_CIPHER = [ - // http://tools.ietf.org/html/rfc5647 - 'aes128-gcm', - 'aes128-gcm@openssh.com', - 'aes256-gcm', - 'aes256-gcm@openssh.com' - ].concat(DEFAULT_CIPHER); -} -DEFAULT_CIPHER = [ - // http://tools.ietf.org/html/rfc4344#section-4 - 'aes128-ctr', - 'aes192-ctr', - 'aes256-ctr' -].concat(DEFAULT_CIPHER); -var CIPHER_BUF = new Buffer(DEFAULT_CIPHER.join(','), 'ascii'); -SUPPORTED_CIPHER = DEFAULT_CIPHER.concat(SUPPORTED_CIPHER); - -var DEFAULT_HMAC = [ - 'hmac-sha2-256', - 'hmac-sha2-512', - 'hmac-sha1', -]; -var SUPPORTED_HMAC = [ - 'hmac-md5', - 'hmac-sha2-256-96', // first 96 bits of HMAC-SHA256 - 'hmac-sha2-512-96', // first 96 bits of HMAC-SHA512 - 'hmac-ripemd160', - 'hmac-sha1-96', // first 96 bits of HMAC-SHA1 - 'hmac-md5-96' // first 96 bits of HMAC-MD5 -]; -var HMAC_BUF = new Buffer(DEFAULT_HMAC.join(','), 'ascii'); -SUPPORTED_HMAC = DEFAULT_HMAC.concat(SUPPORTED_HMAC); - -var DEFAULT_COMPRESS = [ - 'none', - 'zlib@openssh.com', // ZLIB (LZ77) compression, except - // compression/decompression does not start until after - // successful user authentication - 'zlib' // ZLIB (LZ77) compression -]; -var SUPPORTED_COMPRESS = []; -var COMPRESS_BUF = new Buffer(DEFAULT_COMPRESS.join(','), 'ascii'); -SUPPORTED_COMPRESS = DEFAULT_COMPRESS.concat(SUPPORTED_COMPRESS); - -exports.ALGORITHMS = { - KEX: DEFAULT_KEX, - KEX_BUF: KEX_BUF, - SUPPORTED_KEX: SUPPORTED_KEX, - - SERVER_HOST_KEY: DEFAULT_SERVER_HOST_KEY, - SERVER_HOST_KEY_BUF: SERVER_HOST_KEY_BUF, - SUPPORTED_SERVER_HOST_KEY: SUPPORTED_SERVER_HOST_KEY, - - CIPHER: DEFAULT_CIPHER, - CIPHER_BUF: CIPHER_BUF, - SUPPORTED_CIPHER: SUPPORTED_CIPHER, - - HMAC: DEFAULT_HMAC, - HMAC_BUF: HMAC_BUF, - SUPPORTED_HMAC: SUPPORTED_HMAC, - - COMPRESS: DEFAULT_COMPRESS, - COMPRESS_BUF: COMPRESS_BUF, - SUPPORTED_COMPRESS: SUPPORTED_COMPRESS -}; -exports.SSH_TO_OPENSSL = { - // ECDH key exchange - 'ecdh-sha2-nistp256': 'prime256v1', // OpenSSL's name for 'secp256r1' - 'ecdh-sha2-nistp384': 'secp384r1', - 'ecdh-sha2-nistp521': 'secp521r1', - // Ciphers - 'aes128-gcm': 'aes-128-gcm', - 'aes256-gcm': 'aes-256-gcm', - 'aes128-gcm@openssh.com': 'aes-128-gcm', - 'aes256-gcm@openssh.com': 'aes-256-gcm', - '3des-cbc': 'des-ede3-cbc', - 'blowfish-cbc': 'bf-cbc', - 'aes256-cbc': 'aes-256-cbc', - 'aes192-cbc': 'aes-192-cbc', - 'aes128-cbc': 'aes-128-cbc', - 'idea-cbc': 'idea-cbc', - 'cast128-cbc': 'cast-cbc', - 'rijndael-cbc@lysator.liu.se': 'aes-256-cbc', - 'arcfour128': 'rc4', - 'arcfour256': 'rc4', - 'arcfour512': 'rc4', - 'arcfour': 'rc4', - 'camellia128-cbc': 'camellia-128-cbc', - 'camellia192-cbc': 'camellia-192-cbc', - 'camellia256-cbc': 'camellia-256-cbc', - 'camellia128-cbc@openssh.com': 'camellia-128-cbc', - 'camellia192-cbc@openssh.com': 'camellia-192-cbc', - 'camellia256-cbc@openssh.com': 'camellia-256-cbc', - '3des-ctr': 'des-ede3', - 'blowfish-ctr': 'bf-ecb', - 'aes256-ctr': 'aes-256-ctr', - 'aes192-ctr': 'aes-192-ctr', - 'aes128-ctr': 'aes-128-ctr', - 'cast128-ctr': 'cast5-ecb', - 'camellia128-ctr': 'camellia-128-ecb', - 'camellia192-ctr': 'camellia-192-ecb', - 'camellia256-ctr': 'camellia-256-ecb', - 'camellia128-ctr@openssh.com': 'camellia-128-ecb', - 'camellia192-ctr@openssh.com': 'camellia-192-ecb', - 'camellia256-ctr@openssh.com': 'camellia-256-ecb', - // HMAC - 'hmac-sha1-96': 'sha1', - 'hmac-sha1': 'sha1', - 'hmac-sha2-256': 'sha256', - 'hmac-sha2-256-96': 'sha256', - 'hmac-sha2-512': 'sha512', - 'hmac-sha2-512-96': 'sha512', - 'hmac-md5-96': 'md5', - 'hmac-md5': 'md5', - 'hmac-ripemd160': 'ripemd160' -}; - -var BUGS = exports.BUGS = { - BAD_DHGEX: 1, - OLD_EXIT: 2, - DYN_RPORT_BUG: 4 -}; - -exports.BUGGY_IMPLS = [ - [ 'Cisco-1.25', BUGS.BAD_DHGEX ], - [ /^[0-9.]+$/, BUGS.OLD_EXIT ], // old SSH.com implementations - [ /^OpenSSH_5\.\d+/, BUGS.DYN_RPORT_BUG ] -]; diff --git a/reverse_engineering/node_modules/ssh2-streams/lib/jsbn.js b/reverse_engineering/node_modules/ssh2-streams/lib/jsbn.js deleted file mode 100644 index 309fe0d..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/lib/jsbn.js +++ /dev/null @@ -1,1186 +0,0 @@ -// Copyright (c) 2005 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Basic JavaScript BN library - subset useful for RSA encryption. - -// Bits per digit -var dbits; - -// JavaScript engine analysis -var canary = 0xdeadbeefcafe; -var j_lm = ((canary&0xffffff)==0xefcafe); - -// (public) Constructor -function BigInteger(a,b,c) { - if(a != null) - if("number" == typeof a) this.fromNumber(a,b,c); - else if(b == null && "string" != typeof a) this.fromString(a,256); - else this.fromString(a,b); -} - -// return new, unset BigInteger -function nbi() { return new BigInteger(null); } - -// am: Compute w_j += (x*this_i), propagate carries, -// c is initial carry, returns final carry. -// c < 3*dvalue, x < 2*dvalue, this_i < dvalue -// We need to select the fastest one that works in this environment. - -// Set max digit bits to 28 since some -// browsers slow down when dealing with 32-bit numbers. -function am3(i,x,w,j,c,n) { - var xl = x&0x3fff, xh = x>>14; - while(--n >= 0) { - var l = this[i]&0x3fff; - var h = this[i++]>>14; - var m = xh*l+h*xl; - l = xl*l+((m&0x3fff)<<14)+w[j]+c; - c = (l>>28)+(m>>14)+xh*h; - w[j++] = l&0xfffffff; - } - return c; -} -BigInteger.prototype.am = am3; -dbits = 28; - -BigInteger.prototype.DB = dbits; -BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; - r.t = this.t; - r.s = this.s; -} - -// (protected) set from integer value x, -DV <= x < DV -function bnpFromInt(x) { - this.t = 1; - this.s = (x<0)?-1:0; - if(x > 0) this[0] = x; - else if(x < -1) this[0] = x+this.DV; - else this.t = 0; -} - -// return bigint initialized to value -function nbv(i) { var r = nbi(); r.fromInt(i); return r; } - -// (protected) set from string and radix -function bnpFromString(s,b) { - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 256) k = 8; // byte array - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else { this.fromRadix(s,b); return; } - this.t = 0; - this.s = 0; - var i = s.length, mi = false, sh = 0; - while(--i >= 0) { - var x = (k==8)?s[i]&0xff:intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-") mi = true; - continue; - } - mi = false; - if(sh == 0) - this[this.t++] = x; - else if(sh+k > this.DB) { - this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); - } - else - this[this.t-1] |= x<= this.DB) sh -= this.DB; - } - if(k == 8 && (s[0]&0x80) != 0) { - this.s = -1; - if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; -} - -// (public) return string representation in given radix -function bnToString(b) { - if(this.s < 0) return "-"+this.negate().toString(b); - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else return this.toRadix(b); - var km = (1< 0) { - if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } - while(i >= 0) { - if(p < k) { - d = (this[i]&((1<>(p+=this.DB-k); - } - else { - d = (this[i]>>(p-=k))&km; - if(p <= 0) { p += this.DB; --i; } - } - if(d > 0) m = true; - if(m) r += int2char(d); - } - } - return m?r:"0"; -} - -// (public) -this -function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } - -// (public) |this| -function bnAbs() { return (this.s<0)?this.negate():this; } - -// (public) return + if this > a, - if this < a, 0 if equal -function bnCompareTo(a) { - var r = this.s-a.s; - if(r != 0) return r; - var i = this.t; - r = i-a.t; - if(r != 0) return (this.s<0)?-r:r; - while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; - return 0; -} - -// returns bit length of the integer x -function nbits(x) { - var r = 1, t; - if((t=x>>>16) != 0) { x = t; r += 16; } - if((t=x>>8) != 0) { x = t; r += 8; } - if((t=x>>4) != 0) { x = t; r += 4; } - if((t=x>>2) != 0) { x = t; r += 2; } - if((t=x>>1) != 0) { x = t; r += 1; } - return r; -} - -// (public) return the number of bits in "this" -function bnBitLength() { - if(this.t <= 0) return 0; - return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); -} - -// (protected) r = this << n*DB -function bnpDLShiftTo(n,r) { - var i; - for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; - for(i = n-1; i >= 0; --i) r[i] = 0; - r.t = this.t+n; - r.s = this.s; -} - -// (protected) r = this >> n*DB -function bnpDRShiftTo(n,r) { - for(var i = n; i < this.t; ++i) r[i-n] = this[i]; - r.t = Math.max(this.t-n,0); - r.s = this.s; -} - -// (protected) r = this << n -function bnpLShiftTo(n,r) { - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<= 0; --i) { - r[i+ds+1] = (this[i]>>cbs)|c; - c = (this[i]&bm)<= 0; --i) r[i] = 0; - r[ds] = c; - r.t = this.t+ds+1; - r.s = this.s; - r.clamp(); -} - -// (protected) r = this >> n -function bnpRShiftTo(n,r) { - r.s = this.s; - var ds = Math.floor(n/this.DB); - if(ds >= this.t) { r.t = 0; return; } - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<>bs; - for(var i = ds+1; i < this.t; ++i) { - r[i-ds-1] |= (this[i]&bm)<>bs; - } - if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; - } - if(a.t < this.t) { - c -= a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c -= a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c -= a.s; - } - r.s = (c<0)?-1:0; - if(c < -1) r[i++] = this.DV+c; - else if(c > 0) r[i++] = c; - r.t = i; - r.clamp(); -} - -// (protected) r = this * a, r != this,a (HAC 14.12) -// "this" should be the larger one if appropriate. -function bnpMultiplyTo(a,r) { - var x = this.abs(), y = a.abs(); - var i = x.t; - r.t = i+y.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); - r.s = 0; - r.clamp(); - if(this.s != a.s) BigInteger.ZERO.subTo(r,r); -} - -// (protected) r = this^2, r != this (HAC 14.16) -function bnpSquareTo(r) { - var x = this.abs(); - var i = r.t = 2*x.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < x.t-1; ++i) { - var c = x.am(i,x[i],r,2*i,0,1); - if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { - r[i+x.t] -= x.DV; - r[i+x.t+1] = 1; - } - } - if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); - r.s = 0; - r.clamp(); -} - -// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) -// r != q, this != m. q or r may be null. -function bnpDivRemTo(m,q,r) { - var pm = m.abs(); - if(pm.t <= 0) return; - var pt = this.abs(); - if(pt.t < pm.t) { - if(q != null) q.fromInt(0); - if(r != null) this.copyTo(r); - return; - } - if(r == null) r = nbi(); - var y = nbi(), ts = this.s, ms = m.s; - var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus - if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } - else { pm.copyTo(y); pt.copyTo(r); } - var ys = y.t; - var y0 = y[ys-1]; - if(y0 == 0) return; - var yt = y0*(1<1)?y[ys-2]>>this.F2:0); - var d1 = this.FV/yt, d2 = (1<= 0) { - r[r.t++] = 1; - r.subTo(t,r); - } - BigInteger.ONE.dlShiftTo(ys,t); - t.subTo(y,y); // "negative" y so we can replace sub with am later - while(y.t < ys) y[y.t++] = 0; - while(--j >= 0) { - // Estimate quotient digit - var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); - if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out - y.dlShiftTo(j,t); - r.subTo(t,r); - while(r[i] < --qd) r.subTo(t,r); - } - } - if(q != null) { - r.drShiftTo(ys,q); - if(ts != ms) BigInteger.ZERO.subTo(q,q); - } - r.t = ys; - r.clamp(); - if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder - if(ts < 0) BigInteger.ZERO.subTo(r,r); -} - -// (public) this mod a -function bnMod(a) { - var r = nbi(); - this.abs().divRemTo(a,null,r); - if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); - return r; -} - -// Modular reduction using "classic" algorithm -function Classic(m) { this.m = m; } -function cConvert(x) { - if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); - else return x; -} -function cRevert(x) { return x; } -function cReduce(x) { x.divRemTo(this.m,null,x); } -function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } -function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -Classic.prototype.convert = cConvert; -Classic.prototype.revert = cRevert; -Classic.prototype.reduce = cReduce; -Classic.prototype.mulTo = cMulTo; -Classic.prototype.sqrTo = cSqrTo; - -// (protected) return "-1/this % 2^DB"; useful for Mont. reduction -// justification: -// xy == 1 (mod m) -// xy = 1+km -// xy(2-xy) = (1+km)(1-km) -// x[y(2-xy)] = 1-k^2m^2 -// x[y(2-xy)] == 1 (mod m^2) -// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 -// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. -// JS multiply "overflows" differently from C/C++, so care is needed here. -function bnpInvDigit() { - if(this.t < 1) return 0; - var x = this[0]; - if((x&1) == 0) return 0; - var y = x&3; // y == 1/x mod 2^2 - y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 - y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 - y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 - // last step - calculate inverse mod DV directly; - // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints - y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits - // we really want the negative inverse, and -DV < y < DV - return (y>0)?this.DV-y:-y; -} - -// Montgomery reduction -function Montgomery(m) { - this.m = m; - this.mp = m.invDigit(); - this.mpl = this.mp&0x7fff; - this.mph = this.mp>>15; - this.um = (1<<(m.DB-15))-1; - this.mt2 = 2*m.t; -} - -// xR mod m -function montConvert(x) { - var r = nbi(); - x.abs().dlShiftTo(this.m.t,r); - r.divRemTo(this.m,null,r); - if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); - return r; -} - -// x/R mod m -function montRevert(x) { - var r = nbi(); - x.copyTo(r); - this.reduce(r); - return r; -} - -// x = x/R mod m (HAC 14.32) -function montReduce(x) { - while(x.t <= this.mt2) // pad x so am has enough room later - x[x.t++] = 0; - for(var i = 0; i < this.m.t; ++i) { - // faster way of calculating u0 = x[i]*mp mod DV - var j = x[i]&0x7fff; - var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; - // use am to combine the multiply-shift-add into one call - j = i+this.m.t; - x[j] += this.m.am(0,u0,x,i,0,this.m.t); - // propagate carry - while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } - } - x.clamp(); - x.drShiftTo(this.m.t,x); - if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = "x^2/R mod m"; x != r -function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = "xy/R mod m"; x,y != r -function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Montgomery.prototype.convert = montConvert; -Montgomery.prototype.revert = montRevert; -Montgomery.prototype.reduce = montReduce; -Montgomery.prototype.mulTo = montMulTo; -Montgomery.prototype.sqrTo = montSqrTo; - -// (protected) true iff this is even -function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } - -// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) -function bnpExp(e,z) { - if(e > 0xffffffff || e < 1) return BigInteger.ONE; - var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; - g.copyTo(r); - while(--i >= 0) { - z.sqrTo(r,r2); - if((e&(1< 0) z.mulTo(r2,g,r); - else { var t = r; r = r2; r2 = t; } - } - return z.revert(r); -} - -// (public) this^e % m, 0 <= e < 2^32 -function bnModPowInt(e,m) { - var z; - if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); - return this.exp(e,z); -} - -// protected -BigInteger.prototype.copyTo = bnpCopyTo; -BigInteger.prototype.fromInt = bnpFromInt; -BigInteger.prototype.fromString = bnpFromString; -BigInteger.prototype.clamp = bnpClamp; -BigInteger.prototype.dlShiftTo = bnpDLShiftTo; -BigInteger.prototype.drShiftTo = bnpDRShiftTo; -BigInteger.prototype.lShiftTo = bnpLShiftTo; -BigInteger.prototype.rShiftTo = bnpRShiftTo; -BigInteger.prototype.subTo = bnpSubTo; -BigInteger.prototype.multiplyTo = bnpMultiplyTo; -BigInteger.prototype.squareTo = bnpSquareTo; -BigInteger.prototype.divRemTo = bnpDivRemTo; -BigInteger.prototype.invDigit = bnpInvDigit; -BigInteger.prototype.isEven = bnpIsEven; -BigInteger.prototype.exp = bnpExp; - -// public -BigInteger.prototype.toString = bnToString; -BigInteger.prototype.negate = bnNegate; -BigInteger.prototype.abs = bnAbs; -BigInteger.prototype.compareTo = bnCompareTo; -BigInteger.prototype.bitLength = bnBitLength; -BigInteger.prototype.mod = bnMod; -BigInteger.prototype.modPowInt = bnModPowInt; - -// "constants" -BigInteger.ZERO = nbv(0); -BigInteger.ONE = nbv(1); - -// Copyright (c) 2005-2009 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Extended JavaScript BN functions, required for RSA private ops. - -// Version 1.1: new BigInteger("0", 10) returns "proper" zero -// Version 1.2: square() API, isProbablePrime fix - -// (public) -function bnClone() { var r = nbi(); this.copyTo(r); return r; } - -// (public) return value as integer -function bnIntValue() { - if(this.s < 0) { - if(this.t == 1) return this[0]-this.DV; - else if(this.t == 0) return -1; - } - else if(this.t == 1) return this[0]; - else if(this.t == 0) return 0; - // assumes 16 < DB < 32 - return ((this[1]&((1<<(32-this.DB))-1))<>24; } - -// (public) return value as short (assumes DB>=16) -function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } - -// (protected) return x s.t. r^x < DV -function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } - -// (public) 0 if this == 0, 1 if this > 0 -function bnSigNum() { - if(this.s < 0) return -1; - else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; - else return 1; -} - -// (protected) convert to radix string -function bnpToRadix(b) { - if(b == null) b = 10; - if(this.signum() == 0 || b < 2 || b > 36) return "0"; - var cs = this.chunkSize(b); - var a = Math.pow(b,cs); - var d = nbv(a), y = nbi(), z = nbi(), r = ""; - this.divRemTo(d,y,z); - while(y.signum() > 0) { - r = (a+z.intValue()).toString(b).substr(1) + r; - y.divRemTo(d,y,z); - } - return z.intValue().toString(b) + r; -} - -// (protected) convert from radix string -function bnpFromRadix(s,b) { - this.fromInt(0); - if(b == null) b = 10; - var cs = this.chunkSize(b); - var d = Math.pow(b,cs), mi = false, j = 0, w = 0; - for(var i = 0; i < s.length; ++i) { - var x = intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-" && this.signum() == 0) mi = true; - continue; - } - w = b*w+x; - if(++j >= cs) { - this.dMultiply(d); - this.dAddOffset(w,0); - j = 0; - w = 0; - } - } - if(j > 0) { - this.dMultiply(Math.pow(b,j)); - this.dAddOffset(w,0); - } - if(mi) BigInteger.ZERO.subTo(this,this); -} - -// (protected) alternate constructor -function bnpFromNumber(a,b,c) { - if("number" == typeof b) { - // new BigInteger(int,int,RNG) - if(a < 2) this.fromInt(1); - else { - this.fromNumber(a,c); - if(!this.testBit(a-1)) // force MSB set - this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); - if(this.isEven()) this.dAddOffset(1,0); // force odd - while(!this.isProbablePrime(b)) { - this.dAddOffset(2,0); - if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); - } - } - } - else { - // new BigInteger(int,RNG) - var x = new Array(), t = a&7; - x.length = (a>>3)+1; - b.nextBytes(x); - if(t > 0) x[0] &= ((1< 0) { - if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) - r[k++] = d|(this.s<<(this.DB-p)); - while(i >= 0) { - if(p < 8) { - d = (this[i]&((1<>(p+=this.DB-8); - } - else { - d = (this[i]>>(p-=8))&0xff; - if(p <= 0) { p += this.DB; --i; } - } - if((d&0x80) != 0) d |= -256; - if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; - if(k > 0 || d != this.s) r[k++] = d; - } - } - return r; -} - -function bnEquals(a) { return(this.compareTo(a)==0); } -function bnMin(a) { return(this.compareTo(a)<0)?this:a; } -function bnMax(a) { return(this.compareTo(a)>0)?this:a; } - -// (protected) r = this op a (bitwise) -function bnpBitwiseTo(a,op,r) { - var i, f, m = Math.min(a.t,this.t); - for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); - if(a.t < this.t) { - f = a.s&this.DM; - for(i = m; i < this.t; ++i) r[i] = op(this[i],f); - r.t = this.t; - } - else { - f = this.s&this.DM; - for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); - r.t = a.t; - } - r.s = op(this.s,a.s); - r.clamp(); -} - -// (public) this & a -function op_and(x,y) { return x&y; } -function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } - -// (public) this | a -function op_or(x,y) { return x|y; } -function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } - -// (public) this ^ a -function op_xor(x,y) { return x^y; } -function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } - -// (public) this & ~a -function op_andnot(x,y) { return x&~y; } -function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } - -// (public) ~this -function bnNot() { - var r = nbi(); - for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; - r.t = this.t; - r.s = ~this.s; - return r; -} - -// (public) this << n -function bnShiftLeft(n) { - var r = nbi(); - if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); - return r; -} - -// (public) this >> n -function bnShiftRight(n) { - var r = nbi(); - if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); - return r; -} - -// return index of lowest 1-bit in x, x < 2^31 -function lbit(x) { - if(x == 0) return -1; - var r = 0; - if((x&0xffff) == 0) { x >>= 16; r += 16; } - if((x&0xff) == 0) { x >>= 8; r += 8; } - if((x&0xf) == 0) { x >>= 4; r += 4; } - if((x&3) == 0) { x >>= 2; r += 2; } - if((x&1) == 0) ++r; - return r; -} - -// (public) returns index of lowest 1-bit (or -1 if none) -function bnGetLowestSetBit() { - for(var i = 0; i < this.t; ++i) - if(this[i] != 0) return i*this.DB+lbit(this[i]); - if(this.s < 0) return this.t*this.DB; - return -1; -} - -// return number of 1 bits in x -function cbit(x) { - var r = 0; - while(x != 0) { x &= x-1; ++r; } - return r; -} - -// (public) return number of set bits -function bnBitCount() { - var r = 0, x = this.s&this.DM; - for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); - return r; -} - -// (public) true iff nth bit is set -function bnTestBit(n) { - var j = Math.floor(n/this.DB); - if(j >= this.t) return(this.s!=0); - return((this[j]&(1<<(n%this.DB)))!=0); -} - -// (protected) this op (1<>= this.DB; - } - if(a.t < this.t) { - c += a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c += a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += a.s; - } - r.s = (c<0)?-1:0; - if(c > 0) r[i++] = c; - else if(c < -1) r[i++] = this.DV+c; - r.t = i; - r.clamp(); -} - -// (public) this + a -function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } - -// (public) this - a -function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } - -// (public) this * a -function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } - -// (public) this^2 -function bnSquare() { var r = nbi(); this.squareTo(r); return r; } - -// (public) this / a -function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } - -// (public) this % a -function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } - -// (public) [this/a,this%a] -function bnDivideAndRemainder(a) { - var q = nbi(), r = nbi(); - this.divRemTo(a,q,r); - return new Array(q,r); -} - -// (protected) this *= n, this >= 0, 1 < n < DV -function bnpDMultiply(n) { - this[this.t] = this.am(0,n-1,this,0,0,this.t); - ++this.t; - this.clamp(); -} - -// (protected) this += n << w words, this >= 0 -function bnpDAddOffset(n,w) { - if(n == 0) return; - while(this.t <= w) this[this.t++] = 0; - this[w] += n; - while(this[w] >= this.DV) { - this[w] -= this.DV; - if(++w >= this.t) this[this.t++] = 0; - ++this[w]; - } -} - -// A "null" reducer -function NullExp() {} -function nNop(x) { return x; } -function nMulTo(x,y,r) { x.multiplyTo(y,r); } -function nSqrTo(x,r) { x.squareTo(r); } - -NullExp.prototype.convert = nNop; -NullExp.prototype.revert = nNop; -NullExp.prototype.mulTo = nMulTo; -NullExp.prototype.sqrTo = nSqrTo; - -// (public) this^e -function bnPow(e) { return this.exp(e,new NullExp()); } - -// (protected) r = lower n words of "this * a", a.t <= n -// "this" should be the larger one if appropriate. -function bnpMultiplyLowerTo(a,n,r) { - var i = Math.min(this.t+a.t,n); - r.s = 0; // assumes a,this >= 0 - r.t = i; - while(i > 0) r[--i] = 0; - var j; - for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); - for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); - r.clamp(); -} - -// (protected) r = "this * a" without lower n words, n > 0 -// "this" should be the larger one if appropriate. -function bnpMultiplyUpperTo(a,n,r) { - --n; - var i = r.t = this.t+a.t-n; - r.s = 0; // assumes a,this >= 0 - while(--i >= 0) r[i] = 0; - for(i = Math.max(n-this.t,0); i < a.t; ++i) - r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); - r.clamp(); - r.drShiftTo(1,r); -} - -// Barrett modular reduction -function Barrett(m) { - // setup Barrett - this.r2 = nbi(); - this.q3 = nbi(); - BigInteger.ONE.dlShiftTo(2*m.t,this.r2); - this.mu = this.r2.divide(m); - this.m = m; -} - -function barrettConvert(x) { - if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); - else if(x.compareTo(this.m) < 0) return x; - else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } -} - -function barrettRevert(x) { return x; } - -// x = x mod m (HAC 14.42) -function barrettReduce(x) { - x.drShiftTo(this.m.t-1,this.r2); - if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } - this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); - this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); - while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); - x.subTo(this.r2,x); - while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = x^2 mod m; x != r -function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = x*y mod m; x,y != r -function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Barrett.prototype.convert = barrettConvert; -Barrett.prototype.revert = barrettRevert; -Barrett.prototype.reduce = barrettReduce; -Barrett.prototype.mulTo = barrettMulTo; -Barrett.prototype.sqrTo = barrettSqrTo; - -// (public) this^e % m (HAC 14.85) -function bnModPow(e,m) { - var i = e.bitLength(), k, r = nbv(1), z; - if(i <= 0) return r; - else if(i < 18) k = 1; - else if(i < 48) k = 3; - else if(i < 144) k = 4; - else if(i < 768) k = 5; - else k = 6; - if(i < 8) - z = new Classic(m); - else if(m.isEven()) - z = new Barrett(m); - else - z = new Montgomery(m); - - // precomputation - var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { - var g2 = nbi(); - z.sqrTo(g[1],g2); - while(n <= km) { - g[n] = nbi(); - z.mulTo(g2,g[n-2],g[n]); - n += 2; - } - } - - var j = e.t-1, w, is1 = true, r2 = nbi(), t; - i = nbits(e[j])-1; - while(j >= 0) { - if(i >= k1) w = (e[j]>>(i-k1))&km; - else { - w = (e[j]&((1<<(i+1))-1))<<(k1-i); - if(j > 0) w |= e[j-1]>>(this.DB+i-k1); - } - - n = k; - while((w&1) == 0) { w >>= 1; --n; } - if((i -= n) < 0) { i += this.DB; --j; } - if(is1) { // ret == 1, don't bother squaring or multiplying it - g[w].copyTo(r); - is1 = false; - } - else { - while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } - if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } - z.mulTo(r2,g[w],r); - } - - while(j >= 0 && (e[j]&(1< 0) { - x.rShiftTo(g,x); - y.rShiftTo(g,y); - } - while(x.signum() > 0) { - if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); - if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); - if(x.compareTo(y) >= 0) { - x.subTo(y,x); - x.rShiftTo(1,x); - } - else { - y.subTo(x,y); - y.rShiftTo(1,y); - } - } - if(g > 0) y.lShiftTo(g,y); - return y; -} - -// (protected) this % n, n < 2^26 -function bnpModInt(n) { - if(n <= 0) return 0; - var d = this.DV%n, r = (this.s<0)?n-1:0; - if(this.t > 0) - if(d == 0) r = this[0]%n; - else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; - return r; -} - -// (public) 1/this % m (HAC 14.61) -function bnModInverse(m) { - var ac = m.isEven(); - if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; - var u = m.clone(), v = this.clone(); - var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); - while(u.signum() != 0) { - while(u.isEven()) { - u.rShiftTo(1,u); - if(ac) { - if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } - a.rShiftTo(1,a); - } - else if(!b.isEven()) b.subTo(m,b); - b.rShiftTo(1,b); - } - while(v.isEven()) { - v.rShiftTo(1,v); - if(ac) { - if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } - c.rShiftTo(1,c); - } - else if(!d.isEven()) d.subTo(m,d); - d.rShiftTo(1,d); - } - if(u.compareTo(v) >= 0) { - u.subTo(v,u); - if(ac) a.subTo(c,a); - b.subTo(d,b); - } - else { - v.subTo(u,v); - if(ac) c.subTo(a,c); - d.subTo(b,d); - } - } - if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; - if(d.compareTo(m) >= 0) return d.subtract(m); - if(d.signum() < 0) d.addTo(m,d); else return d; - if(d.signum() < 0) return d.add(m); else return d; -} - -var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; -var lplim = (1<<26)/lowprimes[lowprimes.length-1]; - -// (public) test primality with certainty >= 1-.5^t -function bnIsProbablePrime(t) { - var i, x = this.abs(); - if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { - for(i = 0; i < lowprimes.length; ++i) - if(x[0] == lowprimes[i]) return true; - return false; - } - if(x.isEven()) return false; - i = 1; - while(i < lowprimes.length) { - var m = lowprimes[i], j = i+1; - while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; - m = x.modInt(m); - while(i < j) if(m%lowprimes[i++] == 0) return false; - } - return x.millerRabin(t); -} - -// (protected) true if probably prime (HAC 4.24, Miller-Rabin) -function bnpMillerRabin(t) { - var n1 = this.subtract(BigInteger.ONE); - var k = n1.getLowestSetBit(); - if(k <= 0) return false; - var r = n1.shiftRight(k); - t = (t+1)>>1; - if(t > lowprimes.length) t = lowprimes.length; - var a = nbi(); - for(var i = 0; i < t; ++i) { - //Pick bases at random, instead of starting at 2 - a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); - var y = a.modPow(r,this); - if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { - var j = 1; - while(j++ < k && y.compareTo(n1) != 0) { - y = y.modPowInt(2,this); - if(y.compareTo(BigInteger.ONE) == 0) return false; - } - if(y.compareTo(n1) != 0) return false; - } - } - return true; -} - -// protected -BigInteger.prototype.chunkSize = bnpChunkSize; -BigInteger.prototype.toRadix = bnpToRadix; -BigInteger.prototype.fromRadix = bnpFromRadix; -BigInteger.prototype.fromNumber = bnpFromNumber; -BigInteger.prototype.bitwiseTo = bnpBitwiseTo; -BigInteger.prototype.changeBit = bnpChangeBit; -BigInteger.prototype.addTo = bnpAddTo; -BigInteger.prototype.dMultiply = bnpDMultiply; -BigInteger.prototype.dAddOffset = bnpDAddOffset; -BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; -BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; -BigInteger.prototype.modInt = bnpModInt; -BigInteger.prototype.millerRabin = bnpMillerRabin; - -// public -BigInteger.prototype.clone = bnClone; -BigInteger.prototype.intValue = bnIntValue; -BigInteger.prototype.byteValue = bnByteValue; -BigInteger.prototype.shortValue = bnShortValue; -BigInteger.prototype.signum = bnSigNum; -BigInteger.prototype.toByteArray = bnToByteArray; -BigInteger.prototype.equals = bnEquals; -BigInteger.prototype.min = bnMin; -BigInteger.prototype.max = bnMax; -BigInteger.prototype.and = bnAnd; -BigInteger.prototype.or = bnOr; -BigInteger.prototype.xor = bnXor; -BigInteger.prototype.andNot = bnAndNot; -BigInteger.prototype.not = bnNot; -BigInteger.prototype.shiftLeft = bnShiftLeft; -BigInteger.prototype.shiftRight = bnShiftRight; -BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; -BigInteger.prototype.bitCount = bnBitCount; -BigInteger.prototype.testBit = bnTestBit; -BigInteger.prototype.setBit = bnSetBit; -BigInteger.prototype.clearBit = bnClearBit; -BigInteger.prototype.flipBit = bnFlipBit; -BigInteger.prototype.add = bnAdd; -BigInteger.prototype.subtract = bnSubtract; -BigInteger.prototype.multiply = bnMultiply; -BigInteger.prototype.divide = bnDivide; -BigInteger.prototype.remainder = bnRemainder; -BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; -BigInteger.prototype.modPow = bnModPow; -BigInteger.prototype.modInverse = bnModInverse; -BigInteger.prototype.pow = bnPow; -BigInteger.prototype.gcd = bnGCD; -BigInteger.prototype.isProbablePrime = bnIsProbablePrime; - -// JSBN-specific extension -BigInteger.prototype.square = bnSquare; - -// Expose the Barrett function -BigInteger.prototype.Barrett = Barrett - -// BigInteger interfaces not implemented in jsbn: - -// BigInteger(int signum, byte[] magnitude) -// double doubleValue() -// float floatValue() -// int hashCode() -// long longValue() -// static BigInteger valueOf(long val) - -module.exports = BigInteger; - diff --git a/reverse_engineering/node_modules/ssh2-streams/lib/keyParser.js b/reverse_engineering/node_modules/ssh2-streams/lib/keyParser.js deleted file mode 100644 index 937f08d..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/lib/keyParser.js +++ /dev/null @@ -1,239 +0,0 @@ -// TODO: -// * handle multi-line header values (OpenSSH)? -// * more thorough validation? - -var utils; -var Ber = require('asn1').Ber; -var semver = require('semver'); - -var RE_PPK = /^PuTTY-User-Key-File-2: ssh-(rsa|dss)\r?\nEncryption: (aes256-cbc|none)\r?\nComment: ([^\r\n]*)\r?\nPublic-Lines: \d+\r?\n([\s\S]+?)\r?\nPrivate-Lines: \d+\r?\n([\s\S]+?)\r?\nPrivate-MAC: ([^\r\n]+)/; -var RE_HEADER_OPENSSH_PRIV = /^-----BEGIN (RSA|DSA|EC) PRIVATE KEY-----$/i; -var RE_FOOTER_OPENSSH_PRIV = /^-----END (?:RSA|DSA|EC) PRIVATE KEY-----$/i; -var RE_HEADER_OPENSSH_PUB = /^((?:(?:ssh-(rsa|dss))|ecdsa-sha2-nistp(256|384|521))(?:-cert-v0[01]@openssh.com)?) ([A-Z0-9a-z\/+=]+)(?:$|\s+([\S].*)?)$/i; -var RE_HEADER_RFC4716_PUB = /^---- BEGIN SSH2 PUBLIC KEY ----$/i; -var RE_FOOTER_RFC4716_PUB = /^---- END SSH2 PUBLIC KEY ----$/i; -var RE_HEADER_OPENSSH = /^([^:]+):\s*([\S].*)?$/i; -var RE_HEADER_RFC4716 = /^([^:]+): (.*)?$/i; - -module.exports = function(data) { - if (Buffer.isBuffer(data)) - data = data.toString('utf8'); - else if (typeof data !== 'string') - return new Error('Key data must be a Buffer or string'); - - var ret = { - fulltype: undefined, - type: undefined, - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: undefined, - publicOrig: undefined - }; - var m; - var i; - var len; - - data = data.trim().split(/\r\n|\n/); - - while (!data[0].length) - data.shift(); - while (!data.slice(-1)[0].length) - data.pop(); - - var orig = data.join('\n'); - - if ((m = RE_HEADER_OPENSSH_PRIV.exec(data[0])) - && RE_FOOTER_OPENSSH_PRIV.test(data.slice(-1))) { - // OpenSSH private key - var keyType = m[1].toLowerCase(); - if (keyType === 'dsa') - keyType = 'dss'; - - if (keyType === 'ec' && semver.lt(process.version, '5.2.0')) { - return new Error( - 'EC private keys are not supported in this version of node' - ); - } - - if (!RE_HEADER_OPENSSH.test(data[1])) { - // unencrypted, no headers - var privData = new Buffer(data.slice(1, -1).join(''), 'base64'); - if (keyType !== 'ec') { - ret.fulltype = 'ssh-' + keyType; - } else { - // ECDSA - var asnReader = new Ber.Reader(privData); - asnReader.readSequence(); - asnReader.readInt(); - asnReader.readString(Ber.OctetString, true); - asnReader.readByte(); // Skip "complex" context type byte - var offset = asnReader.readLength(); // Skip context length - if (offset !== null) { - asnReader._offset = offset; - switch (asnReader.readOID()) { - case '1.2.840.10045.3.1.7': - // prime256v1/secp256r1 - ret.fulltype = 'ecdsa-sha2-nistp256'; - break; - case '1.3.132.0.34': - // secp384r1 - ret.fulltype = 'ecdsa-sha2-nistp384'; - break; - case '1.3.132.0.35': - // secp521r1 - ret.fulltype = 'ecdsa-sha2-nistp521'; - break; - } - } - if (ret.fulltype === undefined) - return new Error('Unsupported EC private key type'); - } - ret.private = privData; - } else { - // possibly encrypted, headers - for (i = 1, len = data.length; i < len; ++i) { - m = RE_HEADER_OPENSSH.exec(data[i]); - if (m) { - m[1] = m[1].toLowerCase(); - if (m[1] === 'dek-info') { - m[2] = m[2].split(','); - ret.encryption = m[2][0].toLowerCase(); - if (m[2].length > 1) - ret.extra = m[2].slice(1); - } - } else if (data[i].length) - break; - } - ret.private = new Buffer(data.slice(i, -1).join(''), 'base64'); - } - ret.type = keyType; - ret.privateOrig = new Buffer(orig); - } else if (m = RE_HEADER_OPENSSH_PUB.exec(data[0])) { - // OpenSSH public key - ret.fulltype = m[1]; - ret.type = (m[2] || 'ec').toLowerCase(); - ret.public = new Buffer(m[4], 'base64'); - ret.publicOrig = new Buffer(orig); - ret.comment = m[5]; - if (m[3]) // ECDSA only - ret.curve = 'nistp' + m[3]; - } else if (RE_HEADER_RFC4716_PUB.test(data[0]) - && RE_FOOTER_RFC4716_PUB.test(data.slice(-1))) { - if (data[1].indexOf(': ') === -1) { - // no headers - ret.public = new Buffer(data.slice(1, -1).join(''), 'base64'); - } else { - // headers - for (i = 1, len = data.length; i < len; ++i) { - if (data[i].indexOf(': ') === -1) { - if (data[i].length) - break; // start of key data - else - continue; // empty line - } - while (data[i].substr(-1) === '\\') { - if (i + 1 < len) { - data[i] = data[i].slice(0, -1) + data[i + 1]; - data.splice(i + 1, 1); - --len; - } else - return new Error('RFC4716 public key missing header continuation line'); - } - m = RE_HEADER_RFC4716.exec(data[i]); - if (m) { - m[1] = m[1].toLowerCase(); - if (m[1] === 'comment') { - ret.comment = m[2] || ''; - if (ret.comment[0] === '"' && ret.comment.substr(-1) === '"') - ret.comment = ret.comment.slice(1, -1); - } - } else - return new Error('RFC4716 public key invalid header line'); - } - ret.public = new Buffer(data.slice(i, -1).join(''), 'base64'); - } - len = ret.public.readUInt32BE(0, true); - var fulltype = ret.public.toString('ascii', 4, 4 + len); - ret.fulltype = fulltype; - if (fulltype === 'ssh-dss') - ret.type = 'dss'; - else if (fulltype === 'ssh-rsa') - ret.type = 'rsa'; - else - return new Error('Unsupported RFC4716 public key type: ' + fulltype); - ret.public = ret.public.slice(11); - ret.publicOrig = new Buffer(orig); - } else if (m = RE_PPK.exec(orig)) { - // m[1] = short type - // m[2] = encryption type - // m[3] = comment - // m[4] = base64-encoded public key data: - // for "ssh-rsa": - // string "ssh-rsa" - // mpint e (public exponent) - // mpint n (modulus) - // for "ssh-dss": - // string "ssh-dss" - // mpint p (modulus) - // mpint q (prime) - // mpint g (base number) - // mpint y (public key parameter: g^x mod p) - // m[5] = base64-encoded private key data: - // for "ssh-rsa": - // mpint d (private exponent) - // mpint p (prime 1) - // mpint q (prime 2) - // mpint iqmp ([inverse of q] mod p) - // for "ssh-dss": - // mpint x (private key parameter) - // m[6] = SHA1 HMAC over: - // string name of algorithm ("ssh-dss", "ssh-rsa") - // string encryption type - // string comment - // string public key data - // string private-plaintext (including the final padding) - - // avoid cyclic require by requiring on first use - if (!utils) - utils = require('./utils'); - - ret.ppk = true; - ret.type = m[1]; - ret.fulltype = 'ssh-' + m[1]; - if (m[2] !== 'none') - ret.encryption = m[2]; - ret.comment = m[3]; - - ret.public = new Buffer(m[4].replace(/\r?\n/g, ''), 'base64'); - var privateKey = new Buffer(m[5].replace(/\r?\n/g, ''), 'base64'); - - ret.privateMAC = m[6].replace(/\r?\n/g, ''); - - // automatically verify private key MAC if we don't need to wait for - // decryption - if (!ret.encryption) { - var valid = utils.verifyPPKMAC(ret, undefined, privateKey); - if (!valid) - throw new Error('PPK MAC mismatch'); - } - - // generate a PEM encoded version of the public key - var pubkey = utils.genPublicKey(ret); - ret.public = pubkey.public; - ret.publicOrig = pubkey.publicOrig; - - ret.private = privateKey; - - // automatically convert private key data to OpenSSL format (including PEM) - // if we don't need to wait for decryption - if (!ret.encryption) - utils.convertPPKPrivate(ret); - } else - return new Error('Unsupported key format'); - - return ret; -}; diff --git a/reverse_engineering/node_modules/ssh2-streams/lib/sftp.js b/reverse_engineering/node_modules/ssh2-streams/lib/sftp.js deleted file mode 100644 index 9e93200..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/lib/sftp.js +++ /dev/null @@ -1,2967 +0,0 @@ -// TODO: support EXTENDED request packets - -var TransformStream = require('stream').Transform; -var ReadableStream = require('stream').Readable; -var WritableStream = require('stream').Writable; -var constants = require('fs').constants || process.binding('constants'); -var util = require('util'); -var inherits = util.inherits; -var isDate = util.isDate; -var listenerCount = require('events').EventEmitter.listenerCount; -var fs = require('fs'); - -var readString = require('./utils').readString; -var readInt = require('./utils').readInt; - -var ATTR = { - SIZE: 0x00000001, - UIDGID: 0x00000002, - PERMISSIONS: 0x00000004, - ACMODTIME: 0x00000008, - EXTENDED: 0x80000000 -}; - -var STATUS_CODE = { - OK: 0, - EOF: 1, - NO_SUCH_FILE: 2, - PERMISSION_DENIED: 3, - FAILURE: 4, - BAD_MESSAGE: 5, - NO_CONNECTION: 6, - CONNECTION_LOST: 7, - OP_UNSUPPORTED: 8 -}; -Object.keys(STATUS_CODE).forEach(function(key) { - STATUS_CODE[STATUS_CODE[key]] = key; -}); -var STATUS_CODE_STR = { - 0: 'No error', - 1: 'End of file', - 2: 'No such file or directory', - 3: 'Permission denied', - 4: 'Failure', - 5: 'Bad message', - 6: 'No connection', - 7: 'Connection lost', - 8: 'Operation unsupported' -}; -SFTPStream.STATUS_CODE = STATUS_CODE; - -var REQUEST = { - INIT: 1, - OPEN: 3, - CLOSE: 4, - READ: 5, - WRITE: 6, - LSTAT: 7, - FSTAT: 8, - SETSTAT: 9, - FSETSTAT: 10, - OPENDIR: 11, - READDIR: 12, - REMOVE: 13, - MKDIR: 14, - RMDIR: 15, - REALPATH: 16, - STAT: 17, - RENAME: 18, - READLINK: 19, - SYMLINK: 20, - EXTENDED: 200 -}; -Object.keys(REQUEST).forEach(function(key) { - REQUEST[REQUEST[key]] = key; -}); - -var RESPONSE = { - VERSION: 2, - STATUS: 101, - HANDLE: 102, - DATA: 103, - NAME: 104, - ATTRS: 105, - EXTENDED: 201 -}; -Object.keys(RESPONSE).forEach(function(key) { - RESPONSE[RESPONSE[key]] = key; -}); - -var OPEN_MODE = { - READ: 0x00000001, - WRITE: 0x00000002, - APPEND: 0x00000004, - CREAT: 0x00000008, - TRUNC: 0x00000010, - EXCL: 0x00000020 -}; -SFTPStream.OPEN_MODE = OPEN_MODE; - -var MAX_PKT_LEN = 34000; -var MAX_REQID = Math.pow(2, 32) - 1; -var CLIENT_VERSION_BUFFER = new Buffer([0, 0, 0, 5 /* length */, - REQUEST.INIT, - 0, 0, 0, 3 /* version */]); -var SERVER_VERSION_BUFFER = new Buffer([0, 0, 0, 5 /* length */, - RESPONSE.VERSION, - 0, 0, 0, 3 /* version */]); -/* - http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02: - - The maximum size of a packet is in practice determined by the client - (the maximum size of read or write requests that it sends, plus a few - bytes of packet overhead). All servers SHOULD support packets of at - least 34000 bytes (where the packet size refers to the full length, - including the header above). This should allow for reads and writes - of at most 32768 bytes. - - OpenSSH caps this to 256kb instead of the ~34kb as mentioned in the sftpv3 - spec. -*/ -var RE_OPENSSH = /^SSH-2.0-(?:OpenSSH|dropbear)/; -var OPENSSH_MAX_DATA_LEN = (256 * 1024) - (2 * 1024)/*account for header data*/; - -function DEBUG_NOOP(msg) {} - -function SFTPStream(cfg, remoteIdentRaw) { - if (typeof cfg === 'string' && !remoteIdentRaw) { - remoteIdentRaw = cfg; - cfg = undefined; - } - if (typeof cfg !== 'object' || !cfg) - cfg = {}; - - TransformStream.call(this, { - highWaterMark: (typeof cfg.highWaterMark === 'number' - ? cfg.highWaterMark - : 32 * 1024) - }); - - this.debug = (typeof cfg.debug === 'function' ? cfg.debug : DEBUG_NOOP); - this.server = (cfg.server ? true : false); - this._isOpenSSH = (remoteIdentRaw && RE_OPENSSH.test(remoteIdentRaw)); - this._needContinue = false; - this._state = { - // common - status: 'packet_header', - writeReqid: -1, - pktLeft: undefined, - pktHdrBuf: new Buffer(9), // room for pktLen + pktType + req id - pktBuf: undefined, - pktType: undefined, - version: undefined, - extensions: {}, - - // client - maxDataLen: (this._isOpenSSH ? OPENSSH_MAX_DATA_LEN : 32768), - requests: {} - }; - - var self = this; - this.on('end', function() { - self.readable = false; - }).on('finish', onFinish) - .on('prefinish', onFinish); - function onFinish() { - self.writable = false; - self._cleanup(false); - } - - if (!this.server) - this.push(CLIENT_VERSION_BUFFER); -} -inherits(SFTPStream, TransformStream); - -SFTPStream.prototype.__read = TransformStream.prototype._read; -SFTPStream.prototype._read = function(n) { - if (this._needContinue) { - this._needContinue = false; - this.emit('continue'); - } - return this.__read(n); -}; -SFTPStream.prototype.__push = TransformStream.prototype.push; -SFTPStream.prototype.push = function(chunk, encoding) { - if (!this.readable) - return false; - if (chunk === null) - this.readable = false; - var ret = this.__push(chunk, encoding); - this._needContinue = (ret === false); - return ret; -}; - -SFTPStream.prototype._cleanup = function(callback) { - var state = this._state; - - state.pktBuf = undefined; // give GC something to do - - var requests = state.requests; - var keys = Object.keys(requests); - var len = keys.length; - if (len) { - if (this.readable) { - var err = new Error('SFTP session ended early'); - for (var i = 0, cb; i < len; ++i) - (cb = requests[keys[i]].cb) && cb(err); - } - state.requests = {}; - } - - if (this.readable) - this.push(null); - if (!this._readableState.endEmitted && !this._readableState.flowing) { - // Ugh! - this.resume(); - } - if (callback !== false) { - this.debug('DEBUG[SFTP]: Parser: Malformed packet'); - callback && callback(new Error('Malformed packet')); - } -}; - -SFTPStream.prototype._transform = function(chunk, encoding, callback) { - var state = this._state; - var server = this.server; - var status = state.status; - var pktType = state.pktType; - var pktBuf = state.pktBuf; - var pktLeft = state.pktLeft; - var version = state.version; - var pktHdrBuf = state.pktHdrBuf; - var requests = state.requests; - var debug = this.debug; - var chunkLen = chunk.length; - var chunkPos = 0; - var buffer; - var chunkLeft; - var id; - - while (true) { - if (status === 'discard') { - chunkLeft = (chunkLen - chunkPos); - if (pktLeft <= chunkLeft) { - chunkPos += pktLeft; - pktLeft = 0; - status = 'packet_header'; - buffer = pktBuf = undefined; - } else { - pktLeft -= chunkLeft; - break; - } - } else if (pktBuf !== undefined) { - chunkLeft = (chunkLen - chunkPos); - if (pktLeft <= chunkLeft) { - chunk.copy(pktBuf, - pktBuf.length - pktLeft, - chunkPos, - chunkPos + pktLeft); - chunkPos += pktLeft; - pktLeft = 0; - buffer = pktBuf; - pktBuf = undefined; - continue; - } else { - chunk.copy(pktBuf, pktBuf.length - pktLeft, chunkPos); - pktLeft -= chunkLeft; - break; - } - } else if (status === 'packet_header') { - if (!buffer) { - pktLeft = 5; - pktBuf = pktHdrBuf; - } else { - // here we read the right-most 5 bytes from buffer (pktHdrBuf) - pktLeft = buffer.readUInt32BE(4, true) - 1; // account for type byte - pktType = buffer[8]; - - if (server) { - if (version === undefined && pktType !== REQUEST.INIT) { - debug('DEBUG[SFTP]: Parser: Unexpected packet before init'); - this._cleanup(false); - return callback(new Error('Unexpected packet before init')); - } else if (version !== undefined && pktType === REQUEST.INIT) { - debug('DEBUG[SFTP]: Parser: Unexpected duplicate init'); - status = 'bad_pkt'; - } else if (pktLeft > MAX_PKT_LEN) { - var msg = 'Packet length (' - + pktLeft - + ') exceeds max length (' - + MAX_PKT_LEN - + ')'; - debug('DEBUG[SFTP]: Parser: ' + msg); - this._cleanup(false); - return callback(new Error(msg)); - } else if (pktType === REQUEST.EXTENDED) { - status = 'bad_pkt'; - } else if (REQUEST[pktType] === undefined) { - debug('DEBUG[SFTP]: Parser: Unsupported packet type: ' + pktType); - status = 'discard'; - } - } else if (version === undefined && pktType !== RESPONSE.VERSION) { - debug('DEBUG[SFTP]: Parser: Unexpected packet before version'); - this._cleanup(false); - return callback(new Error('Unexpected packet before version')); - } else if (version !== undefined && pktType === RESPONSE.VERSION) { - debug('DEBUG[SFTP]: Parser: Unexpected duplicate version'); - status = 'bad_pkt'; - } else if (RESPONSE[pktType] === undefined) { - status = 'discard'; - } - - if (status === 'bad_pkt') { - // copy original packet info - pktHdrBuf.writeUInt32BE(pktLeft, 0, true); - pktHdrBuf[4] = pktType; - - pktLeft = 4; - pktBuf = pktHdrBuf; - } else { - pktBuf = new Buffer(pktLeft); - status = 'payload'; - } - } - } else if (status === 'payload') { - if (pktType === RESPONSE.VERSION || pktType === REQUEST.INIT) { - /* - uint32 version - - */ - version = state.version = readInt(buffer, 0, this, callback); - if (version === false) - return; - if (version < 3) { - this._cleanup(false); - return callback(new Error('Incompatible SFTP version: ' + version)); - } else if (server) - this.push(SERVER_VERSION_BUFFER); - - var buflen = buffer.length; - var extname; - var extdata; - buffer._pos = 4; - while (buffer._pos < buflen) { - extname = readString(buffer, buffer._pos, 'ascii', this, callback); - if (extname === false) - return; - extdata = readString(buffer, buffer._pos, 'ascii', this, callback); - if (extdata === false) - return; - if (state.extensions[extname]) - state.extensions[extname].push(extdata); - else - state.extensions[extname] = [ extdata ]; - } - - this.emit('ready'); - } else { - /* - All other packets (client and server) begin with a (client) request - id: - uint32 id - */ - id = readInt(buffer, 0, this, callback); - if (id === false) - return; - - var filename; - var attrs; - var handle; - var data; - - if (!server) { - var req = requests[id]; - var cb = req && req.cb; - debug('DEBUG[SFTP]: Parser: Response: ' + RESPONSE[pktType]); - if (req && cb) { - if (pktType === RESPONSE.STATUS) { - /* - uint32 error/status code - string error message (ISO-10646 UTF-8) - string language tag - */ - var code = readInt(buffer, 4, this, callback); - if (code === false) - return; - if (code === STATUS_CODE.OK) { - cb(); - } else { - // We borrow OpenSSH behavior here, specifically we make the - // message and language fields optional, despite the - // specification requiring them (even if they are empty). This - // helps to avoid problems with buggy implementations that do - // not fully conform to the SFTP(v3) specification. - var msg; - var lang = ''; - if (buffer.length >= 12) { - msg = readString(buffer, 8, 'utf8', this, callback); - if (msg === false) - return; - if ((buffer._pos + 4) < buffer.length) { - lang = readString(buffer, - buffer._pos, - 'ascii', - this, - callback); - if (lang === false) - return; - } - } - var err = new Error(msg - || STATUS_CODE_STR[code] - || 'Unknown status'); - err.code = code; - err.lang = lang; - cb(err); - } - } else if (pktType === RESPONSE.HANDLE) { - /* - string handle - */ - handle = readString(buffer, 4, this, callback); - if (handle === false) - return; - cb(undefined, handle); - } else if (pktType === RESPONSE.DATA) { - /* - string data - */ - if (req.buffer) { - // we have already pre-allocated space to store the data - var dataLen = readInt(buffer, 4, this, callback); - if (dataLen === false) - return; - var reqBufLen = req.buffer.length; - if (dataLen > reqBufLen) { - // truncate response data to fit expected size - buffer.writeUInt32BE(reqBufLen, 4, true); - } - data = readString(buffer, 4, req.buffer, this, callback); - if (data === false) - return; - cb(undefined, data, dataLen); - } else { - data = readString(buffer, 4, this, callback); - if (data === false) - return; - cb(undefined, data); - } - } else if (pktType === RESPONSE.NAME) { - /* - uint32 count - repeats count times: - string filename - string longname - ATTRS attrs - */ - var namesLen = readInt(buffer, 4, this, callback); - if (namesLen === false) - return; - var names = [], - longname; - buffer._pos = 8; - for (var i = 0; i < namesLen; ++i) { - // we are going to assume UTF-8 for filenames despite the SFTPv3 - // spec not specifying an encoding because the specs for newer - // versions of the protocol all explicitly specify UTF-8 for - // filenames - filename = readString(buffer, - buffer._pos, - 'utf8', - this, - callback); - if (filename === false) - return; - // `longname` only exists in SFTPv3 and since it typically will - // contain the filename, we assume it is also UTF-8 - longname = readString(buffer, - buffer._pos, - 'utf8', - this, - callback); - if (longname === false) - return; - attrs = readAttrs(buffer, buffer._pos, this, callback); - if (attrs === false) - return; - names.push({ - filename: filename, - longname: longname, - attrs: attrs - }); - } - cb(undefined, names); - } else if (pktType === RESPONSE.ATTRS) { - /* - ATTRS attrs - */ - attrs = readAttrs(buffer, 4, this, callback); - if (attrs === false) - return; - cb(undefined, attrs); - } else if (pktType === RESPONSE.EXTENDED) { - if (req.extended) { - switch (req.extended) { - case 'statvfs@openssh.com': - case 'fstatvfs@openssh.com': - /* - uint64 f_bsize // file system block size - uint64 f_frsize // fundamental fs block size - uint64 f_blocks // number of blocks (unit f_frsize) - uint64 f_bfree // free blocks in file system - uint64 f_bavail // free blocks for non-root - uint64 f_files // total file inodes - uint64 f_ffree // free file inodes - uint64 f_favail // free file inodes for to non-root - uint64 f_fsid // file system id - uint64 f_flag // bit mask of f_flag values - uint64 f_namemax // maximum filename length - */ - var stats = { - f_bsize: undefined, - f_frsize: undefined, - f_blocks: undefined, - f_bfree: undefined, - f_bavail: undefined, - f_files: undefined, - f_ffree: undefined, - f_favail: undefined, - f_sid: undefined, - f_flag: undefined, - f_namemax: undefined - }; - stats.f_bsize = readUInt64BE(buffer, 4, this, callback); - if (stats.f_bsize === false) - return; - stats.f_frsize = readUInt64BE(buffer, 12, this, callback); - if (stats.f_frsize === false) - return; - stats.f_blocks = readUInt64BE(buffer, 20, this, callback); - if (stats.f_blocks === false) - return; - stats.f_bfree = readUInt64BE(buffer, 28, this, callback); - if (stats.f_bfree === false) - return; - stats.f_bavail = readUInt64BE(buffer, 36, this, callback); - if (stats.f_bavail === false) - return; - stats.f_files = readUInt64BE(buffer, 44, this, callback); - if (stats.f_files === false) - return; - stats.f_ffree = readUInt64BE(buffer, 52, this, callback); - if (stats.f_ffree === false) - return; - stats.f_favail = readUInt64BE(buffer, 60, this, callback); - if (stats.f_favail === false) - return; - stats.f_sid = readUInt64BE(buffer, 68, this, callback); - if (stats.f_sid === false) - return; - stats.f_flag = readUInt64BE(buffer, 76, this, callback); - if (stats.f_flag === false) - return; - stats.f_namemax = readUInt64BE(buffer, 84, this, callback); - if (stats.f_namemax === false) - return; - cb(undefined, stats); - break; - } - } - // XXX: at least provide the raw buffer data to the callback in - // case of unexpected extended response? - cb(); - } - } - if (req) - delete requests[id]; - } else { - // server - var evName = REQUEST[pktType]; - var offset; - var path; - - debug('DEBUG[SFTP]: Parser: Request: ' + evName); - if (listenerCount(this, evName)) { - if (pktType === REQUEST.OPEN) { - /* - string filename - uint32 pflags - ATTRS attrs - */ - filename = readString(buffer, 4, 'utf8', this, callback); - if (filename === false) - return; - var pflags = readInt(buffer, buffer._pos, this, callback); - if (pflags === false) - return; - attrs = readAttrs(buffer, buffer._pos + 4, this, callback); - if (attrs === false) - return; - this.emit(evName, id, filename, pflags, attrs); - } else if (pktType === REQUEST.CLOSE - || pktType === REQUEST.FSTAT - || pktType === REQUEST.READDIR) { - /* - string handle - */ - handle = readString(buffer, 4, this, callback); - if (handle === false) - return; - this.emit(evName, id, handle); - } else if (pktType === REQUEST.READ) { - /* - string handle - uint64 offset - uint32 len - */ - handle = readString(buffer, 4, this, callback); - if (handle === false) - return; - offset = readUInt64BE(buffer, buffer._pos, this, callback); - if (offset === false) - return; - var len = readInt(buffer, buffer._pos, this, callback); - if (len === false) - return; - this.emit(evName, id, handle, offset, len); - } else if (pktType === REQUEST.WRITE) { - /* - string handle - uint64 offset - string data - */ - handle = readString(buffer, 4, this, callback); - if (handle === false) - return; - offset = readUInt64BE(buffer, buffer._pos, this, callback); - if (offset === false) - return; - data = readString(buffer, buffer._pos, this, callback); - if (data === false) - return; - this.emit(evName, id, handle, offset, data); - } else if (pktType === REQUEST.LSTAT - || pktType === REQUEST.STAT - || pktType === REQUEST.OPENDIR - || pktType === REQUEST.REMOVE - || pktType === REQUEST.RMDIR - || pktType === REQUEST.REALPATH - || pktType === REQUEST.READLINK) { - /* - string path - */ - path = readString(buffer, 4, 'utf8', this, callback); - if (path === false) - return; - this.emit(evName, id, path); - } else if (pktType === REQUEST.SETSTAT - || pktType === REQUEST.MKDIR) { - /* - string path - ATTRS attrs - */ - path = readString(buffer, 4, 'utf8', this, callback); - if (path === false) - return; - attrs = readAttrs(buffer, buffer._pos, this, callback); - if (attrs === false) - return; - this.emit(evName, id, path, attrs); - } else if (pktType === REQUEST.FSETSTAT) { - /* - string handle - ATTRS attrs - */ - handle = readString(buffer, 4, this, callback); - if (handle === false) - return; - attrs = readAttrs(buffer, buffer._pos, this, callback); - if (attrs === false) - return; - this.emit(evName, id, handle, attrs); - } else if (pktType === REQUEST.RENAME - || pktType === REQUEST.SYMLINK) { - /* - RENAME: - string oldpath - string newpath - SYMLINK: - string linkpath - string targetpath - */ - var str1; - var str2; - str1 = readString(buffer, 4, 'utf8', this, callback); - if (str1 === false) - return; - str2 = readString(buffer, buffer._pos, 'utf8', this, callback); - if (str2 === false) - return; - if (pktType === REQUEST.SYMLINK && this._isOpenSSH) { - // OpenSSH has linkpath and targetpath positions switched - this.emit(evName, id, str2, str1); - } else - this.emit(evName, id, str1, str2); - } - } else { - // automatically reject request if no handler for request type - this.status(id, STATUS_CODE.OP_UNSUPPORTED); - } - } - } - - // prepare for next packet - status = 'packet_header'; - buffer = pktBuf = undefined; - } else if (status === 'bad_pkt') { - if (server && buffer[4] !== REQUEST.INIT) { - var errCode = (buffer[4] === REQUEST.EXTENDED - ? STATUS_CODE.OP_UNSUPPORTED - : STATUS_CODE.FAILURE); - - // no request id for init/version packets, so we have no way to send a - // status response, so we just close up shop ... - if (buffer[4] === REQUEST.INIT || buffer[4] === RESPONSE.VERSION) - return this._cleanup(callback); - - id = readInt(buffer, 5, this, callback); - if (id === false) - return; - this.status(id, errCode); - } - - // by this point we have already read the type byte and the id bytes, so - // we subtract those from the number of bytes to skip - pktLeft = buffer.readUInt32BE(0, true) - 5; - - status = 'discard'; - } - - if (chunkPos >= chunkLen) - break; - } - - state.status = status; - state.pktType = pktType; - state.pktBuf = pktBuf; - state.pktLeft = pktLeft; - state.version = version; - - callback(); -}; - -// client -SFTPStream.prototype.createReadStream = function(path, options) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - return new ReadStream(this, path, options); -}; -SFTPStream.prototype.createWriteStream = function(path, options) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - return new WriteStream(this, path, options); -}; -SFTPStream.prototype.open = function(path, flags_, attrs, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - if (typeof attrs === 'function') { - cb = attrs; - attrs = undefined; - } - - var flags = stringToFlags(flags_); - if (flags === null) - throw new Error('Unknown flags string: ' + flags_); - - var attrFlags = 0; - var attrBytes = 0; - if (typeof attrs === 'string' || typeof attrs === 'number') { - attrs = { mode: attrs }; - } - if (typeof attrs === 'object') { - attrs = attrsToBytes(attrs); - attrFlags = attrs.flags; - attrBytes = attrs.nbytes; - attrs = attrs.bytes; - } - - /* - uint32 id - string filename - uint32 pflags - ATTRS attrs - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen + 4 + 4 + attrBytes); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.OPEN; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - buf.writeUInt32BE(flags, p += pathlen, true); - buf.writeUInt32BE(attrFlags, p += 4, true); - if (attrs && attrFlags) { - p += 4; - for (var i = 0, len = attrs.length; i < len; ++i) - for (var j = 0, len2 = attrs[i].length; j < len2; ++j) - buf[p++] = attrs[i][j]; - } - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing OPEN'); - return this.push(buf); -}; -SFTPStream.prototype.close = function(handle, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - - var state = this._state; - - /* - uint32 id - string handle - */ - var handlelen = handle.length; - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + handlelen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.CLOSE; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(handlelen, p, true); - handle.copy(buf, p += 4); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing CLOSE'); - return this.push(buf); -}; -SFTPStream.prototype.readData = function(handle, buf, off, len, position, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - else if (!Buffer.isBuffer(buf)) - throw new Error('buffer is not a Buffer'); - else if (off >= buf.length) - throw new Error('offset is out of bounds'); - else if (off + len > buf.length) - throw new Error('length extends beyond buffer'); - else if (position === null) - throw new Error('null position currently unsupported'); - - var state = this._state; - - /* - uint32 id - string handle - uint64 offset - uint32 len - */ - var handlelen = handle.length; - var p = 9; - var pos = position; - var out = new Buffer(4 + 1 + 4 + 4 + handlelen + 8 + 4); - - out.writeUInt32BE(out.length - 4, 0, true); - out[4] = REQUEST.READ; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - out.writeUInt32BE(reqid, 5, true); - - out.writeUInt32BE(handlelen, p, true); - handle.copy(out, p += 4); - p += handlelen; - for (var i = 7; i >= 0; --i) { - out[p + i] = pos & 0xFF; - pos /= 256; - } - out.writeUInt32BE(len, p += 8, true); - - state.requests[reqid] = { - cb: function(err, data, nb) { - if (err && err.code !== STATUS_CODE.EOF) - return cb(err); - cb(undefined, nb || 0, data, position); - }, - buffer: buf.slice(off, off + len) - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing READ'); - return this.push(out); -}; -SFTPStream.prototype.writeData = function(handle, buf, off, len, position, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - else if (!Buffer.isBuffer(buf)) - throw new Error('buffer is not a Buffer'); - else if (off > buf.length) - throw new Error('offset is out of bounds'); - else if (off + len > buf.length) - throw new Error('length extends beyond buffer'); - else if (position === null) - throw new Error('null position currently unsupported'); - - var self = this; - var state = this._state; - - if (!len) { - cb && process.nextTick(function() { cb(undefined, 0); }); - return; - } - - var overflow = (len > state.maxDataLen - ? len - state.maxDataLen - : 0); - var origPosition = position; - - if (overflow) - len = state.maxDataLen; - - /* - uint32 id - string handle - uint64 offset - string data - */ - var handlelen = handle.length; - var p = 9; - var out = new Buffer(4 + 1 + 4 + 4 + handlelen + 8 + 4 + len); - - out.writeUInt32BE(out.length - 4, 0, true); - out[4] = REQUEST.WRITE; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - out.writeUInt32BE(reqid, 5, true); - - out.writeUInt32BE(handlelen, p, true); - handle.copy(out, p += 4); - p += handlelen; - for (var i = 7; i >= 0; --i) { - out[p + i] = position & 0xFF; - position /= 256; - } - out.writeUInt32BE(len, p += 8, true); - buf.copy(out, p += 4, off, off + len); - - state.requests[reqid] = { - cb: function(err) { - if (err) - cb && cb(err); - else if (overflow) { - self.writeData(handle, - buf, - off + len, - overflow, - origPosition + len, - cb); - } else - cb && cb(undefined, off + len); - } - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing WRITE'); - return this.push(out); -}; -function tryCreateBuffer(size) { - try { - return new Buffer(size); - } catch (ex) { - return ex; - } -} -function fastXfer(src, dst, srcPath, dstPath, opts, cb) { - var concurrency = 64; - var chunkSize = 32768; - //var preserve = false; - var onstep; - var mode; - - if (typeof opts === 'function') { - cb = opts; - } else if (typeof opts === 'object') { - if (typeof opts.concurrency === 'number' - && opts.concurrency > 0 - && !isNaN(opts.concurrency)) - concurrency = opts.concurrency; - if (typeof opts.chunkSize === 'number' - && opts.chunkSize > 0 - && !isNaN(opts.chunkSize)) - chunkSize = opts.chunkSize; - if (typeof opts.step === 'function') - onstep = opts.step; - //preserve = (opts.preserve ? true : false); - if (typeof opts.mode === 'string' || typeof opts.mode === 'number') - mode = modeNum(opts.mode); - } - - // internal state variables - var fsize; - var chunk; - var psrc = 0; - var pdst = 0; - var reads = 0; - var total = 0; - var hadError = false; - var srcHandle; - var dstHandle; - var readbuf; - var bufsize = chunkSize * concurrency; - - function onerror(err) { - if (hadError) - return; - - hadError = true; - - var left = 0; - var cbfinal; - - if (srcHandle || dstHandle) { - cbfinal = function() { - if (--left === 0) - cb(err); - }; - if (srcHandle && (src === fs || src.writable)) - ++left; - if (dstHandle && (dst === fs || dst.writable)) - ++left; - if (srcHandle && (src === fs || src.writable)) - src.close(srcHandle, cbfinal); - if (dstHandle && (dst === fs || dst.writable)) - dst.close(dstHandle, cbfinal); - } else - cb(err); - } - - src.open(srcPath, 'r', function(err, sourceHandle) { - if (err) - return onerror(err); - - srcHandle = sourceHandle; - - src.fstat(srcHandle, function tryStat(err, attrs) { - if (err) { - if (src !== fs) { - // Try stat() for sftp servers that may not support fstat() for - // whatever reason - src.stat(srcPath, function(err_, attrs_) { - if (err_) - return onerror(err); - tryStat(null, attrs_); - }); - return; - } - return onerror(err); - } - fsize = attrs.size; - - dst.open(dstPath, 'w', function(err, destHandle) { - if (err) - return onerror(err); - - dstHandle = destHandle; - - if (fsize <= 0) - return onerror(); - - // Use less memory where possible - while (bufsize > fsize) { - if (concurrency === 1) { - bufsize = fsize; - break; - } - bufsize -= chunkSize; - --concurrency; - } - - readbuf = tryCreateBuffer(bufsize); - if (readbuf instanceof Error) - return onerror(readbuf); - - if (mode !== undefined) { - dst.fchmod(dstHandle, mode, function tryAgain(err) { - if (err) { - // Try chmod() for sftp servers that may not support fchmod() for - // whatever reason - dst.chmod(dstPath, mode, function(err_) { - tryAgain(); - }); - return; - } - read(); - }); - } else { - read(); - } - - function onread(err, nb, data, dstpos, datapos) { - if (err) - return onerror(err); - - if (src === fs) - dst.writeData(dstHandle, data, datapos || 0, nb, dstpos, writeCb); - else - dst.write(dstHandle, data, datapos || 0, nb, dstpos, writeCb); - - function writeCb(err) { - if (err) - return onerror(err); - - total += nb; - onstep && onstep(total, nb, fsize); - - if (--reads === 0) { - if (total === fsize) { - dst.close(dstHandle, function(err) { - dstHandle = undefined; - if (err) - return onerror(err); - src.close(srcHandle, function(err) { - srcHandle = undefined; - if (err) - return onerror(err); - cb(); - }); - }); - } else - read(); - } - } - } - - function makeCb(psrc, pdst) { - return function(err, nb, data) { - onread(err, nb, data, pdst, psrc); - }; - } - - function read() { - while (pdst < fsize && reads < concurrency) { - chunk = (pdst + chunkSize > fsize ? fsize - pdst : chunkSize); - if (src === fs) { - src.read(srcHandle, - readbuf, - psrc, - chunk, - pdst, - makeCb(psrc, pdst)); - } else - src.readData(srcHandle, readbuf, psrc, chunk, pdst, onread); - psrc += chunk; - pdst += chunk; - ++reads; - } - psrc = 0; - } - }); - }); - }); -} -SFTPStream.prototype.fastGet = function(remotePath, localPath, opts, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - fastXfer(this, fs, remotePath, localPath, opts, cb); -}; -SFTPStream.prototype.fastPut = function(localPath, remotePath, opts, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - fastXfer(fs, this, localPath, remotePath, opts, cb); -}; -SFTPStream.prototype.readFile = function(path, options, callback_) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var callback; - if (typeof callback_ === 'function') { - callback = callback_; - } else if (typeof options === 'function') { - callback = options; - options = undefined; - } - - var self = this; - - if (typeof options === 'string') - options = { encoding: options, flag: 'r' }; - else if (!options) - options = { encoding: null, flag: 'r' }; - else if (typeof options !== 'object') - throw new TypeError('Bad arguments'); - - var encoding = options.encoding; - if (encoding && !Buffer.isEncoding(encoding)) - throw new Error('Unknown encoding: ' + encoding); - - // first, stat the file, so we know the size. - var size; - var buffer; // single buffer with file data - var buffers; // list for when size is unknown - var pos = 0; - var handle; - - // SFTPv3 does not support using -1 for read position, so we have to track - // read position manually - var bytesRead = 0; - - var flag = options.flag || 'r'; - this.open(path, flag, 438 /*=0666*/, function(er, handle_) { - if (er) - return callback && callback(er); - handle = handle_; - - self.fstat(handle, function tryStat(er, st) { - if (er) { - // Try stat() for sftp servers that may not support fstat() for - // whatever reason - self.stat(path, function(er_, st_) { - if (er_) { - return self.close(handle, function() { - callback && callback(er); - }); - } - tryStat(null, st_); - }); - return; - } - - size = st.size || 0; - if (size === 0) { - // the kernel lies about many files. - // Go ahead and try to read some bytes. - buffers = []; - return read(); - } - - buffer = new Buffer(size); - read(); - }); - }); - - function read() { - if (size === 0) { - buffer = new Buffer(8192); - self.readData(handle, buffer, 0, 8192, bytesRead, afterRead); - } else - self.readData(handle, buffer, pos, size - pos, bytesRead, afterRead); - } - - function afterRead(er, nbytes) { - if (er) { - return self.close(handle, function() { - return callback && callback(er); - }); - } - - if (nbytes === 0) - return close(); - - bytesRead += nbytes; - pos += nbytes; - if (size !== 0) { - if (pos === size) - close(); - else - read(); - } else { - // unknown size, just read until we don't get bytes. - buffers.push(buffer.slice(0, nbytes)); - read(); - } - } - - function close() { - self.close(handle, function(er) { - if (size === 0) { - // collected the data into the buffers list. - buffer = Buffer.concat(buffers, pos); - } else if (pos < size) - buffer = buffer.slice(0, pos); - - if (encoding) - buffer = buffer.toString(encoding); - return callback && callback(er, buffer); - }); - } -}; -function writeAll(self, handle, buffer, offset, length, position, callback_) { - var callback = (typeof callback_ === 'function' ? callback_ : undefined); - - self.writeData(handle, - buffer, - offset, - length, - position, - function(writeErr, written) { - if (writeErr) { - return self.close(handle, function() { - callback && callback(writeErr); - }); - } - if (written === length) - self.close(handle, callback); - else { - offset += written; - length -= written; - position += written; - writeAll(self, handle, buffer, offset, length, position, callback); - } - }); -} -SFTPStream.prototype.writeFile = function(path, data, options, callback_) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var callback; - if (typeof callback_ === 'function') { - callback = callback_; - } else if (typeof options === 'function') { - callback = options; - options = undefined; - } - var self = this; - - if (typeof options === 'string') - options = { encoding: options, mode: 438, flag: 'w' }; - else if (!options) - options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; - else if (typeof options !== 'object') - throw new TypeError('Bad arguments'); - - if (options.encoding && !Buffer.isEncoding(options.encoding)) - throw new Error('Unknown encoding: ' + options.encoding); - - var flag = options.flag || 'w'; - this.open(path, flag, options.mode, function(openErr, handle) { - if (openErr) - callback && callback(openErr); - else { - var buffer = (Buffer.isBuffer(data) - ? data - : new Buffer('' + data, options.encoding || 'utf8')); - var position = (/a/.test(flag) ? null : 0); - - // SFTPv3 does not support the notion of 'current position' - // (null position), so we just attempt to append to the end of the file - // instead - if (position === null) { - self.fstat(handle, function tryStat(er, st) { - if (er) { - // Try stat() for sftp servers that may not support fstat() for - // whatever reason - self.stat(path, function(er_, st_) { - if (er_) { - return self.close(handle, function() { - callback && callback(er); - }); - } - tryStat(null, st_); - }); - return; - } - writeAll(self, handle, buffer, 0, buffer.length, st.size, callback); - }); - return; - } - writeAll(self, handle, buffer, 0, buffer.length, position, callback); - } - }); -}; -SFTPStream.prototype.appendFile = function(path, data, options, callback_) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var callback; - if (typeof callback_ === 'function') { - callback = callback_; - } else if (typeof options === 'function') { - callback = options; - options = undefined; - } - - if (typeof options === 'string') - options = { encoding: options, mode: 438, flag: 'a' }; - else if (!options) - options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; - else if (typeof options !== 'object') - throw new TypeError('Bad arguments'); - - if (!options.flag) - options = util._extend({ flag: 'a' }, options); - this.writeFile(path, data, options, callback); -}; -SFTPStream.prototype.exists = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - this.stat(path, function(err) { - cb && cb(err ? false : true); - }); -}; -SFTPStream.prototype.unlink = function(filename, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string filename - */ - var fnamelen = Buffer.byteLength(filename); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + fnamelen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.REMOVE; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(fnamelen, p, true); - buf.write(filename, p += 4, fnamelen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing REMOVE'); - return this.push(buf); -}; -SFTPStream.prototype.rename = function(oldPath, newPath, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string oldpath - string newpath - */ - var oldlen = Buffer.byteLength(oldPath); - var newlen = Buffer.byteLength(newPath); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + oldlen + 4 + newlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.RENAME; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(oldlen, p, true); - buf.write(oldPath, p += 4, oldlen, 'utf8'); - buf.writeUInt32BE(newlen, p += oldlen, true); - buf.write(newPath, p += 4, newlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing RENAME'); - return this.push(buf); -}; -SFTPStream.prototype.mkdir = function(path, attrs, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var flags = 0; - var attrBytes = 0; - var state = this._state; - - if (typeof attrs === 'function') { - cb = attrs; - attrs = undefined; - } - if (typeof attrs === 'object') { - attrs = attrsToBytes(attrs); - flags = attrs.flags; - attrBytes = attrs.nbytes; - attrs = attrs.bytes; - } - - /* - uint32 id - string path - ATTRS attrs - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen + 4 + attrBytes); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.MKDIR; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - buf.writeUInt32BE(flags, p += pathlen); - if (flags) { - p += 4; - for (var i = 0, len = attrs.length; i < len; ++i) - for (var j = 0, len2 = attrs[i].length; j < len2; ++j) - buf[p++] = attrs[i][j]; - } - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing MKDIR'); - return this.push(buf); -}; -SFTPStream.prototype.rmdir = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.RMDIR; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing RMDIR'); - return this.push(buf); -}; -SFTPStream.prototype.readdir = function(where, opts, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - var doFilter; - - if (typeof opts === 'function') { - cb = opts; - opts = {}; - } - if (typeof opts !== 'object') - opts = {}; - - doFilter = (opts && opts.full ? false : true); - - if (!Buffer.isBuffer(where) && typeof where !== 'string') - throw new Error('missing directory handle or path'); - - if (typeof where === 'string') { - var self = this; - var entries = []; - var e = 0; - - return this.opendir(where, function reread(err, handle) { - if (err) - return cb(err); - - self.readdir(handle, opts, function(err, list) { - var eof = (err && err.code === STATUS_CODE.EOF); - - if (err && !eof) { - return self.close(handle, function() { - cb(err); - }); - } else if (eof) { - return self.close(handle, function(err) { - if (err) - return cb(err); - cb(undefined, entries); - }); - } - - for (var i = 0, len = list.length; i < len; ++i, ++e) - entries[e] = list[i]; - - reread(undefined, handle); - }); - }); - } - - /* - uint32 id - string handle - */ - var handlelen = where.length; - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + handlelen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.READDIR; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(handlelen, p, true); - where.copy(buf, p += 4); - - state.requests[reqid] = { - cb: (doFilter - ? function(err, list) { - if (err) - return cb(err); - - for (var i = list.length - 1; i >= 0; --i) { - if (list[i].filename === '.' || list[i].filename === '..') - list.splice(i, 1); - } - - cb(undefined, list); - } - : cb) - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing READDIR'); - return this.push(buf); -}; -SFTPStream.prototype.fstat = function(handle, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - - var state = this._state; - - /* - uint32 id - string handle - */ - var handlelen = handle.length; - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + handlelen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.FSTAT; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(handlelen, p, true); - handle.copy(buf, p += 4); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing FSTAT'); - return this.push(buf); -}; -SFTPStream.prototype.stat = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.STAT; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing STAT'); - return this.push(buf); -}; -SFTPStream.prototype.lstat = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.LSTAT; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing LSTAT'); - return this.push(buf); -}; -SFTPStream.prototype.opendir = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.OPENDIR; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing OPENDIR'); - return this.push(buf); -}; -SFTPStream.prototype.setstat = function(path, attrs, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var flags = 0; - var attrBytes = 0; - var state = this._state; - - if (typeof attrs === 'object') { - attrs = attrsToBytes(attrs); - flags = attrs.flags; - attrBytes = attrs.nbytes; - attrs = attrs.bytes; - } else if (typeof attrs === 'function') - cb = attrs; - - /* - uint32 id - string path - ATTRS attrs - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen + 4 + attrBytes); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.SETSTAT; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - buf.writeUInt32BE(flags, p += pathlen); - if (flags) { - p += 4; - for (var i = 0, len = attrs.length; i < len; ++i) - for (var j = 0, len2 = attrs[i].length; j < len2; ++j) - buf[p++] = attrs[i][j]; - } - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing SETSTAT'); - return this.push(buf); -}; -SFTPStream.prototype.fsetstat = function(handle, attrs, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - - var flags = 0; - var attrBytes = 0; - var state = this._state; - - if (typeof attrs === 'object') { - attrs = attrsToBytes(attrs); - flags = attrs.flags; - attrBytes = attrs.nbytes; - attrs = attrs.bytes; - } else if (typeof attrs === 'function') - cb = attrs; - - /* - uint32 id - string handle - ATTRS attrs - */ - var handlelen = handle.length; - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + handlelen + 4 + attrBytes); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.FSETSTAT; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(handlelen, p, true); - handle.copy(buf, p += 4); - buf.writeUInt32BE(flags, p += handlelen); - if (flags) { - p += 4; - for (var i = 0, len = attrs.length; i < len; ++i) - for (var j = 0, len2 = attrs[i].length; j < len2; ++j) - buf[p++] = attrs[i][j]; - } - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing FSETSTAT'); - return this.push(buf); -}; -SFTPStream.prototype.futimes = function(handle, atime, mtime, cb) { - return this.fsetstat(handle, { - atime: toUnixTimestamp(atime), - mtime: toUnixTimestamp(mtime) - }, cb); -}; -SFTPStream.prototype.utimes = function(path, atime, mtime, cb) { - return this.setstat(path, { - atime: toUnixTimestamp(atime), - mtime: toUnixTimestamp(mtime) - }, cb); -}; -SFTPStream.prototype.fchown = function(handle, uid, gid, cb) { - return this.fsetstat(handle, { - uid: uid, - gid: gid - }, cb); -}; -SFTPStream.prototype.chown = function(path, uid, gid, cb) { - return this.setstat(path, { - uid: uid, - gid: gid - }, cb); -}; -SFTPStream.prototype.fchmod = function(handle, mode, cb) { - return this.fsetstat(handle, { - mode: mode - }, cb); -}; -SFTPStream.prototype.chmod = function(path, mode, cb) { - return this.setstat(path, { - mode: mode - }, cb); -}; -SFTPStream.prototype.readlink = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.READLINK; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { - cb: function(err, names) { - if (err) - return cb(err); - else if (!names || !names.length) - return cb(new Error('Response missing link info')); - cb(undefined, names[0].filename); - } - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing READLINK'); - return this.push(buf); -}; -SFTPStream.prototype.symlink = function(targetPath, linkPath, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string linkpath - string targetpath - */ - var linklen = Buffer.byteLength(linkPath); - var targetlen = Buffer.byteLength(targetPath); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + linklen + 4 + targetlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.SYMLINK; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - if (this._isOpenSSH) { - // OpenSSH has linkpath and targetpath positions switched - buf.writeUInt32BE(targetlen, p, true); - buf.write(targetPath, p += 4, targetlen, 'utf8'); - buf.writeUInt32BE(linklen, p += targetlen, true); - buf.write(linkPath, p += 4, linklen, 'utf8'); - } else { - buf.writeUInt32BE(linklen, p, true); - buf.write(linkPath, p += 4, linklen, 'utf8'); - buf.writeUInt32BE(targetlen, p += linklen, true); - buf.write(targetPath, p += 4, targetlen, 'utf8'); - } - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing SYMLINK'); - return this.push(buf); -}; -SFTPStream.prototype.realpath = function(path, cb) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var state = this._state; - - /* - uint32 id - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.REALPATH; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { - cb: function(err, names) { - if (err) - return cb(err); - else if (!names || !names.length) - return cb(new Error('Response missing path info')); - cb(undefined, names[0].filename); - } - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing REALPATH'); - return this.push(buf); -}; -// extended requests -SFTPStream.prototype.ext_openssh_rename = function(oldPath, newPath, cb) { - var state = this._state; - - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!state.extensions['posix-rename@openssh.com'] - || state.extensions['posix-rename@openssh.com'].indexOf('1') === -1) - throw new Error('Server does not support this extended request'); - - /* - uint32 id - string "posix-rename@openssh.com" - string oldpath - string newpath - */ - var oldlen = Buffer.byteLength(oldPath); - var newlen = Buffer.byteLength(newPath); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + 24 + 4 + oldlen + 4 + newlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.EXTENDED; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - buf.writeUInt32BE(24, p, true); - buf.write('posix-rename@openssh.com', p += 4, 24, 'ascii'); - - buf.writeUInt32BE(oldlen, p += 24, true); - buf.write(oldPath, p += 4, oldlen, 'utf8'); - buf.writeUInt32BE(newlen, p += oldlen, true); - buf.write(newPath, p += 4, newlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing posix-rename@openssh.com'); - return this.push(buf); -}; -SFTPStream.prototype.ext_openssh_statvfs = function(path, cb) { - var state = this._state; - - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!state.extensions['statvfs@openssh.com'] - || state.extensions['statvfs@openssh.com'].indexOf('2') === -1) - throw new Error('Server does not support this extended request'); - - /* - uint32 id - string "statvfs@openssh.com" - string path - */ - var pathlen = Buffer.byteLength(path); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + 19 + 4 + pathlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.EXTENDED; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - buf.writeUInt32BE(19, p, true); - buf.write('statvfs@openssh.com', p += 4, 19, 'ascii'); - - buf.writeUInt32BE(pathlen, p += 19, true); - buf.write(path, p += 4, pathlen, 'utf8'); - - state.requests[reqid] = { - extended: 'statvfs@openssh.com', - cb: cb - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing statvfs@openssh.com'); - return this.push(buf); -}; -SFTPStream.prototype.ext_openssh_fstatvfs = function(handle, cb) { - var state = this._state; - - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!state.extensions['fstatvfs@openssh.com'] - || state.extensions['fstatvfs@openssh.com'].indexOf('2') === -1) - throw new Error('Server does not support this extended request'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - - /* - uint32 id - string "fstatvfs@openssh.com" - string handle - */ - var handlelen = handle.length; - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + 20 + 4 + handlelen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.EXTENDED; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - buf.writeUInt32BE(20, p, true); - buf.write('fstatvfs@openssh.com', p += 4, 20, 'ascii'); - - buf.writeUInt32BE(handlelen, p += 20, true); - buf.write(handle, p += 4, handlelen, 'utf8'); - - state.requests[reqid] = { - extended: 'fstatvfs@openssh.com', - cb: cb - }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing fstatvfs@openssh.com'); - return this.push(buf); -}; -SFTPStream.prototype.ext_openssh_hardlink = function(oldPath, newPath, cb) { - var state = this._state; - - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!state.extensions['hardlink@openssh.com'] - || state.extensions['hardlink@openssh.com'].indexOf('1') === -1) - throw new Error('Server does not support this extended request'); - - /* - uint32 id - string "hardlink@openssh.com" - string oldpath - string newpath - */ - var oldlen = Buffer.byteLength(oldPath); - var newlen = Buffer.byteLength(newPath); - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + 20 + 4 + oldlen + 4 + newlen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.EXTENDED; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - buf.writeUInt32BE(20, p, true); - buf.write('hardlink@openssh.com', p += 4, 20, 'ascii'); - - buf.writeUInt32BE(oldlen, p += 20, true); - buf.write(oldPath, p += 4, oldlen, 'utf8'); - buf.writeUInt32BE(newlen, p += oldlen, true); - buf.write(newPath, p += 4, newlen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing hardlink@openssh.com'); - return this.push(buf); -}; -SFTPStream.prototype.ext_openssh_fsync = function(handle, cb) { - var state = this._state; - - if (this.server) - throw new Error('Client-only method called in server mode'); - else if (!state.extensions['fsync@openssh.com'] - || state.extensions['fsync@openssh.com'].indexOf('1') === -1) - throw new Error('Server does not support this extended request'); - else if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - - /* - uint32 id - string "fsync@openssh.com" - string handle - */ - var handlelen = handle.length; - var p = 9; - var buf = new Buffer(4 + 1 + 4 + 4 + 17 + 4 + handlelen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = REQUEST.EXTENDED; - var reqid = state.writeReqid = (state.writeReqid + 1) % MAX_REQID; - buf.writeUInt32BE(reqid, 5, true); - buf.writeUInt32BE(17, p, true); - buf.write('fsync@openssh.com', p += 4, 17, 'ascii'); - - buf.writeUInt32BE(handlelen, p += 17, true); - buf.write(handle, p += 4, handlelen, 'utf8'); - - state.requests[reqid] = { cb: cb }; - - this.debug('DEBUG[SFTP]: Outgoing: Writing fsync@openssh.com'); - return this.push(buf); -}; - -// server -SFTPStream.prototype.status = function(id, code, message, lang) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - if (!STATUS_CODE[code] || typeof code !== 'number') - throw new Error('Bad status code: ' + code); - - message || (message = ''); - lang || (lang = ''); - - var msgLen = Buffer.byteLength(message); - var langLen = Buffer.byteLength(lang); - var buf = new Buffer(4 + 1 + 4 + 4 + 4 + msgLen + 4 + langLen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = RESPONSE.STATUS; - buf.writeUInt32BE(id, 5, true); - - buf.writeUInt32BE(code, 9, true); - - buf.writeUInt32BE(msgLen, 13, true); - if (msgLen) - buf.write(message, 17, msgLen, 'utf8'); - - buf.writeUInt32BE(langLen, 17 + msgLen, true); - if (langLen) - buf.write(lang, 17 + msgLen + 4, langLen, 'ascii'); - - this.debug('DEBUG[SFTP]: Outgoing: Writing STATUS'); - return this.push(buf); -}; -SFTPStream.prototype.handle = function(id, handle) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - if (!Buffer.isBuffer(handle)) - throw new Error('handle is not a Buffer'); - - var handleLen = handle.length; - - if (handleLen > 256) - throw new Error('handle too large (> 256 bytes)'); - - var buf = new Buffer(4 + 1 + 4 + 4 + handleLen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = RESPONSE.HANDLE; - buf.writeUInt32BE(id, 5, true); - - buf.writeUInt32BE(handleLen, 9, true); - if (handleLen) - handle.copy(buf, 13); - - this.debug('DEBUG[SFTP]: Outgoing: Writing HANDLE'); - return this.push(buf); -}; -SFTPStream.prototype.data = function(id, data, encoding) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var isBuffer = Buffer.isBuffer(data); - - if (!isBuffer && typeof data !== 'string') - throw new Error('data is not a Buffer or string'); - - if (!isBuffer) - encoding || (encoding = 'utf8'); - - var dataLen = (isBuffer ? data.length : Buffer.byteLength(data, encoding)); - var buf = new Buffer(4 + 1 + 4 + 4 + dataLen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = RESPONSE.DATA; - buf.writeUInt32BE(id, 5, true); - - buf.writeUInt32BE(dataLen, 9, true); - if (dataLen) { - if (isBuffer) - data.copy(buf, 13); - else - buf.write(data, 13, dataLen, encoding); - } - - this.debug('DEBUG[SFTP]: Outgoing: Writing DATA'); - return this.push(buf); -}; -SFTPStream.prototype.name = function(id, names) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - if (!Array.isArray(names) && typeof names === 'object') - names = [ names ]; - else if (!Array.isArray(names)) - throw new Error('names is not an object or array'); - - var count = names.length; - var namesLen = 0; - var nameAttrs; - var attrs = []; - var name; - var filename; - var longname; - var attr; - var len; - var len2; - var buf; - var p; - var i; - var j; - var k; - - for (i = 0; i < count; ++i) { - name = names[i]; - filename = (!name || !name.filename || typeof name.filename !== 'string' - ? '' - : name.filename); - namesLen += 4 + Buffer.byteLength(filename); - longname = (!name || !name.longname || typeof name.longname !== 'string' - ? '' - : name.longname); - namesLen += 4 + Buffer.byteLength(longname); - - if (typeof name.attrs === 'object') { - nameAttrs = attrsToBytes(name.attrs); - namesLen += 4 + nameAttrs.nbytes; - attrs.push(nameAttrs); - } else { - namesLen += 4; - attrs.push(null); - } - } - - buf = new Buffer(4 + 1 + 4 + 4 + namesLen); - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = RESPONSE.NAME; - buf.writeUInt32BE(id, 5, true); - - buf.writeUInt32BE(count, 9, true); - - p = 13; - - for (i = 0; i < count; ++i) { - name = names[i]; - - filename = (!name || !name.filename || typeof name.filename !== 'string' - ? '' - : name.filename); - len = Buffer.byteLength(filename); - buf.writeUInt32BE(len, p, true); - p += 4; - if (len) { - buf.write(filename, p, len, 'utf8'); - p += len; - } - - longname = (!name || !name.longname || typeof name.longname !== 'string' - ? '' - : name.longname); - len = Buffer.byteLength(longname); - buf.writeUInt32BE(len, p, true); - p += 4; - if (len) { - buf.write(longname, p, len, 'utf8'); - p += len; - } - - attr = attrs[i]; - if (attr) { - buf.writeUInt32BE(attr.flags, p, true); - p += 4; - if (attr.flags && attr.bytes) { - var bytes = attr.bytes; - for (j = 0, len = bytes.length; j < len; ++j) - for (k = 0, len2 = bytes[j].length; k < len2; ++k) - buf[p++] = bytes[j][k]; - } - } else { - buf.writeUInt32BE(0, p, true); - p += 4; - } - } - - this.debug('DEBUG[SFTP]: Outgoing: Writing NAME'); - return this.push(buf); -}; -SFTPStream.prototype.attrs = function(id, attrs) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - if (typeof attrs !== 'object') - throw new Error('attrs is not an object'); - - var info = attrsToBytes(attrs); - var buf = new Buffer(4 + 1 + 4 + 4 + info.nbytes); - var p = 13; - - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = RESPONSE.ATTRS; - buf.writeUInt32BE(id, 5, true); - - buf.writeUInt32BE(info.flags, 9, true); - - if (info.flags && info.bytes) { - var bytes = info.bytes; - for (var j = 0, len = bytes.length; j < len; ++j) - for (var k = 0, len2 = bytes[j].length; k < len2; ++k) - buf[p++] = bytes[j][k]; - } - - this.debug('DEBUG[SFTP]: Outgoing: Writing ATTRS'); - return this.push(buf); -}; - -function readAttrs(buf, p, stream, callback) { - /* - uint32 flags - uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE - uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID - uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID - uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS - uint32 atime present only if flag SSH_FILEXFER_ACMODTIME - uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME - uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED - string extended_type - string extended_data - ... more extended data (extended_type - extended_data pairs), - so that number of pairs equals extended_count - */ - var flags = buf.readUInt32BE(p, true); - var attrs = new Stats(); - - p += 4; - - if (flags & ATTR.SIZE) { - var size = readUInt64BE(buf, p, stream, callback); - if (size === false) - return false; - attrs.size = size; - p += 8; - } - if (flags & ATTR.UIDGID) { - var uid; - var gid; - uid = readInt(buf, p, this, callback); - if (uid === false) - return false; - attrs.uid = uid; - p += 4; - gid = readInt(buf, p, this, callback); - if (gid === false) - return false; - attrs.gid = gid; - p += 4; - } - if (flags & ATTR.PERMISSIONS) { - var mode = readInt(buf, p, this, callback); - if (mode === false) - return false; - attrs.mode = mode; - // backwards compatibility - attrs.permissions = mode; - p += 4; - } - if (flags & ATTR.ACMODTIME) { - var atime; - var mtime; - atime = readInt(buf, p, this, callback); - if (atime === false) - return false; - attrs.atime = atime; - p += 4; - mtime = readInt(buf, p, this, callback); - if (mtime === false) - return false; - attrs.mtime = mtime; - p += 4; - } - if (flags & ATTR.EXTENDED) { - // TODO: read/parse extended data - var extcount = readInt(buf, p, this, callback); - if (extcount === false) - return false; - p += 4; - for (var i = 0, len; i < extcount; ++i) { - len = readInt(buf, p, this, callback); - if (len === false) - return false; - p += 4 + len; - } - } - - buf._pos = p; - - return attrs; -} - -function readUInt64BE(buffer, p, stream, callback) { - if ((buffer.length - p) < 8) { - stream && stream._cleanup(callback); - return false; - } - - var val = 0; - - for (var len = p + 8; p < len; ++p) { - val *= 256; - val += buffer[p]; - } - - buffer._pos = p; - - return val; -} - -function attrsToBytes(attrs) { - var flags = 0; - var attrBytes = 0; - var ret = []; - var i = 0; - - if (typeof attrs.size === 'number') { - flags |= ATTR.SIZE; - attrBytes += 8; - var sizeBytes = new Array(8); - var val = attrs.size; - for (i = 7; i >= 0; --i) { - sizeBytes[i] = val & 0xFF; - val /= 256; - } - ret.push(sizeBytes); - } - if (typeof attrs.uid === 'number' && typeof attrs.gid === 'number') { - flags |= ATTR.UIDGID; - attrBytes += 8; - ret.push([(attrs.uid >> 24) & 0xFF, (attrs.uid >> 16) & 0xFF, - (attrs.uid >> 8) & 0xFF, attrs.uid & 0xFF]); - ret.push([(attrs.gid >> 24) & 0xFF, (attrs.gid >> 16) & 0xFF, - (attrs.gid >> 8) & 0xFF, attrs.gid & 0xFF]); - } - if (typeof attrs.permissions === 'number' - || typeof attrs.permissions === 'string' - || typeof attrs.mode === 'number' - || typeof attrs.mode === 'string') { - var mode = modeNum(attrs.mode || attrs.permissions); - flags |= ATTR.PERMISSIONS; - attrBytes += 4; - ret.push([(mode >> 24) & 0xFF, - (mode >> 16) & 0xFF, - (mode >> 8) & 0xFF, - mode & 0xFF]); - } - if ((typeof attrs.atime === 'number' || isDate(attrs.atime)) - && (typeof attrs.mtime === 'number' || isDate(attrs.mtime))) { - var atime = toUnixTimestamp(attrs.atime); - var mtime = toUnixTimestamp(attrs.mtime); - - flags |= ATTR.ACMODTIME; - attrBytes += 8; - ret.push([(atime >> 24) & 0xFF, (atime >> 16) & 0xFF, - (atime >> 8) & 0xFF, atime & 0xFF]); - ret.push([(mtime >> 24) & 0xFF, (mtime >> 16) & 0xFF, - (mtime >> 8) & 0xFF, mtime & 0xFF]); - } - // TODO: extended attributes - - return { flags: flags, nbytes: attrBytes, bytes: ret }; -} - -function toUnixTimestamp(time) { - if (typeof time === 'number' && !isNaN(time)) - return time; - else if (isDate(time)) - return parseInt(time.getTime() / 1000, 10); - throw new Error('Cannot parse time: ' + time); -} - -function modeNum(mode) { - if (typeof mode === 'number' && !isNaN(mode)) - return mode; - else if (typeof mode === 'string') - return modeNum(parseInt(mode, 8)); - throw new Error('Cannot parse mode: ' + mode); -} - -var stringFlagMap = { - 'r': OPEN_MODE.READ, - 'r+': OPEN_MODE.READ | OPEN_MODE.WRITE, - 'w': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE, - 'wx': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, - 'xw': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, - 'w+': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE, - 'wx+': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE - | OPEN_MODE.EXCL, - 'xw+': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE - | OPEN_MODE.EXCL, - 'a': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.WRITE, - 'ax': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, - 'xa': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, - 'a+': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE, - 'ax+': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE - | OPEN_MODE.EXCL, - 'xa+': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE - | OPEN_MODE.EXCL -}; -var stringFlagMapKeys = Object.keys(stringFlagMap); - -function stringToFlags(str) { - var flags = stringFlagMap[str]; - if (flags !== undefined) - return flags; - return null; -} -SFTPStream.stringToFlags = stringToFlags; - -function flagsToString(flags) { - for (var i = 0; i < stringFlagMapKeys.length; ++i) { - var key = stringFlagMapKeys[i]; - if (stringFlagMap[key] === flags) - return key; - } - return null; -} -SFTPStream.flagsToString = flagsToString; - -function Stats(initial) { - this.mode = (initial && initial.mode); - this.permissions = this.mode; // backwards compatiblity - this.uid = (initial && initial.uid); - this.gid = (initial && initial.gid); - this.size = (initial && initial.size); - this.atime = (initial && initial.atime); - this.mtime = (initial && initial.mtime); -} -Stats.prototype._checkModeProperty = function(property) { - return ((this.mode & constants.S_IFMT) === property); -}; -Stats.prototype.isDirectory = function() { - return this._checkModeProperty(constants.S_IFDIR); -}; -Stats.prototype.isFile = function() { - return this._checkModeProperty(constants.S_IFREG); -}; -Stats.prototype.isBlockDevice = function() { - return this._checkModeProperty(constants.S_IFBLK); -}; -Stats.prototype.isCharacterDevice = function() { - return this._checkModeProperty(constants.S_IFCHR); -}; -Stats.prototype.isSymbolicLink = function() { - return this._checkModeProperty(constants.S_IFLNK); -}; -Stats.prototype.isFIFO = function() { - return this._checkModeProperty(constants.S_IFIFO); -}; -Stats.prototype.isSocket = function() { - return this._checkModeProperty(constants.S_IFSOCK); -}; -SFTPStream.Stats = Stats; - - -// ReadStream-related -var kMinPoolSpace = 128; -var pool; -function allocNewPool(poolSize) { - pool = new Buffer(poolSize); - pool.used = 0; -} - -function ReadStream(sftp, path, options) { - if (!(this instanceof ReadStream)) - return new ReadStream(sftp, path, options); - - var self = this; - - if (options === undefined) - options = {}; - else if (typeof options === 'string') - options = { encoding: options }; - else if (options === null || typeof options !== 'object') - throw new TypeError('"options" argument must be a string or an object'); - else - options = Object.create(options); - - // a little bit bigger buffer and water marks by default - if (options.highWaterMark === undefined) - options.highWaterMark = 64 * 1024; - - ReadableStream.call(this, options); - - this.path = path; - this.handle = options.handle === undefined ? null : options.handle; - this.flags = options.flags === undefined ? 'r' : options.flags; - this.mode = options.mode === undefined ? 438/*0666*/ : options.mode; - - this.start = options.start === undefined ? undefined : options.start; - this.end = options.end === undefined ? undefined : options.end; - this.autoClose = options.autoClose === undefined ? true : options.autoClose; - this.pos = 0; - this.sftp = sftp; - - if (this.start !== undefined) { - if (typeof this.start !== 'number') - throw new TypeError('start must be a Number'); - if (this.end === undefined) - this.end = Infinity; - else if (typeof this.end !== 'number') - throw new TypeError('end must be a Number'); - - if (this.start > this.end) - throw new Error('start must be <= end'); - else if (this.start < 0) - throw new Error('start must be >= zero'); - - this.pos = this.start; - } - - this.on('end', function() { - if (self.autoClose) { - self.destroy(); - } - }); - - if (!Buffer.isBuffer(this.handle)) - this.open(); -} -inherits(ReadStream, ReadableStream); - -ReadStream.prototype.open = function() { - var self = this; - this.sftp.open(this.path, this.flags, this.mode, function(er, handle) { - if (er) { - self.emit('error', er); - this.destroyed = this.closed = true; - self.emit('close'); - return; - } - - self.handle = handle; - self.emit('open', handle); - // start the flow of data. - self.read(); - }); -}; - -ReadStream.prototype._read = function(n) { - if (!Buffer.isBuffer(this.handle)) { - return this.once('open', function() { - this._read(n); - }); - } - - if (this.destroyed) - return; - - if (!pool || pool.length - pool.used < kMinPoolSpace) { - // discard the old pool. - pool = null; - allocNewPool(this._readableState.highWaterMark); - } - - // Grab another reference to the pool in the case that while we're - // in the thread pool another read() finishes up the pool, and - // allocates a new one. - var thisPool = pool; - var toRead = Math.min(pool.length - pool.used, n); - var start = pool.used; - - if (this.end !== undefined) - toRead = Math.min(this.end - this.pos + 1, toRead); - - // already read everything we were supposed to read! - // treat as EOF. - if (toRead <= 0) - return this.push(null); - - // the actual read. - var self = this; - this.sftp.readData(this.handle, pool, pool.used, toRead, this.pos, onread); - - // move the pool positions, and internal position for reading. - this.pos += toRead; - pool.used += toRead; - - function onread(er, bytesRead) { - if (er) { - if (self.autoClose) - self.destroy(); - self.emit('error', er); - } else { - var b = null; - if (bytesRead > 0) - b = thisPool.slice(start, start + bytesRead); - - self.push(b); - } - } -}; - -ReadStream.prototype.destroy = function() { - if (this.destroyed) - return; - this.destroyed = true; - if (Buffer.isBuffer(this.handle)) - this.close(); -}; - - -ReadStream.prototype.close = function(cb) { - var self = this; - if (cb) - this.once('close', cb); - if (this.closed || !Buffer.isBuffer(this.handle)) { - if (!Buffer.isBuffer(this.handle)) { - this.once('open', close); - return; - } - return process.nextTick(this.emit.bind(this, 'close')); - } - this.closed = true; - close(); - - function close(handle) { - self.sftp.close(handle || self.handle, function(er) { - if (er) - self.emit('error', er); - else - self.emit('close'); - }); - self.handle = null; - } -}; - - -function WriteStream(sftp, path, options) { - if (!(this instanceof WriteStream)) - return new WriteStream(sftp, path, options); - - if (options === undefined) - options = {}; - else if (typeof options === 'string') - options = { encoding: options }; - else if (options === null || typeof options !== 'object') - throw new TypeError('"options" argument must be a string or an object'); - else - options = Object.create(options); - - WritableStream.call(this, options); - - this.path = path; - this.handle = options.handle === undefined ? null : options.handle; - this.flags = options.flags === undefined ? 'w' : options.flags; - this.mode = options.mode === undefined ? 438/*0666*/ : options.mode; - - this.start = options.start === undefined ? undefined : options.start; - this.autoClose = options.autoClose === undefined ? true : options.autoClose; - this.pos = 0; - this.bytesWritten = 0; - this.sftp = sftp; - - if (this.start !== undefined) { - if (typeof this.start !== 'number') - throw new TypeError('start must be a Number'); - if (this.start < 0) - throw new Error('start must be >= zero'); - - this.pos = this.start; - } - - if (options.encoding) - this.setDefaultEncoding(options.encoding); - - if (!Buffer.isBuffer(this.handle)) - this.open(); - - // dispose on finish. - this.once('finish', function onclose() { - if (this.autoClose) - this.close(); - }); -} -inherits(WriteStream, WritableStream); - -WriteStream.prototype.open = function() { - var self = this; - this.sftp.open(this.path, this.flags, this.mode, function(er, handle) { - if (er) { - self.emit('error', er); - if (self.autoClose) { - self.destroyed = self.closed = true; - self.emit('close'); - } - return; - } - - self.handle = handle; - - self.sftp.fchmod(handle, self.mode, function tryAgain(err) { - if (err) { - // Try chmod() for sftp servers that may not support fchmod() for - // whatever reason - self.sftp.chmod(self.path, self.mode, function(err_) { - tryAgain(); - }); - return; - } - - // SFTPv3 requires absolute offsets, no matter the open flag used - if (self.flags[0] === 'a') { - self.sftp.fstat(handle, function tryStat(err, st) { - if (err) { - // Try stat() for sftp servers that may not support fstat() for - // whatever reason - self.sftp.stat(self.path, function(err_, st_) { - if (err_) { - self.destroy(); - self.emit('error', err); - return; - } - tryStat(null, st_); - }); - return; - } - - self.pos = st.size; - self.emit('open', handle); - }); - return; - } - self.emit('open', handle); - }); - }); -}; - -WriteStream.prototype._write = function(data, encoding, cb) { - if (!Buffer.isBuffer(data)) - return this.emit('error', new Error('Invalid data')); - - if (!Buffer.isBuffer(this.handle)) { - return this.once('open', function() { - this._write(data, encoding, cb); - }); - } - - var self = this; - this.sftp.writeData(this.handle, - data, - 0, - data.length, - this.pos, - function(er, bytes) { - if (er) { - if (self.autoClose) - self.destroy(); - return cb(er); - } - self.bytesWritten += bytes; - cb(); - }); - - this.pos += data.length; -}; - -WriteStream.prototype._writev = function(data, cb) { - if (!Buffer.isBuffer(this.handle)) { - return this.once('open', function() { - this._writev(data, cb); - }); - } - - var sftp = this.sftp; - var handle = this.handle; - var writesLeft = data.length; - var self = this; - - for (var i = 0; i < data.length; ++i) { - var chunk = data[i].chunk; - - sftp.writeData(handle, chunk, 0, chunk.length, this.pos, onwrite); - this.pos += chunk.length; - } - - function onwrite(er, bytes) { - if (er) { - self.destroy(); - return cb(er); - } - self.bytesWritten += bytes; - if (--writesLeft === 0) - cb(); - } -}; - -WriteStream.prototype.destroy = ReadStream.prototype.destroy; -WriteStream.prototype.close = ReadStream.prototype.close; - -// There is no shutdown() for files. -WriteStream.prototype.destroySoon = WriteStream.prototype.end; - - -module.exports = SFTPStream; - diff --git a/reverse_engineering/node_modules/ssh2-streams/lib/ssh.js b/reverse_engineering/node_modules/ssh2-streams/lib/ssh.js deleted file mode 100644 index d70dc74..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/lib/ssh.js +++ /dev/null @@ -1,5403 +0,0 @@ -// TODO: * Automatic re-key every (configurable) n bytes or length of time -// - RFC suggests every 1GB of transmitted data or 1 hour, whichever -// comes sooner -// * Filter control codes from strings -// (as per http://tools.ietf.org/html/rfc4251#section-9.2) - -var crypto = require('crypto'); -var zlib = require('zlib'); -var TransformStream = require('stream').Transform; -var inherits = require('util').inherits; -var inspect = require('util').inspect; -var BUFFER_MAX_LEN = require('buffer').kMaxLength; - -var StreamSearch = require('streamsearch'); - -var consts = require('./constants'); -var utils = require('./utils'); -var isStreamCipher = utils.isStreamCipher; -var iv_inc = utils.iv_inc; -var readString = utils.readString; -var readInt = utils.readInt; -var DSASigBERToBare = utils.DSASigBERToBare; -var DSASigBareToBER = utils.DSASigBareToBER; -var ECDSASigSSHToASN1 = utils.ECDSASigSSHToASN1; -var ECDSASigASN1ToSSH = utils.ECDSASigASN1ToSSH; -var RSAKeySSHToASN1 = utils.RSAKeySSHToASN1; -var DSAKeySSHToASN1 = utils.DSAKeySSHToASN1; -var ECDSAKeySSHToASN1 = utils.ECDSAKeySSHToASN1; - -var MESSAGE = consts.MESSAGE; -var DYNAMIC_KEXDH_MESSAGE = consts.DYNAMIC_KEXDH_MESSAGE; -var KEXDH_MESSAGE = consts.KEXDH_MESSAGE; -var ALGORITHMS = consts.ALGORITHMS; -var DISCONNECT_REASON = consts.DISCONNECT_REASON; -var CHANNEL_OPEN_FAILURE = consts.CHANNEL_OPEN_FAILURE; -var SSH_TO_OPENSSL = consts.SSH_TO_OPENSSL; -var TERMINAL_MODE = consts.TERMINAL_MODE; -var SIGNALS = consts.SIGNALS; -var BUGS = consts.BUGS; -var BUGGY_IMPLS = consts.BUGGY_IMPLS; -var BUGGY_IMPLS_LEN = BUGGY_IMPLS.length; -var MODULE_VER = require('../package.json').version; -var I = 0; -var IN_INIT = I++; -var IN_GREETING = I++; -var IN_HEADER = I++; -var IN_PACKETBEFORE = I++; -var IN_PACKET = I++; -var IN_PACKETDATA = I++; -var IN_PACKETDATAVERIFY = I++; -var IN_PACKETDATAAFTER = I++; -var OUT_INIT = I++; -var OUT_READY = I++; -var OUT_REKEYING = I++; -var MAX_SEQNO = 4294967295; -var MAX_PACKET_SIZE = 35000; -var MAX_PACKETS_REKEYING = 50; -var EXP_TYPE_HEADER = 0; -var EXP_TYPE_LF = 1; -var EXP_TYPE_BYTES = 2; // Waits until n bytes have been seen -var Z_PARTIAL_FLUSH = zlib.Z_PARTIAL_FLUSH; -var ZLIB_OPTS = { flush: Z_PARTIAL_FLUSH }; - -var RE_KEX_HASH = /-(.+)$/; -var RE_GEX = /^gex-/; -var RE_NULL = /\x00/g; -var RE_GCM = /^aes\d+-gcm/i; - -var IDENT_PREFIX_BUFFER = new Buffer('SSH-'); -var EMPTY_BUFFER = new Buffer(0); -var PING_PACKET = new Buffer([ - MESSAGE.GLOBAL_REQUEST, - // "keepalive@openssh.com" - 0, 0, 0, 21, - 107, 101, 101, 112, 97, 108, 105, 118, 101, 64, 111, 112, 101, 110, 115, - 115, 104, 46, 99, 111, 109, - // Request a reply - 1 -]); -var NEWKEYS_PACKET = new Buffer([MESSAGE.NEWKEYS]); -var USERAUTH_SUCCESS_PACKET = new Buffer([MESSAGE.USERAUTH_SUCCESS]); -var REQUEST_SUCCESS_PACKET = new Buffer([MESSAGE.REQUEST_SUCCESS]); -var REQUEST_FAILURE_PACKET = new Buffer([MESSAGE.REQUEST_FAILURE]); -var NO_TERMINAL_MODES_BUFFER = new Buffer([TERMINAL_MODE.TTY_OP_END]); -var KEXDH_GEX_REQ_PACKET = new Buffer([ - MESSAGE.KEXDH_GEX_REQUEST, - // Minimal size in bits of an acceptable group - 0, 0, 4, 0, // 1024, modp2 - // Preferred size in bits of the group the server will send - 0, 0, 16, 0, // 4096, modp16 - // Maximal size in bits of an acceptable group - 0, 0, 32, 0 // 8192, modp18 -]); - -function DEBUG_NOOP(msg) {} - -function SSH2Stream(cfg) { - if (typeof cfg !== 'object' || cfg === null) - cfg = {}; - - TransformStream.call(this, { - highWaterMark: (typeof cfg.highWaterMark === 'number' - ? cfg.highWaterMark - : 32 * 1024) - }); - - this._needContinue = false; - this.bytesSent = this.bytesReceived = 0; - this.debug = (typeof cfg.debug === 'function' ? cfg.debug : DEBUG_NOOP); - this.server = (cfg.server === true); - this.maxPacketSize = (typeof cfg.maxPacketSize === 'number' - ? cfg.maxPacketSize - : MAX_PACKET_SIZE); - // Bitmap that indicates any bugs the remote side has. This is determined - // by the reported software version. - this.remoteBugs = 0; - - if (this.server) { - // TODO: Remove when we support group exchange for server implementation - this.remoteBugs = BUGS.BAD_DHGEX; - } - - var self = this; - - var hostKeys = cfg.hostKeys; - if (this.server && (typeof hostKeys !== 'object' || hostKeys === null)) - throw new Error('hostKeys must be an object keyed on host key type'); - - this.config = { - // Server - hostKeys: hostKeys, // All keys supported by server - - // Client/Server - ident: 'SSH-2.0-' - + (cfg.ident - || ('ssh2js' + MODULE_VER + (this.server ? 'srv' : ''))), - algorithms: { - kex: ALGORITHMS.KEX, - kexBuf: ALGORITHMS.KEX_BUF, - serverHostKey: ALGORITHMS.SERVER_HOST_KEY, - serverHostKeyBuf: ALGORITHMS.SERVER_HOST_KEY_BUF, - cipher: ALGORITHMS.CIPHER, - cipherBuf: ALGORITHMS.CIPHER_BUF, - hmac: ALGORITHMS.HMAC, - hmacBuf: ALGORITHMS.HMAC_BUF, - compress: ALGORITHMS.COMPRESS, - compressBuf: ALGORITHMS.COMPRESS_BUF - } - }; - // RFC 4253 states the identification string must not contain NULL - this.config.ident.replace(RE_NULL, ''); - - if (this.config.ident.length + 2 /* Account for "\r\n" */ > 255) - throw new Error('ident too long'); - - if (typeof cfg.algorithms === 'object' && cfg.algorithms !== null) { - var algos = cfg.algorithms; - if (Array.isArray(algos.kex) && algos.kex.length > 0) { - this.config.algorithms.kex = algos.kex; - if (!Buffer.isBuffer(algos.kexBuf)) - algos.kexBuf = new Buffer(algos.kex.join(','), 'ascii'); - this.config.algorithms.kexBuf = algos.kexBuf; - } - if (Array.isArray(algos.serverHostKey) && algos.serverHostKey.length > 0) { - this.config.algorithms.serverHostKey = algos.serverHostKey; - if (!Buffer.isBuffer(algos.serverHostKeyBuf)) { - algos.serverHostKeyBuf = new Buffer(algos.serverHostKey.join(','), - 'ascii'); - } - this.config.algorithms.serverHostKeyBuf = algos.serverHostKeyBuf; - } - if (Array.isArray(algos.cipher) && algos.cipher.length > 0) { - this.config.algorithms.cipher = algos.cipher; - if (!Buffer.isBuffer(algos.cipherBuf)) - algos.cipherBuf = new Buffer(algos.cipher.join(','), 'ascii'); - this.config.algorithms.cipherBuf = algos.cipherBuf; - } - if (Array.isArray(algos.hmac) && algos.hmac.length > 0) { - this.config.algorithms.hmac = algos.hmac; - if (!Buffer.isBuffer(algos.hmacBuf)) - algos.hmacBuf = new Buffer(algos.hmac.join(','), 'ascii'); - this.config.algorithms.hmacBuf = algos.hmacBuf; - } - if (Array.isArray(algos.compress) && algos.compress.length > 0) { - this.config.algorithms.compress = algos.compress; - if (!Buffer.isBuffer(algos.compressBuf)) - algos.compressBuf = new Buffer(algos.compress.join(','), 'ascii'); - this.config.algorithms.compressBuf = algos.compressBuf; - } - } - - this.reset(true); - - // Common events - this.on('end', function() { - // Let GC collect any Buffers we were previously storing - self._state = undefined; - self.reset(); - self._state.incoming.hmac.bufCompute = undefined; - self._state.outgoing.bufSeqno = undefined; - }); - this.on('DISCONNECT', function(reason, code, desc, lang) { - onDISCONNECT(self, reason, code, desc, lang); - }); - this.on('KEXINIT', function(init, firstFollows) { - onKEXINIT(self, init, firstFollows); - }); - this.on('NEWKEYS', function() { onNEWKEYS(self); }); - - if (this.server) { - // Server-specific events - this.on('KEXDH_INIT', function(e) { onKEXDH_INIT(self, e); }); - } else { - // Client-specific events - this.on('KEXDH_REPLY', function(info) { onKEXDH_REPLY(self, info); }) - .on('KEXDH_GEX_GROUP', - function(prime, gen) { onKEXDH_GEX_GROUP(self, prime, gen); }); - } - - if (this.server) { - // Greeting displayed before the ssh identification string is sent, this is - // usually ignored by most clients - if (typeof cfg.greeting === 'string' && cfg.greeting.length) { - if (cfg.greeting.slice(-2) === '\r\n') - this.push(cfg.greeting); - else - this.push(cfg.greeting + '\r\n'); - } - // Banner shown after the handshake completes, but before user - // authentication begins - if (typeof cfg.banner === 'string' && cfg.banner.length) { - if (cfg.banner.slice(-2) === '\r\n') - this.banner = cfg.banner; - else - this.banner = cfg.banner + '\r\n'; - } - } - this.debug('DEBUG: Local ident: ' + inspect(this.config.ident)); - this.push(this.config.ident + '\r\n'); - - this._state.incoming.expectedPacket = 'KEXINIT'; -} -inherits(SSH2Stream, TransformStream); - -SSH2Stream.prototype.__read = TransformStream.prototype._read; -SSH2Stream.prototype._read = function(n) { - if (this._needContinue) { - this._needContinue = false; - this.emit('continue'); - } - return this.__read(n); -}; -SSH2Stream.prototype.__push = TransformStream.prototype.push; -SSH2Stream.prototype.push = function(chunk, encoding) { - var ret = this.__push(chunk, encoding); - this._needContinue = (ret === false); - return ret; -}; - -SSH2Stream.prototype._cleanup = function(callback) { - this.reset(); - this.debug('DEBUG: Parser: Malformed packet'); - callback && callback(new Error('Malformed packet')); -}; - -SSH2Stream.prototype._transform = function(chunk, encoding, callback, decomp) { - var skipDecrypt = false; - var doDecryptGCM = false; - var state = this._state; - var instate = state.incoming; - var outstate = state.outgoing; - var expect = instate.expect; - var decrypt = instate.decrypt; - var decompress = instate.decompress; - var chlen = chunk.length; - var chleft = 0; - var debug = this.debug; - var self = this; - var i = 0; - var p = i; - var buffer; - var buf; - var r; - - this.bytesReceived += chlen; - - while (true) { - if (expect.type !== undefined) { - if (i >= chlen) - break; - if (expect.type === EXP_TYPE_BYTES) { - chleft = (chlen - i); - var pktLeft = (expect.buf.length - expect.ptr); - if (pktLeft <= chleft) { - chunk.copy(expect.buf, expect.ptr, i, i + pktLeft); - i += pktLeft; - buffer = expect.buf; - expect.buf = undefined; - expect.ptr = 0; - expect.type = undefined; - } else { - chunk.copy(expect.buf, expect.ptr, i); - expect.ptr += chleft; - i += chleft; - } - continue; - } else if (expect.type === EXP_TYPE_HEADER) { - i += instate.search.push(chunk); - if (expect.type !== undefined) - continue; - } else if (expect.type === EXP_TYPE_LF) { - if (++expect.ptr + 4 /* Account for "SSH-" */ > 255) { - this.reset(); - debug('DEBUG: Parser: Identification string exceeded 255 characters'); - return callback(new Error('Max identification string size exceeded')); - } - if (chunk[i] === 0x0A) { - expect.type = undefined; - if (p < i) { - if (expect.buf === undefined) - expect.buf = chunk.toString('ascii', p, i); - else - expect.buf += chunk.toString('ascii', p, i); - } - buffer = expect.buf; - expect.buf = undefined; - ++i; - } else { - if (++i === chlen && p < i) { - if (expect.buf === undefined) - expect.buf = chunk.toString('ascii', p, i); - else - expect.buf += chunk.toString('ascii', p, i); - } - continue; - } - } - } - - if (instate.status === IN_INIT) { - if (this.server) { - // Retrieve what should be the start of the protocol version exchange - if (!buffer) { - debug('DEBUG: Parser: IN_INIT (waiting for identification begin)'); - expectData(this, EXP_TYPE_BYTES, 4); - } else { - if (buffer[0] === 0x53 // S - && buffer[1] === 0x53 // S - && buffer[2] === 0x48 // H - && buffer[3] === 0x2D) { // - - instate.status = IN_GREETING; - debug('DEBUG: Parser: IN_INIT (waiting for rest of identification)'); - } else { - this.reset(); - debug('DEBUG: Parser: Bad identification start'); - return callback(new Error('Bad identification start')); - } - } - } else { - debug('DEBUG: Parser: IN_INIT'); - // Retrieve any bytes that may come before the protocol version exchange - var ss = instate.search = new StreamSearch(IDENT_PREFIX_BUFFER); - ss.on('info', function onInfo(matched, data, start, end) { - if (data) { - if (instate.greeting === undefined) - instate.greeting = data.toString('binary', start, end); - else - instate.greeting += data.toString('binary', start, end); - } - if (matched) { - expect.type = undefined; - instate.search.removeListener('info', onInfo); - } - }); - ss.maxMatches = 1; - expectData(this, EXP_TYPE_HEADER); - instate.status = IN_GREETING; - } - } else if (instate.status === IN_GREETING) { - debug('DEBUG: Parser: IN_GREETING'); - instate.search = undefined; - // Retrieve the identification bytes after the "SSH-" header - p = i; - expectData(this, EXP_TYPE_LF); - instate.status = IN_HEADER; - } else if (instate.status === IN_HEADER) { - debug('DEBUG: Parser: IN_HEADER'); - if (buffer.charCodeAt(buffer.length - 1) === 13) - buffer = buffer.slice(0, -1); - var idxDash = buffer.indexOf('-'); - var idxSpace = buffer.indexOf(' '); - var header = { - // RFC says greeting SHOULD be utf8 - greeting: instate.greeting, - identRaw: 'SSH-' + buffer, - versions: { - protocol: buffer.substr(0, idxDash), - software: (idxSpace === -1 - ? buffer.substring(idxDash + 1) - : buffer.substring(idxDash + 1, idxSpace)) - }, - comments: (idxSpace > -1 ? buffer.substring(idxSpace + 1) : undefined) - }; - instate.greeting = undefined; - - if (header.versions.protocol !== '1.99' - && header.versions.protocol !== '2.0') { - this.reset(); - debug('DEBUG: Parser: protocol version not supported: ' - + header.versions.protocol); - return callback(new Error('Protocol version not supported')); - } else - this.emit('header', header); - - if (instate.status === IN_INIT) { - // We reset from an event handler, possibly due to an unsupported SSH - // protocol version? - return; - } - - var identRaw = header.identRaw; - var software = header.versions.software; - this.debug('DEBUG: Remote ident: ' + inspect(identRaw)); - for (var j = 0, rule; j < BUGGY_IMPLS_LEN; ++j) { - rule = BUGGY_IMPLS[j]; - if (typeof rule[0] === 'string') { - if (software === rule[0]) - this.remoteBugs |= rule[1]; - } else if (rule[0].test(software)) - this.remoteBugs |= rule[1]; - } - instate.identRaw = identRaw; - // Adjust bytesReceived first otherwise it will have an incorrectly larger - // total when we call back into this function after completing KEXINIT - this.bytesReceived -= (chlen - i); - KEXINIT(this, function() { - if (i === chlen) - callback(); - else - self._transform(chunk.slice(i), encoding, callback); - }); - instate.status = IN_PACKETBEFORE; - return; - } else if (instate.status === IN_PACKETBEFORE) { - debug('DEBUG: Parser: IN_PACKETBEFORE (expecting ' + decrypt.size + ')'); - // Wait for the right number of bytes so we can determine the incoming - // packet length - expectData(this, EXP_TYPE_BYTES, decrypt.size, decrypt.buf); - instate.status = IN_PACKET; - } else if (instate.status === IN_PACKET) { - debug('DEBUG: Parser: IN_PACKET'); - doDecryptGCM = (decrypt.instance && decrypt.isGCM); - if (decrypt.instance && !decrypt.isGCM) - buffer = decryptData(this, buffer); - - r = readInt(buffer, 0, this, callback); - if (r === false) - return; - var macSize = (instate.hmac.size || 0); - var fullPacketLen = r + 4 + macSize; - var maxPayloadLen = this.maxPacketSize; - if (decompress.instance) { - // Account for compressed payloads - // This formula is taken from dropbear which derives it from zlib's - // documentation. Explanation from dropbear: - /* For exact details see http://www.zlib.net/zlib_tech.html - * 5 bytes per 16kB block, plus 6 bytes for the stream. - * We might allocate 5 unnecessary bytes here if it's an - * exact multiple. */ - maxPayloadLen += (((this.maxPacketSize / 16384) + 1) * 5 + 6); - } - if (r > maxPayloadLen - // TODO: Change 16 to "MAX(16, decrypt.size)" when/if SSH2 adopts - // 512-bit ciphers - || fullPacketLen < (16 + macSize) - || ((r + (doDecryptGCM ? 0 : 4)) % decrypt.size) !== 0) { - this.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - debug('DEBUG: Parser: Bad packet length (' + fullPacketLen + ')'); - return callback(new Error('Bad packet length')); - } - - instate.pktLen = r; - var remainLen = instate.pktLen + 4 - decrypt.size; - if (doDecryptGCM) { - decrypt.instance.setAAD(buffer.slice(0, 4)); - debug('DEBUG: Parser: pktLen:' - + instate.pktLen - + ',remainLen:' - + remainLen); - } else { - instate.padLen = buffer[4]; - debug('DEBUG: Parser: pktLen:' - + instate.pktLen - + ',padLen:' - + instate.padLen - + ',remainLen:' - + remainLen); - } - if (remainLen > 0) { - if (doDecryptGCM) - instate.pktExtra = buffer.slice(4); - else - instate.pktExtra = buffer.slice(5); - // Grab the rest of the packet - expectData(this, EXP_TYPE_BYTES, remainLen); - instate.status = IN_PACKETDATA; - } else if (remainLen < 0) - instate.status = IN_PACKETBEFORE; - else { - // Entire message fit into one block - skipDecrypt = true; - instate.status = IN_PACKETDATA; - continue; - } - } else if (instate.status === IN_PACKETDATA) { - debug('DEBUG: Parser: IN_PACKETDATA'); - doDecryptGCM = (decrypt.instance && decrypt.isGCM); - if (decrypt.instance && !skipDecrypt && !doDecryptGCM) - buffer = decryptData(this, buffer); - else if (skipDecrypt) - skipDecrypt = false; - var padStart = instate.pktLen - instate.padLen - 1; - // TODO: Allocate a Buffer once that is slightly larger than maxPacketSize - // (to accommodate for packet length field and MAC) and re-use that - // instead - if (instate.pktExtra) { - buf = new Buffer(instate.pktExtra.length + buffer.length); - instate.pktExtra.copy(buf); - buffer.copy(buf, instate.pktExtra.length); - instate.payload = buf.slice(0, padStart); - } else { - // Entire message fit into one block - if (doDecryptGCM) - buf = buffer.slice(4); - else - buf = buffer.slice(5); - instate.payload = buffer.slice(5, 5 + padStart); - } - if (instate.hmac.size !== undefined) { - // Wait for hmac hash - debug('DEBUG: Parser: HMAC size:' + instate.hmac.size); - expectData(this, EXP_TYPE_BYTES, instate.hmac.size, instate.hmac.buf); - instate.status = IN_PACKETDATAVERIFY; - instate.packet = buf; - } else - instate.status = IN_PACKETDATAAFTER; - instate.pktExtra = undefined; - buf = undefined; - } else if (instate.status === IN_PACKETDATAVERIFY) { - debug('DEBUG: Parser: IN_PACKETDATAVERIFY'); - // Verify packet data integrity - if (hmacVerify(this, buffer)) { - debug('DEBUG: Parser: IN_PACKETDATAVERIFY (Valid HMAC)'); - instate.status = IN_PACKETDATAAFTER; - instate.packet = undefined; - } else { - this.reset(); - debug('DEBUG: Parser: IN_PACKETDATAVERIFY (Invalid HMAC)'); - return callback(new Error('Invalid HMAC')); - } - } else if (instate.status === IN_PACKETDATAAFTER) { - if (decompress.instance) { - if (!decomp) { - debug('DEBUG: Parser: Decompressing'); - decompress.instance.write(instate.payload); - var decompBuf = []; - var decompBufLen = 0; - decompress.instance.on('readable', function() { - var buf; - while (buf = this.read()) { - decompBuf.push(buf); - decompBufLen += buf.length; - } - }).flush(Z_PARTIAL_FLUSH, function() { - decompress.instance.removeAllListeners('readable'); - if (decompBuf.length === 1) - instate.payload = decompBuf[0]; - else - instate.payload = Buffer.concat(decompBuf, decompBufLen); - decompBuf = null; - var nextSlice; - if (i === chlen) - nextSlice = EMPTY_BUFFER; // Avoid slicing a zero-length buffer - else - nextSlice = chunk.slice(i); - self._transform(nextSlice, encoding, callback, true); - }); - return; - } else { - // Make sure we reset this after this first time in the loop, - // otherwise we could end up trying to interpret as-is another - // compressed packet that is within the same chunk - decomp = false; - } - } - - this.emit('packet'); - - var ptype = instate.payload[0]; - - if (debug !== DEBUG_NOOP) { - var msgPacket = 'DEBUG: Parser: IN_PACKETDATAAFTER, packet: '; - var kexdh = state.kexdh; - var authMethod = state.authsQueue[0]; - var msgPktType = null; - - if (outstate.status === OUT_REKEYING - && !(ptype <= 4 || (ptype >= 20 && ptype <= 49))) - msgPacket += '(enqueued) '; - - if (ptype === MESSAGE.KEXDH_INIT) { - if (kexdh === 'group') - msgPktType = 'KEXDH_INIT'; - else if (kexdh[0] === 'e') - msgPktType = 'KEXECDH_INIT'; - else - msgPktType = 'KEXDH_GEX_REQUEST'; - } else if (ptype === MESSAGE.KEXDH_REPLY) { - if (kexdh === 'group') - msgPktType = 'KEXDH_REPLY'; - else if (kexdh[0] === 'e') - msgPktType = 'KEXECDH_REPLY'; - else - msgPktType = 'KEXDH_GEX_GROUP'; - } else if (ptype === MESSAGE.KEXDH_GEX_GROUP) - msgPktType = 'KEXDH_GEX_GROUP'; - else if (ptype === MESSAGE.KEXDH_GEX_REPLY) - msgPktType = 'KEXDH_GEX_REPLY'; - else if (ptype === 60) { - if (authMethod === 'password') - msgPktType = 'USERAUTH_PASSWD_CHANGEREQ'; - else if (authMethod === 'keyboard-interactive') - msgPktType = 'USERAUTH_INFO_REQUEST'; - else if (authMethod === 'publickey') - msgPktType = 'USERAUTH_PK_OK'; - else - msgPktType = 'UNKNOWN PACKET 60'; - } else if (ptype === 61) { - if (authMethod === 'keyboard-interactive') - msgPktType = 'USERAUTH_INFO_RESPONSE'; - else - msgPktType = 'UNKNOWN PACKET 61'; - } - - if (msgPktType === null) - msgPktType = MESSAGE[ptype]; - - // Don't write debug output for messages we custom make in parsePacket() - if (ptype !== MESSAGE.CHANNEL_OPEN - && ptype !== MESSAGE.CHANNEL_REQUEST - && ptype !== MESSAGE.CHANNEL_SUCCESS - && ptype !== MESSAGE.CHANNEL_FAILURE - && ptype !== MESSAGE.CHANNEL_EOF - && ptype !== MESSAGE.CHANNEL_CLOSE - && ptype !== MESSAGE.CHANNEL_DATA - && ptype !== MESSAGE.CHANNEL_EXTENDED_DATA - && ptype !== MESSAGE.CHANNEL_WINDOW_ADJUST - && ptype !== MESSAGE.DISCONNECT - && ptype !== MESSAGE.USERAUTH_REQUEST - && ptype !== MESSAGE.GLOBAL_REQUEST) - debug(msgPacket + msgPktType); - } - - // Only parse packet if we are not re-keying or the packet is not a - // transport layer packet needed for re-keying - if (outstate.status === OUT_READY - || ptype <= 4 - || (ptype >= 20 && ptype <= 49)) { - if (parsePacket(this, callback) === false) - return; - - if (instate.status === IN_INIT) { - // We were reset due to some error/disagreement ? - return; - } - } else if (outstate.status === OUT_REKEYING) { - if (instate.rekeyQueue.length === MAX_PACKETS_REKEYING) { - debug('DEBUG: Parser: Max incoming re-key queue length reached'); - this.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - return callback( - new Error('Incoming re-key queue length limit reached') - ); - } - - // Make sure to record the sequence number in case we need it later on - // when we drain the queue (e.g. unknown packet) - var seqno = instate.seqno; - if (++instate.seqno > MAX_SEQNO) - instate.seqno = 0; - - instate.rekeyQueue.push(seqno, instate.payload); - } - - instate.status = IN_PACKETBEFORE; - instate.payload = undefined; - } - if (buffer !== undefined) - buffer = undefined; - } - - callback(); -}; - -SSH2Stream.prototype.reset = function(noend) { - if (this._state) { - var state = this._state; - state.incoming.status = IN_INIT; - state.outgoing.status = OUT_INIT; - } else { - this._state = { - authsQueue: [], - hostkeyFormat: undefined, - kex: undefined, - kexdh: undefined, - - incoming: { - status: IN_INIT, - expectedPacket: undefined, - search: undefined, - greeting: undefined, - seqno: 0, - pktLen: undefined, - padLen: undefined, - pktExtra: undefined, - payload: undefined, - packet: undefined, - kexinit: undefined, - identRaw: undefined, - rekeyQueue: [], - ignoreNext: false, - - expect: { - amount: undefined, - type: undefined, - ptr: 0, - buf: undefined - }, - - decrypt: { - instance: false, - size: 8, - isGCM: false, - iv: undefined, // GCM - key: undefined, // GCM - buf: undefined, - type: undefined - }, - - hmac: { - size: undefined, - key: undefined, - buf: undefined, - bufCompute: new Buffer(9), - type: false - }, - - decompress: { - instance: false, - type: false - } - }, - - outgoing: { - status: OUT_INIT, - seqno: 0, - bufSeqno: new Buffer(4), - rekeyQueue: [], - kexinit: undefined, - kexsecret: undefined, - pubkey: undefined, - exchangeHash: undefined, - sessionId: undefined, - sentNEWKEYS: false, - - encrypt: { - instance: false, - size: 8, - isGCM: false, - iv: undefined, // GCM - key: undefined, // GCM - type: undefined - }, - - hmac: { - size: undefined, - key: undefined, - buf: undefined, - type: false - }, - - compress: { - instance: false, - type: false - } - } - }; - } - if (!noend) { - if (this.readable) - this.push(null); - } -}; - -// Common methods -// Global -SSH2Stream.prototype.disconnect = function(reason) { - /* - byte SSH_MSG_DISCONNECT - uint32 reason code - string description in ISO-10646 UTF-8 encoding - string language tag - */ - var buf = new Buffer(1 + 4 + 4 + 4); - - buf.fill(0); - buf[0] = MESSAGE.DISCONNECT; - - if (DISCONNECT_REASON[reason] === undefined) - reason = DISCONNECT_REASON.BY_APPLICATION; - buf.writeUInt32BE(reason, 1, true); - - this.debug('DEBUG: Outgoing: Writing DISCONNECT (' - + DISCONNECT_REASON[reason] - + ')'); - send(this, buf); - this.reset(); - - return false; -}; -SSH2Stream.prototype.ping = function() { - this.debug('DEBUG: Outgoing: Writing ping (GLOBAL_REQUEST: keepalive@openssh.com)'); - return send(this, PING_PACKET); -}; -SSH2Stream.prototype.rekey = function() { - var status = this._state.outgoing.status; - if (status === OUT_REKEYING) - throw new Error('A re-key is already in progress'); - else if (status !== OUT_READY) - throw new Error('Cannot re-key yet'); - - this.debug('DEBUG: Outgoing: Starting re-key'); - return KEXINIT(this); -}; - -// 'ssh-connection' service-specific -SSH2Stream.prototype.requestSuccess = function(data) { - var buf; - if (Buffer.isBuffer(data)) { - buf = new Buffer(1 + data.length); - - buf[0] = MESSAGE.REQUEST_SUCCESS; - - data.copy(buf, 1); - } else - buf = REQUEST_SUCCESS_PACKET; - - this.debug('DEBUG: Outgoing: Writing REQUEST_SUCCESS'); - return send(this, buf); -}; -SSH2Stream.prototype.requestFailure = function() { - this.debug('DEBUG: Outgoing: Writing REQUEST_FAILURE'); - return send(this, REQUEST_FAILURE_PACKET); -}; -SSH2Stream.prototype.channelSuccess = function(chan) { - // Does not consume window space - var buf = new Buffer(1 + 4); - - buf[0] = MESSAGE.CHANNEL_SUCCESS; - - buf.writeUInt32BE(chan, 1, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_SUCCESS (' + chan + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelFailure = function(chan) { - // Does not consume window space - var buf = new Buffer(1 + 4); - - buf[0] = MESSAGE.CHANNEL_FAILURE; - - buf.writeUInt32BE(chan, 1, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_FAILURE (' + chan + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelEOF = function(chan) { - // Does not consume window space - var buf = new Buffer(1 + 4); - - buf[0] = MESSAGE.CHANNEL_EOF; - - buf.writeUInt32BE(chan, 1, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_EOF (' + chan + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelClose = function(chan) { - // Does not consume window space - var buf = new Buffer(1 + 4); - - buf[0] = MESSAGE.CHANNEL_CLOSE; - - buf.writeUInt32BE(chan, 1, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_CLOSE (' + chan + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelWindowAdjust = function(chan, amount) { - // Does not consume window space - var buf = new Buffer(1 + 4 + 4); - - buf[0] = MESSAGE.CHANNEL_WINDOW_ADJUST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(amount, 5, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_WINDOW_ADJUST (' - + chan - + ', ' - + amount - + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelData = function(chan, data) { - var dataIsBuffer = Buffer.isBuffer(data); - var dataLen = (dataIsBuffer ? data.length : Buffer.byteLength(data)); - var buf = new Buffer(1 + 4 + 4 + dataLen); - - buf[0] = MESSAGE.CHANNEL_DATA; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(dataLen, 5, true); - if (dataIsBuffer) - data.copy(buf, 9); - else - buf.write(data, 9, dataLen, 'utf8'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_DATA (' + chan + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelExtData = function(chan, data, type) { - var dataIsBuffer = Buffer.isBuffer(data); - var dataLen = (dataIsBuffer ? data.length : Buffer.byteLength(data)); - var buf = new Buffer(1 + 4 + 4 + 4 + dataLen); - - buf[0] = MESSAGE.CHANNEL_EXTENDED_DATA; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(type, 5, true); - - buf.writeUInt32BE(dataLen, 9, true); - if (dataIsBuffer) - data.copy(buf, 13); - else - buf.write(data, 13, dataLen, 'utf8'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_EXTENDED_DATA (' + chan + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelOpenConfirm = function(remoteChan, localChan, - initWindow, maxPacket) { - var buf = new Buffer(1 + 4 + 4 + 4 + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN_CONFIRMATION; - - buf.writeUInt32BE(remoteChan, 1, true); - - buf.writeUInt32BE(localChan, 5, true); - - buf.writeUInt32BE(initWindow, 9, true); - - buf.writeUInt32BE(maxPacket, 13, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN_CONFIRMATION (r:' - + remoteChan - + ', l:' - + localChan - + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.channelOpenFail = function(remoteChan, reason, desc, - lang) { - if (typeof desc !== 'string') - desc = ''; - if (typeof lang !== 'string') - lang = ''; - - var descLen = Buffer.byteLength(desc); - var langLen = Buffer.byteLength(lang); - var p = 9; - var buf = new Buffer(1 + 4 + 4 + 4 + descLen + 4 + langLen); - - buf[0] = MESSAGE.CHANNEL_OPEN_FAILURE; - - buf.writeUInt32BE(remoteChan, 1, true); - - buf.writeUInt32BE(reason, 5, true); - - buf.writeUInt32BE(descLen, p, true); - p += 4; - if (descLen) { - buf.write(desc, p, descLen, 'utf8'); - p += descLen; - } - - buf.writeUInt32BE(langLen, p, true); - if (langLen) - buf.write(lang, p += 4, langLen, 'ascii'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN_FAILURE (' - + remoteChan - + ')'); - return send(this, buf); -}; - -// Client-specific methods -// Global -SSH2Stream.prototype.service = function(svcName) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var svcNameLen = Buffer.byteLength(svcName); - var buf = new Buffer(1 + 4 + svcNameLen); - - buf[0] = MESSAGE.SERVICE_REQUEST; - - buf.writeUInt32BE(svcNameLen, 1, true); - buf.write(svcName, 5, svcNameLen, 'ascii'); - - this.debug('DEBUG: Outgoing: Writing SERVICE_REQUEST (' + svcName + ')'); - return send(this, buf); -}; -// 'ssh-connection' service-specific -SSH2Stream.prototype.tcpipForward = function(bindAddr, bindPort, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var addrlen = Buffer.byteLength(bindAddr); - var buf = new Buffer(1 + 4 + 13 + 1 + 4 + addrlen + 4); - - buf[0] = MESSAGE.GLOBAL_REQUEST; - - buf.writeUInt32BE(13, 1, true); - buf.write('tcpip-forward', 5, 13, 'ascii'); - - buf[18] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(addrlen, 19, true); - buf.write(bindAddr, 23, addrlen, 'ascii'); - - buf.writeUInt32BE(bindPort, 23 + addrlen, true); - - this.debug('DEBUG: Outgoing: Writing GLOBAL_REQUEST (tcpip-forward)'); - return send(this, buf); -}; -SSH2Stream.prototype.cancelTcpipForward = function(bindAddr, bindPort, - wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var addrlen = Buffer.byteLength(bindAddr); - var buf = new Buffer(1 + 4 + 20 + 1 + 4 + addrlen + 4); - - buf[0] = MESSAGE.GLOBAL_REQUEST; - - buf.writeUInt32BE(20, 1, true); - buf.write('cancel-tcpip-forward', 5, 20, 'ascii'); - - buf[25] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(addrlen, 26, true); - buf.write(bindAddr, 30, addrlen, 'ascii'); - - buf.writeUInt32BE(bindPort, 30 + addrlen, true); - - this.debug('DEBUG: Outgoing: Writing GLOBAL_REQUEST (cancel-tcpip-forward)'); - return send(this, buf); -}; -SSH2Stream.prototype.openssh_streamLocalForward = function(socketPath, - wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var pathlen = Buffer.byteLength(socketPath); - var buf = new Buffer(1 + 4 + 31 + 1 + 4 + pathlen); - - buf[0] = MESSAGE.GLOBAL_REQUEST; - - buf.writeUInt32BE(31, 1, true); - buf.write('streamlocal-forward@openssh.com', 5, 31, 'ascii'); - - buf[36] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(pathlen, 37, true); - buf.write(socketPath, 41, pathlen, 'utf8'); - - this.debug('DEBUG: Outgoing: Writing GLOBAL_REQUEST (streamlocal-forward@openssh.com)'); - return send(this, buf); -}; -SSH2Stream.prototype.openssh_cancelStreamLocalForward = function(socketPath, - wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var pathlen = Buffer.byteLength(socketPath); - var buf = new Buffer(1 + 4 + 38 + 1 + 4 + pathlen); - - buf[0] = MESSAGE.GLOBAL_REQUEST; - - buf.writeUInt32BE(38, 1, true); - buf.write('cancel-streamlocal-forward@openssh.com', 5, 38, 'ascii'); - - buf[43] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(pathlen, 44, true); - buf.write(socketPath, 48, pathlen, 'utf8'); - - this.debug('DEBUG: Outgoing: Writing GLOBAL_REQUEST (cancel-streamlocal-forward@openssh.com)'); - return send(this, buf); -}; -SSH2Stream.prototype.directTcpip = function(chan, initWindow, maxPacket, cfg) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var srclen = Buffer.byteLength(cfg.srcIP); - var dstlen = Buffer.byteLength(cfg.dstIP); - var p = 29; - var buf = new Buffer(1 + 4 + 12 + 4 + 4 + 4 + 4 + srclen + 4 + 4 + dstlen - + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN; - - buf.writeUInt32BE(12, 1, true); - buf.write('direct-tcpip', 5, 12, 'ascii'); - - buf.writeUInt32BE(chan, 17, true); - - buf.writeUInt32BE(initWindow, 21, true); - - buf.writeUInt32BE(maxPacket, 25, true); - - buf.writeUInt32BE(dstlen, p, true); - buf.write(cfg.dstIP, p += 4, dstlen, 'ascii'); - - buf.writeUInt32BE(cfg.dstPort, p += dstlen, true); - - buf.writeUInt32BE(srclen, p += 4, true); - buf.write(cfg.srcIP, p += 4, srclen, 'ascii'); - - buf.writeUInt32BE(cfg.srcPort, p += srclen, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN (' - + chan - + ', direct-tcpip)'); - return send(this, buf); -}; -SSH2Stream.prototype.openssh_directStreamLocal = function(chan, initWindow, - maxPacket, cfg) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var pathlen = Buffer.byteLength(cfg.socketPath); - var p = 47; - var buf = new Buffer(1 + 4 + 30 + 4 + 4 + 4 + 4 + pathlen + 4 + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN; - - buf.writeUInt32BE(30, 1, true); - buf.write('direct-streamlocal@openssh.com', 5, 30, 'ascii'); - - buf.writeUInt32BE(chan, 35, true); - - buf.writeUInt32BE(initWindow, 39, true); - - buf.writeUInt32BE(maxPacket, 43, true); - - buf.writeUInt32BE(pathlen, p, true); - buf.write(cfg.socketPath, p += 4, pathlen, 'utf8'); - - // reserved fields (string and uint32) - buf.fill(0, buf.length - 8); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN (' - + chan - + ', direct-streamlocal@openssh.com)'); - return send(this, buf); -}; -SSH2Stream.prototype.openssh_noMoreSessions = function(wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var buf = new Buffer(1 + 4 + 28 + 1); - - buf[0] = MESSAGE.GLOBAL_REQUEST; - - buf.writeUInt32BE(28, 1, true); - buf.write('no-more-sessions@openssh.com', 5, 28, 'ascii'); - - buf[33] = (wantReply === undefined || wantReply === true ? 1 : 0); - - this.debug('DEBUG: Outgoing: Writing GLOBAL_REQUEST (no-more-sessions@openssh.com)'); - return send(this, buf); -}; -SSH2Stream.prototype.session = function(chan, initWindow, maxPacket) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var buf = new Buffer(1 + 4 + 7 + 4 + 4 + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN; - - buf.writeUInt32BE(7, 1, true); - buf.write('session', 5, 7, 'ascii'); - - buf.writeUInt32BE(chan, 12, true); - - buf.writeUInt32BE(initWindow, 16, true); - - buf.writeUInt32BE(maxPacket, 20, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN (' - + chan - + ', session)'); - return send(this, buf); -}; -SSH2Stream.prototype.windowChange = function(chan, rows, cols, height, width) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var buf = new Buffer(1 + 4 + 4 + 13 + 1 + 4 + 4 + 4 + 4); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(13, 5, true); - buf.write('window-change', 9, 13, 'ascii'); - - buf[22] = 0; - - buf.writeUInt32BE(cols, 23, true); - - buf.writeUInt32BE(rows, 27, true); - - buf.writeUInt32BE(width, 31, true); - - buf.writeUInt32BE(height, 35, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', window-change)'); - return send(this, buf); -}; -SSH2Stream.prototype.pty = function(chan, rows, cols, height, - width, term, modes, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - if (!term || !term.length) - term = 'vt100'; - if (modes - && !Buffer.isBuffer(modes) - && !Array.isArray(modes) - && typeof modes === 'object') - modes = modesToBytes(modes); - if (!modes || !modes.length) - modes = NO_TERMINAL_MODES_BUFFER; - - var termLen = term.length; - var modesLen = modes.length; - var p = 21; - var buf = new Buffer(1 + 4 + 4 + 7 + 1 + 4 + termLen + 4 + 4 + 4 + 4 + 4 - + modesLen); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(7, 5, true); - buf.write('pty-req', 9, 7, 'ascii'); - - buf[16] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(termLen, 17, true); - buf.write(term, 21, termLen, 'utf8'); - - buf.writeUInt32BE(cols, p += termLen, true); - - buf.writeUInt32BE(rows, p += 4, true); - - buf.writeUInt32BE(width, p += 4, true); - - buf.writeUInt32BE(height, p += 4, true); - - buf.writeUInt32BE(modesLen, p += 4, true); - p += 4; - if (Array.isArray(modes)) { - for (var i = 0; i < modesLen; ++i) - buf[p++] = modes[i]; - } else if (Buffer.isBuffer(modes)) { - modes.copy(buf, p); - } - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', pty-req)'); - return send(this, buf); -}; -SSH2Stream.prototype.shell = function(chan, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var buf = new Buffer(1 + 4 + 4 + 5 + 1); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(5, 5, true); - buf.write('shell', 9, 5, 'ascii'); - - buf[14] = (wantReply === undefined || wantReply === true ? 1 : 0); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', shell)'); - return send(this, buf); -}; -SSH2Stream.prototype.exec = function(chan, cmd, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var cmdlen = (Buffer.isBuffer(cmd) ? cmd.length : Buffer.byteLength(cmd)); - var buf = new Buffer(1 + 4 + 4 + 4 + 1 + 4 + cmdlen); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(4, 5, true); - buf.write('exec', 9, 4, 'ascii'); - - buf[13] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(cmdlen, 14, true); - if (Buffer.isBuffer(cmd)) - cmd.copy(buf, 18); - else - buf.write(cmd, 18, cmdlen, 'utf8'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', exec)'); - return send(this, buf); -}; -SSH2Stream.prototype.signal = function(chan, signal) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - signal = signal.toUpperCase(); - if (signal.slice(0, 3) === 'SIG') - signal = signal.substring(3); - - if (SIGNALS.indexOf(signal) === -1) - throw new Error('Invalid signal: ' + signal); - - var signalLen = signal.length; - var buf = new Buffer(1 + 4 + 4 + 6 + 1 + 4 + signalLen); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(6, 5, true); - buf.write('signal', 9, 6, 'ascii'); - - buf[15] = 0; - - buf.writeUInt32BE(signalLen, 16, true); - buf.write(signal, 20, signalLen, 'ascii'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', signal)'); - return send(this, buf); -}; -SSH2Stream.prototype.env = function(chan, key, val, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var keyLen = Buffer.byteLength(key); - var valLen = (Buffer.isBuffer(val) ? val.length : Buffer.byteLength(val)); - var buf = new Buffer(1 + 4 + 4 + 3 + 1 + 4 + keyLen + 4 + valLen); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(3, 5, true); - buf.write('env', 9, 3, 'ascii'); - - buf[12] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(keyLen, 13, true); - buf.write(key, 17, keyLen, 'ascii'); - - buf.writeUInt32BE(valLen, 17 + keyLen, true); - if (Buffer.isBuffer(val)) - val.copy(buf, 17 + keyLen + 4); - else - buf.write(val, 17 + keyLen + 4, valLen, 'utf8'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', env)'); - return send(this, buf); -}; -SSH2Stream.prototype.x11Forward = function(chan, cfg, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var protolen = Buffer.byteLength(cfg.protocol); - var cookielen = Buffer.byteLength(cfg.cookie); - var buf = new Buffer(1 + 4 + 4 + 7 + 1 + 1 + 4 + protolen + 4 + cookielen - + 4); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(7, 5, true); - buf.write('x11-req', 9, 7, 'ascii'); - - buf[16] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf[17] = (cfg.single ? 1 : 0); - - buf.writeUInt32BE(protolen, 18, true); - var bp = 22; - if (Buffer.isBuffer(cfg.protocol)) - cfg.protocol.copy(buf, bp); - else - buf.write(cfg.protocol, bp, protolen, 'utf8'); - bp += protolen; - - buf.writeUInt32BE(cookielen, bp, true); - bp += 4; - if (Buffer.isBuffer(cfg.cookie)) - cfg.cookie.copy(buf, bp); - else - buf.write(cfg.cookie, bp, cookielen, 'utf8'); - bp += cookielen; - - buf.writeUInt32BE((cfg.screen || 0), bp, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', x11-req)'); - return send(this, buf); -}; -SSH2Stream.prototype.subsystem = function(chan, name, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var nameLen = Buffer.byteLength(name); - var buf = new Buffer(1 + 4 + 4 + 9 + 1 + 4 + nameLen); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(9, 5, true); - buf.write('subsystem', 9, 9, 'ascii'); - - buf[18] = (wantReply === undefined || wantReply === true ? 1 : 0); - - buf.writeUInt32BE(nameLen, 19, true); - buf.write(name, 23, nameLen, 'ascii'); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', subsystem: ' - + name - + ')'); - return send(this, buf); -}; -SSH2Stream.prototype.openssh_agentForward = function(chan, wantReply) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - // Does not consume window space - var buf = new Buffer(1 + 4 + 4 + 26 + 1); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(26, 5, true); - buf.write('auth-agent-req@openssh.com', 9, 26, 'ascii'); - - buf[35] = (wantReply === undefined || wantReply === true ? 1 : 0); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', auth-agent-req@openssh.com)'); - return send(this, buf); -}; -// 'ssh-userauth' service-specific -SSH2Stream.prototype.authPassword = function(username, password) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var userLen = Buffer.byteLength(username); - var passLen = Buffer.byteLength(password); - var p = 0; - var buf = new Buffer(1 - + 4 + userLen - + 4 + 14 // "ssh-connection" - + 4 + 8 // "password" - + 1 - + 4 + passLen); - - buf[p] = MESSAGE.USERAUTH_REQUEST; - - buf.writeUInt32BE(userLen, ++p, true); - buf.write(username, p += 4, userLen, 'utf8'); - - buf.writeUInt32BE(14, p += userLen, true); - buf.write('ssh-connection', p += 4, 14, 'ascii'); - - buf.writeUInt32BE(8, p += 14, true); - buf.write('password', p += 4, 8, 'ascii'); - - buf[p += 8] = 0; - - buf.writeUInt32BE(passLen, ++p, true); - buf.write(password, p += 4, passLen, 'utf8'); - - this._state.authsQueue.push('password'); - this.debug('DEBUG: Outgoing: Writing USERAUTH_REQUEST (password)'); - return send(this, buf); -}; -SSH2Stream.prototype.authPK = function(username, pubKey, cbSign) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var self = this; - var outstate = this._state.outgoing; - var pubKeyFullType; - - if (pubKey.public) { - pubKeyFullType = pubKey.fulltype; - pubKey = pubKey.public; - } else { - pubKeyFullType = pubKey.toString('ascii', - 4, - 4 + pubKey.readUInt32BE(0, true)); - } - - var userLen = Buffer.byteLength(username); - var algoLen = Buffer.byteLength(pubKeyFullType); - var pubKeyLen = pubKey.length; - var sesLen = outstate.sessionId.length; - var p = 0; - var buf = new Buffer((cbSign ? 4 + sesLen : 0) - + 1 - + 4 + userLen - + 4 + 14 // "ssh-connection" - + 4 + 9 // "publickey" - + 1 - + 4 + algoLen - + 4 + pubKeyLen - ); - - if (cbSign) { - buf.writeUInt32BE(sesLen, p, true); - outstate.sessionId.copy(buf, p += 4); - buf[p += sesLen] = MESSAGE.USERAUTH_REQUEST; - } else - buf[p] = MESSAGE.USERAUTH_REQUEST; - - buf.writeUInt32BE(userLen, ++p, true); - buf.write(username, p += 4, userLen, 'utf8'); - - buf.writeUInt32BE(14, p += userLen, true); - buf.write('ssh-connection', p += 4, 14, 'ascii'); - - buf.writeUInt32BE(9, p += 14, true); - buf.write('publickey', p += 4, 9, 'ascii'); - - buf[p += 9] = (cbSign ? 1 : 0); - - buf.writeUInt32BE(algoLen, ++p, true); - buf.write(pubKeyFullType, p += 4, algoLen, 'ascii'); - - buf.writeUInt32BE(pubKeyLen, p += algoLen, true); - pubKey.copy(buf, p += 4); - - if (!cbSign) { - this._state.authsQueue.push('publickey'); - this.debug('DEBUG: Outgoing: Writing USERAUTH_REQUEST (publickey -- check)'); - return send(this, buf); - } - - cbSign(buf, function(signature) { - if (pubKeyFullType === 'ssh-dss') { - signature = DSASigBERToBare(signature); - } else if (pubKeyFullType !== 'ssh-rsa') { - // ECDSA - signature = ECDSASigASN1ToSSH(signature); - } - - var sigLen = signature.length; - var sigbuf = new Buffer(1 - + 4 + userLen - + 4 + 14 // "ssh-connection" - + 4 + 9 // "publickey" - + 1 - + 4 + algoLen - + 4 + pubKeyLen - + 4 // 4 + algoLen + 4 + sigLen - + 4 + algoLen - + 4 + sigLen); - - p = 0; - - sigbuf[p] = MESSAGE.USERAUTH_REQUEST; - - sigbuf.writeUInt32BE(userLen, ++p, true); - sigbuf.write(username, p += 4, userLen, 'utf8'); - - sigbuf.writeUInt32BE(14, p += userLen, true); - sigbuf.write('ssh-connection', p += 4, 14, 'ascii'); - - sigbuf.writeUInt32BE(9, p += 14, true); - sigbuf.write('publickey', p += 4, 9, 'ascii'); - - sigbuf[p += 9] = 1; - - sigbuf.writeUInt32BE(algoLen, ++p, true); - sigbuf.write(pubKeyFullType, p += 4, algoLen, 'ascii'); - - sigbuf.writeUInt32BE(pubKeyLen, p += algoLen, true); - pubKey.copy(sigbuf, p += 4); - sigbuf.writeUInt32BE(4 + algoLen + 4 + sigLen, p += pubKeyLen, true); - sigbuf.writeUInt32BE(algoLen, p += 4, true); - sigbuf.write(pubKeyFullType, p += 4, algoLen, 'ascii'); - sigbuf.writeUInt32BE(sigLen, p += algoLen, true); - signature.copy(sigbuf, p += 4); - - // Servers shouldn't send packet type 60 in response to signed publickey - // attempts, but if they do, interpret as type 60. - self._state.authsQueue.push('publickey'); - self.debug('DEBUG: Outgoing: Writing USERAUTH_REQUEST (publickey)'); - return send(self, sigbuf); - }); - return true; -}; -SSH2Stream.prototype.authHostbased = function(username, pubKey, hostname, - userlocal, cbSign) { - // TODO: Make DRY by sharing similar code with authPK() - - if (this.server) - throw new Error('Client-only method called in server mode'); - - var self = this; - var outstate = this._state.outgoing; - var pubKeyFullType; - - if (pubKey.public) { - pubKeyFullType = pubKey.fulltype; - pubKey = pubKey.public; - } else { - pubKeyFullType = pubKey.toString('ascii', - 4, - 4 + pubKey.readUInt32BE(0, true)); - } - - var userLen = Buffer.byteLength(username); - var algoLen = Buffer.byteLength(pubKeyFullType); - var pubKeyLen = pubKey.length; - var sesLen = outstate.sessionId.length; - var hostnameLen = Buffer.byteLength(hostname); - var userlocalLen = Buffer.byteLength(userlocal); - var p = 0; - var buf = new Buffer(4 + sesLen - + 1 - + 4 + userLen - + 4 + 14 // "ssh-connection" - + 4 + 9 // "hostbased" - + 4 + algoLen - + 4 + pubKeyLen - + 4 + hostnameLen - + 4 + userlocalLen - ); - - buf.writeUInt32BE(sesLen, p, true); - outstate.sessionId.copy(buf, p += 4); - - buf[p += sesLen] = MESSAGE.USERAUTH_REQUEST; - - buf.writeUInt32BE(userLen, ++p, true); - buf.write(username, p += 4, userLen, 'utf8'); - - buf.writeUInt32BE(14, p += userLen, true); - buf.write('ssh-connection', p += 4, 14, 'ascii'); - - buf.writeUInt32BE(9, p += 14, true); - buf.write('hostbased', p += 4, 9, 'ascii'); - - buf.writeUInt32BE(algoLen, p += 9, true); - buf.write(pubKeyFullType, p += 4, algoLen, 'ascii'); - - buf.writeUInt32BE(pubKeyLen, p += algoLen, true); - pubKey.copy(buf, p += 4); - - buf.writeUInt32BE(hostnameLen, p += pubKeyLen, true); - buf.write(hostname, p += 4, hostnameLen, 'ascii'); - - buf.writeUInt32BE(userlocalLen, p += hostnameLen, true); - buf.write(userlocal, p += 4, userlocalLen, 'utf8'); - - cbSign(buf, function(signature) { - if (pubKeyFullType === 'ssh-dss') { - signature = DSASigBERToBare(signature); - } else if (pubKeyFullType !== 'ssh-rsa') { - // ECDSA - signature = ECDSASigASN1ToSSH(signature); - } - var sigLen = signature.length; - var sigbuf = new Buffer((buf.length - sesLen) + sigLen); - - buf.copy(sigbuf, 0, 4 + sesLen); - sigbuf.writeUInt32BE(sigLen, sigbuf.length - sigLen - 4, true); - signature.copy(sigbuf, sigbuf.length - sigLen); - - self._state.authsQueue.push('hostbased'); - self.debug('DEBUG: Outgoing: Writing USERAUTH_REQUEST (hostbased)'); - return send(self, sigbuf); - }); - return true; -}; -SSH2Stream.prototype.authKeyboard = function(username) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var userLen = Buffer.byteLength(username); - var p = 0; - var buf = new Buffer(1 - + 4 + userLen - + 4 + 14 // "ssh-connection" - + 4 + 20 // "keyboard-interactive" - + 4 // no language set - + 4 // no submethods - ); - - buf[p] = MESSAGE.USERAUTH_REQUEST; - - buf.writeUInt32BE(userLen, ++p, true); - buf.write(username, p += 4, userLen, 'utf8'); - - buf.writeUInt32BE(14, p += userLen, true); - buf.write('ssh-connection', p += 4, 14, 'ascii'); - - buf.writeUInt32BE(20, p += 14, true); - buf.write('keyboard-interactive', p += 4, 20, 'ascii'); - - buf.writeUInt32BE(0, p += 20, true); - - buf.writeUInt32BE(0, p += 4, true); - - this._state.authsQueue.push('keyboard-interactive'); - this.debug('DEBUG: Outgoing: Writing USERAUTH_REQUEST (keyboard-interactive)'); - return send(this, buf); -}; -SSH2Stream.prototype.authNone = function(username) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var userLen = Buffer.byteLength(username); - var p = 0; - var buf = new Buffer(1 - + 4 + userLen - + 4 + 14 // "ssh-connection" - + 4 + 4 // "none" - ); - - buf[p] = MESSAGE.USERAUTH_REQUEST; - - buf.writeUInt32BE(userLen, ++p, true); - buf.write(username, p += 4, userLen, 'utf8'); - - buf.writeUInt32BE(14, p += userLen, true); - buf.write('ssh-connection', p += 4, 14, 'ascii'); - - buf.writeUInt32BE(4, p += 14, true); - buf.write('none', p += 4, 4, 'ascii'); - - this._state.authsQueue.push('none'); - this.debug('DEBUG: Outgoing: Writing USERAUTH_REQUEST (none)'); - return send(this, buf); -}; -SSH2Stream.prototype.authInfoRes = function(responses) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - var responsesLen = 0; - var p = 0; - var resLen; - var len; - var i; - - if (responses) { - for (i = 0, len = responses.length; i < len; ++i) - responsesLen += 4 + Buffer.byteLength(responses[i]); - } - var buf = new Buffer(1 + 4 + responsesLen); - - buf[p++] = MESSAGE.USERAUTH_INFO_RESPONSE; - - buf.writeUInt32BE(responses ? responses.length : 0, p, true); - if (responses) { - p += 4; - for (i = 0, len = responses.length; i < len; ++i) { - resLen = Buffer.byteLength(responses[i]); - buf.writeUInt32BE(resLen, p, true); - p += 4; - if (resLen) { - buf.write(responses[i], p, resLen, 'utf8'); - p += resLen; - } - } - } - - this.debug('DEBUG: Outgoing: Writing USERAUTH_INFO_RESPONSE'); - return send(this, buf); -}; - -// Server-specific methods -// Global -SSH2Stream.prototype.serviceAccept = function(svcName) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var svcNameLen = svcName.length; - var buf = new Buffer(1 + 4 + svcNameLen); - - buf[0] = MESSAGE.SERVICE_ACCEPT; - - buf.writeUInt32BE(svcNameLen, 1, true); - buf.write(svcName, 5, svcNameLen, 'ascii'); - - this.debug('DEBUG: Outgoing: Writing SERVICE_ACCEPT (' + svcName + ')'); - send(this, buf); - - if (this.server && this.banner && svcName === 'ssh-userauth') { - /* - byte SSH_MSG_USERAUTH_BANNER - string message in ISO-10646 UTF-8 encoding - string language tag - */ - var bannerLen = Buffer.byteLength(this.banner); - var packetLen = 1 + 4 + bannerLen + 4; - if (packetLen > BUFFER_MAX_LEN) { - bannerLen -= 1 + 4 + 4; - packetLen -= 1 + 4 + 4; - } - var packet = new Buffer(packetLen); - packet[0] = MESSAGE.USERAUTH_BANNER; - packet.writeUInt32BE(bannerLen, 1, true); - packet.write(this.banner, 5, bannerLen, 'utf8'); - packet.fill(0, packetLen - 4); // Empty language tag - this.debug('DEBUG: Outgoing: Writing USERAUTH_BANNER'); - send(this, packet); - this.banner = undefined; // Prevent banner from being displayed again - } -}; -// 'ssh-connection' service-specific -SSH2Stream.prototype.forwardedTcpip = function(chan, initWindow, maxPacket, - cfg) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var boundAddrLen = Buffer.byteLength(cfg.boundAddr); - var remoteAddrLen = Buffer.byteLength(cfg.remoteAddr); - var p = 36 + boundAddrLen; - var buf = new Buffer(1 + 4 + 15 + 4 + 4 + 4 + 4 + boundAddrLen + 4 + 4 - + remoteAddrLen + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN; - - buf.writeUInt32BE(15, 1, true); - buf.write('forwarded-tcpip', 5, 15, 'ascii'); - - buf.writeUInt32BE(chan, 20, true); - - buf.writeUInt32BE(initWindow, 24, true); - - buf.writeUInt32BE(maxPacket, 28, true); - - buf.writeUInt32BE(boundAddrLen, 32, true); - buf.write(cfg.boundAddr, 36, boundAddrLen, 'ascii'); - - buf.writeUInt32BE(cfg.boundPort, p, true); - - buf.writeUInt32BE(remoteAddrLen, p += 4, true); - buf.write(cfg.remoteAddr, p += 4, remoteAddrLen, 'ascii'); - - buf.writeUInt32BE(cfg.remotePort, p += remoteAddrLen, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN (' - + chan - + ', forwarded-tcpip)'); - return send(this, buf); -}; -SSH2Stream.prototype.x11 = function(chan, initWindow, maxPacket, cfg) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var addrLen = Buffer.byteLength(cfg.originAddr); - var p = 24 + addrLen; - var buf = new Buffer(1 + 4 + 3 + 4 + 4 + 4 + 4 + addrLen + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN; - - buf.writeUInt32BE(3, 1, true); - buf.write('x11', 5, 3, 'ascii'); - - buf.writeUInt32BE(chan, 8, true); - - buf.writeUInt32BE(initWindow, 12, true); - - buf.writeUInt32BE(maxPacket, 16, true); - - buf.writeUInt32BE(addrLen, 20, true); - buf.write(cfg.originAddr, 24, addrLen, 'ascii'); - - buf.writeUInt32BE(cfg.originPort, p, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN (' - + chan - + ', x11)'); - return send(this, buf); -}; -SSH2Stream.prototype.openssh_forwardedStreamLocal = function(chan, initWindow, - maxPacket, cfg) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var pathlen = Buffer.byteLength(cfg.socketPath); - var buf = new Buffer(1 + 4 + 33 + 4 + 4 + 4 + 4 + pathlen + 4); - - buf[0] = MESSAGE.CHANNEL_OPEN; - - buf.writeUInt32BE(33, 1, true); - buf.write('forwarded-streamlocal@openssh.com', 5, 33, 'ascii'); - - buf.writeUInt32BE(chan, 38, true); - - buf.writeUInt32BE(initWindow, 42, true); - - buf.writeUInt32BE(maxPacket, 46, true); - - buf.writeUInt32BE(pathlen, 50, true); - buf.write(cfg.socketPath, 54, pathlen, 'utf8'); - - buf.writeUInt32BE(0, 54 + pathlen, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_OPEN (' - + chan - + ', forwarded-streamlocal@openssh.com)'); - return send(this, buf); -}; -SSH2Stream.prototype.exitStatus = function(chan, status) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - // Does not consume window space - var buf = new Buffer(1 + 4 + 4 + 11 + 1 + 4); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(11, 5, true); - buf.write('exit-status', 9, 11, 'ascii'); - - buf[20] = 0; - - buf.writeUInt32BE(status, 21, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', exit-status)'); - return send(this, buf); -}; -SSH2Stream.prototype.exitSignal = function(chan, name, coreDumped, msg) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - // Does not consume window space - var nameLen = Buffer.byteLength(name); - var msgLen = (msg ? Buffer.byteLength(msg) : 0); - var p = 25 + nameLen; - var buf = new Buffer(1 + 4 + 4 + 11 + 1 + 4 + nameLen + 1 + 4 + msgLen + 4); - - buf[0] = MESSAGE.CHANNEL_REQUEST; - - buf.writeUInt32BE(chan, 1, true); - - buf.writeUInt32BE(11, 5, true); - buf.write('exit-signal', 9, 11, 'ascii'); - - buf[20] = 0; - - buf.writeUInt32BE(nameLen, 21, true); - buf.write(name, 25, nameLen, 'utf8'); - - buf[p++] = (coreDumped ? 1 : 0); - - buf.writeUInt32BE(msgLen, p, true); - p += 4; - if (msgLen) { - buf.write(msg, p, msgLen, 'utf8'); - p += msgLen; - } - - buf.writeUInt32BE(0, p, true); - - this.debug('DEBUG: Outgoing: Writing CHANNEL_REQUEST (' - + chan - + ', exit-signal)'); - return send(this, buf); -}; -// 'ssh-userauth' service-specific -SSH2Stream.prototype.authFailure = function(authMethods, isPartial) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var authsQueue = this._state.authsQueue; - if (!authsQueue.length) - throw new Error('No auth in progress'); - - var methods; - - if (typeof authMethods === 'boolean') { - isPartial = authMethods; - authMethods = undefined; - } - - if (authMethods) { - methods = []; - for (var i = 0, len = authMethods.length; i < len; ++i) { - if (authMethods[i].toLowerCase() === 'none') - continue; - methods.push(authMethods[i]); - } - methods = methods.join(','); - } else - methods = ''; - - var methodsLen = methods.length; - var buf = new Buffer(1 + 4 + methodsLen + 1); - - buf[0] = MESSAGE.USERAUTH_FAILURE; - - buf.writeUInt32BE(methodsLen, 1, true); - buf.write(methods, 5, methodsLen, 'ascii'); - - buf[5 + methodsLen] = (isPartial === true ? 1 : 0); - - this._state.authsQueue.shift(); - this.debug('DEBUG: Outgoing: Writing USERAUTH_FAILURE'); - return send(this, buf); -}; -SSH2Stream.prototype.authSuccess = function() { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var authsQueue = this._state.authsQueue; - if (!authsQueue.length) - throw new Error('No auth in progress'); - - this._state.authsQueue.shift(); - this.debug('DEBUG: Outgoing: Writing USERAUTH_SUCCESS'); - return send(this, USERAUTH_SUCCESS_PACKET); -}; -SSH2Stream.prototype.authPKOK = function(keyAlgo, key) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var authsQueue = this._state.authsQueue; - if (!authsQueue.length || authsQueue[0] !== 'publickey') - throw new Error('"publickey" auth not in progress'); - - var keyAlgoLen = keyAlgo.length; - var keyLen = key.length; - var buf = new Buffer(1 + 4 + keyAlgoLen + 4 + keyLen); - - buf[0] = MESSAGE.USERAUTH_PK_OK; - - buf.writeUInt32BE(keyAlgoLen, 1, true); - buf.write(keyAlgo, 5, keyAlgoLen, 'ascii'); - - buf.writeUInt32BE(keyLen, 5 + keyAlgoLen, true); - key.copy(buf, 5 + keyAlgoLen + 4); - - this._state.authsQueue.shift(); - this.debug('DEBUG: Outgoing: Writing USERAUTH_PK_OK'); - return send(this, buf); -}; -SSH2Stream.prototype.authPasswdChg = function(prompt, lang) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var promptLen = Buffer.byteLength(prompt); - var langLen = lang ? lang.length : 0; - var p = 0; - var buf = new Buffer(1 + 4 + promptLen + 4 + langLen); - - buf[p] = MESSAGE.USERAUTH_PASSWD_CHANGEREQ; - - buf.writeUInt32BE(promptLen, ++p, true); - buf.write(prompt, p += 4, promptLen, 'utf8'); - - buf.writeUInt32BE(langLen, p += promptLen, true); - if (langLen) - buf.write(lang, p += 4, langLen, 'ascii'); - - this.debug('DEBUG: Outgoing: Writing USERAUTH_PASSWD_CHANGEREQ'); - return send(this, buf); -}; -SSH2Stream.prototype.authInfoReq = function(name, instructions, prompts) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - var promptsLen = 0; - var nameLen = name ? Buffer.byteLength(name) : 0; - var instrLen = instructions ? Buffer.byteLength(instructions) : 0; - var p = 0; - var promptLen; - var prompt; - var len; - var i; - - for (i = 0, len = prompts.length; i < len; ++i) - promptsLen += 4 + Buffer.byteLength(prompts[i].prompt) + 1; - var buf = new Buffer(1 + 4 + nameLen + 4 + instrLen + 4 + 4 + promptsLen); - - buf[p++] = MESSAGE.USERAUTH_INFO_REQUEST; - - buf.writeUInt32BE(nameLen, p, true); - p += 4; - if (name) { - buf.write(name, p, nameLen, 'utf8'); - p += nameLen; - } - - buf.writeUInt32BE(instrLen, p, true); - p += 4; - if (instructions) { - buf.write(instructions, p, instrLen, 'utf8'); - p += instrLen; - } - - buf.writeUInt32BE(0, p, true); - p += 4; - - buf.writeUInt32BE(prompts.length, p, true); - p += 4; - for (i = 0, len = prompts.length; i < len; ++i) { - prompt = prompts[i]; - promptLen = Buffer.byteLength(prompt.prompt); - buf.writeUInt32BE(promptLen, p, true); - p += 4; - if (promptLen) { - buf.write(prompt.prompt, p, promptLen, 'utf8'); - p += promptLen; - } - buf[p++] = (prompt.echo ? 1 : 0); - } - - this.debug('DEBUG: Outgoing: Writing USERAUTH_INFO_REQUEST'); - return send(this, buf); -}; - -// Shared incoming/parser functions -function onDISCONNECT(self, reason, code, desc, lang) { // Client/Server - if (code !== DISCONNECT_REASON.BY_APPLICATION) { - var err = new Error(desc || reason); - err.code = code; - self.emit('error', err); - } - self.reset(); -} - -function onKEXINIT(self, init, firstFollows) { // Client/Server - var state = self._state; - var outstate = state.outgoing; - - if (outstate.status === OUT_READY) { - self.debug('DEBUG: Received re-key request'); - outstate.status = OUT_REKEYING; - outstate.kexinit = undefined; - KEXINIT(self, check); - } else - check(); - - function check() { - if (check_KEXINIT(self, init, firstFollows) === true) { - var isGEX = RE_GEX.test(state.kexdh); - if (!self.server) { - if (isGEX) - KEXDH_GEX_REQ(self); - else - KEXDH_INIT(self); - } else { - if (isGEX) - state.incoming.expectedPacket = 'KEXDH_GEX_REQ'; - else - state.incoming.expectedPacket = 'KEXDH_INIT'; - } - } - } -} - -function check_KEXINIT(self, init, firstFollows) { - var state = self._state; - var instate = state.incoming; - var outstate = state.outgoing; - var debug = self.debug; - var serverList; - var clientList; - var val; - var len; - var i; - - debug('DEBUG: Comparing KEXINITs ...'); - - var algos = self.config.algorithms; - - var kexList = algos.kex; - if (self.remoteBugs & BUGS.BAD_DHGEX) { - var copied = false; - for (var j = kexList.length - 1; j >= 0; --j) { - if (kexList[j].indexOf('group-exchange') !== -1) { - if (!copied) { - kexList = kexList.slice(); - copied = true; - } - kexList.splice(j, 1); - } - } - } - - debug('DEBUG: (local) KEX algorithms: ' + kexList); - debug('DEBUG: (remote) KEX algorithms: ' + init.algorithms.kex); - if (self.server) { - serverList = kexList; - clientList = init.algorithms.kex; - } else { - serverList = init.algorithms.kex; - clientList = kexList; - } - // Check for agreeable key exchange algorithm - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching key exchange algorithm'); - var err = new Error('Handshake failed: no matching key exchange algorithm'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - var kex_algorithm = clientList[i]; - debug('DEBUG: KEX algorithm: ' + kex_algorithm); - if (firstFollows - && (!init.algorithms.kex.length - || kex_algorithm !== init.algorithms.kex[0])) { - // Ignore next incoming packet, it was a wrong first guess at KEX algorithm - instate.ignoreNext = true; - } - - debug('DEBUG: (local) Host key formats: ' + algos.serverHostKey); - debug('DEBUG: (remote) Host key formats: ' + init.algorithms.srvHostKey); - if (self.server) { - serverList = algos.serverHostKey; - clientList = init.algorithms.srvHostKey; - } else { - serverList = init.algorithms.srvHostKey; - clientList = algos.serverHostKey; - } - // Check for agreeable server host key format - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching host key format'); - var err = new Error('Handshake failed: no matching host key format'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - state.hostkeyFormat = clientList[i]; - debug('DEBUG: Host key format: ' + state.hostkeyFormat); - - debug('DEBUG: (local) Client->Server ciphers: ' + algos.cipher); - debug('DEBUG: (remote) Client->Server ciphers: ' - + init.algorithms.cs.encrypt); - if (self.server) { - serverList = algos.cipher; - clientList = init.algorithms.cs.encrypt; - } else { - serverList = init.algorithms.cs.encrypt; - clientList = algos.cipher; - } - // Check for agreeable client->server cipher - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching Client->Server cipher'); - var err = new Error('Handshake failed: no matching client->server cipher'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (self.server) { - val = instate.decrypt.type = clientList[i]; - instate.decrypt.isGCM = RE_GCM.test(val); - } else { - val = outstate.encrypt.type = clientList[i]; - outstate.encrypt.isGCM = RE_GCM.test(val); - } - debug('DEBUG: Client->Server Cipher: ' + val); - - debug('DEBUG: (local) Server->Client ciphers: ' + algos.cipher); - debug('DEBUG: (remote) Server->Client ciphers: ' - + (init.algorithms.sc.encrypt)); - if (self.server) { - serverList = algos.cipher; - clientList = init.algorithms.sc.encrypt; - } else { - serverList = init.algorithms.sc.encrypt; - clientList = algos.cipher; - } - // Check for agreeable server->client cipher - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching Server->Client cipher'); - var err = new Error('Handshake failed: no matching server->client cipher'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (self.server) { - val = outstate.encrypt.type = clientList[i]; - outstate.encrypt.isGCM = RE_GCM.test(val); - } else { - val = instate.decrypt.type = clientList[i]; - instate.decrypt.isGCM = RE_GCM.test(val); - } - debug('DEBUG: Server->Client Cipher: ' + val); - - debug('DEBUG: (local) Client->Server HMAC algorithms: ' + algos.hmac); - debug('DEBUG: (remote) Client->Server HMAC algorithms: ' - + init.algorithms.cs.mac); - if (self.server) { - serverList = algos.hmac; - clientList = init.algorithms.cs.mac; - } else { - serverList = init.algorithms.cs.mac; - clientList = algos.hmac; - } - // Check for agreeable client->server hmac algorithm - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching Client->Server HMAC algorithm'); - var err = new Error('Handshake failed: no matching client->server HMAC'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (self.server) - val = instate.hmac.type = clientList[i]; - else - val = outstate.hmac.type = clientList[i]; - debug('DEBUG: Client->Server HMAC algorithm: ' + val); - - debug('DEBUG: (local) Server->Client HMAC algorithms: ' + algos.hmac); - debug('DEBUG: (remote) Server->Client HMAC algorithms: ' - + init.algorithms.sc.mac); - if (self.server) { - serverList = algos.hmac; - clientList = init.algorithms.sc.mac; - } else { - serverList = init.algorithms.sc.mac; - clientList = algos.hmac; - } - // Check for agreeable server->client hmac algorithm - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching Server->Client HMAC algorithm'); - var err = new Error('Handshake failed: no matching server->client HMAC'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (self.server) - val = outstate.hmac.type = clientList[i]; - else - val = instate.hmac.type = clientList[i]; - debug('DEBUG: Server->Client HMAC algorithm: ' + val); - - debug('DEBUG: (local) Client->Server compression algorithms: ' - + algos.compress); - debug('DEBUG: (remote) Client->Server compression algorithms: ' - + init.algorithms.cs.compress); - if (self.server) { - serverList = algos.compress; - clientList = init.algorithms.cs.compress; - } else { - serverList = init.algorithms.cs.compress; - clientList = algos.compress; - } - // Check for agreeable client->server compression algorithm - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching Client->Server compression algorithm'); - var err = new Error('Handshake failed: no matching client->server ' - + 'compression algorithm'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (self.server) - val = instate.decompress.type = clientList[i]; - else - val = outstate.compress.type = clientList[i]; - debug('DEBUG: Client->Server compression algorithm: ' + val); - - debug('DEBUG: (local) Server->Client compression algorithms: ' - + algos.compress); - debug('DEBUG: (remote) Server->Client compression algorithms: ' - + init.algorithms.sc.compress); - if (self.server) { - serverList = algos.compress; - clientList = init.algorithms.sc.compress; - } else { - serverList = init.algorithms.sc.compress; - clientList = algos.compress; - } - // Check for agreeable server->client compression algorithm - for (i = 0, len = clientList.length; - i < len && serverList.indexOf(clientList[i]) === -1; - ++i); - if (i === len) { - // No suitable match found! - debug('DEBUG: No matching Server->Client compression algorithm'); - var err = new Error('Handshake failed: no matching server->client ' - + 'compression algorithm'); - err.level = 'handshake'; - self.emit('error', err); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (self.server) - val = outstate.compress.type = clientList[i]; - else - val = instate.decompress.type = clientList[i]; - debug('DEBUG: Server->Client compression algorithm: ' + val); - - switch (kex_algorithm) { - case 'diffie-hellman-group1-sha1': - state.kexdh = 'group'; - state.kex = crypto.getDiffieHellman('modp2'); - break; - case 'diffie-hellman-group14-sha1': - state.kexdh = 'group'; - state.kex = crypto.getDiffieHellman('modp14'); - break; - case 'ecdh-sha2-nistp256': - state.kexdh = 'ec-sha256'; - state.kex = crypto.createECDH(SSH_TO_OPENSSL[kex_algorithm]); - break; - case 'ecdh-sha2-nistp384': - state.kexdh = 'ec-sha384'; - state.kex = crypto.createECDH(SSH_TO_OPENSSL[kex_algorithm]); - break; - case 'ecdh-sha2-nistp521': - state.kexdh = 'ec-sha512'; - state.kex = crypto.createECDH(SSH_TO_OPENSSL[kex_algorithm]); - break; - default: - if (kex_algorithm === 'diffie-hellman-group-exchange-sha1') - state.kexdh = 'gex-sha1'; - else if (kex_algorithm === 'diffie-hellman-group-exchange-sha256') - state.kexdh = 'gex-sha256'; - // Reset kex object if DH group exchange is selected on re-key and DH - // group exchange was used before the re-key. This ensures that we send - // the right DH packet after the KEXINIT exchange - state.kex = undefined; - } - - if (state.kex) { - outstate.pubkey = state.kex.generateKeys(); - var idx = 0; - len = outstate.pubkey.length; - while (outstate.pubkey[idx] === 0x00) { - ++idx; - --len; - } - if (outstate.pubkey[idx] & 0x80) { - var key = new Buffer(len + 1); - key[0] = 0; - outstate.pubkey.copy(key, 1, idx); - outstate.pubkey = key; - } - } - - return true; -} - -function onKEXDH_GEX_GROUP(self, prime, gen) { - var state = self._state; - var outstate = state.outgoing; - - state.kex = crypto.createDiffieHellman(prime, gen); - outstate.pubkey = state.kex.generateKeys(); - var idx = 0; - var len = outstate.pubkey.length; - while (outstate.pubkey[idx] === 0x00) { - ++idx; - --len; - } - if (outstate.pubkey[idx] & 0x80) { - var key = new Buffer(len + 1); - key[0] = 0; - outstate.pubkey.copy(key, 1, idx); - outstate.pubkey = key; - } - KEXDH_INIT(self); -} - -function onKEXDH_INIT(self, e) { // Server - KEXDH_REPLY(self, e); -} - -function onKEXDH_REPLY(self, info, verifiedHost) { // Client - var state = self._state; - var instate = state.incoming; - var outstate = state.outgoing; - var debug = self.debug; - var len; - var i; - - if (verifiedHost === undefined) { - instate.expectedPacket = 'NEWKEYS'; - outstate.sentNEWKEYS = false; - - debug('DEBUG: Checking host key format'); - // Ensure all host key formats agree - var hostkey_format = readString(info.hostkey, 0, 'ascii', self); - if (hostkey_format === false) - return false; - if (info.hostkey_format !== state.hostkeyFormat - || info.hostkey_format !== hostkey_format) { - // Expected and actual server host key format do not match! - debug('DEBUG: Host key format mismatch'); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - self.reset(); - var err = new Error('Handshake failed: host key format mismatch'); - err.level = 'handshake'; - self.emit('error', err); - return false; - } - - debug('DEBUG: Checking signature format'); - // Ensure signature formats agree - var sig_format = readString(info.sig, 0, 'ascii', self); - if (sig_format === false) - return false; - if (info.sig_format !== sig_format) { - debug('DEBUG: Signature format mismatch'); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - self.reset(); - var err = new Error('Handshake failed: signature format mismatch'); - err.level = 'handshake'; - self.emit('error', err); - return false; - } - } - - // Verify the host fingerprint first if needed - if (outstate.status === OUT_INIT) { - if (verifiedHost === undefined) { - debug('DEBUG: Verifying host fingerprint'); - var sync = true; - var emitted = self.emit('fingerprint', info.hostkey, function(permitted) { - // Prevent multiple calls to this callback - if (verifiedHost !== undefined) - return; - verifiedHost = !!permitted; - if (!sync) { - // Continue execution by re-entry - onKEXDH_REPLY(self, info, verifiedHost); - } - }); - sync = false; - // Support async calling of verification callback - if (emitted && verifiedHost === undefined) - return; - } - if (verifiedHost === undefined) - debug('DEBUG: Host accepted by default (no verification)'); - else if (verifiedHost === true) - debug('DEBUG: Host accepted (verified)'); - else { - debug('DEBUG: Host denied via fingerprint verification'); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - self.reset(); - var err = new Error('Handshake failed: ' - + 'host fingerprint verification failed'); - err.level = 'handshake'; - self.emit('error', err); - return false; - } - } - - var slicepos = -1; - for (i = 0, len = info.pubkey.length; i < len; ++i) { - if (info.pubkey[i] === 0) - ++slicepos; - else - break; - } - if (slicepos > -1) - info.pubkey = info.pubkey.slice(slicepos + 1); - info.secret = tryComputeSecret(state.kex, info.pubkey); - if (info.secret instanceof Error) { - info.secret.message = 'Error while computing DH secret (' - + state.kexdh + '): ' - + info.secret.message; - info.secret.level = 'handshake'; - self.emit('error', info.secret); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - var hashAlgo; - if (state.kexdh === 'group') - hashAlgo = 'sha1'; - else - hashAlgo = RE_KEX_HASH.exec(state.kexdh)[1]; - var hash = crypto.createHash(hashAlgo); - - var len_ident = Buffer.byteLength(self.config.ident); - var len_sident = Buffer.byteLength(instate.identRaw); - var len_init = outstate.kexinit.length; - var len_sinit = instate.kexinit.length; - var len_hostkey = info.hostkey.length; - var len_pubkey = outstate.pubkey.length; - var len_spubkey = info.pubkey.length; - var len_secret = info.secret.length; - - var idx_pubkey = 0; - var idx_spubkey = 0; - var idx_secret = 0; - - while (outstate.pubkey[idx_pubkey] === 0x00) { - ++idx_pubkey; - --len_pubkey; - } - while (info.pubkey[idx_spubkey] === 0x00) { - ++idx_spubkey; - --len_spubkey; - } - while (info.secret[idx_secret] === 0x00) { - ++idx_secret; - --len_secret; - } - if (outstate.pubkey[idx_pubkey] & 0x80) - ++len_pubkey; - if (info.pubkey[idx_spubkey] & 0x80) - ++len_spubkey; - if (info.secret[idx_secret] & 0x80) - ++len_secret; - - var exchangeBufLen = len_ident - + len_sident - + len_init - + len_sinit - + len_hostkey - + len_pubkey - + len_spubkey - + len_secret - + (4 * 8); // Length fields for above values - - // Group exchange-related - var isGEX = RE_GEX.test(state.kexdh); - var len_gex_prime = 0; - var len_gex_gen = 0; - var idx_gex_prime = 0; - var idx_gex_gen = 0; - var gex_prime; - var gex_gen; - if (isGEX) { - gex_prime = state.kex.getPrime(); - gex_gen = state.kex.getGenerator(); - len_gex_prime = gex_prime.length; - len_gex_gen = gex_gen.length; - while (gex_prime[idx_gex_prime] === 0x00) { - ++idx_gex_prime; - --len_gex_prime; - } - while (gex_gen[idx_gex_gen] === 0x00) { - ++idx_gex_gen; - --len_gex_gen; - } - if (gex_prime[idx_gex_prime] & 0x80) - ++len_gex_prime; - if (gex_gen[idx_gex_gen] & 0x80) - ++len_gex_gen; - exchangeBufLen += (4 * 3); // min, n, max values - exchangeBufLen += (4 * 2); // prime, generator length fields - exchangeBufLen += len_gex_prime; - exchangeBufLen += len_gex_gen; - } - - - var bp = 0; - var exchangeBuf = new Buffer(exchangeBufLen); - - exchangeBuf.writeUInt32BE(len_ident, bp, true); - bp += 4; - exchangeBuf.write(self.config.ident, bp, 'utf8'); // V_C - bp += len_ident; - - exchangeBuf.writeUInt32BE(len_sident, bp, true); - bp += 4; - exchangeBuf.write(instate.identRaw, bp, 'utf8'); // V_S - bp += len_sident; - - exchangeBuf.writeUInt32BE(len_init, bp, true); - bp += 4; - outstate.kexinit.copy(exchangeBuf, bp); // I_C - bp += len_init; - outstate.kexinit = undefined; - - exchangeBuf.writeUInt32BE(len_sinit, bp, true); - bp += 4; - instate.kexinit.copy(exchangeBuf, bp); // I_S - bp += len_sinit; - instate.kexinit = undefined; - - exchangeBuf.writeUInt32BE(len_hostkey, bp, true); - bp += 4; - info.hostkey.copy(exchangeBuf, bp); // K_S - bp += len_hostkey; - - if (isGEX) { - KEXDH_GEX_REQ_PACKET.slice(1).copy(exchangeBuf, bp); // min, n, max - bp += (4 * 3); // Skip over bytes just copied - - exchangeBuf.writeUInt32BE(len_gex_prime, bp, true); - bp += 4; - if (gex_prime[idx_gex_prime] & 0x80) - exchangeBuf[bp++] = 0; - gex_prime.copy(exchangeBuf, bp, idx_gex_prime); // p - bp += len_gex_prime - (gex_prime[idx_gex_prime] & 0x80 ? 1 : 0); - - exchangeBuf.writeUInt32BE(len_gex_gen, bp, true); - bp += 4; - if (gex_gen[idx_gex_gen] & 0x80) - exchangeBuf[bp++] = 0; - gex_gen.copy(exchangeBuf, bp, idx_gex_gen); // g - bp += len_gex_gen - (gex_gen[idx_gex_gen] & 0x80 ? 1 : 0); - } - - exchangeBuf.writeUInt32BE(len_pubkey, bp, true); - bp += 4; - if (outstate.pubkey[idx_pubkey] & 0x80) - exchangeBuf[bp++] = 0; - outstate.pubkey.copy(exchangeBuf, bp, idx_pubkey); // e - bp += len_pubkey - (outstate.pubkey[idx_pubkey] & 0x80 ? 1 : 0); - - exchangeBuf.writeUInt32BE(len_spubkey, bp, true); - bp += 4; - if (info.pubkey[idx_spubkey] & 0x80) - exchangeBuf[bp++] = 0; - info.pubkey.copy(exchangeBuf, bp, idx_spubkey); // f - bp += len_spubkey - (info.pubkey[idx_spubkey] & 0x80 ? 1 : 0); - - exchangeBuf.writeUInt32BE(len_secret, bp, true); - bp += 4; - if (info.secret[idx_secret] & 0x80) - exchangeBuf[bp++] = 0; - info.secret.copy(exchangeBuf, bp, idx_secret); // K - - outstate.exchangeHash = hash.update(exchangeBuf).digest(); // H - - var rawsig = readString(info.sig, info.sig._pos, self); // s - if (rawsig === false) - return false; - - var keyAlgo; - switch (info.sig_format) { - case 'ssh-rsa': - keyAlgo = 'RSA-SHA1'; - break; - case 'ssh-dss': - keyAlgo = 'DSA-SHA1'; - break; - case 'ecdsa-sha2-nistp256': - keyAlgo = 'sha256'; - break; - case 'ecdsa-sha2-nistp384': - keyAlgo = 'sha384'; - break; - case 'ecdsa-sha2-nistp521': - keyAlgo = 'sha512'; - break; - default: - debug('DEBUG: Signature format unsupported: ' + info.sig_format); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - self.reset(); - var err = new Error('Handshake failed: signature format unsupported: ' - + info.sig_format); - err.level = 'handshake'; - self.emit('error', err); - return false; - } - var verifier = crypto.createVerify(keyAlgo); - verifier.update(outstate.exchangeHash); - - var asn1KeyBuf; - if (keyAlgo === 'RSA-SHA1') { - asn1KeyBuf = RSAKeySSHToASN1(info.hostkey, self); - } else if (keyAlgo === 'DSA-SHA1') { - asn1KeyBuf = DSAKeySSHToASN1(info.hostkey, self); - rawsig = DSASigBareToBER(rawsig); - } else { - // ECDSA - asn1KeyBuf = ECDSAKeySSHToASN1(info.hostkey, self); - rawsig = ECDSASigSSHToASN1(rawsig, self); - } - - if (!asn1KeyBuf || !rawsig) - return false; - - debug('DEBUG: Verifying signature'); - - var b64key = asn1KeyBuf.toString('base64').replace(/(.{64})/g, '$1\n'); - var fullkey = '-----BEGIN PUBLIC KEY-----\n' - + b64key - + (b64key[b64key.length - 1] === '\n' ? '' : '\n') - + '-----END PUBLIC KEY-----'; - - var verified = verifier.verify(fullkey, rawsig); - - if (!verified) { - debug('DEBUG: Signature verification failed'); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - self.reset(); - var err = new Error('Handshake failed: signature verification failed'); - err.level = 'handshake'; - self.emit('error', err); - return false; - } - - if (outstate.sessionId === undefined) - outstate.sessionId = outstate.exchangeHash; - outstate.kexsecret = info.secret; - - debug('DEBUG: Outgoing: Writing NEWKEYS'); - if (outstate.status === OUT_REKEYING) - send(self, NEWKEYS_PACKET, undefined, true); - else - send(self, NEWKEYS_PACKET); - outstate.sentNEWKEYS = true; - - if (verifiedHost !== undefined && instate.expectedPacket === undefined) { - // We received NEWKEYS while we were waiting for the fingerprint - // verification callback to be called. In this case we have to re-execute - // onNEWKEYS to finish the handshake. - onNEWKEYS(self); - } -} - -function onNEWKEYS(self) { // Client/Server - var state = self._state; - var outstate = state.outgoing; - var instate = state.incoming; - - instate.expectedPacket = undefined; - - if (!outstate.sentNEWKEYS) - return; - - var idx_secret = 0; - var len = outstate.kexsecret.length; - while (outstate.kexsecret[idx_secret] === 0x00) { - ++idx_secret; - --len; - } - - var blocklen = 8; - var keylen = 0; - var p = 0; - - var dhHashAlgo; - if (state.kexdh === 'group') - dhHashAlgo = 'sha1'; - else - dhHashAlgo = RE_KEX_HASH.exec(state.kexdh)[1]; - - var len_secret = (outstate.kexsecret[idx_secret] & 0x80 ? 1 : 0) + len; - var secret = new Buffer(4 + len_secret); - var iv; - var key; - - // Whenever the client sends a new authentication request, it is enqueued - // here. Once the request is resolved (success, fail, or PK_OK), - // dequeue. Whatever is at the front of the queue determines how we - // interpret packet type 60. - state.authsQueue = []; - - secret.writeUInt32BE(len_secret, p, true); - p += 4; - if (outstate.kexsecret[idx_secret] & 0x80) - secret[p++] = 0; - outstate.kexsecret.copy(secret, p, idx_secret); - outstate.kexsecret = undefined; - if (!isStreamCipher(outstate.encrypt.type)) { - iv = crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(!self.server ? 'A' : 'B', 'ascii') - .update(outstate.sessionId) - .digest(); - switch (outstate.encrypt.type) { - case 'aes128-gcm': - case 'aes256-gcm': - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - blocklen = 12; - break; - case 'aes256-cbc': - case 'aes192-cbc': - case 'aes128-cbc': - case 'aes256-ctr': - case 'aes192-ctr': - case 'aes128-ctr': - blocklen = 16; - } - outstate.encrypt.size = blocklen; - while (blocklen > iv.length) { - iv = Buffer.concat([iv, - crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(iv) - .digest()]); - } - iv = iv.slice(0, blocklen); - } else { - outstate.encrypt.size = blocklen; - iv = EMPTY_BUFFER; // Streaming ciphers don't use an IV upfront - } - switch (outstate.encrypt.type) { - case 'aes256-gcm': - case 'aes256-gcm@openssh.com': - case 'aes256-cbc': - case 'aes256-ctr': - case 'arcfour256': - keylen = 32; - break; - case '3des-cbc': - case '3des-ctr': - case 'aes192-cbc': - case 'aes192-ctr': - keylen = 24; - break; - case 'aes128-gcm': - case 'aes128-gcm@openssh.com': - case 'aes128-cbc': - case 'aes128-ctr': - case 'cast128-cbc': - case 'blowfish-cbc': - case 'arcfour': - case 'arcfour128': - keylen = 16; - break; - } - - key = crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(!self.server ? 'C' : 'D', 'ascii') - .update(outstate.sessionId) - .digest(); - while (keylen > key.length) { - key = Buffer.concat([key, - crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(key) - .digest()]); - } - key = key.slice(0, keylen); - - if (outstate.encrypt.isGCM) { - outstate.encrypt.size = 16; - outstate.encrypt.iv = iv; - outstate.encrypt.key = key; - outstate.encrypt.instance = true; - } else { - var cipherAlgo = SSH_TO_OPENSSL[outstate.encrypt.type]; - outstate.encrypt.instance = crypto.createCipheriv(cipherAlgo, key, iv); - outstate.encrypt.instance.setAutoPadding(false); - } - - // And now for decrypting ... - - blocklen = 8; - keylen = 0; - if (!isStreamCipher(instate.decrypt.type)) { - iv = crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(!self.server ? 'B' : 'A', 'ascii') - .update(outstate.sessionId) - .digest(); - switch (instate.decrypt.type) { - case 'aes128-gcm': - case 'aes256-gcm': - case 'aes128-gcm@openssh.com': - case 'aes256-gcm@openssh.com': - blocklen = 12; - break; - case 'aes256-cbc': - case 'aes192-cbc': - case 'aes128-cbc': - case 'aes256-ctr': - case 'aes192-ctr': - case 'aes128-ctr': - blocklen = 16; - } - if (instate.decrypt.isGCM) - instate.decrypt.size = 16; - else - instate.decrypt.size = blocklen; - while (blocklen > iv.length) { - iv = Buffer.concat([iv, - crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(iv) - .digest()]); - } - iv = iv.slice(0, blocklen); - } else { - instate.decrypt.size = blocklen; - iv = EMPTY_BUFFER; // Streaming ciphers don't use an IV upfront - } - - // Create a reusable buffer for decryption purposes - instate.decrypt.buf = new Buffer(instate.decrypt.size); - - switch (instate.decrypt.type) { - case 'aes256-gcm': - case 'aes256-gcm@openssh.com': - case 'aes256-cbc': - case 'aes256-ctr': - case 'arcfour256': - keylen = 32; - break; - case '3des-cbc': - case '3des-ctr': - case 'aes192-cbc': - case 'aes192-ctr': - keylen = 24; - break; - case 'aes128-gcm': - case 'aes128-gcm@openssh.com': - case 'aes128-cbc': - case 'aes128-ctr': - case 'cast128-cbc': - case 'blowfish-cbc': - case 'arcfour': - case 'arcfour128': - keylen = 16; - break; - } - key = crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(!self.server ? 'D' : 'C', 'ascii') - .update(outstate.sessionId) - .digest(); - while (keylen > key.length) { - key = Buffer.concat([key, - crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(key) - .digest()]); - } - key = key.slice(0, keylen); - - var decipherAlgo = SSH_TO_OPENSSL[instate.decrypt.type]; - instate.decrypt.instance = crypto.createDecipheriv(decipherAlgo, key, iv); - instate.decrypt.instance.setAutoPadding(false); - instate.decrypt.iv = iv; - instate.decrypt.key = key; - - /* The "arcfour128" algorithm is the RC4 cipher, as described in - [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream - generated by the cipher MUST be discarded, and the first byte of the - first encrypted packet MUST be encrypted using the 1537th byte of - keystream. - - -- http://tools.ietf.org/html/rfc4345#section-4 */ - var emptyBuf; - if (outstate.encrypt.type.substr(0, 7) === 'arcfour') { - emptyBuf = new Buffer(1536); - emptyBuf.fill(0); - outstate.encrypt.instance.update(emptyBuf); - } - if (instate.decrypt.type.substr(0, 7) === 'arcfour') { - emptyBuf = new Buffer(1536); - emptyBuf.fill(0); - instate.decrypt.instance.update(emptyBuf); - } - - var createKeyLen = 0; - var checkKeyLen = 0; - switch (outstate.hmac.type) { - case 'hmac-ripemd160': - case 'hmac-sha1': - createKeyLen = 20; - outstate.hmac.size = 20; - break; - case 'hmac-sha1-96': - createKeyLen = 20; - outstate.hmac.size = 12; - break; - case 'hmac-sha2-256': - createKeyLen = 32; - outstate.hmac.size = 32; - break; - case 'hmac-sha2-256-96': - createKeyLen = 32; - outstate.hmac.size = 12; - break; - case 'hmac-sha2-512': - createKeyLen = 64; - outstate.hmac.size = 64; - break; - case 'hmac-sha2-512-96': - createKeyLen = 64; - outstate.hmac.size = 12; - break; - case 'hmac-md5': - createKeyLen = 16; - outstate.hmac.size = 16; - break; - case 'hmac-md5-96': - createKeyLen = 16; - outstate.hmac.size = 12; - break; - } - switch (instate.hmac.type) { - case 'hmac-ripemd160': - case 'hmac-sha1': - checkKeyLen = 20; - instate.hmac.size = 20; - break; - case 'hmac-sha1-96': - checkKeyLen = 20; - instate.hmac.size = 12; - break; - case 'hmac-sha2-256': - checkKeyLen = 32; - instate.hmac.size = 32; - break; - case 'hmac-sha2-256-96': - checkKeyLen = 32; - instate.hmac.size = 12; - break; - case 'hmac-sha2-512': - checkKeyLen = 64; - instate.hmac.size = 64; - break; - case 'hmac-sha2-512-96': - checkKeyLen = 64; - instate.hmac.size = 12; - break; - case 'hmac-md5': - checkKeyLen = 16; - instate.hmac.size = 16; - break; - case 'hmac-md5-96': - checkKeyLen = 16; - instate.hmac.size = 12; - break; - } - - if (!outstate.encrypt.isGCM) { - key = crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(!self.server ? 'E' : 'F', 'ascii') - .update(outstate.sessionId) - .digest(); - while (createKeyLen > key.length) { - key = Buffer.concat([key, - crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(key) - .digest()]); - } - outstate.hmac.key = key.slice(0, createKeyLen); - } else - outstate.hmac.key = undefined; - if (!instate.decrypt.isGCM) { - key = crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(!self.server ? 'F' : 'E', 'ascii') - .update(outstate.sessionId) - .digest(); - while (checkKeyLen > key.length) { - key = Buffer.concat([key, - crypto.createHash(dhHashAlgo) - .update(secret) - .update(outstate.exchangeHash) - .update(key) - .digest()]); - } - instate.hmac.key = key.slice(0, checkKeyLen); - } else { - instate.hmac.key = undefined; - instate.hmac.size = 16; - } - - outstate.exchangeHash = undefined; - - // Create a reusable buffer for message verification purposes - if (!instate.hmac.buf - || instate.hmac.buf.length !== instate.hmac.size) - instate.hmac.buf = new Buffer(instate.hmac.size); - - if (outstate.compress.type === 'zlib') - outstate.compress.instance = zlib.createDeflate(ZLIB_OPTS); - else if (outstate.compress.type === 'none') - outstate.compress.instance = false; - if (instate.decompress.type === 'zlib') - instate.decompress.instance = zlib.createInflate(ZLIB_OPTS); - else if (instate.decompress.type === 'none') - instate.decompress.instance = false; - - self.bytesSent = self.bytesReceived = 0; - - if (outstate.status === OUT_REKEYING) { - outstate.status = OUT_READY; - - // Empty our outbound buffer of any data we tried to send during the - // re-keying process - var queue = outstate.rekeyQueue; - var qlen = queue.length; - var q = 0; - - outstate.rekeyQueue = []; - - for (; q < qlen; ++q) { - if (Buffer.isBuffer(queue[q])) - send(self, queue[q]); - else - send(self, queue[q][0], queue[q][1]); - } - - // Now empty our inbound buffer of any non-transport layer packets we - // received during the re-keying process - queue = instate.rekeyQueue; - qlen = queue.length; - q = 0; - - instate.rekeyQueue = []; - - var curSeqno = instate.seqno; - for (; q < qlen; ++q) { - instate.seqno = queue[q][0]; - instate.payload = queue[q][1]; - if (parsePacket(self) === false) - return; - - if (instate.status === IN_INIT) { - // We were reset due to some error/disagreement ? - return; - } - } - instate.seqno = curSeqno; - } else { - outstate.status = OUT_READY; - if (instate.status === IN_PACKET) { - // Explicitly update incoming packet parser status in order to get the - // correct decipher, hmac, etc. states. - - // We only get here if the host fingerprint callback was called - // asynchronously and the incoming packet parser is still expecting an - // unencrypted packet, etc. - - self.debug('DEBUG: Parser: IN_PACKETBEFORE (update) (expecting ' - + instate.decrypt.size + ')'); - // Wait for the right number of bytes so we can determine the incoming - // packet length - expectData(self, - EXP_TYPE_BYTES, - instate.decrypt.size, - instate.decrypt.buf); - } - self.emit('ready'); - } -} - -function parsePacket(self, callback) { - var instate = self._state.incoming; - var outstate = self._state.outgoing; - var payload = instate.payload; - var seqno = instate.seqno; - var serviceName; - var lang; - var message; - var info; - var chan; - var data; - var srcIP; - var srcPort; - var sender; - var window; - var packetSize; - var recipient; - var description; - var socketPath; - - if (++instate.seqno > MAX_SEQNO) - instate.seqno = 0; - - if (instate.ignoreNext) { - self.debug('DEBUG: Parser: Packet ignored'); - instate.ignoreNext = false; - return; - } - - var type = payload[0]; - if (type === undefined) - return false; - - // If we receive a packet during handshake that is not the expected packet - // and it is not one of: DISCONNECT, IGNORE, UNIMPLEMENTED, or DEBUG, then we - // close the stream - if (outstate.status !== OUT_READY - && MESSAGE[type] !== instate.expectedPacket - && type < 1 - && type > 4) { - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, expected: ' - + instate.expectedPacket - + ' but got: ' - + MESSAGE[type]); - // XXX: Potential issue where the module user decides to initiate a rekey - // via KEXINIT() (which sets `expectedPacket`) after receiving a packet - // and there is still another packet already waiting to be parsed at the - // time the KEXINIT is written. this will cause an unexpected disconnect... - self.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - var err = new Error('Received unexpected packet'); - err.level = 'protocol'; - self.emit('error', err); - return false; - } - - if (type === MESSAGE.CHANNEL_DATA) { - /* - byte SSH_MSG_CHANNEL_DATA - uint32 recipient channel - string data - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - // TODO: MAX_CHAN_DATA_LEN here should really be dependent upon the - // channel's packet size. The ssh2 module uses 32KB, so we'll hard - // code this for now ... - data = readString(payload, 5, self, callback, 32768); - if (data === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_DATA (' - + chan - + ')'); - self.emit('CHANNEL_DATA:' + chan, data); - } else if (type === MESSAGE.CHANNEL_EXTENDED_DATA) { - /* - byte SSH_MSG_CHANNEL_EXTENDED_DATA - uint32 recipient channel - uint32 data_type_code - string data - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - var dataType = readInt(payload, 5, self, callback); - if (dataType === false) - return false; - data = readString(payload, 9, self, callback); - if (data === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: ' - + 'CHANNEL_EXTENDED_DATA (' - + chan - + ')'); - self.emit('CHANNEL_EXTENDED_DATA:' + chan, dataType, data); - } else if (type === MESSAGE.CHANNEL_WINDOW_ADJUST) { - /* - byte SSH_MSG_CHANNEL_WINDOW_ADJUST - uint32 recipient channel - uint32 bytes to add - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - var bytesToAdd = readInt(payload, 5, self, callback); - if (bytesToAdd === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: ' - + 'CHANNEL_WINDOW_ADJUST (' - + chan - + ', ' - + bytesToAdd - + ')'); - self.emit('CHANNEL_WINDOW_ADJUST:' + chan, bytesToAdd); - } else if (type === MESSAGE.CHANNEL_SUCCESS) { - /* - byte SSH_MSG_CHANNEL_SUCCESS - uint32 recipient channel - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_SUCCESS (' - + chan - + ')'); - self.emit('CHANNEL_SUCCESS:' + chan); - } else if (type === MESSAGE.CHANNEL_FAILURE) { - /* - byte SSH_MSG_CHANNEL_FAILURE - uint32 recipient channel - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_FAILURE (' - + chan - + ')'); - self.emit('CHANNEL_FAILURE:' + chan); - } else if (type === MESSAGE.CHANNEL_EOF) { - /* - byte SSH_MSG_CHANNEL_EOF - uint32 recipient channel - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_EOF (' - + chan - + ')'); - self.emit('CHANNEL_EOF:' + chan); - } else if (type === MESSAGE.CHANNEL_OPEN) { - /* - byte SSH_MSG_CHANNEL_OPEN - string channel type in US-ASCII only - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - .... channel type specific data follows - */ - var chanType = readString(payload, 1, 'ascii', self, callback); - if (chanType === false) - return false; - sender = readInt(payload, payload._pos, self, callback); - if (sender === false) - return false; - window = readInt(payload, payload._pos += 4, self, callback); - if (window === false) - return false; - packetSize = readInt(payload, payload._pos += 4, self, callback); - if (packetSize === false) - return false; - var channel; - - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_OPEN (' - + sender - + ', ' - + chanType - + ')'); - - if (chanType === 'forwarded-tcpip' // Server->Client - || chanType === 'direct-tcpip') { // Client->Server - /* - string address that was connected / host to connect - uint32 port that was connected / port to connect - string originator IP address - uint32 originator port - */ - var destIP = readString(payload, - payload._pos += 4, - 'ascii', - self, - callback); - if (destIP === false) - return false; - var destPort = readInt(payload, payload._pos, self, callback); - if (destPort === false) - return false; - srcIP = readString(payload, payload._pos += 4, 'ascii', self, callback); - if (srcIP === false) - return false; - srcPort = readInt(payload, payload._pos, self, callback); - if (srcPort === false) - return false; - channel = { - type: chanType, - sender: sender, - window: window, - packetSize: packetSize, - data: { - destIP: destIP, - destPort: destPort, - srcIP: srcIP, - srcPort: srcPort - } - }; - } else if (// Server->Client - chanType === 'forwarded-streamlocal@openssh.com' - // Client->Server - || chanType === 'direct-streamlocal@openssh.com') { - /* - string socket path - string reserved for future use - */ - socketPath = readString(payload, - payload._pos += 4, - 'utf8', - self, - callback); - if (socketPath === false) - return false; - channel = { - type: chanType, - sender: sender, - window: window, - packetSize: packetSize, - data: { - socketPath: socketPath, - } - }; - } else if (chanType === 'x11') { // Server->Client - /* - string originator address (e.g., "192.168.7.38") - uint32 originator port - */ - srcIP = readString(payload, payload._pos += 4, 'ascii', self, callback); - if (srcIP === false) - return false; - srcPort = readInt(payload, payload._pos, self, callback); - if (srcPort === false) - return false; - channel = { - type: chanType, - sender: sender, - window: window, - packetSize: packetSize, - data: { - srcIP: srcIP, - srcPort: srcPort - } - }; - } else { - // 'session' (Client->Server), 'auth-agent@openssh.com' (Server->Client) - channel = { - type: chanType, - sender: sender, - window: window, - packetSize: packetSize, - data: {} - }; - } - - self.emit('CHANNEL_OPEN', channel); - } else if (type === MESSAGE.CHANNEL_OPEN_CONFIRMATION) { - /* - byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION - uint32 recipient channel - uint32 sender channel - uint32 initial window size - uint32 maximum packet size - .... channel type specific data follows - */ - // "The 'recipient channel' is the channel number given in the - // original open request, and 'sender channel' is the channel number - // allocated by the other side." - recipient = readInt(payload, 1, self, callback); - if (recipient === false) - return false; - sender = readInt(payload, 5, self, callback); - if (sender === false) - return false; - window = readInt(payload, 9, self, callback); - if (window === false) - return false; - packetSize = readInt(payload, 13, self, callback); - if (packetSize === false) - return false; - - info = { - recipient: recipient, - sender: sender, - window: window, - packetSize: packetSize - }; - - if (payload.length > 17) - info.data = payload.slice(17); - - self.emit('CHANNEL_OPEN_CONFIRMATION:' + info.recipient, info); - } else if (type === MESSAGE.CHANNEL_OPEN_FAILURE) { - /* - byte SSH_MSG_CHANNEL_OPEN_FAILURE - uint32 recipient channel - uint32 reason code - string description in ISO-10646 UTF-8 encoding - string language tag - */ - recipient = readInt(payload, 1, self, callback); - if (recipient === false) - return false; - var reasonCode = readInt(payload, 5, self, callback); - if (reasonCode === false) - return false; - description = readString(payload, 9, 'utf8', self, callback); - if (description === false) - return false; - lang = readString(payload, payload._pos, 'utf8', self, callback); - if (lang === false) - return false; - payload._pos = 9; - info = { - recipient: recipient, - reasonCode: reasonCode, - reason: CHANNEL_OPEN_FAILURE[reasonCode], - description: description, - lang: lang - }; - - self.emit('CHANNEL_OPEN_FAILURE:' + info.recipient, info); - } else if (type === MESSAGE.CHANNEL_CLOSE) { - /* - byte SSH_MSG_CHANNEL_CLOSE - uint32 recipient channel - */ - chan = readInt(payload, 1, self, callback); - if (chan === false) - return false; - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_CLOSE (' - + chan - + ')'); - self.emit('CHANNEL_CLOSE:' + chan); - } else if (type === MESSAGE.IGNORE) { - /* - byte SSH_MSG_IGNORE - string data - */ - } else if (type === MESSAGE.DISCONNECT) { - /* - byte SSH_MSG_DISCONNECT - uint32 reason code - string description in ISO-10646 UTF-8 encoding - string language tag - */ - var reason = readInt(payload, 1, self, callback); - if (reason === false) - return false; - var reasonText = DISCONNECT_REASON[reason]; - description = readString(payload, 5, 'utf8', self, callback); - if (description === false) - return false; - - if (payload._pos < payload.length) - lang = readString(payload, payload._pos, 'ascii', self, callback); - - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: DISCONNECT (' - + reasonText - + ')'); - - self.emit('DISCONNECT', reasonText, reason, description, lang); - } else if (type === MESSAGE.DEBUG) { - /* - byte SSH_MSG_DEBUG - boolean always_display - string message in ISO-10646 UTF-8 encoding - string language tag - */ - message = readString(payload, 2, 'utf8', self, callback); - if (message === false) - return false; - lang = readString(payload, payload._pos, 'ascii', self, callback); - if (lang === false) - return false; - - self.emit('DEBUG', message, lang); - } else if (type === MESSAGE.NEWKEYS) { - /* - byte SSH_MSG_NEW_KEYS - */ - self.emit('NEWKEYS'); - } else if (type === MESSAGE.SERVICE_REQUEST) { - /* - byte SSH_MSG_SERVICE_REQUEST - string service name - */ - serviceName = readString(payload, 1, 'ascii', self, callback); - if (serviceName === false) - return false; - - self.emit('SERVICE_REQUEST', serviceName); - } else if (type === MESSAGE.SERVICE_ACCEPT) { - /* - byte SSH_MSG_SERVICE_ACCEPT - string service name - */ - serviceName = readString(payload, 1, 'ascii', self, callback); - if (serviceName === false) - return false; - - self.emit('SERVICE_ACCEPT', serviceName); - } else if (type === MESSAGE.USERAUTH_REQUEST) { - /* - byte SSH_MSG_USERAUTH_REQUEST - string user name in ISO-10646 UTF-8 encoding [RFC3629] - string service name in US-ASCII - string method name in US-ASCII - .... method specific fields - */ - var username = readString(payload, 1, 'utf8', self, callback); - if (username === false) - return false; - var svcName = readString(payload, payload._pos, 'ascii', self, callback); - if (svcName === false) - return false; - var method = readString(payload, payload._pos, 'ascii', self, callback); - if (method === false) - return false; - var methodData; - - if (method === 'password') { - methodData = readString(payload, - payload._pos + 1, - 'utf8', - self, - callback); - if (methodData === false) - return false; - } else if (method === 'publickey' || method === 'hostbased') { - var pkSigned; - var keyAlgo; - var key; - var signature; - var blob; - var hostname; - var userlocal; - if (method === 'publickey') { - pkSigned = payload[payload._pos++]; - if (pkSigned === undefined) - return false; - pkSigned = (pkSigned !== 0); - } - keyAlgo = readString(payload, payload._pos, 'ascii', self, callback); - if (keyAlgo === false) - return false; - key = readString(payload, payload._pos, self, callback); - if (key === false) - return false; - - if (pkSigned || method === 'hostbased') { - if (method === 'hostbased') { - hostname = readString(payload, payload._pos, 'ascii', self, callback); - if (hostname === false) - return false; - userlocal = readString(payload, payload._pos, 'utf8', self, callback); - if (userlocal === false) - return false; - } - - var blobEnd = payload._pos; - signature = readString(payload, blobEnd, self, callback); - if (signature === false) - return false; - - if (signature.length > (4 + keyAlgo.length + 4) - && signature.toString('ascii', 4, 4 + keyAlgo.length) === keyAlgo) { - // Skip algoLen + algo + sigLen - signature = signature.slice(4 + keyAlgo.length + 4); - } - - if (keyAlgo === 'ssh-dss') { - signature = DSASigBareToBER(signature); - } else if (keyAlgo !== 'ssh-rsa' && keyAlgo !== 'ssh-dss') { - // ECDSA - signature = ECDSASigSSHToASN1(signature, self, callback); - if (signature === false) - return false; - } - - blob = new Buffer(4 + outstate.sessionId.length + blobEnd); - blob.writeUInt32BE(outstate.sessionId.length, 0, true); - outstate.sessionId.copy(blob, 4); - payload.copy(blob, 4 + outstate.sessionId.length, 0, blobEnd); - } - - methodData = { - keyAlgo: keyAlgo, - key: key, - signature: signature, - blob: blob, - localHostname: hostname, - localUsername: userlocal - }; - } else if (method === 'keyboard-interactive') { - // Skip language, it's deprecated - var skipLen = readInt(payload, payload._pos, self, callback); - if (skipLen === false) - return false; - methodData = readString(payload, - payload._pos + 4 + skipLen, - 'utf8', - self, - callback); - if (methodData === false) - return false; - } else if (method !== 'none') - methodData = payload.slice(payload._pos); - - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: USERAUTH_REQUEST (' - + method - + ')'); - - self._state.authsQueue.push(method); - self.emit('USERAUTH_REQUEST', username, svcName, method, methodData); - } else if (type === MESSAGE.USERAUTH_SUCCESS) { - /* - byte SSH_MSG_USERAUTH_SUCCESS - */ - if (outstate.compress.type === 'zlib@openssh.com') - outstate.compress.instance = zlib.createDeflate(ZLIB_OPTS); - if (instate.decompress.type === 'zlib@openssh.com') - instate.decompress.instance = zlib.createInflate(ZLIB_OPTS); - self._state.authsQueue.shift(); - self.emit('USERAUTH_SUCCESS'); - } else if (type === MESSAGE.USERAUTH_FAILURE) { - /* - byte SSH_MSG_USERAUTH_FAILURE - name-list authentications that can continue - boolean partial success - */ - var auths = readString(payload, 1, 'ascii', self, callback); - if (auths === false) - return false; - var partSuccess = payload[payload._pos]; - if (partSuccess === undefined) - return false; - - partSuccess = (partSuccess !== 0); - auths = auths.split(','); - - self._state.authsQueue.shift(); - self.emit('USERAUTH_FAILURE', auths, partSuccess); - } else if (type === MESSAGE.USERAUTH_BANNER) { - /* - byte SSH_MSG_USERAUTH_BANNER - string message in ISO-10646 UTF-8 encoding - string language tag - */ - message = readString(payload, 1, 'utf8', self, callback); - if (message === false) - return false; - lang = readString(payload, payload._pos, 'utf8', self, callback); - if (lang === false) - return false; - - self.emit('USERAUTH_BANNER', message, lang); - } else if (type === MESSAGE.GLOBAL_REQUEST) { - /* - byte SSH_MSG_GLOBAL_REQUEST - string request name in US-ASCII only - boolean want reply - .... request-specific data follows - */ - var request = readString(payload, 1, 'ascii', self, callback); - if (request === false) { - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: GLOBAL_REQUEST'); - return false; - } - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: GLOBAL_REQUEST (' - + request - + ')'); - - var wantReply = payload[payload._pos++]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - - var reqData; - if (request === 'tcpip-forward' || request === 'cancel-tcpip-forward') { - var bindAddr = readString(payload, payload._pos, 'ascii', self, callback); - if (bindAddr === false) - return false; - var bindPort = readInt(payload, payload._pos, self, callback); - if (bindPort === false) - return false; - reqData = { - bindAddr: bindAddr, - bindPort: bindPort - }; - } else if (request === 'streamlocal-forward@openssh.com' - || request === 'cancel-streamlocal-forward@openssh.com') { - socketPath = readString(payload, payload._pos, 'utf8', self, callback); - if (socketPath === false) - return false; - reqData = { - socketPath: socketPath - }; - } else if (request === 'no-more-sessions@openssh.com') { - // No data - } else { - reqData = payload.slice(payload._pos); - } - - self.emit('GLOBAL_REQUEST', request, wantReply, reqData); - } else if (type === MESSAGE.REQUEST_SUCCESS) { - /* - byte SSH_MSG_REQUEST_SUCCESS - .... response specific data - */ - if (payload.length > 1) - self.emit('REQUEST_SUCCESS', payload.slice(1)); - else - self.emit('REQUEST_SUCCESS'); - } else if (type === MESSAGE.REQUEST_FAILURE) { - /* - byte SSH_MSG_REQUEST_FAILURE - */ - self.emit('REQUEST_FAILURE'); - } else if (type === MESSAGE.UNIMPLEMENTED) { - /* - byte SSH_MSG_UNIMPLEMENTED - uint32 packet sequence number of rejected message - */ - // TODO - } else if (type === MESSAGE.KEXINIT) - return parse_KEXINIT(self, callback); - else if (type === MESSAGE.CHANNEL_REQUEST) - return parse_CHANNEL_REQUEST(self, callback); - else if (type >= 30 && type <= 49) // Key exchange method-specific messages - return parse_KEX(self, type, callback); - else if (type >= 60 && type <= 70) // User auth context-specific messages - return parse_USERAUTH(self, type, callback); - else { - // Unknown packet type - var unimpl = new Buffer(1 + 4); - unimpl[0] = MESSAGE.UNIMPLEMENTED; - unimpl.writeUInt32BE(seqno, 1, true); - send(self, unimpl); - } -} - -function parse_KEXINIT(self, callback) { - var instate = self._state.incoming; - var payload = instate.payload; - - /* - byte SSH_MSG_KEXINIT - byte[16] cookie (random bytes) - name-list kex_algorithms - name-list server_host_key_algorithms - name-list encryption_algorithms_client_to_server - name-list encryption_algorithms_server_to_client - name-list mac_algorithms_client_to_server - name-list mac_algorithms_server_to_client - name-list compression_algorithms_client_to_server - name-list compression_algorithms_server_to_client - name-list languages_client_to_server - name-list languages_server_to_client - boolean first_kex_packet_follows - uint32 0 (reserved for future extension) - */ - var init = { - algorithms: { - kex: undefined, - srvHostKey: undefined, - cs: { - encrypt: undefined, - mac: undefined, - compress: undefined - }, - sc: { - encrypt: undefined, - mac: undefined, - compress: undefined - } - }, - languages: { - cs: undefined, - sc: undefined - } - }; - var val; - - val = readList(payload, 17, self, callback); - if (val === false) - return false; - init.algorithms.kex = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.srvHostKey = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.cs.encrypt = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.sc.encrypt = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.cs.mac = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.sc.mac = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.cs.compress = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.algorithms.sc.compress = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.languages.cs = val; - val = readList(payload, payload._pos, self, callback); - if (val === false) - return false; - init.languages.sc = val; - - var firstFollows = (payload._pos < payload.length - && payload[payload._pos] === 1); - - instate.kexinit = payload; - - self.emit('KEXINIT', init, firstFollows); -} - -function parse_KEX(self, type, callback) { - var state = self._state; - var instate = state.incoming; - var payload = instate.payload; - var pktType = (RE_GEX.test(state.kexdh) - ? DYNAMIC_KEXDH_MESSAGE[type] - : KEXDH_MESSAGE[type]); - - if (state.outgoing.status === OUT_READY - || instate.expectedPacket !== pktType) { - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, expected: ' - + instate.expectedPacket - + ' but got: ' - + pktType); - self.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - var err = new Error('Received unexpected packet'); - err.level = 'protocol'; - self.emit('error', err); - return false; - } - - if (RE_GEX.test(state.kexdh)) { - // Dynamic group exchange-related - - if (self.server) { - // TODO: Support group exchange server-side - self.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - var err = new Error('DH group exchange not supported by server'); - err.level = 'handshake'; - self.emit('error', err); - return false; - } else { - if (type === MESSAGE.KEXDH_GEX_GROUP) { - /* - byte SSH_MSG_KEX_DH_GEX_GROUP - mpint p, safe prime - mpint g, generator for subgroup in GF(p) - */ - var prime = readString(payload, 1, self, callback); - if (prime === false) - return false; - var gen = readString(payload, payload._pos, self, callback); - if (gen === false) - return false; - self.emit('KEXDH_GEX_GROUP', prime, gen); - } else if (type === MESSAGE.KEXDH_GEX_REPLY) - return parse_KEXDH_REPLY(self, callback); - } - } else { - // Static group or ECDH-related - - if (type === MESSAGE.KEXDH_INIT) { - /* - byte SSH_MSG_KEXDH_INIT - mpint e - */ - var e = readString(payload, 1, self, callback); - if (e === false) - return false; - - self.emit('KEXDH_INIT', e); - } else if (type === MESSAGE.KEXDH_REPLY) - return parse_KEXDH_REPLY(self, callback); - } -} - -function parse_KEXDH_REPLY(self, callback) { - var payload = self._state.incoming.payload; - /* - byte SSH_MSG_KEXDH_REPLY - / SSH_MSG_KEX_DH_GEX_REPLY - / SSH_MSG_KEX_ECDH_REPLY - string server public host key and certificates (K_S) - mpint f - string signature of H - */ - var hostkey = readString(payload, 1, self, callback); - if (hostkey === false) - return false; - var pubkey = readString(payload, payload._pos, self, callback); - if (pubkey === false) - return false; - var sig = readString(payload, payload._pos, self, callback); - if (sig === false) - return false; - var info = { - hostkey: hostkey, - hostkey_format: undefined, - pubkey: pubkey, - sig: sig, - sig_format: undefined - }; - var hostkey_format = readString(hostkey, 0, 'ascii', self, callback); - if (hostkey_format === false) - return false; - info.hostkey_format = hostkey_format; - var sig_format = readString(sig, 0, 'ascii', self, callback); - if (sig_format === false) - return false; - info.sig_format = sig_format; - self.emit('KEXDH_REPLY', info); -} - -function parse_USERAUTH(self, type, callback) { - var state = self._state; - var authMethod = state.authsQueue[0]; - var payload = state.incoming.payload; - var message; - var lang; - var text; - - if (authMethod === 'password') { - if (type === MESSAGE.USERAUTH_PASSWD_CHANGEREQ) { - /* - byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ - string prompt in ISO-10646 UTF-8 encoding - string language tag - */ - message = readString(payload, 1, 'utf8', self, callback); - if (message === false) - return false; - lang = readString(payload, payload._pos, 'utf8', self, callback); - if (lang === false) - return false; - self.emit('USERAUTH_PASSWD_CHANGEREQ', message, lang); - } - } else if (authMethod === 'keyboard-interactive') { - if (type === MESSAGE.USERAUTH_INFO_REQUEST) { - /* - byte SSH_MSG_USERAUTH_INFO_REQUEST - string name (ISO-10646 UTF-8) - string instruction (ISO-10646 UTF-8) - string language tag -- MAY be empty - int num-prompts - string prompt[1] (ISO-10646 UTF-8) - boolean echo[1] - ... - string prompt[num-prompts] (ISO-10646 UTF-8) - boolean echo[num-prompts] - */ - var name; - var instr; - var nprompts; - - name = readString(payload, 1, 'utf8', self, callback); - if (name === false) - return false; - instr = readString(payload, payload._pos, 'utf8', self, callback); - if (instr === false) - return false; - lang = readString(payload, payload._pos, 'utf8', self, callback); - if (lang === false) - return false; - nprompts = readInt(payload, payload._pos, self, callback); - if (nprompts === false) - return false; - - payload._pos += 4; - - var prompts = []; - for (var prompt = 0; prompt < nprompts; ++prompt) { - text = readString(payload, payload._pos, 'utf8', self, callback); - if (text === false) - return false; - var echo = payload[payload._pos++]; - if (echo === undefined) - return false; - echo = (echo !== 0); - prompts.push({ - prompt: text, - echo: echo - }); - } - self.emit('USERAUTH_INFO_REQUEST', name, instr, lang, prompts); - } else if (type === MESSAGE.USERAUTH_INFO_RESPONSE) { - /* - byte SSH_MSG_USERAUTH_INFO_RESPONSE - int num-responses - string response[1] (ISO-10646 UTF-8) - ... - string response[num-responses] (ISO-10646 UTF-8) - */ - var nresponses = readInt(payload, 1, self, callback); - if (nresponses === false) - return false; - - payload._pos = 5; - - var responses = []; - for (var response = 0; response < nresponses; ++response) { - text = readString(payload, payload._pos, 'utf8', self, callback); - if (text === false) - return false; - responses.push(text); - } - self.emit('USERAUTH_INFO_RESPONSE', responses); - } - } else if (authMethod === 'publickey') { - if (type === MESSAGE.USERAUTH_PK_OK) { - /* - byte SSH_MSG_USERAUTH_PK_OK - string public key algorithm name from the request - string public key blob from the request - */ - var authsQueue = self._state.authsQueue; - if (!authsQueue.length || authsQueue[0] !== 'publickey') - return; - authsQueue.shift(); - self.emit('USERAUTH_PK_OK'); - // XXX: Parse public key info? client currently can ignore it because - // there is only one outstanding auth request at any given time, so it - // knows which key was OK'd - } - } else if (authMethod !== undefined) { - // Invalid packet for this auth type - self.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - var err = new Error('Invalid authentication method: ' + authMethod); - err.level = 'protocol'; - self.emit('error', err); - } -} - -function parse_CHANNEL_REQUEST(self, callback) { - var payload = self._state.incoming.payload; - var info; - var cols; - var rows; - var width; - var height; - var wantReply; - var signal; - - var recipient = readInt(payload, 1, self, callback); - if (recipient === false) - return false; - var request = readString(payload, 5, 'ascii', self, callback); - if (request === false) - return false; - - if (request === 'exit-status') { // Server->Client - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "exit-status" - boolean FALSE - uint32 exit_status - */ - var code = readInt(payload, ++payload._pos, self, callback); - if (code === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: false, - code: code - }; - } else if (request === 'exit-signal') { // Server->Client - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "exit-signal" - boolean FALSE - string signal name (without the "SIG" prefix) - boolean core dumped - string error message in ISO-10646 UTF-8 encoding - string language tag - */ - var coredump; - if (!(self.remoteBugs & BUGS.OLD_EXIT)) { - signal = readString(payload, ++payload._pos, 'ascii', self, callback); - if (signal === false) - return false; - coredump = payload[payload._pos++]; - if (coredump === undefined) - return false; - coredump = (coredump !== 0); - } else { - /* - Instead of `signal name` and `core dumped`, we have just: - - uint32 signal number - */ - signal = readInt(payload, ++payload._pos, self, callback); - if (signal === false) - return false; - switch (signal) { - case 1: - signal = 'HUP'; - break; - case 2: - signal = 'INT'; - break; - case 3: - signal = 'QUIT'; - break; - case 6: - signal = 'ABRT'; - break; - case 9: - signal = 'KILL'; - break; - case 14: - signal = 'ALRM'; - break; - case 15: - signal = 'TERM'; - break; - default: - // Unknown or OS-specific - signal = 'UNKNOWN (' + signal + ')'; - } - coredump = false; - } - var description = readString(payload, payload._pos, 'utf8', self, - callback); - if (description === false) - return false; - var lang = readString(payload, payload._pos, 'utf8', self, callback); - if (lang === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: false, - signal: signal, - coredump: coredump, - description: description, - lang: lang - }; - } else if (request === 'pty-req') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "pty-req" - boolean want_reply - string TERM environment variable value (e.g., vt100) - uint32 terminal width, characters (e.g., 80) - uint32 terminal height, rows (e.g., 24) - uint32 terminal width, pixels (e.g., 640) - uint32 terminal height, pixels (e.g., 480) - string encoded terminal modes - */ - wantReply = payload[payload._pos++]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - var term = readString(payload, payload._pos, 'ascii', self, callback); - if (term === false) - return false; - cols = readInt(payload, payload._pos, self, callback); - if (cols === false) - return false; - rows = readInt(payload, payload._pos += 4, self, callback); - if (rows === false) - return false; - width = readInt(payload, payload._pos += 4, self, callback); - if (width === false) - return false; - height = readInt(payload, payload._pos += 4, self, callback); - if (height === false) - return false; - var modes = readString(payload, payload._pos += 4, self, callback); - if (modes === false) - return false; - modes = bytesToModes(modes); - info = { - recipient: recipient, - request: request, - wantReply: wantReply, - term: term, - cols: cols, - rows: rows, - width: width, - height: height, - modes: modes - }; - } else if (request === 'window-change') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "window-change" - boolean FALSE - uint32 terminal width, columns - uint32 terminal height, rows - uint32 terminal width, pixels - uint32 terminal height, pixels - */ - cols = readInt(payload, ++payload._pos, self, callback); - if (cols === false) - return false; - rows = readInt(payload, payload._pos += 4, self, callback); - if (rows === false) - return false; - width = readInt(payload, payload._pos += 4, self, callback); - if (width === false) - return false; - height = readInt(payload, payload._pos += 4, self, callback); - if (height === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: false, - cols: cols, - rows: rows, - width: width, - height: height - }; - } else if (request === 'x11-req') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "x11-req" - boolean want reply - boolean single connection - string x11 authentication protocol - string x11 authentication cookie - uint32 x11 screen number - */ - wantReply = payload[payload._pos++]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - var single = payload[payload._pos++]; - if (single === undefined) - return false; - single = (single !== 0); - var protocol = readString(payload, payload._pos, 'ascii', self, callback); - if (protocol === false) - return false; - var cookie = readString(payload, payload._pos, 'hex', self, callback); - if (cookie === false) - return false; - var screen = readInt(payload, payload._pos, self, callback); - if (screen === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: wantReply, - single: single, - protocol: protocol, - cookie: cookie, - screen: screen - }; - } else if (request === 'env') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "env" - boolean want reply - string variable name - string variable value - */ - wantReply = payload[payload._pos++]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - var key = readString(payload, payload._pos, 'utf8', self, callback); - if (key === false) - return false; - var val = readString(payload, payload._pos, 'utf8', self, callback); - if (val === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: wantReply, - key: key, - val: val - }; - } else if (request === 'shell') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "shell" - boolean want reply - */ - wantReply = payload[payload._pos]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - info = { - recipient: recipient, - request: request, - wantReply: wantReply - }; - } else if (request === 'exec') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "exec" - boolean want reply - string command - */ - wantReply = payload[payload._pos++]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - var command = readString(payload, payload._pos, 'utf8', self, callback); - if (command === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: wantReply, - command: command - }; - } else if (request === 'subsystem') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "subsystem" - boolean want reply - string subsystem name - */ - wantReply = payload[payload._pos++]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - var subsystem = readString(payload, payload._pos, 'utf8', self, callback); - if (subsystem === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: wantReply, - subsystem: subsystem - }; - } else if (request === 'signal') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "signal" - boolean FALSE - string signal name (without the "SIG" prefix) - */ - signal = readString(payload, ++payload._pos, 'ascii', self, callback); - if (signal === false) - return false; - info = { - recipient: recipient, - request: request, - wantReply: false, - signal: 'SIG' + signal - }; - } else if (request === 'xon-xoff') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "xon-xoff" - boolean FALSE - boolean client can do - */ - var clientControl = payload[++payload._pos]; - if (clientControl === undefined) - return false; - clientControl = (clientControl !== 0); - info = { - recipient: recipient, - request: request, - wantReply: false, - clientControl: clientControl - }; - } else if (request === 'auth-agent-req@openssh.com') { // Client->Server - /* - byte SSH_MSG_CHANNEL_REQUEST - uint32 recipient channel - string "auth-agent-req@openssh.com" - boolean want reply - */ - wantReply = payload[payload._pos]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - info = { - recipient: recipient, - request: request, - wantReply: wantReply - }; - } else { - // Unknown request type - wantReply = payload[payload._pos]; - if (wantReply === undefined) - return false; - wantReply = (wantReply !== 0); - info = { - recipient: recipient, - request: request, - wantReply: wantReply - }; - } - self.debug('DEBUG: Parser: IN_PACKETDATAAFTER, packet: CHANNEL_REQUEST (' - + recipient - + ', ' - + request - + ')'); - self.emit('CHANNEL_REQUEST:' + recipient, info); -} - -function hmacVerify(self, data) { - var instate = self._state.incoming; - var hmac = instate.hmac; - - self.debug('DEBUG: Parser: Verifying MAC'); - - if (instate.decrypt.isGCM) { - var decrypt = instate.decrypt; - var instance = decrypt.instance; - - instance.setAuthTag(data); - - var payload = instance.update(instate.packet); - instate.payload = payload.slice(1, instate.packet.length + 4 - payload[0]); - //instance.final(); - iv_inc(decrypt.iv); - - decrypt.instance = crypto.createDecipheriv( - SSH_TO_OPENSSL[decrypt.type], - decrypt.key, - decrypt.iv - ); - decrypt.instance.setAutoPadding(false); - return true; - } else { - var calcHmac = crypto.createHmac(SSH_TO_OPENSSL[hmac.type], hmac.key); - - hmac.bufCompute.writeUInt32BE(instate.seqno, 0, true); - hmac.bufCompute.writeUInt32BE(instate.pktLen, 4, true); - hmac.bufCompute[8] = instate.padLen; - - calcHmac.update(hmac.bufCompute); - calcHmac.update(instate.packet); - - var mac = calcHmac.digest('binary'); - if (mac.length > instate.hmac.size) - mac = mac.slice(0, instate.hmac.size); - return (mac === data.toString('binary')); - } -} - -function decryptData(self, data) { - var instance = self._state.incoming.decrypt.instance; - self.debug('DEBUG: Parser: Decrypting'); - return instance.update(data); -} - -function expectData(self, type, amount, bufferKey) { - var expect = self._state.incoming.expect; - expect.amount = amount; - expect.type = type; - expect.ptr = 0; - if (bufferKey && self[bufferKey]) - expect.buf = self[bufferKey]; - else if (amount) - expect.buf = new Buffer(amount); -} - -function readList(buffer, start, stream, callback) { - var list = readString(buffer, start, 'ascii', stream, callback); - return (list !== false ? (list.length ? list.split(',') : []) : false); -} - -function bytesToModes(buffer) { - var modes = {}; - - for (var i = 0, len = buffer.length, opcode; i < len; i += 5) { - opcode = buffer[i]; - if (opcode === TERMINAL_MODE.TTY_OP_END - || TERMINAL_MODE[opcode] === undefined - || i + 5 > len) - break; - modes[TERMINAL_MODE[opcode]] = buffer.readUInt32BE(i + 1, true); - } - - return modes; -} - -function modesToBytes(modes) { - var RE_IS_NUM = /^\d+$/; - var keys = Object.keys(modes); - var b = 0; - var bytes = []; - - for (var i = 0, len = keys.length, key, opcode, val; i < len; ++i) { - key = keys[i]; - opcode = TERMINAL_MODE[key]; - if (opcode - && !RE_IS_NUM.test(key) - && typeof modes[key] === 'number' - && key !== 'TTY_OP_END') { - val = modes[key]; - bytes[b++] = opcode; - bytes[b++] = (val >>> 24) & 0xFF; - bytes[b++] = (val >>> 16) & 0xFF; - bytes[b++] = (val >>> 8) & 0xFF; - bytes[b++] = val & 0xFF; - } - } - - bytes[b] = TERMINAL_MODE.TTY_OP_END; - - return bytes; -} - -// Shared outgoing functions -function KEXINIT(self, cb) { // Client/Server - randBytes(16, function(myCookie) { - /* - byte SSH_MSG_KEXINIT - byte[16] cookie (random bytes) - name-list kex_algorithms - name-list server_host_key_algorithms - name-list encryption_algorithms_client_to_server - name-list encryption_algorithms_server_to_client - name-list mac_algorithms_client_to_server - name-list mac_algorithms_server_to_client - name-list compression_algorithms_client_to_server - name-list compression_algorithms_server_to_client - name-list languages_client_to_server - name-list languages_server_to_client - boolean first_kex_packet_follows - uint32 0 (reserved for future extension) - */ - var algos = self.config.algorithms; - - var kexBuf = algos.kexBuf; - if (self.remoteBugs & BUGS.BAD_DHGEX) { - var copied = false; - var kexList = algos.kex; - for (var j = kexList.length - 1; j >= 0; --j) { - if (kexList[j].indexOf('group-exchange') !== -1) { - if (!copied) { - kexList = kexList.slice(); - copied = true; - } - kexList.splice(j, 1); - } - } - if (copied) - kexBuf = new Buffer(kexList.join(',')); - } - - var hostKeyBuf = algos.serverHostKeyBuf; - - var kexInitSize = 1 + 16 - + 4 + kexBuf.length - + 4 + hostKeyBuf.length - + (2 * (4 + algos.cipherBuf.length)) - + (2 * (4 + algos.hmacBuf.length)) - + (2 * (4 + algos.compressBuf.length)) - + (2 * (4 /* languages skipped */)) - + 1 + 4; - var buf = new Buffer(kexInitSize); - var p = 17; - - buf.fill(0); - - buf[0] = MESSAGE.KEXINIT; - - if (myCookie !== false) - myCookie.copy(buf, 1); - - buf.writeUInt32BE(kexBuf.length, p, true); - p += 4; - kexBuf.copy(buf, p); - p += kexBuf.length; - - buf.writeUInt32BE(hostKeyBuf.length, p, true); - p += 4; - hostKeyBuf.copy(buf, p); - p += hostKeyBuf.length; - - buf.writeUInt32BE(algos.cipherBuf.length, p, true); - p += 4; - algos.cipherBuf.copy(buf, p); - p += algos.cipherBuf.length; - - buf.writeUInt32BE(algos.cipherBuf.length, p, true); - p += 4; - algos.cipherBuf.copy(buf, p); - p += algos.cipherBuf.length; - - buf.writeUInt32BE(algos.hmacBuf.length, p, true); - p += 4; - algos.hmacBuf.copy(buf, p); - p += algos.hmacBuf.length; - - buf.writeUInt32BE(algos.hmacBuf.length, p, true); - p += 4; - algos.hmacBuf.copy(buf, p); - p += algos.hmacBuf.length; - - buf.writeUInt32BE(algos.compressBuf.length, p, true); - p += 4; - algos.compressBuf.copy(buf, p); - p += algos.compressBuf.length; - - buf.writeUInt32BE(algos.compressBuf.length, p, true); - p += 4; - algos.compressBuf.copy(buf, p); - p += algos.compressBuf.length; - - // Skip language lists, first_kex_packet_follows, and reserved bytes - - self.debug('DEBUG: Outgoing: Writing KEXINIT'); - - self._state.incoming.expectedPacket = 'KEXINIT'; - - var outstate = self._state.outgoing; - - outstate.kexinit = buf; - - if (outstate.status === OUT_READY) { - // We are the one starting the rekeying process ... - outstate.status = OUT_REKEYING; - } - - send(self, buf, cb, true); - }); - return true; -} - -function KEXDH_INIT(self) { // Client - var state = self._state; - var outstate = state.outgoing; - var buf = new Buffer(1 + 4 + outstate.pubkey.length); - - if (RE_GEX.test(state.kexdh)) { - state.incoming.expectedPacket = 'KEXDH_GEX_REPLY'; - buf[0] = MESSAGE.KEXDH_GEX_INIT; - self.debug('DEBUG: Outgoing: Writing KEXDH_GEX_INIT'); - } else { - state.incoming.expectedPacket = 'KEXDH_REPLY'; - buf[0] = MESSAGE.KEXDH_INIT; - if (state.kexdh !== 'group') - self.debug('DEBUG: Outgoing: Writing KEXECDH_INIT'); - else - self.debug('DEBUG: Outgoing: Writing KEXDH_INIT'); - } - - buf.writeUInt32BE(outstate.pubkey.length, 1, true); - outstate.pubkey.copy(buf, 5); - - return send(self, buf, undefined, true); -} - -function KEXDH_REPLY(self, e) { // Server - var state = self._state; - var outstate = state.outgoing; - var instate = state.incoming; - var curHostKey = self.config.hostKeys[state.hostkeyFormat]; - var hostkey = curHostKey.publicKey.public; - var hostkeyAlgo = curHostKey.publicKey.fulltype; - var privateKey = curHostKey.privateKey.privateOrig; - - // e === client DH public key - - var slicepos = -1; - for (var i = 0, len = e.length; i < len; ++i) { - if (e[i] === 0) - ++slicepos; - else - break; - } - if (slicepos > -1) - e = e.slice(slicepos + 1); - - var secret = tryComputeSecret(state.kex, e); - if (secret instanceof Error) { - secret.message = 'Error while computing DH secret (' - + state.kexdh + '): ' - + secret.message; - secret.level = 'handshake'; - self.emit('error', secret); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - var hashAlgo; - if (state.kexdh === 'group') - hashAlgo = 'sha1'; - else - hashAlgo = RE_KEX_HASH.exec(state.kexdh)[1]; - - var hash = crypto.createHash(hashAlgo); - - var len_ident = Buffer.byteLength(instate.identRaw); - var len_sident = Buffer.byteLength(self.config.ident); - var len_init = instate.kexinit.length; - var len_sinit = outstate.kexinit.length; - var len_hostkey = hostkey.length; - var len_pubkey = e.length; - var len_spubkey = outstate.pubkey.length; - var len_secret = secret.length; - - var idx_spubkey = 0; - var idx_secret = 0; - - while (outstate.pubkey[idx_spubkey] === 0x00) { - ++idx_spubkey; - --len_spubkey; - } - while (secret[idx_secret] === 0x00) { - ++idx_secret; - --len_secret; - } - if (e[0] & 0x80) - ++len_pubkey; - if (outstate.pubkey[idx_spubkey] & 0x80) - ++len_spubkey; - if (secret[idx_secret] & 0x80) - ++len_secret; - - var exchangeBufLen = len_ident - + len_sident - + len_init - + len_sinit - + len_hostkey - + len_pubkey - + len_spubkey - + len_secret - + (4 * 8); // Length fields for above values - - // Group exchange-related - var isGEX = RE_GEX.test(state.kexdh); - var len_gex_prime = 0; - var len_gex_gen = 0; - var idx_gex_prime = 0; - var idx_gex_gen = 0; - var gex_prime; - var gex_gen; - if (isGEX) { - gex_prime = state.kex.getPrime(); - gex_gen = state.kex.getGenerator(); - len_gex_prime = gex_prime.length; - len_gex_gen = gex_gen.length; - while (gex_prime[idx_gex_prime] === 0x00) { - ++idx_gex_prime; - --len_gex_prime; - } - while (gex_gen[idx_gex_gen] === 0x00) { - ++idx_gex_gen; - --len_gex_gen; - } - if (gex_prime[idx_gex_prime] & 0x80) - ++len_gex_prime; - if (gex_gen[idx_gex_gen] & 0x80) - ++len_gex_gen; - exchangeBufLen += (4 * 3); // min, n, max values - exchangeBufLen += (4 * 2); // prime, generator length fields - exchangeBufLen += len_gex_prime; - exchangeBufLen += len_gex_gen; - } - - var bp = 0; - var exchangeBuf = new Buffer(exchangeBufLen); - - exchangeBuf.writeUInt32BE(len_ident, bp, true); - bp += 4; - exchangeBuf.write(instate.identRaw, bp, 'utf8'); // V_C - bp += len_ident; - - exchangeBuf.writeUInt32BE(len_sident, bp, true); - bp += 4; - exchangeBuf.write(self.config.ident, bp, 'utf8'); // V_S - bp += len_sident; - - exchangeBuf.writeUInt32BE(len_init, bp, true); - bp += 4; - instate.kexinit.copy(exchangeBuf, bp); // I_C - bp += len_init; - instate.kexinit = undefined; - - exchangeBuf.writeUInt32BE(len_sinit, bp, true); - bp += 4; - outstate.kexinit.copy(exchangeBuf, bp); // I_S - bp += len_sinit; - outstate.kexinit = undefined; - - exchangeBuf.writeUInt32BE(len_hostkey, bp, true); - bp += 4; - hostkey.copy(exchangeBuf, bp); // K_S - bp += len_hostkey; - - if (isGEX) { - KEXDH_GEX_REQ_PACKET.slice(1).copy(exchangeBuf, bp); // min, n, max - bp += (4 * 3); // Skip over bytes just copied - - exchangeBuf.writeUInt32BE(len_gex_prime, bp, true); - bp += 4; - if (gex_prime[idx_gex_prime] & 0x80) - exchangeBuf[bp++] = 0; - gex_prime.copy(exchangeBuf, bp, idx_gex_prime); // p - bp += len_gex_prime - (gex_prime[idx_gex_prime] & 0x80 ? 1 : 0); - - exchangeBuf.writeUInt32BE(len_gex_gen, bp, true); - bp += 4; - if (gex_gen[idx_gex_gen] & 0x80) - exchangeBuf[bp++] = 0; - gex_gen.copy(exchangeBuf, bp, idx_gex_gen); // g - bp += len_gex_gen - (gex_gen[idx_gex_gen] & 0x80 ? 1 : 0); - } - - exchangeBuf.writeUInt32BE(len_pubkey, bp, true); - bp += 4; - if (e[0] & 0x80) - exchangeBuf[bp++] = 0; - e.copy(exchangeBuf, bp); // e - bp += len_pubkey - (e[0] & 0x80 ? 1 : 0); - - exchangeBuf.writeUInt32BE(len_spubkey, bp, true); - bp += 4; - if (outstate.pubkey[idx_spubkey] & 0x80) - exchangeBuf[bp++] = 0; - outstate.pubkey.copy(exchangeBuf, bp, idx_spubkey); // f - bp += len_spubkey - (outstate.pubkey[idx_spubkey] & 0x80 ? 1 : 0); - - exchangeBuf.writeUInt32BE(len_secret, bp, true); - bp += 4; - if (secret[idx_secret] & 0x80) - exchangeBuf[bp++] = 0; - secret.copy(exchangeBuf, bp, idx_secret); // K - - outstate.exchangeHash = hash.update(exchangeBuf).digest(); // H - - if (outstate.sessionId === undefined) - outstate.sessionId = outstate.exchangeHash; - outstate.kexsecret = secret; - - var signAlgo; - switch (hostkeyAlgo) { - case 'ssh-rsa': - signAlgo = 'RSA-SHA1'; - break; - case 'ssh-dss': - signAlgo = 'DSA-SHA1'; - break; - case 'ecdsa-sha2-nistp256': - signAlgo = 'sha256'; - break; - case 'ecdsa-sha2-nistp384': - signAlgo = 'sha384'; - break; - case 'ecdsa-sha2-nistp521': - signAlgo = 'sha512'; - break; - } - var signer = crypto.createSign(signAlgo); - var signature; - signer.update(outstate.exchangeHash); - signature = trySign(signer, privateKey); - if (signature instanceof Error) { - signature.message = 'Error while signing data with host key (' - + hostkeyAlgo + '): ' - + signature.message; - signature.level = 'handshake'; - self.emit('error', signature); - self.disconnect(DISCONNECT_REASON.KEY_EXCHANGE_FAILED); - return false; - } - - if (signAlgo === 'DSA-SHA1') { - signature = DSASigBERToBare(signature); - } else if (signAlgo !== 'RSA-SHA1') { - // ECDSA - signature = ECDSASigASN1ToSSH(signature); - } - - /* - byte SSH_MSG_KEXDH_REPLY - string server public host key and certificates (K_S) - mpint f - string signature of H - */ - - var siglen = 4 + hostkeyAlgo.length + 4 + signature.length; - var buf = new Buffer(1 - + 4 + len_hostkey - + 4 + len_spubkey - + 4 + siglen); - - bp = 0; - buf[bp] = (!isGEX ? MESSAGE.KEXDH_REPLY : MESSAGE.KEXDH_GEX_REPLY); - ++bp; - - buf.writeUInt32BE(len_hostkey, bp, true); - bp += 4; - hostkey.copy(buf, bp); // K_S - bp += len_hostkey; - - buf.writeUInt32BE(len_spubkey, bp, true); - bp += 4; - if (outstate.pubkey[idx_spubkey] & 0x80) - buf[bp++] = 0; - outstate.pubkey.copy(buf, bp, idx_spubkey); // f - bp += len_spubkey - (outstate.pubkey[idx_spubkey] & 0x80 ? 1 : 0); - - buf.writeUInt32BE(siglen, bp, true); - bp += 4; - buf.writeUInt32BE(hostkeyAlgo.length, bp, true); - bp += 4; - buf.write(hostkeyAlgo, bp, hostkeyAlgo.length, 'ascii'); - bp += hostkeyAlgo.length; - buf.writeUInt32BE(signature.length, bp, true); - bp += 4; - signature.copy(buf, bp); - - state.incoming.expectedPacket = 'NEWKEYS'; - - if (isGEX) - self.debug('DEBUG: Outgoing: Writing KEXDH_GEX_REPLY'); - else if (state.kexdh !== 'group') - self.debug('DEBUG: Outgoing: Writing KEXECDH_REPLY'); - else - self.debug('DEBUG: Outgoing: Writing KEXDH_REPLY'); - send(self, buf, undefined, true); - - outstate.sentNEWKEYS = true; - self.debug('DEBUG: Outgoing: Writing NEWKEYS'); - return send(self, NEWKEYS_PACKET, undefined, true); -} - -function KEXDH_GEX_REQ(self) { // Client - self._state.incoming.expectedPacket = 'KEXDH_GEX_GROUP'; - - self.debug('DEBUG: Outgoing: Writing KEXDH_GEX_REQUEST'); - return send(self, KEXDH_GEX_REQ_PACKET, undefined, true); -} - -function send(self, payload, cb, bypass) { - var state = self._state; - - if (!state) - return false; - - var outstate = state.outgoing; - if (outstate.status === OUT_REKEYING && !bypass) { - if (typeof cb === 'function') - outstate.rekeyQueue.push([payload, cb]); - else - outstate.rekeyQueue.push(payload); - return false; - } else if (self._readableState.ended || self._writableState.ended) - return false; - - var compress = outstate.compress.instance; - if (compress) { - compress.write(payload); - compress.flush(Z_PARTIAL_FLUSH, function() { - if (self._readableState.ended || self._writableState.ended) - return; - send_(self, compress.read(), cb); - }); - return true; - } else - return send_(self, payload, cb); -} - -function send_(self, payload, cb) { - // TODO: Implement length checks - - var state = self._state; - var outstate = state.outgoing; - var encrypt = outstate.encrypt; - var hmac = outstate.hmac; - var pktLen; - var padLen; - var buf; - var mac; - var ret; - - pktLen = payload.length + 9; - - if (encrypt.instance !== false && encrypt.isGCM) { - var ptlen = 1 + payload.length + 4 /* Must have at least 4 bytes padding*/; - while ((ptlen % encrypt.size) !== 0) - ++ptlen; - padLen = ptlen - 1 - payload.length; - pktLen = 4 + ptlen; - } else { - pktLen += ((encrypt.size - 1) * pktLen) % encrypt.size; - padLen = pktLen - payload.length - 5; - } - - buf = new Buffer(pktLen); - - buf.writeUInt32BE(pktLen - 4, 0, true); - buf[4] = padLen; - payload.copy(buf, 5); - - var padBytes = crypto.randomBytes(padLen); - padBytes.copy(buf, 5 + payload.length); - - if (hmac.type !== false && hmac.key) { - mac = crypto.createHmac(SSH_TO_OPENSSL[hmac.type], hmac.key); - outstate.bufSeqno.writeUInt32BE(outstate.seqno, 0, true); - mac.update(outstate.bufSeqno); - mac.update(buf); - mac = mac.digest(); - if (mac.length > outstate.hmac.size) - mac = mac.slice(0, outstate.hmac.size); - } - - var nb = 0; - var encData; - - if (encrypt.instance !== false) { - if (encrypt.isGCM) { - var encrypter = crypto.createCipheriv(SSH_TO_OPENSSL[encrypt.type], - encrypt.key, - encrypt.iv); - encrypter.setAutoPadding(false); - - var lenbuf = buf.slice(0, 4); - - encrypter.setAAD(lenbuf); - self.push(lenbuf); - nb += lenbuf; - - encData = encrypter.update(buf.slice(4)); - self.push(encData); - nb += encData.length; - - var final = encrypter.final(); - if (final.length) { - self.push(final); - nb += final.length; - } - - var authTag = encrypter.getAuthTag(); - ret = self.push(authTag); - nb += authTag.length; - - iv_inc(encrypt.iv); - } else { - encData = encrypt.instance.update(buf); - self.push(encData); - nb += encData.length; - - ret = self.push(mac); - nb += mac.length; - } - } else { - ret = self.push(buf); - nb = buf.length; - } - - self.bytesSent += nb; - - if (++outstate.seqno > MAX_SEQNO) - outstate.seqno = 0; - - cb && cb(); - - return ret; -} - -function randBytes(n, cb) { - crypto.randomBytes(n, function retry(err, buf) { - if (err) - return crypto.randomBytes(n, retry); - cb && cb(buf); - }); -} - -function trySign(sig, key) { - try { - return sig.sign(key); - } catch (err) { - return err; - } -} - -function tryComputeSecret(dh, e) { - try { - return dh.computeSecret(e); - } catch (err) { - return err; - } -} - -module.exports = SSH2Stream; -module.exports._send = send; diff --git a/reverse_engineering/node_modules/ssh2-streams/lib/utils.js b/reverse_engineering/node_modules/ssh2-streams/lib/utils.js deleted file mode 100644 index fdb945e..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/lib/utils.js +++ /dev/null @@ -1,817 +0,0 @@ -var crypto = require('crypto'); - -var Ber = require('asn1').Ber; -var BigInteger = require('./jsbn'); // only for converting PPK -> OpenSSL format - -var SSH_TO_OPENSSL = require('./constants').SSH_TO_OPENSSL; - -var RE_STREAM = /^arcfour/i; -var RE_KEY_LEN = /(.{64})/g; -// XXX the value of 2400 from dropbear is only for certain strings, not all -// strings. for example the list strings used during handshakes -var MAX_STRING_LEN = Infinity;//2400; // taken from dropbear -var PPK_IV = new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - -module.exports = { - iv_inc: iv_inc, - isStreamCipher: isStreamCipher, - readInt: readInt, - readString: readString, - parseKey: require('./keyParser'), - genPublicKey: genPublicKey, - convertPPKPrivate: convertPPKPrivate, - verifyPPKMAC: verifyPPKMAC, - decryptKey: decryptKey, - DSASigBERToBare: DSASigBERToBare, - DSASigBareToBER: DSASigBareToBER, - ECDSASigASN1ToSSH: ECDSASigASN1ToSSH, - ECDSASigSSHToASN1: ECDSASigSSHToASN1, - RSAKeySSHToASN1: RSAKeySSHToASN1, - DSAKeySSHToASN1: DSAKeySSHToASN1, - ECDSAKeySSHToASN1: ECDSAKeySSHToASN1 -}; - -function iv_inc(iv) { - var n = 12; - var c = 0; - do { - --n; - c = iv[n]; - if (c === 255) - iv[n] = 0; - else { - iv[n] = ++c; - return; - } - } while (n > 4); -} - -function isStreamCipher(name) { - return RE_STREAM.test(name); -} - -function readInt(buffer, start, stream, cb) { - var bufferLen = buffer.length; - if (start < 0 || start >= bufferLen || (bufferLen - start) < 4) { - stream && stream._cleanup(cb); - return false; - } - - return buffer.readUInt32BE(start, true); -} - -function DSASigBERToBare(signature) { - if (signature.length <= 40) - return signature; - // This is a quick and dirty way to get from BER encoded r and s that - // OpenSSL gives us, to just the bare values back to back (40 bytes - // total) like OpenSSH (and possibly others) are expecting - var asnReader = new Ber.Reader(signature); - asnReader.readSequence(); - var r = asnReader.readString(Ber.Integer, true); - var s = asnReader.readString(Ber.Integer, true); - var rOffset = 0; - var sOffset = 0; - if (r.length < 20) { - var rNew = new Buffer(20); - r.copy(rNew, 1); - r = rNew; - r[0] = 0; - } - if (s.length < 20) { - var sNew = new Buffer(20); - s.copy(sNew, 1); - s = sNew; - s[0] = 0; - } - if (r.length > 20 && r[0] === 0x00) - rOffset = 1; - if (s.length > 20 && s[0] === 0x00) - sOffset = 1; - var newSig = new Buffer((r.length - rOffset) + (s.length - sOffset)); - r.copy(newSig, 0, rOffset); - s.copy(newSig, r.length - rOffset, sOffset); - return newSig; -} - -function DSASigBareToBER(signature) { - if (signature.length > 40) - return signature; - // Change bare signature r and s values to ASN.1 BER values for OpenSSL - var asnWriter = new Ber.Writer(); - asnWriter.startSequence(); - var r = signature.slice(0, 20); - var s = signature.slice(20); - if (r[0] & 0x80) { - var rNew = new Buffer(21); - rNew[0] = 0x00; - r.copy(rNew, 1); - r = rNew; - } else if (r[0] === 0x00 && !(r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] & 0x80) { - var sNew = new Buffer(21); - sNew[0] = 0x00; - s.copy(sNew, 1); - s = sNew; - } else if (s[0] === 0x00 && !(s[1] & 0x80)) { - s = s.slice(1); - } - asnWriter.writeBuffer(r, Ber.Integer); - asnWriter.writeBuffer(s, Ber.Integer); - asnWriter.endSequence(); - return asnWriter.buffer; -} - -function ECDSASigASN1ToSSH(signature) { - if (signature[0] === 0x00) - return signature; - // Convert SSH signature parameters to ASN.1 BER values for OpenSSL - var asnReader = new Ber.Reader(signature); - asnReader.readSequence(); - var r = asnReader.readString(Ber.Integer, true); - var s = asnReader.readString(Ber.Integer, true); - if (r === null || s === null) - throw new Error('Invalid signature'); - var newSig = new Buffer(4 + r.length + 4 + s.length); - newSig.writeUInt32BE(r.length, 0, true); - r.copy(newSig, 4); - newSig.writeUInt32BE(s.length, 4 + r.length, true); - s.copy(newSig, 4 + 4 + r.length); - return newSig; -} - -function ECDSASigSSHToASN1(signature, self, callback) { - // Convert SSH signature parameters to ASN.1 BER values for OpenSSL - var r = readString(signature, 0, self, callback); - if (r === false) - return false; - var s = readString(signature, signature._pos, self, callback); - if (s === false) - return false; - - var asnWriter = new Ber.Writer(); - asnWriter.startSequence(); - asnWriter.writeBuffer(r, Ber.Integer); - asnWriter.writeBuffer(s, Ber.Integer); - asnWriter.endSequence(); - return asnWriter.buffer; -} - -function RSAKeySSHToASN1(key, self, callback) { - // Convert SSH key parameters to ASN.1 BER values for OpenSSL - var e = readString(key, key._pos, self, callback); - if (e === false) - return false; - var n = readString(key, key._pos, self, callback); - if (n === false) - return false; - - var asnWriter = new Ber.Writer(); - asnWriter.startSequence(); - // algorithm - asnWriter.startSequence(); - asnWriter.writeOID('1.2.840.113549.1.1.1'); // rsaEncryption - // algorithm parameters (RSA has none) - asnWriter.writeNull(); - asnWriter.endSequence(); - - // subjectPublicKey - asnWriter.startSequence(Ber.BitString); - asnWriter.writeByte(0x00); - asnWriter.startSequence(); - asnWriter.writeBuffer(n, Ber.Integer); - asnWriter.writeBuffer(e, Ber.Integer); - asnWriter.endSequence(); - asnWriter.endSequence(); - asnWriter.endSequence(); - return asnWriter.buffer; -} - -function DSAKeySSHToASN1(key, self, callback) { - // Convert SSH key parameters to ASN.1 BER values for OpenSSL - var p = readString(key, key._pos, self, callback); - if (p === false) - return false; - var q = readString(key, key._pos, self, callback); - if (q === false) - return false; - var g = readString(key, key._pos, self, callback); - if (g === false) - return false; - var y = readString(key, key._pos, self, callback); - if (y === false) - return false; - - var asnWriter = new Ber.Writer(); - asnWriter.startSequence(); - // algorithm - asnWriter.startSequence(); - asnWriter.writeOID('1.2.840.10040.4.1'); // id-dsa - // algorithm parameters - asnWriter.startSequence(); - asnWriter.writeBuffer(p, Ber.Integer); - asnWriter.writeBuffer(q, Ber.Integer); - asnWriter.writeBuffer(g, Ber.Integer); - asnWriter.endSequence(); - asnWriter.endSequence(); - - // subjectPublicKey - asnWriter.startSequence(Ber.BitString); - asnWriter.writeByte(0x00); - asnWriter.writeBuffer(y, Ber.Integer); - asnWriter.endSequence(); - asnWriter.endSequence(); - return asnWriter.buffer; -} - -function ECDSAKeySSHToASN1(key, self, callback) { - // Convert SSH key parameters to ASN.1 BER values for OpenSSL - var curve = readString(key, key._pos, self, callback); - if (curve === false) - return false; - var Q = readString(key, key._pos, self, callback); - if (Q === false) - return false; - - var ecCurveOID; - switch (curve.toString('ascii')) { - case 'nistp256': - // prime256v1/secp256r1 - ecCurveOID = '1.2.840.10045.3.1.7'; - break; - case 'nistp384': - // secp384r1 - ecCurveOID = '1.3.132.0.34'; - break; - case 'nistp521': - // secp521r1 - ecCurveOID = '1.3.132.0.35'; - break; - default: - return false; - } - var asnWriter = new Ber.Writer(); - asnWriter.startSequence(); - // algorithm - asnWriter.startSequence(); - asnWriter.writeOID('1.2.840.10045.2.1'); // id-ecPublicKey - // algorithm parameters (namedCurve) - asnWriter.writeOID(ecCurveOID); - asnWriter.endSequence(); - - // subjectPublicKey - asnWriter.startSequence(Ber.BitString); - asnWriter.writeByte(0x00); - // XXX: hack to write a raw buffer without a tag -- yuck - asnWriter._ensure(Q.length); - Q.copy(asnWriter._buf, asnWriter._offset, 0, Q.length); - asnWriter._offset += Q.length; - // end hack - asnWriter.endSequence(); - asnWriter.endSequence(); - return asnWriter.buffer; -} - -function decryptKey(keyInfo, passphrase) { - if (keyInfo._decrypted || !keyInfo.encryption) - return; - - var keylen = 0; - var key; - var iv; - var dc; - - keyInfo.encryption = (SSH_TO_OPENSSL[keyInfo.encryption] - || keyInfo.encryption); - switch (keyInfo.encryption) { - case 'aes-256-cbc': - case 'aes-256-ctr': - keylen = 32; - break; - case 'des-ede3-cbc': - case 'des-ede3': - case 'aes-192-cbc': - case 'aes-192-ctr': - keylen = 24; - break; - case 'aes-128-cbc': - case 'aes-128-ctr': - case 'cast-cbc': - case 'bf-cbc': - keylen = 16; - break; - default: - throw new Error('Unsupported cipher for encrypted key: ' - + keyInfo.encryption); - } - - if (keyInfo.ppk) { - iv = PPK_IV; - - key = Buffer.concat([ - crypto.createHash('sha1') - .update('\x00\x00\x00\x00' + passphrase, 'utf8') - .digest(), - crypto.createHash('sha1') - .update('\x00\x00\x00\x01' + passphrase, 'utf8') - .digest() - ]); - key = key.slice(0, keylen); - } else { - iv = new Buffer(keyInfo.extra[0], 'hex'); - - key = crypto.createHash('md5') - .update(passphrase, 'utf8') - .update(iv.slice(0, 8)) - .digest(); - - while (keylen > key.length) { - key = Buffer.concat([ - key, - (crypto.createHash('md5') - .update(key) - .update(passphrase, 'utf8') - .update(iv) - .digest()).slice(0, 8) - ]); - } - if (key.length > keylen) - key = key.slice(0, keylen); - } - - dc = crypto.createDecipheriv(keyInfo.encryption, key, iv); - dc.setAutoPadding(false); - keyInfo.private = Buffer.concat([ dc.update(keyInfo.private), dc.final() ]); - - keyInfo._decrypted = true; - - if (keyInfo.privateOrig) { - // Update our original base64-encoded version of the private key - var orig = keyInfo.privateOrig.toString('utf8'); - var newOrig = /^(.+(?:\r\n|\n))/.exec(orig)[1]; - var b64key = keyInfo.private.toString('base64'); - - newOrig += b64key.match(/.{1,70}/g).join('\n'); - newOrig += /((?:\r\n|\n).+)$/.exec(orig)[1]; - - keyInfo.privateOrig = newOrig; - } else if (keyInfo.ppk) { - var valid = verifyPPKMAC(keyInfo, passphrase, keyInfo.private); - if (!valid) - throw new Error('PPK MAC mismatch'); - // Automatically convert private key data to OpenSSL format - // (including PEM) - convertPPKPrivate(keyInfo); - } - - // Fill in full key type - // TODO: make DRY, we do this also in keyParser - if (keyInfo.type !== 'ec') { - keyInfo.fulltype = 'ssh-' + keyInfo.type; - } else { - // ECDSA - var asnReader = new Ber.Reader(keyInfo.private); - asnReader.readSequence(); - asnReader.readInt(); - asnReader.readString(Ber.OctetString, true); - asnReader.readByte(); // Skip "complex" context type byte - var offset = asnReader.readLength(); // Skip context length - if (offset !== null) { - asnReader._offset = offset; - switch (asnReader.readOID()) { - case '1.2.840.10045.3.1.7': - // prime256v1/secp256r1 - keyInfo.fulltype = 'ecdsa-sha2-nistp256'; - break; - case '1.3.132.0.34': - // secp384r1 - keyInfo.fulltype = 'ecdsa-sha2-nistp384'; - break; - case '1.3.132.0.35': - // secp521r1 - keyInfo.fulltype = 'ecdsa-sha2-nistp521'; - break; - } - } - if (keyInfo.fulltype === undefined) - return new Error('Unsupported EC private key type'); - } -} - -function genPublicKey(keyInfo) { - var publicKey; - var i; - - // RSA - var n; - var e; - - // DSA - var p; - var q; - var g; - var y; - - // ECDSA - var d; - var Q; - var ecCurveOID; - var ecCurveName; - - if (keyInfo.private) { - // parsing private key in ASN.1 format in order to generate a public key - var privKey = keyInfo.private; - var asnReader = new Ber.Reader(privKey); - var errMsg; - - if (asnReader.readSequence() === null) { - errMsg = 'Malformed private key (expected sequence)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - // version (ignored) - if (asnReader.readInt() === null) { - errMsg = 'Malformed private key (expected version)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - if (keyInfo.type === 'rsa') { - // modulus (n) -- integer - n = asnReader.readString(Ber.Integer, true); - if (n === null) { - errMsg = 'Malformed private key (expected RSA n value)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - // public exponent (e) -- integer - e = asnReader.readString(Ber.Integer, true); - if (e === null) { - errMsg = 'Malformed private key (expected RSA e value)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - publicKey = new Buffer(4 + 7 // ssh-rsa - + 4 + n.length - + 4 + e.length); - - publicKey.writeUInt32BE(7, 0, true); - publicKey.write('ssh-rsa', 4, 7, 'ascii'); - - i = 4 + 7; - publicKey.writeUInt32BE(e.length, i, true); - e.copy(publicKey, i += 4); - - publicKey.writeUInt32BE(n.length, i += e.length, true); - n.copy(publicKey, i += 4); - } else if (keyInfo.type === 'dss') { // DSA - // prime (p) -- integer - p = asnReader.readString(Ber.Integer, true); - if (p === null) { - errMsg = 'Malformed private key (expected DSA p value)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - // group order (q) -- integer - q = asnReader.readString(Ber.Integer, true); - if (q === null) { - errMsg = 'Malformed private key (expected DSA q value)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - // group generator (g) -- integer - g = asnReader.readString(Ber.Integer, true); - if (g === null) { - errMsg = 'Malformed private key (expected DSA g value)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - // public key value (y) -- integer - y = asnReader.readString(Ber.Integer, true); - if (y === null) { - errMsg = 'Malformed private key (expected DSA y value)'; - if (keyInfo._decrypted) - errMsg += '. Bad passphrase?'; - throw new Error(errMsg); - } - - publicKey = new Buffer(4 + 7 // ssh-dss - + 4 + p.length - + 4 + q.length - + 4 + g.length - + 4 + y.length); - - publicKey.writeUInt32BE(7, 0, true); - publicKey.write('ssh-dss', 4, 7, 'ascii'); - - i = 4 + 7; - publicKey.writeUInt32BE(p.length, i, true); - p.copy(publicKey, i += 4); - - publicKey.writeUInt32BE(q.length, i += p.length, true); - q.copy(publicKey, i += 4); - - publicKey.writeUInt32BE(g.length, i += q.length, true); - g.copy(publicKey, i += 4); - - publicKey.writeUInt32BE(y.length, i += g.length, true); - y.copy(publicKey, i += 4); - } else { // ECDSA - d = asnReader.readString(Ber.OctetString, true); - if (d === null) - throw new Error('Malformed private key (expected ECDSA private key)'); - asnReader.readByte(); // Skip "complex" context type byte - var offset = asnReader.readLength(); // Skip context length - if (offset === null) - throw new Error('Malformed private key (expected ECDSA context value)'); - asnReader._offset = offset; - ecCurveOID = asnReader.readOID(); - if (ecCurveOID === null) - throw new Error('Malformed private key (expected ECDSA curve)'); - var tempECDH; - switch (ecCurveOID) { - case '1.2.840.10045.3.1.7': - // prime256v1/secp256r1 - keyInfo.curve = ecCurveName = 'nistp256'; - tempECDH = crypto.createECDH('prime256v1'); - break; - case '1.3.132.0.34': - // secp384r1 - keyInfo.curve = ecCurveName = 'nistp384'; - tempECDH = crypto.createECDH('secp384r1'); - break; - case '1.3.132.0.35': - // secp521r1 - keyInfo.curve = ecCurveName = 'nistp521'; - tempECDH = crypto.createECDH('secp521r1'); - break; - default: - throw new Error('Malformed private key (unsupported EC curve)'); - } - tempECDH.setPrivateKey(d); - Q = tempECDH.getPublicKey(); - - publicKey = new Buffer(4 + 19 // ecdsa-sha2- - + 4 + 8 // - + 4 + Q.length); - - publicKey.writeUInt32BE(19, 0, true); - publicKey.write('ecdsa-sha2-' + ecCurveName, 4, 19, 'ascii'); - - publicKey.writeUInt32BE(8, 23, true); - publicKey.write(ecCurveName, 27, 8, 'ascii'); - - publicKey.writeUInt32BE(Q.length, 35, true); - Q.copy(publicKey, 39); - } - } else if (keyInfo.public) { - publicKey = keyInfo.public; - if (keyInfo.type === 'ec') { - // TODO: support adding ecdsa-* prefix - ecCurveName = keyInfo.curve; - } else if (publicKey[0] !== 0 - // check for missing ssh-{dsa,rsa} prefix - || publicKey[1] !== 0 - || publicKey[2] !== 0 - || publicKey[3] !== 7 - || publicKey[4] !== 115 - || publicKey[5] !== 115 - || publicKey[6] !== 104 - || publicKey[7] !== 45 - || ((publicKey[8] !== 114 - || publicKey[9] !== 115 - || publicKey[10] !== 97) - && - ((publicKey[8] !== 100 - || publicKey[9] !== 115 - || publicKey[10] !== 115)))) { - var newPK = new Buffer(4 + 7 + publicKey.length); - publicKey.copy(newPK, 11); - newPK.writeUInt32BE(7, 0, true); - if (keyInfo.type === 'rsa') - newPK.write('ssh-rsa', 4, 7, 'ascii'); - else - newPK.write('ssh-dss', 4, 7, 'ascii'); - publicKey = newPK; - } - } else - throw new Error('Missing data generated by parseKey()'); - - // generate a public key format for use with OpenSSL - - i = 4 + 7; - - var fulltype; - var asn1KeyBuf; - if (keyInfo.type === 'rsa') { - fulltype = 'ssh-rsa'; - asn1KeyBuf = RSAKeySSHToASN1(publicKey.slice(4 + 7)); - } else if (keyInfo.type === 'dss') { - fulltype = 'ssh-dss'; - asn1KeyBuf = DSAKeySSHToASN1(publicKey.slice(4 + 7)); - } else { // ECDSA - fulltype = 'ecdsa-sha2-' + ecCurveName; - asn1KeyBuf = ECDSAKeySSHToASN1(publicKey.slice(4 + 19)); - } - - if (!asn1KeyBuf) - throw new Error('Invalid SSH-formatted public key'); - - var b64key = asn1KeyBuf.toString('base64').replace(RE_KEY_LEN, '$1\n'); - var fullkey = '-----BEGIN PUBLIC KEY-----\n' - + b64key - + (b64key[b64key.length - 1] === '\n' ? '' : '\n') - + '-----END PUBLIC KEY-----'; - - return { - type: keyInfo.type, - fulltype: fulltype, - curve: ecCurveName, - public: publicKey, - publicOrig: new Buffer(fullkey) - }; -} - -function verifyPPKMAC(keyInfo, passphrase, privateKey) { - if (keyInfo._macresult !== undefined) - return keyInfo._macresult; - else if (!keyInfo.ppk) - throw new Error("Key isn't a PPK"); - else if (!keyInfo.privateMAC) - throw new Error('Missing MAC'); - else if (!privateKey) - throw new Error('Missing raw private key data'); - else if (keyInfo.encryption && typeof passphrase !== 'string') - throw new Error('Missing passphrase for encrypted PPK'); - else if (keyInfo.encryption && !keyInfo._decrypted) - throw new Error('PPK must be decrypted before verifying MAC'); - - var mac = keyInfo.privateMAC; - var typelen = keyInfo.fulltype.length; - // encryption algorithm is converted at this point for use with OpenSSL, - // so we need to use the original value so that the MAC is calculated - // correctly - var enc = (keyInfo.encryption ? 'aes256-cbc' : 'none'); - var enclen = enc.length; - var commlen = Buffer.byteLength(keyInfo.comment); - var pub = keyInfo.public; - var publen = pub.length; - var privlen = privateKey.length; - var macdata = new Buffer(4 + typelen - + 4 + enclen - + 4 + commlen - + 4 + publen - + 4 + privlen); - var p = 0; - - macdata.writeUInt32BE(typelen, p, true); - macdata.write(keyInfo.fulltype, p += 4, typelen, 'ascii'); - macdata.writeUInt32BE(enclen, p += typelen, true); - macdata.write(enc, p += 4, enclen, 'ascii'); - macdata.writeUInt32BE(commlen, p += enclen, true); - macdata.write(keyInfo.comment, p += 4, commlen, 'utf8'); - macdata.writeUInt32BE(publen, p += commlen, true); - pub.copy(macdata, p += 4); - macdata.writeUInt32BE(privlen, p += publen, true); - privateKey.copy(macdata, p += 4); - - if (typeof passphrase !== 'string') - passphrase = ''; - - var mackey = crypto.createHash('sha1') - .update('putty-private-key-file-mac-key', 'ascii') - .update(passphrase, 'utf8') - .digest(); - - var calcMAC = crypto.createHmac('sha1', mackey) - .update(macdata) - .digest('hex'); - - return (keyInfo._macresult = (calcMAC === mac)); -} - -function convertPPKPrivate(keyInfo) { - if (!keyInfo.ppk || !keyInfo.public || !keyInfo.private) - throw new Error("Key isn't a PPK"); - else if (keyInfo._converted) - return false; - - var pub = keyInfo.public; - var priv = keyInfo.private; - var asnWriter = new Ber.Writer(); - var p; - var q; - - if (keyInfo.type === 'rsa') { - var e = readString(pub, 4 + 7); - var n = readString(pub, pub._pos); - var d = readString(priv, 0); - p = readString(priv, priv._pos); - q = readString(priv, priv._pos); - var iqmp = readString(priv, priv._pos); - var p1 = new BigInteger(p, 256); - var q1 = new BigInteger(q, 256); - var dmp1 = new BigInteger(d, 256); - var dmq1 = new BigInteger(d, 256); - - dmp1 = new Buffer(dmp1.mod(p1.subtract(BigInteger.ONE)).toByteArray()); - dmq1 = new Buffer(dmq1.mod(q1.subtract(BigInteger.ONE)).toByteArray()); - - asnWriter.startSequence(); - asnWriter.writeInt(0x00, Ber.Integer); - asnWriter.writeBuffer(n, Ber.Integer); - asnWriter.writeBuffer(e, Ber.Integer); - asnWriter.writeBuffer(d, Ber.Integer); - asnWriter.writeBuffer(p, Ber.Integer); - asnWriter.writeBuffer(q, Ber.Integer); - asnWriter.writeBuffer(dmp1, Ber.Integer); - asnWriter.writeBuffer(dmq1, Ber.Integer); - asnWriter.writeBuffer(iqmp, Ber.Integer); - asnWriter.endSequence(); - } else { - p = readString(pub, 4 + 7); - q = readString(pub, pub._pos); - var g = readString(pub, pub._pos); - var y = readString(pub, pub._pos); - var x = readString(priv, 0); - - asnWriter.startSequence(); - asnWriter.writeInt(0x00, Ber.Integer); - asnWriter.writeBuffer(p, Ber.Integer); - asnWriter.writeBuffer(q, Ber.Integer); - asnWriter.writeBuffer(g, Ber.Integer); - asnWriter.writeBuffer(y, Ber.Integer); - asnWriter.writeBuffer(x, Ber.Integer); - asnWriter.endSequence(); - } - - var b64key = asnWriter.buffer.toString('base64').replace(RE_KEY_LEN, '$1\n'); - var fullkey = '-----BEGIN ' - + (keyInfo.type === 'rsa' ? 'RSA' : 'DSA') - + ' PRIVATE KEY-----\n' - + b64key - + (b64key[b64key.length - 1] === '\n' ? '' : '\n') - + '-----END ' - + (keyInfo.type === 'rsa' ? 'RSA' : 'DSA') - + ' PRIVATE KEY-----'; - - keyInfo.private = asnWriter.buffer; - keyInfo.privateOrig = new Buffer(fullkey); - keyInfo._converted = true; - return true; -} - -function readString(buffer, start, encoding, stream, cb, maxLen) { - if (encoding && !Buffer.isBuffer(encoding) && typeof encoding !== 'string') { - if (typeof cb === 'number') - maxLen = cb; - cb = stream; - stream = encoding; - encoding = undefined; - } - - start || (start = 0); - var bufferLen = buffer.length; - var left = (bufferLen - start); - var len; - var end; - if (start < 0 || start >= bufferLen || left < 4) { - stream && stream._cleanup(cb); - return false; - } - - len = buffer.readUInt32BE(start, true); - if (len > (maxLen || MAX_STRING_LEN) || left < (4 + len)) { - stream && stream._cleanup(cb); - return false; - } - - start += 4; - end = start + len; - buffer._pos = end; - - if (encoding) { - if (Buffer.isBuffer(encoding)) { - buffer.copy(encoding, 0, start, end); - return encoding; - } else - return buffer.toString(encoding, start, end); - } else - return buffer.slice(start, end); -} - diff --git a/reverse_engineering/node_modules/ssh2-streams/package.json b/reverse_engineering/node_modules/ssh2-streams/package.json deleted file mode 100644 index c14e8bc..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ "name": "ssh2-streams", - "version": "0.1.20", - "author": "Brian White ", - "description": "SSH2 and SFTP(v3) client/server protocol streams for node.js", - "main": "./index", - "engines": { "node": ">=0.10.0" }, - "dependencies": { - "streamsearch": "~0.1.2", - "asn1": "~0.2.0", - "semver": "^5.1.0" - }, - "scripts": { - "test": "node test/test.js" - }, - "keywords": [ "ssh", "ssh2", "sftp", "secure", "protocol", "streams", "client", "server" ], - "licenses": [ { "type": "MIT", "url": "http://github.com/mscdex/ssh2-streams/raw/master/LICENSE" } ], - "repository" : { "type": "git", "url": "http://github.com/mscdex/ssh2-streams.git" } - -,"_resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.1.20.tgz" -,"_integrity": "sha1-URGNFUVV31Rp7h9n4M8efoosDjo=" -,"_from": "ssh2-streams@0.1.20" -} \ No newline at end of file diff --git a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa b/reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa deleted file mode 100644 index c7c09e1..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpgIBAAKCAQEAysX9gGx5CsLW3xHqOgnrbfCuXy1Y0OFpZBxWs6FNHxtqpxRD -Ii8vnWQw9Ltul5NhBb1QrS/3XlODu5rv8VWZy+ciXDaeaVYvzCR3fHmQyDXA+WLR -x8kkR4ZxHTQREj1yifGyHdZTMsMbSaW9Eh2+sgWIjZaBkLjF2NDT52HX0y+zr2WL -TYVCcYf9ugCJIfwXN4/SpR+cV3MSak+4HfFDRo7EwFbYL8QRpNZLVVas5SUpN3CR -e6u26zPNgcqSRmC81lA/e2t7qG1qvjFy9RgJpUJJsZan5yMYAob9p83Fo61ajLX1 -DeqpZPauEfe9e/4bkjVbU8gW/cgb9Ct6v+59fQIDAQABAoIBAQCUH6GZKKQbKk1Q -UoPptclXXFPkjvmsTJ1yVgk32wK9UIfOWUzZMeL0dHYWsLyO2Ugsqyi9+qYXL6ax -avMQNlnMy6Eb/4IkrKLp21G1ihArUKkRBBD+gn6QCTOkA57c1ipPflGA3kmUcVYD -rKC7FSNyY/xmgaVQFMniIlpJUf4Y9BjIKC2FSTGxtKx2AI7eBDjmiZ7Mkcinaf62 -5jl0AfV0/PgBb7AqhPWcmJp+/jWyZ3IrlPvMspEg6PfLnNzACKrh/Qorkhf3cLcn -aFJmnyRn4Zhx+scqoWq1NcYOfNyU+eAEofTu8TwvGVh0nx9C2vxwPftjDQlfh0kf -wGscN72BAoGBAOZs4u5ObnFf4pNbGfjhLhSf2vXATb9TYjr8vPc4xbviukYGPaNR -tP5d9oXHecFP37IeV6I0SmMmd0Sth56/RfRFD8Rirq3MjjKWvwwbJ1sd34n9cqN3 -goSWERfqPOzVMjxEPqq0wm/7Y61EU5Gt1ou8MOOS+lPx3LmpapSjSNutAoGBAOFH -bLZQUpLaUf7ijCU/yykRdpzBpwDDEgRqf7RLqS8p+tzI9z39KfNSxrVEqhWe7uuZ -3dl8EjrXhBK8FoCDAD6yrx35aUUeUJHZp/kFoXBdlHpGk8VvveTJMSqPS6KxKglB -JqINECpwHzasQSun2vhLsH6ikUUqnB8qkJYMNGMRAoGBAJ5wio1/4pMUclAOWUp3 -U18dF8rZItyGskmLFUgMgnIRkTGrAuD0wrYQ1/zez0pr6I2qLWm7+NY6UdIoW9N9 -A9XVUuUfUarxt2jznIPve908KkPQwO3DtDwEj9ZY2vGiGruz1T89sWCcg8pU6/2E -gbxtd1RT8MqdyL7kzgNMT0G1AoGBAMc1otOBKdPEjVeIPAfAZsXVNH8f268X0Lno -9y6W7W/Qfo54g/HkChGqNB8dLg5accoTURO93Fz+MUNj4b4YmcHXvnUSFV3Slcqz -nw7dRMoZZm/OM2QXEOPcacbJ2kduxM5UN3Z7eL0eUuvE3QhesYp5XARPe4ifSllh -CWQ2PKkRAoGBAMFANW/IxEH6H60yfJbY9t/0ggu4DoVI62rmv43n2dYsdNeaF1Fl -SbGoK16+6ERyjyJtqe0642LpgenrEcpJbXxr1qtG6gGRCJIcZ8gJDiVj4XW1d1cZ -eCNZLVlVOrBNRkKmXDD5Sd10m52tlBMfarvskgbJVvkRO6pSz3o8Q0B1 ------END RSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa_enc b/reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa_enc deleted file mode 100644 index ec0646c..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/id_rsa_enc +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,3E36D2FEB814842942EC58DA9722DB75 - -MBCl5tVBiTjZywjXSMPNnVcBzuAhZzLsvb/pPofnVNnx96CqBMAzaKxGu6Ls9UBu -ejGGOik+8EJHV7p7dj6GAf5srgBnFXVYQy69eoL4xl1IuKoSKOXicS70/QXuApzY -tBdwnqMz1y1tuWZ0q4iOZYQHqvNTvhH4s/rfm8/As7GwPi4NQ4FipsbOifKVIlJN -0+XQAZLBjD6D2BFbVBas2RyI/zT5NyFtFxEPlQwWjuajnDrdVFf59mkzHzQc8Jo1 -qjCv6bDHTW9EeoZeloqpAaYegmOYGynb8HQzmbEBoarXsOkwtaI38jXT3WOljaVJ -xuWV7xl181CsV4dgbyd948YKcHg3riRQiQwXXlKe4MTGwcQ3sybR4oFLzFIa6Ct2 -qbsyqvc+3tiBhOZtiAXgDdbzvXR+60aSTjduVp+52lF/m4l658Sleyx2hxQ3LEcc -lbuG27WIbLEATeqV9gaJ1jDtEyEtGNALAdIZF6YdND5tiTSqHd0n3yUMbZVdiQ5i -s5lSfWD38c3Is4hOdZlG9nMFoAGe7wnFmV+N5Cv3vnlFPFogoO4eVZS5S+ReAmas -syOelwKvVNNy0FzCoQ3URZWLQTKsZ7Wkl1ve9jJ5ZPox0p09A0gcykIB5oya9/OL -oTKDhoenoh0p3ttyQ7WbkUc9VwHNn+rX7N3v/Ui+NF8mnCfD/1UOzBhRY0LjDCfO -qT70wd63c4cSr0HCTDNrGtShztJD9gdzwIH6q/eNDjFk1S8KOrV/K6wQwWzULs+c -Ld/7xkELz+d60Ll5dVUHcSxOhYwBVY+GGC5ybOmSqr5+t1MDfLN0Q4d3x0X6LU2q -sL94x93XFY342x5NpjOusKISCaCx9eBXxCpi132IAfmB7kDZXpbe02aed0bNChUP -IM6eXFYVfPb5YZ3oXlWJ+e/E01dGPK2rHnAzOLH2DSmDZ7MWZW5hkRKQ4zU6/ECo -0K7uGLAdpCoC8FKWcE2Gm7fol5fmHes06SNC1wLyVHtv4g7kFfnfmNIVVy3lSP1f -WoHRL52lNOCR+E1N03djvyKoK46cKiJ9TcBrJXcMHSSjPvqLafS/AUK+FYjxlqyM -qXgATtt/n0h+VxjPm2+xZNVHC5fD5GHhoo3PhmapLpLNyDlhzJTy/iFtrmX6uht1 -4XDYmzzQyoRu6+1DQ7HPpwXZf84+QFGGfb/LTiLUF+pgCHOt41HdHEaU6eIHGEk0 -wfTfWG2pP/2wDUtX8KVAnikfIaa5KrC/ZuDV5pfp0Tk+Rjt2iv9+YuB7fPrvKF3Z -B7zgMuBG8FQZMFHvWsaDHE/vo8fivgeM0zVL0shigLuwL+p6EeanRdm5bRavF8M8 -XDtOjZt/id4UMQDuobawUVadTZhtGfFNfO9Wt16EAa6jhRBJ1A+FRGqFbJXV36ZV -zzx7edCzyCd0rcsZoi6Kz4NeDxm1lcGspBBhstUT5cbgQo91wAZCU1hpj/qsqygr -KK4NcNpDjYFc1azb/zRGe+zx1WzWhKAZR6HfMEoJwzyzTcwRmApbTEYqv+oYxC0+ -f/HNQaCH/UGDy4QEvMVaJRnjFv7oW6GpS7ob6POvi2esgYglwNJR1hN86W7kfOrF ------END RSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/ssh_host_rsa_key b/reverse_engineering/node_modules/ssh2-streams/test/fixtures/ssh_host_rsa_key deleted file mode 100644 index 9c2cc6f..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/ssh_host_rsa_key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC57UB/5H0M+t+mopksrltCCIXghryzofJjau+8tuMT9CG6ta3S -O9aKApJUUG/xtc88giVhB7HFABX/oob+jrkSthR8s/whULC8E+GhvOBjHydRUZIs -aPYOMBb42HcbOsgq3li/hwOcDk0vY00hZDKCum9BgvRAb7dPEkw2dmiCQQIDAQAB -AoGAMG+HOwoaLbR5aR64yrQNYBF6Vvii1iUdURr9o2r9kygpVUuZIcim5kMvPbnK -v+w+NaQt+q4XeJvCH1uG0W/69FwnphfaOVmCCUtsoJ6sU3fWr9x59MtKL2Llh8xR -50lz6R+eDXoYRDq245hG9BFn/bu0vtqQqx06mlZJcjaRocECQQDjdYFmr+DSww3x -VNx0G0DUkaQZZ+iqZiT3Zund2pcBB4aLiewOrqj0GFct4+YNzgxIXPejmS0eSokN -N2lC3NxZAkEA0UGjN5TG5/LEK3zcYtx2kpXryenrYORo1n2L/WPMZ0mjLQyd4LJr -ibfgVUfwX/kV3vgGYLwjpgcaTiMsecv4KQJAYMmMgZSPdz+WvD1e/WznXkyG5mSn -xXJngnrhQw0TulVodBIBR5IcxJli510VdIRcB6K/oXa5ky0mOmB8wv3WKQJBAKEF -PxE//KbzWhyUogm4180IbD4dMDCI0ltqlFRRfTJlqZi6wqnq4XFB+u/kwYU4aKoA -dPfvDgduI8HIsyqt17ECQDI/HC8PiYsDIOyVpQuQdIAsbGmoavK7X1MVEWR2nj9t -7BbUVFSnVKynL4TWIJZ6xP8WQwkDBQc5WjognHDaUTQ= ------END RSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-durability-ssh.js b/reverse_engineering/node_modules/ssh2-streams/test/test-durability-ssh.js deleted file mode 100644 index 853656b..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-durability-ssh.js +++ /dev/null @@ -1,169 +0,0 @@ -var SSH2Stream = require('../lib/ssh'); - -var fs = require('fs'); -var path = require('path'); -var inspect = require('util').inspect; -var inherits = require('util').inherits; -var TransformStream = require('stream').Transform; -var assert = require('assert'); - -var t = -1; -var group = path.basename(__filename, '.js') + '/'; -var fixturesdir = path.join(__dirname, 'fixtures'); - -var HOST_KEY_RSA = fs.readFileSync(path.join(fixturesdir, 'ssh_host_rsa_key')); -var SERVER_CONFIG = { - server: true, - hostKeys: { 'ssh-rsa': HOST_KEY_RSA } -}; - -function SimpleStream() { - TransformStream.call(this); - this.buffer = ''; -} -inherits(SimpleStream, TransformStream); -SimpleStream.prototype._transform = function(chunk, encoding, cb) { - this.buffer += chunk.toString('binary'); - cb(); -}; - -var tests = [ - { run: function() { - var what = this.what; - var serverError = false; - var server = new SSH2Stream(SERVER_CONFIG); - var client = new SimpleStream(); - - client.pipe(server).pipe(client); - - server.on('error', function(err) { - serverError = err; - assert(err.message === 'Protocol version not supported', - makeMsg(what, 'Wrong error message')); - }).on('end', function() { - assert(client.buffer === server.config.ident + '\r\n', - makeMsg(what, 'Wrong server ident: ' + inspect(client.buffer))); - assert(serverError, makeMsg(what, 'Expected server error')); - next(); - }); - - client.push('SSH-1.0-aaa\r\n'); - }, - what: 'Incompatible client SSH protocol version' - }, - { run: function() { - var what = this.what; - var serverError = false; - var server = new SSH2Stream(SERVER_CONFIG); - var client = new SimpleStream(); - - client.pipe(server).pipe(client); - - server.on('error', function(err) { - serverError = err; - assert(err.message === 'Bad identification start', - makeMsg(what, 'Wrong error message')); - }).on('end', function() { - assert(client.buffer === server.config.ident + '\r\n', - makeMsg(what, 'Wrong server ident: ' + inspect(client.buffer))); - assert(serverError, makeMsg(what, 'Expected server error')); - next(); - }); - client.push('LOL-2.0-asdf\r\n'); - }, - what: 'Malformed client protocol identification' - }, - { run: function() { - var what = this.what; - var serverError = false; - var server = new SSH2Stream(SERVER_CONFIG); - var client = new SimpleStream(); - - client.pipe(server).pipe(client); - - server.on('error', function(err) { - serverError = err; - assert(err.message === 'Max identification string size exceeded', - makeMsg(what, 'Wrong error message')); - }).on('end', function() { - assert(client.buffer === server.config.ident + '\r\n', - makeMsg(what, 'Wrong server ident: ' + inspect(client.buffer))); - assert(serverError, makeMsg(what, 'Expected server error')); - next(); - }); - var ident = 'SSH-2.0-'; - for (var i = 0; i < 30; ++i) - ident += 'foobarbaz'; - ident += '\r\n'; - client.push(ident); - }, - what: 'SSH client protocol identification too long (> 255 characters)' - }, - { run: function() { - var what = this.what; - var serverError = false; - var server = new SSH2Stream(SERVER_CONFIG); - var client = new SimpleStream(); - - client.pipe(server).pipe(client); - - server.on('error', function(err) { - serverError = err; - assert(err.message === 'Bad packet length', - makeMsg(what, 'Wrong error message')); - }).on('end', function() { - assert(client.buffer.length, makeMsg(what, 'Expected server data')); - assert(serverError, makeMsg(what, 'Expected server error')); - next(); - }); - client.push('SSH-2.0-asdf\r\n'); - // 500,000 byte packet_length - client.push(new Buffer([0x00, 0x07, 0xA1, 0x20, 0x00, 0x00, 0x00, 0x00])); - }, - what: 'Bad packet length (max)' - }, - { run: function() { - var what = this.what; - var serverError = false; - var server = new SSH2Stream(SERVER_CONFIG); - var client = new SimpleStream(); - - client.pipe(server).pipe(client); - - server.on('error', function(err) { - serverError = err; - assert(err.message === 'Bad packet length', - makeMsg(what, 'Wrong error message')); - }).on('end', function() { - assert(client.buffer.length, makeMsg(what, 'Expected server data')); - assert(serverError, makeMsg(what, 'Expected server error')); - next(); - }); - client.push('SSH-2.0-asdf\r\n'); - client.push(new Buffer([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00])); - }, - what: 'Bad packet length (min)' - }, -]; - -function next() { - if (Array.isArray(process._events.exit)) - process._events.exit = process._events.exit[1]; - if (++t === tests.length) - return; - - var v = tests[t]; - v.run.call(v); -} - -function makeMsg(what, msg) { - return '[' + group + what + ']: ' + msg; -} - -process.once('exit', function() { - assert(t === tests.length, - makeMsg('_exit', - 'Only finished ' + t + '/' + tests.length + ' tests')); -}); - -next(); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-kexdh.js b/reverse_engineering/node_modules/ssh2-streams/test/test-kexdh.js deleted file mode 100644 index 5544168..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-kexdh.js +++ /dev/null @@ -1,66 +0,0 @@ -var SSH2Stream = require('../lib/ssh'); -var parseKey = require('../lib/utils').parseKey; -var genPubKey = require('../lib/utils').genPublicKey; -var MESSAGE = require('../lib/constants').MESSAGE; - -var assert = require('assert'); -var fs = require('fs'); - -var SERVER_KEY = fs.readFileSync(__dirname + '/fixtures/ssh_host_rsa_key'); -var SERVER_KEY_PRV = parseKey(SERVER_KEY); -var SERVER_KEY_PUB = genPubKey(SERVER_KEY_PRV); - -var server = new SSH2Stream({ - server: true, - hostKeys: { - 'ssh-rsa': { - privateKey: SERVER_KEY_PRV, - publicKey: SERVER_KEY_PUB, - } - } -}); -var client = new SSH2Stream(); -var cliError; -var srvError; - -server.on('error', function(err) { - assert(err); - assert(/unexpected/.test(err.message)); - assert(!srvError); - srvError = err; -}); - -// Removed 'KEXDH_REPLY' listeners as it causes client to send 'NEWKEYS' which -// changes server's state. -client.removeAllListeners('KEXDH_REPLY'); -// Removed 'NEWKEYS' listeners as server sends 'NEWKEYS' after receiving -// 'KEXDH_INIT' which causes errors on client if 'NEWKEYS' is processed -// without processing 'KEXDH_REPLY' -client.removeAllListeners('NEWKEYS'); -// Added 'KEXDH_REPLY' which violates protocol and re-sends 'KEXDH_INIT' -// packet -client.on('KEXDH_REPLY', function(info) { - var state = client._state; - var outstate = state.outgoing; - var buf = new Buffer(1 + 4 + outstate.pubkey.length); - buf[0] = MESSAGE.KEXDH_INIT; - buf.writeUInt32BE(outstate.pubkey.length, 1, true); - outstate.pubkey.copy(buf, 5); - SSH2Stream._send(client, buf, undefined, true); -}); -client.on('error', function(err) { - assert(!cliError); - assert(err); - assert.equal( - err.message, - 'PROTOCOL_ERROR', - 'Expected Error: PROTOCOL_ERROR Got Error: ' + err.message - ); - cliError = err; -}); -client.pipe(server).pipe(client); - -process.on('exit', function() { - assert(cliError, 'Expected client error'); - //assert(srvError, 'Expected server error'); -}); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-keyparser.js b/reverse_engineering/node_modules/ssh2-streams/test/test-keyparser.js deleted file mode 100644 index d634dc3..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-keyparser.js +++ /dev/null @@ -1,2301 +0,0 @@ -var parser = require('../lib/keyParser'); - -var path = require('path'); -var assert = require('assert'); -var inspect = require('util').inspect; - -var group = path.basename(__filename, '.js') + '/'; - -[ - { source: [ - '-----BEGIN RSA PRIVATE KEY-----', - 'MIIBywIBAAJhANXy0sLFQFgcY6sfyqlrBBNAcow7MWjQS0flUEj8HmrdTX+denZ5', - 'sArVEBWIoIcCWt0DWGz/mZDS2XPqyy9IbEnhwtZ3bpHmw11J1k61odAwy5sE3P4S', - 'kS/Svl7Wxjcr5wIDAQABAmEAx50pG2QiZpMGQvEEixE32iZ1OXU44kwFEO1Y/N+O', - 'GbKkzf5F9igPIewsd4rkC1MbcVPYTN6a7WlFh2dP1kC5wdPAdVjBf1p7Ii4t4HZt', - 'OokidduJzCmC+TulDCNLFmlBAjEA/6SUxcxRXJV7GHBmu+FIbnR6/drHaBvMkNKZ', - '/tGIq1KfrHIWrhGl2vYqot6hRgoXAjEA1j9VAyuDK2NhQG/WMmf8WV+OMeJQ7vpn', - '3KmtPc/CsWfPNYeQagfwlj0SLGwz8J6xAjEA4qIRkllUN/P9MOlU6nMKN4HkF3EB', - 'HvamIC3Uf+dadifFjqeGG8NhegCKQ+GCsAj5AjAecs3AL5Tqu6r8n2hPrZudkAkD', - 'aeiarhfIsoyedkJzOA+oyeVqTEqS74b/rTkMf2ECMBrts0oFmVJYo77riKQBYbR7', - '/8feisYSPHSg7hwaoXSwU+jU4g39w7rgvO+WkGuzyQ==', - '-----END RSA PRIVATE KEY-----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: new Buffer([ - 0x30, 0x82, 0x01, 0xcb, 0x02, 0x01, 0x00, 0x02, 0x61, 0x00, 0xd5, 0xf2, - 0xd2, 0xc2, 0xc5, 0x40, 0x58, 0x1c, 0x63, 0xab, 0x1f, 0xca, 0xa9, 0x6b, - 0x04, 0x13, 0x40, 0x72, 0x8c, 0x3b, 0x31, 0x68, 0xd0, 0x4b, 0x47, 0xe5, - 0x50, 0x48, 0xfc, 0x1e, 0x6a, 0xdd, 0x4d, 0x7f, 0x9d, 0x7a, 0x76, 0x79, - 0xb0, 0x0a, 0xd5, 0x10, 0x15, 0x88, 0xa0, 0x87, 0x02, 0x5a, 0xdd, 0x03, - 0x58, 0x6c, 0xff, 0x99, 0x90, 0xd2, 0xd9, 0x73, 0xea, 0xcb, 0x2f, 0x48, - 0x6c, 0x49, 0xe1, 0xc2, 0xd6, 0x77, 0x6e, 0x91, 0xe6, 0xc3, 0x5d, 0x49, - 0xd6, 0x4e, 0xb5, 0xa1, 0xd0, 0x30, 0xcb, 0x9b, 0x04, 0xdc, 0xfe, 0x12, - 0x91, 0x2f, 0xd2, 0xbe, 0x5e, 0xd6, 0xc6, 0x37, 0x2b, 0xe7, 0x02, 0x03, - 0x01, 0x00, 0x01, 0x02, 0x61, 0x00, 0xc7, 0x9d, 0x29, 0x1b, 0x64, 0x22, - 0x66, 0x93, 0x06, 0x42, 0xf1, 0x04, 0x8b, 0x11, 0x37, 0xda, 0x26, 0x75, - 0x39, 0x75, 0x38, 0xe2, 0x4c, 0x05, 0x10, 0xed, 0x58, 0xfc, 0xdf, 0x8e, - 0x19, 0xb2, 0xa4, 0xcd, 0xfe, 0x45, 0xf6, 0x28, 0x0f, 0x21, 0xec, 0x2c, - 0x77, 0x8a, 0xe4, 0x0b, 0x53, 0x1b, 0x71, 0x53, 0xd8, 0x4c, 0xde, 0x9a, - 0xed, 0x69, 0x45, 0x87, 0x67, 0x4f, 0xd6, 0x40, 0xb9, 0xc1, 0xd3, 0xc0, - 0x75, 0x58, 0xc1, 0x7f, 0x5a, 0x7b, 0x22, 0x2e, 0x2d, 0xe0, 0x76, 0x6d, - 0x3a, 0x89, 0x22, 0x75, 0xdb, 0x89, 0xcc, 0x29, 0x82, 0xf9, 0x3b, 0xa5, - 0x0c, 0x23, 0x4b, 0x16, 0x69, 0x41, 0x02, 0x31, 0x00, 0xff, 0xa4, 0x94, - 0xc5, 0xcc, 0x51, 0x5c, 0x95, 0x7b, 0x18, 0x70, 0x66, 0xbb, 0xe1, 0x48, - 0x6e, 0x74, 0x7a, 0xfd, 0xda, 0xc7, 0x68, 0x1b, 0xcc, 0x90, 0xd2, 0x99, - 0xfe, 0xd1, 0x88, 0xab, 0x52, 0x9f, 0xac, 0x72, 0x16, 0xae, 0x11, 0xa5, - 0xda, 0xf6, 0x2a, 0xa2, 0xde, 0xa1, 0x46, 0x0a, 0x17, 0x02, 0x31, 0x00, - 0xd6, 0x3f, 0x55, 0x03, 0x2b, 0x83, 0x2b, 0x63, 0x61, 0x40, 0x6f, 0xd6, - 0x32, 0x67, 0xfc, 0x59, 0x5f, 0x8e, 0x31, 0xe2, 0x50, 0xee, 0xfa, 0x67, - 0xdc, 0xa9, 0xad, 0x3d, 0xcf, 0xc2, 0xb1, 0x67, 0xcf, 0x35, 0x87, 0x90, - 0x6a, 0x07, 0xf0, 0x96, 0x3d, 0x12, 0x2c, 0x6c, 0x33, 0xf0, 0x9e, 0xb1, - 0x02, 0x31, 0x00, 0xe2, 0xa2, 0x11, 0x92, 0x59, 0x54, 0x37, 0xf3, 0xfd, - 0x30, 0xe9, 0x54, 0xea, 0x73, 0x0a, 0x37, 0x81, 0xe4, 0x17, 0x71, 0x01, - 0x1e, 0xf6, 0xa6, 0x20, 0x2d, 0xd4, 0x7f, 0xe7, 0x5a, 0x76, 0x27, 0xc5, - 0x8e, 0xa7, 0x86, 0x1b, 0xc3, 0x61, 0x7a, 0x00, 0x8a, 0x43, 0xe1, 0x82, - 0xb0, 0x08, 0xf9, 0x02, 0x30, 0x1e, 0x72, 0xcd, 0xc0, 0x2f, 0x94, 0xea, - 0xbb, 0xaa, 0xfc, 0x9f, 0x68, 0x4f, 0xad, 0x9b, 0x9d, 0x90, 0x09, 0x03, - 0x69, 0xe8, 0x9a, 0xae, 0x17, 0xc8, 0xb2, 0x8c, 0x9e, 0x76, 0x42, 0x73, - 0x38, 0x0f, 0xa8, 0xc9, 0xe5, 0x6a, 0x4c, 0x4a, 0x92, 0xef, 0x86, 0xff, - 0xad, 0x39, 0x0c, 0x7f, 0x61, 0x02, 0x30, 0x1a, 0xed, 0xb3, 0x4a, 0x05, - 0x99, 0x52, 0x58, 0xa3, 0xbe, 0xeb, 0x88, 0xa4, 0x01, 0x61, 0xb4, 0x7b, - 0xff, 0xc7, 0xde, 0x8a, 0xc6, 0x12, 0x3c, 0x74, 0xa0, 0xee, 0x1c, 0x1a, - 0xa1, 0x74, 0xb0, 0x53, 0xe8, 0xd4, 0xe2, 0x0d, 0xfd, 0xc3, 0xba, 0xe0, - 0xbc, 0xef, 0x96, 0x90, 0x6b, 0xb3, 0xc9, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, - 0x79, 0x77, 0x49, 0x42, 0x41, 0x41, 0x4a, 0x68, 0x41, 0x4e, 0x58, 0x79, - 0x30, 0x73, 0x4c, 0x46, 0x51, 0x46, 0x67, 0x63, 0x59, 0x36, 0x73, 0x66, - 0x79, 0x71, 0x6c, 0x72, 0x42, 0x42, 0x4e, 0x41, 0x63, 0x6f, 0x77, 0x37, - 0x4d, 0x57, 0x6a, 0x51, 0x53, 0x30, 0x66, 0x6c, 0x55, 0x45, 0x6a, 0x38, - 0x48, 0x6d, 0x72, 0x64, 0x54, 0x58, 0x2b, 0x64, 0x65, 0x6e, 0x5a, 0x35, - 0x0a, 0x73, 0x41, 0x72, 0x56, 0x45, 0x42, 0x57, 0x49, 0x6f, 0x49, 0x63, - 0x43, 0x57, 0x74, 0x30, 0x44, 0x57, 0x47, 0x7a, 0x2f, 0x6d, 0x5a, 0x44, - 0x53, 0x32, 0x58, 0x50, 0x71, 0x79, 0x79, 0x39, 0x49, 0x62, 0x45, 0x6e, - 0x68, 0x77, 0x74, 0x5a, 0x33, 0x62, 0x70, 0x48, 0x6d, 0x77, 0x31, 0x31, - 0x4a, 0x31, 0x6b, 0x36, 0x31, 0x6f, 0x64, 0x41, 0x77, 0x79, 0x35, 0x73, - 0x45, 0x33, 0x50, 0x34, 0x53, 0x0a, 0x6b, 0x53, 0x2f, 0x53, 0x76, 0x6c, - 0x37, 0x57, 0x78, 0x6a, 0x63, 0x72, 0x35, 0x77, 0x49, 0x44, 0x41, 0x51, - 0x41, 0x42, 0x41, 0x6d, 0x45, 0x41, 0x78, 0x35, 0x30, 0x70, 0x47, 0x32, - 0x51, 0x69, 0x5a, 0x70, 0x4d, 0x47, 0x51, 0x76, 0x45, 0x45, 0x69, 0x78, - 0x45, 0x33, 0x32, 0x69, 0x5a, 0x31, 0x4f, 0x58, 0x55, 0x34, 0x34, 0x6b, - 0x77, 0x46, 0x45, 0x4f, 0x31, 0x59, 0x2f, 0x4e, 0x2b, 0x4f, 0x0a, 0x47, - 0x62, 0x4b, 0x6b, 0x7a, 0x66, 0x35, 0x46, 0x39, 0x69, 0x67, 0x50, 0x49, - 0x65, 0x77, 0x73, 0x64, 0x34, 0x72, 0x6b, 0x43, 0x31, 0x4d, 0x62, 0x63, - 0x56, 0x50, 0x59, 0x54, 0x4e, 0x36, 0x61, 0x37, 0x57, 0x6c, 0x46, 0x68, - 0x32, 0x64, 0x50, 0x31, 0x6b, 0x43, 0x35, 0x77, 0x64, 0x50, 0x41, 0x64, - 0x56, 0x6a, 0x42, 0x66, 0x31, 0x70, 0x37, 0x49, 0x69, 0x34, 0x74, 0x34, - 0x48, 0x5a, 0x74, 0x0a, 0x4f, 0x6f, 0x6b, 0x69, 0x64, 0x64, 0x75, 0x4a, - 0x7a, 0x43, 0x6d, 0x43, 0x2b, 0x54, 0x75, 0x6c, 0x44, 0x43, 0x4e, 0x4c, - 0x46, 0x6d, 0x6c, 0x42, 0x41, 0x6a, 0x45, 0x41, 0x2f, 0x36, 0x53, 0x55, - 0x78, 0x63, 0x78, 0x52, 0x58, 0x4a, 0x56, 0x37, 0x47, 0x48, 0x42, 0x6d, - 0x75, 0x2b, 0x46, 0x49, 0x62, 0x6e, 0x52, 0x36, 0x2f, 0x64, 0x72, 0x48, - 0x61, 0x42, 0x76, 0x4d, 0x6b, 0x4e, 0x4b, 0x5a, 0x0a, 0x2f, 0x74, 0x47, - 0x49, 0x71, 0x31, 0x4b, 0x66, 0x72, 0x48, 0x49, 0x57, 0x72, 0x68, 0x47, - 0x6c, 0x32, 0x76, 0x59, 0x71, 0x6f, 0x74, 0x36, 0x68, 0x52, 0x67, 0x6f, - 0x58, 0x41, 0x6a, 0x45, 0x41, 0x31, 0x6a, 0x39, 0x56, 0x41, 0x79, 0x75, - 0x44, 0x4b, 0x32, 0x4e, 0x68, 0x51, 0x47, 0x2f, 0x57, 0x4d, 0x6d, 0x66, - 0x38, 0x57, 0x56, 0x2b, 0x4f, 0x4d, 0x65, 0x4a, 0x51, 0x37, 0x76, 0x70, - 0x6e, 0x0a, 0x33, 0x4b, 0x6d, 0x74, 0x50, 0x63, 0x2f, 0x43, 0x73, 0x57, - 0x66, 0x50, 0x4e, 0x59, 0x65, 0x51, 0x61, 0x67, 0x66, 0x77, 0x6c, 0x6a, - 0x30, 0x53, 0x4c, 0x47, 0x77, 0x7a, 0x38, 0x4a, 0x36, 0x78, 0x41, 0x6a, - 0x45, 0x41, 0x34, 0x71, 0x49, 0x52, 0x6b, 0x6c, 0x6c, 0x55, 0x4e, 0x2f, - 0x50, 0x39, 0x4d, 0x4f, 0x6c, 0x55, 0x36, 0x6e, 0x4d, 0x4b, 0x4e, 0x34, - 0x48, 0x6b, 0x46, 0x33, 0x45, 0x42, 0x0a, 0x48, 0x76, 0x61, 0x6d, 0x49, - 0x43, 0x33, 0x55, 0x66, 0x2b, 0x64, 0x61, 0x64, 0x69, 0x66, 0x46, 0x6a, - 0x71, 0x65, 0x47, 0x47, 0x38, 0x4e, 0x68, 0x65, 0x67, 0x43, 0x4b, 0x51, - 0x2b, 0x47, 0x43, 0x73, 0x41, 0x6a, 0x35, 0x41, 0x6a, 0x41, 0x65, 0x63, - 0x73, 0x33, 0x41, 0x4c, 0x35, 0x54, 0x71, 0x75, 0x36, 0x72, 0x38, 0x6e, - 0x32, 0x68, 0x50, 0x72, 0x5a, 0x75, 0x64, 0x6b, 0x41, 0x6b, 0x44, 0x0a, - 0x61, 0x65, 0x69, 0x61, 0x72, 0x68, 0x66, 0x49, 0x73, 0x6f, 0x79, 0x65, - 0x64, 0x6b, 0x4a, 0x7a, 0x4f, 0x41, 0x2b, 0x6f, 0x79, 0x65, 0x56, 0x71, - 0x54, 0x45, 0x71, 0x53, 0x37, 0x34, 0x62, 0x2f, 0x72, 0x54, 0x6b, 0x4d, - 0x66, 0x32, 0x45, 0x43, 0x4d, 0x42, 0x72, 0x74, 0x73, 0x30, 0x6f, 0x46, - 0x6d, 0x56, 0x4a, 0x59, 0x6f, 0x37, 0x37, 0x72, 0x69, 0x4b, 0x51, 0x42, - 0x59, 0x62, 0x52, 0x37, 0x0a, 0x2f, 0x38, 0x66, 0x65, 0x69, 0x73, 0x59, - 0x53, 0x50, 0x48, 0x53, 0x67, 0x37, 0x68, 0x77, 0x61, 0x6f, 0x58, 0x53, - 0x77, 0x55, 0x2b, 0x6a, 0x55, 0x34, 0x67, 0x33, 0x39, 0x77, 0x37, 0x72, - 0x67, 0x76, 0x4f, 0x2b, 0x57, 0x6b, 0x47, 0x75, 0x7a, 0x79, 0x51, 0x3d, - 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - public: undefined, - publicOrig: undefined - }, - what: 'Unencrypted RSA private key (OpenSSH format)' - }, - { source: [ - ' ', - '-----BEGIN RSA PRIVATE KEY-----', - 'MIIBywIBAAJhANXy0sLFQFgcY6sfyqlrBBNAcow7MWjQS0flUEj8HmrdTX+denZ5', - 'sArVEBWIoIcCWt0DWGz/mZDS2XPqyy9IbEnhwtZ3bpHmw11J1k61odAwy5sE3P4S', - 'kS/Svl7Wxjcr5wIDAQABAmEAx50pG2QiZpMGQvEEixE32iZ1OXU44kwFEO1Y/N+O', - 'GbKkzf5F9igPIewsd4rkC1MbcVPYTN6a7WlFh2dP1kC5wdPAdVjBf1p7Ii4t4HZt', - 'OokidduJzCmC+TulDCNLFmlBAjEA/6SUxcxRXJV7GHBmu+FIbnR6/drHaBvMkNKZ', - '/tGIq1KfrHIWrhGl2vYqot6hRgoXAjEA1j9VAyuDK2NhQG/WMmf8WV+OMeJQ7vpn', - '3KmtPc/CsWfPNYeQagfwlj0SLGwz8J6xAjEA4qIRkllUN/P9MOlU6nMKN4HkF3EB', - 'HvamIC3Uf+dadifFjqeGG8NhegCKQ+GCsAj5AjAecs3AL5Tqu6r8n2hPrZudkAkD', - 'aeiarhfIsoyedkJzOA+oyeVqTEqS74b/rTkMf2ECMBrts0oFmVJYo77riKQBYbR7', - '/8feisYSPHSg7hwaoXSwU+jU4g39w7rgvO+WkGuzyQ==', - '-----END RSA PRIVATE KEY-----', - ' ' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: new Buffer([ - 0x30, 0x82, 0x01, 0xcb, 0x02, 0x01, 0x00, 0x02, 0x61, 0x00, 0xd5, 0xf2, - 0xd2, 0xc2, 0xc5, 0x40, 0x58, 0x1c, 0x63, 0xab, 0x1f, 0xca, 0xa9, 0x6b, - 0x04, 0x13, 0x40, 0x72, 0x8c, 0x3b, 0x31, 0x68, 0xd0, 0x4b, 0x47, 0xe5, - 0x50, 0x48, 0xfc, 0x1e, 0x6a, 0xdd, 0x4d, 0x7f, 0x9d, 0x7a, 0x76, 0x79, - 0xb0, 0x0a, 0xd5, 0x10, 0x15, 0x88, 0xa0, 0x87, 0x02, 0x5a, 0xdd, 0x03, - 0x58, 0x6c, 0xff, 0x99, 0x90, 0xd2, 0xd9, 0x73, 0xea, 0xcb, 0x2f, 0x48, - 0x6c, 0x49, 0xe1, 0xc2, 0xd6, 0x77, 0x6e, 0x91, 0xe6, 0xc3, 0x5d, 0x49, - 0xd6, 0x4e, 0xb5, 0xa1, 0xd0, 0x30, 0xcb, 0x9b, 0x04, 0xdc, 0xfe, 0x12, - 0x91, 0x2f, 0xd2, 0xbe, 0x5e, 0xd6, 0xc6, 0x37, 0x2b, 0xe7, 0x02, 0x03, - 0x01, 0x00, 0x01, 0x02, 0x61, 0x00, 0xc7, 0x9d, 0x29, 0x1b, 0x64, 0x22, - 0x66, 0x93, 0x06, 0x42, 0xf1, 0x04, 0x8b, 0x11, 0x37, 0xda, 0x26, 0x75, - 0x39, 0x75, 0x38, 0xe2, 0x4c, 0x05, 0x10, 0xed, 0x58, 0xfc, 0xdf, 0x8e, - 0x19, 0xb2, 0xa4, 0xcd, 0xfe, 0x45, 0xf6, 0x28, 0x0f, 0x21, 0xec, 0x2c, - 0x77, 0x8a, 0xe4, 0x0b, 0x53, 0x1b, 0x71, 0x53, 0xd8, 0x4c, 0xde, 0x9a, - 0xed, 0x69, 0x45, 0x87, 0x67, 0x4f, 0xd6, 0x40, 0xb9, 0xc1, 0xd3, 0xc0, - 0x75, 0x58, 0xc1, 0x7f, 0x5a, 0x7b, 0x22, 0x2e, 0x2d, 0xe0, 0x76, 0x6d, - 0x3a, 0x89, 0x22, 0x75, 0xdb, 0x89, 0xcc, 0x29, 0x82, 0xf9, 0x3b, 0xa5, - 0x0c, 0x23, 0x4b, 0x16, 0x69, 0x41, 0x02, 0x31, 0x00, 0xff, 0xa4, 0x94, - 0xc5, 0xcc, 0x51, 0x5c, 0x95, 0x7b, 0x18, 0x70, 0x66, 0xbb, 0xe1, 0x48, - 0x6e, 0x74, 0x7a, 0xfd, 0xda, 0xc7, 0x68, 0x1b, 0xcc, 0x90, 0xd2, 0x99, - 0xfe, 0xd1, 0x88, 0xab, 0x52, 0x9f, 0xac, 0x72, 0x16, 0xae, 0x11, 0xa5, - 0xda, 0xf6, 0x2a, 0xa2, 0xde, 0xa1, 0x46, 0x0a, 0x17, 0x02, 0x31, 0x00, - 0xd6, 0x3f, 0x55, 0x03, 0x2b, 0x83, 0x2b, 0x63, 0x61, 0x40, 0x6f, 0xd6, - 0x32, 0x67, 0xfc, 0x59, 0x5f, 0x8e, 0x31, 0xe2, 0x50, 0xee, 0xfa, 0x67, - 0xdc, 0xa9, 0xad, 0x3d, 0xcf, 0xc2, 0xb1, 0x67, 0xcf, 0x35, 0x87, 0x90, - 0x6a, 0x07, 0xf0, 0x96, 0x3d, 0x12, 0x2c, 0x6c, 0x33, 0xf0, 0x9e, 0xb1, - 0x02, 0x31, 0x00, 0xe2, 0xa2, 0x11, 0x92, 0x59, 0x54, 0x37, 0xf3, 0xfd, - 0x30, 0xe9, 0x54, 0xea, 0x73, 0x0a, 0x37, 0x81, 0xe4, 0x17, 0x71, 0x01, - 0x1e, 0xf6, 0xa6, 0x20, 0x2d, 0xd4, 0x7f, 0xe7, 0x5a, 0x76, 0x27, 0xc5, - 0x8e, 0xa7, 0x86, 0x1b, 0xc3, 0x61, 0x7a, 0x00, 0x8a, 0x43, 0xe1, 0x82, - 0xb0, 0x08, 0xf9, 0x02, 0x30, 0x1e, 0x72, 0xcd, 0xc0, 0x2f, 0x94, 0xea, - 0xbb, 0xaa, 0xfc, 0x9f, 0x68, 0x4f, 0xad, 0x9b, 0x9d, 0x90, 0x09, 0x03, - 0x69, 0xe8, 0x9a, 0xae, 0x17, 0xc8, 0xb2, 0x8c, 0x9e, 0x76, 0x42, 0x73, - 0x38, 0x0f, 0xa8, 0xc9, 0xe5, 0x6a, 0x4c, 0x4a, 0x92, 0xef, 0x86, 0xff, - 0xad, 0x39, 0x0c, 0x7f, 0x61, 0x02, 0x30, 0x1a, 0xed, 0xb3, 0x4a, 0x05, - 0x99, 0x52, 0x58, 0xa3, 0xbe, 0xeb, 0x88, 0xa4, 0x01, 0x61, 0xb4, 0x7b, - 0xff, 0xc7, 0xde, 0x8a, 0xc6, 0x12, 0x3c, 0x74, 0xa0, 0xee, 0x1c, 0x1a, - 0xa1, 0x74, 0xb0, 0x53, 0xe8, 0xd4, 0xe2, 0x0d, 0xfd, 0xc3, 0xba, 0xe0, - 0xbc, 0xef, 0x96, 0x90, 0x6b, 0xb3, 0xc9, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, - 0x79, 0x77, 0x49, 0x42, 0x41, 0x41, 0x4a, 0x68, 0x41, 0x4e, 0x58, 0x79, - 0x30, 0x73, 0x4c, 0x46, 0x51, 0x46, 0x67, 0x63, 0x59, 0x36, 0x73, 0x66, - 0x79, 0x71, 0x6c, 0x72, 0x42, 0x42, 0x4e, 0x41, 0x63, 0x6f, 0x77, 0x37, - 0x4d, 0x57, 0x6a, 0x51, 0x53, 0x30, 0x66, 0x6c, 0x55, 0x45, 0x6a, 0x38, - 0x48, 0x6d, 0x72, 0x64, 0x54, 0x58, 0x2b, 0x64, 0x65, 0x6e, 0x5a, 0x35, - 0x0a, 0x73, 0x41, 0x72, 0x56, 0x45, 0x42, 0x57, 0x49, 0x6f, 0x49, 0x63, - 0x43, 0x57, 0x74, 0x30, 0x44, 0x57, 0x47, 0x7a, 0x2f, 0x6d, 0x5a, 0x44, - 0x53, 0x32, 0x58, 0x50, 0x71, 0x79, 0x79, 0x39, 0x49, 0x62, 0x45, 0x6e, - 0x68, 0x77, 0x74, 0x5a, 0x33, 0x62, 0x70, 0x48, 0x6d, 0x77, 0x31, 0x31, - 0x4a, 0x31, 0x6b, 0x36, 0x31, 0x6f, 0x64, 0x41, 0x77, 0x79, 0x35, 0x73, - 0x45, 0x33, 0x50, 0x34, 0x53, 0x0a, 0x6b, 0x53, 0x2f, 0x53, 0x76, 0x6c, - 0x37, 0x57, 0x78, 0x6a, 0x63, 0x72, 0x35, 0x77, 0x49, 0x44, 0x41, 0x51, - 0x41, 0x42, 0x41, 0x6d, 0x45, 0x41, 0x78, 0x35, 0x30, 0x70, 0x47, 0x32, - 0x51, 0x69, 0x5a, 0x70, 0x4d, 0x47, 0x51, 0x76, 0x45, 0x45, 0x69, 0x78, - 0x45, 0x33, 0x32, 0x69, 0x5a, 0x31, 0x4f, 0x58, 0x55, 0x34, 0x34, 0x6b, - 0x77, 0x46, 0x45, 0x4f, 0x31, 0x59, 0x2f, 0x4e, 0x2b, 0x4f, 0x0a, 0x47, - 0x62, 0x4b, 0x6b, 0x7a, 0x66, 0x35, 0x46, 0x39, 0x69, 0x67, 0x50, 0x49, - 0x65, 0x77, 0x73, 0x64, 0x34, 0x72, 0x6b, 0x43, 0x31, 0x4d, 0x62, 0x63, - 0x56, 0x50, 0x59, 0x54, 0x4e, 0x36, 0x61, 0x37, 0x57, 0x6c, 0x46, 0x68, - 0x32, 0x64, 0x50, 0x31, 0x6b, 0x43, 0x35, 0x77, 0x64, 0x50, 0x41, 0x64, - 0x56, 0x6a, 0x42, 0x66, 0x31, 0x70, 0x37, 0x49, 0x69, 0x34, 0x74, 0x34, - 0x48, 0x5a, 0x74, 0x0a, 0x4f, 0x6f, 0x6b, 0x69, 0x64, 0x64, 0x75, 0x4a, - 0x7a, 0x43, 0x6d, 0x43, 0x2b, 0x54, 0x75, 0x6c, 0x44, 0x43, 0x4e, 0x4c, - 0x46, 0x6d, 0x6c, 0x42, 0x41, 0x6a, 0x45, 0x41, 0x2f, 0x36, 0x53, 0x55, - 0x78, 0x63, 0x78, 0x52, 0x58, 0x4a, 0x56, 0x37, 0x47, 0x48, 0x42, 0x6d, - 0x75, 0x2b, 0x46, 0x49, 0x62, 0x6e, 0x52, 0x36, 0x2f, 0x64, 0x72, 0x48, - 0x61, 0x42, 0x76, 0x4d, 0x6b, 0x4e, 0x4b, 0x5a, 0x0a, 0x2f, 0x74, 0x47, - 0x49, 0x71, 0x31, 0x4b, 0x66, 0x72, 0x48, 0x49, 0x57, 0x72, 0x68, 0x47, - 0x6c, 0x32, 0x76, 0x59, 0x71, 0x6f, 0x74, 0x36, 0x68, 0x52, 0x67, 0x6f, - 0x58, 0x41, 0x6a, 0x45, 0x41, 0x31, 0x6a, 0x39, 0x56, 0x41, 0x79, 0x75, - 0x44, 0x4b, 0x32, 0x4e, 0x68, 0x51, 0x47, 0x2f, 0x57, 0x4d, 0x6d, 0x66, - 0x38, 0x57, 0x56, 0x2b, 0x4f, 0x4d, 0x65, 0x4a, 0x51, 0x37, 0x76, 0x70, - 0x6e, 0x0a, 0x33, 0x4b, 0x6d, 0x74, 0x50, 0x63, 0x2f, 0x43, 0x73, 0x57, - 0x66, 0x50, 0x4e, 0x59, 0x65, 0x51, 0x61, 0x67, 0x66, 0x77, 0x6c, 0x6a, - 0x30, 0x53, 0x4c, 0x47, 0x77, 0x7a, 0x38, 0x4a, 0x36, 0x78, 0x41, 0x6a, - 0x45, 0x41, 0x34, 0x71, 0x49, 0x52, 0x6b, 0x6c, 0x6c, 0x55, 0x4e, 0x2f, - 0x50, 0x39, 0x4d, 0x4f, 0x6c, 0x55, 0x36, 0x6e, 0x4d, 0x4b, 0x4e, 0x34, - 0x48, 0x6b, 0x46, 0x33, 0x45, 0x42, 0x0a, 0x48, 0x76, 0x61, 0x6d, 0x49, - 0x43, 0x33, 0x55, 0x66, 0x2b, 0x64, 0x61, 0x64, 0x69, 0x66, 0x46, 0x6a, - 0x71, 0x65, 0x47, 0x47, 0x38, 0x4e, 0x68, 0x65, 0x67, 0x43, 0x4b, 0x51, - 0x2b, 0x47, 0x43, 0x73, 0x41, 0x6a, 0x35, 0x41, 0x6a, 0x41, 0x65, 0x63, - 0x73, 0x33, 0x41, 0x4c, 0x35, 0x54, 0x71, 0x75, 0x36, 0x72, 0x38, 0x6e, - 0x32, 0x68, 0x50, 0x72, 0x5a, 0x75, 0x64, 0x6b, 0x41, 0x6b, 0x44, 0x0a, - 0x61, 0x65, 0x69, 0x61, 0x72, 0x68, 0x66, 0x49, 0x73, 0x6f, 0x79, 0x65, - 0x64, 0x6b, 0x4a, 0x7a, 0x4f, 0x41, 0x2b, 0x6f, 0x79, 0x65, 0x56, 0x71, - 0x54, 0x45, 0x71, 0x53, 0x37, 0x34, 0x62, 0x2f, 0x72, 0x54, 0x6b, 0x4d, - 0x66, 0x32, 0x45, 0x43, 0x4d, 0x42, 0x72, 0x74, 0x73, 0x30, 0x6f, 0x46, - 0x6d, 0x56, 0x4a, 0x59, 0x6f, 0x37, 0x37, 0x72, 0x69, 0x4b, 0x51, 0x42, - 0x59, 0x62, 0x52, 0x37, 0x0a, 0x2f, 0x38, 0x66, 0x65, 0x69, 0x73, 0x59, - 0x53, 0x50, 0x48, 0x53, 0x67, 0x37, 0x68, 0x77, 0x61, 0x6f, 0x58, 0x53, - 0x77, 0x55, 0x2b, 0x6a, 0x55, 0x34, 0x67, 0x33, 0x39, 0x77, 0x37, 0x72, - 0x67, 0x76, 0x4f, 0x2b, 0x57, 0x6b, 0x47, 0x75, 0x7a, 0x79, 0x51, 0x3d, - 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - public: undefined, - publicOrig: undefined - }, - what: 'Unencrypted RSA private key (OpenSSH format) with surrounding whitespace' - }, - { source: [ - '-----BEGIN RSA PRIVATE KEY-----', - 'Proc-Type: 4,ENCRYPTED', - 'DEK-Info: AES-128-CBC,E9F7397F94E585BCE4C739D5C5226A2D', - '', - 'mshPNeXq8XAh79N3F1vKUOCsWoTofhz/Kpt/ddYdgnGG9L5wGDoveJQtpsa5u+A4', - 'hCkAWA7KRCUKbOxZd8lG00cm7HILN7eHCKSoSkyA+X1jN7v1tSGPjiN2RSZFHCOI', - '8jEF0fyTeg9GZzFaiyyD5p1niy7uCssEeo8AzbIBX4yLDR18mmBiMhn0FxVu/YFn', - 'rfkm+ciE4WhkqdCUOkKiqIux7RI6O9ttUuZlhwVvoKZqujMeNrFppOC9kF5hAi6Y', - 'oHvrweE8QmimEUIMAwdDrI1/jglFw2x2K5sRxPIIFJC1aHR8nXLTuO1g2/g6aqls', - 'jGkwlQU4cU5pnkxkLUVCSHi6A6nwbdjQTIIDofpcckQVFHZaBCJx9UF691NR05Dc', - 'GthFFfNGXWU6vbwKia/LDX8R98ay4Ci2zoDXxe7QBnvnWbs2m69HPh6opmo5gKL+', - 'y65Sf6MAi5udIJLVfgXQBgRyX3glS7/rH8YbrrNY9Iop1KcSWXAIC4zlCoO3tBJB', - '9464YBD/R+qOvVMcBGxTjabudi00ougeTgsS7idDTmfc4HYIls0E7yWqzgspsws5', - 'w7K4crSgm+u3oypViUSre2qSvAHTC5gXth8LVCnDZuA=', - '-----END RSA PRIVATE KEY-----' - ].join('\n'), - expected: { - fulltype: undefined, - type: 'rsa', - curve: undefined, - extra: [ 'E9F7397F94E585BCE4C739D5C5226A2D' ], - comment: undefined, - encryption: 'aes-128-cbc', - private: new Buffer([ - 0x9a, 0xc8, 0x4f, 0x35, 0xe5, 0xea, 0xf1, 0x70, 0x21, 0xef, 0xd3, 0x77, - 0x17, 0x5b, 0xca, 0x50, 0xe0, 0xac, 0x5a, 0x84, 0xe8, 0x7e, 0x1c, 0xff, - 0x2a, 0x9b, 0x7f, 0x75, 0xd6, 0x1d, 0x82, 0x71, 0x86, 0xf4, 0xbe, 0x70, - 0x18, 0x3a, 0x2f, 0x78, 0x94, 0x2d, 0xa6, 0xc6, 0xb9, 0xbb, 0xe0, 0x38, - 0x84, 0x29, 0x00, 0x58, 0x0e, 0xca, 0x44, 0x25, 0x0a, 0x6c, 0xec, 0x59, - 0x77, 0xc9, 0x46, 0xd3, 0x47, 0x26, 0xec, 0x72, 0x0b, 0x37, 0xb7, 0x87, - 0x08, 0xa4, 0xa8, 0x4a, 0x4c, 0x80, 0xf9, 0x7d, 0x63, 0x37, 0xbb, 0xf5, - 0xb5, 0x21, 0x8f, 0x8e, 0x23, 0x76, 0x45, 0x26, 0x45, 0x1c, 0x23, 0x88, - 0xf2, 0x31, 0x05, 0xd1, 0xfc, 0x93, 0x7a, 0x0f, 0x46, 0x67, 0x31, 0x5a, - 0x8b, 0x2c, 0x83, 0xe6, 0x9d, 0x67, 0x8b, 0x2e, 0xee, 0x0a, 0xcb, 0x04, - 0x7a, 0x8f, 0x00, 0xcd, 0xb2, 0x01, 0x5f, 0x8c, 0x8b, 0x0d, 0x1d, 0x7c, - 0x9a, 0x60, 0x62, 0x32, 0x19, 0xf4, 0x17, 0x15, 0x6e, 0xfd, 0x81, 0x67, - 0xad, 0xf9, 0x26, 0xf9, 0xc8, 0x84, 0xe1, 0x68, 0x64, 0xa9, 0xd0, 0x94, - 0x3a, 0x42, 0xa2, 0xa8, 0x8b, 0xb1, 0xed, 0x12, 0x3a, 0x3b, 0xdb, 0x6d, - 0x52, 0xe6, 0x65, 0x87, 0x05, 0x6f, 0xa0, 0xa6, 0x6a, 0xba, 0x33, 0x1e, - 0x36, 0xb1, 0x69, 0xa4, 0xe0, 0xbd, 0x90, 0x5e, 0x61, 0x02, 0x2e, 0x98, - 0xa0, 0x7b, 0xeb, 0xc1, 0xe1, 0x3c, 0x42, 0x68, 0xa6, 0x11, 0x42, 0x0c, - 0x03, 0x07, 0x43, 0xac, 0x8d, 0x7f, 0x8e, 0x09, 0x45, 0xc3, 0x6c, 0x76, - 0x2b, 0x9b, 0x11, 0xc4, 0xf2, 0x08, 0x14, 0x90, 0xb5, 0x68, 0x74, 0x7c, - 0x9d, 0x72, 0xd3, 0xb8, 0xed, 0x60, 0xdb, 0xf8, 0x3a, 0x6a, 0xa9, 0x6c, - 0x8c, 0x69, 0x30, 0x95, 0x05, 0x38, 0x71, 0x4e, 0x69, 0x9e, 0x4c, 0x64, - 0x2d, 0x45, 0x42, 0x48, 0x78, 0xba, 0x03, 0xa9, 0xf0, 0x6d, 0xd8, 0xd0, - 0x4c, 0x82, 0x03, 0xa1, 0xfa, 0x5c, 0x72, 0x44, 0x15, 0x14, 0x76, 0x5a, - 0x04, 0x22, 0x71, 0xf5, 0x41, 0x7a, 0xf7, 0x53, 0x51, 0xd3, 0x90, 0xdc, - 0x1a, 0xd8, 0x45, 0x15, 0xf3, 0x46, 0x5d, 0x65, 0x3a, 0xbd, 0xbc, 0x0a, - 0x89, 0xaf, 0xcb, 0x0d, 0x7f, 0x11, 0xf7, 0xc6, 0xb2, 0xe0, 0x28, 0xb6, - 0xce, 0x80, 0xd7, 0xc5, 0xee, 0xd0, 0x06, 0x7b, 0xe7, 0x59, 0xbb, 0x36, - 0x9b, 0xaf, 0x47, 0x3e, 0x1e, 0xa8, 0xa6, 0x6a, 0x39, 0x80, 0xa2, 0xfe, - 0xcb, 0xae, 0x52, 0x7f, 0xa3, 0x00, 0x8b, 0x9b, 0x9d, 0x20, 0x92, 0xd5, - 0x7e, 0x05, 0xd0, 0x06, 0x04, 0x72, 0x5f, 0x78, 0x25, 0x4b, 0xbf, 0xeb, - 0x1f, 0xc6, 0x1b, 0xae, 0xb3, 0x58, 0xf4, 0x8a, 0x29, 0xd4, 0xa7, 0x12, - 0x59, 0x70, 0x08, 0x0b, 0x8c, 0xe5, 0x0a, 0x83, 0xb7, 0xb4, 0x12, 0x41, - 0xf7, 0x8e, 0xb8, 0x60, 0x10, 0xff, 0x47, 0xea, 0x8e, 0xbd, 0x53, 0x1c, - 0x04, 0x6c, 0x53, 0x8d, 0xa6, 0xee, 0x76, 0x2d, 0x34, 0xa2, 0xe8, 0x1e, - 0x4e, 0x0b, 0x12, 0xee, 0x27, 0x43, 0x4e, 0x67, 0xdc, 0xe0, 0x76, 0x08, - 0x96, 0xcd, 0x04, 0xef, 0x25, 0xaa, 0xce, 0x0b, 0x29, 0xb3, 0x0b, 0x39, - 0xc3, 0xb2, 0xb8, 0x72, 0xb4, 0xa0, 0x9b, 0xeb, 0xb7, 0xa3, 0x2a, 0x55, - 0x89, 0x44, 0xab, 0x7b, 0x6a, 0x92, 0xbc, 0x01, 0xd3, 0x0b, 0x98, 0x17, - 0xb6, 0x1f, 0x0b, 0x54, 0x29, 0xc3, 0x66, 0xe0, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x50, 0x72, 0x6f, 0x63, - 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x34, 0x2c, 0x45, 0x4e, 0x43, - 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x0a, 0x44, 0x45, 0x4b, 0x2d, 0x49, - 0x6e, 0x66, 0x6f, 0x3a, 0x20, 0x41, 0x45, 0x53, 0x2d, 0x31, 0x32, 0x38, - 0x2d, 0x43, 0x42, 0x43, 0x2c, 0x45, 0x39, 0x46, 0x37, 0x33, 0x39, 0x37, - 0x46, 0x39, 0x34, 0x45, 0x35, 0x38, 0x35, 0x42, 0x43, 0x45, 0x34, 0x43, - 0x37, 0x33, 0x39, 0x44, 0x35, 0x43, 0x35, 0x32, 0x32, 0x36, 0x41, 0x32, - 0x44, 0x0a, 0x0a, 0x6d, 0x73, 0x68, 0x50, 0x4e, 0x65, 0x58, 0x71, 0x38, - 0x58, 0x41, 0x68, 0x37, 0x39, 0x4e, 0x33, 0x46, 0x31, 0x76, 0x4b, 0x55, - 0x4f, 0x43, 0x73, 0x57, 0x6f, 0x54, 0x6f, 0x66, 0x68, 0x7a, 0x2f, 0x4b, - 0x70, 0x74, 0x2f, 0x64, 0x64, 0x59, 0x64, 0x67, 0x6e, 0x47, 0x47, 0x39, - 0x4c, 0x35, 0x77, 0x47, 0x44, 0x6f, 0x76, 0x65, 0x4a, 0x51, 0x74, 0x70, - 0x73, 0x61, 0x35, 0x75, 0x2b, 0x41, 0x34, 0x0a, 0x68, 0x43, 0x6b, 0x41, - 0x57, 0x41, 0x37, 0x4b, 0x52, 0x43, 0x55, 0x4b, 0x62, 0x4f, 0x78, 0x5a, - 0x64, 0x38, 0x6c, 0x47, 0x30, 0x30, 0x63, 0x6d, 0x37, 0x48, 0x49, 0x4c, - 0x4e, 0x37, 0x65, 0x48, 0x43, 0x4b, 0x53, 0x6f, 0x53, 0x6b, 0x79, 0x41, - 0x2b, 0x58, 0x31, 0x6a, 0x4e, 0x37, 0x76, 0x31, 0x74, 0x53, 0x47, 0x50, - 0x6a, 0x69, 0x4e, 0x32, 0x52, 0x53, 0x5a, 0x46, 0x48, 0x43, 0x4f, 0x49, - 0x0a, 0x38, 0x6a, 0x45, 0x46, 0x30, 0x66, 0x79, 0x54, 0x65, 0x67, 0x39, - 0x47, 0x5a, 0x7a, 0x46, 0x61, 0x69, 0x79, 0x79, 0x44, 0x35, 0x70, 0x31, - 0x6e, 0x69, 0x79, 0x37, 0x75, 0x43, 0x73, 0x73, 0x45, 0x65, 0x6f, 0x38, - 0x41, 0x7a, 0x62, 0x49, 0x42, 0x58, 0x34, 0x79, 0x4c, 0x44, 0x52, 0x31, - 0x38, 0x6d, 0x6d, 0x42, 0x69, 0x4d, 0x68, 0x6e, 0x30, 0x46, 0x78, 0x56, - 0x75, 0x2f, 0x59, 0x46, 0x6e, 0x0a, 0x72, 0x66, 0x6b, 0x6d, 0x2b, 0x63, - 0x69, 0x45, 0x34, 0x57, 0x68, 0x6b, 0x71, 0x64, 0x43, 0x55, 0x4f, 0x6b, - 0x4b, 0x69, 0x71, 0x49, 0x75, 0x78, 0x37, 0x52, 0x49, 0x36, 0x4f, 0x39, - 0x74, 0x74, 0x55, 0x75, 0x5a, 0x6c, 0x68, 0x77, 0x56, 0x76, 0x6f, 0x4b, - 0x5a, 0x71, 0x75, 0x6a, 0x4d, 0x65, 0x4e, 0x72, 0x46, 0x70, 0x70, 0x4f, - 0x43, 0x39, 0x6b, 0x46, 0x35, 0x68, 0x41, 0x69, 0x36, 0x59, 0x0a, 0x6f, - 0x48, 0x76, 0x72, 0x77, 0x65, 0x45, 0x38, 0x51, 0x6d, 0x69, 0x6d, 0x45, - 0x55, 0x49, 0x4d, 0x41, 0x77, 0x64, 0x44, 0x72, 0x49, 0x31, 0x2f, 0x6a, - 0x67, 0x6c, 0x46, 0x77, 0x32, 0x78, 0x32, 0x4b, 0x35, 0x73, 0x52, 0x78, - 0x50, 0x49, 0x49, 0x46, 0x4a, 0x43, 0x31, 0x61, 0x48, 0x52, 0x38, 0x6e, - 0x58, 0x4c, 0x54, 0x75, 0x4f, 0x31, 0x67, 0x32, 0x2f, 0x67, 0x36, 0x61, - 0x71, 0x6c, 0x73, 0x0a, 0x6a, 0x47, 0x6b, 0x77, 0x6c, 0x51, 0x55, 0x34, - 0x63, 0x55, 0x35, 0x70, 0x6e, 0x6b, 0x78, 0x6b, 0x4c, 0x55, 0x56, 0x43, - 0x53, 0x48, 0x69, 0x36, 0x41, 0x36, 0x6e, 0x77, 0x62, 0x64, 0x6a, 0x51, - 0x54, 0x49, 0x49, 0x44, 0x6f, 0x66, 0x70, 0x63, 0x63, 0x6b, 0x51, 0x56, - 0x46, 0x48, 0x5a, 0x61, 0x42, 0x43, 0x4a, 0x78, 0x39, 0x55, 0x46, 0x36, - 0x39, 0x31, 0x4e, 0x52, 0x30, 0x35, 0x44, 0x63, 0x0a, 0x47, 0x74, 0x68, - 0x46, 0x46, 0x66, 0x4e, 0x47, 0x58, 0x57, 0x55, 0x36, 0x76, 0x62, 0x77, - 0x4b, 0x69, 0x61, 0x2f, 0x4c, 0x44, 0x58, 0x38, 0x52, 0x39, 0x38, 0x61, - 0x79, 0x34, 0x43, 0x69, 0x32, 0x7a, 0x6f, 0x44, 0x58, 0x78, 0x65, 0x37, - 0x51, 0x42, 0x6e, 0x76, 0x6e, 0x57, 0x62, 0x73, 0x32, 0x6d, 0x36, 0x39, - 0x48, 0x50, 0x68, 0x36, 0x6f, 0x70, 0x6d, 0x6f, 0x35, 0x67, 0x4b, 0x4c, - 0x2b, 0x0a, 0x79, 0x36, 0x35, 0x53, 0x66, 0x36, 0x4d, 0x41, 0x69, 0x35, - 0x75, 0x64, 0x49, 0x4a, 0x4c, 0x56, 0x66, 0x67, 0x58, 0x51, 0x42, 0x67, - 0x52, 0x79, 0x58, 0x33, 0x67, 0x6c, 0x53, 0x37, 0x2f, 0x72, 0x48, 0x38, - 0x59, 0x62, 0x72, 0x72, 0x4e, 0x59, 0x39, 0x49, 0x6f, 0x70, 0x31, 0x4b, - 0x63, 0x53, 0x57, 0x58, 0x41, 0x49, 0x43, 0x34, 0x7a, 0x6c, 0x43, 0x6f, - 0x4f, 0x33, 0x74, 0x42, 0x4a, 0x42, 0x0a, 0x39, 0x34, 0x36, 0x34, 0x59, - 0x42, 0x44, 0x2f, 0x52, 0x2b, 0x71, 0x4f, 0x76, 0x56, 0x4d, 0x63, 0x42, - 0x47, 0x78, 0x54, 0x6a, 0x61, 0x62, 0x75, 0x64, 0x69, 0x30, 0x30, 0x6f, - 0x75, 0x67, 0x65, 0x54, 0x67, 0x73, 0x53, 0x37, 0x69, 0x64, 0x44, 0x54, - 0x6d, 0x66, 0x63, 0x34, 0x48, 0x59, 0x49, 0x6c, 0x73, 0x30, 0x45, 0x37, - 0x79, 0x57, 0x71, 0x7a, 0x67, 0x73, 0x70, 0x73, 0x77, 0x73, 0x35, 0x0a, - 0x77, 0x37, 0x4b, 0x34, 0x63, 0x72, 0x53, 0x67, 0x6d, 0x2b, 0x75, 0x33, - 0x6f, 0x79, 0x70, 0x56, 0x69, 0x55, 0x53, 0x72, 0x65, 0x32, 0x71, 0x53, - 0x76, 0x41, 0x48, 0x54, 0x43, 0x35, 0x67, 0x58, 0x74, 0x68, 0x38, 0x4c, - 0x56, 0x43, 0x6e, 0x44, 0x5a, 0x75, 0x41, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x52, 0x53, 0x41, 0x20, 0x50, 0x52, - 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, - ]), - public: undefined, - publicOrig: undefined - }, - what: 'Encrypted RSA private key (OpenSSH format)' - }, - { source: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRLlnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0fxoLSF3lxQFJ+32/rS0=', - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, - 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0xe5, - 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, 0xb5, - 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, 0x5f, - 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, 0x33, - 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, 0xb1, - 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, 0xde, - 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, 0x02, - 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, 0x0b, - 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x20, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, 0x41, - 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, 0x41, - 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, 0x78, - 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, 0x72, - 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, 0x66, - 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x6c, 0x6e, 0x52, 0x35, 0x4f, 0x36, - 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, 0x65, 0x4f, - 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, 0x57, 0x6f, - 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, 0x72, 0x65, - 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, 0x76, 0x78, - 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, 0x52, 0x36, - 0x68, 0x51, 0x58, 0x30, 0x66, 0x78, 0x6f, 0x4c, 0x53, 0x46, 0x33, 0x6c, - 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, 0x53, 0x30, 0x3d, - ]) - }, - what: 'RSA public key (OpenSSH format)' - }, - { source: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQD3txsEf0HAKElAFUvIXzsM98gfPlIbG4/GlqbYYBulkHu6z0laOdoT14Zx2M+3q+9RjhTZjHxyMfePdcgNK9z98V6tOz5bIQhtMS8tl1Tnw5qZByGqpqOKf665ev62LaM= testing-ssh2-from-node.js', - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'testing-ssh2-from-node.js', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, - 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, 0xf7, - 0xb7, 0x1b, 0x04, 0x7f, 0x41, 0xc0, 0x28, 0x49, 0x40, 0x15, 0x4b, 0xc8, - 0x5f, 0x3b, 0x0c, 0xf7, 0xc8, 0x1f, 0x3e, 0x52, 0x1b, 0x1b, 0x8f, 0xc6, - 0x96, 0xa6, 0xd8, 0x60, 0x1b, 0xa5, 0x90, 0x7b, 0xba, 0xcf, 0x49, 0x5a, - 0x39, 0xda, 0x13, 0xd7, 0x86, 0x71, 0xd8, 0xcf, 0xb7, 0xab, 0xef, 0x51, - 0x8e, 0x14, 0xd9, 0x8c, 0x7c, 0x72, 0x31, 0xf7, 0x8f, 0x75, 0xc8, 0x0d, - 0x2b, 0xdc, 0xfd, 0xf1, 0x5e, 0xad, 0x3b, 0x3e, 0x5b, 0x21, 0x08, 0x6d, - 0x31, 0x2f, 0x2d, 0x97, 0x54, 0xe7, 0xc3, 0x9a, 0x99, 0x07, 0x21, 0xaa, - 0xa6, 0xa3, 0x8a, 0x7f, 0xae, 0xb9, 0x7a, 0xfe, 0xb6, 0x2d, 0xa3, - ]), - publicOrig: new Buffer([ - 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x20, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, 0x41, - 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, 0x41, - 0x59, 0x51, 0x44, 0x33, 0x74, 0x78, 0x73, 0x45, 0x66, 0x30, 0x48, 0x41, - 0x4b, 0x45, 0x6c, 0x41, 0x46, 0x55, 0x76, 0x49, 0x58, 0x7a, 0x73, 0x4d, - 0x39, 0x38, 0x67, 0x66, 0x50, 0x6c, 0x49, 0x62, 0x47, 0x34, 0x2f, 0x47, - 0x6c, 0x71, 0x62, 0x59, 0x59, 0x42, 0x75, 0x6c, 0x6b, 0x48, 0x75, 0x36, - 0x7a, 0x30, 0x6c, 0x61, 0x4f, 0x64, 0x6f, 0x54, 0x31, 0x34, 0x5a, 0x78, - 0x32, 0x4d, 0x2b, 0x33, 0x71, 0x2b, 0x39, 0x52, 0x6a, 0x68, 0x54, 0x5a, - 0x6a, 0x48, 0x78, 0x79, 0x4d, 0x66, 0x65, 0x50, 0x64, 0x63, 0x67, 0x4e, - 0x4b, 0x39, 0x7a, 0x39, 0x38, 0x56, 0x36, 0x74, 0x4f, 0x7a, 0x35, 0x62, - 0x49, 0x51, 0x68, 0x74, 0x4d, 0x53, 0x38, 0x74, 0x6c, 0x31, 0x54, 0x6e, - 0x77, 0x35, 0x71, 0x5a, 0x42, 0x79, 0x47, 0x71, 0x70, 0x71, 0x4f, 0x4b, - 0x66, 0x36, 0x36, 0x35, 0x65, 0x76, 0x36, 0x32, 0x4c, 0x61, 0x4d, 0x3d, - 0x20, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x73, 0x68, - 0x32, 0x2d, 0x66, 0x72, 0x6f, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6a, 0x73, - ]) - }, - what: 'RSA public key with comment (OpenSSH format)' - }, - { source: [ - '-----BEGIN DSA PRIVATE KEY-----', - 'MIIBuwIBAAKBgQD7v1kR31D2NhZIzOjJL1hPzvw79K3eWZqQEgqKmeB+P9MhOx51', - 'MOZrvs3hZoYqmsNxT/Y29EwQ+o+SXpTYjJhw/s2vR0AeJBj32l8weD804+T+S8yr', - 'MJBdgsc5AbV2XYKnsNzl65kAEOLPCobUNysKqYnJ8naYCYL3jjwGhW36iwIVANqh', - 'gZgvnVpVXyYx1GlceA5/8mI1AoGBAOyjuQhGoOW4hILR02WrqwCEPqhRyMp87dMU', - '9z0PQKKrACmiQpEUawvtR4aMB7Xzy+f6MRLwdonQISzswopa7Gwl3CYLiOdKFFIQ', - 'zDdymwGovTjN2fQm8v/UHdafZBPImGBDzf+iykNBhZc7UP1rciMzKOnT3BTF/al8', - 'hhBy0bjsAoGAYrykryPYWUGArKS6NO9Ijtwc7SbbNXZCuBcl6hc1Hdr1UEEKQcsW', - '5fajF5Ut9ZLwcggsWSKZtZk9NA7xybmObuDEU7oiFFNRAbBkam/v/3a3bwvSHGKg', - 'q15cvC313zg1ii9NXylvBIoIS8EWfekl1LMvHC7NdJ41wPYhhmPrUk4CFHJjavJH', - 'kb6tDtemyiAq3N9aQj/D', - '-----END DSA PRIVATE KEY-----' - ].join('\n'), - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: new Buffer([ - 0x30, 0x82, 0x01, 0xbb, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xfb, - 0xbf, 0x59, 0x11, 0xdf, 0x50, 0xf6, 0x36, 0x16, 0x48, 0xcc, 0xe8, 0xc9, - 0x2f, 0x58, 0x4f, 0xce, 0xfc, 0x3b, 0xf4, 0xad, 0xde, 0x59, 0x9a, 0x90, - 0x12, 0x0a, 0x8a, 0x99, 0xe0, 0x7e, 0x3f, 0xd3, 0x21, 0x3b, 0x1e, 0x75, - 0x30, 0xe6, 0x6b, 0xbe, 0xcd, 0xe1, 0x66, 0x86, 0x2a, 0x9a, 0xc3, 0x71, - 0x4f, 0xf6, 0x36, 0xf4, 0x4c, 0x10, 0xfa, 0x8f, 0x92, 0x5e, 0x94, 0xd8, - 0x8c, 0x98, 0x70, 0xfe, 0xcd, 0xaf, 0x47, 0x40, 0x1e, 0x24, 0x18, 0xf7, - 0xda, 0x5f, 0x30, 0x78, 0x3f, 0x34, 0xe3, 0xe4, 0xfe, 0x4b, 0xcc, 0xab, - 0x30, 0x90, 0x5d, 0x82, 0xc7, 0x39, 0x01, 0xb5, 0x76, 0x5d, 0x82, 0xa7, - 0xb0, 0xdc, 0xe5, 0xeb, 0x99, 0x00, 0x10, 0xe2, 0xcf, 0x0a, 0x86, 0xd4, - 0x37, 0x2b, 0x0a, 0xa9, 0x89, 0xc9, 0xf2, 0x76, 0x98, 0x09, 0x82, 0xf7, - 0x8e, 0x3c, 0x06, 0x85, 0x6d, 0xfa, 0x8b, 0x02, 0x15, 0x00, 0xda, 0xa1, - 0x81, 0x98, 0x2f, 0x9d, 0x5a, 0x55, 0x5f, 0x26, 0x31, 0xd4, 0x69, 0x5c, - 0x78, 0x0e, 0x7f, 0xf2, 0x62, 0x35, 0x02, 0x81, 0x81, 0x00, 0xec, 0xa3, - 0xb9, 0x08, 0x46, 0xa0, 0xe5, 0xb8, 0x84, 0x82, 0xd1, 0xd3, 0x65, 0xab, - 0xab, 0x00, 0x84, 0x3e, 0xa8, 0x51, 0xc8, 0xca, 0x7c, 0xed, 0xd3, 0x14, - 0xf7, 0x3d, 0x0f, 0x40, 0xa2, 0xab, 0x00, 0x29, 0xa2, 0x42, 0x91, 0x14, - 0x6b, 0x0b, 0xed, 0x47, 0x86, 0x8c, 0x07, 0xb5, 0xf3, 0xcb, 0xe7, 0xfa, - 0x31, 0x12, 0xf0, 0x76, 0x89, 0xd0, 0x21, 0x2c, 0xec, 0xc2, 0x8a, 0x5a, - 0xec, 0x6c, 0x25, 0xdc, 0x26, 0x0b, 0x88, 0xe7, 0x4a, 0x14, 0x52, 0x10, - 0xcc, 0x37, 0x72, 0x9b, 0x01, 0xa8, 0xbd, 0x38, 0xcd, 0xd9, 0xf4, 0x26, - 0xf2, 0xff, 0xd4, 0x1d, 0xd6, 0x9f, 0x64, 0x13, 0xc8, 0x98, 0x60, 0x43, - 0xcd, 0xff, 0xa2, 0xca, 0x43, 0x41, 0x85, 0x97, 0x3b, 0x50, 0xfd, 0x6b, - 0x72, 0x23, 0x33, 0x28, 0xe9, 0xd3, 0xdc, 0x14, 0xc5, 0xfd, 0xa9, 0x7c, - 0x86, 0x10, 0x72, 0xd1, 0xb8, 0xec, 0x02, 0x81, 0x80, 0x62, 0xbc, 0xa4, - 0xaf, 0x23, 0xd8, 0x59, 0x41, 0x80, 0xac, 0xa4, 0xba, 0x34, 0xef, 0x48, - 0x8e, 0xdc, 0x1c, 0xed, 0x26, 0xdb, 0x35, 0x76, 0x42, 0xb8, 0x17, 0x25, - 0xea, 0x17, 0x35, 0x1d, 0xda, 0xf5, 0x50, 0x41, 0x0a, 0x41, 0xcb, 0x16, - 0xe5, 0xf6, 0xa3, 0x17, 0x95, 0x2d, 0xf5, 0x92, 0xf0, 0x72, 0x08, 0x2c, - 0x59, 0x22, 0x99, 0xb5, 0x99, 0x3d, 0x34, 0x0e, 0xf1, 0xc9, 0xb9, 0x8e, - 0x6e, 0xe0, 0xc4, 0x53, 0xba, 0x22, 0x14, 0x53, 0x51, 0x01, 0xb0, 0x64, - 0x6a, 0x6f, 0xef, 0xff, 0x76, 0xb7, 0x6f, 0x0b, 0xd2, 0x1c, 0x62, 0xa0, - 0xab, 0x5e, 0x5c, 0xbc, 0x2d, 0xf5, 0xdf, 0x38, 0x35, 0x8a, 0x2f, 0x4d, - 0x5f, 0x29, 0x6f, 0x04, 0x8a, 0x08, 0x4b, 0xc1, 0x16, 0x7d, 0xe9, 0x25, - 0xd4, 0xb3, 0x2f, 0x1c, 0x2e, 0xcd, 0x74, 0x9e, 0x35, 0xc0, 0xf6, 0x21, - 0x86, 0x63, 0xeb, 0x52, 0x4e, 0x02, 0x14, 0x72, 0x63, 0x6a, 0xf2, 0x47, - 0x91, 0xbe, 0xad, 0x0e, 0xd7, 0xa6, 0xca, 0x20, 0x2a, 0xdc, 0xdf, 0x5a, - 0x42, 0x3f, 0xc3, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x44, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, - 0x75, 0x77, 0x49, 0x42, 0x41, 0x41, 0x4b, 0x42, 0x67, 0x51, 0x44, 0x37, - 0x76, 0x31, 0x6b, 0x52, 0x33, 0x31, 0x44, 0x32, 0x4e, 0x68, 0x5a, 0x49, - 0x7a, 0x4f, 0x6a, 0x4a, 0x4c, 0x31, 0x68, 0x50, 0x7a, 0x76, 0x77, 0x37, - 0x39, 0x4b, 0x33, 0x65, 0x57, 0x5a, 0x71, 0x51, 0x45, 0x67, 0x71, 0x4b, - 0x6d, 0x65, 0x42, 0x2b, 0x50, 0x39, 0x4d, 0x68, 0x4f, 0x78, 0x35, 0x31, - 0x0a, 0x4d, 0x4f, 0x5a, 0x72, 0x76, 0x73, 0x33, 0x68, 0x5a, 0x6f, 0x59, - 0x71, 0x6d, 0x73, 0x4e, 0x78, 0x54, 0x2f, 0x59, 0x32, 0x39, 0x45, 0x77, - 0x51, 0x2b, 0x6f, 0x2b, 0x53, 0x58, 0x70, 0x54, 0x59, 0x6a, 0x4a, 0x68, - 0x77, 0x2f, 0x73, 0x32, 0x76, 0x52, 0x30, 0x41, 0x65, 0x4a, 0x42, 0x6a, - 0x33, 0x32, 0x6c, 0x38, 0x77, 0x65, 0x44, 0x38, 0x30, 0x34, 0x2b, 0x54, - 0x2b, 0x53, 0x38, 0x79, 0x72, 0x0a, 0x4d, 0x4a, 0x42, 0x64, 0x67, 0x73, - 0x63, 0x35, 0x41, 0x62, 0x56, 0x32, 0x58, 0x59, 0x4b, 0x6e, 0x73, 0x4e, - 0x7a, 0x6c, 0x36, 0x35, 0x6b, 0x41, 0x45, 0x4f, 0x4c, 0x50, 0x43, 0x6f, - 0x62, 0x55, 0x4e, 0x79, 0x73, 0x4b, 0x71, 0x59, 0x6e, 0x4a, 0x38, 0x6e, - 0x61, 0x59, 0x43, 0x59, 0x4c, 0x33, 0x6a, 0x6a, 0x77, 0x47, 0x68, 0x57, - 0x33, 0x36, 0x69, 0x77, 0x49, 0x56, 0x41, 0x4e, 0x71, 0x68, 0x0a, 0x67, - 0x5a, 0x67, 0x76, 0x6e, 0x56, 0x70, 0x56, 0x58, 0x79, 0x59, 0x78, 0x31, - 0x47, 0x6c, 0x63, 0x65, 0x41, 0x35, 0x2f, 0x38, 0x6d, 0x49, 0x31, 0x41, - 0x6f, 0x47, 0x42, 0x41, 0x4f, 0x79, 0x6a, 0x75, 0x51, 0x68, 0x47, 0x6f, - 0x4f, 0x57, 0x34, 0x68, 0x49, 0x4c, 0x52, 0x30, 0x32, 0x57, 0x72, 0x71, - 0x77, 0x43, 0x45, 0x50, 0x71, 0x68, 0x52, 0x79, 0x4d, 0x70, 0x38, 0x37, - 0x64, 0x4d, 0x55, 0x0a, 0x39, 0x7a, 0x30, 0x50, 0x51, 0x4b, 0x4b, 0x72, - 0x41, 0x43, 0x6d, 0x69, 0x51, 0x70, 0x45, 0x55, 0x61, 0x77, 0x76, 0x74, - 0x52, 0x34, 0x61, 0x4d, 0x42, 0x37, 0x58, 0x7a, 0x79, 0x2b, 0x66, 0x36, - 0x4d, 0x52, 0x4c, 0x77, 0x64, 0x6f, 0x6e, 0x51, 0x49, 0x53, 0x7a, 0x73, - 0x77, 0x6f, 0x70, 0x61, 0x37, 0x47, 0x77, 0x6c, 0x33, 0x43, 0x59, 0x4c, - 0x69, 0x4f, 0x64, 0x4b, 0x46, 0x46, 0x49, 0x51, 0x0a, 0x7a, 0x44, 0x64, - 0x79, 0x6d, 0x77, 0x47, 0x6f, 0x76, 0x54, 0x6a, 0x4e, 0x32, 0x66, 0x51, - 0x6d, 0x38, 0x76, 0x2f, 0x55, 0x48, 0x64, 0x61, 0x66, 0x5a, 0x42, 0x50, - 0x49, 0x6d, 0x47, 0x42, 0x44, 0x7a, 0x66, 0x2b, 0x69, 0x79, 0x6b, 0x4e, - 0x42, 0x68, 0x5a, 0x63, 0x37, 0x55, 0x50, 0x31, 0x72, 0x63, 0x69, 0x4d, - 0x7a, 0x4b, 0x4f, 0x6e, 0x54, 0x33, 0x42, 0x54, 0x46, 0x2f, 0x61, 0x6c, - 0x38, 0x0a, 0x68, 0x68, 0x42, 0x79, 0x30, 0x62, 0x6a, 0x73, 0x41, 0x6f, - 0x47, 0x41, 0x59, 0x72, 0x79, 0x6b, 0x72, 0x79, 0x50, 0x59, 0x57, 0x55, - 0x47, 0x41, 0x72, 0x4b, 0x53, 0x36, 0x4e, 0x4f, 0x39, 0x49, 0x6a, 0x74, - 0x77, 0x63, 0x37, 0x53, 0x62, 0x62, 0x4e, 0x58, 0x5a, 0x43, 0x75, 0x42, - 0x63, 0x6c, 0x36, 0x68, 0x63, 0x31, 0x48, 0x64, 0x72, 0x31, 0x55, 0x45, - 0x45, 0x4b, 0x51, 0x63, 0x73, 0x57, 0x0a, 0x35, 0x66, 0x61, 0x6a, 0x46, - 0x35, 0x55, 0x74, 0x39, 0x5a, 0x4c, 0x77, 0x63, 0x67, 0x67, 0x73, 0x57, - 0x53, 0x4b, 0x5a, 0x74, 0x5a, 0x6b, 0x39, 0x4e, 0x41, 0x37, 0x78, 0x79, - 0x62, 0x6d, 0x4f, 0x62, 0x75, 0x44, 0x45, 0x55, 0x37, 0x6f, 0x69, 0x46, - 0x46, 0x4e, 0x52, 0x41, 0x62, 0x42, 0x6b, 0x61, 0x6d, 0x2f, 0x76, 0x2f, - 0x33, 0x61, 0x33, 0x62, 0x77, 0x76, 0x53, 0x48, 0x47, 0x4b, 0x67, 0x0a, - 0x71, 0x31, 0x35, 0x63, 0x76, 0x43, 0x33, 0x31, 0x33, 0x7a, 0x67, 0x31, - 0x69, 0x69, 0x39, 0x4e, 0x58, 0x79, 0x6c, 0x76, 0x42, 0x49, 0x6f, 0x49, - 0x53, 0x38, 0x45, 0x57, 0x66, 0x65, 0x6b, 0x6c, 0x31, 0x4c, 0x4d, 0x76, - 0x48, 0x43, 0x37, 0x4e, 0x64, 0x4a, 0x34, 0x31, 0x77, 0x50, 0x59, 0x68, - 0x68, 0x6d, 0x50, 0x72, 0x55, 0x6b, 0x34, 0x43, 0x46, 0x48, 0x4a, 0x6a, - 0x61, 0x76, 0x4a, 0x48, 0x0a, 0x6b, 0x62, 0x36, 0x74, 0x44, 0x74, 0x65, - 0x6d, 0x79, 0x69, 0x41, 0x71, 0x33, 0x4e, 0x39, 0x61, 0x51, 0x6a, 0x2f, - 0x44, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x44, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - public: undefined, - publicOrig: undefined - }, - what: 'Unencrypted DSA private key (OpenSSH format)' - }, - { source: [ - '-----BEGIN DSA PRIVATE KEY-----', - 'Proc-Type: 4,ENCRYPTED', - 'DEK-Info: AES-128-CBC,D6218FEC397F57918B06DC3F9EC33487', - '', - 'OjtbW9WChM2baMDRXW/IYhmqAmlaulb8pQd0rDcFYGrAS/5PnA96R3X6f9tdooSv', - 'uPrQ37oCI7FfDrRmVy6pn6QOLxLZHk7LViBAA7q8VytRHUyezauicTkhc6/nfxQU', - 'tYN5dNajSl/aFuv/IitaYtuG2ORvXLLJhR3sYe5fs2ai14qtULdWxtrZ4cACXPSz', - 'Ij29/lUfeBIYxNFFDF5hgsyO+jHLHO8bJCgXLCEb1o/Im68kQT3LjmvLbdhVM2+V', - '5c+YVDW/yXKpaSDNqctJFsETP3SsI5k9PVijSeND4U27W9HAoukJmG8jNBXmMOKW', - 'MtOEp0Yw5+fu0OPTACMcK7UoiN90RTFLNcDT9kKjeQwqk37sZBNyOpnQ57Mu6YWX', - 'BS5nnT4bK/WpyWUgGJ+MVzcp6pErBUy3SxlV2LN/LIZq+YzME55sygtwNSuVhpBH', - '+9UwrUIlaT8Ru//OdRKY5Vp8AqomjlAzCkBxnmC9XhVB0r4zqsqgVyzSfsX+oGLe', - 'dbixpbeMXe3WoAowx6LmqojuP46MIL80/9BH6Xr51UqJj156bYXashJtgpYaAQIn', - '8YB9sXf4S027sgHxK0Xanw==', - '-----END DSA PRIVATE KEY-----' - ].join('\n'), - expected: { - fulltype: undefined, - type: 'dss', - curve: undefined, - extra: [ 'D6218FEC397F57918B06DC3F9EC33487' ], - comment: undefined, - encryption: 'aes-128-cbc', - private: new Buffer([ - 0x3a, 0x3b, 0x5b, 0x5b, 0xd5, 0x82, 0x84, 0xcd, 0x9b, 0x68, 0xc0, 0xd1, - 0x5d, 0x6f, 0xc8, 0x62, 0x19, 0xaa, 0x02, 0x69, 0x5a, 0xba, 0x56, 0xfc, - 0xa5, 0x07, 0x74, 0xac, 0x37, 0x05, 0x60, 0x6a, 0xc0, 0x4b, 0xfe, 0x4f, - 0x9c, 0x0f, 0x7a, 0x47, 0x75, 0xfa, 0x7f, 0xdb, 0x5d, 0xa2, 0x84, 0xaf, - 0xb8, 0xfa, 0xd0, 0xdf, 0xba, 0x02, 0x23, 0xb1, 0x5f, 0x0e, 0xb4, 0x66, - 0x57, 0x2e, 0xa9, 0x9f, 0xa4, 0x0e, 0x2f, 0x12, 0xd9, 0x1e, 0x4e, 0xcb, - 0x56, 0x20, 0x40, 0x03, 0xba, 0xbc, 0x57, 0x2b, 0x51, 0x1d, 0x4c, 0x9e, - 0xcd, 0xab, 0xa2, 0x71, 0x39, 0x21, 0x73, 0xaf, 0xe7, 0x7f, 0x14, 0x14, - 0xb5, 0x83, 0x79, 0x74, 0xd6, 0xa3, 0x4a, 0x5f, 0xda, 0x16, 0xeb, 0xff, - 0x22, 0x2b, 0x5a, 0x62, 0xdb, 0x86, 0xd8, 0xe4, 0x6f, 0x5c, 0xb2, 0xc9, - 0x85, 0x1d, 0xec, 0x61, 0xee, 0x5f, 0xb3, 0x66, 0xa2, 0xd7, 0x8a, 0xad, - 0x50, 0xb7, 0x56, 0xc6, 0xda, 0xd9, 0xe1, 0xc0, 0x02, 0x5c, 0xf4, 0xb3, - 0x22, 0x3d, 0xbd, 0xfe, 0x55, 0x1f, 0x78, 0x12, 0x18, 0xc4, 0xd1, 0x45, - 0x0c, 0x5e, 0x61, 0x82, 0xcc, 0x8e, 0xfa, 0x31, 0xcb, 0x1c, 0xef, 0x1b, - 0x24, 0x28, 0x17, 0x2c, 0x21, 0x1b, 0xd6, 0x8f, 0xc8, 0x9b, 0xaf, 0x24, - 0x41, 0x3d, 0xcb, 0x8e, 0x6b, 0xcb, 0x6d, 0xd8, 0x55, 0x33, 0x6f, 0x95, - 0xe5, 0xcf, 0x98, 0x54, 0x35, 0xbf, 0xc9, 0x72, 0xa9, 0x69, 0x20, 0xcd, - 0xa9, 0xcb, 0x49, 0x16, 0xc1, 0x13, 0x3f, 0x74, 0xac, 0x23, 0x99, 0x3d, - 0x3d, 0x58, 0xa3, 0x49, 0xe3, 0x43, 0xe1, 0x4d, 0xbb, 0x5b, 0xd1, 0xc0, - 0xa2, 0xe9, 0x09, 0x98, 0x6f, 0x23, 0x34, 0x15, 0xe6, 0x30, 0xe2, 0x96, - 0x32, 0xd3, 0x84, 0xa7, 0x46, 0x30, 0xe7, 0xe7, 0xee, 0xd0, 0xe3, 0xd3, - 0x00, 0x23, 0x1c, 0x2b, 0xb5, 0x28, 0x88, 0xdf, 0x74, 0x45, 0x31, 0x4b, - 0x35, 0xc0, 0xd3, 0xf6, 0x42, 0xa3, 0x79, 0x0c, 0x2a, 0x93, 0x7e, 0xec, - 0x64, 0x13, 0x72, 0x3a, 0x99, 0xd0, 0xe7, 0xb3, 0x2e, 0xe9, 0x85, 0x97, - 0x05, 0x2e, 0x67, 0x9d, 0x3e, 0x1b, 0x2b, 0xf5, 0xa9, 0xc9, 0x65, 0x20, - 0x18, 0x9f, 0x8c, 0x57, 0x37, 0x29, 0xea, 0x91, 0x2b, 0x05, 0x4c, 0xb7, - 0x4b, 0x19, 0x55, 0xd8, 0xb3, 0x7f, 0x2c, 0x86, 0x6a, 0xf9, 0x8c, 0xcc, - 0x13, 0x9e, 0x6c, 0xca, 0x0b, 0x70, 0x35, 0x2b, 0x95, 0x86, 0x90, 0x47, - 0xfb, 0xd5, 0x30, 0xad, 0x42, 0x25, 0x69, 0x3f, 0x11, 0xbb, 0xff, 0xce, - 0x75, 0x12, 0x98, 0xe5, 0x5a, 0x7c, 0x02, 0xaa, 0x26, 0x8e, 0x50, 0x33, - 0x0a, 0x40, 0x71, 0x9e, 0x60, 0xbd, 0x5e, 0x15, 0x41, 0xd2, 0xbe, 0x33, - 0xaa, 0xca, 0xa0, 0x57, 0x2c, 0xd2, 0x7e, 0xc5, 0xfe, 0xa0, 0x62, 0xde, - 0x75, 0xb8, 0xb1, 0xa5, 0xb7, 0x8c, 0x5d, 0xed, 0xd6, 0xa0, 0x0a, 0x30, - 0xc7, 0xa2, 0xe6, 0xaa, 0x88, 0xee, 0x3f, 0x8e, 0x8c, 0x20, 0xbf, 0x34, - 0xff, 0xd0, 0x47, 0xe9, 0x7a, 0xf9, 0xd5, 0x4a, 0x89, 0x8f, 0x5e, 0x7a, - 0x6d, 0x85, 0xda, 0xb2, 0x12, 0x6d, 0x82, 0x96, 0x1a, 0x01, 0x02, 0x27, - 0xf1, 0x80, 0x7d, 0xb1, 0x77, 0xf8, 0x4b, 0x4d, 0xbb, 0xb2, 0x01, 0xf1, - 0x2b, 0x45, 0xda, 0x9f, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x44, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x50, 0x72, 0x6f, 0x63, - 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x34, 0x2c, 0x45, 0x4e, 0x43, - 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x0a, 0x44, 0x45, 0x4b, 0x2d, 0x49, - 0x6e, 0x66, 0x6f, 0x3a, 0x20, 0x41, 0x45, 0x53, 0x2d, 0x31, 0x32, 0x38, - 0x2d, 0x43, 0x42, 0x43, 0x2c, 0x44, 0x36, 0x32, 0x31, 0x38, 0x46, 0x45, - 0x43, 0x33, 0x39, 0x37, 0x46, 0x35, 0x37, 0x39, 0x31, 0x38, 0x42, 0x30, - 0x36, 0x44, 0x43, 0x33, 0x46, 0x39, 0x45, 0x43, 0x33, 0x33, 0x34, 0x38, - 0x37, 0x0a, 0x0a, 0x4f, 0x6a, 0x74, 0x62, 0x57, 0x39, 0x57, 0x43, 0x68, - 0x4d, 0x32, 0x62, 0x61, 0x4d, 0x44, 0x52, 0x58, 0x57, 0x2f, 0x49, 0x59, - 0x68, 0x6d, 0x71, 0x41, 0x6d, 0x6c, 0x61, 0x75, 0x6c, 0x62, 0x38, 0x70, - 0x51, 0x64, 0x30, 0x72, 0x44, 0x63, 0x46, 0x59, 0x47, 0x72, 0x41, 0x53, - 0x2f, 0x35, 0x50, 0x6e, 0x41, 0x39, 0x36, 0x52, 0x33, 0x58, 0x36, 0x66, - 0x39, 0x74, 0x64, 0x6f, 0x6f, 0x53, 0x76, 0x0a, 0x75, 0x50, 0x72, 0x51, - 0x33, 0x37, 0x6f, 0x43, 0x49, 0x37, 0x46, 0x66, 0x44, 0x72, 0x52, 0x6d, - 0x56, 0x79, 0x36, 0x70, 0x6e, 0x36, 0x51, 0x4f, 0x4c, 0x78, 0x4c, 0x5a, - 0x48, 0x6b, 0x37, 0x4c, 0x56, 0x69, 0x42, 0x41, 0x41, 0x37, 0x71, 0x38, - 0x56, 0x79, 0x74, 0x52, 0x48, 0x55, 0x79, 0x65, 0x7a, 0x61, 0x75, 0x69, - 0x63, 0x54, 0x6b, 0x68, 0x63, 0x36, 0x2f, 0x6e, 0x66, 0x78, 0x51, 0x55, - 0x0a, 0x74, 0x59, 0x4e, 0x35, 0x64, 0x4e, 0x61, 0x6a, 0x53, 0x6c, 0x2f, - 0x61, 0x46, 0x75, 0x76, 0x2f, 0x49, 0x69, 0x74, 0x61, 0x59, 0x74, 0x75, - 0x47, 0x32, 0x4f, 0x52, 0x76, 0x58, 0x4c, 0x4c, 0x4a, 0x68, 0x52, 0x33, - 0x73, 0x59, 0x65, 0x35, 0x66, 0x73, 0x32, 0x61, 0x69, 0x31, 0x34, 0x71, - 0x74, 0x55, 0x4c, 0x64, 0x57, 0x78, 0x74, 0x72, 0x5a, 0x34, 0x63, 0x41, - 0x43, 0x58, 0x50, 0x53, 0x7a, 0x0a, 0x49, 0x6a, 0x32, 0x39, 0x2f, 0x6c, - 0x55, 0x66, 0x65, 0x42, 0x49, 0x59, 0x78, 0x4e, 0x46, 0x46, 0x44, 0x46, - 0x35, 0x68, 0x67, 0x73, 0x79, 0x4f, 0x2b, 0x6a, 0x48, 0x4c, 0x48, 0x4f, - 0x38, 0x62, 0x4a, 0x43, 0x67, 0x58, 0x4c, 0x43, 0x45, 0x62, 0x31, 0x6f, - 0x2f, 0x49, 0x6d, 0x36, 0x38, 0x6b, 0x51, 0x54, 0x33, 0x4c, 0x6a, 0x6d, - 0x76, 0x4c, 0x62, 0x64, 0x68, 0x56, 0x4d, 0x32, 0x2b, 0x56, 0x0a, 0x35, - 0x63, 0x2b, 0x59, 0x56, 0x44, 0x57, 0x2f, 0x79, 0x58, 0x4b, 0x70, 0x61, - 0x53, 0x44, 0x4e, 0x71, 0x63, 0x74, 0x4a, 0x46, 0x73, 0x45, 0x54, 0x50, - 0x33, 0x53, 0x73, 0x49, 0x35, 0x6b, 0x39, 0x50, 0x56, 0x69, 0x6a, 0x53, - 0x65, 0x4e, 0x44, 0x34, 0x55, 0x32, 0x37, 0x57, 0x39, 0x48, 0x41, 0x6f, - 0x75, 0x6b, 0x4a, 0x6d, 0x47, 0x38, 0x6a, 0x4e, 0x42, 0x58, 0x6d, 0x4d, - 0x4f, 0x4b, 0x57, 0x0a, 0x4d, 0x74, 0x4f, 0x45, 0x70, 0x30, 0x59, 0x77, - 0x35, 0x2b, 0x66, 0x75, 0x30, 0x4f, 0x50, 0x54, 0x41, 0x43, 0x4d, 0x63, - 0x4b, 0x37, 0x55, 0x6f, 0x69, 0x4e, 0x39, 0x30, 0x52, 0x54, 0x46, 0x4c, - 0x4e, 0x63, 0x44, 0x54, 0x39, 0x6b, 0x4b, 0x6a, 0x65, 0x51, 0x77, 0x71, - 0x6b, 0x33, 0x37, 0x73, 0x5a, 0x42, 0x4e, 0x79, 0x4f, 0x70, 0x6e, 0x51, - 0x35, 0x37, 0x4d, 0x75, 0x36, 0x59, 0x57, 0x58, 0x0a, 0x42, 0x53, 0x35, - 0x6e, 0x6e, 0x54, 0x34, 0x62, 0x4b, 0x2f, 0x57, 0x70, 0x79, 0x57, 0x55, - 0x67, 0x47, 0x4a, 0x2b, 0x4d, 0x56, 0x7a, 0x63, 0x70, 0x36, 0x70, 0x45, - 0x72, 0x42, 0x55, 0x79, 0x33, 0x53, 0x78, 0x6c, 0x56, 0x32, 0x4c, 0x4e, - 0x2f, 0x4c, 0x49, 0x5a, 0x71, 0x2b, 0x59, 0x7a, 0x4d, 0x45, 0x35, 0x35, - 0x73, 0x79, 0x67, 0x74, 0x77, 0x4e, 0x53, 0x75, 0x56, 0x68, 0x70, 0x42, - 0x48, 0x0a, 0x2b, 0x39, 0x55, 0x77, 0x72, 0x55, 0x49, 0x6c, 0x61, 0x54, - 0x38, 0x52, 0x75, 0x2f, 0x2f, 0x4f, 0x64, 0x52, 0x4b, 0x59, 0x35, 0x56, - 0x70, 0x38, 0x41, 0x71, 0x6f, 0x6d, 0x6a, 0x6c, 0x41, 0x7a, 0x43, 0x6b, - 0x42, 0x78, 0x6e, 0x6d, 0x43, 0x39, 0x58, 0x68, 0x56, 0x42, 0x30, 0x72, - 0x34, 0x7a, 0x71, 0x73, 0x71, 0x67, 0x56, 0x79, 0x7a, 0x53, 0x66, 0x73, - 0x58, 0x2b, 0x6f, 0x47, 0x4c, 0x65, 0x0a, 0x64, 0x62, 0x69, 0x78, 0x70, - 0x62, 0x65, 0x4d, 0x58, 0x65, 0x33, 0x57, 0x6f, 0x41, 0x6f, 0x77, 0x78, - 0x36, 0x4c, 0x6d, 0x71, 0x6f, 0x6a, 0x75, 0x50, 0x34, 0x36, 0x4d, 0x49, - 0x4c, 0x38, 0x30, 0x2f, 0x39, 0x42, 0x48, 0x36, 0x58, 0x72, 0x35, 0x31, - 0x55, 0x71, 0x4a, 0x6a, 0x31, 0x35, 0x36, 0x62, 0x59, 0x58, 0x61, 0x73, - 0x68, 0x4a, 0x74, 0x67, 0x70, 0x59, 0x61, 0x41, 0x51, 0x49, 0x6e, 0x0a, - 0x38, 0x59, 0x42, 0x39, 0x73, 0x58, 0x66, 0x34, 0x53, 0x30, 0x32, 0x37, - 0x73, 0x67, 0x48, 0x78, 0x4b, 0x30, 0x58, 0x61, 0x6e, 0x77, 0x3d, 0x3d, - 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x44, 0x53, - 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, - 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - public: undefined, - publicOrig: undefined - }, - what: 'Encrypted DSA private key (OpenSSH format)' - }, - { source: 'ssh-dss AAAAB3NzaC1kc3MAAACBAL1FzdhtSYN22YgbInypxa//RyKiZAvWxNzDKNF0cYvabH6ESjdwdEcW96H7pHaKb69hoCHKZzfWmdpj93CcezGnorWvUaO4nAvbR+l/gH+AEYzHmJsECvM/nWnmPltwbvrPi/NmXCNf5aeqQlPbL44vZZjFRcCEwOomGY2FWUKJAAAAFQDBD5Y6VM8slL2I/HhqTmnoVFuGmQAAAIAUkwKajnUklN4CX/ZWEhIOZWCRa6ZKCosICBc/yC4RGJldqsXaM0PCmdy0dmcv0XuOZ4Nb92aiZnWdGRXTN5KJ405WVOQLBB3LpebA6qeyDGiVt/iPOxgJGZy0LIWiqWuzAAf199cQ2BkWmGTC6AAJi1depXC+KVAP+HwXOLjSUAAAAIBeoyKKEiVDQOpB0KAr5RLH3/+5BP+mR+52gTAbxZbxQPYyH7mqq2/PI1A0bjnvnLe45a/iVumoIjP/atMtVJ6w103Ex5JGMwVB7uZBWeyJ4m3MqQdPf1/+r+UCoOaL7stK3rWeTCydb82z34ejX0dZobAPGj2F7SyZy7jM8THgcw==', - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, - 0x00, 0x00, 0x81, 0x00, 0xbd, 0x45, 0xcd, 0xd8, 0x6d, 0x49, 0x83, 0x76, - 0xd9, 0x88, 0x1b, 0x22, 0x7c, 0xa9, 0xc5, 0xaf, 0xff, 0x47, 0x22, 0xa2, - 0x64, 0x0b, 0xd6, 0xc4, 0xdc, 0xc3, 0x28, 0xd1, 0x74, 0x71, 0x8b, 0xda, - 0x6c, 0x7e, 0x84, 0x4a, 0x37, 0x70, 0x74, 0x47, 0x16, 0xf7, 0xa1, 0xfb, - 0xa4, 0x76, 0x8a, 0x6f, 0xaf, 0x61, 0xa0, 0x21, 0xca, 0x67, 0x37, 0xd6, - 0x99, 0xda, 0x63, 0xf7, 0x70, 0x9c, 0x7b, 0x31, 0xa7, 0xa2, 0xb5, 0xaf, - 0x51, 0xa3, 0xb8, 0x9c, 0x0b, 0xdb, 0x47, 0xe9, 0x7f, 0x80, 0x7f, 0x80, - 0x11, 0x8c, 0xc7, 0x98, 0x9b, 0x04, 0x0a, 0xf3, 0x3f, 0x9d, 0x69, 0xe6, - 0x3e, 0x5b, 0x70, 0x6e, 0xfa, 0xcf, 0x8b, 0xf3, 0x66, 0x5c, 0x23, 0x5f, - 0xe5, 0xa7, 0xaa, 0x42, 0x53, 0xdb, 0x2f, 0x8e, 0x2f, 0x65, 0x98, 0xc5, - 0x45, 0xc0, 0x84, 0xc0, 0xea, 0x26, 0x19, 0x8d, 0x85, 0x59, 0x42, 0x89, - 0x00, 0x00, 0x00, 0x15, 0x00, 0xc1, 0x0f, 0x96, 0x3a, 0x54, 0xcf, 0x2c, - 0x94, 0xbd, 0x88, 0xfc, 0x78, 0x6a, 0x4e, 0x69, 0xe8, 0x54, 0x5b, 0x86, - 0x99, 0x00, 0x00, 0x00, 0x80, 0x14, 0x93, 0x02, 0x9a, 0x8e, 0x75, 0x24, - 0x94, 0xde, 0x02, 0x5f, 0xf6, 0x56, 0x12, 0x12, 0x0e, 0x65, 0x60, 0x91, - 0x6b, 0xa6, 0x4a, 0x0a, 0x8b, 0x08, 0x08, 0x17, 0x3f, 0xc8, 0x2e, 0x11, - 0x18, 0x99, 0x5d, 0xaa, 0xc5, 0xda, 0x33, 0x43, 0xc2, 0x99, 0xdc, 0xb4, - 0x76, 0x67, 0x2f, 0xd1, 0x7b, 0x8e, 0x67, 0x83, 0x5b, 0xf7, 0x66, 0xa2, - 0x66, 0x75, 0x9d, 0x19, 0x15, 0xd3, 0x37, 0x92, 0x89, 0xe3, 0x4e, 0x56, - 0x54, 0xe4, 0x0b, 0x04, 0x1d, 0xcb, 0xa5, 0xe6, 0xc0, 0xea, 0xa7, 0xb2, - 0x0c, 0x68, 0x95, 0xb7, 0xf8, 0x8f, 0x3b, 0x18, 0x09, 0x19, 0x9c, 0xb4, - 0x2c, 0x85, 0xa2, 0xa9, 0x6b, 0xb3, 0x00, 0x07, 0xf5, 0xf7, 0xd7, 0x10, - 0xd8, 0x19, 0x16, 0x98, 0x64, 0xc2, 0xe8, 0x00, 0x09, 0x8b, 0x57, 0x5e, - 0xa5, 0x70, 0xbe, 0x29, 0x50, 0x0f, 0xf8, 0x7c, 0x17, 0x38, 0xb8, 0xd2, - 0x50, 0x00, 0x00, 0x00, 0x80, 0x5e, 0xa3, 0x22, 0x8a, 0x12, 0x25, 0x43, - 0x40, 0xea, 0x41, 0xd0, 0xa0, 0x2b, 0xe5, 0x12, 0xc7, 0xdf, 0xff, 0xb9, - 0x04, 0xff, 0xa6, 0x47, 0xee, 0x76, 0x81, 0x30, 0x1b, 0xc5, 0x96, 0xf1, - 0x40, 0xf6, 0x32, 0x1f, 0xb9, 0xaa, 0xab, 0x6f, 0xcf, 0x23, 0x50, 0x34, - 0x6e, 0x39, 0xef, 0x9c, 0xb7, 0xb8, 0xe5, 0xaf, 0xe2, 0x56, 0xe9, 0xa8, - 0x22, 0x33, 0xff, 0x6a, 0xd3, 0x2d, 0x54, 0x9e, 0xb0, 0xd7, 0x4d, 0xc4, - 0xc7, 0x92, 0x46, 0x33, 0x05, 0x41, 0xee, 0xe6, 0x41, 0x59, 0xec, 0x89, - 0xe2, 0x6d, 0xcc, 0xa9, 0x07, 0x4f, 0x7f, 0x5f, 0xfe, 0xaf, 0xe5, 0x02, - 0xa0, 0xe6, 0x8b, 0xee, 0xcb, 0x4a, 0xde, 0xb5, 0x9e, 0x4c, 0x2c, 0x9d, - 0x6f, 0xcd, 0xb3, 0xdf, 0x87, 0xa3, 0x5f, 0x47, 0x59, 0xa1, 0xb0, 0x0f, - 0x1a, 0x3d, 0x85, 0xed, 0x2c, 0x99, 0xcb, 0xb8, 0xcc, 0xf1, 0x31, 0xe0, - 0x73, - ]), - publicOrig: new Buffer([ - 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x20, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x6b, 0x63, 0x33, 0x4d, 0x41, - 0x41, 0x41, 0x43, 0x42, 0x41, 0x4c, 0x31, 0x46, 0x7a, 0x64, 0x68, 0x74, - 0x53, 0x59, 0x4e, 0x32, 0x32, 0x59, 0x67, 0x62, 0x49, 0x6e, 0x79, 0x70, - 0x78, 0x61, 0x2f, 0x2f, 0x52, 0x79, 0x4b, 0x69, 0x5a, 0x41, 0x76, 0x57, - 0x78, 0x4e, 0x7a, 0x44, 0x4b, 0x4e, 0x46, 0x30, 0x63, 0x59, 0x76, 0x61, - 0x62, 0x48, 0x36, 0x45, 0x53, 0x6a, 0x64, 0x77, 0x64, 0x45, 0x63, 0x57, - 0x39, 0x36, 0x48, 0x37, 0x70, 0x48, 0x61, 0x4b, 0x62, 0x36, 0x39, 0x68, - 0x6f, 0x43, 0x48, 0x4b, 0x5a, 0x7a, 0x66, 0x57, 0x6d, 0x64, 0x70, 0x6a, - 0x39, 0x33, 0x43, 0x63, 0x65, 0x7a, 0x47, 0x6e, 0x6f, 0x72, 0x57, 0x76, - 0x55, 0x61, 0x4f, 0x34, 0x6e, 0x41, 0x76, 0x62, 0x52, 0x2b, 0x6c, 0x2f, - 0x67, 0x48, 0x2b, 0x41, 0x45, 0x59, 0x7a, 0x48, 0x6d, 0x4a, 0x73, 0x45, - 0x43, 0x76, 0x4d, 0x2f, 0x6e, 0x57, 0x6e, 0x6d, 0x50, 0x6c, 0x74, 0x77, - 0x62, 0x76, 0x72, 0x50, 0x69, 0x2f, 0x4e, 0x6d, 0x58, 0x43, 0x4e, 0x66, - 0x35, 0x61, 0x65, 0x71, 0x51, 0x6c, 0x50, 0x62, 0x4c, 0x34, 0x34, 0x76, - 0x5a, 0x5a, 0x6a, 0x46, 0x52, 0x63, 0x43, 0x45, 0x77, 0x4f, 0x6f, 0x6d, - 0x47, 0x59, 0x32, 0x46, 0x57, 0x55, 0x4b, 0x4a, 0x41, 0x41, 0x41, 0x41, - 0x46, 0x51, 0x44, 0x42, 0x44, 0x35, 0x59, 0x36, 0x56, 0x4d, 0x38, 0x73, - 0x6c, 0x4c, 0x32, 0x49, 0x2f, 0x48, 0x68, 0x71, 0x54, 0x6d, 0x6e, 0x6f, - 0x56, 0x46, 0x75, 0x47, 0x6d, 0x51, 0x41, 0x41, 0x41, 0x49, 0x41, 0x55, - 0x6b, 0x77, 0x4b, 0x61, 0x6a, 0x6e, 0x55, 0x6b, 0x6c, 0x4e, 0x34, 0x43, - 0x58, 0x2f, 0x5a, 0x57, 0x45, 0x68, 0x49, 0x4f, 0x5a, 0x57, 0x43, 0x52, - 0x61, 0x36, 0x5a, 0x4b, 0x43, 0x6f, 0x73, 0x49, 0x43, 0x42, 0x63, 0x2f, - 0x79, 0x43, 0x34, 0x52, 0x47, 0x4a, 0x6c, 0x64, 0x71, 0x73, 0x58, 0x61, - 0x4d, 0x30, 0x50, 0x43, 0x6d, 0x64, 0x79, 0x30, 0x64, 0x6d, 0x63, 0x76, - 0x30, 0x58, 0x75, 0x4f, 0x5a, 0x34, 0x4e, 0x62, 0x39, 0x32, 0x61, 0x69, - 0x5a, 0x6e, 0x57, 0x64, 0x47, 0x52, 0x58, 0x54, 0x4e, 0x35, 0x4b, 0x4a, - 0x34, 0x30, 0x35, 0x57, 0x56, 0x4f, 0x51, 0x4c, 0x42, 0x42, 0x33, 0x4c, - 0x70, 0x65, 0x62, 0x41, 0x36, 0x71, 0x65, 0x79, 0x44, 0x47, 0x69, 0x56, - 0x74, 0x2f, 0x69, 0x50, 0x4f, 0x78, 0x67, 0x4a, 0x47, 0x5a, 0x79, 0x30, - 0x4c, 0x49, 0x57, 0x69, 0x71, 0x57, 0x75, 0x7a, 0x41, 0x41, 0x66, 0x31, - 0x39, 0x39, 0x63, 0x51, 0x32, 0x42, 0x6b, 0x57, 0x6d, 0x47, 0x54, 0x43, - 0x36, 0x41, 0x41, 0x4a, 0x69, 0x31, 0x64, 0x65, 0x70, 0x58, 0x43, 0x2b, - 0x4b, 0x56, 0x41, 0x50, 0x2b, 0x48, 0x77, 0x58, 0x4f, 0x4c, 0x6a, 0x53, - 0x55, 0x41, 0x41, 0x41, 0x41, 0x49, 0x42, 0x65, 0x6f, 0x79, 0x4b, 0x4b, - 0x45, 0x69, 0x56, 0x44, 0x51, 0x4f, 0x70, 0x42, 0x30, 0x4b, 0x41, 0x72, - 0x35, 0x52, 0x4c, 0x48, 0x33, 0x2f, 0x2b, 0x35, 0x42, 0x50, 0x2b, 0x6d, - 0x52, 0x2b, 0x35, 0x32, 0x67, 0x54, 0x41, 0x62, 0x78, 0x5a, 0x62, 0x78, - 0x51, 0x50, 0x59, 0x79, 0x48, 0x37, 0x6d, 0x71, 0x71, 0x32, 0x2f, 0x50, - 0x49, 0x31, 0x41, 0x30, 0x62, 0x6a, 0x6e, 0x76, 0x6e, 0x4c, 0x65, 0x34, - 0x35, 0x61, 0x2f, 0x69, 0x56, 0x75, 0x6d, 0x6f, 0x49, 0x6a, 0x50, 0x2f, - 0x61, 0x74, 0x4d, 0x74, 0x56, 0x4a, 0x36, 0x77, 0x31, 0x30, 0x33, 0x45, - 0x78, 0x35, 0x4a, 0x47, 0x4d, 0x77, 0x56, 0x42, 0x37, 0x75, 0x5a, 0x42, - 0x57, 0x65, 0x79, 0x4a, 0x34, 0x6d, 0x33, 0x4d, 0x71, 0x51, 0x64, 0x50, - 0x66, 0x31, 0x2f, 0x2b, 0x72, 0x2b, 0x55, 0x43, 0x6f, 0x4f, 0x61, 0x4c, - 0x37, 0x73, 0x74, 0x4b, 0x33, 0x72, 0x57, 0x65, 0x54, 0x43, 0x79, 0x64, - 0x62, 0x38, 0x32, 0x7a, 0x33, 0x34, 0x65, 0x6a, 0x58, 0x30, 0x64, 0x5a, - 0x6f, 0x62, 0x41, 0x50, 0x47, 0x6a, 0x32, 0x46, 0x37, 0x53, 0x79, 0x5a, - 0x79, 0x37, 0x6a, 0x4d, 0x38, 0x54, 0x48, 0x67, 0x63, 0x77, 0x3d, 0x3d, - ]) - }, - what: 'DSA public key (OpenSSH format)' - }, - { source: 'ssh-dss AAAAB3NzaC1kc3MAAACBAILCaN5QbaErJBa0nNoCY2QvvgcSd7WMgIgQ2qPAPH3Sav+9SWZB0SlHP8QYmV/ntBufaRw9ZdIop6esZBoXmNXDxjcfwpJAzrT3qOMfHXeNcc7w/6dHp+2DlkWD3yzK07SheIZnGNtF1fpfrUvkHFA8UX96awWRLnYuSvWvAK9dAAAAFQCrfeadO0tCCwgnq97Skk0Ng/xV6wAAAIBcVYaMkjXNgfvcUS4pwMabY8rFNGbYo9Jgv7IU2LGFEzD6yFbp2t1sQw031EYlad4n3BMTrZdE6K2/SMi3f3yRr0Z6S6nVSbo7/kIT8/tGJAj9/8RHdCihrFUMaAJNzdk5dmbyaCzexLmLXlKfUVW9A1WOsASjeJBwpFrJ8deuVAAAAIAu/zdW1qxdUVd0b7sjWFFZpp3l6HgOXlZpaOYchIoybs7n2dkYwmvn9glNcLCvRqiZpm2oEZIg1dy8RaH5b7AqY2huwmv+hLZ1XkUFyS2Ae2AKux5rslmiKmvglbDY0Rng1Wj3r3/N0KcKke1g1ohEUaQfXnz7VVx2YoVxhT1dTQ== testing ssh2 from node.js', - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: 'testing ssh2 from node.js', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, - 0x00, 0x00, 0x81, 0x00, 0x82, 0xc2, 0x68, 0xde, 0x50, 0x6d, 0xa1, 0x2b, - 0x24, 0x16, 0xb4, 0x9c, 0xda, 0x02, 0x63, 0x64, 0x2f, 0xbe, 0x07, 0x12, - 0x77, 0xb5, 0x8c, 0x80, 0x88, 0x10, 0xda, 0xa3, 0xc0, 0x3c, 0x7d, 0xd2, - 0x6a, 0xff, 0xbd, 0x49, 0x66, 0x41, 0xd1, 0x29, 0x47, 0x3f, 0xc4, 0x18, - 0x99, 0x5f, 0xe7, 0xb4, 0x1b, 0x9f, 0x69, 0x1c, 0x3d, 0x65, 0xd2, 0x28, - 0xa7, 0xa7, 0xac, 0x64, 0x1a, 0x17, 0x98, 0xd5, 0xc3, 0xc6, 0x37, 0x1f, - 0xc2, 0x92, 0x40, 0xce, 0xb4, 0xf7, 0xa8, 0xe3, 0x1f, 0x1d, 0x77, 0x8d, - 0x71, 0xce, 0xf0, 0xff, 0xa7, 0x47, 0xa7, 0xed, 0x83, 0x96, 0x45, 0x83, - 0xdf, 0x2c, 0xca, 0xd3, 0xb4, 0xa1, 0x78, 0x86, 0x67, 0x18, 0xdb, 0x45, - 0xd5, 0xfa, 0x5f, 0xad, 0x4b, 0xe4, 0x1c, 0x50, 0x3c, 0x51, 0x7f, 0x7a, - 0x6b, 0x05, 0x91, 0x2e, 0x76, 0x2e, 0x4a, 0xf5, 0xaf, 0x00, 0xaf, 0x5d, - 0x00, 0x00, 0x00, 0x15, 0x00, 0xab, 0x7d, 0xe6, 0x9d, 0x3b, 0x4b, 0x42, - 0x0b, 0x08, 0x27, 0xab, 0xde, 0xd2, 0x92, 0x4d, 0x0d, 0x83, 0xfc, 0x55, - 0xeb, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x55, 0x86, 0x8c, 0x92, 0x35, 0xcd, - 0x81, 0xfb, 0xdc, 0x51, 0x2e, 0x29, 0xc0, 0xc6, 0x9b, 0x63, 0xca, 0xc5, - 0x34, 0x66, 0xd8, 0xa3, 0xd2, 0x60, 0xbf, 0xb2, 0x14, 0xd8, 0xb1, 0x85, - 0x13, 0x30, 0xfa, 0xc8, 0x56, 0xe9, 0xda, 0xdd, 0x6c, 0x43, 0x0d, 0x37, - 0xd4, 0x46, 0x25, 0x69, 0xde, 0x27, 0xdc, 0x13, 0x13, 0xad, 0x97, 0x44, - 0xe8, 0xad, 0xbf, 0x48, 0xc8, 0xb7, 0x7f, 0x7c, 0x91, 0xaf, 0x46, 0x7a, - 0x4b, 0xa9, 0xd5, 0x49, 0xba, 0x3b, 0xfe, 0x42, 0x13, 0xf3, 0xfb, 0x46, - 0x24, 0x08, 0xfd, 0xff, 0xc4, 0x47, 0x74, 0x28, 0xa1, 0xac, 0x55, 0x0c, - 0x68, 0x02, 0x4d, 0xcd, 0xd9, 0x39, 0x76, 0x66, 0xf2, 0x68, 0x2c, 0xde, - 0xc4, 0xb9, 0x8b, 0x5e, 0x52, 0x9f, 0x51, 0x55, 0xbd, 0x03, 0x55, 0x8e, - 0xb0, 0x04, 0xa3, 0x78, 0x90, 0x70, 0xa4, 0x5a, 0xc9, 0xf1, 0xd7, 0xae, - 0x54, 0x00, 0x00, 0x00, 0x80, 0x2e, 0xff, 0x37, 0x56, 0xd6, 0xac, 0x5d, - 0x51, 0x57, 0x74, 0x6f, 0xbb, 0x23, 0x58, 0x51, 0x59, 0xa6, 0x9d, 0xe5, - 0xe8, 0x78, 0x0e, 0x5e, 0x56, 0x69, 0x68, 0xe6, 0x1c, 0x84, 0x8a, 0x32, - 0x6e, 0xce, 0xe7, 0xd9, 0xd9, 0x18, 0xc2, 0x6b, 0xe7, 0xf6, 0x09, 0x4d, - 0x70, 0xb0, 0xaf, 0x46, 0xa8, 0x99, 0xa6, 0x6d, 0xa8, 0x11, 0x92, 0x20, - 0xd5, 0xdc, 0xbc, 0x45, 0xa1, 0xf9, 0x6f, 0xb0, 0x2a, 0x63, 0x68, 0x6e, - 0xc2, 0x6b, 0xfe, 0x84, 0xb6, 0x75, 0x5e, 0x45, 0x05, 0xc9, 0x2d, 0x80, - 0x7b, 0x60, 0x0a, 0xbb, 0x1e, 0x6b, 0xb2, 0x59, 0xa2, 0x2a, 0x6b, 0xe0, - 0x95, 0xb0, 0xd8, 0xd1, 0x19, 0xe0, 0xd5, 0x68, 0xf7, 0xaf, 0x7f, 0xcd, - 0xd0, 0xa7, 0x0a, 0x91, 0xed, 0x60, 0xd6, 0x88, 0x44, 0x51, 0xa4, 0x1f, - 0x5e, 0x7c, 0xfb, 0x55, 0x5c, 0x76, 0x62, 0x85, 0x71, 0x85, 0x3d, 0x5d, - 0x4d, - ]), - publicOrig: new Buffer([ - 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x20, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x6b, 0x63, 0x33, 0x4d, 0x41, - 0x41, 0x41, 0x43, 0x42, 0x41, 0x49, 0x4c, 0x43, 0x61, 0x4e, 0x35, 0x51, - 0x62, 0x61, 0x45, 0x72, 0x4a, 0x42, 0x61, 0x30, 0x6e, 0x4e, 0x6f, 0x43, - 0x59, 0x32, 0x51, 0x76, 0x76, 0x67, 0x63, 0x53, 0x64, 0x37, 0x57, 0x4d, - 0x67, 0x49, 0x67, 0x51, 0x32, 0x71, 0x50, 0x41, 0x50, 0x48, 0x33, 0x53, - 0x61, 0x76, 0x2b, 0x39, 0x53, 0x57, 0x5a, 0x42, 0x30, 0x53, 0x6c, 0x48, - 0x50, 0x38, 0x51, 0x59, 0x6d, 0x56, 0x2f, 0x6e, 0x74, 0x42, 0x75, 0x66, - 0x61, 0x52, 0x77, 0x39, 0x5a, 0x64, 0x49, 0x6f, 0x70, 0x36, 0x65, 0x73, - 0x5a, 0x42, 0x6f, 0x58, 0x6d, 0x4e, 0x58, 0x44, 0x78, 0x6a, 0x63, 0x66, - 0x77, 0x70, 0x4a, 0x41, 0x7a, 0x72, 0x54, 0x33, 0x71, 0x4f, 0x4d, 0x66, - 0x48, 0x58, 0x65, 0x4e, 0x63, 0x63, 0x37, 0x77, 0x2f, 0x36, 0x64, 0x48, - 0x70, 0x2b, 0x32, 0x44, 0x6c, 0x6b, 0x57, 0x44, 0x33, 0x79, 0x7a, 0x4b, - 0x30, 0x37, 0x53, 0x68, 0x65, 0x49, 0x5a, 0x6e, 0x47, 0x4e, 0x74, 0x46, - 0x31, 0x66, 0x70, 0x66, 0x72, 0x55, 0x76, 0x6b, 0x48, 0x46, 0x41, 0x38, - 0x55, 0x58, 0x39, 0x36, 0x61, 0x77, 0x57, 0x52, 0x4c, 0x6e, 0x59, 0x75, - 0x53, 0x76, 0x57, 0x76, 0x41, 0x4b, 0x39, 0x64, 0x41, 0x41, 0x41, 0x41, - 0x46, 0x51, 0x43, 0x72, 0x66, 0x65, 0x61, 0x64, 0x4f, 0x30, 0x74, 0x43, - 0x43, 0x77, 0x67, 0x6e, 0x71, 0x39, 0x37, 0x53, 0x6b, 0x6b, 0x30, 0x4e, - 0x67, 0x2f, 0x78, 0x56, 0x36, 0x77, 0x41, 0x41, 0x41, 0x49, 0x42, 0x63, - 0x56, 0x59, 0x61, 0x4d, 0x6b, 0x6a, 0x58, 0x4e, 0x67, 0x66, 0x76, 0x63, - 0x55, 0x53, 0x34, 0x70, 0x77, 0x4d, 0x61, 0x62, 0x59, 0x38, 0x72, 0x46, - 0x4e, 0x47, 0x62, 0x59, 0x6f, 0x39, 0x4a, 0x67, 0x76, 0x37, 0x49, 0x55, - 0x32, 0x4c, 0x47, 0x46, 0x45, 0x7a, 0x44, 0x36, 0x79, 0x46, 0x62, 0x70, - 0x32, 0x74, 0x31, 0x73, 0x51, 0x77, 0x30, 0x33, 0x31, 0x45, 0x59, 0x6c, - 0x61, 0x64, 0x34, 0x6e, 0x33, 0x42, 0x4d, 0x54, 0x72, 0x5a, 0x64, 0x45, - 0x36, 0x4b, 0x32, 0x2f, 0x53, 0x4d, 0x69, 0x33, 0x66, 0x33, 0x79, 0x52, - 0x72, 0x30, 0x5a, 0x36, 0x53, 0x36, 0x6e, 0x56, 0x53, 0x62, 0x6f, 0x37, - 0x2f, 0x6b, 0x49, 0x54, 0x38, 0x2f, 0x74, 0x47, 0x4a, 0x41, 0x6a, 0x39, - 0x2f, 0x38, 0x52, 0x48, 0x64, 0x43, 0x69, 0x68, 0x72, 0x46, 0x55, 0x4d, - 0x61, 0x41, 0x4a, 0x4e, 0x7a, 0x64, 0x6b, 0x35, 0x64, 0x6d, 0x62, 0x79, - 0x61, 0x43, 0x7a, 0x65, 0x78, 0x4c, 0x6d, 0x4c, 0x58, 0x6c, 0x4b, 0x66, - 0x55, 0x56, 0x57, 0x39, 0x41, 0x31, 0x57, 0x4f, 0x73, 0x41, 0x53, 0x6a, - 0x65, 0x4a, 0x42, 0x77, 0x70, 0x46, 0x72, 0x4a, 0x38, 0x64, 0x65, 0x75, - 0x56, 0x41, 0x41, 0x41, 0x41, 0x49, 0x41, 0x75, 0x2f, 0x7a, 0x64, 0x57, - 0x31, 0x71, 0x78, 0x64, 0x55, 0x56, 0x64, 0x30, 0x62, 0x37, 0x73, 0x6a, - 0x57, 0x46, 0x46, 0x5a, 0x70, 0x70, 0x33, 0x6c, 0x36, 0x48, 0x67, 0x4f, - 0x58, 0x6c, 0x5a, 0x70, 0x61, 0x4f, 0x59, 0x63, 0x68, 0x49, 0x6f, 0x79, - 0x62, 0x73, 0x37, 0x6e, 0x32, 0x64, 0x6b, 0x59, 0x77, 0x6d, 0x76, 0x6e, - 0x39, 0x67, 0x6c, 0x4e, 0x63, 0x4c, 0x43, 0x76, 0x52, 0x71, 0x69, 0x5a, - 0x70, 0x6d, 0x32, 0x6f, 0x45, 0x5a, 0x49, 0x67, 0x31, 0x64, 0x79, 0x38, - 0x52, 0x61, 0x48, 0x35, 0x62, 0x37, 0x41, 0x71, 0x59, 0x32, 0x68, 0x75, - 0x77, 0x6d, 0x76, 0x2b, 0x68, 0x4c, 0x5a, 0x31, 0x58, 0x6b, 0x55, 0x46, - 0x79, 0x53, 0x32, 0x41, 0x65, 0x32, 0x41, 0x4b, 0x75, 0x78, 0x35, 0x72, - 0x73, 0x6c, 0x6d, 0x69, 0x4b, 0x6d, 0x76, 0x67, 0x6c, 0x62, 0x44, 0x59, - 0x30, 0x52, 0x6e, 0x67, 0x31, 0x57, 0x6a, 0x33, 0x72, 0x33, 0x2f, 0x4e, - 0x30, 0x4b, 0x63, 0x4b, 0x6b, 0x65, 0x31, 0x67, 0x31, 0x6f, 0x68, 0x45, - 0x55, 0x61, 0x51, 0x66, 0x58, 0x6e, 0x7a, 0x37, 0x56, 0x56, 0x78, 0x32, - 0x59, 0x6f, 0x56, 0x78, 0x68, 0x54, 0x31, 0x64, 0x54, 0x51, 0x3d, 0x3d, - 0x20, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x73, 0x68, - 0x32, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6a, 0x73, - ]) - }, - what: 'DSA public key (OpenSSH format) with comment' - }, - { source: 'ssh-dss AAAAB3NzaC1kc3MAAACBAILCaN5QbaErJBa0nNoCY2QvvgcSd7WMgIgQ2qPAPH3Sav+9SWZB0SlHP8QYmV/ntBufaRw9ZdIop6esZBoXmNXDxjcfwpJAzrT3qOMfHXeNcc7w/6dHp+2DlkWD3yzK07SheIZnGNtF1fpfrUvkHFA8UX96awWRLnYuSvWvAK9dAAAAFQCrfeadO0tCCwgnq97Skk0Ng/xV6wAAAIBcVYaMkjXNgfvcUS4pwMabY8rFNGbYo9Jgv7IU2LGFEzD6yFbp2t1sQw031EYlad4n3BMTrZdE6K2/SMi3f3yRr0Z6S6nVSbo7/kIT8/tGJAj9/8RHdCihrFUMaAJNzdk5dmbyaCzexLmLXlKfUVW9A1WOsASjeJBwpFrJ8deuVAAAAIAu/zdW1qxdUVd0b7sjWFFZpp3l6HgOXlZpaOYchIoybs7n2dkYwmvn9glNcLCvRqiZpm2oEZIg1dy8RaH5b7AqY2huwmv+hLZ1XkUFyS2Ae2AKux5rslmiKmvglbDY0Rng1Wj3r3/N0KcKke1g1ohEUaQfXnz7VVx2YoVxhT1dTQ== ssh2test', - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: 'ssh2test', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, - 0x00, 0x00, 0x81, 0x00, 0x82, 0xc2, 0x68, 0xde, 0x50, 0x6d, 0xa1, 0x2b, - 0x24, 0x16, 0xb4, 0x9c, 0xda, 0x02, 0x63, 0x64, 0x2f, 0xbe, 0x07, 0x12, - 0x77, 0xb5, 0x8c, 0x80, 0x88, 0x10, 0xda, 0xa3, 0xc0, 0x3c, 0x7d, 0xd2, - 0x6a, 0xff, 0xbd, 0x49, 0x66, 0x41, 0xd1, 0x29, 0x47, 0x3f, 0xc4, 0x18, - 0x99, 0x5f, 0xe7, 0xb4, 0x1b, 0x9f, 0x69, 0x1c, 0x3d, 0x65, 0xd2, 0x28, - 0xa7, 0xa7, 0xac, 0x64, 0x1a, 0x17, 0x98, 0xd5, 0xc3, 0xc6, 0x37, 0x1f, - 0xc2, 0x92, 0x40, 0xce, 0xb4, 0xf7, 0xa8, 0xe3, 0x1f, 0x1d, 0x77, 0x8d, - 0x71, 0xce, 0xf0, 0xff, 0xa7, 0x47, 0xa7, 0xed, 0x83, 0x96, 0x45, 0x83, - 0xdf, 0x2c, 0xca, 0xd3, 0xb4, 0xa1, 0x78, 0x86, 0x67, 0x18, 0xdb, 0x45, - 0xd5, 0xfa, 0x5f, 0xad, 0x4b, 0xe4, 0x1c, 0x50, 0x3c, 0x51, 0x7f, 0x7a, - 0x6b, 0x05, 0x91, 0x2e, 0x76, 0x2e, 0x4a, 0xf5, 0xaf, 0x00, 0xaf, 0x5d, - 0x00, 0x00, 0x00, 0x15, 0x00, 0xab, 0x7d, 0xe6, 0x9d, 0x3b, 0x4b, 0x42, - 0x0b, 0x08, 0x27, 0xab, 0xde, 0xd2, 0x92, 0x4d, 0x0d, 0x83, 0xfc, 0x55, - 0xeb, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x55, 0x86, 0x8c, 0x92, 0x35, 0xcd, - 0x81, 0xfb, 0xdc, 0x51, 0x2e, 0x29, 0xc0, 0xc6, 0x9b, 0x63, 0xca, 0xc5, - 0x34, 0x66, 0xd8, 0xa3, 0xd2, 0x60, 0xbf, 0xb2, 0x14, 0xd8, 0xb1, 0x85, - 0x13, 0x30, 0xfa, 0xc8, 0x56, 0xe9, 0xda, 0xdd, 0x6c, 0x43, 0x0d, 0x37, - 0xd4, 0x46, 0x25, 0x69, 0xde, 0x27, 0xdc, 0x13, 0x13, 0xad, 0x97, 0x44, - 0xe8, 0xad, 0xbf, 0x48, 0xc8, 0xb7, 0x7f, 0x7c, 0x91, 0xaf, 0x46, 0x7a, - 0x4b, 0xa9, 0xd5, 0x49, 0xba, 0x3b, 0xfe, 0x42, 0x13, 0xf3, 0xfb, 0x46, - 0x24, 0x08, 0xfd, 0xff, 0xc4, 0x47, 0x74, 0x28, 0xa1, 0xac, 0x55, 0x0c, - 0x68, 0x02, 0x4d, 0xcd, 0xd9, 0x39, 0x76, 0x66, 0xf2, 0x68, 0x2c, 0xde, - 0xc4, 0xb9, 0x8b, 0x5e, 0x52, 0x9f, 0x51, 0x55, 0xbd, 0x03, 0x55, 0x8e, - 0xb0, 0x04, 0xa3, 0x78, 0x90, 0x70, 0xa4, 0x5a, 0xc9, 0xf1, 0xd7, 0xae, - 0x54, 0x00, 0x00, 0x00, 0x80, 0x2e, 0xff, 0x37, 0x56, 0xd6, 0xac, 0x5d, - 0x51, 0x57, 0x74, 0x6f, 0xbb, 0x23, 0x58, 0x51, 0x59, 0xa6, 0x9d, 0xe5, - 0xe8, 0x78, 0x0e, 0x5e, 0x56, 0x69, 0x68, 0xe6, 0x1c, 0x84, 0x8a, 0x32, - 0x6e, 0xce, 0xe7, 0xd9, 0xd9, 0x18, 0xc2, 0x6b, 0xe7, 0xf6, 0x09, 0x4d, - 0x70, 0xb0, 0xaf, 0x46, 0xa8, 0x99, 0xa6, 0x6d, 0xa8, 0x11, 0x92, 0x20, - 0xd5, 0xdc, 0xbc, 0x45, 0xa1, 0xf9, 0x6f, 0xb0, 0x2a, 0x63, 0x68, 0x6e, - 0xc2, 0x6b, 0xfe, 0x84, 0xb6, 0x75, 0x5e, 0x45, 0x05, 0xc9, 0x2d, 0x80, - 0x7b, 0x60, 0x0a, 0xbb, 0x1e, 0x6b, 0xb2, 0x59, 0xa2, 0x2a, 0x6b, 0xe0, - 0x95, 0xb0, 0xd8, 0xd1, 0x19, 0xe0, 0xd5, 0x68, 0xf7, 0xaf, 0x7f, 0xcd, - 0xd0, 0xa7, 0x0a, 0x91, 0xed, 0x60, 0xd6, 0x88, 0x44, 0x51, 0xa4, 0x1f, - 0x5e, 0x7c, 0xfb, 0x55, 0x5c, 0x76, 0x62, 0x85, 0x71, 0x85, 0x3d, 0x5d, - 0x4d, - ]), - publicOrig: new Buffer([ - 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x20, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x6b, 0x63, 0x33, 0x4d, 0x41, - 0x41, 0x41, 0x43, 0x42, 0x41, 0x49, 0x4c, 0x43, 0x61, 0x4e, 0x35, 0x51, - 0x62, 0x61, 0x45, 0x72, 0x4a, 0x42, 0x61, 0x30, 0x6e, 0x4e, 0x6f, 0x43, - 0x59, 0x32, 0x51, 0x76, 0x76, 0x67, 0x63, 0x53, 0x64, 0x37, 0x57, 0x4d, - 0x67, 0x49, 0x67, 0x51, 0x32, 0x71, 0x50, 0x41, 0x50, 0x48, 0x33, 0x53, - 0x61, 0x76, 0x2b, 0x39, 0x53, 0x57, 0x5a, 0x42, 0x30, 0x53, 0x6c, 0x48, - 0x50, 0x38, 0x51, 0x59, 0x6d, 0x56, 0x2f, 0x6e, 0x74, 0x42, 0x75, 0x66, - 0x61, 0x52, 0x77, 0x39, 0x5a, 0x64, 0x49, 0x6f, 0x70, 0x36, 0x65, 0x73, - 0x5a, 0x42, 0x6f, 0x58, 0x6d, 0x4e, 0x58, 0x44, 0x78, 0x6a, 0x63, 0x66, - 0x77, 0x70, 0x4a, 0x41, 0x7a, 0x72, 0x54, 0x33, 0x71, 0x4f, 0x4d, 0x66, - 0x48, 0x58, 0x65, 0x4e, 0x63, 0x63, 0x37, 0x77, 0x2f, 0x36, 0x64, 0x48, - 0x70, 0x2b, 0x32, 0x44, 0x6c, 0x6b, 0x57, 0x44, 0x33, 0x79, 0x7a, 0x4b, - 0x30, 0x37, 0x53, 0x68, 0x65, 0x49, 0x5a, 0x6e, 0x47, 0x4e, 0x74, 0x46, - 0x31, 0x66, 0x70, 0x66, 0x72, 0x55, 0x76, 0x6b, 0x48, 0x46, 0x41, 0x38, - 0x55, 0x58, 0x39, 0x36, 0x61, 0x77, 0x57, 0x52, 0x4c, 0x6e, 0x59, 0x75, - 0x53, 0x76, 0x57, 0x76, 0x41, 0x4b, 0x39, 0x64, 0x41, 0x41, 0x41, 0x41, - 0x46, 0x51, 0x43, 0x72, 0x66, 0x65, 0x61, 0x64, 0x4f, 0x30, 0x74, 0x43, - 0x43, 0x77, 0x67, 0x6e, 0x71, 0x39, 0x37, 0x53, 0x6b, 0x6b, 0x30, 0x4e, - 0x67, 0x2f, 0x78, 0x56, 0x36, 0x77, 0x41, 0x41, 0x41, 0x49, 0x42, 0x63, - 0x56, 0x59, 0x61, 0x4d, 0x6b, 0x6a, 0x58, 0x4e, 0x67, 0x66, 0x76, 0x63, - 0x55, 0x53, 0x34, 0x70, 0x77, 0x4d, 0x61, 0x62, 0x59, 0x38, 0x72, 0x46, - 0x4e, 0x47, 0x62, 0x59, 0x6f, 0x39, 0x4a, 0x67, 0x76, 0x37, 0x49, 0x55, - 0x32, 0x4c, 0x47, 0x46, 0x45, 0x7a, 0x44, 0x36, 0x79, 0x46, 0x62, 0x70, - 0x32, 0x74, 0x31, 0x73, 0x51, 0x77, 0x30, 0x33, 0x31, 0x45, 0x59, 0x6c, - 0x61, 0x64, 0x34, 0x6e, 0x33, 0x42, 0x4d, 0x54, 0x72, 0x5a, 0x64, 0x45, - 0x36, 0x4b, 0x32, 0x2f, 0x53, 0x4d, 0x69, 0x33, 0x66, 0x33, 0x79, 0x52, - 0x72, 0x30, 0x5a, 0x36, 0x53, 0x36, 0x6e, 0x56, 0x53, 0x62, 0x6f, 0x37, - 0x2f, 0x6b, 0x49, 0x54, 0x38, 0x2f, 0x74, 0x47, 0x4a, 0x41, 0x6a, 0x39, - 0x2f, 0x38, 0x52, 0x48, 0x64, 0x43, 0x69, 0x68, 0x72, 0x46, 0x55, 0x4d, - 0x61, 0x41, 0x4a, 0x4e, 0x7a, 0x64, 0x6b, 0x35, 0x64, 0x6d, 0x62, 0x79, - 0x61, 0x43, 0x7a, 0x65, 0x78, 0x4c, 0x6d, 0x4c, 0x58, 0x6c, 0x4b, 0x66, - 0x55, 0x56, 0x57, 0x39, 0x41, 0x31, 0x57, 0x4f, 0x73, 0x41, 0x53, 0x6a, - 0x65, 0x4a, 0x42, 0x77, 0x70, 0x46, 0x72, 0x4a, 0x38, 0x64, 0x65, 0x75, - 0x56, 0x41, 0x41, 0x41, 0x41, 0x49, 0x41, 0x75, 0x2f, 0x7a, 0x64, 0x57, - 0x31, 0x71, 0x78, 0x64, 0x55, 0x56, 0x64, 0x30, 0x62, 0x37, 0x73, 0x6a, - 0x57, 0x46, 0x46, 0x5a, 0x70, 0x70, 0x33, 0x6c, 0x36, 0x48, 0x67, 0x4f, - 0x58, 0x6c, 0x5a, 0x70, 0x61, 0x4f, 0x59, 0x63, 0x68, 0x49, 0x6f, 0x79, - 0x62, 0x73, 0x37, 0x6e, 0x32, 0x64, 0x6b, 0x59, 0x77, 0x6d, 0x76, 0x6e, - 0x39, 0x67, 0x6c, 0x4e, 0x63, 0x4c, 0x43, 0x76, 0x52, 0x71, 0x69, 0x5a, - 0x70, 0x6d, 0x32, 0x6f, 0x45, 0x5a, 0x49, 0x67, 0x31, 0x64, 0x79, 0x38, - 0x52, 0x61, 0x48, 0x35, 0x62, 0x37, 0x41, 0x71, 0x59, 0x32, 0x68, 0x75, - 0x77, 0x6d, 0x76, 0x2b, 0x68, 0x4c, 0x5a, 0x31, 0x58, 0x6b, 0x55, 0x46, - 0x79, 0x53, 0x32, 0x41, 0x65, 0x32, 0x41, 0x4b, 0x75, 0x78, 0x35, 0x72, - 0x73, 0x6c, 0x6d, 0x69, 0x4b, 0x6d, 0x76, 0x67, 0x6c, 0x62, 0x44, 0x59, - 0x30, 0x52, 0x6e, 0x67, 0x31, 0x57, 0x6a, 0x33, 0x72, 0x33, 0x2f, 0x4e, - 0x30, 0x4b, 0x63, 0x4b, 0x6b, 0x65, 0x31, 0x67, 0x31, 0x6f, 0x68, 0x45, - 0x55, 0x61, 0x51, 0x66, 0x58, 0x6e, 0x7a, 0x37, 0x56, 0x56, 0x78, 0x32, - 0x59, 0x6f, 0x56, 0x78, 0x68, 0x54, 0x31, 0x64, 0x54, 0x51, 0x3d, 0x3d, - 0x20, 0x73, 0x73, 0x68, 0x32, 0x74, 0x65, 0x73, 0x74, - ]) - }, - what: 'DSA public key (OpenSSH format) with comment (no spaces)' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: "testing ssh2 from node.js"', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'testing ssh2 from node.js', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x67, 0x20, 0x73, 0x73, 0x68, 0x32, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6a, 0x73, 0x22, 0x0a, 0x41, 0x41, 0x41, - 0x41, 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, - 0x41, 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, - 0x41, 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, - 0x78, 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, - 0x72, 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, - 0x66, 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, 0x35, - 0x4f, 0x36, 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, - 0x65, 0x4f, 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, - 0x57, 0x6f, 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, - 0x72, 0x65, 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, - 0x76, 0x78, 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, - 0x52, 0x36, 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, 0x53, - 0x46, 0x33, 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, - 0x53, 0x30, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, 0x44, - 0x20, 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, - 0x20, 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with quoted comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: testing ssh2 from node.js', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'testing ssh2 from node.js', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, - 0x20, 0x73, 0x73, 0x68, 0x32, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x6a, 0x73, 0x0a, 0x41, 0x41, 0x41, 0x41, 0x42, - 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, 0x41, 0x41, - 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, 0x41, 0x59, - 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, 0x78, 0x77, - 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, 0x72, 0x62, - 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, 0x66, 0x2b, - 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, 0x35, 0x4f, 0x36, - 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, 0x65, 0x4f, - 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, 0x57, 0x6f, - 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, 0x72, 0x65, - 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, 0x76, 0x78, - 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, 0x52, 0x36, - 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, 0x53, 0x46, 0x33, - 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, 0x53, 0x30, - 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, 0x44, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with unquoted comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: "testing ssh2 \\', - 'from node.js"', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'testing ssh2 from node.js', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x67, 0x20, 0x73, 0x73, 0x68, 0x32, 0x20, 0x5c, 0x0a, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6a, 0x73, 0x22, 0x0a, 0x41, - 0x41, 0x41, 0x41, 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, - 0x32, 0x45, 0x41, 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, - 0x41, 0x41, 0x41, 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, - 0x68, 0x67, 0x78, 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, - 0x76, 0x41, 0x72, 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, - 0x63, 0x6c, 0x66, 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, - 0x52, 0x35, 0x4f, 0x36, 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, - 0x4f, 0x2b, 0x65, 0x4f, 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, - 0x5a, 0x7a, 0x57, 0x6f, 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, - 0x69, 0x39, 0x72, 0x65, 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, - 0x57, 0x46, 0x76, 0x78, 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, - 0x55, 0x50, 0x52, 0x36, 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, - 0x4c, 0x53, 0x46, 0x33, 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, - 0x2f, 0x72, 0x53, 0x30, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, - 0x4e, 0x44, 0x20, 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, - 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with multi-line quoted comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: testing ssh2 \\', - 'from node.js', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'testing ssh2 from node.js', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, - 0x20, 0x73, 0x73, 0x68, 0x32, 0x20, 0x5c, 0x0a, 0x66, 0x72, 0x6f, 0x6d, - 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6a, 0x73, 0x0a, 0x41, 0x41, 0x41, - 0x41, 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, - 0x41, 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, - 0x41, 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, - 0x78, 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, - 0x72, 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, - 0x66, 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, 0x35, - 0x4f, 0x36, 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, - 0x65, 0x4f, 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, - 0x57, 0x6f, 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, - 0x72, 0x65, 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, - 0x76, 0x78, 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, - 0x52, 0x36, 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, 0x53, - 0x46, 0x33, 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, - 0x53, 0x30, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, 0x44, - 0x20, 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, - 0x20, 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with multi-line unquoted comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: ""', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: '', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x22, 0x0a, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, 0x41, - 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, 0x41, - 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, 0x78, - 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, 0x72, - 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, 0x66, - 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, 0x35, 0x4f, - 0x36, 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, 0x65, - 0x4f, 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, 0x57, - 0x6f, 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, 0x72, - 0x65, 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, 0x76, - 0x78, 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, 0x52, - 0x36, 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, 0x53, 0x46, - 0x33, 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, 0x53, - 0x30, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, 0x44, 0x20, - 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, - 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with empty quoted comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: ', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: '', - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x0a, 0x41, 0x41, 0x41, 0x41, 0x42, 0x33, - 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, 0x41, 0x41, 0x41, - 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, 0x41, 0x59, 0x51, - 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, 0x78, 0x77, 0x47, - 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, 0x72, 0x62, 0x4e, - 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, 0x66, 0x2b, 0x6f, - 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, 0x35, 0x4f, 0x36, 0x72, - 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, 0x65, 0x4f, 0x63, - 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, 0x57, 0x6f, 0x2f, - 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, 0x72, 0x65, 0x54, - 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, 0x76, 0x78, 0x34, - 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, 0x52, 0x36, 0x68, - 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, 0x53, 0x46, 0x33, 0x6c, - 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, 0x53, 0x30, 0x3d, - 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, 0x44, 0x20, 0x53, 0x53, - 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, - 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with empty unquoted comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, 0x45, 0x41, - 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, 0x41, 0x41, - 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, 0x67, 0x78, - 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, 0x41, 0x72, - 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, 0x6c, 0x66, - 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, 0x35, 0x4f, - 0x36, 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, 0x2b, 0x65, - 0x4f, 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, 0x7a, 0x57, - 0x6f, 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, 0x39, 0x72, - 0x65, 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, 0x46, 0x76, - 0x78, 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, 0x50, 0x52, - 0x36, 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, 0x53, 0x46, - 0x33, 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, 0x72, 0x53, - 0x30, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, 0x44, 0x20, - 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, - 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with no comment' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - '', - '', - 'AAAAB3NzaC1yc2EAAAADAQABAAAAYQDl6dxL+hgxwGNhZrq18vArbNB0UqNxvclf+ociRL', - 'lnR5O6r/czAhySO+eOc5SF7wexZzWo/COQ37tEi9reTucYFNQQWFvx4E8CRFP+UPR6hQX0', - 'fxoLSF3lxQFJ+32/rS0=', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x61, 0x00, - 0xe5, 0xe9, 0xdc, 0x4b, 0xfa, 0x18, 0x31, 0xc0, 0x63, 0x61, 0x66, 0xba, - 0xb5, 0xf2, 0xf0, 0x2b, 0x6c, 0xd0, 0x74, 0x52, 0xa3, 0x71, 0xbd, 0xc9, - 0x5f, 0xfa, 0x87, 0x22, 0x44, 0xb9, 0x67, 0x47, 0x93, 0xba, 0xaf, 0xf7, - 0x33, 0x02, 0x1c, 0x92, 0x3b, 0xe7, 0x8e, 0x73, 0x94, 0x85, 0xef, 0x07, - 0xb1, 0x67, 0x35, 0xa8, 0xfc, 0x23, 0x90, 0xdf, 0xbb, 0x44, 0x8b, 0xda, - 0xde, 0x4e, 0xe7, 0x18, 0x14, 0xd4, 0x10, 0x58, 0x5b, 0xf1, 0xe0, 0x4f, - 0x02, 0x44, 0x53, 0xfe, 0x50, 0xf4, 0x7a, 0x85, 0x05, 0xf4, 0x7f, 0x1a, - 0x0b, 0x48, 0x5d, 0xe5, 0xc5, 0x01, 0x49, 0xfb, 0x7d, 0xbf, 0xad, 0x2d, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x0a, 0x41, 0x41, - 0x41, 0x41, 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x79, 0x63, 0x32, - 0x45, 0x41, 0x41, 0x41, 0x41, 0x44, 0x41, 0x51, 0x41, 0x42, 0x41, 0x41, - 0x41, 0x41, 0x59, 0x51, 0x44, 0x6c, 0x36, 0x64, 0x78, 0x4c, 0x2b, 0x68, - 0x67, 0x78, 0x77, 0x47, 0x4e, 0x68, 0x5a, 0x72, 0x71, 0x31, 0x38, 0x76, - 0x41, 0x72, 0x62, 0x4e, 0x42, 0x30, 0x55, 0x71, 0x4e, 0x78, 0x76, 0x63, - 0x6c, 0x66, 0x2b, 0x6f, 0x63, 0x69, 0x52, 0x4c, 0x0a, 0x6c, 0x6e, 0x52, - 0x35, 0x4f, 0x36, 0x72, 0x2f, 0x63, 0x7a, 0x41, 0x68, 0x79, 0x53, 0x4f, - 0x2b, 0x65, 0x4f, 0x63, 0x35, 0x53, 0x46, 0x37, 0x77, 0x65, 0x78, 0x5a, - 0x7a, 0x57, 0x6f, 0x2f, 0x43, 0x4f, 0x51, 0x33, 0x37, 0x74, 0x45, 0x69, - 0x39, 0x72, 0x65, 0x54, 0x75, 0x63, 0x59, 0x46, 0x4e, 0x51, 0x51, 0x57, - 0x46, 0x76, 0x78, 0x34, 0x45, 0x38, 0x43, 0x52, 0x46, 0x50, 0x2b, 0x55, - 0x50, 0x52, 0x36, 0x68, 0x51, 0x58, 0x30, 0x0a, 0x66, 0x78, 0x6f, 0x4c, - 0x53, 0x46, 0x33, 0x6c, 0x78, 0x51, 0x46, 0x4a, 0x2b, 0x33, 0x32, 0x2f, - 0x72, 0x53, 0x30, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x4e, - 0x44, 0x20, 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, - 0x43, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - ]) - }, - what: 'RSA public key (RFC4716 format) with blank lines' - }, - { source: [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'AAAAB3NzaC1kc3MAAACBAI4CR+tgz/kZnbmKJjccZNWKqcifcxLy/pTMnRLh5SrzQ44R8T', - 'QSbQTNnJHVpc6ucW369+TtQRpRmr4iU65ttZkZqCJ1jawXAnxcpIrVq/xBfsXfCIr26LaG', - 'qNm//vYBAPs5j648Fhg6AHyM/LewPSnek3fE8gIB9gtCsPei5L7lAAAAFQDJ3k6TdJK/eo', - 'LgUqg2bUB94Mjg9wAAAIAp9Q3SyooklLGMPdG2kj0vMWF+cVtChcjGjemhPeHXyjD5/in8', - 'gWYFifVqoYKBJhAaPP5HpPtA3BEGgIkLVGRzCk3tnwXbutGbwt7PzutbJ9LKiiR7z1HLqn', - 'E+r0//6Nhqz/ZNQPWZRbcG0l1EIQNgjuZkSzJLLO15TSPZeVhZcQAAAIAUAYobyKQ3Rl4q', - 'XAcOP8uOt5q7YHMy43JmZJnTCQ7X95TuNv5kFj7a5RkDU9HjgzSg5aabVsJAD6wDy5/rm+', - 'kJA9uXGOvHfiToh+tRjDp2SrWDERfPCRDl8oTJr36p1zqFXERwTJsNJF32QClszhzk7NYv', - 'G6kcaQC8Hhm9yccRoA==', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'), - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: undefined, - encryption: undefined, - private: undefined, - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x81, 0x00, 0x8e, 0x02, 0x47, 0xeb, 0x60, 0xcf, 0xf9, - 0x19, 0x9d, 0xb9, 0x8a, 0x26, 0x37, 0x1c, 0x64, 0xd5, 0x8a, 0xa9, 0xc8, - 0x9f, 0x73, 0x12, 0xf2, 0xfe, 0x94, 0xcc, 0x9d, 0x12, 0xe1, 0xe5, 0x2a, - 0xf3, 0x43, 0x8e, 0x11, 0xf1, 0x34, 0x12, 0x6d, 0x04, 0xcd, 0x9c, 0x91, - 0xd5, 0xa5, 0xce, 0xae, 0x71, 0x6d, 0xfa, 0xf7, 0xe4, 0xed, 0x41, 0x1a, - 0x51, 0x9a, 0xbe, 0x22, 0x53, 0xae, 0x6d, 0xb5, 0x99, 0x19, 0xa8, 0x22, - 0x75, 0x8d, 0xac, 0x17, 0x02, 0x7c, 0x5c, 0xa4, 0x8a, 0xd5, 0xab, 0xfc, - 0x41, 0x7e, 0xc5, 0xdf, 0x08, 0x8a, 0xf6, 0xe8, 0xb6, 0x86, 0xa8, 0xd9, - 0xbf, 0xfe, 0xf6, 0x01, 0x00, 0xfb, 0x39, 0x8f, 0xae, 0x3c, 0x16, 0x18, - 0x3a, 0x00, 0x7c, 0x8c, 0xfc, 0xb7, 0xb0, 0x3d, 0x29, 0xde, 0x93, 0x77, - 0xc4, 0xf2, 0x02, 0x01, 0xf6, 0x0b, 0x42, 0xb0, 0xf7, 0xa2, 0xe4, 0xbe, - 0xe5, 0x00, 0x00, 0x00, 0x15, 0x00, 0xc9, 0xde, 0x4e, 0x93, 0x74, 0x92, - 0xbf, 0x7a, 0x82, 0xe0, 0x52, 0xa8, 0x36, 0x6d, 0x40, 0x7d, 0xe0, 0xc8, - 0xe0, 0xf7, 0x00, 0x00, 0x00, 0x80, 0x29, 0xf5, 0x0d, 0xd2, 0xca, 0x8a, - 0x24, 0x94, 0xb1, 0x8c, 0x3d, 0xd1, 0xb6, 0x92, 0x3d, 0x2f, 0x31, 0x61, - 0x7e, 0x71, 0x5b, 0x42, 0x85, 0xc8, 0xc6, 0x8d, 0xe9, 0xa1, 0x3d, 0xe1, - 0xd7, 0xca, 0x30, 0xf9, 0xfe, 0x29, 0xfc, 0x81, 0x66, 0x05, 0x89, 0xf5, - 0x6a, 0xa1, 0x82, 0x81, 0x26, 0x10, 0x1a, 0x3c, 0xfe, 0x47, 0xa4, 0xfb, - 0x40, 0xdc, 0x11, 0x06, 0x80, 0x89, 0x0b, 0x54, 0x64, 0x73, 0x0a, 0x4d, - 0xed, 0x9f, 0x05, 0xdb, 0xba, 0xd1, 0x9b, 0xc2, 0xde, 0xcf, 0xce, 0xeb, - 0x5b, 0x27, 0xd2, 0xca, 0x8a, 0x24, 0x7b, 0xcf, 0x51, 0xcb, 0xaa, 0x71, - 0x3e, 0xaf, 0x4f, 0xff, 0xe8, 0xd8, 0x6a, 0xcf, 0xf6, 0x4d, 0x40, 0xf5, - 0x99, 0x45, 0xb7, 0x06, 0xd2, 0x5d, 0x44, 0x21, 0x03, 0x60, 0x8e, 0xe6, - 0x64, 0x4b, 0x32, 0x4b, 0x2c, 0xed, 0x79, 0x4d, 0x23, 0xd9, 0x79, 0x58, - 0x59, 0x71, 0x00, 0x00, 0x00, 0x80, 0x14, 0x01, 0x8a, 0x1b, 0xc8, 0xa4, - 0x37, 0x46, 0x5e, 0x2a, 0x5c, 0x07, 0x0e, 0x3f, 0xcb, 0x8e, 0xb7, 0x9a, - 0xbb, 0x60, 0x73, 0x32, 0xe3, 0x72, 0x66, 0x64, 0x99, 0xd3, 0x09, 0x0e, - 0xd7, 0xf7, 0x94, 0xee, 0x36, 0xfe, 0x64, 0x16, 0x3e, 0xda, 0xe5, 0x19, - 0x03, 0x53, 0xd1, 0xe3, 0x83, 0x34, 0xa0, 0xe5, 0xa6, 0x9b, 0x56, 0xc2, - 0x40, 0x0f, 0xac, 0x03, 0xcb, 0x9f, 0xeb, 0x9b, 0xe9, 0x09, 0x03, 0xdb, - 0x97, 0x18, 0xeb, 0xc7, 0x7e, 0x24, 0xe8, 0x87, 0xeb, 0x51, 0x8c, 0x3a, - 0x76, 0x4a, 0xb5, 0x83, 0x11, 0x17, 0xcf, 0x09, 0x10, 0xe5, 0xf2, 0x84, - 0xc9, 0xaf, 0x7e, 0xa9, 0xd7, 0x3a, 0x85, 0x5c, 0x44, 0x70, 0x4c, 0x9b, - 0x0d, 0x24, 0x5d, 0xf6, 0x40, 0x29, 0x6c, 0xce, 0x1c, 0xe4, 0xec, 0xd6, - 0x2f, 0x1b, 0xa9, 0x1c, 0x69, 0x00, 0xbc, 0x1e, 0x19, 0xbd, 0xc9, 0xc7, - 0x11, 0xa0, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x53, - 0x53, 0x48, 0x32, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, - 0x45, 0x59, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x41, 0x41, 0x41, 0x41, - 0x42, 0x33, 0x4e, 0x7a, 0x61, 0x43, 0x31, 0x6b, 0x63, 0x33, 0x4d, 0x41, - 0x41, 0x41, 0x43, 0x42, 0x41, 0x49, 0x34, 0x43, 0x52, 0x2b, 0x74, 0x67, - 0x7a, 0x2f, 0x6b, 0x5a, 0x6e, 0x62, 0x6d, 0x4b, 0x4a, 0x6a, 0x63, 0x63, - 0x5a, 0x4e, 0x57, 0x4b, 0x71, 0x63, 0x69, 0x66, 0x63, 0x78, 0x4c, 0x79, - 0x2f, 0x70, 0x54, 0x4d, 0x6e, 0x52, 0x4c, 0x68, 0x35, 0x53, 0x72, 0x7a, - 0x51, 0x34, 0x34, 0x52, 0x38, 0x54, 0x0a, 0x51, 0x53, 0x62, 0x51, 0x54, - 0x4e, 0x6e, 0x4a, 0x48, 0x56, 0x70, 0x63, 0x36, 0x75, 0x63, 0x57, 0x33, - 0x36, 0x39, 0x2b, 0x54, 0x74, 0x51, 0x52, 0x70, 0x52, 0x6d, 0x72, 0x34, - 0x69, 0x55, 0x36, 0x35, 0x74, 0x74, 0x5a, 0x6b, 0x5a, 0x71, 0x43, 0x4a, - 0x31, 0x6a, 0x61, 0x77, 0x58, 0x41, 0x6e, 0x78, 0x63, 0x70, 0x49, 0x72, - 0x56, 0x71, 0x2f, 0x78, 0x42, 0x66, 0x73, 0x58, 0x66, 0x43, 0x49, 0x72, - 0x32, 0x36, 0x4c, 0x61, 0x47, 0x0a, 0x71, 0x4e, 0x6d, 0x2f, 0x2f, 0x76, - 0x59, 0x42, 0x41, 0x50, 0x73, 0x35, 0x6a, 0x36, 0x34, 0x38, 0x46, 0x68, - 0x67, 0x36, 0x41, 0x48, 0x79, 0x4d, 0x2f, 0x4c, 0x65, 0x77, 0x50, 0x53, - 0x6e, 0x65, 0x6b, 0x33, 0x66, 0x45, 0x38, 0x67, 0x49, 0x42, 0x39, 0x67, - 0x74, 0x43, 0x73, 0x50, 0x65, 0x69, 0x35, 0x4c, 0x37, 0x6c, 0x41, 0x41, - 0x41, 0x41, 0x46, 0x51, 0x44, 0x4a, 0x33, 0x6b, 0x36, 0x54, 0x64, 0x4a, - 0x4b, 0x2f, 0x65, 0x6f, 0x0a, 0x4c, 0x67, 0x55, 0x71, 0x67, 0x32, 0x62, - 0x55, 0x42, 0x39, 0x34, 0x4d, 0x6a, 0x67, 0x39, 0x77, 0x41, 0x41, 0x41, - 0x49, 0x41, 0x70, 0x39, 0x51, 0x33, 0x53, 0x79, 0x6f, 0x6f, 0x6b, 0x6c, - 0x4c, 0x47, 0x4d, 0x50, 0x64, 0x47, 0x32, 0x6b, 0x6a, 0x30, 0x76, 0x4d, - 0x57, 0x46, 0x2b, 0x63, 0x56, 0x74, 0x43, 0x68, 0x63, 0x6a, 0x47, 0x6a, - 0x65, 0x6d, 0x68, 0x50, 0x65, 0x48, 0x58, 0x79, 0x6a, 0x44, 0x35, 0x2f, - 0x69, 0x6e, 0x38, 0x0a, 0x67, 0x57, 0x59, 0x46, 0x69, 0x66, 0x56, 0x71, - 0x6f, 0x59, 0x4b, 0x42, 0x4a, 0x68, 0x41, 0x61, 0x50, 0x50, 0x35, 0x48, - 0x70, 0x50, 0x74, 0x41, 0x33, 0x42, 0x45, 0x47, 0x67, 0x49, 0x6b, 0x4c, - 0x56, 0x47, 0x52, 0x7a, 0x43, 0x6b, 0x33, 0x74, 0x6e, 0x77, 0x58, 0x62, - 0x75, 0x74, 0x47, 0x62, 0x77, 0x74, 0x37, 0x50, 0x7a, 0x75, 0x74, 0x62, - 0x4a, 0x39, 0x4c, 0x4b, 0x69, 0x69, 0x52, 0x37, 0x7a, 0x31, 0x48, 0x4c, - 0x71, 0x6e, 0x0a, 0x45, 0x2b, 0x72, 0x30, 0x2f, 0x2f, 0x36, 0x4e, 0x68, - 0x71, 0x7a, 0x2f, 0x5a, 0x4e, 0x51, 0x50, 0x57, 0x5a, 0x52, 0x62, 0x63, - 0x47, 0x30, 0x6c, 0x31, 0x45, 0x49, 0x51, 0x4e, 0x67, 0x6a, 0x75, 0x5a, - 0x6b, 0x53, 0x7a, 0x4a, 0x4c, 0x4c, 0x4f, 0x31, 0x35, 0x54, 0x53, 0x50, - 0x5a, 0x65, 0x56, 0x68, 0x5a, 0x63, 0x51, 0x41, 0x41, 0x41, 0x49, 0x41, - 0x55, 0x41, 0x59, 0x6f, 0x62, 0x79, 0x4b, 0x51, 0x33, 0x52, 0x6c, 0x34, - 0x71, 0x0a, 0x58, 0x41, 0x63, 0x4f, 0x50, 0x38, 0x75, 0x4f, 0x74, 0x35, - 0x71, 0x37, 0x59, 0x48, 0x4d, 0x79, 0x34, 0x33, 0x4a, 0x6d, 0x5a, 0x4a, - 0x6e, 0x54, 0x43, 0x51, 0x37, 0x58, 0x39, 0x35, 0x54, 0x75, 0x4e, 0x76, - 0x35, 0x6b, 0x46, 0x6a, 0x37, 0x61, 0x35, 0x52, 0x6b, 0x44, 0x55, 0x39, - 0x48, 0x6a, 0x67, 0x7a, 0x53, 0x67, 0x35, 0x61, 0x61, 0x62, 0x56, 0x73, - 0x4a, 0x41, 0x44, 0x36, 0x77, 0x44, 0x79, 0x35, 0x2f, 0x72, 0x6d, 0x2b, - 0x0a, 0x6b, 0x4a, 0x41, 0x39, 0x75, 0x58, 0x47, 0x4f, 0x76, 0x48, 0x66, - 0x69, 0x54, 0x6f, 0x68, 0x2b, 0x74, 0x52, 0x6a, 0x44, 0x70, 0x32, 0x53, - 0x72, 0x57, 0x44, 0x45, 0x52, 0x66, 0x50, 0x43, 0x52, 0x44, 0x6c, 0x38, - 0x6f, 0x54, 0x4a, 0x72, 0x33, 0x36, 0x70, 0x31, 0x7a, 0x71, 0x46, 0x58, - 0x45, 0x52, 0x77, 0x54, 0x4a, 0x73, 0x4e, 0x4a, 0x46, 0x33, 0x32, 0x51, - 0x43, 0x6c, 0x73, 0x7a, 0x68, 0x7a, 0x6b, 0x37, 0x4e, 0x59, 0x76, 0x0a, - 0x47, 0x36, 0x6b, 0x63, 0x61, 0x51, 0x43, 0x38, 0x48, 0x68, 0x6d, 0x39, - 0x79, 0x63, 0x63, 0x52, 0x6f, 0x41, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, - 0x2d, 0x20, 0x45, 0x4e, 0x44, 0x20, 0x53, 0x53, 0x48, 0x32, 0x20, 0x50, - 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x20, 0x2d, 0x2d, - 0x2d, 0x2d, - ]) - }, - what: 'DSA public key (RFC4716 format) with no comment' - }, - { source: [ - 'PuTTY-User-Key-File-2: ssh-rsa', - 'Encryption: none', - 'Comment: rsa-key-20141119', - 'Public-Lines: 4', - 'AAAAB3NzaC1yc2EAAAABJQAAAIBrBWETAVAyJmuNG53jwTNDlbIcH5lrEvcx6lx5', - 'bM6EKg0XmOIH96VqUjS7eRRTTD9lpBA8hYhkrOjOx93/JWB/pcVN8/B3DYHshT9O', - 'BW1DCkrNwut2pbJ2oZOBirhhAr+xqWFr3551FqbzaCIXpOKubr4EcIwCipBl6PxL', - 'USfHgw==', - 'Private-Lines: 8', - 'AAAAgFPhnxy71xKM0NZhwPDH3BJgkoS+0jFUDdsDy/B34CJmJe/mh6VhPHXtZ5nb', - 'cMuqduD2Nj1GEPT2Oe4t8y/DWXfFkO0YNEQRw5Z3WhXheBH9Li26KmHf8TdK838u', - 'ec+4Vji/vFYaMU6wVL73joWcAT5Dnh38ZpFc98W264N5DZaNAAAAQQDJYPKtCs/l', - '46KJmN3lUANdI4QIuWQ+Zllz7p94FfdotnkvqG++Bp1wOqJSCih6UViwLfvpNZtG', - 'MCtk46WNhc0zAAAAQQCIDI3hZSz/THhai8b3nonUD65IQp5bO6p+kYZtaBn1d+c+', - 'eT7UCXwU5bW271Zasw8hq9Cdlb91fGGR41ZMfvxxAAAAQFSBjCa/fzeICVkPFBaK', - 'QUmXjQ3IcPTOr90mSAiPnAAppSwTj5SYSfE9rSVb+EhQ0hk2VKWIfocNHBD1MAN9', - 'zb4=', - 'Private-MAC: 0bc5cc619df85b79dfd3ea25f0e59230cf671cd2' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'rsa-key-20141119', - encryption: undefined, - private: new Buffer([ - 0x30, 0x82, 0x02, 0x59, 0x02, 0x01, 0x00, 0x02, 0x81, 0x80, 0x6b, 0x05, - 0x61, 0x13, 0x01, 0x50, 0x32, 0x26, 0x6b, 0x8d, 0x1b, 0x9d, 0xe3, 0xc1, - 0x33, 0x43, 0x95, 0xb2, 0x1c, 0x1f, 0x99, 0x6b, 0x12, 0xf7, 0x31, 0xea, - 0x5c, 0x79, 0x6c, 0xce, 0x84, 0x2a, 0x0d, 0x17, 0x98, 0xe2, 0x07, 0xf7, - 0xa5, 0x6a, 0x52, 0x34, 0xbb, 0x79, 0x14, 0x53, 0x4c, 0x3f, 0x65, 0xa4, - 0x10, 0x3c, 0x85, 0x88, 0x64, 0xac, 0xe8, 0xce, 0xc7, 0xdd, 0xff, 0x25, - 0x60, 0x7f, 0xa5, 0xc5, 0x4d, 0xf3, 0xf0, 0x77, 0x0d, 0x81, 0xec, 0x85, - 0x3f, 0x4e, 0x05, 0x6d, 0x43, 0x0a, 0x4a, 0xcd, 0xc2, 0xeb, 0x76, 0xa5, - 0xb2, 0x76, 0xa1, 0x93, 0x81, 0x8a, 0xb8, 0x61, 0x02, 0xbf, 0xb1, 0xa9, - 0x61, 0x6b, 0xdf, 0x9e, 0x75, 0x16, 0xa6, 0xf3, 0x68, 0x22, 0x17, 0xa4, - 0xe2, 0xae, 0x6e, 0xbe, 0x04, 0x70, 0x8c, 0x02, 0x8a, 0x90, 0x65, 0xe8, - 0xfc, 0x4b, 0x51, 0x27, 0xc7, 0x83, 0x02, 0x01, 0x25, 0x02, 0x81, 0x80, - 0x53, 0xe1, 0x9f, 0x1c, 0xbb, 0xd7, 0x12, 0x8c, 0xd0, 0xd6, 0x61, 0xc0, - 0xf0, 0xc7, 0xdc, 0x12, 0x60, 0x92, 0x84, 0xbe, 0xd2, 0x31, 0x54, 0x0d, - 0xdb, 0x03, 0xcb, 0xf0, 0x77, 0xe0, 0x22, 0x66, 0x25, 0xef, 0xe6, 0x87, - 0xa5, 0x61, 0x3c, 0x75, 0xed, 0x67, 0x99, 0xdb, 0x70, 0xcb, 0xaa, 0x76, - 0xe0, 0xf6, 0x36, 0x3d, 0x46, 0x10, 0xf4, 0xf6, 0x39, 0xee, 0x2d, 0xf3, - 0x2f, 0xc3, 0x59, 0x77, 0xc5, 0x90, 0xed, 0x18, 0x34, 0x44, 0x11, 0xc3, - 0x96, 0x77, 0x5a, 0x15, 0xe1, 0x78, 0x11, 0xfd, 0x2e, 0x2d, 0xba, 0x2a, - 0x61, 0xdf, 0xf1, 0x37, 0x4a, 0xf3, 0x7f, 0x2e, 0x79, 0xcf, 0xb8, 0x56, - 0x38, 0xbf, 0xbc, 0x56, 0x1a, 0x31, 0x4e, 0xb0, 0x54, 0xbe, 0xf7, 0x8e, - 0x85, 0x9c, 0x01, 0x3e, 0x43, 0x9e, 0x1d, 0xfc, 0x66, 0x91, 0x5c, 0xf7, - 0xc5, 0xb6, 0xeb, 0x83, 0x79, 0x0d, 0x96, 0x8d, 0x02, 0x41, 0x00, 0xc9, - 0x60, 0xf2, 0xad, 0x0a, 0xcf, 0xe5, 0xe3, 0xa2, 0x89, 0x98, 0xdd, 0xe5, - 0x50, 0x03, 0x5d, 0x23, 0x84, 0x08, 0xb9, 0x64, 0x3e, 0x66, 0x59, 0x73, - 0xee, 0x9f, 0x78, 0x15, 0xf7, 0x68, 0xb6, 0x79, 0x2f, 0xa8, 0x6f, 0xbe, - 0x06, 0x9d, 0x70, 0x3a, 0xa2, 0x52, 0x0a, 0x28, 0x7a, 0x51, 0x58, 0xb0, - 0x2d, 0xfb, 0xe9, 0x35, 0x9b, 0x46, 0x30, 0x2b, 0x64, 0xe3, 0xa5, 0x8d, - 0x85, 0xcd, 0x33, 0x02, 0x41, 0x00, 0x88, 0x0c, 0x8d, 0xe1, 0x65, 0x2c, - 0xff, 0x4c, 0x78, 0x5a, 0x8b, 0xc6, 0xf7, 0x9e, 0x89, 0xd4, 0x0f, 0xae, - 0x48, 0x42, 0x9e, 0x5b, 0x3b, 0xaa, 0x7e, 0x91, 0x86, 0x6d, 0x68, 0x19, - 0xf5, 0x77, 0xe7, 0x3e, 0x79, 0x3e, 0xd4, 0x09, 0x7c, 0x14, 0xe5, 0xb5, - 0xb6, 0xef, 0x56, 0x5a, 0xb3, 0x0f, 0x21, 0xab, 0xd0, 0x9d, 0x95, 0xbf, - 0x75, 0x7c, 0x61, 0x91, 0xe3, 0x56, 0x4c, 0x7e, 0xfc, 0x71, 0x02, 0x41, - 0x00, 0xb9, 0x0c, 0xfa, 0xac, 0xd9, 0x80, 0xc5, 0x69, 0x64, 0xed, 0x24, - 0xb0, 0x3a, 0x80, 0xe0, 0x7f, 0x19, 0xb7, 0x99, 0x50, 0x69, 0xf4, 0x26, - 0xb3, 0x10, 0x96, 0x15, 0xff, 0xa5, 0x7b, 0x90, 0xa7, 0xad, 0xa1, 0x6a, - 0x58, 0xd8, 0x21, 0xc1, 0x1b, 0x05, 0x72, 0x90, 0x93, 0xb6, 0x7e, 0x3c, - 0xe9, 0xb6, 0xa6, 0xcb, 0xcf, 0x61, 0xb1, 0x47, 0x6a, 0x88, 0xbd, 0x92, - 0xeb, 0x28, 0x1a, 0x16, 0x81, 0x02, 0x40, 0x50, 0xe4, 0xde, 0xbd, 0x5e, - 0xc0, 0xcf, 0x26, 0x8c, 0xc0, 0x37, 0x6f, 0x62, 0xcc, 0xf8, 0x01, 0x8c, - 0xc8, 0x7d, 0xfe, 0x18, 0xf7, 0xf9, 0xf6, 0xac, 0x1f, 0x2d, 0x55, 0xcf, - 0x32, 0x07, 0x93, 0x66, 0xe6, 0xe0, 0x4e, 0xde, 0xf0, 0xe1, 0xfe, 0x96, - 0x6c, 0x0b, 0xe8, 0x41, 0x2f, 0x02, 0xaf, 0x0d, 0x1a, 0x0d, 0x56, 0xc7, - 0xbd, 0xf2, 0xd4, 0x55, 0xb0, 0xb0, 0xaf, 0xda, 0x75, 0x04, 0xcd, 0x02, - 0x40, 0x54, 0x81, 0x8c, 0x26, 0xbf, 0x7f, 0x37, 0x88, 0x09, 0x59, 0x0f, - 0x14, 0x16, 0x8a, 0x41, 0x49, 0x97, 0x8d, 0x0d, 0xc8, 0x70, 0xf4, 0xce, - 0xaf, 0xdd, 0x26, 0x48, 0x08, 0x8f, 0x9c, 0x00, 0x29, 0xa5, 0x2c, 0x13, - 0x8f, 0x94, 0x98, 0x49, 0xf1, 0x3d, 0xad, 0x25, 0x5b, 0xf8, 0x48, 0x50, - 0xd2, 0x19, 0x36, 0x54, 0xa5, 0x88, 0x7e, 0x87, 0x0d, 0x1c, 0x10, 0xf5, - 0x30, 0x03, 0x7d, 0xcd, 0xbe, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43, - 0x57, 0x51, 0x49, 0x42, 0x41, 0x41, 0x4b, 0x42, 0x67, 0x47, 0x73, 0x46, - 0x59, 0x52, 0x4d, 0x42, 0x55, 0x44, 0x49, 0x6d, 0x61, 0x34, 0x30, 0x62, - 0x6e, 0x65, 0x50, 0x42, 0x4d, 0x30, 0x4f, 0x56, 0x73, 0x68, 0x77, 0x66, - 0x6d, 0x57, 0x73, 0x53, 0x39, 0x7a, 0x48, 0x71, 0x58, 0x48, 0x6c, 0x73, - 0x7a, 0x6f, 0x51, 0x71, 0x44, 0x52, 0x65, 0x59, 0x34, 0x67, 0x66, 0x33, - 0x0a, 0x70, 0x57, 0x70, 0x53, 0x4e, 0x4c, 0x74, 0x35, 0x46, 0x46, 0x4e, - 0x4d, 0x50, 0x32, 0x57, 0x6b, 0x45, 0x44, 0x79, 0x46, 0x69, 0x47, 0x53, - 0x73, 0x36, 0x4d, 0x37, 0x48, 0x33, 0x66, 0x38, 0x6c, 0x59, 0x48, 0x2b, - 0x6c, 0x78, 0x55, 0x33, 0x7a, 0x38, 0x48, 0x63, 0x4e, 0x67, 0x65, 0x79, - 0x46, 0x50, 0x30, 0x34, 0x46, 0x62, 0x55, 0x4d, 0x4b, 0x53, 0x73, 0x33, - 0x43, 0x36, 0x33, 0x61, 0x6c, 0x0a, 0x73, 0x6e, 0x61, 0x68, 0x6b, 0x34, - 0x47, 0x4b, 0x75, 0x47, 0x45, 0x43, 0x76, 0x37, 0x47, 0x70, 0x59, 0x57, - 0x76, 0x66, 0x6e, 0x6e, 0x55, 0x57, 0x70, 0x76, 0x4e, 0x6f, 0x49, 0x68, - 0x65, 0x6b, 0x34, 0x71, 0x35, 0x75, 0x76, 0x67, 0x52, 0x77, 0x6a, 0x41, - 0x4b, 0x4b, 0x6b, 0x47, 0x58, 0x6f, 0x2f, 0x45, 0x74, 0x52, 0x4a, 0x38, - 0x65, 0x44, 0x41, 0x67, 0x45, 0x6c, 0x41, 0x6f, 0x47, 0x41, 0x0a, 0x55, - 0x2b, 0x47, 0x66, 0x48, 0x4c, 0x76, 0x58, 0x45, 0x6f, 0x7a, 0x51, 0x31, - 0x6d, 0x48, 0x41, 0x38, 0x4d, 0x66, 0x63, 0x45, 0x6d, 0x43, 0x53, 0x68, - 0x4c, 0x37, 0x53, 0x4d, 0x56, 0x51, 0x4e, 0x32, 0x77, 0x50, 0x4c, 0x38, - 0x48, 0x66, 0x67, 0x49, 0x6d, 0x59, 0x6c, 0x37, 0x2b, 0x61, 0x48, 0x70, - 0x57, 0x45, 0x38, 0x64, 0x65, 0x31, 0x6e, 0x6d, 0x64, 0x74, 0x77, 0x79, - 0x36, 0x70, 0x32, 0x0a, 0x34, 0x50, 0x59, 0x32, 0x50, 0x55, 0x59, 0x51, - 0x39, 0x50, 0x59, 0x35, 0x37, 0x69, 0x33, 0x7a, 0x4c, 0x38, 0x4e, 0x5a, - 0x64, 0x38, 0x57, 0x51, 0x37, 0x52, 0x67, 0x30, 0x52, 0x42, 0x48, 0x44, - 0x6c, 0x6e, 0x64, 0x61, 0x46, 0x65, 0x46, 0x34, 0x45, 0x66, 0x30, 0x75, - 0x4c, 0x62, 0x6f, 0x71, 0x59, 0x64, 0x2f, 0x78, 0x4e, 0x30, 0x72, 0x7a, - 0x66, 0x79, 0x35, 0x35, 0x7a, 0x37, 0x68, 0x57, 0x0a, 0x4f, 0x4c, 0x2b, - 0x38, 0x56, 0x68, 0x6f, 0x78, 0x54, 0x72, 0x42, 0x55, 0x76, 0x76, 0x65, - 0x4f, 0x68, 0x5a, 0x77, 0x42, 0x50, 0x6b, 0x4f, 0x65, 0x48, 0x66, 0x78, - 0x6d, 0x6b, 0x56, 0x7a, 0x33, 0x78, 0x62, 0x62, 0x72, 0x67, 0x33, 0x6b, - 0x4e, 0x6c, 0x6f, 0x30, 0x43, 0x51, 0x51, 0x44, 0x4a, 0x59, 0x50, 0x4b, - 0x74, 0x43, 0x73, 0x2f, 0x6c, 0x34, 0x36, 0x4b, 0x4a, 0x6d, 0x4e, 0x33, - 0x6c, 0x0a, 0x55, 0x41, 0x4e, 0x64, 0x49, 0x34, 0x51, 0x49, 0x75, 0x57, - 0x51, 0x2b, 0x5a, 0x6c, 0x6c, 0x7a, 0x37, 0x70, 0x39, 0x34, 0x46, 0x66, - 0x64, 0x6f, 0x74, 0x6e, 0x6b, 0x76, 0x71, 0x47, 0x2b, 0x2b, 0x42, 0x70, - 0x31, 0x77, 0x4f, 0x71, 0x4a, 0x53, 0x43, 0x69, 0x68, 0x36, 0x55, 0x56, - 0x69, 0x77, 0x4c, 0x66, 0x76, 0x70, 0x4e, 0x5a, 0x74, 0x47, 0x4d, 0x43, - 0x74, 0x6b, 0x34, 0x36, 0x57, 0x4e, 0x0a, 0x68, 0x63, 0x30, 0x7a, 0x41, - 0x6b, 0x45, 0x41, 0x69, 0x41, 0x79, 0x4e, 0x34, 0x57, 0x55, 0x73, 0x2f, - 0x30, 0x78, 0x34, 0x57, 0x6f, 0x76, 0x47, 0x39, 0x35, 0x36, 0x4a, 0x31, - 0x41, 0x2b, 0x75, 0x53, 0x45, 0x4b, 0x65, 0x57, 0x7a, 0x75, 0x71, 0x66, - 0x70, 0x47, 0x47, 0x62, 0x57, 0x67, 0x5a, 0x39, 0x58, 0x66, 0x6e, 0x50, - 0x6e, 0x6b, 0x2b, 0x31, 0x41, 0x6c, 0x38, 0x46, 0x4f, 0x57, 0x31, 0x0a, - 0x74, 0x75, 0x39, 0x57, 0x57, 0x72, 0x4d, 0x50, 0x49, 0x61, 0x76, 0x51, - 0x6e, 0x5a, 0x57, 0x2f, 0x64, 0x58, 0x78, 0x68, 0x6b, 0x65, 0x4e, 0x57, - 0x54, 0x48, 0x37, 0x38, 0x63, 0x51, 0x4a, 0x42, 0x41, 0x4c, 0x6b, 0x4d, - 0x2b, 0x71, 0x7a, 0x5a, 0x67, 0x4d, 0x56, 0x70, 0x5a, 0x4f, 0x30, 0x6b, - 0x73, 0x44, 0x71, 0x41, 0x34, 0x48, 0x38, 0x5a, 0x74, 0x35, 0x6c, 0x51, - 0x61, 0x66, 0x51, 0x6d, 0x0a, 0x73, 0x78, 0x43, 0x57, 0x46, 0x66, 0x2b, - 0x6c, 0x65, 0x35, 0x43, 0x6e, 0x72, 0x61, 0x46, 0x71, 0x57, 0x4e, 0x67, - 0x68, 0x77, 0x52, 0x73, 0x46, 0x63, 0x70, 0x43, 0x54, 0x74, 0x6e, 0x34, - 0x38, 0x36, 0x62, 0x61, 0x6d, 0x79, 0x38, 0x39, 0x68, 0x73, 0x55, 0x64, - 0x71, 0x69, 0x4c, 0x32, 0x53, 0x36, 0x79, 0x67, 0x61, 0x46, 0x6f, 0x45, - 0x43, 0x51, 0x46, 0x44, 0x6b, 0x33, 0x72, 0x31, 0x65, 0x0a, 0x77, 0x4d, - 0x38, 0x6d, 0x6a, 0x4d, 0x41, 0x33, 0x62, 0x32, 0x4c, 0x4d, 0x2b, 0x41, - 0x47, 0x4d, 0x79, 0x48, 0x33, 0x2b, 0x47, 0x50, 0x66, 0x35, 0x39, 0x71, - 0x77, 0x66, 0x4c, 0x56, 0x58, 0x50, 0x4d, 0x67, 0x65, 0x54, 0x5a, 0x75, - 0x62, 0x67, 0x54, 0x74, 0x37, 0x77, 0x34, 0x66, 0x36, 0x57, 0x62, 0x41, - 0x76, 0x6f, 0x51, 0x53, 0x38, 0x43, 0x72, 0x77, 0x30, 0x61, 0x44, 0x56, - 0x62, 0x48, 0x0a, 0x76, 0x66, 0x4c, 0x55, 0x56, 0x62, 0x43, 0x77, 0x72, - 0x39, 0x70, 0x31, 0x42, 0x4d, 0x30, 0x43, 0x51, 0x46, 0x53, 0x42, 0x6a, - 0x43, 0x61, 0x2f, 0x66, 0x7a, 0x65, 0x49, 0x43, 0x56, 0x6b, 0x50, 0x46, - 0x42, 0x61, 0x4b, 0x51, 0x55, 0x6d, 0x58, 0x6a, 0x51, 0x33, 0x49, 0x63, - 0x50, 0x54, 0x4f, 0x72, 0x39, 0x30, 0x6d, 0x53, 0x41, 0x69, 0x50, 0x6e, - 0x41, 0x41, 0x70, 0x70, 0x53, 0x77, 0x54, 0x0a, 0x6a, 0x35, 0x53, 0x59, - 0x53, 0x66, 0x45, 0x39, 0x72, 0x53, 0x56, 0x62, 0x2b, 0x45, 0x68, 0x51, - 0x30, 0x68, 0x6b, 0x32, 0x56, 0x4b, 0x57, 0x49, 0x66, 0x6f, 0x63, 0x4e, - 0x48, 0x42, 0x44, 0x31, 0x4d, 0x41, 0x4e, 0x39, 0x7a, 0x62, 0x34, 0x3d, - 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x52, 0x53, - 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, - 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, - 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x00, 0x80, 0x6b, 0x05, 0x61, 0x13, - 0x01, 0x50, 0x32, 0x26, 0x6b, 0x8d, 0x1b, 0x9d, 0xe3, 0xc1, 0x33, 0x43, - 0x95, 0xb2, 0x1c, 0x1f, 0x99, 0x6b, 0x12, 0xf7, 0x31, 0xea, 0x5c, 0x79, - 0x6c, 0xce, 0x84, 0x2a, 0x0d, 0x17, 0x98, 0xe2, 0x07, 0xf7, 0xa5, 0x6a, - 0x52, 0x34, 0xbb, 0x79, 0x14, 0x53, 0x4c, 0x3f, 0x65, 0xa4, 0x10, 0x3c, - 0x85, 0x88, 0x64, 0xac, 0xe8, 0xce, 0xc7, 0xdd, 0xff, 0x25, 0x60, 0x7f, - 0xa5, 0xc5, 0x4d, 0xf3, 0xf0, 0x77, 0x0d, 0x81, 0xec, 0x85, 0x3f, 0x4e, - 0x05, 0x6d, 0x43, 0x0a, 0x4a, 0xcd, 0xc2, 0xeb, 0x76, 0xa5, 0xb2, 0x76, - 0xa1, 0x93, 0x81, 0x8a, 0xb8, 0x61, 0x02, 0xbf, 0xb1, 0xa9, 0x61, 0x6b, - 0xdf, 0x9e, 0x75, 0x16, 0xa6, 0xf3, 0x68, 0x22, 0x17, 0xa4, 0xe2, 0xae, - 0x6e, 0xbe, 0x04, 0x70, 0x8c, 0x02, 0x8a, 0x90, 0x65, 0xe8, 0xfc, 0x4b, - 0x51, 0x27, 0xc7, 0x83, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, - 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x47, 0x63, 0x4d, 0x41, 0x30, 0x47, 0x43, - 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, - 0x51, 0x55, 0x41, 0x41, 0x34, 0x47, 0x4b, 0x41, 0x44, 0x43, 0x42, 0x68, - 0x67, 0x4b, 0x42, 0x67, 0x47, 0x73, 0x46, 0x59, 0x52, 0x4d, 0x42, 0x55, - 0x44, 0x49, 0x6d, 0x61, 0x34, 0x30, 0x62, 0x6e, 0x65, 0x50, 0x42, 0x4d, - 0x30, 0x4f, 0x56, 0x73, 0x68, 0x77, 0x66, 0x0a, 0x6d, 0x57, 0x73, 0x53, - 0x39, 0x7a, 0x48, 0x71, 0x58, 0x48, 0x6c, 0x73, 0x7a, 0x6f, 0x51, 0x71, - 0x44, 0x52, 0x65, 0x59, 0x34, 0x67, 0x66, 0x33, 0x70, 0x57, 0x70, 0x53, - 0x4e, 0x4c, 0x74, 0x35, 0x46, 0x46, 0x4e, 0x4d, 0x50, 0x32, 0x57, 0x6b, - 0x45, 0x44, 0x79, 0x46, 0x69, 0x47, 0x53, 0x73, 0x36, 0x4d, 0x37, 0x48, - 0x33, 0x66, 0x38, 0x6c, 0x59, 0x48, 0x2b, 0x6c, 0x78, 0x55, 0x33, 0x7a, - 0x0a, 0x38, 0x48, 0x63, 0x4e, 0x67, 0x65, 0x79, 0x46, 0x50, 0x30, 0x34, - 0x46, 0x62, 0x55, 0x4d, 0x4b, 0x53, 0x73, 0x33, 0x43, 0x36, 0x33, 0x61, - 0x6c, 0x73, 0x6e, 0x61, 0x68, 0x6b, 0x34, 0x47, 0x4b, 0x75, 0x47, 0x45, - 0x43, 0x76, 0x37, 0x47, 0x70, 0x59, 0x57, 0x76, 0x66, 0x6e, 0x6e, 0x55, - 0x57, 0x70, 0x76, 0x4e, 0x6f, 0x49, 0x68, 0x65, 0x6b, 0x34, 0x71, 0x35, - 0x75, 0x76, 0x67, 0x52, 0x77, 0x0a, 0x6a, 0x41, 0x4b, 0x4b, 0x6b, 0x47, - 0x58, 0x6f, 0x2f, 0x45, 0x74, 0x52, 0x4a, 0x38, 0x65, 0x44, 0x41, 0x67, - 0x45, 0x6c, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, - 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, - ]), - ppk: true, - privateMAC: '0bc5cc619df85b79dfd3ea25f0e59230cf671cd2', - _converted: true, - _macresult: true - }, - what: 'Unencrypted RSA key (PPK format)' - }, - { source: [ - 'PuTTY-User-Key-File-2: ssh-rsa', - 'Encryption: aes256-cbc', - 'Comment: rsa-key-20141119', - 'Public-Lines: 4', - 'AAAAB3NzaC1yc2EAAAABJQAAAIBrBWETAVAyJmuNG53jwTNDlbIcH5lrEvcx6lx5', - 'bM6EKg0XmOIH96VqUjS7eRRTTD9lpBA8hYhkrOjOx93/JWB/pcVN8/B3DYHshT9O', - 'BW1DCkrNwut2pbJ2oZOBirhhAr+xqWFr3551FqbzaCIXpOKubr4EcIwCipBl6PxL', - 'USfHgw==', - 'Private-Lines: 8', - '8O3NrBePR4+4RHHys8wrRKCmgx3Gsdz1cKoRJJDgnnrQxuAxBTVUlVTC2vzSOXrP', - 'jlKdRP9DbtrL5YF8g9HkMPpzzTdgpiEAGikpIc+L0sJhN+S9VvMoXRRKqyuB7o1C', - 'xZhAeRaZ68izdUUbFd7ajUwBNpGoFppOznGXyf/3/Ao9FfoTKReZzeBd/e2/JFhc', - 'nsYkSbtWfKQBVXF1Fhr10UwRWSMaVJSDkcSuk8ghICoKBBCgRBnZFap0SR77oIJh', - 'DKgmNFktoKzEqh111vYPhQyEEyGNxpD0aEPaGUJEjPEd3C5a46n7mIiqrNX7QJoo', - 'xxZtkueGdXWaoe5mBf1tFc+nCA1l72nUlghJZooQhnO9NPpieu6NNZ8X+tFQ1Rq/', - 'xvOZHzpDOOeOgWdV7oAmRDbDjYPh0H67z2OKCFaP0Z9kgmnwqV2IJvTDrexj1VwY', - '6kFaPldnK+ohXl37oVIlWA==', - 'Private-MAC: 9d09a15a122e48955682ba969d33c75ba8e4be2c' - ].join('\n'), - expected: { - fulltype: 'ssh-rsa', - type: 'rsa', - curve: undefined, - extra: undefined, - comment: 'rsa-key-20141119', - encryption: 'aes256-cbc', - private: new Buffer([ - 0xf0, 0xed, 0xcd, 0xac, 0x17, 0x8f, 0x47, 0x8f, 0xb8, 0x44, 0x71, 0xf2, - 0xb3, 0xcc, 0x2b, 0x44, 0xa0, 0xa6, 0x83, 0x1d, 0xc6, 0xb1, 0xdc, 0xf5, - 0x70, 0xaa, 0x11, 0x24, 0x90, 0xe0, 0x9e, 0x7a, 0xd0, 0xc6, 0xe0, 0x31, - 0x05, 0x35, 0x54, 0x95, 0x54, 0xc2, 0xda, 0xfc, 0xd2, 0x39, 0x7a, 0xcf, - 0x8e, 0x52, 0x9d, 0x44, 0xff, 0x43, 0x6e, 0xda, 0xcb, 0xe5, 0x81, 0x7c, - 0x83, 0xd1, 0xe4, 0x30, 0xfa, 0x73, 0xcd, 0x37, 0x60, 0xa6, 0x21, 0x00, - 0x1a, 0x29, 0x29, 0x21, 0xcf, 0x8b, 0xd2, 0xc2, 0x61, 0x37, 0xe4, 0xbd, - 0x56, 0xf3, 0x28, 0x5d, 0x14, 0x4a, 0xab, 0x2b, 0x81, 0xee, 0x8d, 0x42, - 0xc5, 0x98, 0x40, 0x79, 0x16, 0x99, 0xeb, 0xc8, 0xb3, 0x75, 0x45, 0x1b, - 0x15, 0xde, 0xda, 0x8d, 0x4c, 0x01, 0x36, 0x91, 0xa8, 0x16, 0x9a, 0x4e, - 0xce, 0x71, 0x97, 0xc9, 0xff, 0xf7, 0xfc, 0x0a, 0x3d, 0x15, 0xfa, 0x13, - 0x29, 0x17, 0x99, 0xcd, 0xe0, 0x5d, 0xfd, 0xed, 0xbf, 0x24, 0x58, 0x5c, - 0x9e, 0xc6, 0x24, 0x49, 0xbb, 0x56, 0x7c, 0xa4, 0x01, 0x55, 0x71, 0x75, - 0x16, 0x1a, 0xf5, 0xd1, 0x4c, 0x11, 0x59, 0x23, 0x1a, 0x54, 0x94, 0x83, - 0x91, 0xc4, 0xae, 0x93, 0xc8, 0x21, 0x20, 0x2a, 0x0a, 0x04, 0x10, 0xa0, - 0x44, 0x19, 0xd9, 0x15, 0xaa, 0x74, 0x49, 0x1e, 0xfb, 0xa0, 0x82, 0x61, - 0x0c, 0xa8, 0x26, 0x34, 0x59, 0x2d, 0xa0, 0xac, 0xc4, 0xaa, 0x1d, 0x75, - 0xd6, 0xf6, 0x0f, 0x85, 0x0c, 0x84, 0x13, 0x21, 0x8d, 0xc6, 0x90, 0xf4, - 0x68, 0x43, 0xda, 0x19, 0x42, 0x44, 0x8c, 0xf1, 0x1d, 0xdc, 0x2e, 0x5a, - 0xe3, 0xa9, 0xfb, 0x98, 0x88, 0xaa, 0xac, 0xd5, 0xfb, 0x40, 0x9a, 0x28, - 0xc7, 0x16, 0x6d, 0x92, 0xe7, 0x86, 0x75, 0x75, 0x9a, 0xa1, 0xee, 0x66, - 0x05, 0xfd, 0x6d, 0x15, 0xcf, 0xa7, 0x08, 0x0d, 0x65, 0xef, 0x69, 0xd4, - 0x96, 0x08, 0x49, 0x66, 0x8a, 0x10, 0x86, 0x73, 0xbd, 0x34, 0xfa, 0x62, - 0x7a, 0xee, 0x8d, 0x35, 0x9f, 0x17, 0xfa, 0xd1, 0x50, 0xd5, 0x1a, 0xbf, - 0xc6, 0xf3, 0x99, 0x1f, 0x3a, 0x43, 0x38, 0xe7, 0x8e, 0x81, 0x67, 0x55, - 0xee, 0x80, 0x26, 0x44, 0x36, 0xc3, 0x8d, 0x83, 0xe1, 0xd0, 0x7e, 0xbb, - 0xcf, 0x63, 0x8a, 0x08, 0x56, 0x8f, 0xd1, 0x9f, 0x64, 0x82, 0x69, 0xf0, - 0xa9, 0x5d, 0x88, 0x26, 0xf4, 0xc3, 0xad, 0xec, 0x63, 0xd5, 0x5c, 0x18, - 0xea, 0x41, 0x5a, 0x3e, 0x57, 0x67, 0x2b, 0xea, 0x21, 0x5e, 0x5d, 0xfb, - 0xa1, 0x52, 0x25, 0x58, - ]), - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, - 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x00, 0x80, 0x6b, 0x05, 0x61, 0x13, - 0x01, 0x50, 0x32, 0x26, 0x6b, 0x8d, 0x1b, 0x9d, 0xe3, 0xc1, 0x33, 0x43, - 0x95, 0xb2, 0x1c, 0x1f, 0x99, 0x6b, 0x12, 0xf7, 0x31, 0xea, 0x5c, 0x79, - 0x6c, 0xce, 0x84, 0x2a, 0x0d, 0x17, 0x98, 0xe2, 0x07, 0xf7, 0xa5, 0x6a, - 0x52, 0x34, 0xbb, 0x79, 0x14, 0x53, 0x4c, 0x3f, 0x65, 0xa4, 0x10, 0x3c, - 0x85, 0x88, 0x64, 0xac, 0xe8, 0xce, 0xc7, 0xdd, 0xff, 0x25, 0x60, 0x7f, - 0xa5, 0xc5, 0x4d, 0xf3, 0xf0, 0x77, 0x0d, 0x81, 0xec, 0x85, 0x3f, 0x4e, - 0x05, 0x6d, 0x43, 0x0a, 0x4a, 0xcd, 0xc2, 0xeb, 0x76, 0xa5, 0xb2, 0x76, - 0xa1, 0x93, 0x81, 0x8a, 0xb8, 0x61, 0x02, 0xbf, 0xb1, 0xa9, 0x61, 0x6b, - 0xdf, 0x9e, 0x75, 0x16, 0xa6, 0xf3, 0x68, 0x22, 0x17, 0xa4, 0xe2, 0xae, - 0x6e, 0xbe, 0x04, 0x70, 0x8c, 0x02, 0x8a, 0x90, 0x65, 0xe8, 0xfc, 0x4b, - 0x51, 0x27, 0xc7, 0x83, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, - 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x47, 0x63, 0x4d, 0x41, 0x30, 0x47, 0x43, - 0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, - 0x51, 0x55, 0x41, 0x41, 0x34, 0x47, 0x4b, 0x41, 0x44, 0x43, 0x42, 0x68, - 0x67, 0x4b, 0x42, 0x67, 0x47, 0x73, 0x46, 0x59, 0x52, 0x4d, 0x42, 0x55, - 0x44, 0x49, 0x6d, 0x61, 0x34, 0x30, 0x62, 0x6e, 0x65, 0x50, 0x42, 0x4d, - 0x30, 0x4f, 0x56, 0x73, 0x68, 0x77, 0x66, 0x0a, 0x6d, 0x57, 0x73, 0x53, - 0x39, 0x7a, 0x48, 0x71, 0x58, 0x48, 0x6c, 0x73, 0x7a, 0x6f, 0x51, 0x71, - 0x44, 0x52, 0x65, 0x59, 0x34, 0x67, 0x66, 0x33, 0x70, 0x57, 0x70, 0x53, - 0x4e, 0x4c, 0x74, 0x35, 0x46, 0x46, 0x4e, 0x4d, 0x50, 0x32, 0x57, 0x6b, - 0x45, 0x44, 0x79, 0x46, 0x69, 0x47, 0x53, 0x73, 0x36, 0x4d, 0x37, 0x48, - 0x33, 0x66, 0x38, 0x6c, 0x59, 0x48, 0x2b, 0x6c, 0x78, 0x55, 0x33, 0x7a, - 0x0a, 0x38, 0x48, 0x63, 0x4e, 0x67, 0x65, 0x79, 0x46, 0x50, 0x30, 0x34, - 0x46, 0x62, 0x55, 0x4d, 0x4b, 0x53, 0x73, 0x33, 0x43, 0x36, 0x33, 0x61, - 0x6c, 0x73, 0x6e, 0x61, 0x68, 0x6b, 0x34, 0x47, 0x4b, 0x75, 0x47, 0x45, - 0x43, 0x76, 0x37, 0x47, 0x70, 0x59, 0x57, 0x76, 0x66, 0x6e, 0x6e, 0x55, - 0x57, 0x70, 0x76, 0x4e, 0x6f, 0x49, 0x68, 0x65, 0x6b, 0x34, 0x71, 0x35, - 0x75, 0x76, 0x67, 0x52, 0x77, 0x0a, 0x6a, 0x41, 0x4b, 0x4b, 0x6b, 0x47, - 0x58, 0x6f, 0x2f, 0x45, 0x74, 0x52, 0x4a, 0x38, 0x65, 0x44, 0x41, 0x67, - 0x45, 0x6c, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, - 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, - ]), - ppk: true, - privateMAC: '9d09a15a122e48955682ba969d33c75ba8e4be2c' - }, - what: 'Encrypted RSA key (PPK format)' - }, - { source: [ - 'PuTTY-User-Key-File-2: ssh-dss', - 'Encryption: none', - 'Comment: dsa-key-20141202', - 'Public-Lines: 10', - 'AAAAB3NzaC1kc3MAAACBAJn2I8YefRo3BsEeinQt8KQ4cEyArAs7Y/W733oRSYOI', - 'zWF1Ju124ysKrmg2okv+05CYcjV3Yp4AzQeomYAlgmB/7xCEnWaEnxCwAxmrrJMm', - 'PrkwNjHOIi7yM5QOE90IM/Q+IJA4EPBfSb+Xr8fYhrp53KNHVSnc2KkOqpo2FsIj', - 'AAAAFQC4NlP50GqyUqq2B82Vh/w5j3TzwQAAAIAeSGom9LLNdzcwCHnGfxKNnEz3', - '55KITADTxiIpBvnQW+eDHwQvIw6V2Oc73bKCu5ZirZmIMW5w6KjQVwkuQBoF9Koq', - '/2u6VeevtL9pD6TBzSLMVw5pV3PmE4/C/eLiaUxZLIHdbzpqPkAvAUBrXKkj0ijz', - 'cNzCp1fuF8H0pvR8yQAAAIAmvV+kqWhUgDYwNNz1qDaoS8XdsOponutZ/0stRQ66', - 'mKAy8kNVNNQ6oUx1XFl1WUt4iyFY/2Rz2fZhLz5/TbZRK5ygo666WgnxB/Ud4GAx', - '/BPQTghOJJOL00vJk+8jVCGNDc942V6nFXznDMXwqxhRCW6dm+2lTh7ntrli8mCk', - '5g==', - 'Private-Lines: 1', - 'AAAAFAiWSgDAM5Mq9r5dj3uPGnYvFbPb', - 'Private-MAC: c07e1d3ae080613e7cdb63ab06bde2e805bc420b' - ].join('\n'), - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: 'dsa-key-20141202', - encryption: undefined, - private: new Buffer([ - 0x30, 0x82, 0x01, 0xba, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0x99, - 0xf6, 0x23, 0xc6, 0x1e, 0x7d, 0x1a, 0x37, 0x06, 0xc1, 0x1e, 0x8a, 0x74, - 0x2d, 0xf0, 0xa4, 0x38, 0x70, 0x4c, 0x80, 0xac, 0x0b, 0x3b, 0x63, 0xf5, - 0xbb, 0xdf, 0x7a, 0x11, 0x49, 0x83, 0x88, 0xcd, 0x61, 0x75, 0x26, 0xed, - 0x76, 0xe3, 0x2b, 0x0a, 0xae, 0x68, 0x36, 0xa2, 0x4b, 0xfe, 0xd3, 0x90, - 0x98, 0x72, 0x35, 0x77, 0x62, 0x9e, 0x00, 0xcd, 0x07, 0xa8, 0x99, 0x80, - 0x25, 0x82, 0x60, 0x7f, 0xef, 0x10, 0x84, 0x9d, 0x66, 0x84, 0x9f, 0x10, - 0xb0, 0x03, 0x19, 0xab, 0xac, 0x93, 0x26, 0x3e, 0xb9, 0x30, 0x36, 0x31, - 0xce, 0x22, 0x2e, 0xf2, 0x33, 0x94, 0x0e, 0x13, 0xdd, 0x08, 0x33, 0xf4, - 0x3e, 0x20, 0x90, 0x38, 0x10, 0xf0, 0x5f, 0x49, 0xbf, 0x97, 0xaf, 0xc7, - 0xd8, 0x86, 0xba, 0x79, 0xdc, 0xa3, 0x47, 0x55, 0x29, 0xdc, 0xd8, 0xa9, - 0x0e, 0xaa, 0x9a, 0x36, 0x16, 0xc2, 0x23, 0x02, 0x15, 0x00, 0xb8, 0x36, - 0x53, 0xf9, 0xd0, 0x6a, 0xb2, 0x52, 0xaa, 0xb6, 0x07, 0xcd, 0x95, 0x87, - 0xfc, 0x39, 0x8f, 0x74, 0xf3, 0xc1, 0x02, 0x81, 0x80, 0x1e, 0x48, 0x6a, - 0x26, 0xf4, 0xb2, 0xcd, 0x77, 0x37, 0x30, 0x08, 0x79, 0xc6, 0x7f, 0x12, - 0x8d, 0x9c, 0x4c, 0xf7, 0xe7, 0x92, 0x88, 0x4c, 0x00, 0xd3, 0xc6, 0x22, - 0x29, 0x06, 0xf9, 0xd0, 0x5b, 0xe7, 0x83, 0x1f, 0x04, 0x2f, 0x23, 0x0e, - 0x95, 0xd8, 0xe7, 0x3b, 0xdd, 0xb2, 0x82, 0xbb, 0x96, 0x62, 0xad, 0x99, - 0x88, 0x31, 0x6e, 0x70, 0xe8, 0xa8, 0xd0, 0x57, 0x09, 0x2e, 0x40, 0x1a, - 0x05, 0xf4, 0xaa, 0x2a, 0xff, 0x6b, 0xba, 0x55, 0xe7, 0xaf, 0xb4, 0xbf, - 0x69, 0x0f, 0xa4, 0xc1, 0xcd, 0x22, 0xcc, 0x57, 0x0e, 0x69, 0x57, 0x73, - 0xe6, 0x13, 0x8f, 0xc2, 0xfd, 0xe2, 0xe2, 0x69, 0x4c, 0x59, 0x2c, 0x81, - 0xdd, 0x6f, 0x3a, 0x6a, 0x3e, 0x40, 0x2f, 0x01, 0x40, 0x6b, 0x5c, 0xa9, - 0x23, 0xd2, 0x28, 0xf3, 0x70, 0xdc, 0xc2, 0xa7, 0x57, 0xee, 0x17, 0xc1, - 0xf4, 0xa6, 0xf4, 0x7c, 0xc9, 0x02, 0x81, 0x80, 0x26, 0xbd, 0x5f, 0xa4, - 0xa9, 0x68, 0x54, 0x80, 0x36, 0x30, 0x34, 0xdc, 0xf5, 0xa8, 0x36, 0xa8, - 0x4b, 0xc5, 0xdd, 0xb0, 0xea, 0x68, 0x9e, 0xeb, 0x59, 0xff, 0x4b, 0x2d, - 0x45, 0x0e, 0xba, 0x98, 0xa0, 0x32, 0xf2, 0x43, 0x55, 0x34, 0xd4, 0x3a, - 0xa1, 0x4c, 0x75, 0x5c, 0x59, 0x75, 0x59, 0x4b, 0x78, 0x8b, 0x21, 0x58, - 0xff, 0x64, 0x73, 0xd9, 0xf6, 0x61, 0x2f, 0x3e, 0x7f, 0x4d, 0xb6, 0x51, - 0x2b, 0x9c, 0xa0, 0xa3, 0xae, 0xba, 0x5a, 0x09, 0xf1, 0x07, 0xf5, 0x1d, - 0xe0, 0x60, 0x31, 0xfc, 0x13, 0xd0, 0x4e, 0x08, 0x4e, 0x24, 0x93, 0x8b, - 0xd3, 0x4b, 0xc9, 0x93, 0xef, 0x23, 0x54, 0x21, 0x8d, 0x0d, 0xcf, 0x78, - 0xd9, 0x5e, 0xa7, 0x15, 0x7c, 0xe7, 0x0c, 0xc5, 0xf0, 0xab, 0x18, 0x51, - 0x09, 0x6e, 0x9d, 0x9b, 0xed, 0xa5, 0x4e, 0x1e, 0xe7, 0xb6, 0xb9, 0x62, - 0xf2, 0x60, 0xa4, 0xe6, 0x02, 0x14, 0x08, 0x96, 0x4a, 0x00, 0xc0, 0x33, - 0x93, 0x2a, 0xf6, 0xbe, 0x5d, 0x8f, 0x7b, 0x8f, 0x1a, 0x76, 0x2f, 0x15, - 0xb3, 0xdb, - ]), - privateOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x44, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, - 0x75, 0x67, 0x49, 0x42, 0x41, 0x41, 0x4b, 0x42, 0x67, 0x51, 0x43, 0x5a, - 0x39, 0x69, 0x50, 0x47, 0x48, 0x6e, 0x30, 0x61, 0x4e, 0x77, 0x62, 0x42, - 0x48, 0x6f, 0x70, 0x30, 0x4c, 0x66, 0x43, 0x6b, 0x4f, 0x48, 0x42, 0x4d, - 0x67, 0x4b, 0x77, 0x4c, 0x4f, 0x32, 0x50, 0x31, 0x75, 0x39, 0x39, 0x36, - 0x45, 0x55, 0x6d, 0x44, 0x69, 0x4d, 0x31, 0x68, 0x64, 0x53, 0x62, 0x74, - 0x0a, 0x64, 0x75, 0x4d, 0x72, 0x43, 0x71, 0x35, 0x6f, 0x4e, 0x71, 0x4a, - 0x4c, 0x2f, 0x74, 0x4f, 0x51, 0x6d, 0x48, 0x49, 0x31, 0x64, 0x32, 0x4b, - 0x65, 0x41, 0x4d, 0x30, 0x48, 0x71, 0x4a, 0x6d, 0x41, 0x4a, 0x59, 0x4a, - 0x67, 0x66, 0x2b, 0x38, 0x51, 0x68, 0x4a, 0x31, 0x6d, 0x68, 0x4a, 0x38, - 0x51, 0x73, 0x41, 0x4d, 0x5a, 0x71, 0x36, 0x79, 0x54, 0x4a, 0x6a, 0x36, - 0x35, 0x4d, 0x44, 0x59, 0x78, 0x0a, 0x7a, 0x69, 0x49, 0x75, 0x38, 0x6a, - 0x4f, 0x55, 0x44, 0x68, 0x50, 0x64, 0x43, 0x44, 0x50, 0x30, 0x50, 0x69, - 0x43, 0x51, 0x4f, 0x42, 0x44, 0x77, 0x58, 0x30, 0x6d, 0x2f, 0x6c, 0x36, - 0x2f, 0x48, 0x32, 0x49, 0x61, 0x36, 0x65, 0x64, 0x79, 0x6a, 0x52, 0x31, - 0x55, 0x70, 0x33, 0x4e, 0x69, 0x70, 0x44, 0x71, 0x71, 0x61, 0x4e, 0x68, - 0x62, 0x43, 0x49, 0x77, 0x49, 0x56, 0x41, 0x4c, 0x67, 0x32, 0x0a, 0x55, - 0x2f, 0x6e, 0x51, 0x61, 0x72, 0x4a, 0x53, 0x71, 0x72, 0x59, 0x48, 0x7a, - 0x5a, 0x57, 0x48, 0x2f, 0x44, 0x6d, 0x50, 0x64, 0x50, 0x50, 0x42, 0x41, - 0x6f, 0x47, 0x41, 0x48, 0x6b, 0x68, 0x71, 0x4a, 0x76, 0x53, 0x79, 0x7a, - 0x58, 0x63, 0x33, 0x4d, 0x41, 0x68, 0x35, 0x78, 0x6e, 0x38, 0x53, 0x6a, - 0x5a, 0x78, 0x4d, 0x39, 0x2b, 0x65, 0x53, 0x69, 0x45, 0x77, 0x41, 0x30, - 0x38, 0x59, 0x69, 0x0a, 0x4b, 0x51, 0x62, 0x35, 0x30, 0x46, 0x76, 0x6e, - 0x67, 0x78, 0x38, 0x45, 0x4c, 0x79, 0x4d, 0x4f, 0x6c, 0x64, 0x6a, 0x6e, - 0x4f, 0x39, 0x32, 0x79, 0x67, 0x72, 0x75, 0x57, 0x59, 0x71, 0x32, 0x5a, - 0x69, 0x44, 0x46, 0x75, 0x63, 0x4f, 0x69, 0x6f, 0x30, 0x46, 0x63, 0x4a, - 0x4c, 0x6b, 0x41, 0x61, 0x42, 0x66, 0x53, 0x71, 0x4b, 0x76, 0x39, 0x72, - 0x75, 0x6c, 0x58, 0x6e, 0x72, 0x37, 0x53, 0x2f, 0x0a, 0x61, 0x51, 0x2b, - 0x6b, 0x77, 0x63, 0x30, 0x69, 0x7a, 0x46, 0x63, 0x4f, 0x61, 0x56, 0x64, - 0x7a, 0x35, 0x68, 0x4f, 0x50, 0x77, 0x76, 0x33, 0x69, 0x34, 0x6d, 0x6c, - 0x4d, 0x57, 0x53, 0x79, 0x42, 0x33, 0x57, 0x38, 0x36, 0x61, 0x6a, 0x35, - 0x41, 0x4c, 0x77, 0x46, 0x41, 0x61, 0x31, 0x79, 0x70, 0x49, 0x39, 0x49, - 0x6f, 0x38, 0x33, 0x44, 0x63, 0x77, 0x71, 0x64, 0x58, 0x37, 0x68, 0x66, - 0x42, 0x0a, 0x39, 0x4b, 0x62, 0x30, 0x66, 0x4d, 0x6b, 0x43, 0x67, 0x59, - 0x41, 0x6d, 0x76, 0x56, 0x2b, 0x6b, 0x71, 0x57, 0x68, 0x55, 0x67, 0x44, - 0x59, 0x77, 0x4e, 0x4e, 0x7a, 0x31, 0x71, 0x44, 0x61, 0x6f, 0x53, 0x38, - 0x58, 0x64, 0x73, 0x4f, 0x70, 0x6f, 0x6e, 0x75, 0x74, 0x5a, 0x2f, 0x30, - 0x73, 0x74, 0x52, 0x51, 0x36, 0x36, 0x6d, 0x4b, 0x41, 0x79, 0x38, 0x6b, - 0x4e, 0x56, 0x4e, 0x4e, 0x51, 0x36, 0x0a, 0x6f, 0x55, 0x78, 0x31, 0x58, - 0x46, 0x6c, 0x31, 0x57, 0x55, 0x74, 0x34, 0x69, 0x79, 0x46, 0x59, 0x2f, - 0x32, 0x52, 0x7a, 0x32, 0x66, 0x5a, 0x68, 0x4c, 0x7a, 0x35, 0x2f, 0x54, - 0x62, 0x5a, 0x52, 0x4b, 0x35, 0x79, 0x67, 0x6f, 0x36, 0x36, 0x36, 0x57, - 0x67, 0x6e, 0x78, 0x42, 0x2f, 0x55, 0x64, 0x34, 0x47, 0x41, 0x78, 0x2f, - 0x42, 0x50, 0x51, 0x54, 0x67, 0x68, 0x4f, 0x4a, 0x4a, 0x4f, 0x4c, 0x0a, - 0x30, 0x30, 0x76, 0x4a, 0x6b, 0x2b, 0x38, 0x6a, 0x56, 0x43, 0x47, 0x4e, - 0x44, 0x63, 0x39, 0x34, 0x32, 0x56, 0x36, 0x6e, 0x46, 0x58, 0x7a, 0x6e, - 0x44, 0x4d, 0x58, 0x77, 0x71, 0x78, 0x68, 0x52, 0x43, 0x57, 0x36, 0x64, - 0x6d, 0x2b, 0x32, 0x6c, 0x54, 0x68, 0x37, 0x6e, 0x74, 0x72, 0x6c, 0x69, - 0x38, 0x6d, 0x43, 0x6b, 0x35, 0x67, 0x49, 0x55, 0x43, 0x4a, 0x5a, 0x4b, - 0x41, 0x4d, 0x41, 0x7a, 0x0a, 0x6b, 0x79, 0x72, 0x32, 0x76, 0x6c, 0x32, - 0x50, 0x65, 0x34, 0x38, 0x61, 0x64, 0x69, 0x38, 0x56, 0x73, 0x39, 0x73, - 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x44, - 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, - 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, - 0x00, 0x00, 0x81, 0x00, 0x99, 0xf6, 0x23, 0xc6, 0x1e, 0x7d, 0x1a, 0x37, - 0x06, 0xc1, 0x1e, 0x8a, 0x74, 0x2d, 0xf0, 0xa4, 0x38, 0x70, 0x4c, 0x80, - 0xac, 0x0b, 0x3b, 0x63, 0xf5, 0xbb, 0xdf, 0x7a, 0x11, 0x49, 0x83, 0x88, - 0xcd, 0x61, 0x75, 0x26, 0xed, 0x76, 0xe3, 0x2b, 0x0a, 0xae, 0x68, 0x36, - 0xa2, 0x4b, 0xfe, 0xd3, 0x90, 0x98, 0x72, 0x35, 0x77, 0x62, 0x9e, 0x00, - 0xcd, 0x07, 0xa8, 0x99, 0x80, 0x25, 0x82, 0x60, 0x7f, 0xef, 0x10, 0x84, - 0x9d, 0x66, 0x84, 0x9f, 0x10, 0xb0, 0x03, 0x19, 0xab, 0xac, 0x93, 0x26, - 0x3e, 0xb9, 0x30, 0x36, 0x31, 0xce, 0x22, 0x2e, 0xf2, 0x33, 0x94, 0x0e, - 0x13, 0xdd, 0x08, 0x33, 0xf4, 0x3e, 0x20, 0x90, 0x38, 0x10, 0xf0, 0x5f, - 0x49, 0xbf, 0x97, 0xaf, 0xc7, 0xd8, 0x86, 0xba, 0x79, 0xdc, 0xa3, 0x47, - 0x55, 0x29, 0xdc, 0xd8, 0xa9, 0x0e, 0xaa, 0x9a, 0x36, 0x16, 0xc2, 0x23, - 0x00, 0x00, 0x00, 0x15, 0x00, 0xb8, 0x36, 0x53, 0xf9, 0xd0, 0x6a, 0xb2, - 0x52, 0xaa, 0xb6, 0x07, 0xcd, 0x95, 0x87, 0xfc, 0x39, 0x8f, 0x74, 0xf3, - 0xc1, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x48, 0x6a, 0x26, 0xf4, 0xb2, 0xcd, - 0x77, 0x37, 0x30, 0x08, 0x79, 0xc6, 0x7f, 0x12, 0x8d, 0x9c, 0x4c, 0xf7, - 0xe7, 0x92, 0x88, 0x4c, 0x00, 0xd3, 0xc6, 0x22, 0x29, 0x06, 0xf9, 0xd0, - 0x5b, 0xe7, 0x83, 0x1f, 0x04, 0x2f, 0x23, 0x0e, 0x95, 0xd8, 0xe7, 0x3b, - 0xdd, 0xb2, 0x82, 0xbb, 0x96, 0x62, 0xad, 0x99, 0x88, 0x31, 0x6e, 0x70, - 0xe8, 0xa8, 0xd0, 0x57, 0x09, 0x2e, 0x40, 0x1a, 0x05, 0xf4, 0xaa, 0x2a, - 0xff, 0x6b, 0xba, 0x55, 0xe7, 0xaf, 0xb4, 0xbf, 0x69, 0x0f, 0xa4, 0xc1, - 0xcd, 0x22, 0xcc, 0x57, 0x0e, 0x69, 0x57, 0x73, 0xe6, 0x13, 0x8f, 0xc2, - 0xfd, 0xe2, 0xe2, 0x69, 0x4c, 0x59, 0x2c, 0x81, 0xdd, 0x6f, 0x3a, 0x6a, - 0x3e, 0x40, 0x2f, 0x01, 0x40, 0x6b, 0x5c, 0xa9, 0x23, 0xd2, 0x28, 0xf3, - 0x70, 0xdc, 0xc2, 0xa7, 0x57, 0xee, 0x17, 0xc1, 0xf4, 0xa6, 0xf4, 0x7c, - 0xc9, 0x00, 0x00, 0x00, 0x80, 0x26, 0xbd, 0x5f, 0xa4, 0xa9, 0x68, 0x54, - 0x80, 0x36, 0x30, 0x34, 0xdc, 0xf5, 0xa8, 0x36, 0xa8, 0x4b, 0xc5, 0xdd, - 0xb0, 0xea, 0x68, 0x9e, 0xeb, 0x59, 0xff, 0x4b, 0x2d, 0x45, 0x0e, 0xba, - 0x98, 0xa0, 0x32, 0xf2, 0x43, 0x55, 0x34, 0xd4, 0x3a, 0xa1, 0x4c, 0x75, - 0x5c, 0x59, 0x75, 0x59, 0x4b, 0x78, 0x8b, 0x21, 0x58, 0xff, 0x64, 0x73, - 0xd9, 0xf6, 0x61, 0x2f, 0x3e, 0x7f, 0x4d, 0xb6, 0x51, 0x2b, 0x9c, 0xa0, - 0xa3, 0xae, 0xba, 0x5a, 0x09, 0xf1, 0x07, 0xf5, 0x1d, 0xe0, 0x60, 0x31, - 0xfc, 0x13, 0xd0, 0x4e, 0x08, 0x4e, 0x24, 0x93, 0x8b, 0xd3, 0x4b, 0xc9, - 0x93, 0xef, 0x23, 0x54, 0x21, 0x8d, 0x0d, 0xcf, 0x78, 0xd9, 0x5e, 0xa7, - 0x15, 0x7c, 0xe7, 0x0c, 0xc5, 0xf0, 0xab, 0x18, 0x51, 0x09, 0x6e, 0x9d, - 0x9b, 0xed, 0xa5, 0x4e, 0x1e, 0xe7, 0xb6, 0xb9, 0x62, 0xf2, 0x60, 0xa4, - 0xe6, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, - 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, 0x74, 0x6a, 0x43, 0x43, 0x41, - 0x53, 0x73, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x34, 0x42, - 0x41, 0x45, 0x77, 0x67, 0x67, 0x45, 0x65, 0x41, 0x6f, 0x47, 0x42, 0x41, - 0x4a, 0x6e, 0x32, 0x49, 0x38, 0x59, 0x65, 0x66, 0x52, 0x6f, 0x33, 0x42, - 0x73, 0x45, 0x65, 0x69, 0x6e, 0x51, 0x74, 0x38, 0x4b, 0x51, 0x34, 0x63, - 0x45, 0x79, 0x41, 0x72, 0x41, 0x73, 0x37, 0x0a, 0x59, 0x2f, 0x57, 0x37, - 0x33, 0x33, 0x6f, 0x52, 0x53, 0x59, 0x4f, 0x49, 0x7a, 0x57, 0x46, 0x31, - 0x4a, 0x75, 0x31, 0x32, 0x34, 0x79, 0x73, 0x4b, 0x72, 0x6d, 0x67, 0x32, - 0x6f, 0x6b, 0x76, 0x2b, 0x30, 0x35, 0x43, 0x59, 0x63, 0x6a, 0x56, 0x33, - 0x59, 0x70, 0x34, 0x41, 0x7a, 0x51, 0x65, 0x6f, 0x6d, 0x59, 0x41, 0x6c, - 0x67, 0x6d, 0x42, 0x2f, 0x37, 0x78, 0x43, 0x45, 0x6e, 0x57, 0x61, 0x45, - 0x0a, 0x6e, 0x78, 0x43, 0x77, 0x41, 0x78, 0x6d, 0x72, 0x72, 0x4a, 0x4d, - 0x6d, 0x50, 0x72, 0x6b, 0x77, 0x4e, 0x6a, 0x48, 0x4f, 0x49, 0x69, 0x37, - 0x79, 0x4d, 0x35, 0x51, 0x4f, 0x45, 0x39, 0x30, 0x49, 0x4d, 0x2f, 0x51, - 0x2b, 0x49, 0x4a, 0x41, 0x34, 0x45, 0x50, 0x42, 0x66, 0x53, 0x62, 0x2b, - 0x58, 0x72, 0x38, 0x66, 0x59, 0x68, 0x72, 0x70, 0x35, 0x33, 0x4b, 0x4e, - 0x48, 0x56, 0x53, 0x6e, 0x63, 0x0a, 0x32, 0x4b, 0x6b, 0x4f, 0x71, 0x70, - 0x6f, 0x32, 0x46, 0x73, 0x49, 0x6a, 0x41, 0x68, 0x55, 0x41, 0x75, 0x44, - 0x5a, 0x54, 0x2b, 0x64, 0x42, 0x71, 0x73, 0x6c, 0x4b, 0x71, 0x74, 0x67, - 0x66, 0x4e, 0x6c, 0x59, 0x66, 0x38, 0x4f, 0x59, 0x39, 0x30, 0x38, 0x38, - 0x45, 0x43, 0x67, 0x59, 0x41, 0x65, 0x53, 0x47, 0x6f, 0x6d, 0x39, 0x4c, - 0x4c, 0x4e, 0x64, 0x7a, 0x63, 0x77, 0x43, 0x48, 0x6e, 0x47, 0x0a, 0x66, - 0x78, 0x4b, 0x4e, 0x6e, 0x45, 0x7a, 0x33, 0x35, 0x35, 0x4b, 0x49, 0x54, - 0x41, 0x44, 0x54, 0x78, 0x69, 0x49, 0x70, 0x42, 0x76, 0x6e, 0x51, 0x57, - 0x2b, 0x65, 0x44, 0x48, 0x77, 0x51, 0x76, 0x49, 0x77, 0x36, 0x56, 0x32, - 0x4f, 0x63, 0x37, 0x33, 0x62, 0x4b, 0x43, 0x75, 0x35, 0x5a, 0x69, 0x72, - 0x5a, 0x6d, 0x49, 0x4d, 0x57, 0x35, 0x77, 0x36, 0x4b, 0x6a, 0x51, 0x56, - 0x77, 0x6b, 0x75, 0x0a, 0x51, 0x42, 0x6f, 0x46, 0x39, 0x4b, 0x6f, 0x71, - 0x2f, 0x32, 0x75, 0x36, 0x56, 0x65, 0x65, 0x76, 0x74, 0x4c, 0x39, 0x70, - 0x44, 0x36, 0x54, 0x42, 0x7a, 0x53, 0x4c, 0x4d, 0x56, 0x77, 0x35, 0x70, - 0x56, 0x33, 0x50, 0x6d, 0x45, 0x34, 0x2f, 0x43, 0x2f, 0x65, 0x4c, 0x69, - 0x61, 0x55, 0x78, 0x5a, 0x4c, 0x49, 0x48, 0x64, 0x62, 0x7a, 0x70, 0x71, - 0x50, 0x6b, 0x41, 0x76, 0x41, 0x55, 0x42, 0x72, 0x0a, 0x58, 0x4b, 0x6b, - 0x6a, 0x30, 0x69, 0x6a, 0x7a, 0x63, 0x4e, 0x7a, 0x43, 0x70, 0x31, 0x66, - 0x75, 0x46, 0x38, 0x48, 0x30, 0x70, 0x76, 0x52, 0x38, 0x79, 0x51, 0x4f, - 0x42, 0x68, 0x41, 0x41, 0x43, 0x67, 0x59, 0x41, 0x6d, 0x76, 0x56, 0x2b, - 0x6b, 0x71, 0x57, 0x68, 0x55, 0x67, 0x44, 0x59, 0x77, 0x4e, 0x4e, 0x7a, - 0x31, 0x71, 0x44, 0x61, 0x6f, 0x53, 0x38, 0x58, 0x64, 0x73, 0x4f, 0x70, - 0x6f, 0x0a, 0x6e, 0x75, 0x74, 0x5a, 0x2f, 0x30, 0x73, 0x74, 0x52, 0x51, - 0x36, 0x36, 0x6d, 0x4b, 0x41, 0x79, 0x38, 0x6b, 0x4e, 0x56, 0x4e, 0x4e, - 0x51, 0x36, 0x6f, 0x55, 0x78, 0x31, 0x58, 0x46, 0x6c, 0x31, 0x57, 0x55, - 0x74, 0x34, 0x69, 0x79, 0x46, 0x59, 0x2f, 0x32, 0x52, 0x7a, 0x32, 0x66, - 0x5a, 0x68, 0x4c, 0x7a, 0x35, 0x2f, 0x54, 0x62, 0x5a, 0x52, 0x4b, 0x35, - 0x79, 0x67, 0x6f, 0x36, 0x36, 0x36, 0x0a, 0x57, 0x67, 0x6e, 0x78, 0x42, - 0x2f, 0x55, 0x64, 0x34, 0x47, 0x41, 0x78, 0x2f, 0x42, 0x50, 0x51, 0x54, - 0x67, 0x68, 0x4f, 0x4a, 0x4a, 0x4f, 0x4c, 0x30, 0x30, 0x76, 0x4a, 0x6b, - 0x2b, 0x38, 0x6a, 0x56, 0x43, 0x47, 0x4e, 0x44, 0x63, 0x39, 0x34, 0x32, - 0x56, 0x36, 0x6e, 0x46, 0x58, 0x7a, 0x6e, 0x44, 0x4d, 0x58, 0x77, 0x71, - 0x78, 0x68, 0x52, 0x43, 0x57, 0x36, 0x64, 0x6d, 0x2b, 0x32, 0x6c, 0x0a, - 0x54, 0x68, 0x37, 0x6e, 0x74, 0x72, 0x6c, 0x69, 0x38, 0x6d, 0x43, 0x6b, - 0x35, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, - 0x44, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - ppk: true, - privateMAC: 'c07e1d3ae080613e7cdb63ab06bde2e805bc420b', - _converted: true, - _macresult: true - }, - what: 'Unencrypted DSA key (PPK format)' - }, - { source: [ - 'PuTTY-User-Key-File-2: ssh-dss', - 'Encryption: aes256-cbc', - 'Comment: dsa-key-20141202', - 'Public-Lines: 10', - 'AAAAB3NzaC1kc3MAAACBAJn2I8YefRo3BsEeinQt8KQ4cEyArAs7Y/W733oRSYOI', - 'zWF1Ju124ysKrmg2okv+05CYcjV3Yp4AzQeomYAlgmB/7xCEnWaEnxCwAxmrrJMm', - 'PrkwNjHOIi7yM5QOE90IM/Q+IJA4EPBfSb+Xr8fYhrp53KNHVSnc2KkOqpo2FsIj', - 'AAAAFQC4NlP50GqyUqq2B82Vh/w5j3TzwQAAAIAeSGom9LLNdzcwCHnGfxKNnEz3', - '55KITADTxiIpBvnQW+eDHwQvIw6V2Oc73bKCu5ZirZmIMW5w6KjQVwkuQBoF9Koq', - '/2u6VeevtL9pD6TBzSLMVw5pV3PmE4/C/eLiaUxZLIHdbzpqPkAvAUBrXKkj0ijz', - 'cNzCp1fuF8H0pvR8yQAAAIAmvV+kqWhUgDYwNNz1qDaoS8XdsOponutZ/0stRQ66', - 'mKAy8kNVNNQ6oUx1XFl1WUt4iyFY/2Rz2fZhLz5/TbZRK5ygo666WgnxB/Ud4GAx', - '/BPQTghOJJOL00vJk+8jVCGNDc942V6nFXznDMXwqxhRCW6dm+2lTh7ntrli8mCk', - '5g==', - 'Private-Lines: 1', - 'BytvbK+jNyMjiVxCO5lcE4YbW7q293oC+LZjkZ8Ajlw=', - 'Private-MAC: c3da536ea28851fc32d5d1ff01498c8fcebc1170' - ].join('\n'), - expected: { - fulltype: 'ssh-dss', - type: 'dss', - curve: undefined, - extra: undefined, - comment: 'dsa-key-20141202', - encryption: 'aes256-cbc', - private: new Buffer([ - 0x07, 0x2b, 0x6f, 0x6c, 0xaf, 0xa3, 0x37, 0x23, 0x23, 0x89, 0x5c, 0x42, - 0x3b, 0x99, 0x5c, 0x13, 0x86, 0x1b, 0x5b, 0xba, 0xb6, 0xf7, 0x7a, 0x02, - 0xf8, 0xb6, 0x63, 0x91, 0x9f, 0x00, 0x8e, 0x5c, - ]), - privateOrig: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, - 0x00, 0x00, 0x81, 0x00, 0x99, 0xf6, 0x23, 0xc6, 0x1e, 0x7d, 0x1a, 0x37, - 0x06, 0xc1, 0x1e, 0x8a, 0x74, 0x2d, 0xf0, 0xa4, 0x38, 0x70, 0x4c, 0x80, - 0xac, 0x0b, 0x3b, 0x63, 0xf5, 0xbb, 0xdf, 0x7a, 0x11, 0x49, 0x83, 0x88, - 0xcd, 0x61, 0x75, 0x26, 0xed, 0x76, 0xe3, 0x2b, 0x0a, 0xae, 0x68, 0x36, - 0xa2, 0x4b, 0xfe, 0xd3, 0x90, 0x98, 0x72, 0x35, 0x77, 0x62, 0x9e, 0x00, - 0xcd, 0x07, 0xa8, 0x99, 0x80, 0x25, 0x82, 0x60, 0x7f, 0xef, 0x10, 0x84, - 0x9d, 0x66, 0x84, 0x9f, 0x10, 0xb0, 0x03, 0x19, 0xab, 0xac, 0x93, 0x26, - 0x3e, 0xb9, 0x30, 0x36, 0x31, 0xce, 0x22, 0x2e, 0xf2, 0x33, 0x94, 0x0e, - 0x13, 0xdd, 0x08, 0x33, 0xf4, 0x3e, 0x20, 0x90, 0x38, 0x10, 0xf0, 0x5f, - 0x49, 0xbf, 0x97, 0xaf, 0xc7, 0xd8, 0x86, 0xba, 0x79, 0xdc, 0xa3, 0x47, - 0x55, 0x29, 0xdc, 0xd8, 0xa9, 0x0e, 0xaa, 0x9a, 0x36, 0x16, 0xc2, 0x23, - 0x00, 0x00, 0x00, 0x15, 0x00, 0xb8, 0x36, 0x53, 0xf9, 0xd0, 0x6a, 0xb2, - 0x52, 0xaa, 0xb6, 0x07, 0xcd, 0x95, 0x87, 0xfc, 0x39, 0x8f, 0x74, 0xf3, - 0xc1, 0x00, 0x00, 0x00, 0x80, 0x1e, 0x48, 0x6a, 0x26, 0xf4, 0xb2, 0xcd, - 0x77, 0x37, 0x30, 0x08, 0x79, 0xc6, 0x7f, 0x12, 0x8d, 0x9c, 0x4c, 0xf7, - 0xe7, 0x92, 0x88, 0x4c, 0x00, 0xd3, 0xc6, 0x22, 0x29, 0x06, 0xf9, 0xd0, - 0x5b, 0xe7, 0x83, 0x1f, 0x04, 0x2f, 0x23, 0x0e, 0x95, 0xd8, 0xe7, 0x3b, - 0xdd, 0xb2, 0x82, 0xbb, 0x96, 0x62, 0xad, 0x99, 0x88, 0x31, 0x6e, 0x70, - 0xe8, 0xa8, 0xd0, 0x57, 0x09, 0x2e, 0x40, 0x1a, 0x05, 0xf4, 0xaa, 0x2a, - 0xff, 0x6b, 0xba, 0x55, 0xe7, 0xaf, 0xb4, 0xbf, 0x69, 0x0f, 0xa4, 0xc1, - 0xcd, 0x22, 0xcc, 0x57, 0x0e, 0x69, 0x57, 0x73, 0xe6, 0x13, 0x8f, 0xc2, - 0xfd, 0xe2, 0xe2, 0x69, 0x4c, 0x59, 0x2c, 0x81, 0xdd, 0x6f, 0x3a, 0x6a, - 0x3e, 0x40, 0x2f, 0x01, 0x40, 0x6b, 0x5c, 0xa9, 0x23, 0xd2, 0x28, 0xf3, - 0x70, 0xdc, 0xc2, 0xa7, 0x57, 0xee, 0x17, 0xc1, 0xf4, 0xa6, 0xf4, 0x7c, - 0xc9, 0x00, 0x00, 0x00, 0x80, 0x26, 0xbd, 0x5f, 0xa4, 0xa9, 0x68, 0x54, - 0x80, 0x36, 0x30, 0x34, 0xdc, 0xf5, 0xa8, 0x36, 0xa8, 0x4b, 0xc5, 0xdd, - 0xb0, 0xea, 0x68, 0x9e, 0xeb, 0x59, 0xff, 0x4b, 0x2d, 0x45, 0x0e, 0xba, - 0x98, 0xa0, 0x32, 0xf2, 0x43, 0x55, 0x34, 0xd4, 0x3a, 0xa1, 0x4c, 0x75, - 0x5c, 0x59, 0x75, 0x59, 0x4b, 0x78, 0x8b, 0x21, 0x58, 0xff, 0x64, 0x73, - 0xd9, 0xf6, 0x61, 0x2f, 0x3e, 0x7f, 0x4d, 0xb6, 0x51, 0x2b, 0x9c, 0xa0, - 0xa3, 0xae, 0xba, 0x5a, 0x09, 0xf1, 0x07, 0xf5, 0x1d, 0xe0, 0x60, 0x31, - 0xfc, 0x13, 0xd0, 0x4e, 0x08, 0x4e, 0x24, 0x93, 0x8b, 0xd3, 0x4b, 0xc9, - 0x93, 0xef, 0x23, 0x54, 0x21, 0x8d, 0x0d, 0xcf, 0x78, 0xd9, 0x5e, 0xa7, - 0x15, 0x7c, 0xe7, 0x0c, 0xc5, 0xf0, 0xab, 0x18, 0x51, 0x09, 0x6e, 0x9d, - 0x9b, 0xed, 0xa5, 0x4e, 0x1e, 0xe7, 0xb6, 0xb9, 0x62, 0xf2, 0x60, 0xa4, - 0xe6, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50, - 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x42, 0x74, 0x6a, 0x43, 0x43, 0x41, - 0x53, 0x73, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x34, 0x42, - 0x41, 0x45, 0x77, 0x67, 0x67, 0x45, 0x65, 0x41, 0x6f, 0x47, 0x42, 0x41, - 0x4a, 0x6e, 0x32, 0x49, 0x38, 0x59, 0x65, 0x66, 0x52, 0x6f, 0x33, 0x42, - 0x73, 0x45, 0x65, 0x69, 0x6e, 0x51, 0x74, 0x38, 0x4b, 0x51, 0x34, 0x63, - 0x45, 0x79, 0x41, 0x72, 0x41, 0x73, 0x37, 0x0a, 0x59, 0x2f, 0x57, 0x37, - 0x33, 0x33, 0x6f, 0x52, 0x53, 0x59, 0x4f, 0x49, 0x7a, 0x57, 0x46, 0x31, - 0x4a, 0x75, 0x31, 0x32, 0x34, 0x79, 0x73, 0x4b, 0x72, 0x6d, 0x67, 0x32, - 0x6f, 0x6b, 0x76, 0x2b, 0x30, 0x35, 0x43, 0x59, 0x63, 0x6a, 0x56, 0x33, - 0x59, 0x70, 0x34, 0x41, 0x7a, 0x51, 0x65, 0x6f, 0x6d, 0x59, 0x41, 0x6c, - 0x67, 0x6d, 0x42, 0x2f, 0x37, 0x78, 0x43, 0x45, 0x6e, 0x57, 0x61, 0x45, - 0x0a, 0x6e, 0x78, 0x43, 0x77, 0x41, 0x78, 0x6d, 0x72, 0x72, 0x4a, 0x4d, - 0x6d, 0x50, 0x72, 0x6b, 0x77, 0x4e, 0x6a, 0x48, 0x4f, 0x49, 0x69, 0x37, - 0x79, 0x4d, 0x35, 0x51, 0x4f, 0x45, 0x39, 0x30, 0x49, 0x4d, 0x2f, 0x51, - 0x2b, 0x49, 0x4a, 0x41, 0x34, 0x45, 0x50, 0x42, 0x66, 0x53, 0x62, 0x2b, - 0x58, 0x72, 0x38, 0x66, 0x59, 0x68, 0x72, 0x70, 0x35, 0x33, 0x4b, 0x4e, - 0x48, 0x56, 0x53, 0x6e, 0x63, 0x0a, 0x32, 0x4b, 0x6b, 0x4f, 0x71, 0x70, - 0x6f, 0x32, 0x46, 0x73, 0x49, 0x6a, 0x41, 0x68, 0x55, 0x41, 0x75, 0x44, - 0x5a, 0x54, 0x2b, 0x64, 0x42, 0x71, 0x73, 0x6c, 0x4b, 0x71, 0x74, 0x67, - 0x66, 0x4e, 0x6c, 0x59, 0x66, 0x38, 0x4f, 0x59, 0x39, 0x30, 0x38, 0x38, - 0x45, 0x43, 0x67, 0x59, 0x41, 0x65, 0x53, 0x47, 0x6f, 0x6d, 0x39, 0x4c, - 0x4c, 0x4e, 0x64, 0x7a, 0x63, 0x77, 0x43, 0x48, 0x6e, 0x47, 0x0a, 0x66, - 0x78, 0x4b, 0x4e, 0x6e, 0x45, 0x7a, 0x33, 0x35, 0x35, 0x4b, 0x49, 0x54, - 0x41, 0x44, 0x54, 0x78, 0x69, 0x49, 0x70, 0x42, 0x76, 0x6e, 0x51, 0x57, - 0x2b, 0x65, 0x44, 0x48, 0x77, 0x51, 0x76, 0x49, 0x77, 0x36, 0x56, 0x32, - 0x4f, 0x63, 0x37, 0x33, 0x62, 0x4b, 0x43, 0x75, 0x35, 0x5a, 0x69, 0x72, - 0x5a, 0x6d, 0x49, 0x4d, 0x57, 0x35, 0x77, 0x36, 0x4b, 0x6a, 0x51, 0x56, - 0x77, 0x6b, 0x75, 0x0a, 0x51, 0x42, 0x6f, 0x46, 0x39, 0x4b, 0x6f, 0x71, - 0x2f, 0x32, 0x75, 0x36, 0x56, 0x65, 0x65, 0x76, 0x74, 0x4c, 0x39, 0x70, - 0x44, 0x36, 0x54, 0x42, 0x7a, 0x53, 0x4c, 0x4d, 0x56, 0x77, 0x35, 0x70, - 0x56, 0x33, 0x50, 0x6d, 0x45, 0x34, 0x2f, 0x43, 0x2f, 0x65, 0x4c, 0x69, - 0x61, 0x55, 0x78, 0x5a, 0x4c, 0x49, 0x48, 0x64, 0x62, 0x7a, 0x70, 0x71, - 0x50, 0x6b, 0x41, 0x76, 0x41, 0x55, 0x42, 0x72, 0x0a, 0x58, 0x4b, 0x6b, - 0x6a, 0x30, 0x69, 0x6a, 0x7a, 0x63, 0x4e, 0x7a, 0x43, 0x70, 0x31, 0x66, - 0x75, 0x46, 0x38, 0x48, 0x30, 0x70, 0x76, 0x52, 0x38, 0x79, 0x51, 0x4f, - 0x42, 0x68, 0x41, 0x41, 0x43, 0x67, 0x59, 0x41, 0x6d, 0x76, 0x56, 0x2b, - 0x6b, 0x71, 0x57, 0x68, 0x55, 0x67, 0x44, 0x59, 0x77, 0x4e, 0x4e, 0x7a, - 0x31, 0x71, 0x44, 0x61, 0x6f, 0x53, 0x38, 0x58, 0x64, 0x73, 0x4f, 0x70, - 0x6f, 0x0a, 0x6e, 0x75, 0x74, 0x5a, 0x2f, 0x30, 0x73, 0x74, 0x52, 0x51, - 0x36, 0x36, 0x6d, 0x4b, 0x41, 0x79, 0x38, 0x6b, 0x4e, 0x56, 0x4e, 0x4e, - 0x51, 0x36, 0x6f, 0x55, 0x78, 0x31, 0x58, 0x46, 0x6c, 0x31, 0x57, 0x55, - 0x74, 0x34, 0x69, 0x79, 0x46, 0x59, 0x2f, 0x32, 0x52, 0x7a, 0x32, 0x66, - 0x5a, 0x68, 0x4c, 0x7a, 0x35, 0x2f, 0x54, 0x62, 0x5a, 0x52, 0x4b, 0x35, - 0x79, 0x67, 0x6f, 0x36, 0x36, 0x36, 0x0a, 0x57, 0x67, 0x6e, 0x78, 0x42, - 0x2f, 0x55, 0x64, 0x34, 0x47, 0x41, 0x78, 0x2f, 0x42, 0x50, 0x51, 0x54, - 0x67, 0x68, 0x4f, 0x4a, 0x4a, 0x4f, 0x4c, 0x30, 0x30, 0x76, 0x4a, 0x6b, - 0x2b, 0x38, 0x6a, 0x56, 0x43, 0x47, 0x4e, 0x44, 0x63, 0x39, 0x34, 0x32, - 0x56, 0x36, 0x6e, 0x46, 0x58, 0x7a, 0x6e, 0x44, 0x4d, 0x58, 0x77, 0x71, - 0x78, 0x68, 0x52, 0x43, 0x57, 0x36, 0x64, 0x6d, 0x2b, 0x32, 0x6c, 0x0a, - 0x54, 0x68, 0x37, 0x6e, 0x74, 0x72, 0x6c, 0x69, 0x38, 0x6d, 0x43, 0x6b, - 0x35, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, - 0x44, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - ]), - ppk: true, - privateMAC: 'c3da536ea28851fc32d5d1ff01498c8fcebc1170' - }, - what: 'Encrypted DSA key (PPK format)' - }, -].forEach(function(v) { - require('buffer').INSPECT_MAX_BYTES = Infinity; - var result; - try { - result = parser(v.source); - } catch (ex) { - console.log('Exception encountered for: ' + v.what + '\n' + ex.stack); - process.exit(1); - } - /*if (result.private) { - for (var i = 0; i < result.private.length; ++i) { - if (i % 12 === 0) - process.stdout.write('\n'); - process.stdout.write('0x' + (result.private[i] < 16 ? '0' : '') + result.private[i].toString(16) + ', '); - } - } - console.log('');*/ - assert.deepEqual(result, - v.expected, - '[' + group + v.what + ']: parser output mismatch.' - + '\nSaw: ' + inspect(result) - + '\nExpected: ' + inspect(v.expected)); -}); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-packet60.js b/reverse_engineering/node_modules/ssh2-streams/test/test-packet60.js deleted file mode 100644 index eba9b79..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-packet60.js +++ /dev/null @@ -1,256 +0,0 @@ -var SSH2Stream = require('../lib/ssh'); -var parseKey = require('../lib/utils').parseKey; -var genPubKey = require('../lib/utils').genPublicKey; - -var assert = require('assert'); -var crypto = require('crypto'); -var fs = require('fs'); - -var t = -1; -var SERVER_PRV_KEY = fs.readFileSync(__dirname + '/fixtures/ssh_host_rsa_key'); -var PARSED_SERVER_PRV_KEY = parseKey(SERVER_PRV_KEY); -var PARSED_SERVER_PUB_KEY = genPubKey(PARSED_SERVER_PRV_KEY); -var CLIENT_PRV_KEY = fs.readFileSync(__dirname + '/fixtures/id_rsa'); -var PARSED_CLIENT_PRV_KEY = parseKey(CLIENT_PRV_KEY); -var PARSED_CLIENT_PUB_KEY = genPubKey(PARSED_CLIENT_PRV_KEY); - -function makePair(cb) { - var server = new SSH2Stream({ - server: true, - hostKeys: { - 'ssh-rsa': { - privateKey: PARSED_SERVER_PRV_KEY, - publicKey: PARSED_SERVER_PUB_KEY - } - } - }); - var client = new SSH2Stream(); - - var done = []; - function tryDone(who) { - done.push(who); - if (done.length !== 2) - return; - cb(server, client); - } - - server.on('NEWKEYS', function () { tryDone('server'); }); - client.on('NEWKEYS', function () { tryDone('client'); }); - server.pipe(client).pipe(server); -} - -function signWithClientKey(blob, syncCb) { - var signType = (PARSED_CLIENT_PRV_KEY.type === 'rsa' ? 'R' : 'D') + 'SA-SHA1'; - var signature = crypto.createSign(signType); - signature.update(blob); - signature = signature.sign(PARSED_CLIENT_PRV_KEY.privateOrig); - syncCb(signature); -} - -function bufferEqual(a, b) { - if (a.length !== b.length) - return false; - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) - return false; - } - return true; -} - -function publickey(server, client) { - server.on('USERAUTH_REQUEST', function(user, service, method, data) { - assert.equal(user, 'bob'); - assert.equal(service, 'ssh-connection'); - assert.equal(method, 'publickey'); - assert.equal(data.keyAlgo, PARSED_CLIENT_PUB_KEY.fulltype); - assert.equal(true, bufferEqual(data.key, PARSED_CLIENT_PUB_KEY.public)); - assert.equal(data.signature, undefined); - assert.equal(data.blob, undefined); - return server.authPKOK(data.keyAlgo, data.key); - }); - client.on('USERAUTH_PK_OK', function() { - next(); - }).authPK('bob', PARSED_CLIENT_PUB_KEY); -} - -function keyboardInteractive(server, client) { - var infoReqsRxed = 0; - - server.on('USERAUTH_REQUEST', function(user, service, method, data) { - assert.equal(user, 'bob'); - assert.equal(service, 'ssh-connection'); - assert.equal(method, 'keyboard-interactive'); - assert.equal(data, ''); - process.nextTick(function() { - server.authInfoReq('req 0', 'instructions', [ - { prompt: 'Say something to req 0', echo: true } - ]); - }); - }).on('USERAUTH_INFO_RESPONSE', function(responses) { - if (infoReqsRxed === 1) { - assert.equal(responses.length, 1); - assert.equal(responses[0], 'hello to req 0'); - process.nextTick(function() { - server.authInfoReq('req 1', 'new instructions', [ - { prompt: 'Say something to req 1', echo: true }, - { prompt: 'Say something else', echo: false } - ]); - }); - } else if (infoReqsRxed === 2) { - assert.equal(responses.length, 2); - assert.equal(responses[0], 'hello to req 1'); - assert.equal(responses[1], 'something else'); - next(); - } else { - throw new Error('Received too many info reqs: ' + infoReqsRxed); - } - }); - - client.on('USERAUTH_INFO_REQUEST', function (name, inst, lang, prompts) { - infoReqsRxed++; - if (infoReqsRxed === 1) { - assert.equal(name, 'req 0'); - assert.equal(inst, 'instructions'); - assert.equal(lang, ''); - assert.deepEqual(prompts, [ - { prompt: 'Say something to req 0', echo: true } - ]); - process.nextTick(function() { - client.authInfoRes([ 'hello to req 0' ]); - }); - } else if (infoReqsRxed === 2) { - assert.equal(name, 'req 1'); - assert.equal(inst, 'new instructions'); - assert.equal(lang, ''); - assert.deepEqual(prompts, [ - { prompt: 'Say something to req 1', echo: true }, - { prompt: 'Say something else', echo: false } - ]); - process.nextTick(function() { - client.authInfoRes([ 'hello to req 1', 'something else' ]); - }); - } else { - throw new Error('Received too many info reqs: ' + infoReqsRxed); - } - }).authKeyboard('bob'); -} - -function mixedMethods(server, client) { - var expectedStages = [ - 'SERVER_SEES_PK_CHECK', - 'SERVER_SEES_PK_REQUEST', - 'SERVER_SEES_PASSWORD', - 'SERVER_SEES_KEYBOARD_INTERACTIVE', - 'CLIENT_SEES_PK_OK', - 'CLIENT_SEES_USERAUTH_FAILURE_PK', - 'CLIENT_SEES_USERAUTH_FAILURE_PASSWORD', - 'CLIENT_SEES_KEYBOARD_REQ', - 'SERVER_SEES_KEYBOARD_RES', - 'CLIENT_SEES_USERAUTH_SUCCESS', - ]; - - server.on('USERAUTH_REQUEST', function(name, service, method, data) { - assert.equal(name, 'bob'); - assert.equal(service, 'ssh-connection'); - var expectedStage = expectedStages.shift(); - switch (expectedStage) { - case 'SERVER_SEES_PK_CHECK': - assert.equal(method, 'publickey'); - assert.equal(data.signature, undefined); - return process.nextTick(function() { - server.authPKOK(data.keyAlgo, data.key); - }); - case 'SERVER_SEES_PK_REQUEST': - assert.equal(method, 'publickey'); - assert.notEqual(data.signature, undefined); - return process.nextTick(function() { - server.authFailure( - ['publickey', 'password', 'keyboard-interactive'], - false - ); - }); - case 'SERVER_SEES_PASSWORD': - assert.equal(method, 'password'); - assert.equal(data, 'seekrit'); - return process.nextTick(function() { - server.authFailure( - ['publickey', 'password', 'keyboard-interactive'], - false - ); - }); - case 'SERVER_SEES_KEYBOARD_INTERACTIVE': - assert.equal(method, 'keyboard-interactive'); - assert.equal(data, ''); - return process.nextTick(function() { - server.authInfoReq('Password required', 'Password prompt', [ - { prompt: 'Password:', echo: false } - ]); - }); - default: - throw new Error('Server saw USERAUTH_REQUEST ' + method + - ' but expected ' + expectedStage); - } - }).on('USERAUTH_INFO_RESPONSE', function(responses) { - assert.equal(expectedStages.shift(), 'SERVER_SEES_KEYBOARD_RES'); - assert.deepEqual(responses, [ 'seekrit' ]); - process.nextTick(function() { - server.authSuccess(); - }); - }); - - - client.on('USERAUTH_PK_OK', function() { - assert.equal(expectedStages.shift(), 'CLIENT_SEES_PK_OK'); - }).on('USERAUTH_FAILURE', function() { - var expectedStage = expectedStages.shift(); - if (expectedStage !== 'CLIENT_SEES_USERAUTH_FAILURE_PK' && - expectedStage !== 'CLIENT_SEES_USERAUTH_FAILURE_PASSWORD') { - throw new Error('Client saw USERAUTH_FAILURE but expected ' + - expectedStage); - } - }).on('USERAUTH_INFO_REQUEST', function(name, inst, lang, prompts) { - assert.equal(expectedStages.shift(), 'CLIENT_SEES_KEYBOARD_REQ'); - assert.equal(name, 'Password required'); - assert.equal(inst, 'Password prompt'); - assert.equal(lang, ''); - assert.deepEqual(prompts, [ { prompt: 'Password:', echo: false } ]); - process.nextTick(function() { - client.authInfoRes([ 'seekrit' ]); - }); - }).on('USERAUTH_SUCCESS', function() { - assert.equal(expectedStages.shift(), 'CLIENT_SEES_USERAUTH_SUCCESS'); - assert.equal(expectedStages.shift(), undefined); - next(); - }); - - // Silly to submit all these auths at once, but allowed by RFC4252 - client.authPK('bob', PARSED_CLIENT_PUB_KEY); - client.authPK('bob', PARSED_CLIENT_PUB_KEY, signWithClientKey); - client.authPassword('bob', 'seekrit'); - client.authKeyboard('bob'); -} - -var tests = [ - publickey, - keyboardInteractive, - // password // ssh2-streams can't generate a password change request - mixedMethods -]; - - -function next() { - if (Array.isArray(process._events.exit)) - process._events.exit = process._events.exit[1]; - if (++t === tests.length) - return; - - var v = tests[t]; - makePair(v); -} - -process.once('exit', function() { - assert(t === tests.length, - 'Only finished ' + t + '/' + tests.length + ' tests'); -}); - -next(); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-sftp.js b/reverse_engineering/node_modules/ssh2-streams/test/test-sftp.js deleted file mode 100644 index 03a3093..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-sftp.js +++ /dev/null @@ -1,1274 +0,0 @@ -var SFTPStream = require('../lib/sftp'); -var Stats = SFTPStream.Stats; -var STATUS_CODE = SFTPStream.STATUS_CODE; -var OPEN_MODE = SFTPStream.OPEN_MODE; - -var constants = require('constants'); -var basename = require('path').basename; -var assert = require('assert'); - -var group = basename(__filename, '.js') + '/'; -var t = -1; - -var tests = [ -// successful client requests - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/tmp/foo.txt'; - var handle_ = new Buffer('node.js'); - server.on('OPEN', function(id, path, pflags, attrs) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert(pflags === (OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE), - makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags))); - server.handle(id, handle_); - server.end(); - }); - client.open(path_, 'w', function(err, handle) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected open() error: ' + err)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - }); - }; - }, - what: 'open' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - server.on('CLOSE', function(id, handle) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.close(handle_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected close() error: ' + err)); - }); - }; - }, - what: 'close' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var expected = new Buffer('node.jsnode.jsnode.jsnode.jsnode.jsnode.js'); - var buffer = new Buffer(expected.length); - buffer.fill(0); - server.on('READ', function(id, handle, offset, len) { - assert(++self.state.requests <= 2, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert(offset === 5, makeMsg(what, 'Wrong read offset: ' + offset)); - assert(len === buffer.length, makeMsg(what, 'Wrong read len: ' + len)); - server.data(id, expected); - server.end(); - }); - client.readData(handle_, buffer, 0, buffer.length, 5, clientReadCb); - function clientReadCb(err, code) { - assert(++self.state.responses <= 2, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected readData() error: ' + err)); - assert.deepEqual(buffer, - expected, - makeMsg(what, 'read data mismatch')); - } - }; - }, - what: 'readData' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var buf = new Buffer('node.jsnode.jsnode.jsnode.jsnode.jsnode.js'); - server.on('WRITE', function(id, handle, offset, data) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert(offset === 5, makeMsg(what, 'Wrong write offset: ' + offset)); - assert.deepEqual(data, buf, makeMsg(what, 'write data mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.writeData(handle_, buf, 0, buf.length, 5, function(err, nb) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected writeData() error: ' + err)); - assert.equal(nb, buf.length); - }); - }; - }, - what: 'write' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var buf = new Buffer(3 * 32 * 1024); - server.on('WRITE', function(id, handle, offset, data) { - ++self.state.requests; - assert.equal(id, - self.state.requests - 1, - makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert.equal(offset, - (self.state.requests - 1) * 32 * 1024, - makeMsg(what, 'Wrong write offset: ' + offset)); - assert((offset + data.length) <= buf.length); - assert.deepEqual(data, - buf.slice(offset, offset + data.length), - makeMsg(what, 'write data mismatch')); - server.status(id, STATUS_CODE.OK); - if (self.state.requests === 3) - server.end(); - }); - client.writeData(handle_, buf, 0, buf.length, 0, function(err, nb) { - ++self.state.responses; - assert(!err, makeMsg(what, 'Unexpected writeData() error: ' + err)); - assert.equal(nb, buf.length); - }); - }; - }, - expected: { - requests: 3, - responses: 1 - }, - what: 'write (overflow)' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - var attrs_ = new Stats({ - size: 10 * 1024, - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.on('LSTAT', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.attrs(id, attrs_); - server.end(); - }); - client.lstat(path_, function(err, attrs) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected lstat() error: ' + err)); - assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch')); - }); - }; - }, - what: 'lstat' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var attrs_ = new Stats({ - size: 10 * 1024, - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.on('FSTAT', function(id, handle) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.attrs(id, attrs_); - server.end(); - }); - client.fstat(handle_, function(err, attrs) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected fstat() error: ' + err)); - assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch')); - }); - }; - }, - what: 'fstat' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - var attrs_ = new Stats({ - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.on('SETSTAT', function(id, path, attrs) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.setstat(path_, attrs_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected setstat() error: ' + err)); - }); - }; - }, - what: 'setstat' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var attrs_ = new Stats({ - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.on('FSETSTAT', function(id, handle, attrs) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.fsetstat(handle_, attrs_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected fsetstat() error: ' + err)); - }); - }; - }, - what: 'fsetstat' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var path_ = '/tmp'; - server.on('OPENDIR', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.handle(id, handle_); - server.end(); - }); - client.opendir(path_, function(err, handle) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected opendir() error: ' + err)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - }); - }; - }, - what: 'opendir' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var list_ = [ - { filename: '.', - longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .', - attrs: new Stats({ - mode: 0755 | constants.S_IFDIR, - size: 4096, - uid: 9001, - gid: 8001, - atime: 1415599549, - mtime: 1415599590 - }) - }, - { filename: '..', - longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..', - attrs: new Stats({ - mode: 0755 | constants.S_IFDIR, - size: 4096, - uid: 0, - gid: 0, - atime: 1368729954, - mtime: 1368729999 - }) - }, - { filename: 'foo', - longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo', - attrs: new Stats({ - mode: 0777 | constants.S_IFDIR, - size: 4096, - uid: 9001, - gid: 8001, - atime: 1368729954, - mtime: 1368729999 - }) - }, - { filename: 'bar', - longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar', - attrs: new Stats({ - mode: 0644 | constants.S_IFREG, - size: 513901992, - uid: 9001, - gid: 8001, - atime: 1259972199, - mtime: 1259972199 - }) - } - ]; - server.on('READDIR', function(id, handle) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.name(id, list_); - server.end(); - }); - client.readdir(handle_, function(err, list) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected readdir() error: ' + err)); - assert.deepEqual(list, - list_.slice(2), - makeMsg(what, 'dir list mismatch')); - }); - }; - }, - what: 'readdir' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - var list_ = [ - { filename: '.', - longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .', - attrs: new Stats({ - mode: 0755 | constants.S_IFDIR, - size: 4096, - uid: 9001, - gid: 8001, - atime: 1415599549, - mtime: 1415599590 - }) - }, - { filename: '..', - longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..', - attrs: new Stats({ - mode: 0755 | constants.S_IFDIR, - size: 4096, - uid: 0, - gid: 0, - atime: 1368729954, - mtime: 1368729999 - }) - }, - { filename: 'foo', - longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo', - attrs: new Stats({ - mode: 0777 | constants.S_IFDIR, - size: 4096, - uid: 9001, - gid: 8001, - atime: 1368729954, - mtime: 1368729999 - }) - }, - { filename: 'bar', - longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar', - attrs: new Stats({ - mode: 0644 | constants.S_IFREG, - size: 513901992, - uid: 9001, - gid: 8001, - atime: 1259972199, - mtime: 1259972199 - }) - } - ]; - server.on('READDIR', function(id, handle) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.name(id, list_); - server.end(); - }); - client.readdir(handle_, { full: true }, function(err, list) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected readdir() error: ' + err)); - assert.deepEqual(list, list_, makeMsg(what, 'dir list mismatch')); - }); - }; - }, - what: 'readdir (full)' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - server.on('REMOVE', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.unlink(path_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected unlink() error: ' + err)); - }); - }; - }, - what: 'remove' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - server.on('MKDIR', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.mkdir(path_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected mkdir() error: ' + err)); - }); - }; - }, - what: 'mkdir' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - server.on('RMDIR', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.rmdir(path_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected rmdir() error: ' + err)); - }); - }; - }, - what: 'rmdir' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - var name_ = { filename: '/tmp/foo' }; - server.on('REALPATH', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.name(id, name_); - server.end(); - }); - client.realpath(path_, function(err, name) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected realpath() error: ' + err)); - assert.deepEqual(name, name_.filename, makeMsg(what, 'name mismatch')); - }); - }; - }, - what: 'realpath' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - var attrs_ = new Stats({ - size: 10 * 1024, - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.on('STAT', function(id, path) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - server.attrs(id, attrs_); - server.end(); - }); - client.stat(path_, function(err, attrs) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected stat() error: ' + err)); - assert.deepEqual(attrs, attrs_, makeMsg(what, 'attrs mismatch')); - }); - }; - }, - what: 'stat' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var oldPath_ = '/foo/bar/baz'; - var newPath_ = '/tmp/foo'; - server.on('RENAME', function(id, oldPath, newPath) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(oldPath === oldPath_, - makeMsg(what, 'Wrong old path: ' + oldPath)); - assert(newPath === newPath_, - makeMsg(what, 'Wrong new path: ' + newPath)); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.rename(oldPath_, newPath_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected rename() error: ' + err)); - }); - }; - }, - what: 'rename' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var linkPath_ = '/foo/bar/baz'; - var name = { filename: '/tmp/foo' }; - server.on('READLINK', function(id, linkPath) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(linkPath === linkPath_, - makeMsg(what, 'Wrong link path: ' + linkPath)); - server.name(id, name); - server.end(); - }); - client.readlink(linkPath_, function(err, targetPath) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected readlink() error: ' + err)); - assert(targetPath === name.filename, - makeMsg(what, 'Wrong target path: ' + targetPath)); - }); - }; - }, - what: 'readlink' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var linkPath_ = '/foo/bar/baz'; - var targetPath_ = '/tmp/foo'; - server.on('SYMLINK', function(id, linkPath, targetPath) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(linkPath === linkPath_, - makeMsg(what, 'Wrong link path: ' + linkPath)); - assert(targetPath === targetPath_, - makeMsg(what, 'Wrong target path: ' + targetPath)); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - client.symlink(targetPath_, linkPath_, function(err) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(!err, makeMsg(what, 'Unexpected symlink() error: ' + err)); - }); - }; - }, - what: 'symlink' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - var handle_ = new Buffer('hi mom!'); - var data_ = new Buffer('hello world'); - server.once('OPEN', function(id, path, pflags, attrs) { - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert(pflags === OPEN_MODE.READ, - makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags))); - server.handle(id, handle_); - }).once('FSTAT', function(id, handle) { - assert(id === 1, makeMsg(what, 'Wrong request id: ' + id)); - var attrs = new Stats({ - size: data_.length, - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.attrs(id, attrs); - }).once('READ', function(id, handle, offset, len) { - assert(id === 2, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert(offset === 0, makeMsg(what, 'Wrong read offset: ' + offset)); - server.data(id, data_); - }).once('CLOSE', function(id, handle) { - ++self.state.requests; - assert(id === 3, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - var buf = []; - client.readFile(path_, function(err, buf) { - ++self.state.responses; - assert(!err, makeMsg(what, 'Unexpected error: ' + err)); - assert.deepEqual(buf, data_, makeMsg(what, 'data mismatch')); - }); - }; - }, - what: 'readFile' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/foo/bar/baz'; - var handle_ = new Buffer('hi mom!'); - var data_ = new Buffer('hello world'); - var reads = 0; - server.once('OPEN', function(id, path, pflags, attrs) { - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert(pflags === OPEN_MODE.READ, - makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags))); - server.handle(id, handle_); - }).once('FSTAT', function(id, handle) { - assert(id === 1, makeMsg(what, 'Wrong request id: ' + id)); - var attrs = new Stats({ - uid: 9001, - gid: 9001, - atime: (Date.now() / 1000) | 0, - mtime: (Date.now() / 1000) | 0 - }); - server.attrs(id, attrs); - }).on('READ', function(id, handle, offset, len) { - assert(++reads <= 2, makeMsg(what, 'Saw too many READs')); - assert(id === 2 || id === 3, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - switch(id) { - case 2: - assert(offset === 0, makeMsg(what, 'Wrong read offset for first read: ' + offset)); - server.data(id, data_); - break; - case 3: - assert(offset === data_.length, makeMsg(what, 'Wrong read offset for second read: ' + offset)); - server.status(id, STATUS_CODE.EOF); - break; - } - }).once('CLOSE', function(id, handle) { - ++self.state.requests; - assert(id === 4, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - var buf = []; - client.readFile(path_, function(err, buf) { - ++self.state.responses; - assert(!err, makeMsg(what, 'Unexpected error: ' + err)); - assert.deepEqual(buf, data_, makeMsg(what, 'data mismatch')); - }); - }; - }, - what: 'readFile (no size from fstat)' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var opens = 0; - var reads = 0; - var closes = 0; - var path_ = '/foo/bar/baz'; - var handle_ = new Buffer('hi mom!'); - var data_ = new Buffer('hello world'); - server.on('OPEN', function(id, path, pflags, attrs) { - assert(++opens === 1, makeMsg(what, 'Saw too many OPENs')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert(pflags === OPEN_MODE.READ, - makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags))); - server.handle(id, handle_); - }).on('READ', function(id, handle, offset, len) { - assert(++reads <= 2, makeMsg(what, 'Saw too many READs')); - assert(id === reads, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - if (reads === 1) { - assert(offset === 0, makeMsg(what, 'Wrong read offset: ' + offset)); - server.data(id, data_); - } else - server.status(id, STATUS_CODE.EOF); - }).on('CLOSE', function(id, handle) { - ++self.state.requests; - assert(++closes === 1, makeMsg(what, 'Saw too many CLOSEs')); - assert(id === 3, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }); - var buf = []; - client.createReadStream(path_).on('readable', function() { - var chunk; - while ((chunk = this.read()) !== null) { - buf.push(chunk); - } - }).on('end', function() { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - buf = Buffer.concat(buf); - assert.deepEqual(buf, data_, makeMsg(what, 'data mismatch')); - }); - }; - }, - what: 'ReadStream' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var opens = 0; - var path_ = '/foo/bar/baz'; - var error; - server.on('OPEN', function(id, path, pflags, attrs) { - ++opens; - ++self.state.requests; - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert(pflags === OPEN_MODE.READ, - makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags))); - server.status(id, STATUS_CODE.NO_SUCH_FILE); - server.end(); - }); - client.createReadStream(path_).on('error', function(err) { - error = err; - }).on('close', function() { - assert(opens === 1, makeMsg(what, 'Saw ' + opens + ' OPENs')); - assert(error, makeMsg(what, 'Expected error')); - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - }); - }; - }, - what: 'ReadStream (error)' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var opens = 0; - var writes = 0; - var closes = 0; - var fsetstat = false; - var path_ = '/foo/bar/baz'; - var handle_ = new Buffer('hi mom!'); - var data_ = new Buffer('hello world'); - var expFlags = OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE; - server.on('OPEN', function(id, path, pflags, attrs) { - assert(++opens === 1, makeMsg(what, 'Saw too many OPENs')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert(path === path_, makeMsg(what, 'Wrong path: ' + path)); - assert(pflags === expFlags, - makeMsg(what, 'Wrong flags: ' + flagsToHuman(pflags))); - server.handle(id, handle_); - }).once('FSETSTAT', function(id, handle, attrs) { - fsetstat = true; - assert(id === 1, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert.strictEqual(attrs.mode, - parseInt('0666', 8), - makeMsg(what, 'Wrong file mode')); - server.status(id, STATUS_CODE.OK); - }).on('WRITE', function(id, handle, offset, data) { - assert(++writes <= 3, makeMsg(what, 'Saw too many WRITEs')); - assert(id === writes + 1, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - assert(offset === ((writes - 1) * data_.length), - makeMsg(what, 'Wrong write offset: ' + offset)); - assert.deepEqual(data, data_, makeMsg(what, 'Wrong data')); - server.status(id, STATUS_CODE.OK); - }).on('CLOSE', function(id, handle) { - ++self.state.requests; - assert(++closes === 1, makeMsg(what, 'Saw too many CLOSEs')); - assert(id === 5, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.status(id, STATUS_CODE.OK); - server.end(); - }).on('end', function() { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(opens === 1, makeMsg(what, 'Wrong OPEN count')); - assert(writes === 3, makeMsg(what, 'Wrong WRITE count')); - assert(closes === 1, makeMsg(what, 'Wrong CLOSE count')); - assert(fsetstat, makeMsg(what, 'Expected FSETSTAT')); - }); - - var writer = client.createWriteStream(path_); - if (writer.cork) - writer.cork(); - writer.write(data_); - writer.write(data_); - writer.write(data_); - if (writer.uncork) - writer.uncork(); - writer.end(); - }; - }, - what: 'WriteStream' - }, - -// other client request scenarios - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var handle_ = new Buffer('node.js'); - server.on('READDIR', function(id, handle) { - assert(++self.state.requests === 1, - makeMsg(what, 'Saw too many requests')); - assert(id === 0, makeMsg(what, 'Wrong request id: ' + id)); - assert.deepEqual(handle, handle_, makeMsg(what, 'handle mismatch')); - server.status(id, STATUS_CODE.EOF); - server.end(); - }); - client.readdir(handle_, function(err, list) { - assert(++self.state.responses === 1, - makeMsg(what, 'Saw too many responses')); - assert(err && err.code === STATUS_CODE.EOF, - makeMsg(what, 'Expected EOF, got: ' + err)); - }); - }; - }, - what: 'readdir (EOF)' - }, - { run: function() { - setup(this); - - var self = this; - var what = this.what; - var client = this.client; - var server = this.server; - - this.onReady = function() { - var path_ = '/tmp/foo.txt'; - var reqs = 0; - var continues = 0; - - client.unpipe(server); - - function clientCb(err, handle) { - assert(++self.state.responses <= reqs, - makeMsg(what, 'Saw too many responses')); - if (self.state.responses === reqs) { - assert(continues === 1, makeMsg(what, 'no continue event seen')); - server.end(); - } - } - - client.on('continue', function() { - assert(++continues === 1, makeMsg(what, 'saw > 1 continue event')); - }); - - while (true) { - ++reqs; - if (!client.open(path_, 'w', clientCb)) - break; - } - - client.pipe(server); - }; - }, - expected: { - requests: -1, - responses: -1 - }, - what: '"continue" event after push() === false' - }, - { run: function() { - var self = this; - var client = new SFTPStream(); - client.once('ready', function() { - client.open('/foo/bar', 'w', function(err, handle) { - assert(err, 'Expected error'); - assert.strictEqual(err.code, 4); - assert.strictEqual(err.message, 'Uh oh'); - assert.strictEqual(err.lang, ''); - next(); - }); - client.write(new Buffer([ - 0, 0, 0, 18, - 101, - 0, 0, 0, 0, - 0, 0, 0, SFTPStream.STATUS_CODE.FAILURE, - 0, 0, 0, 5, 85, 104, 32, 111, 104 - ])); - }); - client.write(new Buffer([ - 0, 0, 0, 5, - 2, - 0, 0, 0, 3 - ])); - }, - what: 'Can parse status response without language' - }, - { run: function() { - var self = this; - var client = new SFTPStream(); - client.once('ready', function() { - client.open('/foo/bar', 'w', function(err, handle) { - assert(err, 'Expected error'); - assert.strictEqual(err.code, 4); - assert.strictEqual(err.message, 'Failure'); - assert.strictEqual(err.lang, ''); - next(); - }); - client.write(new Buffer([ - 0, 0, 0, 9, - 101, - 0, 0, 0, 0, - 0, 0, 0, SFTPStream.STATUS_CODE.FAILURE - ])); - }); - client.write(new Buffer([ - 0, 0, 0, 5, - 2, - 0, 0, 0, 3 - ])); - }, - what: 'Can parse status response without message' - }, - { run: function() { - var self = this; - var err; - var client = new SFTPStream(); - client.once('ready', function() { - assert(false, 'Handshake should not succeed'); - }).once('error', function(err_) { - err = err_; - }).once('end', function() { - assert.strictEqual(err && err.message, - 'Unexpected packet before version'); - next(); - }); - client.write(new Buffer([ - 1, 2, 3, 4, - 5, - 6, 7, 8, 9 - ])); - }, - what: 'End SFTP stream on bad handshake (client)' - }, - { run: function() { - var self = this; - var err; - var client = new SFTPStream({ server: true }); - client.once('ready', function() { - assert(false, 'Handshake should not succeed'); - }).once('error', function(err_) { - err = err_; - }).once('end', function() { - assert.strictEqual(err && err.message, - 'Unexpected packet before init'); - next(); - }); - client.write(new Buffer([ - 1, 2, 3, 4, - 5, - 6, 7, 8, 9 - ])); - }, - what: 'End SFTP stream on bad handshake (server)' - }, -]; - -function setup(self) { - var expectedRequests = (self.expected && self.expected.requests) || 1; - var expectedResponses = (self.expected && self.expected.responses) || 1; - var clientEnded = false; - var serverEnded = false; - - self.state = { - clientReady: false, - serverReady: false, - requests: 0, - responses: 0 - }; - - self.client = new SFTPStream(); - self.server = new SFTPStream({ server: true }); - - self.server.on('error', onError) - .on('ready', onReady) - .on('end', onEnd); - self.client.on('error', onError) - .on('ready', onReady) - .on('end', onEnd); - - function onError(err) { - var which = (this === self.server ? 'server' : 'client'); - assert(false, makeMsg(self.what, 'Unexpected ' + which + ' error: ' + err)); - } - function onReady() { - if (this === self.client) { - assert(!self.state.clientReady, - makeMsg(self.what, 'Received multiple ready events for client')); - self.state.clientReady = true; - } else { - assert(!self.state.serverReady, - makeMsg(self.what, 'Received multiple ready events for server')); - self.state.serverReady = true; - } - if (self.state.clientReady && self.state.serverReady) - self.onReady && self.onReady(); - } - function onEnd() { - if (this === self.client) { - assert(!clientEnded, - makeMsg(self.what, 'Received multiple close events for client')); - clientEnded = true; - } else { - assert(!serverEnded, - makeMsg(self.what, 'Received multiple close events for server')); - serverEnded = true; - } - if (clientEnded && serverEnded) { - var msg; - if (expectedRequests > 0) { - msg = 'Expected ' + expectedRequests + ' request(s) but received ' - + self.state.requests; - assert(self.state.requests === expectedRequests, - makeMsg(self.what, msg)); - } - if (expectedResponses > 0) { - msg = 'Expected ' + expectedResponses + ' response(s) but received ' - + self.state.responses; - assert(self.state.responses === expectedResponses, - makeMsg(self.what, msg)); - } - next(); - } - } - - process.nextTick(function() { - self.client.pipe(self.server).pipe(self.client); - }); -} - -function flagsToHuman(flags) { - var ret = []; - - for (var i = 0, keys = Object.keys(OPEN_MODE), len = keys.length; i < len; ++i) - if (flags & OPEN_MODE[keys[i]]) - ret.push(keys[i]); - - return ret.join(' | '); -} - -function next() { - if (++t === tests.length) - return; - - var v = tests[t]; - v.run.call(v); -} - -function makeMsg(what, msg) { - return '[' + group + what + ']: ' + msg; -} - -process.once('exit', function() { - assert(t === tests.length, - makeMsg('_exit', - 'Only finished ' + t + '/' + tests.length + ' tests')); -}); - -next(); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-ssh.js b/reverse_engineering/node_modules/ssh2-streams/test/test-ssh.js deleted file mode 100644 index 5d61522..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-ssh.js +++ /dev/null @@ -1,143 +0,0 @@ -var SSH2Stream = require('../lib/ssh'); -var utils = require('../lib/utils'); -var parseKey = utils.parseKey; -var genPubKey = utils.genPublicKey; - -var basename = require('path').basename; -var assert_ = require('assert'); -var inherits = require('util').inherits; -var inspect = require('util').inspect; -var TransformStream = require('stream').Transform; -var fs = require('fs'); - -var group = basename(__filename, '.js') + '/'; -var t = -1; -var SERVER_KEY = fs.readFileSync(__dirname + '/fixtures/ssh_host_rsa_key'); -var HOST_KEYS = { 'ssh-rsa': makeServerKey(SERVER_KEY) }; - -function SimpleStream() { - TransformStream.call(this); - this.buffer = ''; -} -inherits(SimpleStream, TransformStream); -SimpleStream.prototype._transform = function(chunk, encoding, cb) { - this.buffer += chunk.toString('binary'); - cb(null, chunk); -}; - -var tests = [ - // client-side tests - { run: function() { - var algos = ['ssh-dss', 'ssh-rsa', 'ecdsa-sha2-nistp521']; - var client = new SSH2Stream({ - algorithms: { - serverHostKey: algos - } - }); - var clientBufStream = new SimpleStream(); - var clientReady = false; - var server = new SSH2Stream({ - server: true, - hostKeys: HOST_KEYS - }); - var serverBufStream = new SimpleStream(); - var serverReady = false; - - function onNEWKEYS() { - if (this === client) { - assert(!clientReady, 'Already received client NEWKEYS event'); - clientReady = true; - } else { - assert(!serverReady, 'Already received server NEWKEYS event'); - serverReady = true; - } - if (clientReady && serverReady) { - var traffic = clientBufStream.buffer; - var algoList = algos.join(','); - var re = new RegExp('\x00\x00\x00' - + hexByte(algoList.length) - + algoList); - assert(re.test(traffic), 'Unexpected client algorithms'); - - traffic = serverBufStream.buffer; - assert(/\x00\x00\x00\x07ssh-rsa/.test(traffic), - 'Unexpected server algorithms'); - - next(); - } - } - - client.on('NEWKEYS', onNEWKEYS); - server.on('NEWKEYS', onNEWKEYS); - - client.pipe(clientBufStream) - .pipe(server) - .pipe(serverBufStream) - .pipe(client); - }, - what: 'Custom algorithms' - }, - { run: function() { - var serverIdent = 'testing \t'; - var expectedFullIdent = 'SSH-2.0-' + serverIdent; - - var client = new SSH2Stream({}); - client.on('header', function(header) { - assert(header.identRaw === expectedFullIdent, - '\nSaw: ' + inspect(header.identRaw) + '\n' - + 'Expected: ' + inspect(expectedFullIdent)); - next(); - }); - - var server = new SSH2Stream({ - server: true, - hostKeys: HOST_KEYS, - ident: serverIdent - }); - - client.pipe(server).pipe(client); - }, - what: 'Remote ident is not trimmed' - } -]; - -function makeServerKey(raw) { - var privateKey = parseKey(raw); - return { - privateKey: privateKey, - publicKey: genPubKey(privateKey) - }; -} - -function hexByte(n) { - return String.fromCharCode(n); -} - -function assert(expression, msg) { - msg || (msg = 'failed assertion'); - assert_(expression, makeMsg(tests[t].what, msg)); -} - - - -function next() { - if (Array.isArray(process._events.exit)) - process._events.exit = process._events.exit[1]; - if (++t === tests.length) - return; - - var v = tests[t]; - v.run.call(v); -} - -function makeMsg(what, msg) { - return '[' + group + what + ']: ' + msg; -} - -process.once('exit', function() { - assert_(t === tests.length, - makeMsg('_exit', - 'Only finished ' + t + '/' + tests.length + ' tests')); -}); - -next(); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test-utils.js b/reverse_engineering/node_modules/ssh2-streams/test/test-utils.js deleted file mode 100644 index 2949ab3..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test-utils.js +++ /dev/null @@ -1,678 +0,0 @@ -var utils = require('../lib/utils'); - -var fs = require('fs'); -var path = require('path'); -var assert = require('assert'); - -var t = -1; -var group = path.basename(__filename, '.js') + '/'; -var fixturesdir = path.join(__dirname, 'fixtures'); - -var tests = [ - { run: function() { - var what = this.what; - var r; - - assert.strictEqual(r = utils.readInt(new Buffer([0,0,0]), 0), - false, - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readInt - without stream callback - failure #1' - }, - { run: function() { - var what = this.what; - var r; - - assert.strictEqual(r = utils.readInt(new Buffer([]), 0), - false, - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readInt - without stream callback - failure #2' - }, - { run: function() { - var what = this.what; - var r; - - assert.strictEqual(r = utils.readInt(new Buffer([0,0,0,5]), 0), - 5, - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readInt - without stream callback - success' - }, - { run: function() { - var what = this.what; - var callback = function() {}; - var stream = { - _cleanup: function(cb) { - cleanupCalled = true; - assert(cb === callback, makeMsg(what, 'Wrong callback')); - } - }; - var cleanupCalled = false; - var r; - - assert.strictEqual(r = utils.readInt(new Buffer([]), 0, stream, callback), - false, - makeMsg(what, 'Wrong result: ' + r)); - assert(cleanupCalled, makeMsg(what, 'Cleanup not called')); - next(); - }, - what: 'readInt - with stream callback' - }, - { run: function() { - var what = this.what; - var r; - - assert.strictEqual(r = utils.readString(new Buffer([0,0,0]), 0), - false, - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readString - without stream callback - bad length #1' - }, - { run: function() { - var what = this.what; - var r; - - assert.strictEqual(r = utils.readString(new Buffer([]), 0), - false, - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readString - without stream callback - bad length #2' - }, - { run: function() { - var what = this.what; - var r; - - assert.deepEqual(r = utils.readString(new Buffer([0,0,0,1,5]), 0), - new Buffer([5]), - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readString - without stream callback - success' - }, - { run: function() { - var what = this.what; - var r; - - assert.deepEqual(r = utils.readString(new Buffer([0,0,0,1,33]), 0, 'ascii'), - '!', - makeMsg(what, 'Wrong result: ' + r)); - next(); - }, - what: 'readString - without stream callback - encoding' - }, - { run: function() { - var what = this.what; - var callback = function() {}; - var stream = { - _cleanup: function(cb) { - cleanupCalled = true; - assert(cb === callback, makeMsg(what, 'Wrong callback')); - } - }; - var cleanupCalled = false; - var r; - - assert.deepEqual(r = utils.readString(new Buffer([0,0,0,1]), - 0, - stream, - callback), - false, - makeMsg(what, 'Wrong result: ' + r)); - assert(cleanupCalled, makeMsg(what, 'Cleanup not called')); - next(); - }, - what: 'readString - with stream callback - no encoding' - }, - { run: function() { - var what = this.what; - var callback = function() {}; - var stream = { - _cleanup: function(cb) { - cleanupCalled = true; - assert(cb === callback, makeMsg(what, 'Wrong callback')); - } - }; - var cleanupCalled = false; - var r; - - assert.deepEqual(r = utils.readString(new Buffer([0,0,0,1]), - 0, - 'ascii', - stream, - callback), - false, - makeMsg(what, 'Wrong result: ' + r)); - assert(cleanupCalled, makeMsg(what, 'Cleanup not called')); - next(); - }, - what: 'readString - with stream callback - encoding' - }, - { run: function() { - var what = this.what; - var filepath = fixturesdir + '/encrypted-rsa.ppk'; - var passphrase = 'node.js'; - var keyInfo = utils.parseKey(fs.readFileSync(filepath)); - - utils.decryptKey(keyInfo, passphrase); - - var expPrivOrig = new Buffer([ - 45,45,45,45,45,66,69,71,73,78,32,82,83,65,32,80,82,73,86,65,84,69,32,75, - 69,89,45,45,45,45,45,10,77,73,73,67,87,81,73,66,65,65,75,66,103,71,115, - 70,89,82,77,66,85,68,73,109,97,52,48,98,110,101,80,66,77,48,79,86,115, - 104,119,102,109,87,115,83,57,122,72,113,88,72,108,115,122,111,81,113,68, - 82,101,89,52,103,102,51,10,112,87,112,83,78,76,116,53,70,70,78,77,80,50, - 87,107,69,68,121,70,105,71,83,115,54,77,55,72,51,102,56,108,89,72,43,108, - 120,85,51,122,56,72,99,78,103,101,121,70,80,48,52,70,98,85,77,75,83,115, - 51,67,54,51,97,108,10,115,110,97,104,107,52,71,75,117,71,69,67,118,55,71, - 112,89,87,118,102,110,110,85,87,112,118,78,111,73,104,101,107,52,113,53, - 117,118,103,82,119,106,65,75,75,107,71,88,111,47,69,116,82,74,56,101,68, - 65,103,69,108,65,111,71,65,10,85,43,71,102,72,76,118,88,69,111,122,81,49, - 109,72,65,56,77,102,99,69,109,67,83,104,76,55,83,77,86,81,78,50,119,80, - 76,56,72,102,103,73,109,89,108,55,43,97,72,112,87,69,56,100,101,49,110, - 109,100,116,119,121,54,112,50,10,52,80,89,50,80,85,89,81,57,80,89,53,55, - 105,51,122,76,56,78,90,100,56,87,81,55,82,103,48,82,66,72,68,108,110,100, - 97,70,101,70,52,69,102,48,117,76,98,111,113,89,100,47,120,78,48,114,122, - 102,121,53,53,122,55,104,87,10,79,76,43,56,86,104,111,120,84,114,66,85, - 118,118,101,79,104,90,119,66,80,107,79,101,72,102,120,109,107,86,122,51, - 120,98,98,114,103,51,107,78,108,111,48,67,81,81,68,74,89,80,75,116,67, - 115,47,108,52,54,75,74,109,78,51,108,10,85,65,78,100,73,52,81,73,117,87, - 81,43,90,108,108,122,55,112,57,52,70,102,100,111,116,110,107,118,113,71, - 43,43,66,112,49,119,79,113,74,83,67,105,104,54,85,86,105,119,76,102,118, - 112,78,90,116,71,77,67,116,107,52,54,87,78,10,104,99,48,122,65,107,69,65, - 105,65,121,78,52,87,85,115,47,48,120,52,87,111,118,71,57,53,54,74,49,65, - 43,117,83,69,75,101,87,122,117,113,102,112,71,71,98,87,103,90,57,88,102, - 110,80,110,107,43,49,65,108,56,70,79,87,49,10,116,117,57,87,87,114,77,80, - 73,97,118,81,110,90,87,47,100,88,120,104,107,101,78,87,84,72,55,56,99,81, - 74,66,65,76,107,77,43,113,122,90,103,77,86,112,90,79,48,107,115,68,113, - 65,52,72,56,90,116,53,108,81,97,102,81,109,10,115,120,67,87,70,102,43, - 108,101,53,67,110,114,97,70,113,87,78,103,104,119,82,115,70,99,112,67,84, - 116,110,52,56,54,98,97,109,121,56,57,104,115,85,100,113,105,76,50,83,54, - 121,103,97,70,111,69,67,81,70,68,107,51,114,49,101,10,119,77,56,109,106, - 77,65,51,98,50,76,77,43,65,71,77,121,72,51,43,71,80,102,53,57,113,119, - 102,76,86,88,80,77,103,101,84,90,117,98,103,84,116,55,119,52,102,54,87, - 98,65,118,111,81,83,56,67,114,119,48,97,68,86,98,72,10,118,102,76,85,86, - 98,67,119,114,57,112,49,66,77,48,67,81,70,83,66,106,67,97,47,102,122,101, - 73,67,86,107,80,70,66,97,75,81,85,109,88,106,81,51,73,99,80,84,79,114,57, - 48,109,83,65,105,80,110,65,65,112,112,83,119,84,10,106,53,83,89,83,102, - 69,57,114,83,86,98,43,69,104,81,48,104,107,50,86,75,87,73,102,111,99,78, - 72,66,68,49,77,65,78,57,122,98,52,61,10,45,45,45,45,45,69,78,68,32,82,83, - 65,32,80,82,73,86,65,84,69,32,75,69,89,45,45,45,45,45 - ]); - assert(keyInfo.ppk === true, makeMsg(what, 'Expected PPK flag')); - assert(keyInfo._converted === true, - makeMsg(what, 'Expected automatic private PEM generation')); - assert(keyInfo._macresult === true, - makeMsg(what, 'Expected successful MAC verification')); - assert(keyInfo._decrypted === true, - makeMsg(what, 'Expected decrypted flag')); - assert.deepEqual(keyInfo.privateOrig, - expPrivOrig, - makeMsg(what, 'Decrypted private PEM data mismatch')); - next(); - }, - what: 'decryptKey - with encrypted RSA PPK' - }, - { run: function() { - var what = this.what; - var filepath = fixturesdir + '/encrypted-dsa.ppk'; - var passphrase = 'node.js'; - var keyInfo = utils.parseKey(fs.readFileSync(filepath)); - - utils.decryptKey(keyInfo, passphrase); - - var expPrivOrig = new Buffer([ - 45,45,45,45,45,66,69,71,73,78,32,68,83,65,32,80,82,73,86,65,84,69,32,75, - 69,89,45,45,45,45,45,10,77,73,73,66,117,103,73,66,65,65,75,66,103,81,67, - 90,57,105,80,71,72,110,48,97,78,119,98,66,72,111,112,48,76,102,67,107, - 79,72,66,77,103,75,119,76,79,50,80,49,117,57,57,54,69,85,109,68,105,77, - 49,104,100,83,98,116,10,100,117,77,114,67,113,53,111,78,113,74,76,47,116, - 79,81,109,72,73,49,100,50,75,101,65,77,48,72,113,74,109,65,74,89,74,103, - 102,43,56,81,104,74,49,109,104,74,56,81,115,65,77,90,113,54,121,84,74, - 106,54,53,77,68,89,120,10,122,105,73,117,56,106,79,85,68,104,80,100,67, - 68,80,48,80,105,67,81,79,66,68,119,88,48,109,47,108,54,47,72,50,73,97,54, - 101,100,121,106,82,49,85,112,51,78,105,112,68,113,113,97,78,104,98,67,73, - 119,73,86,65,76,103,50,10,85,47,110,81,97,114,74,83,113,114,89,72,122,90, - 87,72,47,68,109,80,100,80,80,66,65,111,71,65,72,107,104,113,74,118,83, - 121,122,88,99,51,77,65,104,53,120,110,56,83,106,90,120,77,57,43,101,83, - 105,69,119,65,48,56,89,105,10,75,81,98,53,48,70,118,110,103,120,56,69,76, - 121,77,79,108,100,106,110,79,57,50,121,103,114,117,87,89,113,50,90,105, - 68,70,117,99,79,105,111,48,70,99,74,76,107,65,97,66,102,83,113,75,118,57, - 114,117,108,88,110,114,55,83,47,10,97,81,43,107,119,99,48,105,122,70,99, - 79,97,86,100,122,53,104,79,80,119,118,51,105,52,109,108,77,87,83,121,66, - 51,87,56,54,97,106,53,65,76,119,70,65,97,49,121,112,73,57,73,111,56,51, - 68,99,119,113,100,88,55,104,102,66,10,57,75,98,48,102,77,107,67,103,89, - 65,109,118,86,43,107,113,87,104,85,103,68,89,119,78,78,122,49,113,68,97, - 111,83,56,88,100,115,79,112,111,110,117,116,90,47,48,115,116,82,81,54,54, - 109,75,65,121,56,107,78,86,78,78,81,54,10,111,85,120,49,88,70,108,49,87, - 85,116,52,105,121,70,89,47,50,82,122,50,102,90,104,76,122,53,47,84,98,90, - 82,75,53,121,103,111,54,54,54,87,103,110,120,66,47,85,100,52,71,65,120, - 47,66,80,81,84,103,104,79,74,74,79,76,10,48,48,118,74,107,43,56,106,86, - 67,71,78,68,99,57,52,50,86,54,110,70,88,122,110,68,77,88,119,113,120,104, - 82,67,87,54,100,109,43,50,108,84,104,55,110,116,114,108,105,56,109,67, - 107,53,103,73,85,67,74,90,75,65,77,65,122,10,107,121,114,50,118,108,50, - 80,101,52,56,97,100,105,56,86,115,57,115,61,10,45,45,45,45,45,69,78,68, - 32,68,83,65,32,80,82,73,86,65,84,69,32,75,69,89,45,45,45,45,45, - ]); - assert(keyInfo.ppk === true, makeMsg(what, 'Expected PPK flag')); - assert(keyInfo._converted === true, - makeMsg(what, 'Expected automatic private PEM generation')); - assert(keyInfo._macresult === true, - makeMsg(what, 'Expected successful MAC verification')); - assert(keyInfo._decrypted === true, - makeMsg(what, 'Expected decrypted flag')); - assert.deepEqual(keyInfo.privateOrig, - expPrivOrig, - makeMsg(what, 'Decrypted private PEM data mismatch')); - next(); - }, - what: 'decryptKey - with encrypted DSA PPK' - }, - { run: function() { - var what = this.what; - var filepath = fixturesdir + '/id_rsa_enc'; - var passphrase = 'foobarbaz'; - var keyInfo = utils.parseKey(fs.readFileSync(filepath)); - - utils.decryptKey(keyInfo, passphrase); - - var expPriv = new Buffer([ - 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xec, 0x9f, 0xd7, 0x6e, 0x17, 0xfa, 0xe4, 0xc5, 0xff, 0xac, 0x83, 0x6e, - 0xbe, 0x60, 0x66, 0xb2, 0xf2, 0x6a, 0x34, 0xfa, 0x4f, 0xe2, 0x49, 0xcd, - 0x54, 0x29, 0x34, 0x95, 0x3b, 0x55, 0xc1, 0xf5, 0x1f, 0x16, 0x3f, 0x6a, - 0x9f, 0xe5, 0x93, 0x7c, 0x25, 0xe0, 0x92, 0xdb, 0x63, 0x8d, 0xbb, 0xb4, - 0xc2, 0x24, 0x7c, 0x9c, 0x69, 0x4c, 0xe0, 0xa7, 0x21, 0xac, 0xfc, 0xd3, - 0x44, 0x3b, 0x1a, 0xaf, 0x9e, 0x60, 0x93, 0x09, 0xd3, 0xac, 0xb4, 0x65, - 0x88, 0x39, 0x85, 0x8c, 0xd2, 0x04, 0x2c, 0xaf, 0x85, 0x27, 0x92, 0x59, - 0x1b, 0x28, 0x73, 0x99, 0xf9, 0xc1, 0x6c, 0x37, 0x08, 0xa2, 0x77, 0x58, - 0x5a, 0x8c, 0xb0, 0x96, 0xc0, 0x63, 0x8a, 0x10, 0x10, 0x84, 0xd8, 0xfa, - 0x1e, 0xb7, 0x27, 0x58, 0xc1, 0x6b, 0x34, 0xb4, 0xe6, 0xa1, 0x05, 0x68, - 0x82, 0xc9, 0xe3, 0x6a, 0x6f, 0x0b, 0xb5, 0xf7, 0x13, 0xa8, 0x8b, 0x14, - 0x4a, 0x6e, 0x0a, 0x72, 0x39, 0xa6, 0x1f, 0xa0, 0x4f, 0xcb, 0x72, 0xd9, - 0xe5, 0x61, 0x61, 0xa7, 0x63, 0x53, 0xae, 0x66, 0xd6, 0xba, 0xb4, 0xda, - 0x98, 0x92, 0xb4, 0x50, 0x93, 0x36, 0xdf, 0x9a, 0xfe, 0x58, 0x36, 0x6d, - 0x31, 0xd7, 0xff, 0x01, 0x88, 0xe4, 0x49, 0x3b, 0x71, 0x8f, 0x09, 0xe6, - 0x6f, 0xc9, 0xe1, 0x98, 0x51, 0x8c, 0xc4, 0xfa, 0x16, 0xb9, 0x45, 0x14, - 0x7b, 0x9e, 0x0e, 0x09, 0x6d, 0x07, 0x1e, 0x79, 0x4e, 0xa1, 0xb6, 0xf0, - 0xdd, 0x0a, 0x3d, 0xa3, 0x9c, 0xf4, 0xeb, 0x5f, 0xaa, 0x29, 0x37, 0x8c, - 0xb4, 0x03, 0x25, 0xac, 0xe8, 0x64, 0xf6, 0x07, 0xbe, 0xca, 0xc8, 0x48, - 0x39, 0x51, 0xaf, 0x36, 0x42, 0xdd, 0x32, 0x7d, 0x37, 0x7a, 0xdd, 0xd6, - 0xbf, 0x57, 0xf9, 0x10, 0xd7, 0x9f, 0xe4, 0xb8, 0xc8, 0xa7, 0x1b, 0x0c, - 0x89, 0x69, 0xf0, 0x9d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xcb, 0xad, 0x9a, 0xe6, 0x6d, 0x45, 0xcd, 0x7e, 0x91, 0x61, - 0x91, 0x90, 0xd5, 0xd6, 0x6d, 0x10, 0x43, 0x92, 0x20, 0x20, 0x06, 0x7b, - 0x26, 0x43, 0xd3, 0xd9, 0xd4, 0x25, 0x50, 0x79, 0xb5, 0x06, 0xa5, 0xc7, - 0xa4, 0xb6, 0xc7, 0x03, 0xfa, 0x3b, 0xb6, 0xee, 0xe3, 0xfa, 0x6c, 0x6b, - 0x27, 0xd3, 0xa3, 0xf9, 0x7c, 0x39, 0xb6, 0x7a, 0x32, 0x36, 0x2a, 0xca, - 0x98, 0xa5, 0xd1, 0xe9, 0x7e, 0x43, 0x04, 0xf4, 0xe4, 0x1c, 0x65, 0x54, - 0x17, 0xc3, 0xfd, 0xca, 0x65, 0xa6, 0x9d, 0x70, 0x72, 0x76, 0x73, 0x0b, - 0x68, 0xf1, 0xc2, 0x6a, 0xc3, 0x77, 0x1a, 0x80, 0xe0, 0x01, 0x4f, 0x31, - 0x69, 0xc1, 0x67, 0xd0, 0x0a, 0x80, 0xf9, 0x01, 0xb5, 0x69, 0xb6, 0x8e, - 0x63, 0xa6, 0x88, 0xa1, 0xe7, 0x00, 0x83, 0x1d, 0x20, 0xb5, 0x46, 0x7f, - 0xfc, 0x03, 0xc5, 0xf0, 0xba, 0x0c, 0x77, 0xa1, 0x80, 0xf2, 0x90, 0xcf, - 0x0a, 0x57, 0x14, 0xa0, 0xc7, 0x30, 0x5b, 0x10, 0x2c, 0x78, 0x85, 0xa2, - 0x52, 0x7e, 0xf1, 0xa8, 0xd0, 0xbc, 0x78, 0x3e, 0x7e, 0xf6, 0xc5, 0xc5, - 0xac, 0xf3, 0x02, 0xd4, 0xdc, 0x02, 0x20, 0xb8, 0xcc, 0x37, 0xe1, 0xaa, - 0x2d, 0x24, 0xed, 0x44, 0xfb, 0x77, 0x20, 0xe5, 0xc4, 0x38, 0x63, 0x08, - 0xe2, 0x92, 0xd2, 0x6a, 0xdf, 0x0a, 0xcb, 0x54, 0x97, 0x91, 0xc7, 0x55, - 0x9c, 0x31, 0x00, 0xe2, 0xf2, 0x25, 0xda, 0xd8, 0x6c, 0xea, 0x6d, 0xf2, - 0xff, 0x98, 0x16, 0x17, 0xf5, 0xfa, 0x5c, 0xd8, 0xfd, 0x8a, 0xf7, 0xea, - 0x35, 0xa0, 0x96, 0xbd, 0xed, 0xd3, 0x35, 0x1c, 0xee, 0x78, 0xa3, 0x1f, - 0xfd, 0x0c, 0x24, 0x4b, 0xad, 0x4f, 0xa5, 0x08, 0xb3, 0xd7, 0x90, 0xe7, - 0x08, 0x60, 0x52, 0x26, 0xee, 0x93, 0x40, 0x80, 0xd1, 0xaf, 0xaf, 0x74, - 0x4d, 0x3b, 0x6f, 0x4e, 0x42, 0x91, 0x02, 0x81, 0x81, 0x00, 0xfe, 0x26, - 0x9d, 0x81, 0xa1, 0xf3, 0xe2, 0x48, 0xad, 0x22, 0x4d, 0xf4, 0x1c, 0x68, - 0x4d, 0xe1, 0xe2, 0xff, 0x09, 0xbf, 0xa6, 0x12, 0x0a, 0x16, 0xce, 0xd6, - 0x34, 0x73, 0x7d, 0x55, 0xd3, 0x35, 0x6f, 0xb2, 0x4d, 0x64, 0xcb, 0x5e, - 0x5e, 0x1a, 0xc8, 0xcf, 0x29, 0x58, 0x28, 0x30, 0xec, 0x29, 0x95, 0x09, - 0x1b, 0x11, 0x80, 0xba, 0xe0, 0x16, 0x99, 0x49, 0x76, 0xb3, 0x42, 0x72, - 0x05, 0x10, 0xf2, 0xf5, 0xa8, 0x36, 0x84, 0xf1, 0x83, 0x57, 0x5d, 0x27, - 0xae, 0xe9, 0xae, 0x13, 0x47, 0xf3, 0xda, 0xb1, 0x42, 0xde, 0xa1, 0x25, - 0xc7, 0x72, 0xee, 0x2e, 0x34, 0x78, 0x64, 0x6a, 0xed, 0x91, 0x81, 0xaf, - 0x1e, 0xd3, 0xed, 0x68, 0x91, 0x37, 0x2f, 0xdd, 0x57, 0x5d, 0x2a, 0x3a, - 0x21, 0x86, 0x74, 0x6d, 0xff, 0x0b, 0x56, 0xac, 0xc2, 0x65, 0x3a, 0x88, - 0x91, 0x5e, 0x3c, 0x10, 0x7e, 0x53, 0x02, 0x81, 0x81, 0x00, 0xee, 0x58, - 0x94, 0xcc, 0x96, 0x1b, 0x9a, 0x63, 0x84, 0x45, 0x7c, 0x92, 0x78, 0x35, - 0x17, 0x7e, 0x7f, 0x7d, 0x6f, 0x06, 0x77, 0x69, 0x5c, 0xc4, 0xe8, 0xc7, - 0x19, 0xd2, 0x5e, 0x58, 0xd2, 0x1d, 0xee, 0x4c, 0xf2, 0xd9, 0xcb, 0xca, - 0x2a, 0x27, 0xec, 0x5b, 0x55, 0x37, 0x66, 0x0d, 0x2c, 0xe6, 0xfd, 0x48, - 0x35, 0x51, 0x66, 0x13, 0x1e, 0xab, 0x70, 0xda, 0xe6, 0x45, 0xac, 0x25, - 0x8b, 0x2b, 0x89, 0x4b, 0x19, 0x99, 0x6a, 0x06, 0x81, 0x24, 0xd5, 0xa9, - 0x3c, 0xf6, 0xc4, 0x28, 0x39, 0x70, 0x24, 0x0d, 0x8d, 0xcd, 0x69, 0xb4, - 0x65, 0x78, 0x0d, 0xaf, 0x4f, 0x68, 0xe3, 0xac, 0x9d, 0xaf, 0x07, 0x93, - 0x10, 0xeb, 0xc9, 0x40, 0x8c, 0x82, 0x85, 0x85, 0x16, 0xc0, 0xfc, 0x49, - 0x76, 0x03, 0x63, 0x7a, 0x2c, 0x95, 0x61, 0xc8, 0x3b, 0x07, 0x79, 0x68, - 0x60, 0xb1, 0xc8, 0xf0, 0x97, 0x4f, 0x02, 0x81, 0x81, 0x00, 0xe4, 0xa3, - 0x3c, 0xa3, 0x38, 0x5d, 0x3d, 0x3f, 0x00, 0x72, 0x92, 0x0a, 0x7f, 0xdb, - 0xdd, 0xe4, 0xce, 0xdf, 0x7d, 0x97, 0xaa, 0x01, 0x24, 0x8e, 0x6c, 0x39, - 0x0c, 0x2a, 0xb1, 0xa0, 0x9a, 0x47, 0xc2, 0x5a, 0x77, 0x81, 0xab, 0xeb, - 0x13, 0x61, 0xa9, 0x31, 0xa5, 0x12, 0x27, 0xe6, 0x0b, 0x2f, 0x45, 0x62, - 0x51, 0xb5, 0xa7, 0x47, 0x76, 0xfd, 0x1d, 0x9d, 0x97, 0x69, 0xa0, 0xe7, - 0x0e, 0x63, 0xb7, 0x0f, 0x04, 0xeb, 0x37, 0x22, 0x46, 0x74, 0x3b, 0xdb, - 0xcd, 0x61, 0x70, 0x36, 0xec, 0x4e, 0x16, 0x79, 0xcd, 0x9c, 0x97, 0x00, - 0x73, 0xb3, 0x93, 0x4e, 0x81, 0xe9, 0xa4, 0xfd, 0x05, 0x08, 0x17, 0xd0, - 0xc1, 0x3d, 0x0a, 0xa1, 0x3d, 0xb2, 0x96, 0x1e, 0xdb, 0xcf, 0x76, 0x83, - 0xa1, 0x51, 0x62, 0x40, 0xea, 0x66, 0xfa, 0xec, 0xa4, 0x5d, 0x89, 0x10, - 0xff, 0x25, 0xf5, 0x87, 0x28, 0xfd, 0x02, 0x81, 0x80, 0x0e, 0xb4, 0x22, - 0x41, 0xd8, 0xc4, 0xcd, 0x2a, 0x74, 0x7f, 0x80, 0xe6, 0xdc, 0x49, 0x92, - 0x30, 0x78, 0x96, 0xf9, 0x61, 0x71, 0xbe, 0x6b, 0x3d, 0xae, 0x8a, 0x91, - 0xda, 0x3b, 0x7d, 0xc9, 0x40, 0x95, 0x71, 0xe3, 0xcd, 0x71, 0xd7, 0xff, - 0xef, 0xc4, 0x92, 0x01, 0xd8, 0xd0, 0x0f, 0xe2, 0x04, 0x41, 0xfd, 0xd1, - 0x64, 0x3b, 0x22, 0xd4, 0xd2, 0x88, 0xbc, 0xc8, 0x55, 0xe5, 0xff, 0xce, - 0xed, 0x19, 0xa4, 0x2b, 0x69, 0x1e, 0x74, 0x56, 0x45, 0x3a, 0x75, 0x1d, - 0x50, 0xaf, 0xdb, 0x37, 0x67, 0xe6, 0xa1, 0x7b, 0x6c, 0xff, 0xa7, 0x64, - 0x57, 0x1a, 0xa9, 0x05, 0x02, 0x18, 0x81, 0x8e, 0x9c, 0xbc, 0x9f, 0xe2, - 0xfc, 0x58, 0xc7, 0x05, 0xa4, 0x0b, 0xae, 0xa1, 0x2f, 0xb8, 0xa0, 0xa3, - 0x8a, 0x23, 0xf9, 0xe6, 0x84, 0x34, 0xab, 0x10, 0x91, 0x2e, 0x79, 0x34, - 0xf5, 0xe2, 0xca, 0x8c, 0xdb, 0x02, 0x81, 0x81, 0x00, 0x8e, 0x9e, 0xc9, - 0xc2, 0xdf, 0xf7, 0x36, 0xef, 0x6e, 0x2a, 0x36, 0xeb, 0xd7, 0xa4, 0x52, - 0x43, 0x27, 0x8d, 0xaa, 0x52, 0x2d, 0xa8, 0xc1, 0x66, 0xf4, 0x9f, 0xc6, - 0x78, 0x9e, 0x31, 0x64, 0xe6, 0x56, 0xc9, 0x6d, 0x85, 0x79, 0x2a, 0x5c, - 0xca, 0x53, 0x2b, 0x1a, 0x46, 0xf4, 0x16, 0x60, 0xfe, 0x41, 0xcf, 0xc7, - 0x74, 0x57, 0xd0, 0x06, 0xf4, 0xc9, 0xfa, 0x47, 0x9c, 0xa2, 0xcb, 0xe0, - 0x85, 0xc5, 0x95, 0x9f, 0x35, 0xdd, 0x4c, 0x15, 0x7a, 0xda, 0x34, 0xc4, - 0x81, 0x20, 0x7d, 0x55, 0x85, 0xee, 0x24, 0xa7, 0xa6, 0xcb, 0x0a, 0xec, - 0xa8, 0x13, 0x4a, 0xc4, 0xaa, 0x5a, 0x4c, 0xf9, 0x32, 0xc0, 0x4b, 0x65, - 0x47, 0x65, 0xba, 0x38, 0x57, 0x17, 0x0c, 0xdd, 0xe1, 0x68, 0xd1, 0x4f, - 0x3d, 0xb9, 0x0e, 0xdd, 0x3f, 0x53, 0xe6, 0x91, 0x0e, 0x33, 0xba, 0x77, - 0xc2, 0x03, 0xf5, 0x90, 0x60, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - ]); - var expPrivOrig = [ - '-----BEGIN RSA PRIVATE KEY-----', - 'MIIEpQIBAAKCAQEA7J/Xbhf65MX/rINuvmBmsvJqNPpP4knNVCk0lTtVwfUfFj9qn+WTfC', - 'Xgkttjjbu0wiR8nGlM4KchrPzTRDsar55gkwnTrLRliDmFjNIELK+FJ5JZGyhzmfnBbDcI', - 'ondYWoywlsBjihAQhNj6HrcnWMFrNLTmoQVogsnjam8LtfcTqIsUSm4KcjmmH6BPy3LZ5W', - 'Fhp2NTrmbWurTamJK0UJM235r+WDZtMdf/AYjkSTtxjwnmb8nhmFGMxPoWuUUUe54OCW0H', - 'HnlOobbw3Qo9o5z061+qKTeMtAMlrOhk9ge+yshIOVGvNkLdMn03et3Wv1f5ENef5LjIpx', - 'sMiWnwnQIDAQABAoIBAQDLrZrmbUXNfpFhkZDV1m0QQ5IgIAZ7JkPT2dQlUHm1BqXHpLbH', - 'A/o7tu7j+mxrJ9Oj+Xw5tnoyNirKmKXR6X5DBPTkHGVUF8P9ymWmnXBydnMLaPHCasN3Go', - 'DgAU8xacFn0AqA+QG1abaOY6aIoecAgx0gtUZ//APF8LoMd6GA8pDPClcUoMcwWxAseIWi', - 'Un7xqNC8eD5+9sXFrPMC1NwCILjMN+GqLSTtRPt3IOXEOGMI4pLSat8Ky1SXkcdVnDEA4v', - 'Il2ths6m3y/5gWF/X6XNj9ivfqNaCWve3TNRzueKMf/QwkS61PpQiz15DnCGBSJu6TQIDR', - 'r690TTtvTkKRAoGBAP4mnYGh8+JIrSJN9BxoTeHi/wm/phIKFs7WNHN9VdM1b7JNZMteXh', - 'rIzylYKDDsKZUJGxGAuuAWmUl2s0JyBRDy9ag2hPGDV10nrumuE0fz2rFC3qElx3LuLjR4', - 'ZGrtkYGvHtPtaJE3L91XXSo6IYZ0bf8LVqzCZTqIkV48EH5TAoGBAO5YlMyWG5pjhEV8kn', - 'g1F35/fW8Gd2lcxOjHGdJeWNId7kzy2cvKKifsW1U3Zg0s5v1INVFmEx6rcNrmRawliyuJ', - 'SxmZagaBJNWpPPbEKDlwJA2NzWm0ZXgNr09o46ydrweTEOvJQIyChYUWwPxJdgNjeiyVYc', - 'g7B3loYLHI8JdPAoGBAOSjPKM4XT0/AHKSCn/b3eTO332XqgEkjmw5DCqxoJpHwlp3gavr', - 'E2GpMaUSJ+YLL0ViUbWnR3b9HZ2XaaDnDmO3DwTrNyJGdDvbzWFwNuxOFnnNnJcAc7OTTo', - 'HppP0FCBfQwT0KoT2ylh7bz3aDoVFiQOpm+uykXYkQ/yX1hyj9AoGADrQiQdjEzSp0f4Dm', - '3EmSMHiW+WFxvms9roqR2jt9yUCVcePNcdf/78SSAdjQD+IEQf3RZDsi1NKIvMhV5f/O7R', - 'mkK2kedFZFOnUdUK/bN2fmoXts/6dkVxqpBQIYgY6cvJ/i/FjHBaQLrqEvuKCjiiP55oQ0', - 'qxCRLnk09eLKjNsCgYEAjp7Jwt/3Nu9uKjbr16RSQyeNqlItqMFm9J/GeJ4xZOZWyW2FeS', - 'pcylMrGkb0FmD+Qc/HdFfQBvTJ+kecosvghcWVnzXdTBV62jTEgSB9VYXuJKemywrsqBNK', - 'xKpaTPkywEtlR2W6OFcXDN3haNFPPbkO3T9T5pEOM7p3wgP1kGAHBwcHBwcH', - '-----END RSA PRIVATE KEY-----' - ].join('\n'); - assert(keyInfo.ppk === undefined, makeMsg(what, 'Unexpected PPK flag')); - assert(keyInfo._converted === undefined, - makeMsg(what, 'Unexpected automatic private PEM generation')); - assert(keyInfo._macresult === undefined, - makeMsg(what, 'Unexpected MAC verification')); - assert(keyInfo._decrypted === true, - makeMsg(what, 'Expected decrypted flag')); - assert.deepEqual(keyInfo.private, - expPriv, - makeMsg(what, 'Decrypted private data mismatch')); - assert.deepEqual(keyInfo.privateOrig, - expPrivOrig, - makeMsg(what, 'Decrypted private PEM data mismatch')); - next(); - }, - what: 'decryptKey - with encrypted RSA' - }, - { run: function() { - var pubkey = [ - '---- BEGIN SSH2 PUBLIC KEY ----', - 'Comment: "dsa-key-20151028"', - 'AAAAB3NzaC1kc3MAAAEBAJ0Gth9JHw/a8RmY3Y0UFqBWVWkzWxkzG+DR2oqHwTIq', - 'jAi9Xr06oSbdmXd3Jl3bHsbd2gVq4+/j32s0uIf6FEW7mFooSiDOcRWARJSAAmkI', - 'T9ep//ag+gNUmwhtPebliCqcAn9VWE7wq2v0FJsG3trFW/pvi/hVsBOrkz4Qieqb', - 'KbwNwZc/MI+h9KAQPV7tWN2y5aG3jlVD9PERyeFPlmYkD1P+IqytxvL3thUFKeru', - 'N8w+hjKIGGonEcVzWRJ9UUBQqAaNNH4/9mzedpS8CivfnUvsIw9rSTB4N+Wf70jb', - '6a2qD1mHs1DqOkX136UOn5HkFldBnny0NSmlR/LewQkAAAAVAMu94kPPMR0Ew6Zh', - 'mAoJJc0RjisBAAABAGkOU/b/I0opGITGCx9qFEcqiJ/VJHVsYhQgM/jCkydEc9kW', - 'yjY+wKulGWpmA8wGmYm9j4IAgMGEXjBR8dyYJNZVXK0JOJmWrqUj5Q1GCUS5hCyU', - 'iA7nmVQ4syhGE49aFBLFdyKS6t7//swEEEV+6Hw9qcQWB98zoD8qdPGz3W/9kNXB', - 'OgVHWyqfWsbA/7MW2vjjF/u2EJe8YRKIJnodLOSNwPf0iCmj1HdaIm5N2Nl1k/6/', - '9MwlY6tjn4hinrEN/pOiC1ci/1ADmTq4L9upi1Paix51zD8Yp7q3SxOgZqFU0ELF', - 'VP/XHokm278t1mE9hxDwkepv7XgBda8uamWzwSoAAAEAYl2bjiCjIB68+DNuRgtf', - 'lvVk00nOH3dYXSslwKIFTivYDczjz0splaLsEhrdTRiOXyVsCEDhYtlvWlTw34rg', - 's2QoutpqISOiq26XwPdOlejD7Hy7gtw3yRyrhbXHYHE0nOvx0/SP7il4ub//QRTd', - '7cUPao2f359cGpap84anqKJjF3m4oRGdZGhTAQPqtGMkchZvItKyZe6pJ9HhsE7h', - 'NMsxPHAUon8QwNL1v+JkHg7i+Oe8rEZx/51m/qGVtXLN+z885lsqzuwe9KhY5I8C', - 'C3f8nR+Mivfp1ce9pSMKCpdRASzOBuykZKYZmns6SA0UqAp7ZLDKubbhk9ZLVyAO', - 'dA==', - '---- END SSH2 PUBLIC KEY ----' - ].join('\n'); - assert.doesNotThrow(function() { - var res = utils.genPublicKey(utils.parseKey(pubkey)); - assert.deepEqual( - res, - { type: 'dss', - fulltype: 'ssh-dss', - curve: undefined, - public: new Buffer([ - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x9d, 0x06, 0xb6, 0x1f, 0x49, 0x1f, - 0x0f, 0xda, 0xf1, 0x19, 0x98, 0xdd, 0x8d, 0x14, 0x16, 0xa0, 0x56, - 0x55, 0x69, 0x33, 0x5b, 0x19, 0x33, 0x1b, 0xe0, 0xd1, 0xda, 0x8a, - 0x87, 0xc1, 0x32, 0x2a, 0x8c, 0x08, 0xbd, 0x5e, 0xbd, 0x3a, 0xa1, - 0x26, 0xdd, 0x99, 0x77, 0x77, 0x26, 0x5d, 0xdb, 0x1e, 0xc6, 0xdd, - 0xda, 0x05, 0x6a, 0xe3, 0xef, 0xe3, 0xdf, 0x6b, 0x34, 0xb8, 0x87, - 0xfa, 0x14, 0x45, 0xbb, 0x98, 0x5a, 0x28, 0x4a, 0x20, 0xce, 0x71, - 0x15, 0x80, 0x44, 0x94, 0x80, 0x02, 0x69, 0x08, 0x4f, 0xd7, 0xa9, - 0xff, 0xf6, 0xa0, 0xfa, 0x03, 0x54, 0x9b, 0x08, 0x6d, 0x3d, 0xe6, - 0xe5, 0x88, 0x2a, 0x9c, 0x02, 0x7f, 0x55, 0x58, 0x4e, 0xf0, 0xab, - 0x6b, 0xf4, 0x14, 0x9b, 0x06, 0xde, 0xda, 0xc5, 0x5b, 0xfa, 0x6f, - 0x8b, 0xf8, 0x55, 0xb0, 0x13, 0xab, 0x93, 0x3e, 0x10, 0x89, 0xea, - 0x9b, 0x29, 0xbc, 0x0d, 0xc1, 0x97, 0x3f, 0x30, 0x8f, 0xa1, 0xf4, - 0xa0, 0x10, 0x3d, 0x5e, 0xed, 0x58, 0xdd, 0xb2, 0xe5, 0xa1, 0xb7, - 0x8e, 0x55, 0x43, 0xf4, 0xf1, 0x11, 0xc9, 0xe1, 0x4f, 0x96, 0x66, - 0x24, 0x0f, 0x53, 0xfe, 0x22, 0xac, 0xad, 0xc6, 0xf2, 0xf7, 0xb6, - 0x15, 0x05, 0x29, 0xea, 0xee, 0x37, 0xcc, 0x3e, 0x86, 0x32, 0x88, - 0x18, 0x6a, 0x27, 0x11, 0xc5, 0x73, 0x59, 0x12, 0x7d, 0x51, 0x40, - 0x50, 0xa8, 0x06, 0x8d, 0x34, 0x7e, 0x3f, 0xf6, 0x6c, 0xde, 0x76, - 0x94, 0xbc, 0x0a, 0x2b, 0xdf, 0x9d, 0x4b, 0xec, 0x23, 0x0f, 0x6b, - 0x49, 0x30, 0x78, 0x37, 0xe5, 0x9f, 0xef, 0x48, 0xdb, 0xe9, 0xad, - 0xaa, 0x0f, 0x59, 0x87, 0xb3, 0x50, 0xea, 0x3a, 0x45, 0xf5, 0xdf, - 0xa5, 0x0e, 0x9f, 0x91, 0xe4, 0x16, 0x57, 0x41, 0x9e, 0x7c, 0xb4, - 0x35, 0x29, 0xa5, 0x47, 0xf2, 0xde, 0xc1, 0x09, 0x00, 0x00, 0x00, - 0x15, 0x00, 0xcb, 0xbd, 0xe2, 0x43, 0xcf, 0x31, 0x1d, 0x04, 0xc3, - 0xa6, 0x61, 0x98, 0x0a, 0x09, 0x25, 0xcd, 0x11, 0x8e, 0x2b, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x69, 0x0e, 0x53, 0xf6, 0xff, 0x23, 0x4a, - 0x29, 0x18, 0x84, 0xc6, 0x0b, 0x1f, 0x6a, 0x14, 0x47, 0x2a, 0x88, - 0x9f, 0xd5, 0x24, 0x75, 0x6c, 0x62, 0x14, 0x20, 0x33, 0xf8, 0xc2, - 0x93, 0x27, 0x44, 0x73, 0xd9, 0x16, 0xca, 0x36, 0x3e, 0xc0, 0xab, - 0xa5, 0x19, 0x6a, 0x66, 0x03, 0xcc, 0x06, 0x99, 0x89, 0xbd, 0x8f, - 0x82, 0x00, 0x80, 0xc1, 0x84, 0x5e, 0x30, 0x51, 0xf1, 0xdc, 0x98, - 0x24, 0xd6, 0x55, 0x5c, 0xad, 0x09, 0x38, 0x99, 0x96, 0xae, 0xa5, - 0x23, 0xe5, 0x0d, 0x46, 0x09, 0x44, 0xb9, 0x84, 0x2c, 0x94, 0x88, - 0x0e, 0xe7, 0x99, 0x54, 0x38, 0xb3, 0x28, 0x46, 0x13, 0x8f, 0x5a, - 0x14, 0x12, 0xc5, 0x77, 0x22, 0x92, 0xea, 0xde, 0xff, 0xfe, 0xcc, - 0x04, 0x10, 0x45, 0x7e, 0xe8, 0x7c, 0x3d, 0xa9, 0xc4, 0x16, 0x07, - 0xdf, 0x33, 0xa0, 0x3f, 0x2a, 0x74, 0xf1, 0xb3, 0xdd, 0x6f, 0xfd, - 0x90, 0xd5, 0xc1, 0x3a, 0x05, 0x47, 0x5b, 0x2a, 0x9f, 0x5a, 0xc6, - 0xc0, 0xff, 0xb3, 0x16, 0xda, 0xf8, 0xe3, 0x17, 0xfb, 0xb6, 0x10, - 0x97, 0xbc, 0x61, 0x12, 0x88, 0x26, 0x7a, 0x1d, 0x2c, 0xe4, 0x8d, - 0xc0, 0xf7, 0xf4, 0x88, 0x29, 0xa3, 0xd4, 0x77, 0x5a, 0x22, 0x6e, - 0x4d, 0xd8, 0xd9, 0x75, 0x93, 0xfe, 0xbf, 0xf4, 0xcc, 0x25, 0x63, - 0xab, 0x63, 0x9f, 0x88, 0x62, 0x9e, 0xb1, 0x0d, 0xfe, 0x93, 0xa2, - 0x0b, 0x57, 0x22, 0xff, 0x50, 0x03, 0x99, 0x3a, 0xb8, 0x2f, 0xdb, - 0xa9, 0x8b, 0x53, 0xda, 0x8b, 0x1e, 0x75, 0xcc, 0x3f, 0x18, 0xa7, - 0xba, 0xb7, 0x4b, 0x13, 0xa0, 0x66, 0xa1, 0x54, 0xd0, 0x42, 0xc5, - 0x54, 0xff, 0xd7, 0x1e, 0x89, 0x26, 0xdb, 0xbf, 0x2d, 0xd6, 0x61, - 0x3d, 0x87, 0x10, 0xf0, 0x91, 0xea, 0x6f, 0xed, 0x78, 0x01, 0x75, - 0xaf, 0x2e, 0x6a, 0x65, 0xb3, 0xc1, 0x2a, 0x00, 0x00, 0x01, 0x00, - 0x62, 0x5d, 0x9b, 0x8e, 0x20, 0xa3, 0x20, 0x1e, 0xbc, 0xf8, 0x33, - 0x6e, 0x46, 0x0b, 0x5f, 0x96, 0xf5, 0x64, 0xd3, 0x49, 0xce, 0x1f, - 0x77, 0x58, 0x5d, 0x2b, 0x25, 0xc0, 0xa2, 0x05, 0x4e, 0x2b, 0xd8, - 0x0d, 0xcc, 0xe3, 0xcf, 0x4b, 0x29, 0x95, 0xa2, 0xec, 0x12, 0x1a, - 0xdd, 0x4d, 0x18, 0x8e, 0x5f, 0x25, 0x6c, 0x08, 0x40, 0xe1, 0x62, - 0xd9, 0x6f, 0x5a, 0x54, 0xf0, 0xdf, 0x8a, 0xe0, 0xb3, 0x64, 0x28, - 0xba, 0xda, 0x6a, 0x21, 0x23, 0xa2, 0xab, 0x6e, 0x97, 0xc0, 0xf7, - 0x4e, 0x95, 0xe8, 0xc3, 0xec, 0x7c, 0xbb, 0x82, 0xdc, 0x37, 0xc9, - 0x1c, 0xab, 0x85, 0xb5, 0xc7, 0x60, 0x71, 0x34, 0x9c, 0xeb, 0xf1, - 0xd3, 0xf4, 0x8f, 0xee, 0x29, 0x78, 0xb9, 0xbf, 0xff, 0x41, 0x14, - 0xdd, 0xed, 0xc5, 0x0f, 0x6a, 0x8d, 0x9f, 0xdf, 0x9f, 0x5c, 0x1a, - 0x96, 0xa9, 0xf3, 0x86, 0xa7, 0xa8, 0xa2, 0x63, 0x17, 0x79, 0xb8, - 0xa1, 0x11, 0x9d, 0x64, 0x68, 0x53, 0x01, 0x03, 0xea, 0xb4, 0x63, - 0x24, 0x72, 0x16, 0x6f, 0x22, 0xd2, 0xb2, 0x65, 0xee, 0xa9, 0x27, - 0xd1, 0xe1, 0xb0, 0x4e, 0xe1, 0x34, 0xcb, 0x31, 0x3c, 0x70, 0x14, - 0xa2, 0x7f, 0x10, 0xc0, 0xd2, 0xf5, 0xbf, 0xe2, 0x64, 0x1e, 0x0e, - 0xe2, 0xf8, 0xe7, 0xbc, 0xac, 0x46, 0x71, 0xff, 0x9d, 0x66, 0xfe, - 0xa1, 0x95, 0xb5, 0x72, 0xcd, 0xfb, 0x3f, 0x3c, 0xe6, 0x5b, 0x2a, - 0xce, 0xec, 0x1e, 0xf4, 0xa8, 0x58, 0xe4, 0x8f, 0x02, 0x0b, 0x77, - 0xfc, 0x9d, 0x1f, 0x8c, 0x8a, 0xf7, 0xe9, 0xd5, 0xc7, 0xbd, 0xa5, - 0x23, 0x0a, 0x0a, 0x97, 0x51, 0x01, 0x2c, 0xce, 0x06, 0xec, 0xa4, - 0x64, 0xa6, 0x19, 0x9a, 0x7b, 0x3a, 0x48, 0x0d, 0x14, 0xa8, 0x0a, - 0x7b, 0x64, 0xb0, 0xca, 0xb9, 0xb6, 0xe1, 0x93, 0xd6, 0x4b, 0x57, - 0x20, 0x0e, 0x74, - ]), - publicOrig: new Buffer([ - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, - 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x4f, 0x6a, - 0x43, 0x43, 0x41, 0x69, 0x30, 0x47, 0x42, 0x79, 0x71, 0x47, 0x53, - 0x4d, 0x34, 0x34, 0x42, 0x41, 0x45, 0x77, 0x67, 0x67, 0x49, 0x67, - 0x41, 0x6f, 0x49, 0x42, 0x41, 0x51, 0x43, 0x64, 0x42, 0x72, 0x59, - 0x66, 0x53, 0x52, 0x38, 0x50, 0x32, 0x76, 0x45, 0x5a, 0x6d, 0x4e, - 0x32, 0x4e, 0x46, 0x42, 0x61, 0x67, 0x56, 0x6c, 0x56, 0x70, 0x4d, - 0x31, 0x73, 0x5a, 0x0a, 0x4d, 0x78, 0x76, 0x67, 0x30, 0x64, 0x71, - 0x4b, 0x68, 0x38, 0x45, 0x79, 0x4b, 0x6f, 0x77, 0x49, 0x76, 0x56, - 0x36, 0x39, 0x4f, 0x71, 0x45, 0x6d, 0x33, 0x5a, 0x6c, 0x33, 0x64, - 0x79, 0x5a, 0x64, 0x32, 0x78, 0x37, 0x47, 0x33, 0x64, 0x6f, 0x46, - 0x61, 0x75, 0x50, 0x76, 0x34, 0x39, 0x39, 0x72, 0x4e, 0x4c, 0x69, - 0x48, 0x2b, 0x68, 0x52, 0x46, 0x75, 0x35, 0x68, 0x61, 0x4b, 0x45, - 0x6f, 0x67, 0x0a, 0x7a, 0x6e, 0x45, 0x56, 0x67, 0x45, 0x53, 0x55, - 0x67, 0x41, 0x4a, 0x70, 0x43, 0x45, 0x2f, 0x58, 0x71, 0x66, 0x2f, - 0x32, 0x6f, 0x50, 0x6f, 0x44, 0x56, 0x4a, 0x73, 0x49, 0x62, 0x54, - 0x33, 0x6d, 0x35, 0x59, 0x67, 0x71, 0x6e, 0x41, 0x4a, 0x2f, 0x56, - 0x56, 0x68, 0x4f, 0x38, 0x4b, 0x74, 0x72, 0x39, 0x42, 0x53, 0x62, - 0x42, 0x74, 0x37, 0x61, 0x78, 0x56, 0x76, 0x36, 0x62, 0x34, 0x76, - 0x34, 0x0a, 0x56, 0x62, 0x41, 0x54, 0x71, 0x35, 0x4d, 0x2b, 0x45, - 0x49, 0x6e, 0x71, 0x6d, 0x79, 0x6d, 0x38, 0x44, 0x63, 0x47, 0x58, - 0x50, 0x7a, 0x43, 0x50, 0x6f, 0x66, 0x53, 0x67, 0x45, 0x44, 0x31, - 0x65, 0x37, 0x56, 0x6a, 0x64, 0x73, 0x75, 0x57, 0x68, 0x74, 0x34, - 0x35, 0x56, 0x51, 0x2f, 0x54, 0x78, 0x45, 0x63, 0x6e, 0x68, 0x54, - 0x35, 0x5a, 0x6d, 0x4a, 0x41, 0x39, 0x54, 0x2f, 0x69, 0x4b, 0x73, - 0x0a, 0x72, 0x63, 0x62, 0x79, 0x39, 0x37, 0x59, 0x56, 0x42, 0x53, - 0x6e, 0x71, 0x37, 0x6a, 0x66, 0x4d, 0x50, 0x6f, 0x59, 0x79, 0x69, - 0x42, 0x68, 0x71, 0x4a, 0x78, 0x48, 0x46, 0x63, 0x31, 0x6b, 0x53, - 0x66, 0x56, 0x46, 0x41, 0x55, 0x4b, 0x67, 0x47, 0x6a, 0x54, 0x52, - 0x2b, 0x50, 0x2f, 0x5a, 0x73, 0x33, 0x6e, 0x61, 0x55, 0x76, 0x41, - 0x6f, 0x72, 0x33, 0x35, 0x31, 0x4c, 0x37, 0x43, 0x4d, 0x50, 0x0a, - 0x61, 0x30, 0x6b, 0x77, 0x65, 0x44, 0x66, 0x6c, 0x6e, 0x2b, 0x39, - 0x49, 0x32, 0x2b, 0x6d, 0x74, 0x71, 0x67, 0x39, 0x5a, 0x68, 0x37, - 0x4e, 0x51, 0x36, 0x6a, 0x70, 0x46, 0x39, 0x64, 0x2b, 0x6c, 0x44, - 0x70, 0x2b, 0x52, 0x35, 0x42, 0x5a, 0x58, 0x51, 0x5a, 0x35, 0x38, - 0x74, 0x44, 0x55, 0x70, 0x70, 0x55, 0x66, 0x79, 0x33, 0x73, 0x45, - 0x4a, 0x41, 0x68, 0x55, 0x41, 0x79, 0x37, 0x33, 0x69, 0x0a, 0x51, - 0x38, 0x38, 0x78, 0x48, 0x51, 0x54, 0x44, 0x70, 0x6d, 0x47, 0x59, - 0x43, 0x67, 0x6b, 0x6c, 0x7a, 0x52, 0x47, 0x4f, 0x4b, 0x77, 0x45, - 0x43, 0x67, 0x67, 0x45, 0x41, 0x61, 0x51, 0x35, 0x54, 0x39, 0x76, - 0x38, 0x6a, 0x53, 0x69, 0x6b, 0x59, 0x68, 0x4d, 0x59, 0x4c, 0x48, - 0x32, 0x6f, 0x55, 0x52, 0x79, 0x71, 0x49, 0x6e, 0x39, 0x55, 0x6b, - 0x64, 0x57, 0x78, 0x69, 0x46, 0x43, 0x41, 0x7a, 0x0a, 0x2b, 0x4d, - 0x4b, 0x54, 0x4a, 0x30, 0x52, 0x7a, 0x32, 0x52, 0x62, 0x4b, 0x4e, - 0x6a, 0x37, 0x41, 0x71, 0x36, 0x55, 0x5a, 0x61, 0x6d, 0x59, 0x44, - 0x7a, 0x41, 0x61, 0x5a, 0x69, 0x62, 0x32, 0x50, 0x67, 0x67, 0x43, - 0x41, 0x77, 0x59, 0x52, 0x65, 0x4d, 0x46, 0x48, 0x78, 0x33, 0x4a, - 0x67, 0x6b, 0x31, 0x6c, 0x56, 0x63, 0x72, 0x51, 0x6b, 0x34, 0x6d, - 0x5a, 0x61, 0x75, 0x70, 0x53, 0x50, 0x6c, 0x0a, 0x44, 0x55, 0x59, - 0x4a, 0x52, 0x4c, 0x6d, 0x45, 0x4c, 0x4a, 0x53, 0x49, 0x44, 0x75, - 0x65, 0x5a, 0x56, 0x44, 0x69, 0x7a, 0x4b, 0x45, 0x59, 0x54, 0x6a, - 0x31, 0x6f, 0x55, 0x45, 0x73, 0x56, 0x33, 0x49, 0x70, 0x4c, 0x71, - 0x33, 0x76, 0x2f, 0x2b, 0x7a, 0x41, 0x51, 0x51, 0x52, 0x58, 0x37, - 0x6f, 0x66, 0x44, 0x32, 0x70, 0x78, 0x42, 0x59, 0x48, 0x33, 0x7a, - 0x4f, 0x67, 0x50, 0x79, 0x70, 0x30, 0x0a, 0x38, 0x62, 0x50, 0x64, - 0x62, 0x2f, 0x32, 0x51, 0x31, 0x63, 0x45, 0x36, 0x42, 0x55, 0x64, - 0x62, 0x4b, 0x70, 0x39, 0x61, 0x78, 0x73, 0x44, 0x2f, 0x73, 0x78, - 0x62, 0x61, 0x2b, 0x4f, 0x4d, 0x58, 0x2b, 0x37, 0x59, 0x51, 0x6c, - 0x37, 0x78, 0x68, 0x45, 0x6f, 0x67, 0x6d, 0x65, 0x68, 0x30, 0x73, - 0x35, 0x49, 0x33, 0x41, 0x39, 0x2f, 0x53, 0x49, 0x4b, 0x61, 0x50, - 0x55, 0x64, 0x31, 0x6f, 0x69, 0x0a, 0x62, 0x6b, 0x33, 0x59, 0x32, - 0x58, 0x57, 0x54, 0x2f, 0x72, 0x2f, 0x30, 0x7a, 0x43, 0x56, 0x6a, - 0x71, 0x32, 0x4f, 0x66, 0x69, 0x47, 0x4b, 0x65, 0x73, 0x51, 0x33, - 0x2b, 0x6b, 0x36, 0x49, 0x4c, 0x56, 0x79, 0x4c, 0x2f, 0x55, 0x41, - 0x4f, 0x5a, 0x4f, 0x72, 0x67, 0x76, 0x32, 0x36, 0x6d, 0x4c, 0x55, - 0x39, 0x71, 0x4c, 0x48, 0x6e, 0x58, 0x4d, 0x50, 0x78, 0x69, 0x6e, - 0x75, 0x72, 0x64, 0x4c, 0x0a, 0x45, 0x36, 0x42, 0x6d, 0x6f, 0x56, - 0x54, 0x51, 0x51, 0x73, 0x56, 0x55, 0x2f, 0x39, 0x63, 0x65, 0x69, - 0x53, 0x62, 0x62, 0x76, 0x79, 0x33, 0x57, 0x59, 0x54, 0x32, 0x48, - 0x45, 0x50, 0x43, 0x52, 0x36, 0x6d, 0x2f, 0x74, 0x65, 0x41, 0x46, - 0x31, 0x72, 0x79, 0x35, 0x71, 0x5a, 0x62, 0x50, 0x42, 0x4b, 0x67, - 0x4f, 0x43, 0x41, 0x51, 0x55, 0x41, 0x41, 0x6f, 0x49, 0x42, 0x41, - 0x47, 0x4a, 0x64, 0x0a, 0x6d, 0x34, 0x34, 0x67, 0x6f, 0x79, 0x41, - 0x65, 0x76, 0x50, 0x67, 0x7a, 0x62, 0x6b, 0x59, 0x4c, 0x58, 0x35, - 0x62, 0x31, 0x5a, 0x4e, 0x4e, 0x4a, 0x7a, 0x68, 0x39, 0x33, 0x57, - 0x46, 0x30, 0x72, 0x4a, 0x63, 0x43, 0x69, 0x42, 0x55, 0x34, 0x72, - 0x32, 0x41, 0x33, 0x4d, 0x34, 0x38, 0x39, 0x4c, 0x4b, 0x5a, 0x57, - 0x69, 0x37, 0x42, 0x49, 0x61, 0x33, 0x55, 0x30, 0x59, 0x6a, 0x6c, - 0x38, 0x6c, 0x0a, 0x62, 0x41, 0x68, 0x41, 0x34, 0x57, 0x4c, 0x5a, - 0x62, 0x31, 0x70, 0x55, 0x38, 0x4e, 0x2b, 0x4b, 0x34, 0x4c, 0x4e, - 0x6b, 0x4b, 0x4c, 0x72, 0x61, 0x61, 0x69, 0x45, 0x6a, 0x6f, 0x71, - 0x74, 0x75, 0x6c, 0x38, 0x44, 0x33, 0x54, 0x70, 0x58, 0x6f, 0x77, - 0x2b, 0x78, 0x38, 0x75, 0x34, 0x4c, 0x63, 0x4e, 0x38, 0x6b, 0x63, - 0x71, 0x34, 0x57, 0x31, 0x78, 0x32, 0x42, 0x78, 0x4e, 0x4a, 0x7a, - 0x72, 0x0a, 0x38, 0x64, 0x50, 0x30, 0x6a, 0x2b, 0x34, 0x70, 0x65, - 0x4c, 0x6d, 0x2f, 0x2f, 0x30, 0x45, 0x55, 0x33, 0x65, 0x33, 0x46, - 0x44, 0x32, 0x71, 0x4e, 0x6e, 0x39, 0x2b, 0x66, 0x58, 0x42, 0x71, - 0x57, 0x71, 0x66, 0x4f, 0x47, 0x70, 0x36, 0x69, 0x69, 0x59, 0x78, - 0x64, 0x35, 0x75, 0x4b, 0x45, 0x52, 0x6e, 0x57, 0x52, 0x6f, 0x55, - 0x77, 0x45, 0x44, 0x36, 0x72, 0x52, 0x6a, 0x4a, 0x48, 0x49, 0x57, - 0x0a, 0x62, 0x79, 0x4c, 0x53, 0x73, 0x6d, 0x58, 0x75, 0x71, 0x53, - 0x66, 0x52, 0x34, 0x62, 0x42, 0x4f, 0x34, 0x54, 0x54, 0x4c, 0x4d, - 0x54, 0x78, 0x77, 0x46, 0x4b, 0x4a, 0x2f, 0x45, 0x4d, 0x44, 0x53, - 0x39, 0x62, 0x2f, 0x69, 0x5a, 0x42, 0x34, 0x4f, 0x34, 0x76, 0x6a, - 0x6e, 0x76, 0x4b, 0x78, 0x47, 0x63, 0x66, 0x2b, 0x64, 0x5a, 0x76, - 0x36, 0x68, 0x6c, 0x62, 0x56, 0x79, 0x7a, 0x66, 0x73, 0x2f, 0x0a, - 0x50, 0x4f, 0x5a, 0x62, 0x4b, 0x73, 0x37, 0x73, 0x48, 0x76, 0x53, - 0x6f, 0x57, 0x4f, 0x53, 0x50, 0x41, 0x67, 0x74, 0x33, 0x2f, 0x4a, - 0x30, 0x66, 0x6a, 0x49, 0x72, 0x33, 0x36, 0x64, 0x58, 0x48, 0x76, - 0x61, 0x55, 0x6a, 0x43, 0x67, 0x71, 0x58, 0x55, 0x51, 0x45, 0x73, - 0x7a, 0x67, 0x62, 0x73, 0x70, 0x47, 0x53, 0x6d, 0x47, 0x5a, 0x70, - 0x37, 0x4f, 0x6b, 0x67, 0x4e, 0x46, 0x4b, 0x67, 0x4b, 0x0a, 0x65, - 0x32, 0x53, 0x77, 0x79, 0x72, 0x6d, 0x32, 0x34, 0x5a, 0x50, 0x57, - 0x53, 0x31, 0x63, 0x67, 0x44, 0x6e, 0x51, 0x3d, 0x0a, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4c, - 0x49, 0x43, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d - ]) - } - ); - next(); - }); - }, - what: 'Generate public key from parsed public key' - }, -]; - -function next() { - if (Array.isArray(process._events.exit)) - process._events.exit = process._events.exit[1]; - if (++t === tests.length) - return; - - var v = tests[t]; - process.nextTick(function() { - v.run.call(v); - }); -} - -function makeMsg(what, msg) { - return '[' + group + what + ']: ' + msg; -} - -process.once('exit', function() { - assert(t === tests.length, - makeMsg('_exit', - 'Only finished ' + t + '/' + tests.length + ' tests')); -}); - -next(); diff --git a/reverse_engineering/node_modules/ssh2-streams/test/test.js b/reverse_engineering/node_modules/ssh2-streams/test/test.js deleted file mode 100644 index 4a91765..0000000 --- a/reverse_engineering/node_modules/ssh2-streams/test/test.js +++ /dev/null @@ -1,22 +0,0 @@ -var spawn = require('child_process').spawn, - join = require('path').join; - -var files = require('fs').readdirSync(__dirname).filter(function(f) { - return (f.substr(0, 5) === 'test-'); - }).map(function(f) { - return join(__dirname, f); - }), - f = -1; - -function next() { - if (++f < files.length) { - spawn(process.argv[0], [ files[f] ], { stdio: 'inherit' }) - .on('exit', function(code) { - if (code === 0) - process.nextTick(next); - else - process.exit(code); - }); - } -} -next(); diff --git a/reverse_engineering/node_modules/ssh2/.eslintignore b/reverse_engineering/node_modules/ssh2/.eslintignore new file mode 100644 index 0000000..73ed104 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/.eslintignore @@ -0,0 +1,4 @@ +node_modules +lib/protocol/crypto/poly1305.js +.eslint-plugins +!.eslintrc.js diff --git a/reverse_engineering/node_modules/ssh2/.eslintrc.js b/reverse_engineering/node_modules/ssh2/.eslintrc.js new file mode 100644 index 0000000..be9311d --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/.eslintrc.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + extends: '@mscdex/eslint-config', +}; diff --git a/reverse_engineering/node_modules/ssh2/.github/workflows/ci.yml b/reverse_engineering/node_modules/ssh2/.github/workflows/ci.yml new file mode 100644 index 0000000..c6f610a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + pull_request: + push: + branches: [ master ] + +jobs: + tests-linux: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: [10.16.0, 10.x, 12.x, 14.x, 16.x] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Install module + run: npm install + - name: Run tests + run: npm test + tests-windows: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + node-version: [16.x] + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Install module + run: npm install + - name: Run tests + run: npm test diff --git a/reverse_engineering/node_modules/ssh2/.github/workflows/lint.yml b/reverse_engineering/node_modules/ssh2/.github/workflows/lint.yml new file mode 100644 index 0000000..ec109fd --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/.github/workflows/lint.yml @@ -0,0 +1,23 @@ +name: lint + +on: + pull_request: + push: + branches: [ master ] + +env: + NODE_VERSION: 14.x + +jobs: + lint-js: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v1 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Install ESLint + ESLint configs/plugins + run: npm install --only=dev + - name: Lint files + run: npm run lint diff --git a/reverse_engineering/node_modules/ssh2/.travis.yml b/reverse_engineering/node_modules/ssh2/.travis.yml deleted file mode 100644 index 3511e64..0000000 --- a/reverse_engineering/node_modules/ssh2/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -sudo: false -language: cpp -notifications: - email: false -env: - matrix: - - TRAVIS_NODE_VERSION="0.10" - - TRAVIS_NODE_VERSION="0.12" - - TRAVIS_NODE_VERSION="4" - - TRAVIS_NODE_VERSION="6" - - TRAVIS_NODE_VERSION="7" -install: - - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - - node --version - - npm --version - - npm install - - ssh -V -script: npm test diff --git a/reverse_engineering/node_modules/ssh2/README.md b/reverse_engineering/node_modules/ssh2/README.md index 39e5b6c..e39ec73 100644 --- a/reverse_engineering/node_modules/ssh2/README.md +++ b/reverse_engineering/node_modules/ssh2/README.md @@ -1,46 +1,79 @@ -Description -=========== +# Description SSH2 client and server modules written in pure JavaScript for [node.js](http://nodejs.org/). -Development/testing is done against OpenSSH (7.1 currently). - -[Changes from v0.4.x-v0.5.x](https://github.com/mscdex/ssh2/wiki/Changes-from-0.4.x-to-0.5.x) - -[![Build Status](https://travis-ci.org/mscdex/ssh2.svg?branch=master)](https://travis-ci.org/mscdex/ssh2) - - -Requirements -============ - -* [node.js](http://nodejs.org/) -- v0.10 or newer - - -Install -======= +Development/testing is done against OpenSSH (8.7 currently). + +Changes (breaking or otherwise) in v1.0.0 can be found [here](https://github.com/mscdex/ssh2/issues/935). + +# Table of Contents + +* [Requirements](#requirements) +* [Installation](#installation) +* [Client Examples](#client-examples) + * [Execute 'uptime' on a server](#execute-uptime-on-a-server) + * [Start an interactive shell session](#start-an-interactive-shell-session) + * [Send a raw HTTP request to port 80 on the server](#send-a-raw-http-request-to-port-80-on-the-server) + * [Forward local connections to port 8000 on the server to us](#forward-local-connections-to-port-8000-on-the-server-to-us) + * [Get a directory listing via SFTP](#get-a-directory-listing-via-sftp) + * [Connection hopping](#connection-hopping) + * [Forward remote X11 connections](#forward-remote-x11-connections) + * [Dynamic (1:1) port forwarding using a SOCKSv5 proxy (using `socksv5`)](#dynamic-11-port-forwarding-using-a-socksv5-proxy-using-socksv5) + * [Make HTTP(S) connections easily using a custom http(s).Agent](#make-https-connections-easily-using-a-custom-httpsagent) + * [Invoke an arbitrary subsystem (e.g. netconf)](#invoke-an-arbitrary-subsystem) +* [Server Examples](#server-examples) + * [Password and public key authentication and non-interactive (exec) command execution](#password-and-public-key-authentication-and-non-interactive-exec-command-execution) + * [SFTP-only server](#sftp-only-server) +* [API](#api) + * [Client](#client) + * [Client events](#client-events) + * [Client methods](#client-methods) + * [Server](#server) + * [Server events](#server-events) + * [Server methods](#server-methods) + * [Connection events](#connection-events) + * [Connection methods](#connection-methods) + * [Session events](#session-events) + * [Channel](#channel) + * [Pseudo-TTY settings](#pseudo-tty-settings) + * [Terminal modes](#terminal-modes) + * [HTTPAgent](#httpagent) + * [HTTPAgent methods](#httpagent-methods) + * [HTTPSAgent](#httpsagent) + * [HTTPSAgent methods](#httpsagent-methods) + * [Utilities](#utilities) + +## Requirements + +* [node.js](http://nodejs.org/) -- v10.16.0 or newer + * node v12.0.0 or newer for Ed25519 key support +* (Optional) [`cpu-features`](https://github.com/mscdex/cpu-features) is set as an optional package dependency (you do not need to install it explicitly/separately from `ssh2`) that will be automatically built and used if possible. See the project's documentation for its own requirements. + * This addon is currently used to help generate an optimal default cipher list + +## Installation npm install ssh2 +## Client Examples -Client Examples -=============== +### Execute 'uptime' on a server -* Execute `uptime` on a server: +```js +const { readFileSync } = require('fs'); -```javascript -var Client = require('ssh2').Client; +const { Client } = require('ssh2'); -var conn = new Client(); -conn.on('ready', function() { +const conn = new Client(); +conn.on('ready', () => { console.log('Client :: ready'); - conn.exec('uptime', function(err, stream) { + conn.exec('uptime', (err, stream) => { if (err) throw err; - stream.on('close', function(code, signal) { + stream.on('close', (code, signal) => { console.log('Stream :: close :: code: ' + code + ', signal: ' + signal); conn.end(); - }).on('data', function(data) { + }).on('data', (data) => { console.log('STDOUT: ' + data); - }).stderr.on('data', function(data) { + }).stderr.on('data', (data) => { console.log('STDERR: ' + data); }); }); @@ -48,7 +81,7 @@ conn.on('ready', function() { host: '192.168.100.100', port: 22, username: 'frylock', - privateKey: require('fs').readFileSync('/here/is/my/key') + privateKey: readFileSync('/path/to/my/key') }); // example output: @@ -59,23 +92,23 @@ conn.on('ready', function() { // Stream :: close ``` -* Start an interactive shell session: +### Start an interactive shell session -```javascript -var Client = require('ssh2').Client; +```js +const { readFileSync } = require('fs'); -var conn = new Client(); -conn.on('ready', function() { +const { Client } = require('ssh2'); + +const conn = new Client(); +conn.on('ready', () => { console.log('Client :: ready'); - conn.shell(function(err, stream) { + conn.shell((err, stream) => { if (err) throw err; - stream.on('close', function() { + stream.on('close', () => { console.log('Stream :: close'); conn.end(); - }).on('data', function(data) { - console.log('STDOUT: ' + data); - }).stderr.on('data', function(data) { - console.log('STDERR: ' + data); + }).on('data', (data) => { + console.log('OUTPUT: ' + data); }); stream.end('ls -l\nexit\n'); }); @@ -83,7 +116,7 @@ conn.on('ready', function() { host: '192.168.100.100', port: 22, username: 'frylock', - privateKey: require('fs').readFileSync('/here/is/my/key') + privateKey: readFileSync('/path/to/my/key') }); // example output: @@ -108,20 +141,20 @@ conn.on('ready', function() { // Stream :: close ``` -* Send a raw HTTP request to port 80 on the server: +### Send a raw HTTP request to port 80 on the server -```javascript -var Client = require('ssh2').Client; +```js +const { Client } = require('ssh2'); -var conn = new Client(); -conn.on('ready', function() { +const conn = new Client(); +conn.on('ready', () => { console.log('Client :: ready'); - conn.forwardOut('192.168.100.102', 8000, '127.0.0.1', 80, function(err, stream) { + conn.forwardOut('192.168.100.102', 8000, '127.0.0.1', 80, (err, stream) => { if (err) throw err; - stream.on('close', function() { + stream.on('close', () => { console.log('TCP :: CLOSED'); conn.end(); - }).on('data', function(data) { + }).on('data', (data) => { console.log('TCP :: DATA: ' + data); }).end([ 'HEAD / HTTP/1.1', @@ -156,24 +189,24 @@ conn.on('ready', function() { // TCP :: CLOSED ``` -* Forward connections to 127.0.0.1:8000 on the server to us: +### Forward local connections to port 8000 on the server to us -```javascript -var Client = require('ssh2').Client; +```js +const { Client } = require('ssh2'); -var conn = new Client(); -conn.on('ready', function() { +const conn = new Client(); +conn.on('ready', () => { console.log('Client :: ready'); - conn.forwardIn('127.0.0.1', 8000, function(err) { + conn.forwardIn('127.0.0.1', 8000, (err) => { if (err) throw err; console.log('Listening for connections on server on port 8000!'); }); -}).on('tcp connection', function(info, accept, reject) { +}).on('tcp connection', (info, accept, reject) => { console.log('TCP :: INCOMING CONNECTION:'); console.dir(info); - accept().on('close', function() { + accept().on('close', () => { console.log('TCP :: CLOSED'); - }).on('data', function(data) { + }).on('data', (data) => { console.log('TCP :: DATA: ' + data); }).end([ 'HTTP/1.1 404 Not Found', @@ -208,17 +241,17 @@ conn.on('ready', function() { // TCP :: CLOSED ``` -* Get a directory listing via SFTP: +### Get a directory listing via SFTP -```javascript -var Client = require('ssh2').Client; +```js +const { Client } = require('ssh2'); -var conn = new Client(); -conn.on('ready', function() { +const conn = new Client(); +conn.on('ready', () => { console.log('Client :: ready'); - conn.sftp(function(err, sftp) { + conn.sftp((err, sftp) => { if (err) throw err; - sftp.readdir('foo', function(err, list) { + sftp.readdir('foo', (err, list) => { if (err) throw err; console.dir(list); conn.end(); @@ -253,19 +286,23 @@ conn.on('ready', function() { // mtime: 1353269007 } } ] ``` -* Connection hopping: +### Connection hopping + +```js +const { Client } = require('ssh2'); -```javascript -var Client = require('ssh2').Client; +const conn1 = new Client(); +const conn2 = new Client(); -var conn1 = new Client(); -var conn2 = new Client(); +// Checks uptime on 10.1.1.40 via 192.168.1.1 -conn1.on('ready', function() { +conn1.on('ready', () => { console.log('FIRST :: connection ready'); - conn1.exec('nc 192.168.1.2 22', function(err, stream) { + // Alternatively, you could use something like netcat or socat with exec() + // instead of forwardOut(), depending on what the server allows + conn1.forwardOut('127.0.0.1', 12345, '10.1.1.40', 22, (err, stream) => { if (err) { - console.log('FIRST :: exec error: ' + err); + console.log('FIRST :: forwardOut error: ' + err); return conn1.end(); } conn2.connect({ @@ -280,50 +317,52 @@ conn1.on('ready', function() { password: 'password1', }); -conn2.on('ready', function() { +conn2.on('ready', () => { + // This connection is the one to 10.1.1.40 + console.log('SECOND :: connection ready'); - conn2.exec('uptime', function(err, stream) { + conn2.exec('uptime', (err, stream) => { if (err) { console.log('SECOND :: exec error: ' + err); return conn1.end(); } - stream.on('end', function() { + stream.on('close', () => { conn1.end(); // close parent (and this) connection - }).on('data', function(data) { + }).on('data', (data) => { console.log(data.toString()); }); }); }); ``` -* Forward X11 connections (xeyes in this case): +### Forward remote X11 connections -```javascript -var net = require('net'); +```js +const { Socket } = require('net'); -var Client = require('ssh2').Client; +const { Client } = require('ssh2'); -var conn = new Client(); +const conn = new Client(); -conn.on('x11', function(info, accept, reject) { - var xserversock = new net.Socket(); - xserversock.on('connect', function() { - var xclientsock = accept(); +conn.on('x11', (info, accept, reject) => { + const xserversock = new net.Socket(); + xserversock.on('connect', () => { + const xclientsock = accept(); xclientsock.pipe(xserversock).pipe(xclientsock); }); // connects to localhost:0.0 xserversock.connect(6000, 'localhost'); }); -conn.on('ready', function() { - conn.exec('xeyes', { x11: true }, function(err, stream) { +conn.on('ready', () => { + conn.exec('xeyes', { x11: true }, (err, stream) => { if (err) throw err; - var code = 0; - stream.on('end', function() { + let code = 0; + stream.on('close', () => { if (code !== 0) console.log('Do you have X11 forwarding enabled on your SSH server?'); conn.end(); - }).on('exit', function(exitcode) { + }).on('exit', (exitcode) => { code = exitcode; }); }); @@ -334,47 +373,48 @@ conn.on('ready', function() { }); ``` -* Dynamic (1:1) port forwarding using a SOCKSv5 proxy (using [socksv5](https://github.com/mscdex/socksv5)): +### Dynamic (1:1) port forwarding using a SOCKSv5 proxy (using [socksv5](https://github.com/mscdex/socksv5)) -```javascript -var socks = require('socksv5'); -var Client = require('ssh2').Client; +```js +const socks = require('socksv5'); +const { Client } = require('ssh2'); -var ssh_config = { +const sshConfig = { host: '192.168.100.1', port: 22, username: 'nodejs', password: 'rules' }; -socks.createServer(function(info, accept, deny) { +socks.createServer((info, accept, deny) => { // NOTE: you could just use one ssh2 client connection for all forwards, but // you could run into server-imposed limits if you have too many forwards open // at any given time - var conn = new Client(); - conn.on('ready', function() { + const conn = new Client(); + conn.on('ready', () => { conn.forwardOut(info.srcAddr, info.srcPort, info.dstAddr, info.dstPort, - function(err, stream) { + (err, stream) => { if (err) { conn.end(); return deny(); } - var clientSocket; - if (clientSocket = accept(true)) { - stream.pipe(clientSocket).pipe(stream).on('close', function() { + const clientSocket = accept(true); + if (clientSocket) { + stream.pipe(clientSocket).pipe(stream).on('close', () => { conn.end(); }); - } else + } else { conn.end(); + } }); - }).on('error', function(err) { + }).on('error', (err) => { deny(); - }).connect(ssh_config); -}).listen(1080, 'localhost', function() { + }).connect(sshConfig); +}).listen(1080, 'localhost', () => { console.log('SOCKSv5 proxy server started on port 1080'); }).useAuth(socks.auth.None()); @@ -382,24 +422,54 @@ socks.createServer(function(info, accept, deny) { // curl -i --socks5 localhost:1080 google.com ``` -* Invoke an arbitrary subsystem (netconf in this case): +### Make HTTP(S) connections easily using a custom http(s).Agent -```javascript -var Client = require('ssh2').Client; -var xmlhello = '' + - '' + - ' ' + - ' urn:ietf:params:netconf:base:1.0' + - ' ' + - ']]>]]>'; +```js +const http = require('http'); -var conn = new Client(); +const { Client, HTTPAgent, HTTPSAgent } = require('ssh2'); -conn.on('ready', function() { +const sshConfig = { + host: '192.168.100.1', + port: 22, + username: 'nodejs', + password: 'rules' +}; + +// Use `HTTPSAgent` instead for an HTTPS request +const agent = new HTTPAgent(sshConfig); +http.get({ + host: '192.168.200.1', + agent, + headers: { Connection: 'close' } +}, (res) => { + console.log(res.statusCode); + console.dir(res.headers); + res.resume(); +}); +``` + + +### Invoke an arbitrary subsystem + +```js +const { Client } = require('ssh2'); + +const xmlhello = ` + + + + urn:ietf:params:netconf:base:1.0 + + ]]>]]>`; + +const conn = new Client(); + +conn.on('ready', () => { console.log('Client :: ready'); - conn.subsys('netconf', function(err, stream) { + conn.subsys('netconf', (err, stream) => { if (err) throw err; - stream.on('data', function(data) { + stream.on('data', (data) => { console.log(data); }).write(xmlhello); }); @@ -411,64 +481,77 @@ conn.on('ready', function() { }); ``` -Server Examples -=============== +## Server Examples -* Only allow password and public key authentication and non-interactive (exec) command execution: +### Password and public key authentication and non-interactive (exec) command execution -```javascript -var fs = require('fs'); -var crypto = require('crypto'); -var inspect = require('util').inspect; +```js +const { timingSafeEqual } = require('crypto'); +const { readFileSync } = require('fs'); +const { inspect } = require('util'); -var buffersEqual = require('buffer-equal-constant-time'); -var ssh2 = require('ssh2'); -var utils = ssh2.utils; +const { utils: { parseKey }, Server } = require('ssh2'); -var pubKey = utils.genPublicKey(utils.parseKey(fs.readFileSync('user.pub'))); +const allowedUser = Buffer.from('foo'); +const allowedPassword = Buffer.from('bar'); +const allowedPubKey = parseKey(readFileSync('foo.pub')); -new ssh2.Server({ - hostKeys: [fs.readFileSync('host.key')] -}, function(client) { +function checkValue(input, allowed) { + const autoReject = (input.length !== allowed.length); + if (autoReject) { + // Prevent leaking length information by always making a comparison with the + // same input when lengths don't match what we expect ... + allowed = input; + } + const isMatch = timingSafeEqual(input, allowed); + return (!autoReject && isMatch); +} + +new Server({ + hostKeys: [readFileSync('host.key')] +}, (client) => { console.log('Client connected!'); - client.on('authentication', function(ctx) { - if (ctx.method === 'password' - && ctx.username === 'foo' - && ctx.password === 'bar') + client.on('authentication', (ctx) => { + let allowed = true; + if (!checkValue(Buffer.from(ctx.username), allowedUser)) + allowed = false; + + switch (ctx.method) { + case 'password': + if (!checkValue(Buffer.from(ctx.password), allowedPassword)) + return ctx.reject(); + break; + case 'publickey': + if (ctx.key.algo !== allowedPubKey.type + || !checkValue(ctx.key.data, allowedPubKey.getPublicSSH()) + || (ctx.signature && allowedPubKey.verify(ctx.blob, ctx.signature) !== true)) { + return ctx.reject(); + } + break; + default: + return ctx.reject(); + } + + if (allowed) ctx.accept(); - else if (ctx.method === 'publickey' - && ctx.key.algo === pubKey.fulltype - && buffersEqual(ctx.key.data, pubKey.public)) { - if (ctx.signature) { - var verifier = crypto.createVerify(ctx.sigAlgo); - verifier.update(ctx.blob); - if (verifier.verify(pubKey.publicOrig, ctx.signature)) - ctx.accept(); - else - ctx.reject(); - } else { - // if no signature present, that means the client is just checking - // the validity of the given public key - ctx.accept(); - } - } else + else ctx.reject(); - }).on('ready', function() { + }).on('ready', () => { console.log('Client authenticated!'); - client.on('session', function(accept, reject) { - var session = accept(); - session.once('exec', function(accept, reject, info) { + client.on('session', (accept, reject) => { + const session = accept(); + session.once('exec', (accept, reject, info) => { console.log('Client wants to execute: ' + inspect(info.command)); - var stream = accept(); + const stream = accept(); stream.stderr.write('Oh no, the dreaded errors!\n'); stream.write('Just kidding about the errors!\n'); stream.exit(0); stream.end(); }); }); - }).on('end', function() { + }).on('close', () => { console.log('Client disconnected'); }); }).listen(0, '127.0.0.1', function() { @@ -476,69 +559,110 @@ new ssh2.Server({ }); ``` -* SFTP only server: - -```javascript -var fs = require('fs'); - -var ssh2 = require('ssh2'); -var OPEN_MODE = ssh2.SFTP_OPEN_MODE; -var STATUS_CODE = ssh2.SFTP_STATUS_CODE; +### SFTP-only server + +```js +const { timingSafeEqual } = require('crypto'); +const { readFileSync } = require('fs'); +const { inspect } = require('util'); + +const { + Server, + sftp: { + OPEN_MODE, + STATUS_CODE, + }, +} = require('ssh2'); + +const allowedUser = Buffer.from('foo'); +const allowedPassword = Buffer.from('bar'); + +function checkValue(input, allowed) { + const autoReject = (input.length !== allowed.length); + if (autoReject) { + // Prevent leaking length information by always making a comparison with the + // same input when lengths don't match what we expect ... + allowed = input; + } + const isMatch = timingSafeEqual(input, allowed); + return (!autoReject && isMatch); +} + +// This simple SFTP server implements file uploading where the contents get +// ignored ... new ssh2.Server({ - hostKeys: [fs.readFileSync('host.key')] -}, function(client) { + hostKeys: [readFileSync('host.key')] +}, (client) => { console.log('Client connected!'); - client.on('authentication', function(ctx) { - if (ctx.method === 'password' - && ctx.username === 'foo' - && ctx.password === 'bar') + client.on('authentication', (ctx) => { + let allowed = true; + if (!checkValue(Buffer.from(ctx.username), allowedUser)) + allowed = false; + + switch (ctx.method) { + case 'password': + if (!checkValue(Buffer.from(ctx.password), allowedPassword)) + return ctx.reject(); + break; + default: + return ctx.reject(); + } + + if (allowed) ctx.accept(); else ctx.reject(); - }).on('ready', function() { + }).on('ready', () => { console.log('Client authenticated!'); - client.on('session', function(accept, reject) { - var session = accept(); - session.on('sftp', function(accept, reject) { + client.on('session', (accept, reject) => { + const session = accept(); + session.on('sftp', (accept, reject) => { console.log('Client SFTP session'); - var openFiles = {}; - var handleCount = 0; - // `sftpStream` is an `SFTPStream` instance in server mode - // see: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md - var sftpStream = accept(); - sftpStream.on('OPEN', function(reqid, filename, flags, attrs) { - // only allow opening /tmp/foo.txt for writing + const openFiles = new Map(); + let handleCount = 0; + const sftp = accept(); + sftp.on('OPEN', (reqid, filename, flags, attrs) => { + // Only allow opening /tmp/foo.txt for writing if (filename !== '/tmp/foo.txt' || !(flags & OPEN_MODE.WRITE)) - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - // create a fake handle to return to the client, this could easily + return sftp.status(reqid, STATUS_CODE.FAILURE); + + // Create a fake handle to return to the client, this could easily // be a real file descriptor number for example if actually opening - // the file on the disk - var handle = new Buffer(4); - openFiles[handleCount] = true; - handle.writeUInt32BE(handleCount++, 0, true); - sftpStream.handle(reqid, handle); + // a file on disk + const handle = Buffer.alloc(4); + openFiles.set(handleCount, true); + handle.writeUInt32BE(handleCount++, 0); + console.log('Opening file for write') - }).on('WRITE', function(reqid, handle, offset, data) { - if (handle.length !== 4 || !openFiles[handle.readUInt32BE(0, true)]) - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - // fake the write - sftpStream.status(reqid, STATUS_CODE.OK); - var inspected = require('util').inspect(data); - console.log('Write to file at offset %d: %s', offset, inspected); - }).on('CLOSE', function(reqid, handle) { - var fnum; - if (handle.length !== 4 || !openFiles[(fnum = handle.readUInt32BE(0, true))]) - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - delete openFiles[fnum]; - sftpStream.status(reqid, STATUS_CODE.OK); + sftp.handle(reqid, handle); + }).on('WRITE', (reqid, handle, offset, data) => { + if (handle.length !== 4 + || !openFiles.has(handle.readUInt32BE(0))) { + return sftp.status(reqid, STATUS_CODE.FAILURE); + } + + // Fake the write operation + sftp.status(reqid, STATUS_CODE.OK); + + console.log('Write to file at offset ${offset}: ${inspect(data)}'); + }).on('CLOSE', (reqid, handle) => { + let fnum; + if (handle.length !== 4 + || !openFiles.has(fnum = handle.readUInt32BE(0))) { + return sftp.status(reqid, STATUS_CODE.FAILURE); + } + console.log('Closing file'); + openFiles.delete(fnum); + + sftp.status(reqid, STATUS_CODE.OK); }); }); }); - }).on('end', function() { + }).on('close', () => { console.log('Client disconnected'); }); }).listen(0, '127.0.0.1', function() { @@ -546,123 +670,295 @@ new ssh2.Server({ }); ``` -* You can find more examples in the `examples` directory of this repository. +You can find more examples in the `examples` directory of this repository. -API -=== +## API -`require('ssh2').Client` returns a **_Client_** constructor. +`require('ssh2').Client` is the **_Client_** constructor. -`require('ssh2').Server` returns a **_Server_** constructor. +`require('ssh2').Server` is the **_Server_** constructor. -`require('ssh2').utils` returns the [utility methods from `ssh2-streams`](https://github.com/mscdex/ssh2-streams#utility-methods). +`require('ssh2').utils` is an object containing some useful [utilities](#utilities). -`require('ssh2').SFTP_STATUS_CODE` returns the [`SFTPStream.STATUS_CODE` from `ssh2-streams`](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md#sftpstream-static-constants). +`require('ssh2').HTTPAgent` is an [`http.Agent`](https://nodejs.org/docs/latest/api/http.html#http_class_http_agent) constructor. -`require('ssh2').SFTP_OPEN_MODE` returns the [`SFTPStream.OPEN_MODE` from `ssh2-streams`](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md#sftpstream-static-constants). +`require('ssh2').HTTPSAgent` is an [`https.Agent`](https://nodejs.org/docs/latest/api/https.html#https_class_https_agent) constructor. Its API is the same as `HTTPAgent` except it's for HTTPS connections. -Client events -------------- +### Agent-related -* **banner**(< _string_ >message, < _string_ >language) - A notice was sent by the server upon connection. +`require('ssh2').AgentProtocol` is a Duplex stream [class](#agentprotocol) that aids in communicating over the OpenSSH agent protocol. -* **ready**() - Authentication was successful. - -* **tcp connection**(< _object_ >details, < _function_ >accept, < _function_ >reject) - An incoming forwarded TCP connection is being requested. Calling `accept` accepts the connection and returns a `Channel` object. Calling `reject` rejects the connection and no further action is needed. `details` contains: +`require('ssh2').BaseAgent` is a base [class](#baseagent) for creating custom authentication agents. - * **srcIP** - _string_ - The originating IP of the connection. +`require('ssh2').createAgent` is a helper [function](#createagent) that creates a new agent instance using the same logic as the `agent` configuration option: if the platform is Windows and it's the value "pageant", it creates a `PageantAgent`, otherwise if it's not a path to a Windows pipe it creates a `CygwinAgent`. In all other cases, it creates an `OpenSSHAgent`. - * **srcPort** - _integer_ - The originating port of the connection. +`require('ssh2').CygwinAgent` is an agent [class](#cygwinagent) implementation that communicates with agents in a Cygwin environment. - * **destIP** - _string_ - The remote IP the connection was received on (given in earlier call to `forwardIn()`). +`require('ssh2').OpenSSHAgent` is an agent [class](#opensshagent) implementation that communicates with OpenSSH agents over a UNIX socket. - * **destPort** - _integer_ - The remote port the connection was received on (given in earlier call to `forwardIn()`). +`require('ssh2').PageantAgent` is an agent [class](#pageantagent) implementation that communicates with Pageant agent processes. -* **x11**(< _object_ >details, < _function_ >accept, < _function_ >reject) - An incoming X11 connection is being requested. Calling `accept` accepts the connection and returns a `Channel` object. Calling `reject` rejects the connection and no further action is needed. `details` contains: +### Client - * **srcIP** - _string_ - The originating IP of the connection. +#### Client events - * **srcPort** - _integer_ - The originating port of the connection. +* **banner**(< _string_ >message, < _string_ >language) - A notice was sent by the server upon connection. -* **keyboard-interactive**(< _string_ >name, < _string_ >instructions, < _string_ >instructionsLang, < _array_ >prompts, < _function_ >finish) - The server is asking for replies to the given `prompts` for keyboard-interactive user authentication. `name` is generally what you'd use as a window title (for GUI apps). `prompts` is an array of `{ prompt: 'Password: ', echo: false }` style objects (here `echo` indicates whether user input should be displayed on the screen). The answers for all prompts must be provided as an array of strings and passed to `finish` when you are ready to continue. Note: It's possible for the server to come back and ask more questions. +* **change password**(< _string_ >prompt, < _function_ >done) - If using password-based user authentication, the server has requested that the user's password be changed. Call `done` with the new password. -* **change password**(< _string_ >message, < _string_ >language, < _function_ >done) - If using password-based user authentication, the server has requested that the user's password be changed. Call `done` with the new password. +* **close**() - The socket was closed. -* **continue**() - Emitted when more requests/data can be sent to the server (after a `Client` method returned `false`). +* **end**() - The socket was disconnected. * **error**(< _Error_ >err) - An error occurred. A 'level' property indicates 'client-socket' for socket-level errors and 'client-ssh' for SSH disconnection messages. In the case of 'client-ssh' messages, there may be a 'description' property that provides more detail. -* **end**() - The socket was disconnected. +* **handshake**(< _object_ >negotiated) - Emitted when a handshake has completed (either initial or rekey). `negotiated` contains the negotiated details of the handshake and is of the form: + +```js + // In this particular case `mac` is empty because there is no separate MAC + // because it's integrated into AES in GCM mode + { kex: 'ecdh-sha2-nistp256', + srvHostKey: 'rsa-sha2-512', + cs: { // Client to server algorithms + cipher: 'aes128-gcm', + mac: '', + compress: 'none', + lang: '' + }, + sc: { // Server to client algorithms + cipher: 'aes128-gcm', + mac: '', + compress: 'none', + lang: '' + } + } +``` -* **close**(< _boolean_ >hadError) - The socket was closed. `hadError` is set to `true` if this was due to error. +* **hostkeys**(< _array_ >keys) - Emitted when the server announces its available host keys. `keys` is the list of parsed (using [`parseKey()`](#utilities)) host public keys. +* **keyboard-interactive**(< _string_ >name, < _string_ >instructions, < _string_ >instructionsLang, < _array_ >prompts, < _function_ >finish) - The server is asking for replies to the given `prompts` for keyboard-interactive user authentication. `name` is generally what you'd use as a window title (for GUI apps). `prompts` is an array of `{ prompt: 'Password: ', echo: false }` style objects (here `echo` indicates whether user input should be displayed on the screen). The answers for all prompts must be provided as an array of strings and passed to `finish` when you are ready to continue. Note: It's possible for the server to come back and ask more questions. -Client methods --------------- +* **ready**() - Authentication was successful. -* **(constructor)**() - Creates and returns a new Client instance. +* **rekey**() - Emitted when a rekeying operation has completed (either client or server-initiated). -* **connect**(< _object_ >config) - _(void)_ - Attempts a connection to a server using the information given in `config`: +* **tcp connection**(< _object_ >details, < _function_ >accept, < _function_ >reject) - An incoming forwarded TCP connection is being requested. Calling `accept` accepts the connection and returns a `Channel` object. Calling `reject` rejects the connection and no further action is needed. `details` contains: - * **host** - _string_ - Hostname or IP address of the server. **Default:** `'localhost'` + * **destIP** - _string_ - The remote IP the connection was received on (given in earlier call to `forwardIn()`). - * **port** - _integer_ - Port number of the server. **Default:** `22` + * **destPort** - _integer_ - The remote port the connection was received on (given in earlier call to `forwardIn()`). - * **forceIPv4** - _boolean_ - Only connect via resolved IPv4 address for `host`. **Default:** `false` + * **srcIP** - _string_ - The originating IP of the connection. - * **forceIPv6** - _boolean_ - Only connect via resolved IPv6 address for `host`. **Default:** `false` + * **srcPort** - _integer_ - The originating port of the connection. - * **hostHash** - _string_ - 'md5' or 'sha1'. The host's key is hashed using this method and passed to the **hostVerifier** function. **Default:** (none) +* **unix connection**(< _object_ >details, < _function_ >accept, < _function_ >reject) - An incoming forwarded UNIX socket connection is being requested. Calling `accept` accepts the connection and returns a `Channel` object. Calling `reject` rejects the connection and no further action is needed. `details` contains: - * **hostVerifier** - _function_ - Function with parameters `(hashedKey[, callback])` where `hashedKey` is a string hex hash of the host's key for verification purposes. Return `true` to continue with the handshake or `false` to reject and disconnect, or call `callback()` with `true` or `false` if you need to perform asynchronous verification. **Default:** (auto-accept if `hostVerifier` is not set) + * **socketPath** - _string_ - The originating UNIX socket path of the connection. - * **username** - _string_ - Username for authentication. **Default:** (none) +* **x11**(< _object_ >details, < _function_ >accept, < _function_ >reject) - An incoming X11 connection is being requested. Calling `accept` accepts the connection and returns a `Channel` object. Calling `reject` rejects the connection and no further action is needed. `details` contains: - * **password** - _string_ - Password for password-based user authentication. **Default:** (none) + * **srcIP** - _string_ - The originating IP of the connection. + + * **srcPort** - _integer_ - The originating port of the connection. + +#### Client methods + +* **(constructor)**() - Creates and returns a new Client instance. + +* **connect**(< _object_ >config) - _(void)_ - Attempts a connection to a server using the information given in `config`: * **agent** - _string_ - Path to ssh-agent's UNIX socket for ssh-agent-based user authentication. **Windows users: set to 'pageant' for authenticating with Pageant or (actual) path to a cygwin "UNIX socket."** **Default:** (none) * **agentForward** - _boolean_ - Set to `true` to use OpenSSH agent forwarding (`auth-agent@openssh.com`) for the life of the connection. `agent` must also be set to use this feature. **Default:** `false` - * **privateKey** - _mixed_ - _Buffer_ or _string_ that contains a private key for either key-based or hostbased user authentication (OpenSSH format). **Default:** (none) + * **algorithms** - _object_ - This option allows you to explicitly override the default transport layer algorithms used for the connection. The value for each category must either be an array of valid algorithm names to set an exact list (with the most preferable first) or an object containing `append`, `prepend`, and/or `remove` properties that each contain an _array_ of algorithm names or RegExps to match to adjust default lists for each category. Valid keys: + + * **cipher** - _mixed_ - Ciphers. + * Default list (in order from most to least preferable): + * `chacha20-poly1305@openssh.com` (priority of chacha20-poly1305 may vary depending upon CPU and/or optional binding availability) + * `aes128-gcm` + * `aes128-gcm@openssh.com` + * `aes256-gcm` + * `aes256-gcm@openssh.com` + * `aes128-ctr` + * `aes192-ctr` + * `aes256-ctr` + * Other supported names: + * `3des-cbc` + * `aes256-cbc` + * `aes192-cbc` + * `aes128-cbc` + * `arcfour256` + * `arcfour128` + * `arcfour` + * `blowfish-cbc` + * `cast128-cbc` + + * **compress** - _mixed_ - Compression algorithms. + * Default list (in order from most to least preferable): + * `none` + * `zlib@openssh.com` + * `zlib` + * Other supported names: + + * **hmac** - _mixed_ - (H)MAC algorithms. + * Default list (in order from most to least preferable): + * `hmac-sha2-256-etm@openssh.com` + * `hmac-sha2-512-etm@openssh.com` + * `hmac-sha1-etm@openssh.com` + * `hmac-sha2-256` + * `hmac-sha2-512` + * `hmac-sha1` + * Other supported names: + * `hmac-md5` + * `hmac-sha2-256-96` + * `hmac-sha2-512-96` + * `hmac-ripemd160` + * `hmac-sha1-96` + * `hmac-md5-96` + + * **kex** - _mixed_ - Key exchange algorithms. + * Default list (in order from most to least preferable): + * `curve25519-sha256 (node v14.0.0+)` + * `curve25519-sha256@libssh.org (node v14.0.0+)` + * `ecdh-sha2-nistp256` + * `ecdh-sha2-nistp384` + * `ecdh-sha2-nistp521` + * `diffie-hellman-group-exchange-sha256` + * `diffie-hellman-group14-sha256` + * `diffie-hellman-group15-sha512` + * `diffie-hellman-group16-sha512` + * `diffie-hellman-group17-sha512` + * `diffie-hellman-group18-sha512` + * Other supported names: + * `diffie-hellman-group-exchange-sha1` + * `diffie-hellman-group14-sha1` + * `diffie-hellman-group1-sha1` + + * **serverHostKey** - _mixed_ - Server host key formats. + * Default list (in order from most to least preferable): + * `ssh-ed25519` (node v12.0.0+) + * `ecdsa-sha2-nistp256` + * `ecdsa-sha2-nistp384` + * `ecdsa-sha2-nistp521` + * `rsa-sha2-512` + * `rsa-sha2-256` + * `ssh-rsa` + * Other supported names: + * `ssh-dss` + + * **authHandler** - _mixed_ - Either an array of objects as described below or a function with parameters `(methodsLeft, partialSuccess, callback)` where `methodsLeft` and `partialSuccess` are `null` on the first authentication attempt, otherwise are an array and boolean respectively. Return or call `callback()` with either the name of the authentication method or an object containing the method name along with method-specific details to try next (return/pass `false` to signal no more methods to try). Valid method names are: `'none', 'password', 'publickey', 'agent', 'keyboard-interactive', 'hostbased'`. **Default:** function that follows a set method order: None -> Password -> Private Key -> Agent (-> keyboard-interactive if `tryKeyboard` is `true`) -> Hostbased + + * When returning or calling `callback()` with an object, it can take one of the following forms: + + ```js + { + type: 'none', + username: 'foo', + } + ``` + + ```js + { + type: 'password' + username: 'foo', + password: 'bar', + } + ``` + + ```js + { + type: 'publickey' + username: 'foo', + // Can be a string, Buffer, or parsed key containing a private key + key: ..., + // `passphrase` only required for encrypted keys + passphrase: ..., + } + ``` + + ```js + { + type: 'hostbased' + username: 'foo', + localHostname: 'baz', + localUsername: 'quux', + // Can be a string, Buffer, or parsed key containing a private key + key: ..., + // `passphrase` only required for encrypted keys + passphrase: ..., + } + ``` + + ```js + { + type: 'agent' + username: 'foo', + // Can be a string that is interpreted exactly like the `agent` + // connection config option or can be a custom agent + // object/instance that extends and implements `BaseAgent` + agent: ..., + } + ``` + + ```js + { + type: 'keyboard-interactive' + username: 'foo', + // This works exactly the same way as a 'keyboard-interactive' + // Client event handler + prompt: (name, instructions, instructionsLang, prompts, finish) => { + // ... + }, + } + ``` - * **passphrase** - _string_ - For an encrypted private key, this is the passphrase used to decrypt it. **Default:** (none) + * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information. **Default:** (none) - * **localHostname** - _string_ - Along with **localUsername** and **privateKey**, set this to a non-empty string for hostbased user authentication. **Default:** (none) + * **forceIPv4** - _boolean_ - Only connect via resolved IPv4 address for `host`. **Default:** `false` - * **localUsername** - _string_ - Along with **localHostname** and **privateKey**, set this to a non-empty string for hostbased user authentication. **Default:** (none) + * **forceIPv6** - _boolean_ - Only connect via resolved IPv6 address for `host`. **Default:** `false` - * **tryKeyboard** - _boolean_ - Try keyboard-interactive user authentication if primary user authentication method fails. If you set this to `true`, you need to handle the `keyboard-interactive` event. **Default:** `false` + * **host** - _string_ - Hostname or IP address of the server. **Default:** `'localhost'` - * **keepaliveInterval** - _integer_ - How often (in milliseconds) to send SSH-level keepalive packets to the server (in a similar way as OpenSSH's ServerAliveInterval config option). Set to 0 to disable. **Default:** `0` + * **hostHash** - _string_ - Any valid hash algorithm supported by node. The host's key is hashed using this algorithm and passed to the **hostVerifier** function as a hex string. **Default:** (none) + + * **hostVerifier** - _function_ - Function with parameters `(hashedKey[, callback])` where `hashedKey` is a string hex hash of the host's key for verification purposes. Return `true` to continue with the handshake or `false` to reject and disconnect, or call `callback()` with `true` or `false` if you need to perform asynchronous verification. **Default:** (auto-accept if `hostVerifier` is not set) * **keepaliveCountMax** - _integer_ - How many consecutive, unanswered SSH-level keepalive packets that can be sent to the server before disconnection (similar to OpenSSH's ServerAliveCountMax config option). **Default:** `3` - * **readyTimeout** - _integer_ - How long (in milliseconds) to wait for the SSH handshake to complete. **Default:** `20000` + * **keepaliveInterval** - _integer_ - How often (in milliseconds) to send SSH-level keepalive packets to the server (in a similar way as OpenSSH's ServerAliveInterval config option). Set to 0 to disable. **Default:** `0` - * **sock** - _ReadableStream_ - A _ReadableStream_ to use for communicating with the server instead of creating and using a new TCP connection (useful for connection hopping). + * **localAddress** - _string_ - IP address of the network interface to use to connect to the server. **Default:** (none -- determined by OS) - * **strictVendor** - _boolean_ - Performs a strict server vendor check before sending vendor-specific requests, etc. (e.g. check for OpenSSH server when using `openssh_noMoreSessions()`) **Default:** `true` + * **localHostname** - _string_ - Along with **localUsername** and **privateKey**, set this to a non-empty string for hostbased user authentication. **Default:** (none) - * **algorithms** - _object_ - This option allows you to explicitly override the default transport layer algorithms used for the connection. Each value must be an array of valid algorithms for that category. The order of the algorithms in the arrays are important, with the most favorable being first. For a list of valid and default algorithm names, please review the documentation for the version of `ssh2-streams` used by this module. Valid keys: + * **localPort** - _string_ - The local port number to connect from. **Default:** (none -- determined by OS) - * **kex** - _array_ - Key exchange algorithms. + * **localUsername** - _string_ - Along with **localHostname** and **privateKey**, set this to a non-empty string for hostbased user authentication. **Default:** (none) - * **cipher** - _array_ - Ciphers. + * **passphrase** - _string_ - For an encrypted `privateKey`, this is the passphrase used to decrypt it. **Default:** (none) - * **serverHostKey** - _array_ - Server host key formats. + * **password** - _string_ - Password for password-based user authentication. **Default:** (none) - * **hmac** - _array_ - (H)MAC algorithms. + * **port** - _integer_ - Port number of the server. **Default:** `22` - * **compress** - _array_ - Compression algorithms. + * **privateKey** - _mixed_ - _Buffer_ or _string_ that contains a private key for either key-based or hostbased user authentication (OpenSSH format). **Default:** (none) - * **compress** - _mixed_ - Set to `true` to enable compression if server supports it, `'force'` to force compression (disconnecting if server does not support it), or `false` to explicitly opt out of compression all of the time. Note: this setting is overridden when explicitly setting a compression algorithm in the `algorithms` configuration option. **Default:** (only use compression if that is only what the server supports) + * **readyTimeout** - _integer_ - How long (in milliseconds) to wait for the SSH handshake to complete. **Default:** `20000` - * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information. **Default:** (none) + * **sock** - _ReadableStream_ - A _ReadableStream_ to use for communicating with the server instead of creating and using a new TCP connection (useful for connection hopping). + + * **strictVendor** - _boolean_ - Performs a strict server vendor check before sending vendor-specific requests, etc. (e.g. check for OpenSSH server when using `openssh_noMoreSessions()`) **Default:** `true` + + * **tryKeyboard** - _boolean_ - Try keyboard-interactive user authentication if primary user authentication method fails. If you set this to `true`, you need to handle the `keyboard-interactive` event. **Default:** `false` + + * **username** - _string_ - Username for authentication. **Default:** (none) -**Authentication method priorities:** Password -> Private Key -> Agent (-> keyboard-interactive if `tryKeyboard` is `true`) -> Hostbased -> None +* **end**() - _(void)_ - Disconnects the socket. -* **exec**(< _string_ >command[, < _object_ >options], < _function_ >callback) - _boolean_ - Executes `command` on the server. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Valid `options` properties are: +* **exec**(< _string_ >command[, < _object_ >options], < _function_ >callback) - _(void)_ - Executes `command` on the server. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Valid `options` properties are: * **env** - _object_ - An environment to use for the execution of the command. @@ -670,13 +966,15 @@ Client methods * **x11** - _mixed_ - Set to `true` to use defaults below, set to a number to specify a specific screen number, or an object with the following valid properties: - * **single** - _boolean_ - Allow just a single connection? **Default:** `false` + * **cookie** - _mixed_ - The authentication cookie. Can be a hex _string_ or a _Buffer_ containing the raw cookie value (which will be converted to a hex string). **Default:** (random 16 byte value) + + * **protocol** - _string_ - The authentication protocol name. **Default:** `'MIT-MAGIC-COOKIE-1'` * **screen** - _number_ - Screen number to use **Default:** `0` -* **shell**([[< _mixed_ >window,] < _object_ >options]< _function_ >callback) - _boolean_ - Starts an interactive shell session on the server, with an optional `window` object containing pseudo-tty settings (see 'Pseudo-TTY settings'). If `window === false`, then no pseudo-tty is allocated. `options` supports the `x11` option as described in exec(). `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. + * **single** - _boolean_ - Allow just a single connection? **Default:** `false` -* **forwardIn**(< _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _boolean_ - Bind to `remoteAddr` on `remotePort` on the server and forward incoming TCP connections. `callback` has 2 parameters: < _Error_ >err, < _integer_ >port (`port` is the assigned port number if `remotePort` was 0). Returns `false` if you should wait for the `continue` event before sending any more traffic. Here are some special values for `remoteAddr` and their associated binding behaviors: +* **forwardIn**(< _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _(void)_ - Bind to `remoteAddr` on `remotePort` on the server and forward incoming TCP connections. `callback` has 2 parameters: < _Error_ >err, < _integer_ >port (`port` is the assigned port number if `remotePort` was 0). Here are some special values for `remoteAddr` and their associated binding behaviors: * '' - Connections are to be accepted on all protocol families supported by the server. @@ -688,31 +986,33 @@ Client methods * '127.0.0.1' and '::1' - Listen on the loopback interfaces for IPv4 and IPv6, respectively. -* **unforwardIn**(< _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _boolean_ - Unbind from `remoteAddr` on `remotePort` on the server and stop forwarding incoming TCP connections. Until `callback` is called, more connections may still come in. `callback` has 1 parameter: < _Error_ >err. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **forwardOut**(< _string_ >srcIP, < _integer_ >srcPort, < _string_ >dstIP, < _integer_ >dstPort, < _function_ >callback) - _(void)_ - Open a connection with `srcIP` and `srcPort` as the originating address and port and `dstIP` and `dstPort` as the remote destination address and port. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. -* **forwardOut**(< _string_ >srcIP, < _integer_ >srcPort, < _string_ >dstIP, < _integer_ >dstPort, < _function_ >callback) - _boolean_ - Open a connection with `srcIP` and `srcPort` as the originating address and port and `dstIP` and `dstPort` as the remote destination address and port. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **openssh_forwardInStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _(void)_ - OpenSSH extension that binds to a UNIX domain socket at `socketPath` on the server and forwards incoming connections. `callback` has 1 parameter: < _Error_ >err. -* **sftp**(< _function_ >callback) - _boolean_ - Starts an SFTP session. `callback` has 2 parameters: < _Error_ >err, < _SFTPStream_ >sftp. For methods available on `sftp`, see the [`SFTPStream` client documentation](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md) (except `read()` and `write()` are used instead of `readData()` and `writeData()` respectively, for convenience). Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **openssh_forwardOutStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _(void)_ - OpenSSH extension that opens a connection to a UNIX domain socket at `socketPath` on the server. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. -* **subsys**(< _string_ >subsystem, < _function_ >callback) - _boolean_ - Invokes `subsystem` on the server. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **openssh_noMoreSessions**(< _function_ >callback) - _(void)_ - OpenSSH extension that sends a request to reject any new sessions (e.g. exec, shell, sftp, subsys) for this connection. `callback` has 1 parameter: < _Error_ >err. -* **end**() - _(void)_ - Disconnects the socket. +* **openssh_unforwardInStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _(void)_ - OpenSSH extension that unbinds from a UNIX domain socket at `socketPath` on the server and stops forwarding incoming connections. `callback` has 1 parameter: < _Error_ >err. -* **openssh_noMoreSessions**(< _function_ >callback) - _boolean_ - OpenSSH extension that sends a request to reject any new sessions (e.g. exec, shell, sftp, subsys) for this connection. `callback` has 1 parameter: < _Error_ >err. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **rekey**([< _function_ >callback]) - _(void)_ - Initiates a rekey with the server. If `callback` is supplied, it is added as a one-time handler for the `rekey` event. -* **openssh_forwardInStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _boolean_ - OpenSSH extension that binds to a UNIX domain socket at `socketPath` on the server and forwards incoming connections. `callback` has 1 parameter: < _Error_ >err. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **sftp**(< _function_ >callback) - _(void)_ - Starts an SFTP session. `callback` has 2 parameters: < _Error_ >err, < _SFTP_ >sftp. For methods available on `sftp`, see the [`SFTP` client documentation](https://github.com/mscdex/ssh2/blob/master/SFTP.md). -* **openssh_unforwardInStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _boolean_ - OpenSSH extension that unbinds from a UNIX domain socket at `socketPath` on the server and stops forwarding incoming connections. `callback` has 1 parameter: < _Error_ >err. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **shell**([[< _mixed_ >window,] < _object_ >options]< _function_ >callback) - _(void)_ - Starts an interactive shell session on the server, with an optional `window` object containing pseudo-tty settings (see 'Pseudo-TTY settings'). If `window === false`, then no pseudo-tty is allocated. `options` supports the `x11` and `env` options as described in `exec()`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. -* **openssh_forwardOutStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _boolean_ - OpenSSH extension that opens a connection to a UNIX domain socket at `socketPath` on the server. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **subsys**(< _string_ >subsystem, < _function_ >callback) - _(void)_ - Invokes `subsystem` on the server. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. +* **unforwardIn**(< _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _(void)_ - Unbind from `remoteAddr` on `remotePort` on the server and stop forwarding incoming TCP connections. Until `callback` is called, more connections may still come in. `callback` has 1 parameter: < _Error_ >err. -Server events -------------- +### Server + +#### Server events * **connection**(< _Connection_ >client, < _object_ >info) - A new client has connected. `info` contains the following properties: - * **ip** - _string_ - The remoteAddress of the connection. + * **family** - _string_ - The `remoteFamily` of the connection. * **header** - _object_ - Information about the client's header: @@ -728,7 +1028,7 @@ Server events Example: the identification string `SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2` would be parsed as: -```javascript +```js { identRaw: 'SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2', version: { protocol: '2.0', @@ -737,46 +1037,47 @@ Server events comments: 'Ubuntu-2ubuntu2' } ``` -Server methods --------------- + * **ip** - _string_ - The `remoteAddress` of the connection. -* **(constructor)**(< _object_ >config[, < _function_ >connectionListener]) - Creates and returns a new Server instance. Server instances also have the same methods/properties/events as [`net.Server`](http://nodejs.org/docs/latest/api/net.html#net_class_net_server). `connectionListener` if supplied, is added as a `connection` listener. Valid `config` properties: + * **port** - _integer_ - The `remotePort` of the connection. - * **hostKeys** - _array_ - An array of either Buffers/strings that contain host private keys or objects in the format of `{ key: , passphrase: }` for encrypted private keys. (**Required**) **Default:** (none) +#### Server methods - * **algorithms** - _object_ - This option allows you to explicitly override the default transport layer algorithms used for incoming client connections. Each value must be an array of valid algorithms for that category. The order of the algorithms in the arrays are important, with the most favorable being first. For a list of valid and default algorithm names, please review the documentation for the version of `ssh2-streams` used by this module. Valid keys: +* **(constructor)**(< _object_ >config[, < _function_ >connectionListener]) - Creates and returns a new Server instance. Server instances also have the same methods/properties/events as [`net.Server`](http://nodejs.org/docs/latest/api/net.html#net_class_net_server). `connectionListener` if supplied, is added as a `connection` listener. Valid `config` properties: - * **kex** - _array_ - Key exchange algorithms. + * **algorithms** - _object_ - This option allows you to explicitly override the default transport layer algorithms used for incoming client connections. Each value must be an array of valid algorithms for that category. The order of the algorithms in the arrays are important, with the most favorable being first. For a list of valid and default algorithm names, please review the documentation for the version of `ssh2` used by this module. Valid keys: * **cipher** - _array_ - Ciphers. - * **serverHostKey** - _array_ - Server host key formats. + * **compress** - _array_ - Compression algorithms. * **hmac** - _array_ - (H)MAC algorithms. - * **compress** - _array_ - Compression algorithms. + * **kex** - _array_ - Key exchange algorithms. - * **greeting** - _string_ - A message that is sent to clients immediately upon connection, before handshaking begins. **Note:** Most clients usually ignore this. **Default:** (none) + * **serverHostKey** - _array_ - Server host key formats. * **banner** - _string_ - A message that is sent to clients once, right before authentication begins. **Default:** (none) - * **ident** - _string_ - A custom server software name/version identifier. **Default:** `'ssh2js' + moduleVersion + 'srv'` + * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information. **Default:** (none) + + * **greeting** - _string_ - A message that is sent to clients immediately upon connection, before handshaking begins. **Note:** Most clients usually ignore this. **Default:** (none) * **highWaterMark** - _integer_ - This is the `highWaterMark` to use for the parser stream. **Default:** `32 * 1024` - * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information. **Default:** (none) + * **hostKeys** - _array_ - An array of either Buffers/strings that contain host private keys or objects in the format of `{ key: , passphrase: }` for encrypted private keys. (**Required**) **Default:** (none) + * **ident** - _string_ - A custom server software name/version identifier. **Default:** `'ssh2js' + moduleVersion + 'srv'` -Connection events ------------------ +* **injectSocket**(< _DuplexStream_ >socket) - Injects a bidirectional stream as though it were a TCP socket connection. Additionally, `socket` should include `net.Socket`-like properties to ensure the best compatibility (e.g. `socket.remoteAddress`, `socket.remotePort`, `socket.remoteFamily`). -* **authentication**(< _AuthContext_ >ctx) - The client has requested authentication. `ctx.username` contains the client username, `ctx.method` contains the requested authentication method, and `ctx.accept()` and `ctx.reject([< Array >authMethodsLeft[, < Boolean >isPartialSuccess]])` are used to accept or reject the authentication request respectively. `abort` is emitted if the client aborts the authentication request. Other properties/methods available on `ctx` depends on the `ctx.method` of authentication the client has requested: +#### Connection events - * `password`: +* **authentication**(< _AuthContext_ >ctx) - The client has requested authentication. `ctx.username` contains the client username, `ctx.method` contains the requested authentication method, and `ctx.accept()` and `ctx.reject([< Array >authMethodsLeft[, < Boolean >isPartialSuccess]])` are used to accept or reject the authentication request respectively. `abort` is emitted if the client aborts the authentication request. Other properties/methods available on `ctx` depends on the `ctx.method` of authentication the client has requested: - * **password** - _string_ - This is the password sent by the client. + * `hostbased`: - * `publickey`: + * **blob** - _Buffer_ - This contains the data to be verified that is passed to (along with the signature) `key.verify()` where `key` is a public key parsed with [`parseKey()`](#utilities). * **key** - _object_ - Contains information about the public key sent by the client: @@ -784,145 +1085,177 @@ Connection events * **data** - _Buffer_ - The actual key data. - * **sigAlgo** - _mixed_ - If the value is `undefined`, the client is only checking the validity of the `key`. If the value is a _string_, then this contains the signature algorithm that is passed to [`crypto.createVerify()`](http://nodejs.org/docs/latest/api/crypto.html#crypto_crypto_createverify_algorithm). + * **localHostname** - _string_ - The local hostname provided by the client. - * **blob** - _mixed_ - If the value is `undefined`, the client is only checking the validity of the `key`. If the value is a _Buffer_, then this contains the data that is passed to [`verifier.update()`](http://nodejs.org/docs/latest/api/crypto.html#crypto_verifier_update_data). + * **localUsername** - _string_ - The local username provided by the client. - * **signature** - _mixed_ - If the value is `undefined`, the client is only checking the validity of the `key`. If the value is a _Buffer_, then this contains a signature that is passed to [`verifier.verify()`](http://nodejs.org/docs/latest/api/crypto.html#crypto_verifier_verify_object_signature_signature_format). + * **signature** - _Buffer_ - This contains a signature to be verified that is passed to (along with the blob) `key.verify()` where `key` is a public key parsed with [`parseKey()`](#utilities). * `keyboard-interactive`: + * **prompt**(< _array_ >prompts[, < _string_ >title[, < _string_ >instructions]], < _function_ >callback) - _(void)_ - Send prompts to the client. `prompts` is an array of `{ prompt: 'Prompt text', echo: true }` objects (`prompt` being the prompt text and `echo` indicating whether the client's response to the prompt should be echoed to their display). `callback` is called with `(responses)`, where `responses` is an array of string responses matching up to the `prompts`. + * **submethods** - _array_ - A list of preferred authentication "sub-methods" sent by the client. This may be used to determine what (if any) prompts to send to the client. - * **prompt**(< _array_ >prompts[, < _string_ >title[, < _string_ >instructions]], < _function_ >callback) - _boolean_ - Send prompts to the client. `prompts` is an array of `{ prompt: 'Prompt text', echo: true }` objects (`prompt` being the prompt text and `echo` indicating whether the client's response to the prompt should be echoed to their display). `callback` is called with `(err, responses)`, where `responses` is an array of string responses matching up to the `prompts`. + * `password`: -* **ready**() - Emitted when the client has been successfully authenticated. + * **password** - _string_ - This is the password sent by the client. -* **session**(< _function_ >accept, < _function_ >reject) - Emitted when the client has requested a new session. Sessions are used to start interactive shells, execute commands, request X11 forwarding, etc. `accept()` returns a new _Session_ instance. `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. + * **requestChange**(< _string_ >prompt, < _function_ >callback) - _(void)_ - Sends a password change request to the client. `callback` is called with `(newPassword)`, where `newPassword` is the new password supplied by the client. You may accept, reject, or prompt for another password change after `callback` is called. -* **tcpip**(< _function_ >accept, < _function_ >reject, < _object_ >info) - Emitted when the client has requested an outbound (TCP) connection. `accept()` returns a new _Channel_ instance representing the connection. `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. `info` contains: + * `publickey`: - * **srcIP** - _string_ - Source IP address of outgoing connection. + * **blob** - _mixed_ - If the value is `undefined`, the client is only checking the validity of the `key`. If the value is a _Buffer_, then this contains the data to be verified that is passed to (along with the signature) `key.verify()` where `key` is a public key parsed with [`parseKey()`](#utilities). - * **srcPort** - _string_ - Source port of outgoing connection. + * **key** - _object_ - Contains information about the public key sent by the client: - * **destIP** - _string_ - Destination IP address of outgoing connection. + * **algo** - _string_ - The name of the key algorithm (e.g. `ssh-rsa`). - * **destPort** - _string_ - Destination port of outgoing connection. + * **data** - _Buffer_ - The actual key data. -* **openssh.streamlocal**(< _function_ >accept, < _function_ >reject, < _object_ >info) - Emitted when the client has requested a connection to a UNIX domain socket. `accept()` returns a new _Channel_ instance representing the connection. `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. `info` contains: + * **signature** - _mixed_ - If the value is `undefined`, the client is only checking the validity of the `key`. If the value is a _Buffer_, then this contains a signature to be verified that is passed to (along with the blob) `key.verify()` where `key` is a public key parsed with [`parseKey()`](#utilities). + +* **close**() - The client socket was closed. + +* **end**() - The client socket disconnected. + +* **error**(< _Error_ >err) - An error occurred. + +* **handshake**(< _object_ >negotiated) - Emitted when a handshake has completed (either initial or rekey). `negotiated` contains the negotiated details of the handshake and is of the form: + +```js + // In this particular case `mac` is empty because there is no separate MAC + // because it's integrated into AES in GCM mode + { kex: 'ecdh-sha2-nistp256', + srvHostKey: 'rsa-sha2-512', + cs: { // Client to server algorithms + cipher: 'aes128-gcm', + mac: '', + compress: 'none', + lang: '' + }, + sc: { // Server to client algorithms + cipher: 'aes128-gcm', + mac: '', + compress: 'none', + lang: '' + } + } +``` + +* **openssh.streamlocal**(< _function_ >accept, < _function_ >reject, < _object_ >info) - Emitted when the client has requested a connection to a UNIX domain socket. `accept()` returns a new _Channel_ instance representing the connection. `info` contains: * **socketPath** - _string_ - Destination socket path of outgoing connection. +* **ready**() - Emitted when the client has been successfully authenticated. + +* **rekey**() - Emitted when a rekeying operation has completed (either client or server-initiated). + * **request**(< _mixed_ >accept, < _mixed_ >reject, < _string_ >name, < _object_ >info) - Emitted when the client has sent a global request for `name` (e.g. `tcpip-forward` or `cancel-tcpip-forward`). `accept` and `reject` are functions if the client requested a response. If `bindPort === 0`, you should pass the chosen port to `accept()` so that the client will know what port was bound. `info` contains additional details about the request: - * `tcpip-forward` and `cancel-tcpip-forward`: + * `cancel-tcpip-forward` and `tcpip-forward`: * **bindAddr** - _string_ - The IP address to start/stop binding to. * **bindPort** - _integer_ - The port to start/stop binding to. - * `streamlocal-forward@openssh.com` and `cancel-streamlocal-forward@openssh.com`: + * `cancel-streamlocal-forward@openssh.com` and `streamlocal-forward@openssh.com`: * **socketPath** - _string_ - The socket path to start/stop binding to. -* **rekey**() - Emitted when the client has finished rekeying (either client or server initiated). +* **session**(< _function_ >accept, < _function_ >reject) - Emitted when the client has requested a new session. Sessions are used to start interactive shells, execute commands, request X11 forwarding, etc. `accept()` returns a new _Session_ instance. -* **continue**() - Emitted when more requests/data can be sent to the client (after a `Connection` method returned `false`). +* **tcpip**(< _function_ >accept, < _function_ >reject, < _object_ >info) - Emitted when the client has requested an outbound (TCP) connection. `accept()` returns a new _Channel_ instance representing the connection. `info` contains: -* **error**(< _Error_ >err) - An error occurred. + * **destIP** - _string_ - Destination IP address of outgoing connection. -* **end**() - The client socket disconnected. + * **destPort** - _string_ - Destination port of outgoing connection. -* **close**(< _boolean_ >hadError) - The client socket was closed. `hadError` is set to `true` if this was due to error. + * **srcIP** - _string_ - Source IP address of outgoing connection. -Connection methods ------------------- + * **srcPort** - _string_ - Source port of outgoing connection. -* **end**() - _boolean_ - Closes the client connection. Returns `false` if you should wait for the `continue` event before sending any more traffic. +#### Connection methods -* **x11**(< _string_ >originAddr, < _integer_ >originPort, < _function_ >callback) - _boolean_ - Alert the client of an incoming X11 client connection from `originAddr` on port `originPort`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **end**() - _(void)_ - Closes the client connection. -* **forwardOut**(< _string_ >boundAddr, < _integer_ >boundPort, < _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _boolean_ - Alert the client of an incoming TCP connection on `boundAddr` on port `boundPort` from `remoteAddr` on port `remotePort`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **forwardOut**(< _string_ >boundAddr, < _integer_ >boundPort, < _string_ >remoteAddr, < _integer_ >remotePort, < _function_ >callback) - _(void)_ - Alert the client of an incoming TCP connection on `boundAddr` on port `boundPort` from `remoteAddr` on port `remotePort`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. -* **openssh_forwardOutStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _boolean_ - Alert the client of an incoming UNIX domain socket connection on `socketPath`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **openssh_forwardOutStreamLocal**(< _string_ >socketPath, < _function_ >callback) - _(void)_ - Alert the client of an incoming UNIX domain socket connection on `socketPath`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. -* **rekey**([< _function_ >callback]) - _boolean_ - Initiates a rekeying with the client. If `callback` is supplied, it is added as a one-time handler for the `rekey` event. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **rekey**([< _function_ >callback]) - _(void)_ - Initiates a rekey with the client. If `callback` is supplied, it is added as a one-time handler for the `rekey` event. +* **x11**(< _string_ >originAddr, < _integer_ >originPort, < _function_ >callback) - _(void)_ - Alert the client of an incoming X11 client connection from `originAddr` on port `originPort`. `callback` has 2 parameters: < _Error_ >err, < _Channel_ >stream. -Session events --------------- +#### Session events -* **pty**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client requested allocation of a pseudo-TTY for this session. `accept` and `reject` are functions if the client requested a response and return `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: +* **auth-agent**(< _mixed_ >accept, < _mixed_ >reject) - The client has requested incoming ssh-agent requests be forwarded to them. `accept` and `reject` are functions if the client requested a response. - * **cols** - _integer_ - The number of columns for the pseudo-TTY. +* **close**() - The session was closed. - * **rows** - _integer_ - The number of rows for the pseudo-TTY. +* **env**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client requested an environment variable to be set for this session. `accept` and `reject` are functions if the client requested a response. `info` has these properties: - * **width** - _integer_ - The width of the pseudo-TTY in pixels. + * **key** - _string_ - The environment variable's name. - * **height** - _integer_ - The height of the pseudo-TTY in pixels. + * **value** - _string_ - The environment variable's value. - * **modes** - _object_ - Contains the requested terminal modes of the pseudo-TTY keyed on the mode name with the value being the mode argument. (See the table at the end for valid names). +* **exec**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client has requested execution of a command string. `accept` and `reject` are functions if the client requested a response. `accept()` returns a _Channel_ for the command execution. `info` has these properties: -* **window-change**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client reported a change in window dimensions during this session. `accept` and `reject` are functions if the client requested a response and return `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: + * **command** - _string_ - The command line to be executed. - * **cols** - _integer_ - The new number of columns for the client window. +* **pty**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client requested allocation of a pseudo-TTY for this session. `accept` and `reject` are functions if the client requested a response. `info` has these properties: - * **rows** - _integer_ - The new number of rows for the client window. + * **cols** - _integer_ - The number of columns for the pseudo-TTY. - * **width** - _integer_ - The new width of the client window in pixels. + * **height** - _integer_ - The height of the pseudo-TTY in pixels. - * **height** - _integer_ - The new height of the client window in pixels. + * **modes** - _object_ - Contains the requested terminal modes of the pseudo-TTY keyed on the mode name with the value being the mode argument. (See the table at the end for valid names). -* **x11**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client requested X11 forwarding. `accept` and `reject` are functions if the client requested a response and return `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: + * **rows** - _integer_ - The number of rows for the pseudo-TTY. - * **single** - _boolean_ - `true` if only a single connection should be forwarded. + * **width** - _integer_ - The width of the pseudo-TTY in pixels. - * **protocol** - _string_ - The name of the X11 authentication method used (e.g. `MIT-MAGIC-COOKIE-1`). +* **sftp**(< _mixed_ >accept, < _mixed_ >reject) - The client has requested the SFTP subsystem. `accept` and `reject` are functions if the client requested a response. `accept()` returns an _SFTP_ instance in server mode (see the [`SFTP` documentation](https://github.com/mscdex/ssh2/blob/master/SFTP.md) for details). `info` has these properties: - * **cookie** - _string_ - The X11 authentication cookie encoded in hexadecimal. +* **shell**(< _mixed_ >accept, < _mixed_ >reject) - The client has requested an interactive shell. `accept` and `reject` are functions if the client requested a response. `accept()` returns a _Channel_ for the interactive shell. - * **screen** - _integer_ - The screen number to forward X11 connections for. +* **signal**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client has sent a signal. `accept` and `reject` are functions if the client requested a response. `info` has these properties: -* **env**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client requested an environment variable to be set for this session. `accept` and `reject` are functions if the client requested a response and return `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: + * **name** - _string_ - The signal name (e.g. `SIGUSR1`). - * **key** - _string_ - The environment variable's name. +* **subsystem**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client has requested an arbitrary subsystem. `accept` and `reject` are functions if the client requested a response. `accept()` returns a _Channel_ for the subsystem. `info` has these properties: - * **value** - _string_ - The environment variable's value. + * **name** - _string_ - The name of the subsystem. -* **signal**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client has sent a signal. `accept` and `reject` are functions if the client requested a response and return `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: +* **window-change**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client reported a change in window dimensions during this session. `accept` and `reject` are functions if the client requested a response. `info` has these properties: - * **name** - _string_ - The signal name (e.g. `SIGUSR1`). - -* **auth-agent**(< _mixed_ >accept, < _mixed_ >reject) - The client has requested incoming ssh-agent requests be forwarded to them. `accept` and `reject` are functions if the client requested a response and return `false` if you should wait for the `continue` event before sending any more traffic. + * **cols** - _integer_ - The new number of columns for the client window. -* **shell**(< _mixed_ >accept, < _mixed_ >reject) - The client has requested an interactive shell. `accept` and `reject` are functions if the client requested a response. `accept()` returns a _Channel_ for the interactive shell. `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. + * **height** - _integer_ - The new height of the client window in pixels. -* **exec**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client has requested execution of a command string. `accept` and `reject` are functions if the client requested a response. `accept()` returns a _Channel_ for the command execution. `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: + * **rows** - _integer_ - The new number of rows for the client window. - * **command** - _string_ - The command line to be executed. + * **width** - _integer_ - The new width of the client window in pixels. -* **sftp**(< _mixed_ >accept, < _mixed_ >reject) - The client has requested the SFTP subsystem. `accept` and `reject` are functions if the client requested a response. `accept()` returns an _SFTPStream_ in server mode (see the [`SFTPStream` documentation](https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md) for details). `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: +* **x11**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client requested X11 forwarding. `accept` and `reject` are functions if the client requested a response. `info` has these properties: -* **subsystem**(< _mixed_ >accept, < _mixed_ >reject, < _object_ >info) - The client has requested an arbitrary subsystem. `accept` and `reject` are functions if the client requested a response. `accept()` returns a _Channel_ for the subsystem. `reject()` Returns `false` if you should wait for the `continue` event before sending any more traffic. `info` has these properties: + * **cookie** - _string_ - The X11 authentication cookie encoded in hexadecimal. - * **name** - _string_ - The name of the subsystem. + * **protocol** - _string_ - The name of the X11 authentication method used (e.g. `MIT-MAGIC-COOKIE-1`). -* **close**() - The session was closed. + * **screen** - _integer_ - The screen number to forward X11 connections for. + * **single** - _boolean_ - `true` if only a single connection should be forwarded. -Channel -------- +### Channel -This is a normal **streams2** Duplex Stream, with the following changes: +This is a normal **streams2** Duplex Stream (used both by clients and servers), with the following changes: * A boolean property `allowHalfOpen` exists and behaves similarly to the property of the same name for `net.Socket`. When the stream's end() is called, if `allowHalfOpen` is `true`, only EOF will be sent (the server can still send data if they have not already sent EOF). The default value for this property is `true`. * A `close` event is emitted once the channel is completely closed on both the client and server. -* Client-only: - +* Client-specific: * For exec(): @@ -930,39 +1263,40 @@ This is a normal **streams2** Duplex Stream, with the following changes: * If there was an `exit` event, the `close` event will be passed the same arguments for convenience. - * For shell() and exec(): + * A `stderr` property contains a Readable stream that represents output from stderr. + + * For exec() and shell(): * The readable side represents stdout and the writable side represents stdin. - * A `stderr` property contains a Readable stream that represents output from stderr. + * **setWindow**(< _integer_ >rows, < _integer_ >cols, < _integer_ >height, < _integer_ >width) - _(void)_ - Lets the server know that the local terminal window has been resized. The meaning of these arguments are described in the 'Pseudo-TTY settings' section. - * **signal**(< _string_ >signalName) - _boolean_ - Sends a POSIX signal to the current process on the server. Valid signal names are: 'ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT', 'KILL', 'PIPE', 'QUIT', 'SEGV', 'TERM', 'USR1', and 'USR2'. Some server implementations may ignore this request if they do not support signals. Note: If you are trying to send SIGINT and you find `signal()` doesn't work, try writing `'\x03'` to the Channel stream instead. Returns `false` if you should wait for the `continue` event before sending any more traffic. + * **signal**(< _string_ >signalName) - _(void)_ - Sends a POSIX signal to the current process on the server. Valid signal names are: 'ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT', 'KILL', 'PIPE', 'QUIT', 'SEGV', 'TERM', 'USR1', and 'USR2'. Some server implementations may ignore this request if they do not support signals. Note: If you are trying to send SIGINT and you find `signal()` doesn't work, try writing `'\x03'` to the Channel stream instead. - * **setWindow**(< _integer_ >rows, < _integer_ >cols, < _integer_ >height, < _integer_ >width) - _boolean_ - Lets the server know that the local terminal window has been resized. The meaning of these arguments are described in the 'Pseudo-TTY settings' section. Returns `false` if you should wait for the `continue` event before sending any more traffic. -* Server-only: +* Server-specific: * For exec-enabled channel instances there is an additional method available that may be called right before you close the channel. It has two different signatures: - * **exit**(< _integer_ >exitCode) - _boolean_ - Sends an exit status code to the client. Returns `false` if you should wait for the `continue` event before sending any more traffic. + * **exit**(< _integer_ >exitCode) - _(void)_ - Sends an exit status code to the client. - * **exit**(< _string_ >signalName[, < _boolean_ >coreDumped[, < _string_ >errorMsg]]) - _boolean_ - Sends an exit status code to the client. Returns `false` if you should wait for the `continue` event before sending any more traffic. + * **exit**(< _string_ >signalName[, < _boolean_ >coreDumped[, < _string_ >errorMsg]]) - _(void)_ - Sends an exit status code to the client. * For exec and shell-enabled channel instances, `channel.stderr` is a writable stream. +### Pseudo-TTY settings -Pseudo-TTY settings -------------------- +* **cols** - < _integer_ > - Number of columns. **Default:** `80` -* **rows** - < _integer_ > - Number of rows **Default:** `24` +* **height** - < _integer_ > - Height in pixels. **Default:** `480` -* **cols** - < _integer_ > - Number of columns **Default:** `80` +* **modes** - < _object_ > - An object containing [Terminal Modes](#terminal-modes) as keys, with each value set to each mode argument. **Default:** `null` -* **height** - < _integer_ > - Height in pixels **Default:** `480` +* **rows** - < _integer_ > - Number of rows. **Default:** `24` -* **width** - < _integer_ > - Width in pixels **Default:** `640` +* **term** - < _string_ > - The value to use for $TERM. **Default:** `'vt100'` -* **term** - < _string_ > - The value to use for $TERM **Default:** `'vt100'` +* **width** - < _integer_ > - Width in pixels. **Default:** `640` `rows` and `cols` override `width` and `height` when `rows` and `cols` are non-zero. @@ -970,84 +1304,170 @@ Pixel dimensions refer to the drawable area of the window. Zero dimension parameters are ignored. +### Terminal modes + +Name | Description +-------------- | ------------ +CS7 | 7 bit mode. +CS8 | 8 bit mode. +ECHOCTL | Echo control characters as ^(Char). +ECHO | Enable echoing. +ECHOE | Visually erase chars. +ECHOKE | Visual erase for line kill. +ECHOK | Kill character discards current line. +ECHONL | Echo NL even if ECHO is off. +ICANON | Canonicalize input lines. +ICRNL | Map CR to NL on input. +IEXTEN | Enable extensions. +IGNCR | Ignore CR on input. +IGNPAR | The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE, and 1 if it is TRUE. +IMAXBEL | Ring bell on input queue full. +INLCR | Map NL into CR on input. +INPCK | Enable checking of parity errors. +ISIG | Enable signals INTR, QUIT, [D]SUSP. +ISTRIP | Strip 8th bit off characters. +IUCLC | Translate uppercase characters to lowercase. +IXANY | Any char will restart after stop. +IXOFF | Enable input flow control. +IXON | Enable output flow control. +NOFLSH | Don't flush after interrupt. +OCRNL | Translate carriage return to newline (output). +OLCUC | Convert lowercase to uppercase. +ONLCR | Map NL to CR-NL. +ONLRET | Newline performs a carriage return (output). +ONOCR | Translate newline to carriage return-newline (output). +OPOST | Enable output processing. +PARENB | Parity enable. +PARMRK | Mark parity and framing errors. +PARODD | Odd parity, else even. +PENDIN | Retype pending input. +TOSTOP | Stop background jobs from output. +TTY_OP_ISPEED | Specifies the input baud rate in bits per second. +TTY_OP_OSPEED | Specifies the output baud rate in bits per second. +VDISCARD | Toggles the flushing of terminal output. +VDSUSP | Another suspend character. +VEOF | End-of-file character (sends EOF from the terminal). +VEOL2 | Additional end-of-line character. +VEOL | End-of-line character in addition to carriage return and/or linefeed. +VERASE | Erase the character to left of the cursor. +VFLUSH | Character to flush output. +VINTR | Interrupt character; 255 if none. Similarly for the other characters. Not all of these characters are supported on all systems. +VKILL | Kill the current input line. +VLNEXT | Enter the next character typed literally, even if it is a special character +VQUIT | The quit character (sends SIGQUIT signal on POSIX systems). +VREPRINT | Reprints the current input line. +VSTART | Continues paused output (normally control-Q). +VSTATUS | Prints system status line (load, command, pid, etc). +VSTOP | Pauses output (normally control-S). +VSUSP | Suspends the current program. +VSWTCH | Switch to a different shell layer. +VWERASE | Erases a word left of cursor. +XCASE | Enable input and output of uppercase characters by preceding their lowercase equivalents with "\". + +### HTTPAgent + +#### HTTPAgent methods + +* **(constructor)**(< _object_ >sshConfig[, < _object_ >agentConfig]) - Creates and returns a new `http.Agent` instance used to tunnel an HTTP connection over SSH. `sshConfig` is what is passed to `client.connect()` and `agentOptions` is passed to the `http.Agent` constructor. + +### HTTPSAgent + +#### HTTPSAgent methods + +* **(constructor)**(< _object_ >sshConfig[, < _object_ >agentConfig]) - Creates and returns a new `https.Agent` instance used to tunnel an HTTP connection over SSH. `sshConfig` is what is passed to `client.connect()` and `agentOptions` is passed to the `https.Agent` constructor. + +### Utilities + +* **parseKey**(< _mixed_ >keyData[, < _string_ >passphrase]) - _mixed_ - Parses a private/public key in OpenSSH, RFC4716, or PPK format. For encrypted private keys, the key will be decrypted with the given `passphrase`. `keyData` can be a _Buffer_ or _string_ value containing the key contents. The returned value will be an array of objects (currently in the case of modern OpenSSH keys) or an object with these properties and methods: + + * **comment** - _string_ - The comment for the key + + * **equals**(< _mixed_ >otherKey) - _boolean_ - This returns `true` if `otherKey` (a parsed or parseable key) is the same as this key. This method does not compare the keys' comments + + * **getPrivatePEM**() - _string_ - This returns the PEM version of a private key + + * **getPublicPEM**() - _string_ - This returns the PEM version of a public key (for either public key or derived from a private key) + + * **getPublicSSH**() - _string_ - This returns the SSH version of a public key (for either public key or derived from a private key) + + * **isPrivateKey**() - _boolean_ - This returns `true` if the key is a private key or not + + * **sign**(< _mixed_ >data) - _mixed_ - This signs the given `data` using this key and returns a _Buffer_ containing the signature on success. On failure, an _Error_ will be returned. `data` can be anything accepted by node's [`sign.update()`](https://nodejs.org/docs/latest/api/crypto.html#crypto_sign_update_data_inputencoding). + + * **type** - _string_ - The full key type (e.g. `'ssh-rsa'`) + + * **verify**(< _mixed_ >data, < _Buffer_ >signature) - _mixed_ - This verifies a `signature` of the given `data` using this key and returns `true` if the signature could be verified. On failure, either `false` will be returned or an _Error_ will be returned upon a more critical failure. `data` can be anything accepted by node's [`verify.update()`](https://nodejs.org/docs/latest/api/crypto.html#crypto_verify_update_data_inputencoding). + +* **sftp.OPEN_MODE** - [`OPEN_MODE`](https://github.com/mscdex/ssh2/blob/master/SFTP.md#useful-standalone-data-structures) + +* **sftp.STATUS_CODE** - [`STATUS_CODE`](https://github.com/mscdex/ssh2/blob/master/SFTP.md#useful-standalone-data-structures) + +* **sftp.flagsToString** - [`flagsToString()`](https://github.com/mscdex/ssh2/blob/master/SFTP.md#useful-standalone-methods) + +* **sftp.stringToFlags** - [`stringToFlags()`](https://github.com/mscdex/ssh2/blob/master/SFTP.md#useful-standalone-methods) + +### AgentProtocol + +#### AgentProtocol events + +* **identities**(< _opaque_ >request) - **(Server mode only)** The client has requested a list of public keys stored in the agent. Use `failureReply()` or `getIdentitiesReply()` to reply appropriately. + +* **sign**(< _opaque_ >request, < _mixed_ >pubKey, < _Buffer_ >data, < _object_ >options) - **(Server mode only)** The client has requested `data` to be signed using the key identified by `pubKey`. Use `failureReply()` or `signReply()` to reply appropriately. `options` may contain any of: + + * **hash** - _string_ - The explicitly desired hash to use when computing the signature. Currently if set, this may be either `'sha256'` or `'sha512'` for RSA keys. + +#### AgentProtocol methods + +* **(constructor)**(< _boolean_ >isClient) - Creates and returns a new AgentProtocol instance. `isClient` determines whether the instance operates in client or server mode. + +* **failureReply**(< _opaque_ >request) - _(void)_ - **(Server mode only)** Replies to the given `request` with a failure response. + +* **getIdentities**(< _function_ >callback) - _(void)_ - **(Client mode only)** Requests a list of public keys from the agent. `callback` is passed `(err, keys)` where `keys` is a possible array of public keys for authentication. + +* **getIdentitiesReply**(< _opaque_ >request, < _array_ >keys) - _(void)_ - **(Server mode only)** Responds to a identities list `request` with the given array of keys in `keys`. + +* **sign**(< _mixed_ >pubKey, < _Buffer_ >data, < _object_ >options, < _function_ >callback) - _(void)_ - **(Client mode only)** Requests that the agent sign `data` using the key identified by `pubKey`. `pubKey` can be any parsed (using `utils.parseKey()`) or parseable key value. `callback` is passed `(err, signature)` where `signature` is a possible _Buffer_ containing the signature for the `data`. `options` may contain any of: + + * **hash** - _string_ - The explicitly desired hash to use when computing the signature. Currently if set, this may be either `'sha256'` or `'sha512'` for RSA keys. + +* **signReply**(< _opaque_ >request, < _Buffer_ >signature) - _(void)_ - **(Server mode only)** Responds to a sign `request` with the given signature in `signature`. + +### BaseAgent + +In order to create a custom agent, your class *must*: + + * Extend `BaseAgent` + * Call `super()` in its constructor + * Implement *at least* the following methods: + +* **getIdentities**(< _function_ >callback) - _(void)_ - Passes `(err, keys)` to `callback` where `keys` is a possible array of public keys for authentication. + +* **sign**(< _mixed_ >pubKey, < _Buffer_ >data, < _object_ >options, < _function_ >callback) - _(void)_ - Signs `data` using the key identified by `pubKey`. `pubKey` can be any parsed (using `utils.parseKey()`) or parseable key value. `callback` should be passed `(err, signature)` where `signature` is a possible _Buffer_ containing the signature for the `data`. `options` may contain any of: + + * **hash** - _string_ - The explicitly desired hash to use when computing the signature. Currently if set, this may be either `'sha256'` or `'sha512'` for RSA keys. + +Additionally your class may implement the following method in order to support agent forwarding on the client: + +* **getStream**(< _function_ >callback) - _(void)_ - Passes `(err, stream)` to `callback` where `stream` is a possible Duplex stream to be used to communicate with your agent. You will probably want to utilize `AgentProtocol` as agent forwarding is an OpenSSH feature, so the `stream` needs to be able to transmit/receive OpenSSH agent protocol packets. + +### createAgent + +* **createAgent**(< _string_ >agentValue) - _(Agent)_ - Creates and returns a new agent instance using the same logic as the `Client`'s `agent` configuration option: if the platform is Windows and it's the value "pageant", it creates a `PageantAgent`, otherwise if it's not a path to a Windows pipe it creates a `CygwinAgent`. In all other cases, it creates an `OpenSSHAgent`. + +### CygwinAgent + +#### CygwinAgent methods + +* **(constructor)**(< _string_ >socketPath) - Communicates with an agent listening at `socketPath` in a Cygwin environment. + +### OpenSSHAgent + +#### OpenSSHAgent methods + +* **(constructor)**(< _string_ >socketPath) - Communicates with an OpenSSH agent listening on the UNIX socket at `socketPath`. + +### PageantAgent + +#### PageantAgent methods -Terminal modes --------------- - -

-Name           Description
-------------------------------------------------------------
-VINTR          Interrupt character; 255 if none.  Similarly
-               for the other characters.  Not all of these
-               characters are supported on all systems.
-VQUIT          The quit character (sends SIGQUIT signal on
-               POSIX systems).
-VERASE         Erase the character to left of the cursor.
-VKILL          Kill the current input line.
-VEOF           End-of-file character (sends EOF from the
-               terminal).
-VEOL           End-of-line character in addition to
-               carriage return and/or linefeed.
-VEOL2          Additional end-of-line character.
-VSTART         Continues paused output (normally
-               control-Q).
-VSTOP          Pauses output (normally control-S).
-VSUSP          Suspends the current program.
-VDSUSP         Another suspend character.
-VREPRINT       Reprints the current input line.
-VWERASE        Erases a word left of cursor.
-VLNEXT         Enter the next character typed literally,
-               even if it is a special character
-VFLUSH         Character to flush output.
-VSWTCH         Switch to a different shell layer.
-VSTATUS        Prints system status line (load, command,
-               pid, etc).
-VDISCARD       Toggles the flushing of terminal output.
-IGNPAR         The ignore parity flag.  The parameter
-               SHOULD be 0 if this flag is FALSE,
-               and 1 if it is TRUE.
-PARMRK         Mark parity and framing errors.
-INPCK          Enable checking of parity errors.
-ISTRIP         Strip 8th bit off characters.
-INLCR          Map NL into CR on input.
-IGNCR          Ignore CR on input.
-ICRNL          Map CR to NL on input.
-IUCLC          Translate uppercase characters to
-               lowercase.
-IXON           Enable output flow control.
-IXANY          Any char will restart after stop.
-IXOFF          Enable input flow control.
-IMAXBEL        Ring bell on input queue full.
-ISIG           Enable signals INTR, QUIT, [D]SUSP.
-ICANON         Canonicalize input lines.
-XCASE          Enable input and output of uppercase
-               characters by preceding their lowercase
-               equivalents with "\".
-ECHO           Enable echoing.
-ECHOE          Visually erase chars.
-ECHOK          Kill character discards current line.
-ECHONL         Echo NL even if ECHO is off.
-NOFLSH         Don't flush after interrupt.
-TOSTOP         Stop background jobs from output.
-IEXTEN         Enable extensions.
-ECHOCTL        Echo control characters as ^(Char).
-ECHOKE         Visual erase for line kill.
-PENDIN         Retype pending input.
-OPOST          Enable output processing.
-OLCUC          Convert lowercase to uppercase.
-ONLCR          Map NL to CR-NL.
-OCRNL          Translate carriage return to newline
-               (output).
-ONOCR          Translate newline to carriage
-               return-newline (output).
-ONLRET         Newline performs a carriage return
-               (output).
-CS7            7 bit mode.
-CS8            8 bit mode.
-PARENB         Parity enable.
-PARODD         Odd parity, else even.
-TTY_OP_ISPEED  Specifies the input baud rate in
-               bits per second.
-TTY_OP_OSPEED  Specifies the output baud rate in
-               bits per second.
-
+* **(constructor)**() - Creates a new agent instance for communicating with a running Pageant agent process. diff --git a/reverse_engineering/node_modules/ssh2-streams/SFTPStream.md b/reverse_engineering/node_modules/ssh2/SFTP.md similarity index 50% rename from reverse_engineering/node_modules/ssh2-streams/SFTPStream.md rename to reverse_engineering/node_modules/ssh2/SFTP.md index f44e5bd..60c33ba 100644 --- a/reverse_engineering/node_modules/ssh2-streams/SFTPStream.md +++ b/reverse_engineering/node_modules/ssh2/SFTP.md @@ -1,5 +1,5 @@ -SFTPStream events ------------------ +SFTP events +----------- **Client/Server events** @@ -11,9 +11,9 @@ _Responses to these client requests are sent using one of the methods listed fur * **OPEN**(< _integer_ >reqID, < _string_ >filename, < _integer_ >flags, < _ATTRS_ >attrs) - `flags` is a bitfield containing any of the flags defined in - `SFTPStream.OPEN_MODE`. Use the static method `SFTPStream.flagsToString()` - to convert the value to a mode string to be used by `fs.open()` (e.g. `'r'`). + `flags` is a bitfield containing any of the flags defined in `OPEN_MODE`. + Use the static method `flagsToString()` to convert the value to a mode + string to be used by `fs.open()` (e.g. `'r'`). Respond using one of the following: @@ -168,10 +168,10 @@ _Responses to these client requests are sent using one of the methods listed fur * `status()` - Use this to indicate success/failure of the symlink creation. -SFTPStream static constants ---------------------------- +Useful standalone data structures +--------------------------------- -* **SFTPStream.STATUS_CODE** - _object_ - Contains the various status codes (for use especially with `status()`): +* **STATUS_CODE** - _object_ - Contains the various status codes (for use especially with `status()`): * `OK` @@ -187,7 +187,7 @@ SFTPStream static constants * `OP_UNSUPPORTED` -* **SFTPStream.OPEN_MODE** - _object_ - Contains the various open file flags: +* **OPEN_MODE** - _object_ - Contains the various open file flags: * `READ` @@ -202,23 +202,21 @@ SFTPStream static constants * `EXCL` -SFTPStream static methods +Useful standalone methods ------------------------- -* **SFTPStream.stringToFlags**(< _string_ >flagsStr) - _integer_ - Converts string flags (e.g. `'r'`, `'a+'`, etc.) to the appropriate `SFTPStream.OPEN_MODE` flag mask. Returns `null` if conversion failed. +* **stringToFlags**(< _string_ >flagsStr) - _integer_ - Converts string flags (e.g. `'r'`, `'a+'`, etc.) to the appropriate `OPEN_MODE` flag mask. Returns `null` if conversion failed. -* **SFTPStream.flagsToString**(< _integer_ >flagsMask) - _string_ - Converts flag mask (e.g. number containing `SFTPStream.OPEN_MODE` values) to the appropriate string value. Returns `null` if conversion failed. +* **flagsToString**(< _integer_ >flagsMask) - _string_ - Converts flag mask (e.g. number containing `OPEN_MODE` values) to the appropriate string value. Returns `null` if conversion failed. -SFTPStream methods ------------------- +SFTP methods +------------ -* **(constructor)**(< _object_ >config[, < _string_ >remoteIdentRaw]) - Creates and returns a new SFTPStream instance. SFTPStream instances are Duplex streams. `remoteIdentRaw` can be the raw SSH identification string of the remote party. This is used to change internal behavior based on particular SFTP implementations. `config` can contain: +* **(constructor)**(< _object_ >config[, < _string_ >remoteIdentRaw]) - Creates and returns a new SFTP instance. `remoteIdentRaw` can be the raw SSH identification string of the remote party. This is used to change internal behavior based on particular SFTP implementations. `config` can contain: * **server** - _boolean_ - Set to `true` to create an instance in server mode. **Default:** `false` - * **highWaterMark** - _integer_ - This is the `highWaterMark` to use for the stream. **Default:** `32 * 1024` - * **debug** - _function_ - Set this to a function that receives a single string argument to get detailed (local) debug information. **Default:** (none) @@ -260,7 +258,7 @@ SFTPStream methods `options` can include `start` and `end` values to read a range of bytes from the file instead of the entire file. Both `start` and `end` are inclusive and start at 0. The `encoding` can be `'utf8'`, `'ascii'`, or `'base64'`. - If `autoClose` is false, then the file handle won't be closed, even if there's an error. It is your responsiblity to close it and make sure there's no file handle leak. If `autoClose` is set to true (default behavior), on `error` or `end` the file handle will be closed automatically. + If `autoClose` is false, then the file handle won't be closed, even if there's an error. It is your responsibility to close it and make sure there's no file handle leak. If `autoClose` is set to true (default behavior), on `error` or `end` the file handle will be closed automatically. An example to read the last 10 bytes of a file which is 100 bytes long: @@ -283,74 +281,74 @@ SFTPStream methods If 'autoClose' is set to false and you pipe to this stream, this stream will not automatically close after there is no more data upstream -- allowing future pipes and/or manual writes. -* **open**(< _string_ >filename, < _string_ >flags, [< _mixed_ >attrs_mode, ]< _function_ >callback) - _boolean_ - Opens a file `filename` with `flags` with optional _ATTRS_ object or file mode `attrs_mode`. `flags` is any of the flags supported by `fs.open` (except sync flag). Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _Buffer_ >handle. +* **open**(< _string_ >filename, < _string_ >flags, [< _mixed_ >attrs_mode, ]< _function_ >callback) - _(void)_ - Opens a file `filename` with `flags` with optional _ATTRS_ object or file mode `attrs_mode`. `flags` is any of the flags supported by `fs.open` (except sync flag). `callback` has 2 parameters: < _Error_ >err, < _Buffer_ >handle. -* **close**(< _Buffer_ >handle, < _function_ >callback) - _boolean_ - Closes the resource associated with `handle` given by open() or opendir(). Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **close**(< _Buffer_ >handle, < _function_ >callback) - _(void)_ - Closes the resource associated with `handle` given by open() or opendir(). `callback` has 1 parameter: < _Error_ >err. -* **readData**(< _Buffer_ >handle, < _Buffer_ >buffer, < _integer_ >offset, < _integer_ >length, < _integer_ >position, < _function_ >callback) - _boolean_ - Reads `length` bytes from the resource associated with `handle` starting at `position` and stores the bytes in `buffer` starting at `offset`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 4 parameters: < _Error_ >err, < _integer_ >bytesRead, < _Buffer_ >buffer (offset adjusted), < _integer_ >position. +* **read**(< _Buffer_ >handle, < _Buffer_ >buffer, < _integer_ >offset, < _integer_ >length, < _integer_ >position, < _function_ >callback) - _(void)_ - Reads `length` bytes from the resource associated with `handle` starting at `position` and stores the bytes in `buffer` starting at `offset`. `callback` has 4 parameters: < _Error_ >err, < _integer_ >bytesRead, < _Buffer_ >buffer (offset adjusted), < _integer_ >position. -* **writeData**(< _Buffer_ >handle, < _Buffer_ >buffer, < _integer_ >offset, < _integer_ >length, < _integer_ >position, < _function_ >callback) - _boolean_ - Writes `length` bytes from `buffer` starting at `offset` to the resource associated with `handle` starting at `position`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **write**(< _Buffer_ >handle, < _Buffer_ >buffer, < _integer_ >offset, < _integer_ >length, < _integer_ >position, < _function_ >callback) - _(void)_ - Writes `length` bytes from `buffer` starting at `offset` to the resource associated with `handle` starting at `position`. `callback` has 1 parameter: < _Error_ >err. -* **fstat**(< _Buffer_ >handle, < _function_ >callback) - _boolean_ - Retrieves attributes for the resource associated with `handle`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _Stats_ >stats. +* **fstat**(< _Buffer_ >handle, < _function_ >callback) - _(void)_ - Retrieves attributes for the resource associated with `handle`. `callback` has 2 parameters: < _Error_ >err, < _Stats_ >stats. -* **fsetstat**(< _Buffer_ >handle, < _ATTRS_ >attributes, < _function_ >callback) - _boolean_ - Sets the attributes defined in `attributes` for the resource associated with `handle`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **fsetstat**(< _Buffer_ >handle, < _ATTRS_ >attributes, < _function_ >callback) - _(void)_ - Sets the attributes defined in `attributes` for the resource associated with `handle`. `callback` has 1 parameter: < _Error_ >err. -* **futimes**(< _Buffer_ >handle, < _mixed_ >atime, < _mixed_ >mtime, < _function_ >callback) - _boolean_ - Sets the access time and modified time for the resource associated with `handle`. `atime` and `mtime` can be Date instances or UNIX timestamps. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **futimes**(< _Buffer_ >handle, < _mixed_ >atime, < _mixed_ >mtime, < _function_ >callback) - _(void)_ - Sets the access time and modified time for the resource associated with `handle`. `atime` and `mtime` can be Date instances or UNIX timestamps. `callback` has 1 parameter: < _Error_ >err. -* **fchown**(< _Buffer_ >handle, < _integer_ >uid, < _integer_ >gid, < _function_ >callback) - _boolean_ - Sets the owner for the resource associated with `handle`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **fchown**(< _Buffer_ >handle, < _integer_ >uid, < _integer_ >gid, < _function_ >callback) - _(void)_ - Sets the owner for the resource associated with `handle`. `callback` has 1 parameter: < _Error_ >err. -* **fchmod**(< _Buffer_ >handle, < _mixed_ >mode, < _function_ >callback) - _boolean_ - Sets the mode for the resource associated with `handle`. `mode` can be an integer or a string containing an octal number. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **fchmod**(< _Buffer_ >handle, < _mixed_ >mode, < _function_ >callback) - _(void)_ - Sets the mode for the resource associated with `handle`. `mode` can be an integer or a string containing an octal number. `callback` has 1 parameter: < _Error_ >err. -* **opendir**(< _string_ >path, < _function_ >callback) - _boolean_ - Opens a directory `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _Buffer_ >handle. +* **opendir**(< _string_ >path, < _function_ >callback) - _(void)_ - Opens a directory `path`. `callback` has 2 parameters: < _Error_ >err, < _Buffer_ >handle. -* **readdir**(< _mixed_ >location, < _function_ >callback) - _boolean_ - Retrieves a directory listing. `location` can either be a _Buffer_ containing a valid directory handle from opendir() or a _string_ containing the path to a directory. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _mixed_ >list. `list` is an _Array_ of `{ filename: 'foo', longname: '....', attrs: {...} }` style objects (attrs is of type _ATTR_). If `location` is a directory handle, this function may need to be called multiple times until `list` is boolean false, which indicates that no more directory entries are available for that directory handle. +* **readdir**(< _mixed_ >location, < _function_ >callback) - _(void)_ - Retrieves a directory listing. `location` can either be a _Buffer_ containing a valid directory handle from opendir() or a _string_ containing the path to a directory. `callback` has 2 parameters: < _Error_ >err, < _mixed_ >list. `list` is an _Array_ of `{ filename: 'foo', longname: '....', attrs: {...} }` style objects (attrs is of type _ATTR_). If `location` is a directory handle, this function may need to be called multiple times until `list` is boolean false, which indicates that no more directory entries are available for that directory handle. -* **unlink**(< _string_ >path, < _function_ >callback) - _boolean_ - Removes the file/symlink at `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **unlink**(< _string_ >path, < _function_ >callback) - _(void)_ - Removes the file/symlink at `path`. `callback` has 1 parameter: < _Error_ >err. -* **rename**(< _string_ >srcPath, < _string_ >destPath, < _function_ >callback) - _boolean_ - Renames/moves `srcPath` to `destPath`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **rename**(< _string_ >srcPath, < _string_ >destPath, < _function_ >callback) - _(void)_ - Renames/moves `srcPath` to `destPath`. `callback` has 1 parameter: < _Error_ >err. -* **mkdir**(< _string_ >path, [< _ATTRS_ >attributes, ]< _function_ >callback) - _boolean_ - Creates a new directory `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **mkdir**(< _string_ >path, [< _ATTRS_ >attributes, ]< _function_ >callback) - _(void)_ - Creates a new directory `path`. `callback` has 1 parameter: < _Error_ >err. -* **rmdir**(< _string_ >path, < _function_ >callback) - _boolean_ - Removes the directory at `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **rmdir**(< _string_ >path, < _function_ >callback) - _(void)_ - Removes the directory at `path`. `callback` has 1 parameter: < _Error_ >err. -* **stat**(< _string_ >path, < _function_ >callback) - _boolean_ - Retrieves attributes for `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameter: < _Error_ >err, < _Stats_ >stats. +* **stat**(< _string_ >path, < _function_ >callback) - _(void)_ - Retrieves attributes for `path`. `callback` has 2 parameter: < _Error_ >err, < _Stats_ >stats. -* **lstat**(< _string_ >path, < _function_ >callback) - _boolean_ - Retrieves attributes for `path`. If `path` is a symlink, the link itself is stat'ed instead of the resource it refers to. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _Stats_ >stats. +* **lstat**(< _string_ >path, < _function_ >callback) - _(void)_ - Retrieves attributes for `path`. If `path` is a symlink, the link itself is stat'ed instead of the resource it refers to. `callback` has 2 parameters: < _Error_ >err, < _Stats_ >stats. -* **setstat**(< _string_ >path, < _ATTRS_ >attributes, < _function_ >callback) - _boolean_ - Sets the attributes defined in `attributes` for `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **setstat**(< _string_ >path, < _ATTRS_ >attributes, < _function_ >callback) - _(void)_ - Sets the attributes defined in `attributes` for `path`. `callback` has 1 parameter: < _Error_ >err. -* **utimes**(< _string_ >path, < _mixed_ >atime, < _mixed_ >mtime, < _function_ >callback) - _boolean_ - Sets the access time and modified time for `path`. `atime` and `mtime` can be Date instances or UNIX timestamps. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **utimes**(< _string_ >path, < _mixed_ >atime, < _mixed_ >mtime, < _function_ >callback) - _(void)_ - Sets the access time and modified time for `path`. `atime` and `mtime` can be Date instances or UNIX timestamps. `callback` has 1 parameter: < _Error_ >err. -* **chown**(< _string_ >path, < _integer_ >uid, < _integer_ >gid, < _function_ >callback) - _boolean_ - Sets the owner for `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **chown**(< _string_ >path, < _integer_ >uid, < _integer_ >gid, < _function_ >callback) - _(void)_ - Sets the owner for `path`. `callback` has 1 parameter: < _Error_ >err. -* **chmod**(< _string_ >path, < _mixed_ >mode, < _function_ >callback) - _boolean_ - Sets the mode for `path`. `mode` can be an integer or a string containing an octal number. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **chmod**(< _string_ >path, < _mixed_ >mode, < _function_ >callback) - _(void)_ - Sets the mode for `path`. `mode` can be an integer or a string containing an octal number. `callback` has 1 parameter: < _Error_ >err. -* **readlink**(< _string_ >path, < _function_ >callback) - _boolean_ - Retrieves the target for a symlink at `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _string_ >target. +* **readlink**(< _string_ >path, < _function_ >callback) - _(void)_ - Retrieves the target for a symlink at `path`. `callback` has 2 parameters: < _Error_ >err, < _string_ >target. -* **symlink**(< _string_ >targetPath, < _string_ >linkPath, < _function_ >callback) - _boolean_ - Creates a symlink at `linkPath` to `targetPath`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **symlink**(< _string_ >targetPath, < _string_ >linkPath, < _function_ >callback) - _(void)_ - Creates a symlink at `linkPath` to `targetPath`. `callback` has 1 parameter: < _Error_ >err. -* **realpath**(< _string_ >path, < _function_ >callback) - _boolean_ - Resolves `path` to an absolute path. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _string_ >absPath. +* **realpath**(< _string_ >path, < _function_ >callback) - _(void)_ - Resolves `path` to an absolute path. `callback` has 2 parameters: < _Error_ >err, < _string_ >absPath. -* **ext_openssh_rename**(< _string_ >srcPath, < _string_ >destPath, < _function_ >callback) - _boolean_ - **OpenSSH extension** Performs POSIX rename(3) from `srcPath` to `destPath`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **ext_openssh_rename**(< _string_ >srcPath, < _string_ >destPath, < _function_ >callback) - _(void)_ - **OpenSSH extension** Performs POSIX rename(3) from `srcPath` to `destPath`. `callback` has 1 parameter: < _Error_ >err. -* **ext_openssh_statvfs**(< _string_ >path, < _function_ >callback) - _boolean_ - **OpenSSH extension** Performs POSIX statvfs(2) on `path`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _object_ >fsInfo. `fsInfo` contains the information as found in the [statvfs struct](http://linux.die.net/man/2/statvfs). +* **ext_openssh_statvfs**(< _string_ >path, < _function_ >callback) - _(void)_ - **OpenSSH extension** Performs POSIX statvfs(2) on `path`. `callback` has 2 parameters: < _Error_ >err, < _object_ >fsInfo. `fsInfo` contains the information as found in the [statvfs struct](http://linux.die.net/man/2/statvfs). -* **ext_openssh_fstatvfs**(< _Buffer_ >handle, < _function_ >callback) - _boolean_ - **OpenSSH extension** Performs POSIX fstatvfs(2) on open handle `handle`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 2 parameters: < _Error_ >err, < _object_ >fsInfo. `fsInfo` contains the information as found in the [statvfs struct](http://linux.die.net/man/2/statvfs). +* **ext_openssh_fstatvfs**(< _Buffer_ >handle, < _function_ >callback) - _(void)_ - **OpenSSH extension** Performs POSIX fstatvfs(2) on open handle `handle`. `callback` has 2 parameters: < _Error_ >err, < _object_ >fsInfo. `fsInfo` contains the information as found in the [statvfs struct](http://linux.die.net/man/2/statvfs). -* **ext_openssh_hardlink**(< _string_ >targetPath, < _string_ >linkPath, < _function_ >callback) - _boolean_ - **OpenSSH extension** Performs POSIX link(2) to create a hard link to `targetPath` at `linkPath`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **ext_openssh_hardlink**(< _string_ >targetPath, < _string_ >linkPath, < _function_ >callback) - _(void)_ - **OpenSSH extension** Performs POSIX link(2) to create a hard link to `targetPath` at `linkPath`. `callback` has 1 parameter: < _Error_ >err. -* **ext_openssh_fsync**(< _Buffer_ >handle, < _function_ >callback) - _boolean_ - **OpenSSH extension** Performs POSIX fsync(3) on the open handle `handle`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `callback` has 1 parameter: < _Error_ >err. +* **ext_openssh_fsync**(< _Buffer_ >handle, < _function_ >callback) - _(void)_ - **OpenSSH extension** Performs POSIX fsync(3) on the open handle `handle`. `callback` has 1 parameter: < _Error_ >err. **Server-only methods** -* **status**(< _integer_ >reqID, < _integer_ >statusCode[, < _string_ >message]) - _boolean_ - Sends a status response for the request identified by `id`. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **status**(< _integer_ >reqID, < _integer_ >statusCode[, < _string_ >message]) - _(void)_ - Sends a status response for the request identified by `id`. -* **handle**(< _integer_ >reqID, < _Buffer_ >handle) - _boolean_ - Sends a handle response for the request identified by `id`. `handle` must be less than 256 bytes and is an opaque value that could merely contain the value of a backing file descriptor or some other unique, custom value. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **handle**(< _integer_ >reqID, < _Buffer_ >handle) - _(void)_ - Sends a handle response for the request identified by `id`. `handle` must be less than 256 bytes and is an opaque value that could merely contain the value of a backing file descriptor or some other unique, custom value. -* **data**(< _integer_ >reqID, < _mixed_ >data[, < _string_ >encoding]) - _boolean_ - Sends a data response for the request identified by `id`. `data` can be a _Buffer_ or _string_. If `data` is a string, `encoding` is the encoding of `data`. Returns `false` if you should wait for the `continue` event before sending any more traffic. +* **data**(< _integer_ >reqID, < _mixed_ >data[, < _string_ >encoding]) - _(void)_ - Sends a data response for the request identified by `id`. `data` can be a _Buffer_ or _string_. If `data` is a string, `encoding` is the encoding of `data`. -* **name**(< _integer_ >reqID, < _array_ >names) - _boolean_ - Sends a name response for the request identified by `id`. Returns `false` if you should wait for the `continue` event before sending any more traffic. `names` must be an _array_ of _object_ where each _object_ can contain: +* **name**(< _integer_ >reqID, < _array_ >names) - _(void)_ - Sends a name response for the request identified by `id`. `names` must be an _array_ of _object_ where each _object_ can contain: * **filename** - _string_ - The entry's name. @@ -358,7 +356,7 @@ SFTPStream methods * **attrs** - _ATTRS_ - This is an optional _ATTRS_ object that contains requested/available attributes for the entry. -* **attrs**(< _integer_ >reqID, < _ATTRS_ >attrs) - _boolean_ - Sends an attrs response for the request identified by `id`. `attrs` contains the requested/available attributes. +* **attrs**(< _integer_ >reqID, < _ATTRS_ >attrs) - _(void)_ - Sends an attrs response for the request identified by `id`. `attrs` contains the requested/available attributes. ATTRS diff --git a/reverse_engineering/node_modules/ssh2/examples/server-chat.js b/reverse_engineering/node_modules/ssh2/examples/server-chat.js index 18e5108..a82a955 100644 --- a/reverse_engineering/node_modules/ssh2/examples/server-chat.js +++ b/reverse_engineering/node_modules/ssh2/examples/server-chat.js @@ -4,21 +4,23 @@ // terminal types of client connections // 2. Install `blessed`: `npm install blessed` // 3. Create a server host key in this same directory and name it `host.key` +'use strict'; -var fs = require('fs'); +const { readFileSync } = require('fs'); -var blessed = require('blessed'); -var Server = require('ssh2').Server; +const blessed = require('blessed'); +const { Server } = require('ssh2'); -var RE_SPECIAL = /[\x00-\x1F\x7F]+|(?:\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])/g; -var MAX_MSG_LEN = 128; -var MAX_NAME_LEN = 10; -var PROMPT_NAME = 'Enter a nickname to use (max ' + MAX_NAME_LEN + ' chars): '; +const RE_SPECIAL = +// eslint-disable-next-line no-control-regex + /[\x00-\x1F\x7F]+|(?:\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])/g; +const MAX_MSG_LEN = 128; +const MAX_NAME_LEN = 10; +const PROMPT_NAME = `Enter a nickname to use (max ${MAX_NAME_LEN} chars): `; -var users = []; +const users = []; function formatMessage(msg, output) { - var output = output; output.parseTags = true; msg = output._parseTags(msg); output.parseTags = false; @@ -26,12 +28,11 @@ function formatMessage(msg, output) { } function userBroadcast(msg, source) { - var sourceMsg = '> ' + msg; - var name = '{cyan-fg}{bold}' + source.name + '{/}'; - msg = ': ' + msg; - for (var i = 0; i < users.length; ++i) { - var user = users[i]; - var output = user.output; + const sourceMsg = `> ${msg}`; + const name = `{cyan-fg}{bold}${source.name}{/}`; + msg = `: ${msg}`; + for (const user of users) { + const output = user.output; if (source === user) output.add(sourceMsg); else @@ -40,30 +41,31 @@ function userBroadcast(msg, source) { } function localMessage(msg, source) { - var output = source.output; + const output = source.output; output.add(formatMessage(msg, output)); } function noop(v) {} new Server({ - hostKeys: [fs.readFileSync('host.key')], -}, function(client) { - var stream; - var name; - - client.on('authentication', function(ctx) { - var nick = ctx.username; - var prompt = PROMPT_NAME; - var lowered; + hostKeys: [readFileSync('host.key')], +}, (client) => { + let stream; + let name; + + client.on('authentication', (ctx) => { + let nick = ctx.username; + let prompt = PROMPT_NAME; + let lowered; + // Try to use username as nickname if (nick.length > 0 && nick.length <= MAX_NAME_LEN) { lowered = nick.toLowerCase(); - var ok = true; - for (var i = 0; i < users.length; ++i) { - if (users[i].name.toLowerCase() === lowered) { + let ok = true; + for (const user of users) { + if (user.name.toLowerCase() === lowered) { ok = false; - prompt = 'That nickname is already in use.\n' + PROMPT_NAME; + prompt = `That nickname is already in use.\n${PROMPT_NAME}`; break; } } @@ -71,10 +73,11 @@ new Server({ name = nick; return ctx.accept(); } - } else if (nick.length === 0) + } else if (nick.length === 0) { prompt = 'A nickname is required.\n' + PROMPT_NAME; - else + } else { prompt = 'That nickname is too long.\n' + PROMPT_NAME; + } if (ctx.method !== 'keyboard-interactive') return ctx.reject(['keyboard-interactive']); @@ -84,33 +87,33 @@ new Server({ return ctx.reject(['keyboard-interactive']); nick = answers[0]; if (nick.length > MAX_NAME_LEN) { - return ctx.prompt('That nickname is too long.\n' + PROMPT_NAME, + return ctx.prompt(`That nickname is too long.\n${PROMPT_NAME}`, retryPrompt); } else if (nick.length === 0) { - return ctx.prompt('A nickname is required.\n' + PROMPT_NAME, + return ctx.prompt(`A nickname is required.\n${PROMPT_NAME}`, retryPrompt); } lowered = nick.toLowerCase(); - for (var i = 0; i < users.length; ++i) { - if (users[i].name.toLowerCase() === lowered) { - return ctx.prompt('That nickname is already in use.\n' + PROMPT_NAME, + for (const user of users) { + if (user.name.toLowerCase() === lowered) { + return ctx.prompt(`That nickname is already in use.\n${PROMPT_NAME}`, retryPrompt); } } name = nick; ctx.accept(); }); - }).on('ready', function() { - var rows; - var cols; - var term; - client.once('session', function(accept, reject) { - accept().once('pty', function(accept, reject, info) { + }).on('ready', () => { + let rows; + let cols; + let term; + client.once('session', (accept, reject) => { + accept().once('pty', (accept, reject, info) => { rows = info.rows; cols = info.cols; term = info.term; accept && accept(); - }).on('window-change', function(accept, reject, info) { + }).on('window-change', (accept, reject, info) => { rows = info.rows; cols = info.cols; if (stream) { @@ -119,7 +122,7 @@ new Server({ stream.emit('resize'); } accept && accept(); - }).once('shell', function(accept, reject) { + }).once('shell', (accept, reject) => { stream = accept(); users.push(stream); @@ -130,7 +133,7 @@ new Server({ stream.setRawMode = noop; stream.on('error', noop); - var screen = new blessed.screen({ + const screen = new blessed.screen({ autoPadding: true, smartCSR: true, program: new blessed.program({ @@ -144,14 +147,14 @@ new Server({ // Disable local echo screen.program.attr('invisible', true); - var output = stream.output = new blessed.log({ + const output = stream.output = new blessed.log({ screen: screen, top: 0, left: 0, width: '100%', bottom: 2, scrollOnInput: true - }) + }); screen.append(output); screen.append(new blessed.box({ @@ -164,7 +167,7 @@ new Server({ ch: '=' })); - var input = new blessed.textbox({ + const input = new blessed.textbox({ screen: screen, bottom: 0, height: 1, @@ -184,9 +187,8 @@ new Server({ stream); // Let everyone else know that this user just joined - for (var i = 0; i < users.length; ++i) { - var user = users[i]; - var output = user.output; + for (const user of users) { + const output = user.output; if (user === stream) continue; output.add(formatMessage('{green-fg}*** {bold}', output) @@ -200,7 +202,7 @@ new Server({ screen.program.emit('resize'); // Read a line of input from the user - input.on('submit', function(line) { + input.on('submit', (line) => { input.clearValue(); screen.render(); if (!input.focused) @@ -217,27 +219,20 @@ new Server({ }); }); }); - }).on('end', function() { + }).on('close', () => { if (stream !== undefined) { - spliceOne(users, users.indexOf(stream)); + users.splice(users.indexOf(stream), 1); // Let everyone else know that this user just left - for (var i = 0; i < users.length; ++i) { - var user = users[i]; - var output = user.output; + for (const user of users) { + const output = user.output; output.add(formatMessage('{magenta-fg}*** {bold}', output) + name + formatMessage('{/bold} has left the chat{/}', output)); } } - }).on('error', function(err) { + }).on('error', (err) => { // Ignore errors }); }).listen(0, function() { console.log('Listening on port ' + this.address().port); }); - -function spliceOne(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); -} diff --git a/reverse_engineering/node_modules/ssh2/examples/sftp-server-download-only.js b/reverse_engineering/node_modules/ssh2/examples/sftp-server-download-only.js index 8ea5a5a..d4ae4c5 100644 --- a/reverse_engineering/node_modules/ssh2/examples/sftp-server-download-only.js +++ b/reverse_engineering/node_modules/ssh2/examples/sftp-server-download-only.js @@ -1,96 +1,134 @@ -var constants = require('constants'); -var fs = require('fs'); +'use strict'; -var ssh2 = require('ssh2'); -var OPEN_MODE = ssh2.SFTP_OPEN_MODE; -var STATUS_CODE = ssh2.SFTP_STATUS_CODE; +const { timingSafeEqual } = require('crypto'); +const { constants, readFileSync } = require('fs'); -new ssh2.Server({ - hostKeys: [fs.readFileSync('host.key')] -}, function(client) { +const { Server, sftp: { OPEN_MODE, STATUS_CODE } } = require('ssh2'); + +const allowedUser = Buffer.from('foo'); +const allowedPassword = Buffer.from('bar'); + +function checkValue(input, allowed) { + const autoReject = (input.length !== allowed.length); + if (autoReject) { + // Prevent leaking length information by always making a comparison with the + // same input when lengths don't match what we expect ... + allowed = input; + } + const isMatch = timingSafeEqual(input, allowed); + return (!autoReject && isMatch); +} + +new Server({ + hostKeys: [readFileSync('host.key')] +}, (client) => { console.log('Client connected!'); - client.on('authentication', function(ctx) { - if (ctx.method === 'password' - && ctx.username === 'foo' - && ctx.password === 'bar') + client.on('authentication', (ctx) => { + let allowed = true; + if (!checkValue(Buffer.from(ctx.username), allowedUser)) + allowed = false; + + switch (ctx.method) { + case 'password': + if (!checkValue(Buffer.from(ctx.password), allowedPassword)) + return ctx.reject(); + break; + default: + return ctx.reject(); + } + + if (allowed) ctx.accept(); else - ctx.reject(['password']); - }).on('ready', function() { + ctx.reject(); + }).on('ready', () => { console.log('Client authenticated!'); - client.on('session', function(accept, reject) { - var session = accept(); - session.on('sftp', function(accept, reject) { + client.on('session', (accept, reject) => { + const session = accept(); + session.on('sftp', (accept, reject) => { console.log('Client SFTP session'); - var openFiles = {}; - var handleCount = 0; - // `sftpStream` is an `SFTPStream` instance in server mode - // see: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md - var sftpStream = accept(); - sftpStream.on('OPEN', function(reqid, filename, flags, attrs) { - console.log('OPEN', filename); - // only allow opening /tmp/foo.txt for writing + + const openFiles = new Map(); + let handleCount = 0; + const sftp = accept(); + sftp.on('OPEN', (reqid, filename, flags, attrs) => { + // Only allow opening /tmp/foo.txt for writing if (filename !== '/tmp/foo.txt' || !(flags & OPEN_MODE.READ)) - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - // create a fake handle to return to the client, this could easily + return sftp.status(reqid, STATUS_CODE.FAILURE); + + // Create a fake handle to return to the client, this could easily // be a real file descriptor number for example if actually opening // the file on the disk - var handle = new Buffer(4); - openFiles[handleCount] = { read: false }; + const handle = Buffer.alloc(4); + openFiles.set(handleCount, { read: false }); handle.writeUInt32BE(handleCount++, 0, true); - sftpStream.handle(reqid, handle); - console.log('Opening file for read') - }).on('READ', function(reqid, handle, offset, length) { - if (handle.length !== 4 || !openFiles[handle.readUInt32BE(0, true)]) - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - // fake the read - var state = openFiles[handle.readUInt32BE(0, true)]; - if (state.read) - sftpStream.status(reqid, STATUS_CODE.EOF); - else { + + console.log('Opening file for read'); + sftp.handle(reqid, handle); + }).on('READ', (reqid, handle, offset, length) => { + let fnum; + if (handle.length !== 4 + || !openFiles.has(fnum = handle.readUInt32BE(0, true))) { + return sftp.status(reqid, STATUS_CODE.FAILURE); + } + + // Fake the read + const state = openFiles.get(fnum); + if (state.read) { + sftp.status(reqid, STATUS_CODE.EOF); + } else { state.read = true; - sftpStream.data(reqid, 'bar'); - console.log('Read from file at offset %d, length %d', offset, length); + + console.log( + 'Read from file at offset %d, length %d', offset, length + ); + sftp.data(reqid, 'bar'); + } + }).on('CLOSE', (reqid, handle) => { + let fnum; + if (handle.length !== 4 + || !openFiles.has(fnum = handle.readUInt32BE(0))) { + return sftp.status(reqid, STATUS_CODE.FAILURE); } - }).on('CLOSE', function(reqid, handle) { - var fnum; - if (handle.length !== 4 || !openFiles[(fnum = handle.readUInt32BE(0, true))]) - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - delete openFiles[fnum]; - sftpStream.status(reqid, STATUS_CODE.OK); + + openFiles.delete(fnum); + console.log('Closing file'); + sftp.status(reqid, STATUS_CODE.OK); }).on('REALPATH', function(reqid, path) { - var name = [{ + const name = [{ filename: '/tmp/foo.txt', longname: '-rwxrwxrwx 1 foo foo 3 Dec 8 2009 foo.txt', attrs: {} }]; - sftpStream.name(reqid, name); + sftp.name(reqid, name); }).on('STAT', onSTAT) .on('LSTAT', onSTAT); + function onSTAT(reqid, path) { if (path !== '/tmp/foo.txt') - return sftpStream.status(reqid, STATUS_CODE.FAILURE); - var mode = constants.S_IFREG; // Regular file - mode |= constants.S_IRWXU; // read, write, execute for user - mode |= constants.S_IRWXG; // read, write, execute for group - mode |= constants.S_IRWXO; // read, write, execute for other - sftpStream.attrs(reqid, { + return sftp.status(reqid, STATUS_CODE.FAILURE); + + let mode = constants.S_IFREG; // Regular file + mode |= constants.S_IRWXU; // Read, write, execute for user + mode |= constants.S_IRWXG; // Read, write, execute for group + mode |= constants.S_IRWXO; // Read, write, execute for other + sftp.attrs(reqid, { mode: mode, uid: 0, gid: 0, size: 3, atime: Date.now(), - mtime: Date.now() + mtime: Date.now(), }); } }); }); - }).on('end', function() { + }).on('close', () => { console.log('Client disconnected'); }); }).listen(0, '127.0.0.1', function() { - console.log('Listening on port ' + this.address().port); + console.log(`Listening on port ${this.address().port}`); }); diff --git a/reverse_engineering/node_modules/ssh2/install.js b/reverse_engineering/node_modules/ssh2/install.js new file mode 100644 index 0000000..e536366 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/install.js @@ -0,0 +1,20 @@ +'use strict'; + +const { spawnSync } = require('child_process'); + +// Attempt to build the bundled optional binding +const result = spawnSync('node-gyp', [ + `--target=${process.version}`, + 'rebuild' +], { + cwd: 'lib/protocol/crypto', + encoding: 'utf8', + shell: true, + stdio: 'inherit', + windowsHide: true, +}); +if (result.error || result.status !== 0) + console.log('Failed to build optional crypto binding'); +else + console.log('Succeeded in building optional crypto binding'); +process.exit(0); diff --git a/reverse_engineering/node_modules/ssh2/lib/Channel.js b/reverse_engineering/node_modules/ssh2/lib/Channel.js index 1d8372d..0bf5553 100644 --- a/reverse_engineering/node_modules/ssh2/lib/Channel.js +++ b/reverse_engineering/node_modules/ssh2/lib/Channel.js @@ -1,506 +1,294 @@ -var inherits = require('util').inherits; -var DuplexStream = require('stream').Duplex; -var ReadableStream = require('stream').Readable; -var WritableStream = require('stream').Writable; - -var STDERR = require('ssh2-streams').constants.CHANNEL_EXTENDED_DATATYPE.STDERR; - -var PACKET_SIZE = 32 * 1024; -var MAX_WINDOW = 1 * 1024 * 1024; -var WINDOW_THRESHOLD = MAX_WINDOW / 2; -var CUSTOM_EVENTS = [ - 'CHANNEL_EOF', - 'CHANNEL_CLOSE', - 'CHANNEL_DATA', - 'CHANNEL_EXTENDED_DATA', - 'CHANNEL_WINDOW_ADJUST', - 'CHANNEL_SUCCESS', - 'CHANNEL_FAILURE', - 'CHANNEL_REQUEST' -]; -var CUSTOM_EVENTS_LEN = CUSTOM_EVENTS.length; - -function Channel(info, client, opts) { - var streamOpts = { - highWaterMark: MAX_WINDOW, - allowHalfOpen: (!opts || (opts && opts.allowHalfOpen !== false)) - }; - - this.allowHalfOpen = streamOpts.allowHalfOpen; - - DuplexStream.call(this, streamOpts); - - var self = this; - var server = opts && opts.server; - - this.server = server; - this.type = info.type; - this.subtype = undefined; - /* - incoming and outgoing contain these properties: - { - id: undefined, - window: undefined, - packetSize: undefined, - state: 'closed' - } - */ - var incoming = this.incoming = info.incoming; - var incomingId = incoming.id; - var outgoing = this.outgoing = info.outgoing; - var callbacks = this._callbacks = []; - var exitCode; - var exitSignal; - var exitDump; - var exitDesc; - var exitLang; - - this._client = client; - this._hasX11 = false; - - var channels = client._channels; - var sshstream = client._sshstream; - - function ondrain() { - if (self._waitClientDrain) { - self._waitClientDrain = false; - if (!self._waitWindow) { - if (self._chunk) - self._write(self._chunk, null, self._chunkcb); - else if (self._chunkcb) - self._chunkcb(); - else if (self._chunkErr) - self.stderr._write(self._chunkErr, null, self._chunkcbErr); - else if (self._chunkcbErr) - self._chunkcbErr(); - } - } - } - client._sock.on('drain', ondrain); +'use strict'; - sshstream.once('CHANNEL_EOF:' + incomingId, function() { - if (incoming.state === 'closed' || incoming.state === 'eof') - return; - incoming.state = 'eof'; - - if (self.readable) - self.push(null); - if (!server && self.stderr.readable) - self.stderr.push(null); - }).once('CHANNEL_CLOSE:' + incomingId, function() { - if (incoming.state === 'closed') - return; - incoming.state = 'closed'; - - if (self.readable) - self.push(null); - if (server && self.stderr.writable) - self.stderr.end(); - else if (!server && self.stderr.readable) - self.stderr.push(null); - - if (outgoing.state === 'open' || outgoing.state === 'eof') - self.close(); - if (outgoing.state === 'closing') - outgoing.state = 'closed'; - - delete channels[incomingId]; - - var state = self._writableState; - client._sock.removeListener('drain', ondrain); - if (!state.ending && !state.finished) - self.end(); - - // Take care of any outstanding channel requests - self._callbacks = []; - for (var i = 0; i < callbacks.length; ++i) - callbacks[i](true); - callbacks = self._callbacks; - - if (!server) { - // align more with node child processes, where the close event gets the - // same arguments as the exit event - if (!self.readable) { - if (exitCode === null) { - self.emit('close', exitCode, exitSignal, exitDump, exitDesc, - exitLang); - } else - self.emit('close', exitCode); - } else { - self.once('end', function() { - if (exitCode === null) { - self.emit('close', exitCode, exitSignal, exitDump, exitDesc, - exitLang); - } else - self.emit('close', exitCode); - }); - } +const { + Duplex: DuplexStream, + Readable: ReadableStream, + Writable: WritableStream, +} = require('stream'); - if (!self.stderr.readable) - self.stderr.emit('close'); - else { - self.stderr.once('end', function() { - self.stderr.emit('close'); - }); - } - } else { // Server mode - if (!self.readable) - self.emit('close'); - else { - self.once('end', function() { - self.emit('close'); - }); - } - } +const { + CHANNEL_EXTENDED_DATATYPE: { STDERR }, +} = require('./protocol/constants.js'); +const { bufferSlice } = require('./protocol/utils.js'); - for (var i = 0; i < CUSTOM_EVENTS_LEN; ++i) - sshstream.removeAllListeners(CUSTOM_EVENTS[i] + ':' + incomingId); - }).on('CHANNEL_DATA:' + incomingId, function(data) { - // the remote party should not be sending us data if there is no window - // space available ... - if (incoming.window === 0) - return; +const PACKET_SIZE = 32 * 1024; +const MAX_WINDOW = 2 * 1024 * 1024; +const WINDOW_THRESHOLD = MAX_WINDOW / 2; - incoming.window -= data.length; +class ClientStderr extends ReadableStream { + constructor(channel, streamOpts) { + super(streamOpts); - if (!self.push(data)) { - self._waitChanDrain = true; - return; + this._channel = channel; + } + _read(n) { + if (this._channel._waitChanDrain) { + this._channel._waitChanDrain = false; + if (this._channel.incoming.window <= WINDOW_THRESHOLD) + windowAdjust(this._channel); } + } +} - if (incoming.window <= WINDOW_THRESHOLD) - windowAdjust(self); - }).on('CHANNEL_WINDOW_ADJUST:' + incomingId, function(amt) { - // the server is allowing us to send `amt` more bytes of data - outgoing.window += amt; - - if (self._waitWindow) { - self._waitWindow = false; - if (!self._waitClientDrain) { - if (self._chunk) - self._write(self._chunk, null, self._chunkcb); - else if (self._chunkcb) - self._chunkcb(); - else if (self._chunkErr) - self.stderr._write(self._chunkErr, null, self._chunkcbErr); - else if (self._chunkcbErr) - self._chunkcbErr(); - } - } - }).on('CHANNEL_SUCCESS:' + incomingId, function() { - if (server) { - sshstream._kalast = Date.now(); - sshstream._kacnt = 0; - } else - client._resetKA(); - if (callbacks.length) - callbacks.shift()(false); - }).on('CHANNEL_FAILURE:' + incomingId, function() { - if (server) { - sshstream._kalast = Date.now(); - sshstream._kacnt = 0; - } else - client._resetKA(); - if (callbacks.length) - callbacks.shift()(true); - }).on('CHANNEL_REQUEST:' + incomingId, function(info) { - if (!server) { - if (info.request === 'exit-status') { - self.emit('exit', exitCode = info.code); - return; - } else if (info.request === 'exit-signal') { - self.emit('exit', - exitCode = null, - exitSignal = 'SIG' + info.signal, - exitDump = info.coredump, - exitDesc = info.description, - exitLang = info.lang); - return; - } - } +class ServerStderr extends WritableStream { + constructor(channel) { + super({ highWaterMark: MAX_WINDOW }); - // keepalive request? OpenSSH will send one as a channel request if there - // is a channel open + this._channel = channel; + } - if (info.wantReply) - sshstream.channelFailure(outgoing.id); - }); + _write(data, encoding, cb) { + const channel = this._channel; + const protocol = channel._client._protocol; + const outgoing = channel.outgoing; + const packetSize = outgoing.packetSize; + const id = outgoing.id; + let window = outgoing.window; + const len = data.length; + let p = 0; + + if (outgoing.state !== 'open') + return; - this.stdin = this.stdout = this; + while (len - p > 0 && window > 0) { + let sliceLen = len - p; + if (sliceLen > window) + sliceLen = window; + if (sliceLen > packetSize) + sliceLen = packetSize; - if (server) - this.stderr = new ServerStderr(this); - else { - this.stderr = new ReadableStream(streamOpts); - this.stderr._read = function(n) { - if (self._waitChanDrain) { - self._waitChanDrain = false; - if (incoming.window <= WINDOW_THRESHOLD) - windowAdjust(self); - } - }; + if (p === 0 && sliceLen === len) + protocol.channelExtData(id, data, STDERR); + else + protocol.channelExtData(id, bufferSlice(data, p, p + sliceLen), STDERR); - sshstream.on('CHANNEL_EXTENDED_DATA:' + incomingId, - function(type, data) { - // the remote party should not be sending us data if there is no window - // space available ... - if (incoming.window === 0) - return; + p += sliceLen; + window -= sliceLen; + } - incoming.window -= data.length; + outgoing.window = window; - if (!self.stderr.push(data)) { - self._waitChanDrain = true; - return; - } + if (len - p > 0) { + if (window === 0) + channel._waitWindow = true; + if (p > 0) + channel._chunkErr = bufferSlice(data, p, len); + else + channel._chunkErr = data; + channel._chunkcbErr = cb; + return; + } - if (incoming.window <= WINDOW_THRESHOLD) - windowAdjust(self); - } - ); + cb(); } +} - // outgoing data - this._waitClientDrain = false; // Client stream-level backpressure - this._waitWindow = false; // SSH-level backpressure +class Channel extends DuplexStream { + constructor(client, info, opts) { + const streamOpts = { + highWaterMark: MAX_WINDOW, + allowHalfOpen: (!opts || (opts && opts.allowHalfOpen !== false)), + emitClose: false, + }; + super(streamOpts); + this.allowHalfOpen = streamOpts.allowHalfOpen; + + const server = !!(opts && opts.server); + + this.server = server; + this.type = info.type; + this.subtype = undefined; + + /* + incoming and outgoing contain these properties: + { + id: undefined, + window: undefined, + packetSize: undefined, + state: 'closed' + } + */ + this.incoming = info.incoming; + this.outgoing = info.outgoing; + this._callbacks = []; + + this._client = client; + this._hasX11 = false; + this._exit = { + code: undefined, + signal: undefined, + dump: undefined, + desc: undefined, + }; - // incoming data - this._waitChanDrain = false; // Channel Readable side backpressure + this.stdin = this.stdout = this; - this._chunk = undefined; - this._chunkcb = undefined; - this._chunkErr = undefined; - this._chunkcbErr = undefined; + if (server) + this.stderr = new ServerStderr(this); + else + this.stderr = new ClientStderr(this, streamOpts); - function onFinish() { - self.eof(); - if (server || (!server && !self.allowHalfOpen)) - self.close(); - self.writable = false; - } - this.on('finish', onFinish) - .on('prefinish', onFinish); // for node v0.11+ - function onEnd() { - self.readable = false; - } - this.on('end', onEnd) - .on('close', onEnd); -} -inherits(Channel, DuplexStream); + // Outgoing data + this._waitWindow = false; // SSH-level backpressure -Channel.prototype.eof = function() { - var ret = true; - var outgoing = this.outgoing; + // Incoming data + this._waitChanDrain = false; // Channel Readable side backpressure - if (outgoing.state === 'open') { - outgoing.state = 'eof'; - ret = this._client._sshstream.channelEOF(outgoing.id); - } + this._chunk = undefined; + this._chunkcb = undefined; + this._chunkErr = undefined; + this._chunkcbErr = undefined; - return ret; -}; + this.on('finish', onFinish) + .on('prefinish', onFinish); // For node v0.11+ -Channel.prototype.close = function() { - var ret = true; - var outgoing = this.outgoing; + this.on('end', onEnd).on('close', onEnd); + } - if (outgoing.state === 'open' || outgoing.state === 'eof') { - outgoing.state = 'closing'; - ret = this._client._sshstream.channelClose(outgoing.id); + _read(n) { + if (this._waitChanDrain) { + this._waitChanDrain = false; + if (this.incoming.window <= WINDOW_THRESHOLD) + windowAdjust(this); + } } - return ret; -}; + _write(data, encoding, cb) { + const protocol = this._client._protocol; + const outgoing = this.outgoing; + const packetSize = outgoing.packetSize; + const id = outgoing.id; + let window = outgoing.window; + const len = data.length; + let p = 0; -Channel.prototype._read = function(n) { - if (this._waitChanDrain) { - this._waitChanDrain = false; - if (this.incoming.window <= WINDOW_THRESHOLD) - windowAdjust(this); - } -}; + if (outgoing.state !== 'open') + return; -Channel.prototype._write = function(data, encoding, cb) { - var sshstream = this._client._sshstream; - var outgoing = this.outgoing; - var packetSize = outgoing.packetSize; - var id = outgoing.id; - var window = outgoing.window; - var len = data.length; - var p = 0; - var ret; - var buf; - var sliceLen; - - if (outgoing.state !== 'open') - return; + while (len - p > 0 && window > 0) { + let sliceLen = len - p; + if (sliceLen > window) + sliceLen = window; + if (sliceLen > packetSize) + sliceLen = packetSize; - while (len - p > 0 && window > 0) { - sliceLen = len - p; - if (sliceLen > window) - sliceLen = window; - if (sliceLen > packetSize) - sliceLen = packetSize; + if (p === 0 && sliceLen === len) + protocol.channelData(id, data); + else + protocol.channelData(id, bufferSlice(data, p, p + sliceLen)); - ret = sshstream.channelData(id, data.slice(p, p + sliceLen)); + p += sliceLen; + window -= sliceLen; + } - p += sliceLen; - window -= sliceLen; + outgoing.window = window; - if (!ret) { - this._waitClientDrain = true; - this._chunk = undefined; + if (len - p > 0) { + if (window === 0) + this._waitWindow = true; + if (p > 0) + this._chunk = bufferSlice(data, p, len); + else + this._chunk = data; this._chunkcb = cb; - break; + return; } - } - outgoing.window = window; - - if (len - p > 0) { - if (window === 0) - this._waitWindow = true; - if (p > 0) { - // partial - buf = new Buffer(len - p); - data.copy(buf, 0, p); - this._chunk = buf; - } else - this._chunk = data; - this._chunkcb = cb; - return; + cb(); } - if (!this._waitClientDrain) - cb(); -}; + eof() { + if (this.outgoing.state === 'open') { + this.outgoing.state = 'eof'; + this._client._protocol.channelEOF(this.outgoing.id); + } + } -Channel.prototype.destroy = function() { - this.end(); -}; + close() { + if (this.outgoing.state === 'open' || this.outgoing.state === 'eof') { + this.outgoing.state = 'closing'; + this._client._protocol.channelClose(this.outgoing.id); + } + } -// session type-specific methods -Channel.prototype.setWindow = function(rows, cols, height, width) { - if (this.server) - throw new Error('Client-only method called in server mode'); - - if (this.type === 'session' - && (this.subtype === 'shell' || this.subtype === 'exec') - && this.writable - && this.outgoing.state === 'open') { - return this._client._sshstream.windowChange(this.outgoing.id, - rows, - cols, - height, - width); + destroy() { + this.end(); + this.close(); } - return true; -}; -Channel.prototype.signal = function(signalName) { - if (this.server) - throw new Error('Client-only method called in server mode'); + // Session type-specific methods ============================================= + setWindow(rows, cols, height, width) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (this.type === 'session' + && (this.subtype === 'shell' || this.subtype === 'exec') + && this.writable + && this.outgoing.state === 'open') { + this._client._protocol.windowChange(this.outgoing.id, + rows, + cols, + height, + width); + } + } - if (this.type === 'session' - && this.writable - && this.outgoing.state === 'open') - return this._client._sshstream.signal(this.outgoing.id, signalName); + signal(signalName) { + if (this.server) + throw new Error('Client-only method called in server mode'); - return true; -}; -Channel.prototype.exit = function(name, coreDumped, msg) { - if (!this.server) - throw new Error('Server-only method called in client mode'); - - if (this.type === 'session' - && this.writable - && this.outgoing.state === 'open') { - if (typeof name === 'number') - return this._client._sshstream.exitStatus(this.outgoing.id, name); - else { - return this._client._sshstream.exitSignal(this.outgoing.id, - name, - coreDumped, - msg); + if (this.type === 'session' + && this.writable + && this.outgoing.state === 'open') { + this._client._protocol.signal(this.outgoing.id, signalName); } } - return true; -}; + exit(statusOrSignal, coreDumped, msg) { + if (!this.server) + throw new Error('Server-only method called in client mode'); -Channel.MAX_WINDOW = MAX_WINDOW; -Channel.PACKET_SIZE = PACKET_SIZE; + if (this.type === 'session' + && this.writable + && this.outgoing.state === 'open') { + if (typeof statusOrSignal === 'number') { + this._client._protocol.exitStatus(this.outgoing.id, statusOrSignal); + } else { + this._client._protocol.exitSignal(this.outgoing.id, + statusOrSignal, + coreDumped, + msg); + } + } + } -function windowAdjust(self) { - if (self.outgoing.state !== 'open') - return true; - var amt = MAX_WINDOW - self.incoming.window; - if (amt <= 0) - return true; - self.incoming.window += amt; - return self._client._sshstream.channelWindowAdjust(self.outgoing.id, amt); } -function ServerStderr(channel) { - WritableStream.call(this, { highWaterMark: MAX_WINDOW }); - this._channel = channel; +function onFinish() { + this.eof(); + if (this.server || !this.allowHalfOpen) + this.close(); + this.writable = false; } -inherits(ServerStderr, WritableStream); - -ServerStderr.prototype._write = function(data, encoding, cb) { - var channel = this._channel; - var sshstream = channel._client._sshstream; - var outgoing = channel.outgoing; - var packetSize = outgoing.packetSize; - var id = outgoing.id; - var window = outgoing.window; - var len = data.length; - var p = 0; - var ret; - var buf; - var sliceLen; - - if (channel.outgoing.state !== 'open') - return; - while (len - p > 0 && window > 0) { - sliceLen = len - p; - if (sliceLen > window) - sliceLen = window; - if (sliceLen > packetSize) - sliceLen = packetSize; - - ret = sshstream.channelExtData(id, data.slice(p, p + sliceLen), STDERR); - - p += sliceLen; - window -= sliceLen; - - if (!ret) { - channel._waitClientDrain = true; - channel._chunkErr = undefined; - channel._chunkcbErr = cb; - break; - } - } +function onEnd() { + this.readable = false; +} - outgoing.window = window; - - if (len - p > 0) { - if (window === 0) - channel._waitWindow = true; - if (p > 0) { - // partial - buf = new Buffer(len - p); - data.copy(buf, 0, p); - channel._chunkErr = buf; - } else - channel._chunkErr = data; - channel._chunkcbErr = cb; +function windowAdjust(self) { + if (self.outgoing.state === 'closed') return; - } + const amt = MAX_WINDOW - self.incoming.window; + if (amt <= 0) + return; + self.incoming.window += amt; + self._client._protocol.channelWindowAdjust(self.outgoing.id, amt); +} - if (!channel._waitClientDrain) - cb(); +module.exports = { + Channel, + MAX_WINDOW, + PACKET_SIZE, + windowAdjust, + WINDOW_THRESHOLD, }; - -module.exports = Channel; diff --git a/reverse_engineering/node_modules/ssh2/lib/SFTPWrapper.js b/reverse_engineering/node_modules/ssh2/lib/SFTPWrapper.js deleted file mode 100644 index a04a948..0000000 --- a/reverse_engineering/node_modules/ssh2/lib/SFTPWrapper.js +++ /dev/null @@ -1,145 +0,0 @@ -// This wrapper class is used to retain backwards compatibility with -// pre-v0.4 ssh2. If it weren't for `read()` and `write()` being used by the -// streams2/3 API, we could just pass the SFTPStream directly to the end user... - -var inherits = require('util').inherits, - EventEmitter = require('events').EventEmitter; - -function SFTPWrapper(stream) { - var self = this; - - EventEmitter.call(this); - - this._stream = stream; - - stream.on('error', function(err) { - self.emit('error', err); - }).on('end', function() { - self.emit('end'); - }).on('close', function() { - self.emit('close'); - }).on('continue', function() { - self.emit('continue'); - }); -} -inherits(SFTPWrapper, EventEmitter); - -// stream-related methods to pass on -SFTPWrapper.prototype.end = function() { - return this._stream.end(); -}; -// SFTPStream client methods -SFTPWrapper.prototype.createReadStream = function(path, options) { - return this._stream.createReadStream(path, options); -}; -SFTPWrapper.prototype.createWriteStream = function(path, options) { - return this._stream.createWriteStream(path, options); -}; -SFTPWrapper.prototype.open = function(path, flags, attrs, cb) { - return this._stream.open(path, flags, attrs, cb); -}; -SFTPWrapper.prototype.close = function(handle, cb) { - return this._stream.close(handle, cb); -}; -SFTPWrapper.prototype.read = function(handle, buf, off, len, position, cb) { - return this._stream.readData(handle, buf, off, len, position, cb); -}; -SFTPWrapper.prototype.write = function(handle, buf, off, len, position, cb) { - return this._stream.writeData(handle, buf, off, len, position, cb); -}; -SFTPWrapper.prototype.fastGet = function(remotePath, localPath, opts, cb) { - return this._stream.fastGet(remotePath, localPath, opts, cb); -}; -SFTPWrapper.prototype.fastPut = function(localPath, remotePath, opts, cb) { - return this._stream.fastPut(localPath, remotePath, opts, cb); -}; -SFTPWrapper.prototype.readFile = function(path, options, callback_) { - return this._stream.readFile(path, options, callback_); -}; -SFTPWrapper.prototype.writeFile = function(path, data, options, callback_) { - return this._stream.writeFile(path, data, options, callback_); -}; -SFTPWrapper.prototype.appendFile = function(path, data, options, callback_) { - return this._stream.appendFile(path, data, options, callback_); -}; -SFTPWrapper.prototype.exists = function(path, cb) { - return this._stream.exists(path, cb); -}; -SFTPWrapper.prototype.unlink = function(filename, cb) { - return this._stream.unlink(filename, cb); -}; -SFTPWrapper.prototype.rename = function(oldPath, newPath, cb) { - return this._stream.rename(oldPath, newPath, cb); -}; -SFTPWrapper.prototype.mkdir = function(path, attrs, cb) { - return this._stream.mkdir(path, attrs, cb); -}; -SFTPWrapper.prototype.rmdir = function(path, cb) { - return this._stream.rmdir(path, cb); -}; -SFTPWrapper.prototype.readdir = function(where, opts, cb) { - return this._stream.readdir(where, opts, cb); -}; -SFTPWrapper.prototype.fstat = function(handle, cb) { - return this._stream.fstat(handle, cb); -}; -SFTPWrapper.prototype.stat = function(path, cb) { - return this._stream.stat(path, cb); -}; -SFTPWrapper.prototype.lstat = function(path, cb) { - return this._stream.lstat(path, cb); -}; -SFTPWrapper.prototype.opendir = function(path, cb) { - return this._stream.opendir(path, cb); -}; -SFTPWrapper.prototype.setstat = function(path, attrs, cb) { - return this._stream.setstat(path, attrs, cb); -}; -SFTPWrapper.prototype.fsetstat = function(handle, attrs, cb) { - return this._stream.fsetstat(handle, attrs, cb); -}; -SFTPWrapper.prototype.futimes = function(handle, atime, mtime, cb) { - return this._stream.futimes(handle, atime, mtime, cb); -}; -SFTPWrapper.prototype.utimes = function(path, atime, mtime, cb) { - return this._stream.utimes(path, atime, mtime, cb); -}; -SFTPWrapper.prototype.fchown = function(handle, uid, gid, cb) { - return this._stream.fchown(handle, uid, gid, cb); -}; -SFTPWrapper.prototype.chown = function(path, uid, gid, cb) { - return this._stream.chown(path, uid, gid, cb); -}; -SFTPWrapper.prototype.fchmod = function(handle, mode, cb) { - return this._stream.fchmod(handle, mode, cb); -}; -SFTPWrapper.prototype.chmod = function(path, mode, cb) { - return this._stream.chmod(path, mode, cb); -}; -SFTPWrapper.prototype.readlink = function(path, cb) { - return this._stream.readlink(path, cb); -}; -SFTPWrapper.prototype.symlink = function(targetPath, linkPath, cb) { - return this._stream.symlink(targetPath, linkPath, cb); -}; -SFTPWrapper.prototype.realpath = function(path, cb) { - return this._stream.realpath(path, cb); -}; -// extended requests -SFTPWrapper.prototype.ext_openssh_rename = function(oldPath, newPath, cb) { - return this._stream.ext_openssh_rename(oldPath, newPath, cb); -}; -SFTPWrapper.prototype.ext_openssh_statvfs = function(path, cb) { - return this._stream.ext_openssh_statvfs(path, cb); -}; -SFTPWrapper.prototype.ext_openssh_fstatvfs = function(handle, cb) { - return this._stream.ext_openssh_fstatvfs(handle, cb); -}; -SFTPWrapper.prototype.ext_openssh_hardlink = function(oldPath, newPath, cb) { - return this._stream.ext_openssh_hardlink(oldPath, newPath, cb); -}; -SFTPWrapper.prototype.ext_openssh_fsync = function(handle, cb) { - return this._stream.ext_openssh_fsync(handle, cb); -}; - -module.exports = SFTPWrapper; diff --git a/reverse_engineering/node_modules/ssh2/lib/agent.js b/reverse_engineering/node_modules/ssh2/lib/agent.js index 56985f0..bb495d1 100644 --- a/reverse_engineering/node_modules/ssh2/lib/agent.js +++ b/reverse_engineering/node_modules/ssh2/lib/agent.js @@ -1,412 +1,1123 @@ -var Socket = require('net').Socket; -var EventEmitter = require('events').EventEmitter; -var inherits = require('util').inherits; -var path = require('path'); -var fs = require('fs'); -var cp = require('child_process'); - -var REQUEST_IDENTITIES = 11; -var IDENTITIES_ANSWER = 12; -var SIGN_REQUEST = 13; -var SIGN_RESPONSE = 14; -var FAILURE = 5; - -var RE_CYGWIN_SOCK = /^\!(\d+) s ([A-Z0-9]{8}\-[A-Z0-9]{8}\-[A-Z0-9]{8}\-[A-Z0-9]{8})/; - -module.exports = function(sockPath, key, keyType, data, cb) { - var sock; - var error; - var sig; - var datalen; - var keylen = 0; - var isSigning = Buffer.isBuffer(key); - var type; - var count = 0; - var siglen = 0; - var nkeys = 0; - var keys; - var comlen = 0; - var comment = false; - var accept; - var reject; - - if (typeof key === 'function' && typeof keyType === 'function') { - // agent forwarding - accept = key; - reject = keyType; - } else if (isSigning) { - keylen = key.length; - datalen = data.length; - } else { - cb = key; - key = undefined; +'use strict'; + +const { Socket } = require('net'); +const { Duplex } = require('stream'); +const { resolve } = require('path'); +const { readFile } = require('fs'); +const { execFile, spawn } = require('child_process'); + +const { isParsedKey, parseKey } = require('./protocol/keyParser.js'); + +const { + makeBufferParser, + readUInt32BE, + writeUInt32BE, + writeUInt32LE, +} = require('./protocol/utils.js'); + +function once(cb) { + let called = false; + return (...args) => { + if (called) + return; + called = true; + cb(...args); + }; +} + +function concat(buf1, buf2) { + const combined = Buffer.allocUnsafe(buf1.length + buf2.length); + buf1.copy(combined, 0); + buf2.copy(combined, buf1.length); + return combined; +} + +function noop() {} + +const EMPTY_BUF = Buffer.alloc(0); + +const binaryParser = makeBufferParser(); + +class BaseAgent { + getIdentities(cb) { + cb(new Error('Missing getIdentities() implementation')); + } + sign(pubKey, data, options, cb) { + if (typeof options === 'function') + cb = options; + cb(new Error('Missing sign() implementation')); } +} - function onconnect() { - var buf; - if (isSigning) { - /* - byte SSH2_AGENTC_SIGN_REQUEST - string key_blob - string data - uint32 flags - */ - var p = 9; - buf = new Buffer(4 + 1 + 4 + keylen + 4 + datalen + 4); - buf.writeUInt32BE(buf.length - 4, 0, true); - buf[4] = SIGN_REQUEST; - buf.writeUInt32BE(keylen, 5, true); - key.copy(buf, p); - buf.writeUInt32BE(datalen, p += keylen, true); - data.copy(buf, p += 4); - buf.writeUInt32BE(0, p += datalen, true); - sock.write(buf); - } else { - /* - byte SSH2_AGENTC_REQUEST_IDENTITIES - */ - sock.write(new Buffer([0, 0, 0, 1, REQUEST_IDENTITIES])); +class OpenSSHAgent extends BaseAgent { + constructor(socketPath) { + super(); + this.socketPath = socketPath; + } + + getStream(cb) { + cb = once(cb); + const sock = new Socket(); + sock.on('connect', () => { + cb(null, sock); + }); + sock.on('close', onFail) + .on('end', onFail) + .on('error', onFail); + sock.connect(this.socketPath); + + function onFail() { + try { + sock.destroy(); + } catch {} + + cb(new Error('Failed to connect to agent')); } } - function ondata(chunk) { - for (var i = 0, len = chunk.length; i < len; ++i) { - if (type === undefined) { - // skip over packet length - if (++count === 5) { - type = chunk[i]; - count = 0; - } - } else if (type === SIGN_RESPONSE) { - /* - byte SSH2_AGENT_SIGN_RESPONSE - string signature_blob - */ - if (!sig) { - siglen <<= 8; - siglen += chunk[i]; - if (++count === 4) { - sig = new Buffer(siglen); - count = 0; - } - } else { - sig[count] = chunk[i]; - if (++count === siglen) { - sock.removeAllListeners('data'); - return sock.destroy(); - } - } - } else if (type === IDENTITIES_ANSWER) { - /* - byte SSH2_AGENT_IDENTITIES_ANSWER - uint32 num_keys - - Followed by zero or more consecutive keys, encoded as: - - string public key blob - string public key comment - */ - if (keys === undefined) { - nkeys <<= 8; - nkeys += chunk[i]; - if (++count === 4) { - keys = new Array(nkeys); - count = 0; - if (nkeys === 0) { - sock.removeAllListeners('data'); - return sock.destroy(); - } - } - } else { - if (!key) { - keylen <<= 8; - keylen += chunk[i]; - if (++count === 4) { - key = new Buffer(keylen); - count = 0; - } - } else if (comment === false) { - key[count] = chunk[i]; - if (++count === keylen) { - keys[nkeys - 1] = key; - keylen = 0; - count = 0; - comment = true; - if (--nkeys === 0) { - key = undefined; - sock.removeAllListeners('data'); - return sock.destroy(); - } - } - } else if (comment === true) { - comlen <<= 8; - comlen += chunk[i]; - if (++count === 4) { - count = 0; - if (comlen > 0) - comment = comlen; - else { - key = undefined; - comment = false; - } - comlen = 0; - } - } else { - // skip comments - if (++count === comment) { - comment = false; - count = 0; - key = undefined; - } - } + + getIdentities(cb) { + cb = once(cb); + this.getStream((err, stream) => { + function onFail(err) { + if (stream) { + try { + stream.destroy(); + } catch {} } - } else if (type === FAILURE) { - if (isSigning) - error = new Error('Agent unable to sign data'); - else - error = new Error('Unable to retrieve list of keys from agent'); - sock.removeAllListeners('data'); - return sock.destroy(); + if (!err) + err = new Error('Failed to retrieve identities from agent'); + cb(err); } + + if (err) + return onFail(err); + + const protocol = new AgentProtocol(true); + protocol.on('error', onFail); + protocol.pipe(stream).pipe(protocol); + + stream.on('close', onFail) + .on('end', onFail) + .on('error', onFail); + + protocol.getIdentities((err, keys) => { + if (err) + return onFail(err); + try { + stream.destroy(); + } catch {} + cb(null, keys); + }); + }); + } + + sign(pubKey, data, options, cb) { + if (typeof options === 'function') { + cb = options; + options = undefined; + } else if (typeof options !== 'object' || options === null) { + options = undefined; } + + cb = once(cb); + this.getStream((err, stream) => { + function onFail(err) { + if (stream) { + try { + stream.destroy(); + } catch {} + } + if (!err) + err = new Error('Failed to sign data with agent'); + cb(err); + } + + if (err) + return onFail(err); + + const protocol = new AgentProtocol(true); + protocol.on('error', onFail); + protocol.pipe(stream).pipe(protocol); + + stream.on('close', onFail) + .on('end', onFail) + .on('error', onFail); + + protocol.sign(pubKey, data, options, (err, sig) => { + if (err) + return onFail(err); + + try { + stream.destroy(); + } catch {} + + cb(null, sig); + }); + }); } - function onerror(err) { - error = err; +} + +const PageantAgent = (() => { + const RET_ERR_BADARGS = 10; + const RET_ERR_UNAVAILABLE = 11; + const RET_ERR_NOMAP = 12; + const RET_ERR_BINSTDIN = 13; + const RET_ERR_BINSTDOUT = 14; + const RET_ERR_BADLEN = 15; + + const EXEPATH = resolve(__dirname, '..', 'util/pagent.exe'); + const ERROR = { + [RET_ERR_BADARGS]: new Error('Invalid pagent.exe arguments'), + [RET_ERR_UNAVAILABLE]: new Error('Pageant is not running'), + [RET_ERR_NOMAP]: new Error('pagent.exe could not create an mmap'), + [RET_ERR_BINSTDIN]: new Error('pagent.exe could not set mode for stdin'), + [RET_ERR_BINSTDOUT]: new Error('pagent.exe could not set mode for stdout'), + [RET_ERR_BADLEN]: + new Error('pagent.exe did not get expected input payload'), + }; + + function destroy(stream) { + stream.buffer = null; + if (stream.proc) { + stream.proc.kill(); + stream.proc = undefined; + } } - function onclose() { - if (error) - cb(error); - else if ((isSigning && !sig) || (!isSigning && !keys)) - cb(new Error('Unexpected disconnection from agent')); - else if (isSigning && sig) - cb(undefined, sig); - else if (!isSigning && keys) - cb(undefined, keys); + + class PageantSocket extends Duplex { + constructor() { + super(); + this.proc = undefined; + this.buffer = null; + } + _read(n) {} + _write(data, encoding, cb) { + if (this.buffer === null) { + this.buffer = data; + } else { + const newBuffer = Buffer.allocUnsafe(this.buffer.length + data.length); + this.buffer.copy(newBuffer, 0); + data.copy(newBuffer, this.buffer.length); + this.buffer = newBuffer; + } + // Wait for at least all length bytes + if (this.buffer.length < 4) + return cb(); + + const len = readUInt32BE(this.buffer, 0); + // Make sure we have a full message before querying pageant + if ((this.buffer.length - 4) < len) + return cb(); + + data = this.buffer.slice(0, 4 + len); + if (this.buffer.length > (4 + len)) + return cb(new Error('Unexpected multiple agent requests')); + this.buffer = null; + + let error; + const proc = this.proc = spawn(EXEPATH, [ data.length ]); + proc.stdout.on('data', (data) => { + this.push(data); + }); + proc.on('error', (err) => { + error = err; + cb(error); + }); + proc.on('close', (code) => { + this.proc = undefined; + if (!error) { + if (error = ERROR[code]) + return cb(error); + cb(); + } + }); + proc.stdin.end(data); + } + _final(cb) { + destroy(this); + cb(); + } + _destroy(err, cb) { + destroy(this); + cb(); + } } - if (process.platform === 'win32') { - if (sockPath === 'pageant') { - // Pageant (PuTTY authentication agent) - sock = new PageantSock(); - } else { - // cygwin ssh-agent instance - var triedCygpath = false; - fs.readFile(sockPath, function readCygsocket(err, data) { + return class PageantAgent extends OpenSSHAgent { + getStream(cb) { + cb(null, new PageantSocket()); + } + }; +})(); + +const CygwinAgent = (() => { + const RE_CYGWIN_SOCK = /^!(\d+) s ([A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})/; + + return class CygwinAgent extends OpenSSHAgent { + getStream(cb) { + cb = once(cb); + + // The cygwin ssh-agent connection process looks like this: + // 1. Read the "socket" as a file to get the underlying TCP port and a + // special "secret" that must be sent to the TCP server. + // 2. Connect to the server listening on localhost at the TCP port. + // 3. Send the "secret" to the server. + // 4. The server sends back the same "secret". + // 5. Send three 32-bit integer values of zero. This is ordinarily the + // pid, uid, and gid of this process, but cygwin will actually + // send us the correct values as a response. + // 6. The server sends back the pid, uid, gid. + // 7. Disconnect. + // 8. Repeat steps 2-6, except send the received pid, uid, and gid in + // step 5 instead of zeroes. + // 9. Connection is ready to be used. + + let socketPath = this.socketPath; + let triedCygpath = false; + readFile(socketPath, function readCygsocket(err, data) { if (err) { if (triedCygpath) return cb(new Error('Invalid cygwin unix socket path')); - // try using `cygpath` to convert a possible *nix-style path to the + + // Try using `cygpath` to convert a possible *nix-style path to the // real Windows path before giving up ... - cp.exec('cygpath -w "' + sockPath + '"', - function(err, stdout, stderr) { + execFile('cygpath', ['-w', socketPath], (err, stdout, stderr) => { if (err || stdout.length === 0) return cb(new Error('Invalid cygwin unix socket path')); + triedCygpath = true; - sockPath = stdout.toString().replace(/[\r\n]/g, ''); - fs.readFile(sockPath, readCygsocket); + socketPath = stdout.toString().replace(/[\r\n]/g, ''); + readFile(socketPath, readCygsocket); }); return; } - var m; - if (m = RE_CYGWIN_SOCK.exec(data.toString('ascii'))) { - var port; - var secret; - var secretbuf; - var state; - var bc = 0; - var isRetrying = false; - var inbuf = []; - var credsbuf = new Buffer(12); - var i; - var j; - - // use 0 for pid, uid, and gid to ensure we get an error and also - // a valid uid and gid from cygwin so that we don't have to figure it - // out ourselves - credsbuf.fill(0); - - // parse cygwin unix socket file contents - port = parseInt(m[1], 10); - secret = m[2].replace(/\-/g, ''); - secretbuf = new Buffer(16); - for (i = 0, j = 0; j < 32; ++i,j+=2) - secretbuf[i] = parseInt(secret.substring(j, j + 2), 16); - - // convert to host order (always LE for Windows) - for (i = 0; i < 16; i += 4) - secretbuf.writeUInt32LE(secretbuf.readUInt32BE(i, true), i, true); - - function _onconnect() { - bc = 0; - state = 'secret'; - sock.write(secretbuf); + const m = RE_CYGWIN_SOCK.exec(data.toString('ascii')); + if (!m) + return cb(new Error('Malformed cygwin unix socket file')); + + let state; + let bc = 0; + let isRetrying = false; + const inBuf = []; + let sock; + + // Use 0 for pid, uid, and gid to ensure we get an error and also + // a valid uid and gid from cygwin so that we don't have to figure it + // out ourselves + let credsBuf = Buffer.alloc(12); + + // Parse cygwin unix socket file contents + const port = parseInt(m[1], 10); + const secret = m[2].replace(/-/g, ''); + const secretBuf = Buffer.allocUnsafe(16); + for (let i = 0, j = 0; j < 32; ++i, j += 2) + secretBuf[i] = parseInt(secret.substring(j, j + 2), 16); + + // Convert to host order (always LE for Windows) + for (let i = 0; i < 16; i += 4) + writeUInt32LE(secretBuf, readUInt32BE(secretBuf, i), i); + + tryConnect(); + + function _onconnect() { + bc = 0; + state = 'secret'; + sock.write(secretBuf); + } + + function _ondata(data) { + bc += data.length; + + if (state === 'secret') { + // The secret we sent is echoed back to us by cygwin, not sure of + // the reason for that, but we ignore it nonetheless ... + if (bc === 16) { + bc = 0; + state = 'creds'; + sock.write(credsBuf); + } + return; + } + + if (state === 'creds') { + // If this is the first attempt, make sure to gather the valid + // uid and gid for our next attempt + if (!isRetrying) + inBuf.push(data); + + if (bc === 12) { + sock.removeListener('connect', _onconnect); + sock.removeListener('data', _ondata); + sock.removeListener('error', onFail); + sock.removeListener('end', onFail); + sock.removeListener('close', onFail); + + if (isRetrying) + return cb(null, sock); + + isRetrying = true; + credsBuf = Buffer.concat(inBuf); + writeUInt32LE(credsBuf, process.pid, 0); + sock.on('error', () => {}); + sock.destroy(); + + tryConnect(); + } } - function _ondata(data) { - bc += data.length; - if (state === 'secret') { - // the secret we sent is echoed back to us by cygwin, not sure of - // the reason for that, but we ignore it nonetheless ... - if (bc === 16) { - bc = 0; - state = 'creds'; - sock.write(credsbuf); + } + + function onFail() { + cb(new Error('Problem negotiating cygwin unix socket security')); + } + + function tryConnect() { + sock = new Socket(); + sock.on('connect', _onconnect); + sock.on('data', _ondata); + sock.on('error', onFail); + sock.on('end', onFail); + sock.on('close', onFail); + sock.connect(port); + } + }); + } + }; +})(); + +// Format of `//./pipe/ANYTHING`, with forward slashes and backward slashes +// being interchangeable +const WINDOWS_PIPE_REGEX = /^[/\\][/\\]\.[/\\]pipe[/\\].+/; +function createAgent(path) { + if (process.platform === 'win32' && !WINDOWS_PIPE_REGEX.test(path)) { + return (path === 'pageant' + ? new PageantAgent() + : new CygwinAgent(path)); + } + return new OpenSSHAgent(path); +} + +const AgentProtocol = (() => { + // Client->Server messages + const SSH_AGENTC_REQUEST_IDENTITIES = 11; + const SSH_AGENTC_SIGN_REQUEST = 13; + // const SSH_AGENTC_ADD_IDENTITY = 17; + // const SSH_AGENTC_REMOVE_IDENTITY = 18; + // const SSH_AGENTC_REMOVE_ALL_IDENTITIES = 19; + // const SSH_AGENTC_ADD_SMARTCARD_KEY = 20; + // const SSH_AGENTC_REMOVE_SMARTCARD_KEY = 21; + // const SSH_AGENTC_LOCK = 22; + // const SSH_AGENTC_UNLOCK = 23; + // const SSH_AGENTC_ADD_ID_CONSTRAINED = 25; + // const SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED = 26; + // const SSH_AGENTC_EXTENSION = 27; + // Server->Client messages + const SSH_AGENT_FAILURE = 5; + // const SSH_AGENT_SUCCESS = 6; + const SSH_AGENT_IDENTITIES_ANSWER = 12; + const SSH_AGENT_SIGN_RESPONSE = 14; + // const SSH_AGENT_EXTENSION_FAILURE = 28; + + // const SSH_AGENT_CONSTRAIN_LIFETIME = 1; + // const SSH_AGENT_CONSTRAIN_CONFIRM = 2; + // const SSH_AGENT_CONSTRAIN_EXTENSION = 255; + + const SSH_AGENT_RSA_SHA2_256 = (1 << 1); + const SSH_AGENT_RSA_SHA2_512 = (1 << 2); + + const ROLE_CLIENT = 0; + const ROLE_SERVER = 1; + + // Ensures that responses get sent back in the same order the requests were + // received + function processResponses(protocol) { + let ret; + while (protocol[SYM_REQS].length) { + const nextResponse = protocol[SYM_REQS][0][SYM_RESP]; + if (nextResponse === undefined) + break; + + protocol[SYM_REQS].shift(); + ret = protocol.push(nextResponse); + } + return ret; + } + + const SYM_TYPE = Symbol('Inbound Request Type'); + const SYM_RESP = Symbol('Inbound Request Response'); + const SYM_CTX = Symbol('Inbound Request Context'); + class AgentInboundRequest { + constructor(type, ctx) { + this[SYM_TYPE] = type; + this[SYM_RESP] = undefined; + this[SYM_CTX] = ctx; + } + hasResponded() { + return (this[SYM_RESP] !== undefined); + } + getType() { + return this[SYM_TYPE]; + } + getContext() { + return this[SYM_CTX]; + } + } + function respond(protocol, req, data) { + req[SYM_RESP] = data; + return processResponses(protocol); + } + + function cleanup(protocol) { + protocol[SYM_BUFFER] = null; + if (protocol[SYM_MODE] === ROLE_CLIENT) { + const reqs = protocol[SYM_REQS]; + if (reqs && reqs.length) { + protocol[SYM_REQS] = []; + for (const req of reqs) + req.cb(new Error('No reply from server')); + } + } + + // Node streams hackery to make streams do the "right thing" + try { + protocol.end(); + } catch {} + setImmediate(() => { + if (!protocol[SYM_ENDED]) + protocol.emit('end'); + if (!protocol[SYM_CLOSED]) + protocol.emit('close'); + }); + } + + function onClose() { + this[SYM_CLOSED] = true; + } + + function onEnd() { + this[SYM_ENDED] = true; + } + + const SYM_REQS = Symbol('Requests'); + const SYM_MODE = Symbol('Agent Protocol Role'); + const SYM_BUFFER = Symbol('Agent Protocol Buffer'); + const SYM_MSGLEN = Symbol('Agent Protocol Current Message Length'); + const SYM_CLOSED = Symbol('Agent Protocol Closed'); + const SYM_ENDED = Symbol('Agent Protocol Ended'); + // Implementation based on: + // https://tools.ietf.org/html/draft-miller-ssh-agent-04 + return class AgentProtocol extends Duplex { + /* + Notes: + - `constraint` type consists of: + byte constraint_type + byte[] constraint_data + where `constraint_type` is one of: + * SSH_AGENT_CONSTRAIN_LIFETIME + - `constraint_data` consists of: + uint32 seconds + * SSH_AGENT_CONSTRAIN_CONFIRM + - `constraint_data` N/A + * SSH_AGENT_CONSTRAIN_EXTENSION + - `constraint_data` consists of: + string extension name + byte[] extension-specific details + */ + + constructor(isClient) { + super({ autoDestroy: true, emitClose: false }); + this[SYM_MODE] = (isClient ? ROLE_CLIENT : ROLE_SERVER); + this[SYM_REQS] = []; + this[SYM_BUFFER] = null; + this[SYM_MSGLEN] = -1; + this.once('end', onEnd); + this.once('close', onClose); + } + + _read(n) {} + + _write(data, encoding, cb) { + /* + Messages are of the format: + uint32 message length + byte message type + byte[message length - 1] message contents + */ + if (this[SYM_BUFFER] === null) + this[SYM_BUFFER] = data; + else + this[SYM_BUFFER] = concat(this[SYM_BUFFER], data); + + let buffer = this[SYM_BUFFER]; + let bufferLen = buffer.length; + + let p = 0; + while (p < bufferLen) { + // Wait for length + type + if (bufferLen < 5) + break; + + if (this[SYM_MSGLEN] === -1) + this[SYM_MSGLEN] = readUInt32BE(buffer, p); + + // Check if we have the entire message + if (bufferLen < (4 + this[SYM_MSGLEN])) + break; + + const msgType = buffer[p += 4]; + ++p; + + if (this[SYM_MODE] === ROLE_CLIENT) { + if (this[SYM_REQS].length === 0) + return cb(new Error('Received unexpected message from server')); + + const req = this[SYM_REQS].shift(); + + switch (msgType) { + case SSH_AGENT_FAILURE: + req.cb(new Error('Agent responded with failure')); + break; + case SSH_AGENT_IDENTITIES_ANSWER: { + if (req.type !== SSH_AGENTC_REQUEST_IDENTITIES) + return cb(new Error('Agent responded with wrong message type')); + + /* + byte SSH_AGENT_IDENTITIES_ANSWER + uint32 nkeys + + where `nkeys` is 0 or more of: + string key blob + string comment + */ + + binaryParser.init(buffer, p); + + const numKeys = binaryParser.readUInt32BE(); + + if (numKeys === undefined) { + binaryParser.clear(); + return cb(new Error('Malformed agent response')); } - } else if (state === 'creds') { - // if this is the first attempt, make sure to gather the valid - // uid and gid for our next attempt - if (!isRetrying) - inbuf.push(data); - - if (bc === 12) { - sock.removeListener('connect', _onconnect); - sock.removeListener('data', _ondata); - sock.removeListener('close', _onclose); - if (isRetrying) { - addSockListeners(); - sock.emit('connect'); - } else { - isRetrying = true; - credsbuf = Buffer.concat(inbuf); - credsbuf.writeUInt32LE(process.pid, 0, true); - sock.destroy(); - tryConnect(); + + const keys = []; + for (let i = 0; i < numKeys; ++i) { + let pubKey = binaryParser.readString(); + if (pubKey === undefined) { + binaryParser.clear(); + return cb(new Error('Malformed agent response')); } + + const comment = binaryParser.readString(true); + if (comment === undefined) { + binaryParser.clear(); + return cb(new Error('Malformed agent response')); + } + + pubKey = parseKey(pubKey); + // We continue parsing the packet if we encounter an error + // in case the error is due to the key being an unsupported + // type + if (pubKey instanceof Error) + continue; + + pubKey.comment = pubKey.comment || comment; + + keys.push(pubKey); } + p = binaryParser.pos(); + binaryParser.clear(); + + req.cb(null, keys); + break; } + case SSH_AGENT_SIGN_RESPONSE: { + if (req.type !== SSH_AGENTC_SIGN_REQUEST) + return cb(new Error('Agent responded with wrong message type')); + + /* + byte SSH_AGENT_SIGN_RESPONSE + string signature + */ + + binaryParser.init(buffer, p); + let signature = binaryParser.readString(); + p = binaryParser.pos(); + binaryParser.clear(); + + if (signature === undefined) + return cb(new Error('Malformed agent response')); + + // We strip the algorithm from OpenSSH's output and assume it's + // using the algorithm we specified. This makes it easier on + // custom Agent implementations so they don't have to construct + // the correct binary format for a (OpenSSH-style) signature. + + // TODO: verify signature type based on key and options used + // during initial sign request + binaryParser.init(signature, 0); + binaryParser.readString(true); + signature = binaryParser.readString(); + binaryParser.clear(); + + if (signature === undefined) + return cb(new Error('Malformed OpenSSH signature format')); + + req.cb(null, signature); + break; + } + default: + return cb( + new Error('Agent responded with unsupported message type') + ); } - function _onclose() { - cb(new Error('Problem negotiating cygwin unix socket security')); - } - function tryConnect() { - sock = new Socket(); - sock.once('connect', _onconnect); - sock.on('data', _ondata); - sock.once('close', _onclose); - sock.connect(port); + } else { + switch (msgType) { + case SSH_AGENTC_REQUEST_IDENTITIES: { + const req = new AgentInboundRequest(msgType); + this[SYM_REQS].push(req); + /* + byte SSH_AGENTC_REQUEST_IDENTITIES + */ + this.emit('identities', req); + break; + } + case SSH_AGENTC_SIGN_REQUEST: { + /* + byte SSH_AGENTC_SIGN_REQUEST + string key_blob + string data + uint32 flags + */ + binaryParser.init(buffer, p); + let pubKey = binaryParser.readString(); + const data = binaryParser.readString(); + const flagsVal = binaryParser.readUInt32BE(); + p = binaryParser.pos(); + binaryParser.clear(); + if (flagsVal === undefined) { + const req = new AgentInboundRequest(msgType); + this[SYM_REQS].push(req); + return this.failureReply(req); + } + + pubKey = parseKey(pubKey); + if (pubKey instanceof Error) { + const req = new AgentInboundRequest(msgType); + this[SYM_REQS].push(req); + return this.failureReply(req); + } + + const flags = { + hash: undefined, + }; + let ctx; + if (pubKey.type === 'ssh-rsa') { + if (flagsVal & SSH_AGENT_RSA_SHA2_256) { + ctx = 'rsa-sha2-256'; + flags.hash = 'sha256'; + } else if (flagsVal & SSH_AGENT_RSA_SHA2_512) { + ctx = 'rsa-sha2-512'; + flags.hash = 'sha512'; + } + } + if (ctx === undefined) + ctx = pubKey.type; + + const req = new AgentInboundRequest(msgType, ctx); + this[SYM_REQS].push(req); + + this.emit('sign', req, pubKey, data, flags); + break; + } + default: { + const req = new AgentInboundRequest(msgType); + this[SYM_REQS].push(req); + this.failureReply(req); + } } - tryConnect(); - } else - cb(new Error('Malformed cygwin unix socket file')); - }); - return; + } + + // Get ready for next message + this[SYM_MSGLEN] = -1; + if (p === bufferLen) { + // Nothing left to process for now + this[SYM_BUFFER] = null; + break; + } else { + this[SYM_BUFFER] = buffer = buffer.slice(p); + bufferLen = buffer.length; + p = 0; + } + } + + cb(); } - } else - sock = new Socket(); - - function addSockListeners() { - if (!accept && !reject) { - sock.once('connect', onconnect); - sock.on('data', ondata); - sock.once('error', onerror); - sock.once('close', onclose); - } else { - var chan; - sock.once('connect', function() { - chan = accept(); - var isDone = false; - function onDone() { - if (isDone) - return; - sock.destroy(); - isDone = true; + + _destroy(err, cb) { + cleanup(this); + cb(); + } + + _final(cb) { + cleanup(this); + cb(); + } + + // Client->Server messages ================================================= + sign(pubKey, data, options, cb) { + if (this[SYM_MODE] !== ROLE_CLIENT) + throw new Error('Client-only method called with server role'); + + if (typeof options === 'function') { + cb = options; + options = undefined; + } else if (typeof options !== 'object' || options === null) { + options = undefined; + } + + let flags = 0; + + pubKey = parseKey(pubKey); + if (pubKey instanceof Error) + throw new Error('Invalid public key argument'); + + if (pubKey.type === 'ssh-rsa' && options) { + switch (options.hash) { + case 'sha256': + flags = SSH_AGENT_RSA_SHA2_256; + break; + case 'sha512': + flags = SSH_AGENT_RSA_SHA2_512; + break; } - chan.once('end', onDone) - .once('close', onDone) - .on('data', function(data) { - sock.write(data); - }); - sock.on('data', function(data) { - chan.write(data); - }); - }); - sock.once('close', function() { - if (!chan) - reject(); - }); + } + pubKey = pubKey.getPublicSSH(); + + /* + byte SSH_AGENTC_SIGN_REQUEST + string key_blob + string data + uint32 flags + */ + const type = SSH_AGENTC_SIGN_REQUEST; + const keyLen = pubKey.length; + const dataLen = data.length; + let p = 0; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + keyLen + 4 + dataLen + 4); + + writeUInt32BE(buf, buf.length - 4, p); + + buf[p += 4] = type; + + writeUInt32BE(buf, keyLen, ++p); + pubKey.copy(buf, p += 4); + + writeUInt32BE(buf, dataLen, p += keyLen); + data.copy(buf, p += 4); + + writeUInt32BE(buf, flags, p += dataLen); + + if (typeof cb !== 'function') + cb = noop; + + this[SYM_REQS].push({ type, cb }); + + return this.push(buf); } - } - addSockListeners(); - sock.connect(sockPath); -}; + getIdentities(cb) { + if (this[SYM_MODE] !== ROLE_CLIENT) + throw new Error('Client-only method called with server role'); + /* + byte SSH_AGENTC_REQUEST_IDENTITIES + */ + const type = SSH_AGENTC_REQUEST_IDENTITIES; -// win32 only ------------------------------------------------------------------ -if (process.platform === 'win32') { - var RET_ERR_BADARGS = 10; - var RET_ERR_UNAVAILABLE = 11; - var RET_ERR_NOMAP = 12; - var RET_ERR_BINSTDIN = 13; - var RET_ERR_BINSTDOUT = 14; - var RET_ERR_BADLEN = 15; - - var ERROR = {}; - var EXEPATH = path.resolve(__dirname, '..', 'util/pagent.exe'); - ERROR[RET_ERR_BADARGS] = new Error('Invalid pagent.exe arguments'); - ERROR[RET_ERR_UNAVAILABLE] = new Error('Pageant is not running'); - ERROR[RET_ERR_NOMAP] = new Error('pagent.exe could not create an mmap'); - ERROR[RET_ERR_BINSTDIN] = new Error('pagent.exe could not set mode for stdin'); - ERROR[RET_ERR_BINSTDOUT] = new Error('pagent.exe could not set mode for stdout'); - ERROR[RET_ERR_BADLEN] = new Error('pagent.exe did not get expected input payload'); - - function PageantSock() { - this.proc = undefined; - this.buffer = null; - } - inherits(PageantSock, EventEmitter); - - PageantSock.prototype.write = function(buf) { - if (this.buffer === null) - this.buffer = buf; - else { - this.buffer = Buffer.concat([this.buffer, buf], - this.buffer.length + buf.length); + let p = 0; + const buf = Buffer.allocUnsafe(4 + 1); + + writeUInt32BE(buf, buf.length - 4, p); + + buf[p += 4] = type; + + if (typeof cb !== 'function') + cb = noop; + + this[SYM_REQS].push({ type, cb }); + + return this.push(buf); } - // Wait for at least all length bytes - if (this.buffer.length < 4) - return; - var len = this.buffer.readUInt32BE(0, true); - // Make sure we have a full message before querying pageant - if ((this.buffer.length - 4) < len) - return; + // Server->Client messages ================================================= + failureReply(req) { + if (this[SYM_MODE] !== ROLE_SERVER) + throw new Error('Server-only method called with client role'); - buf = this.buffer.slice(0, 4 + len); - if (this.buffer.length > (4 + len)) - this.buffer = this.buffer.slice(4 + len); - else - this.buffer = null; + if (!(req instanceof AgentInboundRequest)) + throw new Error('Wrong request argument'); - var self = this; - var proc; - var hadError = false; - proc = this.proc = cp.spawn(EXEPATH, [ buf.length ]); - proc.stdout.on('data', function(data) { - self.emit('data', data); - }); - proc.once('error', function(err) { - if (!hadError) { - hadError = true; - self.emit('error', err); + if (req.hasResponded()) + return true; + + let p = 0; + const buf = Buffer.allocUnsafe(4 + 1); + + writeUInt32BE(buf, buf.length - 4, p); + + buf[p += 4] = SSH_AGENT_FAILURE; + + return respond(this, req, buf); + } + getIdentitiesReply(req, keys) { + if (this[SYM_MODE] !== ROLE_SERVER) + throw new Error('Server-only method called with client role'); + + if (!(req instanceof AgentInboundRequest)) + throw new Error('Wrong request argument'); + + if (req.hasResponded()) + return true; + + /* + byte SSH_AGENT_IDENTITIES_ANSWER + uint32 nkeys + + where `nkeys` is 0 or more of: + string key blob + string comment + */ + + if (req.getType() !== SSH_AGENTC_REQUEST_IDENTITIES) + throw new Error('Invalid response to request'); + + if (!Array.isArray(keys)) + throw new Error('Keys argument must be an array'); + + let totalKeysLen = 4; // Include `nkeys` size + + const newKeys = []; + for (let i = 0; i < keys.length; ++i) { + const entry = keys[i]; + if (typeof entry !== 'object' || entry === null) + throw new Error(`Invalid key entry: ${entry}`); + + let pubKey; + let comment; + if (isParsedKey(entry)) { + pubKey = entry; + } else if (isParsedKey(entry.pubKey)) { + pubKey = entry.pubKey; + } else { + if (typeof entry.pubKey !== 'object' || entry.pubKey === null) + continue; + ({ pubKey, comment } = entry.pubKey); + pubKey = parseKey(pubKey); + if (pubKey instanceof Error) + continue; // TODO: add debug output + } + comment = pubKey.comment || comment; + pubKey = pubKey.getPublicSSH(); + + totalKeysLen += 4 + pubKey.length; + + if (comment && typeof comment === 'string') + comment = Buffer.from(comment); + else if (!Buffer.isBuffer(comment)) + comment = EMPTY_BUF; + + totalKeysLen += 4 + comment.length; + + newKeys.push({ pubKey, comment }); } - }); - proc.once('close', function(code) { - self.proc = undefined; - if (ERROR[code] && !hadError) { - hadError = true; - self.emit('error', ERROR[code]); + + let p = 0; + const buf = Buffer.allocUnsafe(4 + 1 + totalKeysLen); + + writeUInt32BE(buf, buf.length - 4, p); + + buf[p += 4] = SSH_AGENT_IDENTITIES_ANSWER; + + writeUInt32BE(buf, newKeys.length, ++p); + p += 4; + for (let i = 0; i < newKeys.length; ++i) { + const { pubKey, comment } = newKeys[i]; + + writeUInt32BE(buf, pubKey.length, p); + pubKey.copy(buf, p += 4); + + writeUInt32BE(buf, comment.length, p += pubKey.length); + p += 4; + if (comment.length) { + comment.copy(buf, p); + p += comment.length; + } } - self.emit('close', hadError); - }); - proc.stdin.end(buf); - }; - PageantSock.prototype.end = PageantSock.prototype.destroy = function() { - this.buffer = null; - if (this.proc) { - this.proc.kill(); - this.proc = undefined; + + return respond(this, req, buf); + } + signReply(req, signature) { + if (this[SYM_MODE] !== ROLE_SERVER) + throw new Error('Server-only method called with client role'); + + if (!(req instanceof AgentInboundRequest)) + throw new Error('Wrong request argument'); + + if (req.hasResponded()) + return true; + + /* + byte SSH_AGENT_SIGN_RESPONSE + string signature + */ + + if (req.getType() !== SSH_AGENTC_SIGN_REQUEST) + throw new Error('Invalid response to request'); + + if (!Buffer.isBuffer(signature)) + throw new Error('Signature argument must be a Buffer'); + + if (signature.length === 0) + throw new Error('Signature argument must be non-empty'); + + /* + OpenSSH agent signatures are encoded as: + + string signature format identifier (as specified by the + public key/certificate format) + byte[n] signature blob in format specific encoding. + - This is actually a `string` for: rsa, dss, ecdsa, and ed25519 + types + */ + + let p = 0; + const sigFormat = req.getContext(); + const sigFormatLen = Buffer.byteLength(sigFormat); + const buf = Buffer.allocUnsafe( + 4 + 1 + 4 + 4 + sigFormatLen + 4 + signature.length + ); + + writeUInt32BE(buf, buf.length - 4, p); + + buf[p += 4] = SSH_AGENT_SIGN_RESPONSE; + + writeUInt32BE(buf, 4 + sigFormatLen + 4 + signature.length, ++p); + writeUInt32BE(buf, sigFormatLen, p += 4); + buf.utf8Write(sigFormat, p += 4, sigFormatLen); + writeUInt32BE(buf, signature.length, p += sigFormatLen); + signature.copy(buf, p += 4); + + return respond(this, req, buf); } }; - PageantSock.prototype.connect = function() { - this.emit('connect'); - }; +})(); + +const SYM_AGENT = Symbol('Agent'); +const SYM_AGENT_KEYS = Symbol('Agent Keys'); +const SYM_AGENT_KEYS_IDX = Symbol('Agent Keys Index'); +const SYM_AGENT_CBS = Symbol('Agent Init Callbacks'); +class AgentContext { + constructor(agent) { + if (typeof agent === 'string') + agent = createAgent(agent); + else if (!isAgent(agent)) + throw new Error('Invalid agent argument'); + this[SYM_AGENT] = agent; + this[SYM_AGENT_KEYS] = null; + this[SYM_AGENT_KEYS_IDX] = -1; + this[SYM_AGENT_CBS] = null; + } + init(cb) { + if (typeof cb !== 'function') + cb = noop; + + if (this[SYM_AGENT_KEYS] === null) { + if (this[SYM_AGENT_CBS] === null) { + this[SYM_AGENT_CBS] = [cb]; + + const doCbs = (...args) => { + process.nextTick(() => { + const cbs = this[SYM_AGENT_CBS]; + this[SYM_AGENT_CBS] = null; + for (const cb of cbs) + cb(...args); + }); + }; + + this[SYM_AGENT].getIdentities(once((err, keys) => { + if (err) + return doCbs(err); + + if (!Array.isArray(keys)) { + return doCbs(new Error( + 'Agent implementation failed to provide keys' + )); + } + + const newKeys = []; + for (let key of keys) { + key = parseKey(key); + if (key instanceof Error) { + // TODO: add debug output + continue; + } + newKeys.push(key); + } + + this[SYM_AGENT_KEYS] = newKeys; + this[SYM_AGENT_KEYS_IDX] = -1; + doCbs(); + })); + } else { + this[SYM_AGENT_CBS].push(cb); + } + } else { + process.nextTick(cb); + } + } + nextKey() { + if (this[SYM_AGENT_KEYS] === null + || ++this[SYM_AGENT_KEYS_IDX] >= this[SYM_AGENT_KEYS].length) { + return false; + } + + return this[SYM_AGENT_KEYS][this[SYM_AGENT_KEYS_IDX]]; + } + currentKey() { + if (this[SYM_AGENT_KEYS] === null + || this[SYM_AGENT_KEYS_IDX] >= this[SYM_AGENT_KEYS].length) { + return null; + } + + return this[SYM_AGENT_KEYS][this[SYM_AGENT_KEYS_IDX]]; + } + pos() { + if (this[SYM_AGENT_KEYS] === null + || this[SYM_AGENT_KEYS_IDX] >= this[SYM_AGENT_KEYS].length) { + return -1; + } + + return this[SYM_AGENT_KEYS_IDX]; + } + reset() { + this[SYM_AGENT_KEYS_IDX] = -1; + } + + sign(...args) { + this[SYM_AGENT].sign(...args); + } +} + +function isAgent(val) { + return (val instanceof BaseAgent); } + +module.exports = { + AgentContext, + AgentProtocol, + BaseAgent, + createAgent, + CygwinAgent, + isAgent, + OpenSSHAgent, + PageantAgent, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/client.js b/reverse_engineering/node_modules/ssh2/lib/client.js index 1d49282..7c16c7b 100644 --- a/reverse_engineering/node_modules/ssh2/lib/client.js +++ b/reverse_engineering/node_modules/ssh2/lib/client.js @@ -1,1251 +1,1605 @@ -var crypto = require('crypto'); -var Socket = require('net').Socket; -var dnsLookup = require('dns').lookup; -var EventEmitter = require('events').EventEmitter; -var inherits = require('util').inherits; -var HASHES = crypto.getHashes(); - -var ssh2_streams = require('ssh2-streams'); -var SSH2Stream = ssh2_streams.SSH2Stream; -var SFTPStream = ssh2_streams.SFTPStream; -var consts = ssh2_streams.constants; -var BUGS = consts.BUGS; -var ALGORITHMS = consts.ALGORITHMS; -var parseKey = ssh2_streams.utils.parseKey; -var decryptKey = ssh2_streams.utils.decryptKey; -var genPublicKey = ssh2_streams.utils.genPublicKey; - -var Channel = require('./Channel'); -var agentQuery = require('./agent'); -var SFTPWrapper = require('./SFTPWrapper'); - -var MAX_CHANNEL = Math.pow(2, 32) - 1; -var RE_OPENSSH = /^OpenSSH_(?:(?![0-4])\d)|(?:\d{2,})/; -var DEBUG_NOOP = function(msg) {}; - -function Client() { - if (!(this instanceof Client)) - return new Client(); - - EventEmitter.call(this); - - this.config = { - host: undefined, - port: undefined, - forceIPv4: undefined, - forceIPv6: undefined, - keepaliveCountMax: undefined, - keepaliveInterval: undefined, - readyTimeout: undefined, - - username: undefined, - password: undefined, - privateKey: undefined, - publicKey: undefined, - tryKeyboard: undefined, - agent: undefined, - allowAgentFwd: undefined, - - hostHashAlgo: undefined, - hostHashCb: undefined, - strictVendor: undefined, - debug: undefined - }; - - this._readyTimeout = undefined; - this._channels = undefined; - this._callbacks = undefined; - this._forwarding = undefined; - this._acceptX11 = undefined; - this._agentFwdEnabled = undefined; - this._curChan = undefined; - this._remoteVer = undefined; - - this._sshstream = undefined; - this._sock = undefined; - this._resetKA = undefined; -} -inherits(Client, EventEmitter); - -Client.prototype.connect = function(cfg) { - var self = this; +// TODO: +// * add `.connected` or similar property to allow immediate connection +// status checking +// * add/improve debug output during user authentication phase +'use strict'; + +const { + createHash, + getHashes, + randomFillSync, +} = require('crypto'); +const { Socket } = require('net'); +const { lookup: dnsLookup } = require('dns'); +const EventEmitter = require('events'); +const HASHES = getHashes(); + +const { + COMPAT, + CHANNEL_EXTENDED_DATATYPE: { STDERR }, + CHANNEL_OPEN_FAILURE, + DEFAULT_CIPHER, + DEFAULT_COMPRESSION, + DEFAULT_KEX, + DEFAULT_MAC, + DEFAULT_SERVER_HOST_KEY, + DISCONNECT_REASON, + DISCONNECT_REASON_BY_VALUE, + SUPPORTED_CIPHER, + SUPPORTED_COMPRESSION, + SUPPORTED_KEX, + SUPPORTED_MAC, + SUPPORTED_SERVER_HOST_KEY, +} = require('./protocol/constants.js'); +const { init: cryptoInit } = require('./protocol/crypto.js'); +const Protocol = require('./protocol/Protocol.js'); +const { parseKey } = require('./protocol/keyParser.js'); +const { SFTP } = require('./protocol/SFTP.js'); +const { + bufferCopy, + makeBufferParser, + makeError, + readUInt32BE, + sigSSHToASN1, + writeUInt32BE, +} = require('./protocol/utils.js'); + +const { AgentContext, createAgent, isAgent } = require('./agent.js'); +const { + Channel, + MAX_WINDOW, + PACKET_SIZE, + windowAdjust, + WINDOW_THRESHOLD, +} = require('./Channel.js'); +const { + ChannelManager, + generateAlgorithmList, + isWritable, + onChannelOpenFailure, + onCHANNEL_CLOSE, +} = require('./utils.js'); + +const bufferParser = makeBufferParser(); +const sigParser = makeBufferParser(); +const RE_OPENSSH = /^OpenSSH_(?:(?![0-4])\d)|(?:\d{2,})/; +const noop = (err) => {}; + +class Client extends EventEmitter { + constructor() { + super(); + + this.config = { + host: undefined, + port: undefined, + localAddress: undefined, + localPort: undefined, + forceIPv4: undefined, + forceIPv6: undefined, + keepaliveCountMax: undefined, + keepaliveInterval: undefined, + readyTimeout: undefined, + ident: undefined, + + username: undefined, + password: undefined, + privateKey: undefined, + tryKeyboard: undefined, + agent: undefined, + allowAgentFwd: undefined, + authHandler: undefined, + + hostHashAlgo: undefined, + hostHashCb: undefined, + strictVendor: undefined, + debug: undefined + }; - if (this._sock && this._sock.writable) { - this.once('close', function() { - self.connect(cfg); - }); - this.end(); - return; + this._agent = undefined; + this._readyTimeout = undefined; + this._chanMgr = undefined; + this._callbacks = undefined; + this._forwarding = undefined; + this._forwardingUnix = undefined; + this._acceptX11 = undefined; + this._agentFwdEnabled = undefined; + this._remoteVer = undefined; + + this._protocol = undefined; + this._sock = undefined; + this._resetKA = undefined; } - this.config.host = cfg.hostname || cfg.host || 'localhost'; - this.config.port = cfg.port || 22; - this.config.forceIPv4 = cfg.forceIPv4 || false; - this.config.forceIPv6 = cfg.forceIPv6 || false; - this.config.keepaliveCountMax = (typeof cfg.keepaliveCountMax === 'number' - && cfg.keepaliveCountMax >= 0 - ? cfg.keepaliveCountMax - : 3); - this.config.keepaliveInterval = (typeof cfg.keepaliveInterval === 'number' - && cfg.keepaliveInterval > 0 - ? cfg.keepaliveInterval - : 0); - this.config.readyTimeout = (typeof cfg.readyTimeout === 'number' - && cfg.readyTimeout >= 0 - ? cfg.readyTimeout - : 20000); - - var algorithms = { - kex: undefined, - kexBuf: undefined, - cipher: undefined, - cipherBuf: undefined, - serverHostKey: undefined, - serverHostKeyBuf: undefined, - hmac: undefined, - hmacBuf: undefined, - compress: undefined, - compressBuf: undefined - }; - var i; - if (typeof cfg.algorithms === 'object' && cfg.algorithms !== null) { - var algosSupported; - var algoList; - - algoList = cfg.algorithms.kex; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_KEX; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported key exchange algorithm: ' + algoList[i]); - } - algorithms.kex = algoList; + connect(cfg) { + if (this._sock && isWritable(this._sock)) { + this.once('close', () => { + this.connect(cfg); + }); + this.end(); + return this; } - algoList = cfg.algorithms.cipher; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_CIPHER; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported cipher algorithm: ' + algoList[i]); - } - algorithms.cipher = algoList; + this.config.host = cfg.hostname || cfg.host || 'localhost'; + this.config.port = cfg.port || 22; + this.config.localAddress = (typeof cfg.localAddress === 'string' + ? cfg.localAddress + : undefined); + this.config.localPort = (typeof cfg.localPort === 'string' + || typeof cfg.localPort === 'number' + ? cfg.localPort + : undefined); + this.config.forceIPv4 = cfg.forceIPv4 || false; + this.config.forceIPv6 = cfg.forceIPv6 || false; + this.config.keepaliveCountMax = (typeof cfg.keepaliveCountMax === 'number' + && cfg.keepaliveCountMax >= 0 + ? cfg.keepaliveCountMax + : 3); + this.config.keepaliveInterval = (typeof cfg.keepaliveInterval === 'number' + && cfg.keepaliveInterval > 0 + ? cfg.keepaliveInterval + : 0); + this.config.readyTimeout = (typeof cfg.readyTimeout === 'number' + && cfg.readyTimeout >= 0 + ? cfg.readyTimeout + : 20000); + this.config.ident = (typeof cfg.ident === 'string' + || Buffer.isBuffer(cfg.ident) + ? cfg.ident + : undefined); + + const algorithms = { + kex: undefined, + serverHostKey: undefined, + cs: { + cipher: undefined, + mac: undefined, + compress: undefined, + lang: [], + }, + sc: undefined, + }; + let allOfferDefaults = true; + if (typeof cfg.algorithms === 'object' && cfg.algorithms !== null) { + algorithms.kex = generateAlgorithmList(cfg.algorithms.kex, + DEFAULT_KEX, + SUPPORTED_KEX); + if (algorithms.kex !== DEFAULT_KEX) + allOfferDefaults = false; + + algorithms.serverHostKey = + generateAlgorithmList(cfg.algorithms.serverHostKey, + DEFAULT_SERVER_HOST_KEY, + SUPPORTED_SERVER_HOST_KEY); + if (algorithms.serverHostKey !== DEFAULT_SERVER_HOST_KEY) + allOfferDefaults = false; + + algorithms.cs.cipher = generateAlgorithmList(cfg.algorithms.cipher, + DEFAULT_CIPHER, + SUPPORTED_CIPHER); + if (algorithms.cs.cipher !== DEFAULT_CIPHER) + allOfferDefaults = false; + + algorithms.cs.mac = generateAlgorithmList(cfg.algorithms.hmac, + DEFAULT_MAC, + SUPPORTED_MAC); + if (algorithms.cs.mac !== DEFAULT_MAC) + allOfferDefaults = false; + + algorithms.cs.compress = generateAlgorithmList(cfg.algorithms.compress, + DEFAULT_COMPRESSION, + SUPPORTED_COMPRESSION); + if (algorithms.cs.compress !== DEFAULT_COMPRESSION) + allOfferDefaults = false; + + if (!allOfferDefaults) + algorithms.sc = algorithms.cs; } - algoList = cfg.algorithms.serverHostKey; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_SERVER_HOST_KEY; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) { - throw new Error('Unsupported server host key algorithm: ' - + algoList[i]); - } - } - algorithms.serverHostKey = algoList; + if (typeof cfg.username === 'string') + this.config.username = cfg.username; + else if (typeof cfg.user === 'string') + this.config.username = cfg.user; + else + throw new Error('Invalid username'); + + this.config.password = (typeof cfg.password === 'string' + ? cfg.password + : undefined); + this.config.privateKey = (typeof cfg.privateKey === 'string' + || Buffer.isBuffer(cfg.privateKey) + ? cfg.privateKey + : undefined); + this.config.localHostname = (typeof cfg.localHostname === 'string' + ? cfg.localHostname + : undefined); + this.config.localUsername = (typeof cfg.localUsername === 'string' + ? cfg.localUsername + : undefined); + this.config.tryKeyboard = (cfg.tryKeyboard === true); + if (typeof cfg.agent === 'string' && cfg.agent.length) + this.config.agent = createAgent(cfg.agent); + else if (isAgent(cfg.agent)) + this.config.agent = cfg.agent; + else + this.config.agent = undefined; + this.config.allowAgentFwd = (cfg.agentForward === true + && this.config.agent !== undefined); + let authHandler = this.config.authHandler = ( + typeof cfg.authHandler === 'function' + || Array.isArray(cfg.authHandler) + ? cfg.authHandler + : undefined + ); + + this.config.strictVendor = (typeof cfg.strictVendor === 'boolean' + ? cfg.strictVendor + : true); + + const debug = this.config.debug = (typeof cfg.debug === 'function' + ? cfg.debug + : undefined); + + if (cfg.agentForward === true && !this.config.allowAgentFwd) { + throw new Error( + 'You must set a valid agent path to allow agent forwarding' + ); } - algoList = cfg.algorithms.hmac; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_HMAC; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported HMAC algorithm: ' + algoList[i]); + let callbacks = this._callbacks = []; + this._chanMgr = new ChannelManager(this); + this._forwarding = {}; + this._forwardingUnix = {}; + this._acceptX11 = 0; + this._agentFwdEnabled = false; + this._agent = (this.config.agent ? this.config.agent : undefined); + this._remoteVer = undefined; + let privateKey; + + if (this.config.privateKey) { + privateKey = parseKey(this.config.privateKey, cfg.passphrase); + if (privateKey instanceof Error) + throw new Error(`Cannot parse privateKey: ${privateKey.message}`); + if (Array.isArray(privateKey)) { + // OpenSSH's newer format only stores 1 key for now + privateKey = privateKey[0]; + } + if (privateKey.getPrivatePEM() === null) { + throw new Error( + 'privateKey value does not contain a (valid) private key' + ); } - algorithms.hmac = algoList; } - algoList = cfg.algorithms.compress; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_COMPRESS; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported compression algorithm: ' + algoList[i]); + let hostVerifier; + if (typeof cfg.hostVerifier === 'function') { + const hashCb = cfg.hostVerifier; + let hasher; + if (HASHES.indexOf(cfg.hostHash) !== -1) { + // Default to old behavior of hashing on user's behalf + hasher = createHash(cfg.hostHash); } - algorithms.compress = algoList; + hostVerifier = (key, verify) => { + if (hasher) { + hasher.update(key); + key = hasher.digest('hex'); + } + const ret = hashCb(key, verify); + if (ret !== undefined) + verify(ret); + }; } - } - if (algorithms.compress === undefined) { - if (cfg.compress) { - algorithms.compress = ['zlib@openssh.com', 'zlib']; - if (cfg.compress !== 'force') - algorithms.compress.push('none'); - } else if (cfg.compress === false) - algorithms.compress = ['none']; - } - this.config.username = cfg.username || cfg.user; - this.config.password = (typeof cfg.password === 'string' - ? cfg.password - : undefined); - this.config.privateKey = (typeof cfg.privateKey === 'string' - || Buffer.isBuffer(cfg.privateKey) - ? cfg.privateKey - : undefined); - this.config.publicKey = undefined; - this.config.localHostname = (typeof cfg.localHostname === 'string' - && cfg.localHostname.length - ? cfg.localHostname - : undefined); - this.config.localUsername = (typeof cfg.localUsername === 'string' - && cfg.localUsername.length - ? cfg.localUsername - : undefined); - this.config.tryKeyboard = (cfg.tryKeyboard === true); - this.config.agent = (typeof cfg.agent === 'string' && cfg.agent.length - ? cfg.agent - : undefined); - this.config.allowAgentFwd = (cfg.agentForward === true - && this.config.agent !== undefined); - - this.config.strictVendor = (typeof cfg.strictVendor === 'boolean' - ? cfg.strictVendor - : true); - - var debug = this.config.debug = (typeof cfg.debug === 'function' - ? cfg.debug - : DEBUG_NOOP); - - if (typeof this.config.username !== 'string') - throw new Error('Invalid username'); - - if (cfg.agentForward === true && !this.config.allowAgentFwd) - throw new Error('You must set a valid agent path to allow agent forwarding'); - - var callbacks = this._callbacks = []; - this._channels = {}; - this._forwarding = {}; - this._acceptX11 = 0; - this._agentFwdEnabled = false; - this._curChan = -1; - this._remoteVer = undefined; - - if (this.config.privateKey) { - var privKeyInfo = parseKey(this.config.privateKey); - if (privKeyInfo instanceof Error) - throw new Error('Cannot parse privateKey: ' + privKeyInfo.message); - if (!privKeyInfo.private) - throw new Error('privateKey value does not contain a (valid) private key'); - if (privKeyInfo.encryption) { - if (typeof cfg.passphrase !== 'string') - throw new Error('Encrypted private key detected, but no passphrase given'); - decryptKey(privKeyInfo, cfg.passphrase); - } - this.config.privateKey = privKeyInfo; - this.config.publicKey = genPublicKey(privKeyInfo); - } + const sock = this._sock = (cfg.sock || new Socket()); + let ready = false; + let sawHeader = false; + if (this._protocol) + this._protocol.cleanup(); + const DEBUG_HANDLER = (!debug ? undefined : (p, display, msg) => { + debug(`Debug output from server: ${JSON.stringify(msg)}`); + }); + const proto = this._protocol = new Protocol({ + ident: this.config.ident, + offer: (allOfferDefaults ? undefined : algorithms), + onWrite: (data) => { + if (isWritable(sock)) + sock.write(data); + }, + onError: (err) => { + if (err.level === 'handshake') + clearTimeout(this._readyTimeout); + if (!proto._destruct) + sock.removeAllListeners('data'); + this.emit('error', err); + try { + sock.end(); + } catch {} + }, + onHeader: (header) => { + sawHeader = true; + this._remoteVer = header.versions.software; + if (header.greeting) + this.emit('greeting', header.greeting); + }, + onHandshakeComplete: (negotiated) => { + this.emit('handshake', negotiated); + if (!ready) { + ready = true; + proto.service('ssh-userauth'); + } + }, + debug, + hostVerifier, + messageHandlers: { + DEBUG: DEBUG_HANDLER, + DISCONNECT: (p, reason, desc) => { + if (reason !== DISCONNECT_REASON.BY_APPLICATION) { + if (!desc) { + desc = DISCONNECT_REASON_BY_VALUE[reason]; + if (desc === undefined) + desc = `Unexpected disconnection reason: ${reason}`; + } + const err = new Error(desc); + err.code = reason; + this.emit('error', err); + } + sock.end(); + }, + SERVICE_ACCEPT: (p, name) => { + if (name === 'ssh-userauth') + tryNextAuth(); + }, + USERAUTH_BANNER: (p, msg) => { + this.emit('banner', msg); + }, + USERAUTH_SUCCESS: (p) => { + // Start keepalive mechanism + resetKA(); + + clearTimeout(this._readyTimeout); + + this.emit('ready'); + }, + USERAUTH_FAILURE: (p, authMethods, partialSuccess) => { + if (curAuth.type === 'agent') { + const pos = curAuth.agentCtx.pos(); + debug && debug(`Client: Agent key #${pos + 1} failed`); + return tryNextAgentKey(); + } - var stream = this._sshstream = new SSH2Stream({ - algorithms: algorithms, - debug: (debug === DEBUG_NOOP ? undefined : debug) - }); - var sock = this._sock = (cfg.sock || new Socket()); - - // drain stderr if we are connection hopping using an exec stream - if (this._sock.stderr) - this._sock.stderr.resume(); - - // keepalive-related - var kainterval = this.config.keepaliveInterval; - var kacountmax = this.config.keepaliveCountMax; - var kacount = 0; - var katimer; - function sendKA() { - if (++kacount > kacountmax) { - clearInterval(katimer); - if (sock.readable) { - var err = new Error('Keepalive timeout'); - err.level = 'client-timeout'; - self.emit('error', err); - sock.destroy(); - } - return; - } - if (sock.writable) { - // append dummy callback to keep correct callback order - callbacks.push(resetKA); - stream.ping(); - } else - clearInterval(katimer); - } - function resetKA() { - if (kainterval > 0) { - kacount = 0; - clearInterval(katimer); - if (sock.writable) - katimer = setInterval(sendKA, kainterval); - } - } - this._resetKA = resetKA; + debug && debug(`Client: ${curAuth.type} auth failed`); + + curPartial = partialSuccess; + curAuthsLeft = authMethods; + tryNextAuth(); + }, + USERAUTH_PASSWD_CHANGEREQ: (p, prompt) => { + if (curAuth.type === 'password') { + // TODO: support a `changePrompt()` on `curAuth` that defaults to + // emitting 'change password' as before + this.emit('change password', prompt, (newPassword) => { + proto.authPassword( + this.config.username, + this.config.password, + newPassword + ); + }); + } + }, + USERAUTH_PK_OK: (p) => { + if (curAuth.type === 'agent') { + const key = curAuth.agentCtx.currentKey(); + proto.authPK(curAuth.username, key, (buf, cb) => { + curAuth.agentCtx.sign(key, buf, {}, (err, signed) => { + if (err) { + err.level = 'agent'; + this.emit('error', err); + } else { + return cb(signed); + } + + tryNextAgentKey(); + }); + }); + } else if (curAuth.type === 'publickey') { + proto.authPK(curAuth.username, curAuth.key, (buf, cb) => { + const signature = curAuth.key.sign(buf); + if (signature instanceof Error) { + signature.message = + `Error signing data with key: ${signature.message}`; + signature.level = 'client-authentication'; + this.emit('error', signature); + return tryNextAuth(); + } + cb(signature); + }); + } + }, + USERAUTH_INFO_REQUEST: (p, name, instructions, prompts) => { + if (curAuth.type === 'keyboard-interactive') { + const nprompts = (Array.isArray(prompts) ? prompts.length : 0); + if (nprompts === 0) { + debug && debug( + 'Client: Sending automatic USERAUTH_INFO_RESPONSE' + ); + proto.authInfoRes(); + return; + } + // We sent a keyboard-interactive user authentication request and + // now the server is sending us the prompts we need to present to + // the user + curAuth.prompt( + name, + instructions, + '', + prompts, + (answers) => { + proto.authInfoRes(answers); + } + ); + } + }, + REQUEST_SUCCESS: (p, data) => { + if (callbacks.length) + callbacks.shift()(false, data); + }, + REQUEST_FAILURE: (p) => { + if (callbacks.length) + callbacks.shift()(true); + }, + GLOBAL_REQUEST: (p, name, wantReply, data) => { + switch (name) { + case 'hostkeys-00@openssh.com': + // Automatically verify keys before passing to end user + hostKeysProve(this, data, (err, keys) => { + if (err) + return; + this.emit('hostkeys', keys); + }); + if (wantReply) + proto.requestSuccess(); + break; + default: + // Auto-reject all other global requests, this can be especially + // useful if the server is sending us dummy keepalive global + // requests + if (wantReply) + proto.requestFailure(); + } + }, + CHANNEL_OPEN: (p, info) => { + // Handle incoming requests from server, typically a forwarded TCP or + // X11 connection + onCHANNEL_OPEN(this, info); + }, + CHANNEL_OPEN_CONFIRMATION: (p, info) => { + const channel = this._chanMgr.get(info.recipient); + if (typeof channel !== 'function') + return; + + const isSFTP = (channel.type === 'sftp'); + const type = (isSFTP ? 'session' : channel.type); + const chanInfo = { + type, + incoming: { + id: info.recipient, + window: MAX_WINDOW, + packetSize: PACKET_SIZE, + state: 'open' + }, + outgoing: { + id: info.sender, + window: info.window, + packetSize: info.packetSize, + state: 'open' + } + }; + const instance = ( + isSFTP + ? new SFTP(this, chanInfo, { debug }) + : new Channel(this, chanInfo) + ); + this._chanMgr.update(info.recipient, instance); + channel(undefined, instance); + }, + CHANNEL_OPEN_FAILURE: (p, recipient, reason, description) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'function') + return; + + const info = { reason, description }; + onChannelOpenFailure(this, recipient, info, channel); + }, + CHANNEL_DATA: (p, recipient, data) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + // The remote party should not be sending us data if there is no + // window space available ... + // TODO: raise error on data with not enough window? + if (channel.incoming.window === 0) + return; + + channel.incoming.window -= data.length; + + if (channel.push(data) === false) { + channel._waitChanDrain = true; + return; + } - stream.on('USERAUTH_BANNER', function(msg) { - self.emit('banner', msg); - }); + if (channel.incoming.window <= WINDOW_THRESHOLD) + windowAdjust(channel); + }, + CHANNEL_EXTENDED_DATA: (p, recipient, data, type) => { + if (type !== STDERR) + return; - sock.on('connect', function() { - debug('DEBUG: Client: Connected'); - self.emit('connect'); - if (!cfg.sock) - stream.pipe(sock).pipe(stream); - }).on('timeout', function() { - self.emit('timeout'); - }).on('error', function(err) { - clearTimeout(self._readyTimeout); - err.level = 'client-socket'; - self.emit('error', err); - }).on('end', function() { - stream.unpipe(sock); - clearTimeout(self._readyTimeout); - clearInterval(katimer); - self.emit('end'); - }).on('close', function() { - stream.unpipe(sock); - clearTimeout(self._readyTimeout); - clearInterval(katimer); - self.emit('close'); - - // notify outstanding channel requests of disconnection ... - var callbacks_ = callbacks; - var err = new Error('No response from server'); - callbacks = self._callbacks = []; - for (i = 0; i < callbacks_.length; ++i) - callbacks_[i](err); - - // simulate error for any channels waiting to be opened. this is safe - // against successfully opened channels because the success and failure - // event handlers are automatically removed when a success/failure response - // is received - var chanNos = Object.keys(self._channels); - self._channels = {}; - for (i = 0; i < chanNos.length; ++i) { - stream.emit('CHANNEL_OPEN_FAILURE:' + chanNos[i], err); - // emitting CHANNEL_CLOSE should be safe too and should help for any - // special channels which might otherwise keep the process alive, such - // as agent forwarding channels which have open unix sockets ... - stream.emit('CHANNEL_CLOSE:' + chanNos[i]); - } - }); - stream.on('drain', function() { - self.emit('drain'); - }).once('header', function(header) { - self._remoteVer = header.versions.software; - if (header.greeting) - self.emit('greeting', header.greeting); - }).on('continue', function() { - self.emit('continue'); - }).on('error', function(err) { - err.level = 'protocol'; - self.emit('error', err); - }); + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; - if (typeof cfg.hostVerifier === 'function') { - if (HASHES.indexOf(cfg.hostHash) === -1) - throw new Error('Invalid host hash algorithm: ' + cfg.hostHash); - var hashCb = cfg.hostVerifier; - var hasher = crypto.createHash(cfg.hostHash); - stream.once('fingerprint', function(key, verify) { - hasher.update(key); - var ret = hashCb(hasher.digest('hex'), verify); - if (ret !== undefined) - verify(ret); - }); - } + // The remote party should not be sending us data if there is no + // window space available ... + // TODO: raise error on data with not enough window? + if (channel.incoming.window === 0) + return; - // begin authentication handling ============================================= - var auths = []; - var curAuth; - var agentKeys; - var agentKeyPos = 0; - if (this.config.password !== undefined) - auths.push('password'); - if (this.config.publicKey !== undefined) - auths.push('publickey'); - if (this.config.agent !== undefined) - auths.push('agent'); - if (this.config.tryKeyboard) - auths.push('keyboard-interactive'); - if (this.config.publicKey !== undefined - && this.config.localHostname !== undefined - && this.config.localUsername !== undefined) - auths.push('hostbased'); - auths.push('none'); - function tryNextAuth() { - // TODO: better shutdown - if (!auths.length) { - stream.removeListener('USERAUTH_FAILURE', onUSERAUTH_FAILURE); - stream.removeListener('USERAUTH_PK_OK', onUSERAUTH_PK_OK); - var err = new Error('All configured authentication methods failed'); - err.level = 'client-authentication'; - self.emit('error', err); - if (stream.writable) - self.end(); - return; - } + channel.incoming.window -= data.length; - curAuth = auths.shift(); - switch (curAuth) { - case 'password': - stream.authPassword(self.config.username, self.config.password); - break; - case 'publickey': - stream.authPK(self.config.username, self.config.publicKey); - stream.once('USERAUTH_PK_OK', onUSERAUTH_PK_OK); - break; - case 'hostbased': - function hostbasedCb(buf, cb) { - var algo; - switch (self.config.privateKey.fulltype) { - case 'ssh-rsa': - algo = 'RSA-SHA1'; - break; - case 'ssh-dss': - algo = 'DSA-SHA1'; - break; - case 'ecdsa-sha2-nistp256': - algo = 'sha256'; - break; - case 'ecdsa-sha2-nistp384': - algo = 'sha384'; - break; - case 'ecdsa-sha2-nistp521': - algo = 'sha512'; - break; - } - var signature = crypto.createSign(algo); - signature.update(buf); - signature = trySign(signature, self.config.privateKey.privateOrig); - if (signature instanceof Error) { - signature.message = 'Error while signing data with privateKey: ' - + signature.message; - signature.level = 'client-authentication'; - self.emit('error', signature); - return tryNextAuth(); + if (!channel.stderr.push(data)) { + channel._waitChanDrain = true; + return; } - cb(signature); - } - stream.authHostbased(self.config.username, - self.config.publicKey, - self.config.localHostname, - self.config.localUsername, - hostbasedCb); - break; - case 'agent': - agentQuery(self.config.agent, function(err, keys) { - if (err) { - err.level = 'agent'; - self.emit('error', err); - agentKeys = undefined; - return tryNextAuth(); - } else if (keys.length === 0) { - debug('DEBUG: Agent: No keys stored in agent'); - agentKeys = undefined; - return tryNextAuth(); + if (channel.incoming.window <= WINDOW_THRESHOLD) + windowAdjust(channel); + }, + CHANNEL_WINDOW_ADJUST: (p, recipient, amount) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + // The other side is allowing us to send `amount` more bytes of data + channel.outgoing.window += amount; + + if (channel._waitWindow) { + channel._waitWindow = false; + + if (channel._chunk) { + channel._write(channel._chunk, null, channel._chunkcb); + } else if (channel._chunkcb) { + channel._chunkcb(); + } else if (channel._chunkErr) { + channel.stderr._write(channel._chunkErr, + null, + channel._chunkcbErr); + } else if (channel._chunkcbErr) { + channel._chunkcbErr(); + } + } + }, + CHANNEL_SUCCESS: (p, recipient) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + this._resetKA(); + + if (channel._callbacks.length) + channel._callbacks.shift()(false); + }, + CHANNEL_FAILURE: (p, recipient) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + this._resetKA(); + + if (channel._callbacks.length) + channel._callbacks.shift()(true); + }, + CHANNEL_REQUEST: (p, recipient, type, wantReply, data) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + const exit = channel._exit; + if (exit.code !== undefined) + return; + switch (type) { + case 'exit-status': + channel.emit('exit', exit.code = data); + return; + case 'exit-signal': + channel.emit('exit', + exit.code = null, + exit.signal = `SIG${data.signal}`, + exit.dump = data.coreDumped, + exit.desc = data.errorMessage); + return; } - agentKeys = keys; - agentKeyPos = 0; + // Keepalive request? OpenSSH will send one as a channel request if + // there is a channel open + + if (wantReply) + p.channelFailure(channel.outgoing.id); + }, + CHANNEL_EOF: (p, recipient) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + if (channel.incoming.state !== 'open') + return; + channel.incoming.state = 'eof'; + + if (channel.readable) + channel.push(null); + if (channel.stderr.readable) + channel.stderr.push(null); + }, + CHANNEL_CLOSE: (p, recipient) => { + onCHANNEL_CLOSE(this, recipient, this._chanMgr.get(recipient)); + }, + }, + }); - stream.authPK(self.config.username, keys[0]); - stream.once('USERAUTH_PK_OK', onUSERAUTH_PK_OK); - }); - break; - case 'keyboard-interactive': - stream.authKeyboard(self.config.username); - stream.on('USERAUTH_INFO_REQUEST', onUSERAUTH_INFO_REQUEST); - break; - case 'none': - stream.authNone(self.config.username); - break; - } - } - function tryNextAgentKey() { - if (curAuth === 'agent') { - if (agentKeyPos >= agentKeys.length) + sock.pause(); + + // TODO: check keepalive implementation + // Keepalive-related + const kainterval = this.config.keepaliveInterval; + const kacountmax = this.config.keepaliveCountMax; + let kacount = 0; + let katimer; + const sendKA = () => { + if (++kacount > kacountmax) { + clearInterval(katimer); + if (sock.readable) { + const err = new Error('Keepalive timeout'); + err.level = 'client-timeout'; + this.emit('error', err); + sock.destroy(); + } return; - if (++agentKeyPos >= agentKeys.length) { - debug('DEBUG: Agent: No more keys left to try'); - debug('DEBUG: Client: agent auth failed'); - agentKeys = undefined; - tryNextAuth(); + } + if (isWritable(sock)) { + // Append dummy callback to keep correct callback order + callbacks.push(resetKA); + proto.ping(); } else { - debug('DEBUG: Agent: Trying key #' + (agentKeyPos + 1)); - stream.authPK(self.config.username, agentKeys[agentKeyPos]); - stream.once('USERAUTH_PK_OK', onUSERAUTH_PK_OK); + clearInterval(katimer); } - } - } - function onUSERAUTH_INFO_REQUEST(name, instructions, lang, prompts) { - var nprompts = (Array.isArray(prompts) ? prompts.length : 0); - if (nprompts === 0) { - debug('DEBUG: Client: Sending automatic USERAUTH_INFO_RESPONSE'); - return stream.authInfoRes(); - } - // we sent a keyboard-interactive user authentication request and now the - // server is sending us the prompts we need to present to the user - self.emit('keyboard-interactive', - name, - instructions, - lang, - prompts, - function(answers) { - stream.authInfoRes(answers); - }); - } - function onUSERAUTH_PK_OK() { - if (curAuth === 'agent') { - var agentKey = agentKeys[agentKeyPos]; - var keyLen = agentKey.readUInt32BE(0, true); - var pubKeyFullType = agentKey.toString('ascii', 4, 4 + keyLen); - var pubKeyType = pubKeyFullType.slice(4); - // Check that we support the key type first - switch (pubKeyFullType) { - case 'ssh-rsa': - case 'ssh-dss': - case 'ecdsa-sha2-nistp256': - case 'ecdsa-sha2-nistp384': - case 'ecdsa-sha2-nistp521': - break; - default: - debug('DEBUG: Agent: Skipping unsupported key type: ' - + pubKeyFullType); - return tryNextAgentKey(); + }; + function resetKA() { + if (kainterval > 0) { + kacount = 0; + clearInterval(katimer); + if (isWritable(sock)) + katimer = setInterval(sendKA, kainterval); } - stream.authPK(self.config.username, - agentKey, - function(buf, cb) { - agentQuery(self.config.agent, - agentKey, - pubKeyType, - buf, - function(err, signed) { - if (err) { - err.level = 'agent'; - self.emit('error', err); - } else { - var sigFullTypeLen = signed.readUInt32BE(0, true); - if (4 + sigFullTypeLen + 4 < signed.length) { - var sigFullType = signed.toString('ascii', 4, 4 + sigFullTypeLen); - if (sigFullType !== pubKeyFullType) { - err = new Error('Agent key/signature type mismatch'); - err.level = 'agent'; - self.emit('error', err); - } else { - // skip algoLen + algo + sigLen - return cb(signed.slice(4 + sigFullTypeLen + 4)); - } + } + this._resetKA = resetKA; + + const onDone = (() => { + let called = false; + return () => { + if (called) + return; + called = true; + if (wasConnected && !sawHeader) { + const err = + makeError('Connection lost before handshake', 'protocol', true); + this.emit('error', err); + } + }; + })(); + const onConnect = (() => { + let called = false; + return () => { + if (called) + return; + called = true; + + wasConnected = true; + debug && debug('Socket connected'); + this.emit('connect'); + + cryptoInit.then(() => { + sock.on('data', (data) => { + try { + proto.parse(data, 0, data.length); + } catch (ex) { + this.emit('error', ex); + try { + if (isWritable(sock)) + sock.end(); + } catch {} } - } + }); - tryNextAgentKey(); + // Drain stderr if we are connection hopping using an exec stream + if (sock.stderr && typeof sock.stderr.resume === 'function') + sock.stderr.resume(); + + sock.resume(); + }).catch((err) => { + this.emit('error', err); + try { + if (isWritable(sock)) + sock.end(); + } catch {} }); - }); - } else if (curAuth === 'publickey') { - stream.authPK(self.config.username, - self.config.publicKey, - function(buf, cb) { - var algo; - switch (self.config.privateKey.fulltype) { - case 'ssh-rsa': - algo = 'RSA-SHA1'; + }; + })(); + let wasConnected = false; + sock.on('connect', onConnect) + .on('timeout', () => { + this.emit('timeout'); + }).on('error', (err) => { + debug && debug(`Socket error: ${err.message}`); + clearTimeout(this._readyTimeout); + err.level = 'client-socket'; + this.emit('error', err); + }).on('end', () => { + debug && debug('Socket ended'); + onDone(); + proto.cleanup(); + clearTimeout(this._readyTimeout); + clearInterval(katimer); + this.emit('end'); + }).on('close', () => { + debug && debug('Socket closed'); + onDone(); + proto.cleanup(); + clearTimeout(this._readyTimeout); + clearInterval(katimer); + this.emit('close'); + + // Notify outstanding channel requests of disconnection ... + const callbacks_ = callbacks; + callbacks = this._callbacks = []; + const err = new Error('No response from server'); + for (let i = 0; i < callbacks_.length; ++i) + callbacks_[i](err); + + // Simulate error for any channels waiting to be opened + this._chanMgr.cleanup(err); + }); + + // Begin authentication handling =========================================== + let curAuth; + let curPartial = null; + let curAuthsLeft = null; + const authsAllowed = ['none']; + if (this.config.password !== undefined) + authsAllowed.push('password'); + if (privateKey !== undefined) + authsAllowed.push('publickey'); + if (this._agent !== undefined) + authsAllowed.push('agent'); + if (this.config.tryKeyboard) + authsAllowed.push('keyboard-interactive'); + if (privateKey !== undefined + && this.config.localHostname !== undefined + && this.config.localUsername !== undefined) { + authsAllowed.push('hostbased'); + } + + if (Array.isArray(authHandler)) + authHandler = makeSimpleAuthHandler(authHandler); + else if (typeof authHandler !== 'function') + authHandler = makeSimpleAuthHandler(authsAllowed); + + let hasSentAuth = false; + const doNextAuth = (nextAuth) => { + if (hasSentAuth) + return; + hasSentAuth = true; + + if (nextAuth === false) { + const err = new Error('All configured authentication methods failed'); + err.level = 'client-authentication'; + this.emit('error', err); + this.end(); + return; + } + + if (typeof nextAuth === 'string') { + // Remain backwards compatible with original `authHandler()` usage, + // which only supported passing names of next method to try using data + // from the `connect()` config object + + const type = nextAuth; + if (authsAllowed.indexOf(type) === -1) + return skipAuth(`Authentication method not allowed: ${type}`); + + const username = this.config.username; + switch (type) { + case 'password': + nextAuth = { type, username, password: this.config.password }; + break; + case 'publickey': + nextAuth = { type, username, key: privateKey }; break; - case 'ssh-dss': - algo = 'DSA-SHA1'; + case 'hostbased': + nextAuth = { + type, + username, + key: privateKey, + localHostname: this.config.localHostname, + localUsername: this.config.localUsername, + }; break; - case 'ecdsa-sha2-nistp256': - algo = 'sha256'; + case 'agent': + nextAuth = { + type, + username, + agentCtx: new AgentContext(this._agent), + }; break; - case 'ecdsa-sha2-nistp384': - algo = 'sha384'; + case 'keyboard-interactive': + nextAuth = { + type, + username, + prompt: (...args) => this.emit('keyboard-interactive', ...args), + }; break; - case 'ecdsa-sha2-nistp521': - algo = 'sha512'; + case 'none': + nextAuth = { type, username }; break; + default: + return skipAuth( + `Skipping unsupported authentication method: ${nextAuth}` + ); } - var signature = crypto.createSign(algo); - signature.update(buf); - signature = trySign(signature, self.config.privateKey.privateOrig); - if (signature instanceof Error) { - signature.message = 'Error while signing data with privateKey: ' - + signature.message; - signature.level = 'client-authentication'; - self.emit('error', signature); - return tryNextAuth(); + } else if (typeof nextAuth !== 'object' || nextAuth === null) { + return skipAuth( + `Skipping invalid authentication attempt: ${nextAuth}` + ); + } else { + const username = nextAuth.username; + if (typeof username !== 'string') { + return skipAuth( + `Skipping invalid authentication attempt: ${nextAuth}` + ); } - cb(signature); - }); + const type = nextAuth.type; + switch (type) { + case 'password': { + const { password } = nextAuth; + if (typeof password !== 'string' && !Buffer.isBuffer(password)) + return skipAuth('Skipping invalid password auth attempt'); + nextAuth = { type, username, password }; + break; + } + case 'publickey': { + const key = parseKey(nextAuth.key, nextAuth.passphrase); + if (key instanceof Error) + return skipAuth('Skipping invalid key auth attempt'); + if (!key.isPrivateKey()) + return skipAuth('Skipping non-private key'); + nextAuth = { type, username, key }; + break; + } + case 'hostbased': { + const { localHostname, localUsername } = nextAuth; + const key = parseKey(nextAuth.key, nextAuth.passphrase); + if (key instanceof Error + || typeof localHostname !== 'string' + || typeof localUsername !== 'string') { + return skipAuth('Skipping invalid hostbased auth attempt'); + } + if (!key.isPrivateKey()) + return skipAuth('Skipping non-private key'); + nextAuth = { type, username, key, localHostname, localUsername }; + break; + } + case 'agent': { + let agent = nextAuth.agent; + if (typeof agent === 'string' && agent.length) { + agent = createAgent(agent); + } else if (!isAgent(agent)) { + return skipAuth( + `Skipping invalid agent: ${nextAuth.agent}` + ); + } + nextAuth = { type, username, agentCtx: new AgentContext(agent) }; + break; + } + case 'keyboard-interactive': { + const { prompt } = nextAuth; + if (typeof prompt !== 'function') { + return skipAuth( + 'Skipping invalid keyboard-interactive auth attempt' + ); + } + nextAuth = { type, username, prompt }; + break; + } + case 'none': + nextAuth = { type, username }; + break; + default: + return skipAuth( + `Skipping unsupported authentication method: ${nextAuth}` + ); + } + } + curAuth = nextAuth; + + // Begin authentication method's process + try { + const username = curAuth.username; + switch (curAuth.type) { + case 'password': + proto.authPassword(username, curAuth.password); + break; + case 'publickey': + proto.authPK(username, curAuth.key); + break; + case 'hostbased': + proto.authHostbased(username, + curAuth.key, + curAuth.localHostname, + curAuth.localUsername, + (buf, cb) => { + const signature = curAuth.key.sign(buf); + if (signature instanceof Error) { + signature.message = + `Error while signing with key: ${signature.message}`; + signature.level = 'client-authentication'; + this.emit('error', signature); + return tryNextAuth(); + } + + cb(signature); + }); + break; + case 'agent': + curAuth.agentCtx.init((err) => { + if (err) { + err.level = 'agent'; + this.emit('error', err); + return tryNextAuth(); + } + tryNextAgentKey(); + }); + break; + case 'keyboard-interactive': + proto.authKeyboard(username); + break; + case 'none': + proto.authNone(username); + break; + } + } finally { + hasSentAuth = false; + } + }; + + function skipAuth(msg) { + debug && debug(msg); + process.nextTick(tryNextAuth); } - } - function onUSERAUTH_FAILURE(authsLeft, partial) { - stream.removeListener('USERAUTH_PK_OK', onUSERAUTH_PK_OK); - stream.removeListener('USERAUTH_INFO_REQUEST', onUSERAUTH_INFO_REQUEST); - if (curAuth === 'agent') { - debug('DEBUG: Client: Agent key #' + (agentKeyPos + 1) + ' failed'); - return tryNextAgentKey(); - } else - debug('DEBUG: Client: ' + curAuth + ' auth failed'); - - tryNextAuth(); - } - stream.once('USERAUTH_SUCCESS', function() { - auths = undefined; - stream.removeListener('USERAUTH_FAILURE', onUSERAUTH_FAILURE); - stream.removeListener('USERAUTH_INFO_REQUEST', onUSERAUTH_INFO_REQUEST); - /*if (self.config.agent && self._agentKeys) - self._agentKeys = undefined;*/ - - // start keepalive mechanism - resetKA(); - - clearTimeout(self._readyTimeout); - - self.emit('ready'); - }).on('USERAUTH_FAILURE', onUSERAUTH_FAILURE); - // end authentication handling =============================================== - - // handle initial handshake completion - stream.once('ready', function() { - stream.service('ssh-userauth'); - stream.once('SERVICE_ACCEPT', function(svcName) { - if (svcName === 'ssh-userauth') - tryNextAuth(); - }); - }); - // handle incoming requests from server, typically a forwarded TCP or X11 - // connection - stream.on('CHANNEL_OPEN', function(info) { - onCHANNEL_OPEN(self, info); - }); + function tryNextAuth() { + hasSentAuth = false; + const auth = authHandler(curAuthsLeft, curPartial, doNextAuth); + if (hasSentAuth || auth === undefined) + return; + doNextAuth(auth); + } - // handle responses for tcpip-forward and other global requests - stream.on('REQUEST_SUCCESS', function(data) { - if (callbacks.length) - callbacks.shift()(false, data); - }).on('REQUEST_FAILURE', function() { - if (callbacks.length) - callbacks.shift()(true); - }); + const tryNextAgentKey = () => { + if (curAuth.type === 'agent') { + const key = curAuth.agentCtx.nextKey(); + if (key === false) { + debug && debug('Agent: No more keys left to try'); + debug && debug('Client: agent auth failed'); + tryNextAuth(); + } else { + const pos = curAuth.agentCtx.pos(); + debug && debug(`Agent: Trying key #${pos + 1}`); + proto.authPK(curAuth.username, key); + } + } + }; - stream.on('GLOBAL_REQUEST', function(name, wantReply, data) { - // auto-reject all global requests, this can be especially useful if the - // server is sending us dummy keepalive global requests - if (wantReply) - stream.requestFailure(); - }); + const startTimeout = () => { + if (this.config.readyTimeout > 0) { + this._readyTimeout = setTimeout(() => { + const err = new Error('Timed out while waiting for handshake'); + err.level = 'client-timeout'; + this.emit('error', err); + sock.destroy(); + }, this.config.readyTimeout); + } + }; + + if (!cfg.sock) { + let host = this.config.host; + const forceIPv4 = this.config.forceIPv4; + const forceIPv6 = this.config.forceIPv6; - if (!cfg.sock) { - var host = this.config.host; - var forceIPv4 = this.config.forceIPv4; - var forceIPv6 = this.config.forceIPv6; + debug && debug(`Client: Trying ${host} on port ${this.config.port} ...`); - debug('DEBUG: Client: Trying ' - + host - + ' on port ' - + this.config.port - + ' ...'); + const doConnect = () => { + startTimeout(); + sock.connect({ + host, + port: this.config.port, + localAddress: this.config.localAddress, + localPort: this.config.localPort + }); + sock.setNoDelay(true); + sock.setMaxListeners(0); + sock.setTimeout(typeof cfg.timeout === 'number' ? cfg.timeout : 0); + }; - function doConnect() { + if ((!forceIPv4 && !forceIPv6) || (forceIPv4 && forceIPv6)) { + doConnect(); + } else { + dnsLookup(host, (forceIPv4 ? 4 : 6), (err, address, family) => { + if (err) { + const type = (forceIPv4 ? 'IPv4' : 'IPv6'); + const error = new Error( + `Error while looking up ${type} address for '${host}': ${err}` + ); + clearTimeout(this._readyTimeout); + error.level = 'client-dns'; + this.emit('error', error); + this.emit('close'); + return; + } + host = address; + doConnect(); + }); + } + } else { + // Custom socket passed in startTimeout(); - self._sock.connect(self.config.port, host); - self._sock.setNoDelay(true); - self._sock.setMaxListeners(0); - self._sock.setTimeout(typeof cfg.timeout === 'number' ? cfg.timeout : 0); - } + if (typeof sock.connecting === 'boolean') { + // net.Socket - if ((!forceIPv4 && !forceIPv6) || (forceIPv4 && forceIPv6)) - doConnect(); - else { - dnsLookup(host, (forceIPv4 ? 4 : 6), function(err, address, family) { - if (err) { - var error = new Error('Error while looking up ' - + (forceIPv4 ? 'IPv4' : 'IPv6') - + ' address for host ' - + host - + ': ' + err); - clearTimeout(self._readyTimeout); - error.level = 'client-dns'; - self.emit('error', error); - self.emit('close'); - return; + if (!sock.connecting) { + // Already connected + onConnect(); } - host = address; - doConnect(); - }); + } else { + // Assume socket/stream is already "connected" + onConnect(); + } } - } else { - startTimeout(); - stream.pipe(sock).pipe(stream); + + return this; } - function startTimeout() { - if (self.config.readyTimeout > 0) { - self._readyTimeout = setTimeout(function() { - var err = new Error('Timed out while waiting for handshake'); - err.level = 'client-timeout'; - self.emit('error', err); - sock.destroy(); - }, self.config.readyTimeout); + end() { + if (this._sock && isWritable(this._sock)) { + this._protocol.disconnect(DISCONNECT_REASON.BY_APPLICATION); + this._sock.end(); } + return this; } -}; - -Client.prototype.end = function() { - if (this._sock - && this._sock.writable - && this._sshstream - && this._sshstream.writable) - return this._sshstream.disconnect(); - return false; -}; - -Client.prototype.destroy = function() { - this._sock && this._sock.destroy(); -}; - -Client.prototype.exec = function(cmd, opts, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); - if (typeof opts === 'function') { - cb = opts; - opts = {}; + destroy() { + this._sock && isWritable(this._sock) && this._sock.destroy(); + return this; } - var self = this; - var extraOpts = { allowHalfOpen: (opts.allowHalfOpen !== false) }; + exec(cmd, opts, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); - return openChannel(this, 'session', extraOpts, function(err, chan) { - if (err) - return cb(err); + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } - var todo = []; + const extraOpts = { allowHalfOpen: (opts.allowHalfOpen !== false) }; - function reqCb(err) { + openChannel(this, 'session', extraOpts, (err, chan) => { if (err) { - chan.close(); - return cb(err); + cb(err); + return; } - if (todo.length) - todo.shift()(); - } - - if (self.config.allowAgentFwd === true - || (opts - && opts.agentForward === true - && self.config.agent !== undefined)) { - todo.push(function() { - reqAgentFwd(chan, reqCb); - }); - } - if (typeof opts === 'object') { - if (typeof opts.env === 'object') - reqEnv(chan, opts.env); - if (typeof opts.pty === 'object' || opts.pty === true) - todo.push(function() { reqPty(chan, opts.pty, reqCb); }); - if (typeof opts.x11 === 'object' - || opts.x11 === 'number' - || opts.x11 === true) - todo.push(function() { reqX11(chan, opts.x11, reqCb); }); - } + const todo = []; - todo.push(function() { reqExec(chan, cmd, opts, cb); }); - todo.shift()(); - }); -}; - -Client.prototype.shell = function(wndopts, opts, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); - - // start an interactive terminal/shell session - var self = this; - - if (typeof wndopts === 'function') { - cb = wndopts; - wndopts = opts = undefined; - } else if (typeof opts === 'function') { - cb = opts; - opts = undefined; - } - if (wndopts && wndopts.x11 !== undefined) { - opts = wndopts; - wndopts = undefined; - } - - return openChannel(this, 'session', function(err, chan) { - if (err) - return cb(err); + function reqCb(err) { + if (err) { + chan.close(); + cb(err); + return; + } + if (todo.length) + todo.shift()(); + } - var todo = []; + if (this.config.allowAgentFwd === true + || (opts + && opts.agentForward === true + && this._agent !== undefined)) { + todo.push(() => reqAgentFwd(chan, reqCb)); + } - function reqCb(err) { - if (err) { - chan.close(); - return cb(err); + if (typeof opts === 'object' && opts !== null) { + if (typeof opts.env === 'object' && opts.env !== null) + reqEnv(chan, opts.env); + if ((typeof opts.pty === 'object' && opts.pty !== null) + || opts.pty === true) { + todo.push(() => reqPty(chan, opts.pty, reqCb)); + } + if ((typeof opts.x11 === 'object' && opts.x11 !== null) + || opts.x11 === 'number' + || opts.x11 === true) { + todo.push(() => reqX11(chan, opts.x11, reqCb)); + } } - if (todo.length) - todo.shift()(); - } - if (self.config.allowAgentFwd === true - || (opts - && opts.agentForward === true - && self.config.agent !== undefined)) { - todo.push(function() { - reqAgentFwd(chan, reqCb); - }); - } + todo.push(() => reqExec(chan, cmd, opts, cb)); + todo.shift()(); + }); + + return this; + } - if (wndopts !== false) - todo.push(function() { reqPty(chan, wndopts, reqCb); }); + shell(wndopts, opts, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); - if (typeof opts === 'object') { - if (typeof opts.x11 === 'object' - || opts.x11 === 'number' - || opts.x11 === true) - todo.push(function() { reqX11(chan, opts.x11, reqCb); }); + if (typeof wndopts === 'function') { + cb = wndopts; + wndopts = opts = undefined; + } else if (typeof opts === 'function') { + cb = opts; + opts = undefined; + } + if (wndopts && (wndopts.x11 !== undefined || wndopts.env !== undefined)) { + opts = wndopts; + wndopts = undefined; } - todo.push(function() { reqShell(chan, cb); }); - todo.shift()(); - }); -}; - -Client.prototype.subsys = function(name, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); - - return openChannel(this, 'session', function(err, chan) { - if (err) - return cb(err); - - reqSubsystem(chan, name, function(err, stream) { - if (err) - return cb(err); - - cb(undefined, stream); - }); - }); -}; - -Client.prototype.sftp = function(cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); - - var self = this; - - // start an SFTP session - return openChannel(this, 'session', function(err, chan) { - if (err) - return cb(err); - - reqSubsystem(chan, 'sftp', function(err, stream) { - if (err) - return cb(err); - - var serverIdentRaw = self._sshstream._state.incoming.identRaw; - var cfg = { debug: self.config.debug }; - var sftp = new SFTPStream(cfg, serverIdentRaw); - - function onError(err) { - sftp.removeListener('ready', onReady); - stream.removeListener('exit', onExit); + openChannel(this, 'session', (err, chan) => { + if (err) { cb(err); + return; } - function onReady() { - sftp.removeListener('error', onError); - stream.removeListener('exit', onExit); - cb(undefined, new SFTPWrapper(sftp)); - } + const todo = []; - function onExit(code, signal) { - sftp.removeListener('ready', onReady); - sftp.removeListener('error', onError); - var msg; - if (typeof code === 'number') { - msg = 'Received exit code ' - + code - + ' while establishing SFTP session'; - } else { - msg = 'Received signal ' - + signal - + ' while establishing SFTP session'; + function reqCb(err) { + if (err) { + chan.close(); + cb(err); + return; } - var err = new Error(msg); - err.code = code; - err.signal = signal; - cb(err); + if (todo.length) + todo.shift()(); } - sftp.once('error', onError) - .once('ready', onReady) - .once('close', function() { - stream.end(); - }); - - // OpenSSH server sends an exit-status if there was a problem spinning up - // an sftp server child process, so we listen for that here in order to - // properly raise an error. - stream.once('exit', onExit); + if (this.config.allowAgentFwd === true + || (opts + && opts.agentForward === true + && this._agent !== undefined)) { + todo.push(() => reqAgentFwd(chan, reqCb)); + } - sftp.pipe(stream).pipe(sftp); - }); - }); -}; + if (wndopts !== false) + todo.push(() => reqPty(chan, wndopts, reqCb)); -Client.prototype.forwardIn = function(bindAddr, bindPort, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); + if (typeof opts === 'object' && opts !== null) { + if (typeof opts.env === 'object' && opts.env !== null) + reqEnv(chan, opts.env); + if ((typeof opts.x11 === 'object' && opts.x11 !== null) + || opts.x11 === 'number' + || opts.x11 === true) { + todo.push(() => reqX11(chan, opts.x11, reqCb)); + } + } - // send a request for the server to start forwarding TCP connections to us - // on a particular address and port + todo.push(() => reqShell(chan, cb)); + todo.shift()(); + }); - var self = this; - var wantReply = (typeof cb === 'function'); + return this; + } - if (wantReply) { - this._callbacks.push(function(had_err, data) { - if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to bind to ' + bindAddr + ':' + bindPort)); - } + subsys(name, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); - var realPort = bindPort; - if (bindPort === 0 && data && data.length >= 4) { - realPort = data.readUInt32BE(0, true); - if (!(self._sshstream.remoteBugs & BUGS.DYN_RPORT_BUG)) - bindPort = realPort; + openChannel(this, 'session', (err, chan) => { + if (err) { + cb(err); + return; } - self._forwarding[bindAddr + ':' + bindPort] = realPort; + reqSubsystem(chan, name, (err, stream) => { + if (err) { + cb(err); + return; + } - cb(undefined, realPort); + cb(undefined, stream); + }); }); - } - return this._sshstream.tcpipForward(bindAddr, bindPort, wantReply); -}; + return this; + } -Client.prototype.unforwardIn = function(bindAddr, bindPort, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); + forwardIn(bindAddr, bindPort, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); - // send a request to stop forwarding us new connections for a particular - // address and port + // Send a request for the server to start forwarding TCP connections to us + // on a particular address and port - var self = this; - var wantReply = (typeof cb === 'function'); + const wantReply = (typeof cb === 'function'); - if (wantReply) { - this._callbacks.push(function(had_err) { - if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to unbind from ' - + bindAddr + ':' + bindPort)); - } - - delete self._forwarding[bindAddr + ':' + bindPort]; + if (wantReply) { + this._callbacks.push((had_err, data) => { + if (had_err) { + cb(had_err !== true + ? had_err + : new Error(`Unable to bind to ${bindAddr}:${bindPort}`)); + return; + } - cb(); - }); - } + let realPort = bindPort; + if (bindPort === 0 && data && data.length >= 4) { + realPort = readUInt32BE(data, 0); + if (!(this._protocol._compatFlags & COMPAT.DYN_RPORT_BUG)) + bindPort = realPort; + } - return this._sshstream.cancelTcpipForward(bindAddr, bindPort, wantReply); -}; + this._forwarding[`${bindAddr}:${bindPort}`] = realPort; -Client.prototype.forwardOut = function(srcIP, srcPort, dstIP, dstPort, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); + cb(undefined, realPort); + }); + } - // send a request to forward a TCP connection to the server + this._protocol.tcpipForward(bindAddr, bindPort, wantReply); - var cfg = { - srcIP: srcIP, - srcPort: srcPort, - dstIP: dstIP, - dstPort: dstPort - }; + return this; + } - return openChannel(this, 'direct-tcpip', cfg, cb); -}; + unforwardIn(bindAddr, bindPort, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); -Client.prototype.openssh_noMoreSessions = function(cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); + // Send a request to stop forwarding us new connections for a particular + // address and port - var wantReply = (typeof cb === 'function'); + const wantReply = (typeof cb === 'function'); - if (!this.config.strictVendor - || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { if (wantReply) { - this._callbacks.push(function(had_err) { + this._callbacks.push((had_err) => { if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to disable future sessions')); + cb(had_err !== true + ? had_err + : new Error(`Unable to unbind from ${bindAddr}:${bindPort}`)); + return; } + delete this._forwarding[`${bindAddr}:${bindPort}`]; + cb(); }); } - return this._sshstream.openssh_noMoreSessions(wantReply); - } else if (wantReply) { - process.nextTick(function() { - cb(new Error('strictVendor enabled and server is not OpenSSH or compatible version')); - }); + this._protocol.cancelTcpipForward(bindAddr, bindPort, wantReply); + + return this; } - return true; -}; + forwardOut(srcIP, srcPort, dstIP, dstPort, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); -Client.prototype.openssh_forwardInStreamLocal = function(socketPath, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); + // Send a request to forward a TCP connection to the server - var wantReply = (typeof cb === 'function'); + const cfg = { + srcIP: srcIP, + srcPort: srcPort, + dstIP: dstIP, + dstPort: dstPort + }; - if (!this.config.strictVendor - || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { - if (wantReply) { - this._callbacks.push(function(had_err) { - if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to bind to ' + socketPath)); - } + if (typeof cb !== 'function') + cb = noop; - cb(); - }); - } + openChannel(this, 'direct-tcpip', cfg, cb); - return this._sshstream.openssh_streamLocalForward(socketPath, wantReply); - } else if (wantReply) { - process.nextTick(function() { - cb(new Error('strictVendor enabled and server is not OpenSSH or compatible version')); - }); + return this; } - return true; -}; + openssh_noMoreSessions(cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); + + const wantReply = (typeof cb === 'function'); + + if (!this.config.strictVendor + || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { + if (wantReply) { + this._callbacks.push((had_err) => { + if (had_err) { + cb(had_err !== true + ? had_err + : new Error('Unable to disable future sessions')); + return; + } -Client.prototype.openssh_unforwardInStreamLocal = function(socketPath, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); + cb(); + }); + } - var wantReply = (typeof cb === 'function'); + this._protocol.openssh_noMoreSessions(wantReply); + return this; + } - if (!this.config.strictVendor - || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { - if (wantReply) { - this._callbacks.push(function(had_err) { - if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to unbind on ' + socketPath)); - } + if (!wantReply) + return this; - cb(); - }); - } + process.nextTick( + cb, + new Error( + 'strictVendor enabled and server is not OpenSSH or compatible version' + ) + ); - return this._sshstream.openssh_cancelStreamLocalForward(socketPath, wantReply); - } else if (wantReply) { - process.nextTick(function() { - cb(new Error('strictVendor enabled and server is not OpenSSH or compatible version')); - }); + return this; } - return true; -}; - -Client.prototype.openssh_forwardOutStreamLocal = function(socketPath, cb) { - if (!this._sock - || !this._sock.writable - || !this._sshstream - || !this._sshstream.writable) - throw new Error('Not connected'); - - if (!this.config.strictVendor - || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { - var cfg = { socketPath: socketPath }; - return openChannel(this, 'direct-streamlocal@openssh.com', cfg, cb); - } else { - process.nextTick(function() { - cb(new Error('strictVendor enabled and server is not OpenSSH or compatible version')); - }); - } + openssh_forwardInStreamLocal(socketPath, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); + + const wantReply = (typeof cb === 'function'); + + if (!this.config.strictVendor + || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { + if (wantReply) { + this._callbacks.push((had_err) => { + if (had_err) { + cb(had_err !== true + ? had_err + : new Error(`Unable to bind to ${socketPath}`)); + return; + } + this._forwardingUnix[socketPath] = true; + cb(); + }); + } - return true; -}; + this._protocol.openssh_streamLocalForward(socketPath, wantReply); + return this; + } -function openChannel(self, type, opts, cb) { - // ask the server to open a channel for some purpose - // (e.g. session (sftp, exec, shell), or forwarding a TCP connection - var localChan = nextChannel(self); - var initWindow = Channel.MAX_WINDOW; - var maxPacket = Channel.PACKET_SIZE; - var ret = true; + if (!wantReply) + return this; - if (localChan === false) - return cb(new Error('No free channels available')); + process.nextTick( + cb, + new Error( + 'strictVendor enabled and server is not OpenSSH or compatible version' + ) + ); - if (typeof opts === 'function') { - cb = opts; - opts = {}; + return this; } - self._channels[localChan] = true; - - var sshstream = self._sshstream; - sshstream.once('CHANNEL_OPEN_CONFIRMATION:' + localChan, onSuccess) - .once('CHANNEL_OPEN_FAILURE:' + localChan, onFailure) - .once('CHANNEL_CLOSE:' + localChan, onFailure); - - if (type === 'session') - ret = sshstream.session(localChan, initWindow, maxPacket); - else if (type === 'direct-tcpip') - ret = sshstream.directTcpip(localChan, initWindow, maxPacket, opts); - else if (type === 'direct-streamlocal@openssh.com') { - ret = sshstream.openssh_directStreamLocal(localChan, - initWindow, - maxPacket, - opts); - } + openssh_unforwardInStreamLocal(socketPath, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); + + const wantReply = (typeof cb === 'function'); + + if (!this.config.strictVendor + || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { + if (wantReply) { + this._callbacks.push((had_err) => { + if (had_err) { + cb(had_err !== true + ? had_err + : new Error(`Unable to unbind from ${socketPath}`)); + return; + } + delete this._forwardingUnix[socketPath]; + cb(); + }); + } - return ret; + this._protocol.openssh_cancelStreamLocalForward(socketPath, wantReply); + return this; + } - function onSuccess(info) { - sshstream.removeListener('CHANNEL_OPEN_FAILURE:' + localChan, onFailure); - sshstream.removeListener('CHANNEL_CLOSE:' + localChan, onFailure); + if (!wantReply) + return this; - var chaninfo = { - type: type, - incoming: { - id: localChan, - window: initWindow, - packetSize: maxPacket, - state: 'open' - }, - outgoing: { - id: info.sender, - window: info.window, - packetSize: info.packetSize, - state: 'open' - } - }; - cb(undefined, new Channel(chaninfo, self)); + process.nextTick( + cb, + new Error( + 'strictVendor enabled and server is not OpenSSH or compatible version' + ) + ); + + return this; } - function onFailure(info) { - sshstream.removeListener('CHANNEL_OPEN_CONFIRMATION:' + localChan, - onSuccess); - sshstream.removeListener('CHANNEL_OPEN_FAILURE:' + localChan, onFailure); - sshstream.removeListener('CHANNEL_CLOSE:' + localChan, onFailure); - - delete self._channels[localChan]; - - var err; - if (info instanceof Error) - err = info; - else if (typeof info === 'object' && info !== null) { - err = new Error('(SSH) Channel open failure: ' + info.description); - err.reason = info.reason; - err.lang = info.lang; - } else { - err = new Error('(SSH) Channel open failure: ' - + 'server closed channel unexpectedly'); - err.reason = err.lang = ''; + openssh_forwardOutStreamLocal(socketPath, cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); + + if (typeof cb !== 'function') + cb = noop; + + if (!this.config.strictVendor + || (this.config.strictVendor && RE_OPENSSH.test(this._remoteVer))) { + openChannel(this, 'direct-streamlocal@openssh.com', { socketPath }, cb); + return this; } - cb(err); + process.nextTick( + cb, + new Error( + 'strictVendor enabled and server is not OpenSSH or compatible version' + ) + ); + + return this; + } + + sftp(cb) { + if (!this._sock || !isWritable(this._sock)) + throw new Error('Not connected'); + + openChannel(this, 'sftp', (err, sftp) => { + if (err) { + cb(err); + return; + } + + reqSubsystem(sftp, 'sftp', (err, sftp_) => { + if (err) { + cb(err); + return; + } + + function removeListeners() { + sftp.removeListener('ready', onReady); + sftp.removeListener('error', onError); + sftp.removeListener('exit', onExit); + sftp.removeListener('close', onExit); + } + + function onReady() { + // TODO: do not remove exit/close in case remote end closes the + // channel abruptly and we need to notify outstanding callbacks + removeListeners(); + cb(undefined, sftp); + } + + function onError(err) { + removeListeners(); + cb(err); + } + + function onExit(code, signal) { + removeListeners(); + let msg; + if (typeof code === 'number') + msg = `Received exit code ${code} while establishing SFTP session`; + else if (signal !== undefined) + msg = `Received signal ${signal} while establishing SFTP session`; + else + msg = 'Received unexpected SFTP session termination'; + const err = new Error(msg); + err.code = code; + err.signal = signal; + cb(err); + } + + sftp.on('ready', onReady) + .on('error', onError) + .on('exit', onExit) + .on('close', onExit); + + sftp._init(); + }); + }); + + return this; } } -function nextChannel(self) { - // get the next available channel number +function openChannel(self, type, opts, cb) { + // Ask the server to open a channel for some purpose + // (e.g. session (sftp, exec, shell), or forwarding a TCP connection + const initWindow = MAX_WINDOW; + const maxPacket = PACKET_SIZE; + + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + + const wrapper = (err, stream) => { + cb(err, stream); + }; + wrapper.type = type; - // optimized path - if (self._curChan < MAX_CHANNEL) - return ++self._curChan; + const localChan = self._chanMgr.add(wrapper); - // slower lookup path - for (var i = 0, channels = self._channels; i < MAX_CHANNEL; ++i) - if (!channels[i]) - return i; + if (localChan === -1) { + cb(new Error('No free channels available')); + return; + } - return false; + switch (type) { + case 'session': + case 'sftp': + self._protocol.session(localChan, initWindow, maxPacket); + break; + case 'direct-tcpip': + self._protocol.directTcpip(localChan, initWindow, maxPacket, opts); + break; + case 'direct-streamlocal@openssh.com': + self._protocol.openssh_directStreamLocal( + localChan, initWindow, maxPacket, opts + ); + break; + default: + throw new Error(`Unsupported channel type: ${type}`); + } } function reqX11(chan, screen, cb) { - // asks server to start sending us X11 connections - var cfg = { + // Asks server to start sending us X11 connections + const cfg = { single: false, protocol: 'MIT-MAGIC-COOKIE-1', - cookie: crypto.randomBytes(16).toString('hex'), - screen: (typeof screen === 'number' ? screen : 0) + cookie: undefined, + screen: 0 }; - if (typeof screen === 'function') + if (typeof screen === 'function') { cb = screen; - else if (typeof screen === 'object') { + } else if (typeof screen === 'object' && screen !== null) { if (typeof screen.single === 'boolean') cfg.single = screen.single; if (typeof screen.screen === 'number') cfg.screen = screen.screen; + if (typeof screen.protocol === 'string') + cfg.protocol = screen.protocol; + if (typeof screen.cookie === 'string') + cfg.cookie = screen.cookie; + else if (Buffer.isBuffer(screen.cookie)) + cfg.cookie = screen.cookie.hexSlice(0, screen.cookie.length); } + if (cfg.cookie === undefined) + cfg.cookie = randomCookie(); - var wantReply = (typeof cb === 'function'); + const wantReply = (typeof cb === 'function'); if (chan.outgoing.state !== 'open') { - wantReply && cb(new Error('Channel is not open')); - return true; + if (wantReply) + cb(new Error('Channel is not open')); + return; } if (wantReply) { - chan._callbacks.push(function(had_err) { + chan._callbacks.push((had_err) => { if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to request X11')); + cb(had_err !== true ? had_err : new Error('Unable to request X11')); + return; } chan._hasX11 = true; ++chan._client._acceptX11; - chan.once('close', function() { + chan.once('close', () => { if (chan._client._acceptX11) --chan._client._acceptX11; }); @@ -1254,19 +1608,20 @@ function reqX11(chan, screen, cb) { }); } - return chan._client._sshstream.x11Forward(chan.outgoing.id, cfg, wantReply); + chan._client._protocol.x11Forward(chan.outgoing.id, cfg, wantReply); } function reqPty(chan, opts, cb) { - var rows = 24; - var cols = 80; - var width = 640; - var height = 480; - var term = 'vt100'; + let rows = 24; + let cols = 80; + let width = 640; + let height = 480; + let term = 'vt100'; + let modes = null; - if (typeof opts === 'function') + if (typeof opts === 'function') { cb = opts; - else if (typeof opts === 'object') { + } else if (typeof opts === 'object' && opts !== null) { if (typeof opts.rows === 'number') rows = opts.rows; if (typeof opts.cols === 'number') @@ -1277,151 +1632,158 @@ function reqPty(chan, opts, cb) { height = opts.height; if (typeof opts.term === 'string') term = opts.term; + if (typeof opts.modes === 'object') + modes = opts.modes; } - var wantReply = (typeof cb === 'function'); + const wantReply = (typeof cb === 'function'); if (chan.outgoing.state !== 'open') { - wantReply && cb(new Error('Channel is not open')); - return true; + if (wantReply) + cb(new Error('Channel is not open')); + return; } if (wantReply) { - chan._callbacks.push(function(had_err) { + chan._callbacks.push((had_err) => { if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to request a pseudo-terminal')); + cb(had_err !== true + ? had_err + : new Error('Unable to request a pseudo-terminal')); + return; } cb(); }); } - return chan._client._sshstream.pty(chan.outgoing.id, - rows, - cols, - height, - width, - term, - null, - wantReply); + chan._client._protocol.pty(chan.outgoing.id, + rows, + cols, + height, + width, + term, + modes, + wantReply); } function reqAgentFwd(chan, cb) { - var wantReply = (typeof cb === 'function'); + const wantReply = (typeof cb === 'function'); if (chan.outgoing.state !== 'open') { wantReply && cb(new Error('Channel is not open')); - return true; - } else if (chan._client._agentFwdEnabled) { + return; + } + if (chan._client._agentFwdEnabled) { wantReply && cb(false); - return true; + return; } chan._client._agentFwdEnabled = true; - chan._callbacks.push(function(had_err) { + chan._callbacks.push((had_err) => { if (had_err) { chan._client._agentFwdEnabled = false; - wantReply && cb(had_err !== true - ? had_err - : new Error('Unable to request agent forwarding')); + if (wantReply) { + cb(had_err !== true + ? had_err + : new Error('Unable to request agent forwarding')); + } return; } - wantReply && cb(); + if (wantReply) + cb(); }); - return chan._client._sshstream.openssh_agentForward(chan.outgoing.id, true); + chan._client._protocol.openssh_agentForward(chan.outgoing.id, true); } function reqShell(chan, cb) { if (chan.outgoing.state !== 'open') { cb(new Error('Channel is not open')); - return true; + return; } - chan._callbacks.push(function(had_err) { + + chan._callbacks.push((had_err) => { if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to open shell')); + cb(had_err !== true ? had_err : new Error('Unable to open shell')); + return; } chan.subtype = 'shell'; cb(undefined, chan); }); - return chan._client._sshstream.shell(chan.outgoing.id, true); + chan._client._protocol.shell(chan.outgoing.id, true); } function reqExec(chan, cmd, opts, cb) { if (chan.outgoing.state !== 'open') { cb(new Error('Channel is not open')); - return true; + return; } - chan._callbacks.push(function(had_err) { + + chan._callbacks.push((had_err) => { if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to exec')); + cb(had_err !== true ? had_err : new Error('Unable to exec')); + return; } chan.subtype = 'exec'; chan.allowHalfOpen = (opts.allowHalfOpen !== false); cb(undefined, chan); }); - return chan._client._sshstream.exec(chan.outgoing.id, cmd, true); + chan._client._protocol.exec(chan.outgoing.id, cmd, true); } function reqEnv(chan, env) { if (chan.outgoing.state !== 'open') - return true; - var ret = true; - var keys = Object.keys(env || {}); - var key; - var val; - - for (var i = 0, len = keys.length; i < len; ++i) { - key = keys[i]; - val = env[key]; - ret = chan._client._sshstream.env(chan.outgoing.id, key, val, false); - } + return; + + const keys = Object.keys(env || {}); - return ret; + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const val = env[key]; + chan._client._protocol.env(chan.outgoing.id, key, val, false); + } } function reqSubsystem(chan, name, cb) { if (chan.outgoing.state !== 'open') { cb(new Error('Channel is not open')); - return true; + return; } - chan._callbacks.push(function(had_err) { + + chan._callbacks.push((had_err) => { if (had_err) { - return cb(had_err !== true - ? had_err - : new Error('Unable to start subsystem: ' + name)); + cb(had_err !== true + ? had_err + : new Error(`Unable to start subsystem: ${name}`)); + return; } chan.subtype = 'subsystem'; cb(undefined, chan); }); - return chan._client._sshstream.subsystem(chan.outgoing.id, name, true); + chan._client._protocol.subsystem(chan.outgoing.id, name, true); } +// TODO: inline implementation into single call site function onCHANNEL_OPEN(self, info) { - // the server is trying to open a channel with us, this is usually when + // The server is trying to open a channel with us, this is usually when // we asked the server to forward us connections on some port and now they // are asking us to accept/deny an incoming connection on their side - var localChan = false; - var reason; + let localChan = -1; + let reason; - function accept() { - var chaninfo = { + const accept = () => { + const chanInfo = { type: info.type, incoming: { id: localChan, - window: Channel.MAX_WINDOW, - packetSize: Channel.PACKET_SIZE, + window: MAX_WINDOW, + packetSize: PACKET_SIZE, state: 'open' }, outgoing: { @@ -1431,92 +1793,221 @@ function onCHANNEL_OPEN(self, info) { state: 'open' } }; - var stream = new Channel(chaninfo, self); + const stream = new Channel(self, chanInfo); + self._chanMgr.update(localChan, stream); - self._sshstream.channelOpenConfirm(info.sender, - localChan, - Channel.MAX_WINDOW, - Channel.PACKET_SIZE); + self._protocol.channelOpenConfirm(info.sender, + localChan, + MAX_WINDOW, + PACKET_SIZE); return stream; - } - function reject() { + }; + const reject = () => { if (reason === undefined) { - if (localChan === false) - reason = consts.CHANNEL_OPEN_FAILURE.RESOURCE_SHORTAGE; + if (localChan === -1) + reason = CHANNEL_OPEN_FAILURE.RESOURCE_SHORTAGE; else - reason = consts.CHANNEL_OPEN_FAILURE.CONNECT_FAILED; + reason = CHANNEL_OPEN_FAILURE.CONNECT_FAILED; } - self._sshstream.channelOpenFail(info.sender, reason, '', ''); - } + if (localChan !== -1) + self._chanMgr.remove(localChan); - if (info.type === 'forwarded-tcpip' - || info.type === 'x11' - || info.type === 'auth-agent@openssh.com') { - // check for conditions for automatic rejection - var rejectConn = ((info.type === 'forwarded-tcpip' - && self._forwarding[info.data.destIP - + ':' - + info.data.destPort] === undefined) - || (info.type === 'x11' && self._acceptX11 === 0) - || (info.type === 'auth-agent@openssh.com' - && !self._agentFwdEnabled)); - if (!rejectConn) { - localChan = nextChannel(self); - - if (localChan === false) { - self.config.debug('DEBUG: Client: Automatic rejection of incoming channel open: no channels available'); - rejectConn = true; - } else - self._channels[localChan] = true; - } else { - reason = consts.CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED; - self.config.debug('DEBUG: Client: Automatic rejection of incoming channel open: unexpected channel open for: ' - + info.type); + self._protocol.channelOpenFail(info.sender, reason, ''); + }; + const reserveChannel = () => { + localChan = self._chanMgr.add(); + + if (localChan === -1) { + reason = CHANNEL_OPEN_FAILURE.RESOURCE_SHORTAGE; + if (self.config.debug) { + self.config.debug( + 'Client: Automatic rejection of incoming channel open: ' + + 'no channels available' + ); + } } - // TODO: automatic rejection after some timeout? - - if (rejectConn) - reject(); + return (localChan !== -1); + }; - if (localChan !== false) { - if (info.type === 'forwarded-tcpip') { - if (info.data.destPort === 0) { - info.data.destPort = self._forwarding[info.data.destIP - + ':' - + info.data.destPort]; - } - self.emit('tcp connection', info.data, accept, reject); - } else if (info.type === 'x11') { - self.emit('x11', info.data, accept, reject); - } else { - agentQuery(self.config.agent, accept, reject); + const data = info.data; + switch (info.type) { + case 'forwarded-tcpip': { + const val = self._forwarding[`${data.destIP}:${data.destPort}`]; + if (val !== undefined && reserveChannel()) { + if (data.destPort === 0) + data.destPort = val; + self.emit('tcp connection', data, accept, reject); + return; } + break; } - } else { - // automatically reject any unsupported channel open requests - self.config.debug('DEBUG: Client: Automatic rejection of incoming channel open: unsupported type: ' - + info.type); - reason = consts.CHANNEL_OPEN_FAILURE.UNKNOWN_CHANNEL_TYPE; - reject(); + case 'forwarded-streamlocal@openssh.com': + if (self._forwardingUnix[data.socketPath] !== undefined + && reserveChannel()) { + self.emit('unix connection', data, accept, reject); + return; + } + break; + case 'auth-agent@openssh.com': + if (self._agentFwdEnabled + && typeof self._agent.getStream === 'function' + && reserveChannel()) { + self._agent.getStream((err, stream) => { + if (err) + return reject(); + + const upstream = accept(); + upstream.pipe(stream).pipe(upstream); + }); + return; + } + break; + case 'x11': + if (self._acceptX11 !== 0 && reserveChannel()) { + self.emit('x11', data, accept, reject); + return; + } + break; + default: + // Automatically reject any unsupported channel open requests + reason = CHANNEL_OPEN_FAILURE.UNKNOWN_CHANNEL_TYPE; + if (self.config.debug) { + self.config.debug( + 'Client: Automatic rejection of unsupported incoming channel open ' + + `type: ${info.type}` + ); + } } -} -function trySign(sig, key) { - try { - return sig.sign(key); - } catch (err) { - return err; + if (reason === undefined) { + reason = CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED; + if (self.config.debug) { + self.config.debug( + 'Client: Automatic rejection of unexpected incoming channel open for: ' + + info.type + ); + } } + + reject(); } -Client.Client = Client; -Client.Server = require('./server'); -// pass some useful utilities on to end user (e.g. parseKey(), genPublicKey()) -Client.utils = ssh2_streams.utils; -// expose useful SFTPStream constants for sftp server usage -Client.SFTP_STATUS_CODE = SFTPStream.STATUS_CODE; -Client.SFTP_OPEN_MODE = SFTPStream.OPEN_MODE; +const randomCookie = (() => { + const buffer = Buffer.allocUnsafe(16); + return () => { + randomFillSync(buffer, 0, 16); + return buffer.hexSlice(0, 16); + }; +})(); + +function makeSimpleAuthHandler(authList) { + if (!Array.isArray(authList)) + throw new Error('authList must be an array'); + + let a = 0; + return (authsLeft, partialSuccess, cb) => { + if (a === authList.length) + return false; + return authList[a++]; + }; +} + +function hostKeysProve(client, keys_, cb) { + if (!client._sock || !isWritable(client._sock)) + return; + + if (typeof cb !== 'function') + cb = noop; + + if (!Array.isArray(keys_)) + throw new TypeError('Invalid keys argument type'); + + const keys = []; + for (const key of keys_) { + const parsed = parseKey(key); + if (parsed instanceof Error) + throw parsed; + keys.push(parsed); + } + + if (!client.config.strictVendor + || (client.config.strictVendor && RE_OPENSSH.test(client._remoteVer))) { + client._callbacks.push((had_err, data) => { + if (had_err) { + cb(had_err !== true + ? had_err + : new Error('Server failed to prove supplied keys')); + return; + } + + // TODO: move all of this parsing/verifying logic out of the client? + const ret = []; + let keyIdx = 0; + bufferParser.init(data, 0); + while (bufferParser.avail()) { + if (keyIdx === keys.length) + break; + const key = keys[keyIdx++]; + const keyPublic = key.getPublicSSH(); + + const sigEntry = bufferParser.readString(); + sigParser.init(sigEntry, 0); + const type = sigParser.readString(true); + let value = sigParser.readString(); + + let algo; + if (type !== key.type) { + if (key.type === 'ssh-rsa') { + switch (type) { + case 'rsa-sha2-256': + algo = 'sha256'; + break; + case 'rsa-sha2-512': + algo = 'sha512'; + break; + default: + continue; + } + } else { + continue; + } + } + + const sessionID = client._protocol._kex.sessionID; + const verifyData = Buffer.allocUnsafe( + 4 + 29 + 4 + sessionID.length + 4 + keyPublic.length + ); + let p = 0; + writeUInt32BE(verifyData, 29, p); + verifyData.utf8Write('hostkeys-prove-00@openssh.com', p += 4, 29); + writeUInt32BE(verifyData, sessionID.length, p += 29); + bufferCopy(sessionID, verifyData, 0, sessionID.length, p += 4); + writeUInt32BE(verifyData, keyPublic.length, p += sessionID.length); + bufferCopy(keyPublic, verifyData, 0, keyPublic.length, p += 4); + + if (!(value = sigSSHToASN1(value, type))) + continue; + if (key.verify(verifyData, value, algo) === true) + ret.push(key); + } + sigParser.clear(); + bufferParser.clear(); + + cb(null, ret); + }); + + client._protocol.openssh_hostKeysProve(keys); + return; + } + + process.nextTick( + cb, + new Error( + 'strictVendor enabled and server is not OpenSSH or compatible version' + ) + ); +} -module.exports = Client; // backwards compatibility +module.exports = Client; diff --git a/reverse_engineering/node_modules/ssh2/lib/http-agents.js b/reverse_engineering/node_modules/ssh2/lib/http-agents.js new file mode 100644 index 0000000..770a0e6 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/http-agents.js @@ -0,0 +1,84 @@ +'use strict'; + +const { Agent: HttpAgent } = require('http'); +const { Agent: HttpsAgent } = require('https'); +const { connect: tlsConnect } = require('tls'); + +let Client; + +for (const ctor of [HttpAgent, HttpsAgent]) { + class SSHAgent extends ctor { + constructor(connectCfg, agentOptions) { + super(agentOptions); + + this._connectCfg = connectCfg; + this._defaultSrcIP = (agentOptions && agentOptions.srcIP) || 'localhost'; + } + + createConnection(options, cb) { + const srcIP = (options && options.localAddress) || this._defaultSrcIP; + const srcPort = (options && options.localPort) || 0; + const dstIP = options.host; + const dstPort = options.port; + + if (Client === undefined) + Client = require('./client.js'); + + const client = new Client(); + let triedForward = false; + client.on('ready', () => { + client.forwardOut(srcIP, srcPort, dstIP, dstPort, (err, stream) => { + triedForward = true; + if (err) { + client.end(); + return cb(err); + } + stream.once('close', () => client.end()); + cb(null, decorateStream(stream, ctor, options)); + }); + }).on('error', cb).on('close', () => { + if (!triedForward) + cb(new Error('Unexpected connection close')); + }).connect(this._connectCfg); + } + } + + exports[ctor === HttpAgent ? 'SSHTTPAgent' : 'SSHTTPSAgent'] = SSHAgent; +} + +function noop() {} + +function decorateStream(stream, ctor, options) { + if (ctor === HttpAgent) { + // HTTP + stream.setKeepAlive = noop; + stream.setNoDelay = noop; + stream.setTimeout = noop; + stream.ref = noop; + stream.unref = noop; + stream.destroySoon = stream.destroy; + return stream; + } + + // HTTPS + options.socket = stream; + const wrapped = tlsConnect(options); + + // This is a workaround for a regression in node v12.16.3+ + // https://github.com/nodejs/node/issues/35904 + const onClose = (() => { + let called = false; + return () => { + if (called) + return; + called = true; + if (stream.isPaused()) + stream.resume(); + }; + })(); + // 'end' listener is needed because 'close' is not emitted in some scenarios + // in node v12.x for some unknown reason + wrapped.on('end', onClose).on('close', onClose); + + return wrapped; +} diff --git a/reverse_engineering/node_modules/ssh2/lib/index.js b/reverse_engineering/node_modules/ssh2/lib/index.js new file mode 100644 index 0000000..459952e --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/index.js @@ -0,0 +1,43 @@ +'use strict'; + +const { + AgentProtocol, + BaseAgent, + createAgent, + CygwinAgent, + OpenSSHAgent, + PageantAgent, +} = require('./agent.js'); +const { + SSHTTPAgent: HTTPAgent, + SSHTTPSAgent: HTTPSAgent, +} = require('./http-agents.js'); +const { parseKey } = require('./protocol/keyParser.js'); +const { + flagsToString, + OPEN_MODE, + STATUS_CODE, + stringToFlags, +} = require('./protocol/SFTP.js'); + +module.exports = { + AgentProtocol, + BaseAgent, + createAgent, + Client: require('./client.js'), + CygwinAgent, + HTTPAgent, + HTTPSAgent, + OpenSSHAgent, + PageantAgent, + Server: require('./server.js'), + utils: { + parseKey, + sftp: { + flagsToString, + OPEN_MODE, + STATUS_CODE, + stringToFlags, + }, + }, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/keepalivemgr.js b/reverse_engineering/node_modules/ssh2/lib/keepalivemgr.js deleted file mode 100644 index 28572ab..0000000 --- a/reverse_engineering/node_modules/ssh2/lib/keepalivemgr.js +++ /dev/null @@ -1,76 +0,0 @@ -var spliceOne = require('./utils').spliceOne; - -function Manager(interval, streamInterval, kaCountMax) { - var streams = this._streams = []; - this._timer = undefined; - this._timerInterval = interval; - this._timerfn = function() { - var now = Date.now(); - for (var i = 0, len = streams.length, s, last; i < len; ++i) { - s = streams[i]; - last = s._kalast; - if (last && (now - last) >= streamInterval) { - if (++s._kacnt > kaCountMax) { - var err = new Error('Keepalive timeout'); - err.level = 'client-timeout'; - s.emit('error', err); - s.disconnect(); - spliceOne(streams, i); - --i; - len = streams.length; - } else { - s._kalast = now; - // XXX: if the server ever starts sending real global requests to the - // client, we will need to add a dummy callback here to keep the - // correct reply order - s.ping(); - } - } - } - }; -} - -Manager.prototype.start = function() { - if (this._timer) - this.stop(); - this._timer = setInterval(this._timerfn, this._timerInterval); -}; - -Manager.prototype.stop = function() { - if (this._timer) { - clearInterval(this._timer); - this._timer = undefined; - } -}; - -Manager.prototype.add = function(stream) { - var streams = this._streams, - self = this; - - stream.once('end', function() { - self.remove(stream); - }).on('packet', resetKA); - - streams[streams.length] = stream; - - resetKA(); - - if (!this._timer) - this.start(); - - function resetKA() { - stream._kalast = Date.now(); - stream._kacnt = 0; - } -}; - -Manager.prototype.remove = function(stream) { - var streams = this._streams, - index = streams.indexOf(stream); - if (index > -1) - spliceOne(streams, index); - if (!streams.length) - this.stop(); -}; - -module.exports = Manager; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/Protocol.js b/reverse_engineering/node_modules/ssh2/lib/protocol/Protocol.js new file mode 100644 index 0000000..e00f1eb --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/Protocol.js @@ -0,0 +1,2076 @@ +/* + TODO: + * Replace `buffer._pos` usage in keyParser.js and elsewhere + * Utilize optional "writev" support when writing packets from + cipher.encrypt() + * Built-in support for automatic re-keying, on by default + * Revisit receiving unexpected/unknown packets + * Error (fatal or otherwise) or ignore or pass on to user (in some or all + cases)? + * Including server/client check for single directional packet types? + * Check packets for validity or bail as early as possible? + * Automatic re-key every 2**31 packets after the last key exchange (sent or + received), as suggested by RFC4344. OpenSSH currently does this. + * Automatic re-key every so many blocks depending on cipher. RFC4344: + Because of a birthday property of block ciphers and some modes of + operation, implementations must be careful not to encrypt too many + blocks with the same encryption key. + + Let L be the block length (in bits) of an SSH encryption method's + block cipher (e.g., 128 for AES). If L is at least 128, then, after + rekeying, an SSH implementation SHOULD NOT encrypt more than 2**(L/4) + blocks before rekeying again. If L is at least 128, then SSH + implementations should also attempt to force a rekey before receiving + more than 2**(L/4) blocks. If L is less than 128 (which is the case + for older ciphers such as 3DES, Blowfish, CAST-128, and IDEA), then, + although it may be too expensive to rekey every 2**(L/4) blocks, it + is still advisable for SSH implementations to follow the original + recommendation in [RFC4253]: rekey at least once for every gigabyte + of transmitted data. + + Note that if L is less than or equal to 128, then the recommendation + in this subsection supersedes the recommendation in Section 3.1. If + an SSH implementation uses a block cipher with a larger block size + (e.g., Rijndael with 256-bit blocks), then the recommendations in + Section 3.1 may supersede the recommendations in this subsection + (depending on the lengths of the packets). +*/ + +'use strict'; + +const { inspect } = require('util'); + +const { bindingAvailable, NullCipher, NullDecipher } = require('./crypto.js'); +const { + COMPAT_CHECKS, + DISCONNECT_REASON, + MESSAGE, + SIGNALS, + TERMINAL_MODE, +} = require('./constants.js'); +const { + DEFAULT_KEXINIT, + KexInit, + kexinit, + onKEXPayload, +} = require('./kex.js'); +const { + parseKey, +} = require('./keyParser.js'); +const MESSAGE_HANDLERS = require('./handlers.js'); +const { + bufferCopy, + bufferFill, + bufferSlice, + convertSignature, + sendPacket, + writeUInt32BE, +} = require('./utils.js'); +const { + PacketReader, + PacketWriter, + ZlibPacketReader, + ZlibPacketWriter, +} = require('./zlib.js'); + +const MODULE_VER = require('../../package.json').version; + +const VALID_DISCONNECT_REASONS = new Map( + Object.values(DISCONNECT_REASON).map((n) => [n, 1]) +); +const IDENT_RAW = Buffer.from(`SSH-2.0-ssh2js${MODULE_VER}`); +const IDENT = Buffer.from(`${IDENT_RAW}\r\n`); +const MAX_LINE_LEN = 8192; +const MAX_LINES = 1024; +const PING_PAYLOAD = Buffer.from([ + MESSAGE.GLOBAL_REQUEST, + // "keepalive@openssh.com" + 0, 0, 0, 21, + 107, 101, 101, 112, 97, 108, 105, 118, 101, 64, 111, 112, 101, 110, 115, + 115, 104, 46, 99, 111, 109, + // Request a reply + 1, +]); +const NO_TERMINAL_MODES_BUFFER = Buffer.from([ TERMINAL_MODE.TTY_OP_END ]); + +function noop() {} + +/* + Inbound: + * kexinit payload (needed only until exchange hash is generated) + * raw ident + * rekey packet queue + * expected packet (implemented as separate _parse() function?) + Outbound: + * kexinit payload (needed only until exchange hash is generated) + * rekey packet queue + * kex secret (needed only until NEWKEYS) + * exchange hash (needed only until NEWKEYS) + * session ID (set to exchange hash from initial handshake) +*/ +class Protocol { + constructor(config) { + const onWrite = config.onWrite; + if (typeof onWrite !== 'function') + throw new Error('Missing onWrite function'); + this._onWrite = (data) => { onWrite(data); }; + + const onError = config.onError; + if (typeof onError !== 'function') + throw new Error('Missing onError function'); + this._onError = (err) => { onError(err); }; + + const debug = config.debug; + this._debug = (typeof debug === 'function' + ? (msg) => { debug(msg); } + : undefined); + + const onHeader = config.onHeader; + this._onHeader = (typeof onHeader === 'function' + ? (...args) => { onHeader(...args); } + : noop); + + const onPacket = config.onPacket; + this._onPacket = (typeof onPacket === 'function' + ? () => { onPacket(); } + : noop); + + let onHandshakeComplete = config.onHandshakeComplete; + if (typeof onHandshakeComplete !== 'function') + onHandshakeComplete = noop; + this._onHandshakeComplete = (...args) => { + this._debug && this._debug('Handshake completed'); + + // Process packets queued during a rekey where necessary + const oldQueue = this._queue; + if (oldQueue) { + this._queue = undefined; + this._debug && this._debug( + `Draining outbound queue (${oldQueue.length}) ...` + ); + for (let i = 0; i < oldQueue.length; ++i) { + const data = oldQueue[i]; + // data === payload only + + // XXX: hacky + let finalized = this._packetRW.write.finalize(data); + if (finalized === data) { + const packet = this._cipher.allocPacket(data.length); + packet.set(data, 5); + finalized = packet; + } + + sendPacket(this, finalized); + } + this._debug && this._debug('... finished draining outbound queue'); + } + + onHandshakeComplete(...args); + }; + this._queue = undefined; + + const messageHandlers = config.messageHandlers; + if (typeof messageHandlers === 'object' && messageHandlers !== null) + this._handlers = messageHandlers; + else + this._handlers = {}; + + this._onPayload = onPayload.bind(this); + + this._server = !!config.server; + this._banner = undefined; + let greeting; + if (this._server) { + if (typeof config.hostKeys !== 'object' || config.hostKeys === null) + throw new Error('Missing server host key(s)'); + this._hostKeys = config.hostKeys; + + // Greeting displayed before the ssh identification string is sent, this + // is usually ignored by most clients + if (typeof config.greeting === 'string' && config.greeting.length) { + greeting = (config.greeting.slice(-2) === '\r\n' + ? config.greeting + : `${config.greeting}\r\n`); + } + + // Banner shown after the handshake completes, but before user + // authentication begins + if (typeof config.banner === 'string' && config.banner.length) { + this._banner = (config.banner.slice(-2) === '\r\n' + ? config.banner + : `${config.banner}\r\n`); + } + } else { + this._hostKeys = undefined; + } + + let offer = config.offer; + if (typeof offer !== 'object' || offer === null) + offer = DEFAULT_KEXINIT; + else if (offer.constructor !== KexInit) + offer = new KexInit(offer); + this._kex = undefined; + this._kexinit = undefined; + this._offer = offer; + this._cipher = new NullCipher(0, this._onWrite); + this._decipher = undefined; + this._skipNextInboundPacket = false; + this._packetRW = { + read: new PacketReader(), + write: new PacketWriter(this), + }; + this._hostVerifier = (!this._server + && typeof config.hostVerifier === 'function' + ? config.hostVerifier + : undefined); + + this._parse = parseHeader; + this._buffer = undefined; + this._authsQueue = []; + this._authenticated = false; + this._remoteIdentRaw = undefined; + let sentIdent; + if (typeof config.ident === 'string') { + this._identRaw = Buffer.from(`SSH-2.0-${config.ident}`); + + sentIdent = Buffer.allocUnsafe(this._identRaw.length + 2); + sentIdent.set(this._identRaw, 0); + sentIdent[sentIdent.length - 2] = 13; // '\r' + sentIdent[sentIdent.length - 1] = 10; // '\n' + } else if (Buffer.isBuffer(config.ident)) { + const fullIdent = Buffer.allocUnsafe(8 + config.ident.length); + fullIdent.latin1Write('SSH-2.0-', 0, 8); + fullIdent.set(config.ident, 8); + this._identRaw = fullIdent; + + sentIdent = Buffer.allocUnsafe(fullIdent.length + 2); + sentIdent.set(fullIdent, 0); + sentIdent[sentIdent.length - 2] = 13; // '\r' + sentIdent[sentIdent.length - 1] = 10; // '\n' + } else { + this._identRaw = IDENT_RAW; + sentIdent = IDENT; + } + this._compatFlags = 0; + + if (this._debug) { + if (bindingAvailable) + this._debug('Custom crypto binding available'); + else + this._debug('Custom crypto binding not available'); + } + + process.nextTick(() => { + this._debug && this._debug( + `Local ident: ${inspect(this._identRaw.toString())}` + ); + if (greeting) + this._onWrite(greeting); + this._onWrite(sentIdent); + }); + } + _destruct(reason) { + this._packetRW.read.cleanup(); + this._packetRW.write.cleanup(); + this._cipher && this._cipher.free(); + this._decipher && this._decipher.free(); + if (typeof reason !== 'string' || reason.length === 0) + reason = 'fatal error'; + this.parse = () => { + throw new Error(`Instance unusable after ${reason}`); + }; + this._onWrite = () => { + throw new Error(`Instance unusable after ${reason}`); + }; + this._destruct = undefined; + } + cleanup() { + this._destruct && this._destruct(); + } + parse(chunk, i, len) { + while (i < len) + i = this._parse(chunk, i, len); + } + + // Protocol message API + + // =========================================================================== + // Common/Shared ============================================================= + // =========================================================================== + + // Global + // ------ + disconnect(reason) { + const pktLen = 1 + 4 + 4 + 4; + // We don't use _packetRW.write.* here because we need to make sure that + // we always get a full packet allocated because this message can be sent + // at any time -- even during a key exchange + let p = this._packetRW.write.allocStartKEX; + const packet = this._packetRW.write.alloc(pktLen, true); + const end = p + pktLen; + + if (!VALID_DISCONNECT_REASONS.has(reason)) + reason = DISCONNECT_REASON.PROTOCOL_ERROR; + + packet[p] = MESSAGE.DISCONNECT; + writeUInt32BE(packet, reason, ++p); + packet.fill(0, p += 4, end); + + this._debug && this._debug(`Outbound: Sending DISCONNECT (${reason})`); + sendPacket(this, this._packetRW.write.finalize(packet, true), true); + } + ping() { + const p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(PING_PAYLOAD.length); + + packet.set(PING_PAYLOAD, p); + + this._debug && this._debug( + 'Outbound: Sending ping (GLOBAL_REQUEST: keepalive@openssh.com)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + rekey() { + if (this._kexinit === undefined) { + this._debug && this._debug('Outbound: Initiated explicit rekey'); + this._queue = []; + kexinit(this); + } else { + this._debug && this._debug('Outbound: Ignoring rekey during handshake'); + } + } + + // 'ssh-connection' service-specific + // --------------------------------- + requestSuccess(data) { + let p = this._packetRW.write.allocStart; + let packet; + if (Buffer.isBuffer(data)) { + packet = this._packetRW.write.alloc(1 + data.length); + + packet[p] = MESSAGE.REQUEST_SUCCESS; + + packet.set(data, ++p); + } else { + packet = this._packetRW.write.alloc(1); + + packet[p] = MESSAGE.REQUEST_SUCCESS; + } + + this._debug && this._debug('Outbound: Sending REQUEST_SUCCESS'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + requestFailure() { + const p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1); + + packet[p] = MESSAGE.REQUEST_FAILURE; + + this._debug && this._debug('Outbound: Sending REQUEST_FAILURE'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelSuccess(chan) { + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4); + + packet[p] = MESSAGE.CHANNEL_SUCCESS; + + writeUInt32BE(packet, chan, ++p); + + this._debug && this._debug(`Outbound: Sending CHANNEL_SUCCESS (r:${chan})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelFailure(chan) { + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4); + + packet[p] = MESSAGE.CHANNEL_FAILURE; + + writeUInt32BE(packet, chan, ++p); + + this._debug && this._debug(`Outbound: Sending CHANNEL_FAILURE (r:${chan})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelEOF(chan) { + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4); + + packet[p] = MESSAGE.CHANNEL_EOF; + + writeUInt32BE(packet, chan, ++p); + + this._debug && this._debug(`Outbound: Sending CHANNEL_EOF (r:${chan})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelClose(chan) { + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4); + + packet[p] = MESSAGE.CHANNEL_CLOSE; + + writeUInt32BE(packet, chan, ++p); + + this._debug && this._debug(`Outbound: Sending CHANNEL_CLOSE (r:${chan})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelWindowAdjust(chan, amount) { + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4); + + packet[p] = MESSAGE.CHANNEL_WINDOW_ADJUST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, amount, p += 4); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_WINDOW_ADJUST (r:${chan}, ${amount})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelData(chan, data) { + const isBuffer = Buffer.isBuffer(data); + const dataLen = (isBuffer ? data.length : Buffer.byteLength(data)); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + dataLen); + + packet[p] = MESSAGE.CHANNEL_DATA; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, dataLen, p += 4); + + if (isBuffer) + packet.set(data, p += 4); + else + packet.utf8Write(data, p += 4, dataLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_DATA (r:${chan}, ${dataLen})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelExtData(chan, data, type) { + const isBuffer = Buffer.isBuffer(data); + const dataLen = (isBuffer ? data.length : Buffer.byteLength(data)); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 4 + dataLen); + + packet[p] = MESSAGE.CHANNEL_EXTENDED_DATA; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, type, p += 4); + + writeUInt32BE(packet, dataLen, p += 4); + + if (isBuffer) + packet.set(data, p += 4); + else + packet.utf8Write(data, p += 4, dataLen); + + this._debug + && this._debug(`Outbound: Sending CHANNEL_EXTENDED_DATA (r:${chan})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelOpenConfirm(remote, local, initWindow, maxPacket) { + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 4 + 4); + + packet[p] = MESSAGE.CHANNEL_OPEN_CONFIRMATION; + + writeUInt32BE(packet, remote, ++p); + + writeUInt32BE(packet, local, p += 4); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_OPEN_CONFIRMATION (r:${remote}, l:${local})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + channelOpenFail(remote, reason, desc) { + if (typeof desc !== 'string') + desc = ''; + + const descLen = Buffer.byteLength(desc); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 4 + descLen + 4); + + packet[p] = MESSAGE.CHANNEL_OPEN_FAILURE; + + writeUInt32BE(packet, remote, ++p); + + writeUInt32BE(packet, reason, p += 4); + + writeUInt32BE(packet, descLen, p += 4); + + p += 4; + if (descLen) { + packet.utf8Write(desc, p, descLen); + p += descLen; + } + + writeUInt32BE(packet, 0, p); // Empty language tag + + this._debug + && this._debug(`Outbound: Sending CHANNEL_OPEN_FAILURE (r:${remote})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + + // =========================================================================== + // Client-specific =========================================================== + // =========================================================================== + + // Global + // ------ + service(name) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const nameLen = Buffer.byteLength(name); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + nameLen); + + packet[p] = MESSAGE.SERVICE_REQUEST; + + writeUInt32BE(packet, nameLen, ++p); + packet.utf8Write(name, p += 4, nameLen); + + this._debug && this._debug(`Outbound: Sending SERVICE_REQUEST (${name})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + + // 'ssh-userauth' service-specific + // ------------------------------- + authPassword(username, password, newPassword) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const userLen = Buffer.byteLength(username); + const passLen = Buffer.byteLength(password); + const newPassLen = (newPassword ? Buffer.byteLength(newPassword) : 0); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + userLen + 4 + 14 + 4 + 8 + 1 + 4 + passLen + + (newPassword ? 4 + newPassLen : 0) + ); + + packet[p] = MESSAGE.USERAUTH_REQUEST; + + writeUInt32BE(packet, userLen, ++p); + packet.utf8Write(username, p += 4, userLen); + + writeUInt32BE(packet, 14, p += userLen); + packet.utf8Write('ssh-connection', p += 4, 14); + + writeUInt32BE(packet, 8, p += 14); + packet.utf8Write('password', p += 4, 8); + + packet[p += 8] = (newPassword ? 1 : 0); + + writeUInt32BE(packet, passLen, ++p); + if (Buffer.isBuffer(password)) + bufferCopy(password, packet, 0, passLen, p += 4); + else + packet.utf8Write(password, p += 4, passLen); + + if (newPassword) { + writeUInt32BE(packet, newPassLen, p += passLen); + if (Buffer.isBuffer(newPassword)) + bufferCopy(newPassword, packet, 0, newPassLen, p += 4); + else + packet.utf8Write(newPassword, p += 4, newPassLen); + this._debug && this._debug( + 'Outbound: Sending USERAUTH_REQUEST (changed password)' + ); + } else { + this._debug && this._debug( + 'Outbound: Sending USERAUTH_REQUEST (password)' + ); + } + + this._authsQueue.push('password'); + + sendPacket(this, this._packetRW.write.finalize(packet)); + } + authPK(username, pubKey, cbSign) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + pubKey = parseKey(pubKey); + if (pubKey instanceof Error) + throw new Error('Invalid key'); + + const keyType = pubKey.type; + pubKey = pubKey.getPublicSSH(); + + const userLen = Buffer.byteLength(username); + const algoLen = Buffer.byteLength(keyType); + const pubKeyLen = pubKey.length; + const sessionID = this._kex.sessionID; + const sesLen = sessionID.length; + const payloadLen = + (cbSign ? 4 + sesLen : 0) + + 1 + 4 + userLen + 4 + 14 + 4 + 9 + 1 + 4 + algoLen + 4 + pubKeyLen; + let packet; + let p; + if (cbSign) { + packet = Buffer.allocUnsafe(payloadLen); + p = 0; + writeUInt32BE(packet, sesLen, p); + packet.set(sessionID, p += 4); + p += sesLen; + } else { + packet = this._packetRW.write.alloc(payloadLen); + p = this._packetRW.write.allocStart; + } + + packet[p] = MESSAGE.USERAUTH_REQUEST; + + writeUInt32BE(packet, userLen, ++p); + packet.utf8Write(username, p += 4, userLen); + + writeUInt32BE(packet, 14, p += userLen); + packet.utf8Write('ssh-connection', p += 4, 14); + + writeUInt32BE(packet, 9, p += 14); + packet.utf8Write('publickey', p += 4, 9); + + packet[p += 9] = (cbSign ? 1 : 0); + + writeUInt32BE(packet, algoLen, ++p); + packet.utf8Write(keyType, p += 4, algoLen); + + writeUInt32BE(packet, pubKeyLen, p += algoLen); + packet.set(pubKey, p += 4); + + if (!cbSign) { + this._authsQueue.push('publickey'); + + this._debug && this._debug( + 'Outbound: Sending USERAUTH_REQUEST (publickey -- check)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + return; + } + + cbSign(packet, (signature) => { + signature = convertSignature(signature, keyType); + if (signature === false) + throw new Error('Error while converting handshake signature'); + + const sigLen = signature.length; + p = this._packetRW.write.allocStart; + packet = this._packetRW.write.alloc( + 1 + 4 + userLen + 4 + 14 + 4 + 9 + 1 + 4 + algoLen + 4 + pubKeyLen + 4 + + 4 + algoLen + 4 + sigLen + ); + + // TODO: simply copy from original "packet" to new `packet` to avoid + // having to write each individual field a second time? + packet[p] = MESSAGE.USERAUTH_REQUEST; + + writeUInt32BE(packet, userLen, ++p); + packet.utf8Write(username, p += 4, userLen); + + writeUInt32BE(packet, 14, p += userLen); + packet.utf8Write('ssh-connection', p += 4, 14); + + writeUInt32BE(packet, 9, p += 14); + packet.utf8Write('publickey', p += 4, 9); + + packet[p += 9] = 1; + + writeUInt32BE(packet, algoLen, ++p); + packet.utf8Write(keyType, p += 4, algoLen); + + writeUInt32BE(packet, pubKeyLen, p += algoLen); + packet.set(pubKey, p += 4); + + writeUInt32BE(packet, 4 + algoLen + 4 + sigLen, p += pubKeyLen); + + writeUInt32BE(packet, algoLen, p += 4); + packet.utf8Write(keyType, p += 4, algoLen); + + writeUInt32BE(packet, sigLen, p += algoLen); + packet.set(signature, p += 4); + + // Servers shouldn't send packet type 60 in response to signed publickey + // attempts, but if they do, interpret as type 60. + this._authsQueue.push('publickey'); + + this._debug && this._debug( + 'Outbound: Sending USERAUTH_REQUEST (publickey)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + }); + } + authHostbased(username, pubKey, hostname, userlocal, cbSign) { + // TODO: Make DRY by sharing similar code with authPK() + if (this._server) + throw new Error('Client-only method called in server mode'); + + pubKey = parseKey(pubKey); + if (pubKey instanceof Error) + throw new Error('Invalid key'); + + const keyType = pubKey.type; + pubKey = pubKey.getPublicSSH(); + + const userLen = Buffer.byteLength(username); + const algoLen = Buffer.byteLength(keyType); + const pubKeyLen = pubKey.length; + const sessionID = this._kex.sessionID; + const sesLen = sessionID.length; + const hostnameLen = Buffer.byteLength(hostname); + const userlocalLen = Buffer.byteLength(userlocal); + const data = Buffer.allocUnsafe( + 4 + sesLen + 1 + 4 + userLen + 4 + 14 + 4 + 9 + 4 + algoLen + + 4 + pubKeyLen + 4 + hostnameLen + 4 + userlocalLen + ); + let p = 0; + + writeUInt32BE(data, sesLen, p); + data.set(sessionID, p += 4); + + data[p += sesLen] = MESSAGE.USERAUTH_REQUEST; + + writeUInt32BE(data, userLen, ++p); + data.utf8Write(username, p += 4, userLen); + + writeUInt32BE(data, 14, p += userLen); + data.utf8Write('ssh-connection', p += 4, 14); + + writeUInt32BE(data, 9, p += 14); + data.utf8Write('hostbased', p += 4, 9); + + writeUInt32BE(data, algoLen, p += 9); + data.utf8Write(keyType, p += 4, algoLen); + + writeUInt32BE(data, pubKeyLen, p += algoLen); + data.set(pubKey, p += 4); + + writeUInt32BE(data, hostnameLen, p += pubKeyLen); + data.utf8Write(hostname, p += 4, hostnameLen); + + writeUInt32BE(data, userlocalLen, p += hostnameLen); + data.utf8Write(userlocal, p += 4, userlocalLen); + + cbSign(data, (signature) => { + signature = convertSignature(signature, keyType); + if (!signature) + throw new Error('Error while converting handshake signature'); + + const sigLen = signature.length; + const reqDataLen = (data.length - sesLen - 4); + p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + reqDataLen + 4 + 4 + algoLen + 4 + sigLen + ); + + bufferCopy(data, packet, 4 + sesLen, data.length, p); + + writeUInt32BE(packet, 4 + algoLen + 4 + sigLen, p += reqDataLen); + writeUInt32BE(packet, algoLen, p += 4); + packet.utf8Write(keyType, p += 4, algoLen); + writeUInt32BE(packet, sigLen, p += algoLen); + packet.set(signature, p += 4); + + this._authsQueue.push('hostbased'); + + this._debug && this._debug( + 'Outbound: Sending USERAUTH_REQUEST (hostbased)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + }); + } + authKeyboard(username) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const userLen = Buffer.byteLength(username); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + userLen + 4 + 14 + 4 + 20 + 4 + 4 + ); + + packet[p] = MESSAGE.USERAUTH_REQUEST; + + writeUInt32BE(packet, userLen, ++p); + packet.utf8Write(username, p += 4, userLen); + + writeUInt32BE(packet, 14, p += userLen); + packet.utf8Write('ssh-connection', p += 4, 14); + + writeUInt32BE(packet, 20, p += 14); + packet.utf8Write('keyboard-interactive', p += 4, 20); + + writeUInt32BE(packet, 0, p += 20); + + writeUInt32BE(packet, 0, p += 4); + + this._authsQueue.push('keyboard-interactive'); + + this._debug && this._debug( + 'Outbound: Sending USERAUTH_REQUEST (keyboard-interactive)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + authNone(username) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const userLen = Buffer.byteLength(username); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + userLen + 4 + 14 + 4 + 4); + + packet[p] = MESSAGE.USERAUTH_REQUEST; + + writeUInt32BE(packet, userLen, ++p); + packet.utf8Write(username, p += 4, userLen); + + writeUInt32BE(packet, 14, p += userLen); + packet.utf8Write('ssh-connection', p += 4, 14); + + writeUInt32BE(packet, 4, p += 14); + packet.utf8Write('none', p += 4, 4); + + this._authsQueue.push('none'); + + this._debug && this._debug('Outbound: Sending USERAUTH_REQUEST (none)'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + authInfoRes(responses) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + let responsesTotalLen = 0; + let responseLens; + + if (responses) { + responseLens = new Array(responses.length); + for (let i = 0; i < responses.length; ++i) { + const len = Buffer.byteLength(responses[i]); + responseLens[i] = len; + responsesTotalLen += 4 + len; + } + } + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + responsesTotalLen); + + packet[p] = MESSAGE.USERAUTH_INFO_RESPONSE; + + if (responses) { + writeUInt32BE(packet, responses.length, ++p); + p += 4; + for (let i = 0; i < responses.length; ++i) { + const len = responseLens[i]; + writeUInt32BE(packet, len, p); + p += 4; + if (len) { + packet.utf8Write(responses[i], p, len); + p += len; + } + } + } else { + writeUInt32BE(packet, 0, ++p); + } + + this._debug && this._debug('Outbound: Sending USERAUTH_INFO_RESPONSE'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + + // 'ssh-connection' service-specific + // --------------------------------- + tcpipForward(bindAddr, bindPort, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const addrLen = Buffer.byteLength(bindAddr); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 13 + 1 + 4 + addrLen + 4); + + packet[p] = MESSAGE.GLOBAL_REQUEST; + + writeUInt32BE(packet, 13, ++p); + packet.utf8Write('tcpip-forward', p += 4, 13); + + packet[p += 13] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, addrLen, ++p); + packet.utf8Write(bindAddr, p += 4, addrLen); + + writeUInt32BE(packet, bindPort, p += addrLen); + + this._debug + && this._debug('Outbound: Sending GLOBAL_REQUEST (tcpip-forward)'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + cancelTcpipForward(bindAddr, bindPort, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const addrLen = Buffer.byteLength(bindAddr); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 20 + 1 + 4 + addrLen + 4); + + packet[p] = MESSAGE.GLOBAL_REQUEST; + + writeUInt32BE(packet, 20, ++p); + packet.utf8Write('cancel-tcpip-forward', p += 4, 20); + + packet[p += 20] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, addrLen, ++p); + packet.utf8Write(bindAddr, p += 4, addrLen); + + writeUInt32BE(packet, bindPort, p += addrLen); + + this._debug + && this._debug('Outbound: Sending GLOBAL_REQUEST (cancel-tcpip-forward)'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_streamLocalForward(socketPath, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const socketPathLen = Buffer.byteLength(socketPath); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 31 + 1 + 4 + socketPathLen + ); + + packet[p] = MESSAGE.GLOBAL_REQUEST; + + writeUInt32BE(packet, 31, ++p); + packet.utf8Write('streamlocal-forward@openssh.com', p += 4, 31); + + packet[p += 31] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, socketPathLen, ++p); + packet.utf8Write(socketPath, p += 4, socketPathLen); + + this._debug && this._debug( + 'Outbound: Sending GLOBAL_REQUEST (streamlocal-forward@openssh.com)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_cancelStreamLocalForward(socketPath, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const socketPathLen = Buffer.byteLength(socketPath); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 38 + 1 + 4 + socketPathLen + ); + + packet[p] = MESSAGE.GLOBAL_REQUEST; + + writeUInt32BE(packet, 38, ++p); + packet.utf8Write('cancel-streamlocal-forward@openssh.com', p += 4, 38); + + packet[p += 38] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, socketPathLen, ++p); + packet.utf8Write(socketPath, p += 4, socketPathLen); + + if (this._debug) { + this._debug( + 'Outbound: Sending GLOBAL_REQUEST ' + + '(cancel-streamlocal-forward@openssh.com)' + ); + } + sendPacket(this, this._packetRW.write.finalize(packet)); + } + directTcpip(chan, initWindow, maxPacket, cfg) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const srcLen = Buffer.byteLength(cfg.srcIP); + const dstLen = Buffer.byteLength(cfg.dstIP); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 12 + 4 + 4 + 4 + 4 + srcLen + 4 + 4 + dstLen + 4 + ); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 12, ++p); + packet.utf8Write('direct-tcpip', p += 4, 12); + + writeUInt32BE(packet, chan, p += 12); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + writeUInt32BE(packet, dstLen, p += 4); + packet.utf8Write(cfg.dstIP, p += 4, dstLen); + + writeUInt32BE(packet, cfg.dstPort, p += dstLen); + + writeUInt32BE(packet, srcLen, p += 4); + packet.utf8Write(cfg.srcIP, p += 4, srcLen); + + writeUInt32BE(packet, cfg.srcPort, p += srcLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_OPEN (r:${chan}, direct-tcpip)` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_directStreamLocal(chan, initWindow, maxPacket, cfg) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + const pathLen = Buffer.byteLength(cfg.socketPath); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 30 + 4 + 4 + 4 + 4 + pathLen + 4 + 4 + ); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 30, ++p); + packet.utf8Write('direct-streamlocal@openssh.com', p += 4, 30); + + writeUInt32BE(packet, chan, p += 30); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + writeUInt32BE(packet, pathLen, p += 4); + packet.utf8Write(cfg.socketPath, p += 4, pathLen); + + // zero-fill reserved fields (string and uint32) + bufferFill(packet, 0, p += pathLen, p + 8); + + if (this._debug) { + this._debug( + 'Outbound: Sending CHANNEL_OPEN ' + + `(r:${chan}, direct-streamlocal@openssh.com)` + ); + } + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_noMoreSessions(wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 28 + 1); + + packet[p] = MESSAGE.GLOBAL_REQUEST; + + writeUInt32BE(packet, 28, ++p); + packet.utf8Write('no-more-sessions@openssh.com', p += 4, 28); + + packet[p += 28] = (wantReply === undefined || wantReply === true ? 1 : 0); + + this._debug && this._debug( + 'Outbound: Sending GLOBAL_REQUEST (no-more-sessions@openssh.com)' + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + session(chan, initWindow, maxPacket) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 7 + 4 + 4 + 4); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 7, ++p); + packet.utf8Write('session', p += 4, 7); + + writeUInt32BE(packet, chan, p += 7); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + this._debug + && this._debug(`Outbound: Sending CHANNEL_OPEN (r:${chan}, session)`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + windowChange(chan, rows, cols, height, width) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 4 + 13 + 1 + 4 + 4 + 4 + 4 + ); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 13, p += 4); + packet.utf8Write('window-change', p += 4, 13); + + packet[p += 13] = 0; + + writeUInt32BE(packet, cols, ++p); + + writeUInt32BE(packet, rows, p += 4); + + writeUInt32BE(packet, width, p += 4); + + writeUInt32BE(packet, height, p += 4); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, window-change)` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + pty(chan, rows, cols, height, width, term, modes, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + if (!term || !term.length) + term = 'vt100'; + if (modes + && !Buffer.isBuffer(modes) + && !Array.isArray(modes) + && typeof modes === 'object' + && modes !== null) { + modes = modesToBytes(modes); + } + if (!modes || !modes.length) + modes = NO_TERMINAL_MODES_BUFFER; + + const termLen = term.length; + const modesLen = modes.length; + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 4 + 7 + 1 + 4 + termLen + 4 + 4 + 4 + 4 + 4 + modesLen + ); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 7, p += 4); + packet.utf8Write('pty-req', p += 4, 7); + + packet[p += 7] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, termLen, ++p); + packet.utf8Write(term, p += 4, termLen); + + writeUInt32BE(packet, cols, p += termLen); + + writeUInt32BE(packet, rows, p += 4); + + writeUInt32BE(packet, width, p += 4); + + writeUInt32BE(packet, height, p += 4); + + writeUInt32BE(packet, modesLen, p += 4); + p += 4; + if (Array.isArray(modes)) { + for (let i = 0; i < modesLen; ++i) + packet[p++] = modes[i]; + } else if (Buffer.isBuffer(modes)) { + packet.set(modes, p); + } + + this._debug + && this._debug(`Outbound: Sending CHANNEL_REQUEST (r:${chan}, pty-req)`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + shell(chan, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 5 + 1); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 5, p += 4); + packet.utf8Write('shell', p += 4, 5); + + packet[p += 5] = (wantReply === undefined || wantReply === true ? 1 : 0); + + this._debug + && this._debug(`Outbound: Sending CHANNEL_REQUEST (r:${chan}, shell)`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + exec(chan, cmd, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + const isBuf = Buffer.isBuffer(cmd); + const cmdLen = (isBuf ? cmd.length : Buffer.byteLength(cmd)); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 4 + 1 + 4 + cmdLen); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 4, p += 4); + packet.utf8Write('exec', p += 4, 4); + + packet[p += 4] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, cmdLen, ++p); + if (isBuf) + packet.set(cmd, p += 4); + else + packet.utf8Write(cmd, p += 4, cmdLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, exec: ${cmd})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + signal(chan, signal) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + const origSignal = signal; + + signal = signal.toUpperCase(); + if (signal.slice(0, 3) === 'SIG') + signal = signal.slice(3); + + if (SIGNALS[signal] !== 1) + throw new Error(`Invalid signal: ${origSignal}`); + + const signalLen = signal.length; + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 4 + 6 + 1 + 4 + signalLen + ); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 6, p += 4); + packet.utf8Write('signal', p += 4, 6); + + packet[p += 6] = 0; + + writeUInt32BE(packet, signalLen, ++p); + packet.utf8Write(signal, p += 4, signalLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, signal: ${signal})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + env(chan, key, val, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + const keyLen = Buffer.byteLength(key); + const isBuf = Buffer.isBuffer(val); + const valLen = (isBuf ? val.length : Buffer.byteLength(val)); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 4 + 3 + 1 + 4 + keyLen + 4 + valLen + ); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 3, p += 4); + packet.utf8Write('env', p += 4, 3); + + packet[p += 3] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, keyLen, ++p); + packet.utf8Write(key, p += 4, keyLen); + + writeUInt32BE(packet, valLen, p += keyLen); + if (isBuf) + packet.set(val, p += 4); + else + packet.utf8Write(val, p += 4, valLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, env: ${key}=${val})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + x11Forward(chan, cfg, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + const protocol = cfg.protocol; + const cookie = cfg.cookie; + const isBufProto = Buffer.isBuffer(protocol); + const protoLen = (isBufProto + ? protocol.length + : Buffer.byteLength(protocol)); + const isBufCookie = Buffer.isBuffer(cookie); + const cookieLen = (isBufCookie + ? cookie.length + : Buffer.byteLength(cookie)); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 4 + 7 + 1 + 1 + 4 + protoLen + 4 + cookieLen + 4 + ); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 7, p += 4); + packet.utf8Write('x11-req', p += 4, 7); + + packet[p += 7] = (wantReply === undefined || wantReply === true ? 1 : 0); + + packet[++p] = (cfg.single ? 1 : 0); + + writeUInt32BE(packet, protoLen, ++p); + if (isBufProto) + packet.set(protocol, p += 4); + else + packet.utf8Write(protocol, p += 4, protoLen); + + writeUInt32BE(packet, cookieLen, p += protoLen); + if (isBufCookie) + packet.set(cookie, p += 4); + else + packet.latin1Write(cookie, p += 4, cookieLen); + + writeUInt32BE(packet, (cfg.screen || 0), p += cookieLen); + + this._debug + && this._debug(`Outbound: Sending CHANNEL_REQUEST (r:${chan}, x11-req)`); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + subsystem(chan, name, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + const nameLen = Buffer.byteLength(name); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 9 + 1 + 4 + nameLen); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 9, p += 4); + packet.utf8Write('subsystem', p += 4, 9); + + packet[p += 9] = (wantReply === undefined || wantReply === true ? 1 : 0); + + writeUInt32BE(packet, nameLen, ++p); + packet.utf8Write(name, p += 4, nameLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, subsystem: ${name})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_agentForward(chan, wantReply) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + // Does not consume window space + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 26 + 1); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 26, p += 4); + packet.utf8Write('auth-agent-req@openssh.com', p += 4, 26); + + packet[p += 26] = (wantReply === undefined || wantReply === true ? 1 : 0); + + if (this._debug) { + this._debug( + 'Outbound: Sending CHANNEL_REQUEST ' + + `(r:${chan}, auth-agent-req@openssh.com)` + ); + } + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_hostKeysProve(keys) { + if (this._server) + throw new Error('Client-only method called in server mode'); + + let keysTotal = 0; + const publicKeys = []; + for (const key of keys) { + const publicKey = key.getPublicSSH(); + keysTotal += 4 + publicKey.length; + publicKeys.push(publicKey); + } + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 29 + 1 + keysTotal); + + packet[p] = MESSAGE.GLOBAL_REQUEST; + + writeUInt32BE(packet, 29, ++p); + packet.utf8Write('hostkeys-prove-00@openssh.com', p += 4, 29); + + packet[p += 29] = 1; // want reply + + ++p; + for (const buf of publicKeys) { + writeUInt32BE(packet, buf.length, p); + bufferCopy(buf, packet, 0, buf.length, p += 4); + p += buf.length; + } + + if (this._debug) { + this._debug( + 'Outbound: Sending GLOBAL_REQUEST (hostkeys-prove-00@openssh.com)' + ); + } + sendPacket(this, this._packetRW.write.finalize(packet)); + } + + // =========================================================================== + // Server-specific =========================================================== + // =========================================================================== + + // Global + // ------ + serviceAccept(svcName) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + const svcNameLen = Buffer.byteLength(svcName); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + svcNameLen); + + packet[p] = MESSAGE.SERVICE_ACCEPT; + + writeUInt32BE(packet, svcNameLen, ++p); + packet.utf8Write(svcName, p += 4, svcNameLen); + + this._debug && this._debug(`Outbound: Sending SERVICE_ACCEPT (${svcName})`); + sendPacket(this, this._packetRW.write.finalize(packet)); + + if (this._server && this._banner && svcName === 'ssh-userauth') { + const banner = this._banner; + this._banner = undefined; // Prevent banner from being displayed again + const bannerLen = Buffer.byteLength(banner); + p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + bannerLen + 4); + + packet[p] = MESSAGE.USERAUTH_BANNER; + + writeUInt32BE(packet, bannerLen, ++p); + packet.utf8Write(banner, p += 4, bannerLen); + + writeUInt32BE(packet, 0, p += bannerLen); // Empty language tag + + this._debug && this._debug('Outbound: Sending USERAUTH_BANNER'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + } + // 'ssh-connection' service-specific + forwardedTcpip(chan, initWindow, maxPacket, cfg) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + const boundAddrLen = Buffer.byteLength(cfg.boundAddr); + const remoteAddrLen = Buffer.byteLength(cfg.remoteAddr); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 15 + 4 + 4 + 4 + 4 + boundAddrLen + 4 + 4 + remoteAddrLen + 4 + ); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 15, ++p); + packet.utf8Write('forwarded-tcpip', p += 4, 15); + + writeUInt32BE(packet, chan, p += 15); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + writeUInt32BE(packet, boundAddrLen, p += 4); + packet.utf8Write(cfg.boundAddr, p += 4, boundAddrLen); + + writeUInt32BE(packet, cfg.boundPort, p += boundAddrLen); + + writeUInt32BE(packet, remoteAddrLen, p += 4); + packet.utf8Write(cfg.remoteAddr, p += 4, remoteAddrLen); + + writeUInt32BE(packet, cfg.remotePort, p += remoteAddrLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_OPEN (r:${chan}, forwarded-tcpip)` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + x11(chan, initWindow, maxPacket, cfg) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + const addrLen = Buffer.byteLength(cfg.originAddr); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 3 + 4 + 4 + 4 + 4 + addrLen + 4 + ); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 3, ++p); + packet.utf8Write('x11', p += 4, 3); + + writeUInt32BE(packet, chan, p += 3); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + writeUInt32BE(packet, addrLen, p += 4); + packet.utf8Write(cfg.originAddr, p += 4, addrLen); + + writeUInt32BE(packet, cfg.originPort, p += addrLen); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_OPEN (r:${chan}, x11)` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_authAgent(chan, initWindow, maxPacket) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 22 + 4 + 4 + 4); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 22, ++p); + packet.utf8Write('auth-agent@openssh.com', p += 4, 22); + + writeUInt32BE(packet, chan, p += 22); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_OPEN (r:${chan}, auth-agent@openssh.com)` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + openssh_forwardedStreamLocal(chan, initWindow, maxPacket, cfg) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + const pathLen = Buffer.byteLength(cfg.socketPath); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 33 + 4 + 4 + 4 + 4 + pathLen + 4 + ); + + packet[p] = MESSAGE.CHANNEL_OPEN; + + writeUInt32BE(packet, 33, ++p); + packet.utf8Write('forwarded-streamlocal@openssh.com', p += 4, 33); + + writeUInt32BE(packet, chan, p += 33); + + writeUInt32BE(packet, initWindow, p += 4); + + writeUInt32BE(packet, maxPacket, p += 4); + + writeUInt32BE(packet, pathLen, p += 4); + packet.utf8Write(cfg.socketPath, p += 4, pathLen); + + writeUInt32BE(packet, 0, p += pathLen); + + if (this._debug) { + this._debug( + 'Outbound: Sending CHANNEL_OPEN ' + + `(r:${chan}, forwarded-streamlocal@openssh.com)` + ); + } + sendPacket(this, this._packetRW.write.finalize(packet)); + } + exitStatus(chan, status) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + // Does not consume window space + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + 4 + 11 + 1 + 4); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 11, p += 4); + packet.utf8Write('exit-status', p += 4, 11); + + packet[p += 11] = 0; + + writeUInt32BE(packet, status, ++p); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, exit-status: ${status})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + exitSignal(chan, name, coreDumped, msg) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + // Does not consume window space + + const origSignal = name; + + if (typeof origSignal !== 'string' || !origSignal) + throw new Error(`Invalid signal: ${origSignal}`); + + let signal = name.toUpperCase(); + if (signal.slice(0, 3) === 'SIG') + signal = signal.slice(3); + + if (SIGNALS[signal] !== 1) + throw new Error(`Invalid signal: ${origSignal}`); + + const nameLen = Buffer.byteLength(signal); + const msgLen = (msg ? Buffer.byteLength(msg) : 0); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + 4 + 11 + 1 + 4 + nameLen + 1 + 4 + msgLen + 4 + ); + + packet[p] = MESSAGE.CHANNEL_REQUEST; + + writeUInt32BE(packet, chan, ++p); + + writeUInt32BE(packet, 11, p += 4); + packet.utf8Write('exit-signal', p += 4, 11); + + packet[p += 11] = 0; + + writeUInt32BE(packet, nameLen, ++p); + packet.utf8Write(signal, p += 4, nameLen); + + packet[p += nameLen] = (coreDumped ? 1 : 0); + + writeUInt32BE(packet, msgLen, ++p); + + p += 4; + if (msgLen) { + packet.utf8Write(msg, p, msgLen); + p += msgLen; + } + + writeUInt32BE(packet, 0, p); + + this._debug && this._debug( + `Outbound: Sending CHANNEL_REQUEST (r:${chan}, exit-signal: ${name})` + ); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + // 'ssh-userauth' service-specific + authFailure(authMethods, isPartial) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + if (this._authsQueue.length === 0) + throw new Error('No auth in progress'); + + let methods; + + if (typeof authMethods === 'boolean') { + isPartial = authMethods; + authMethods = undefined; + } + + if (authMethods) { + methods = []; + for (let i = 0; i < authMethods.length; ++i) { + if (authMethods[i].toLowerCase() === 'none') + continue; + methods.push(authMethods[i]); + } + methods = methods.join(','); + } else { + methods = ''; + } + + const methodsLen = methods.length; + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + methodsLen + 1); + + packet[p] = MESSAGE.USERAUTH_FAILURE; + + writeUInt32BE(packet, methodsLen, ++p); + packet.utf8Write(methods, p += 4, methodsLen); + + packet[p += methodsLen] = (isPartial === true ? 1 : 0); + + this._authsQueue.shift(); + + this._debug && this._debug('Outbound: Sending USERAUTH_FAILURE'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + authSuccess() { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + if (this._authsQueue.length === 0) + throw new Error('No auth in progress'); + + const p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1); + + packet[p] = MESSAGE.USERAUTH_SUCCESS; + + this._authsQueue.shift(); + this._authenticated = true; + + this._debug && this._debug('Outbound: Sending USERAUTH_SUCCESS'); + sendPacket(this, this._packetRW.write.finalize(packet)); + + if (this._kex.negotiated.cs.compress === 'zlib@openssh.com') + this._packetRW.read = new ZlibPacketReader(); + if (this._kex.negotiated.sc.compress === 'zlib@openssh.com') + this._packetRW.write = new ZlibPacketWriter(this); + } + authPKOK(keyAlgo, key) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + if (this._authsQueue.length === 0 || this._authsQueue[0] !== 'publickey') + throw new Error('"publickey" auth not in progress'); + + // TODO: support parsed key for `key` + + const keyAlgoLen = Buffer.byteLength(keyAlgo); + const keyLen = key.length; + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + keyAlgoLen + 4 + keyLen); + + packet[p] = MESSAGE.USERAUTH_PK_OK; + + writeUInt32BE(packet, keyAlgoLen, ++p); + packet.utf8Write(keyAlgo, p += 4, keyAlgoLen); + + writeUInt32BE(packet, keyLen, p += keyAlgoLen); + packet.set(key, p += 4); + + this._authsQueue.shift(); + + this._debug && this._debug('Outbound: Sending USERAUTH_PK_OK'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + authPasswdChg(prompt) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + const promptLen = Buffer.byteLength(prompt); + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc(1 + 4 + promptLen + 4); + + packet[p] = MESSAGE.USERAUTH_PASSWD_CHANGEREQ; + + writeUInt32BE(packet, promptLen, ++p); + packet.utf8Write(prompt, p += 4, promptLen); + + writeUInt32BE(packet, 0, p += promptLen); // Empty language tag + + this._debug && this._debug('Outbound: Sending USERAUTH_PASSWD_CHANGEREQ'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } + authInfoReq(name, instructions, prompts) { + if (!this._server) + throw new Error('Server-only method called in client mode'); + + let promptsLen = 0; + const nameLen = name ? Buffer.byteLength(name) : 0; + const instrLen = instructions ? Buffer.byteLength(instructions) : 0; + + for (let i = 0; i < prompts.length; ++i) + promptsLen += 4 + Buffer.byteLength(prompts[i].prompt) + 1; + + let p = this._packetRW.write.allocStart; + const packet = this._packetRW.write.alloc( + 1 + 4 + nameLen + 4 + instrLen + 4 + 4 + promptsLen + ); + + packet[p] = MESSAGE.USERAUTH_INFO_REQUEST; + + writeUInt32BE(packet, nameLen, ++p); + p += 4; + if (name) { + packet.utf8Write(name, p, nameLen); + p += nameLen; + } + + writeUInt32BE(packet, instrLen, p); + p += 4; + if (instructions) { + packet.utf8Write(instructions, p, instrLen); + p += instrLen; + } + + writeUInt32BE(packet, 0, p); + + writeUInt32BE(packet, prompts.length, p += 4); + p += 4; + for (let i = 0; i < prompts.length; ++i) { + const prompt = prompts[i]; + const promptLen = Buffer.byteLength(prompt.prompt); + + writeUInt32BE(packet, promptLen, p); + p += 4; + if (promptLen) { + packet.utf8Write(prompt.prompt, p, promptLen); + p += promptLen; + } + packet[p++] = (prompt.echo ? 1 : 0); + } + + this._debug && this._debug('Outbound: Sending USERAUTH_INFO_REQUEST'); + sendPacket(this, this._packetRW.write.finalize(packet)); + } +} + +// SSH-protoversion-softwareversion (SP comments) CR LF +const RE_IDENT = /^SSH-(2\.0|1\.99)-([^ ]+)(?: (.*))?$/; + +// TODO: optimize this by starting n bytes from the end of this._buffer instead +// of the beginning +function parseHeader(chunk, p, len) { + let data; + let chunkOffset; + if (this._buffer) { + data = Buffer.allocUnsafe(this._buffer.length + (len - p)); + data.set(this._buffer, 0); + if (p === 0) { + data.set(chunk, this._buffer.length); + } else { + data.set(new Uint8Array(chunk.buffer, + chunk.byteOffset + p, + (len - p)), + this._buffer.length); + } + chunkOffset = this._buffer.length; + p = 0; + } else { + data = chunk; + chunkOffset = 0; + } + const op = p; + let start = p; + let end = p; + let needNL = false; + let lineLen = 0; + let lines = 0; + for (; p < data.length; ++p) { + const ch = data[p]; + + if (ch === 13 /* '\r' */) { + needNL = true; + continue; + } + + if (ch === 10 /* '\n' */) { + if (end > start + && end - start > 4 + && data[start] === 83 /* 'S' */ + && data[start + 1] === 83 /* 'S' */ + && data[start + 2] === 72 /* 'H' */ + && data[start + 3] === 45 /* '-' */) { + + const full = data.latin1Slice(op, end + 1); + const identRaw = (start === op ? full : full.slice(start - op)); + const m = RE_IDENT.exec(identRaw); + if (!m) + throw new Error('Invalid identification string'); + + const header = { + greeting: (start === op ? '' : full.slice(0, start - op)), + identRaw, + versions: { + protocol: m[1], + software: m[2], + }, + comments: m[3] + }; + + // Needed during handshake + this._remoteIdentRaw = Buffer.from(identRaw); + + this._debug && this._debug(`Remote ident: ${inspect(identRaw)}`); + this._compatFlags = getCompatFlags(header); + + this._buffer = undefined; + this._decipher = + new NullDecipher(0, onKEXPayload.bind(this, { firstPacket: true })); + this._parse = parsePacket; + + this._onHeader(header); + if (!this._destruct) { + // We disconnected inside _onHeader + return len; + } + + kexinit(this); + + return p + 1 - chunkOffset; + } + + // Only allow pre-ident greetings when we're a client + if (this._server) + throw new Error('Greetings from clients not permitted'); + + if (++lines > MAX_LINES) + throw new Error('Max greeting lines exceeded'); + + needNL = false; + start = p + 1; + lineLen = 0; + } else if (needNL) { + throw new Error('Invalid header: expected newline'); + } else if (++lineLen >= MAX_LINE_LEN) { + throw new Error('Header line too long'); + } + + end = p; + } + if (!this._buffer) + this._buffer = bufferSlice(data, op); + + return p - chunkOffset; +} + +function parsePacket(chunk, p, len) { + return this._decipher.decrypt(chunk, p, len); +} + +function onPayload(payload) { + // XXX: move this to the Decipher implementations? + + this._onPacket(); + + if (payload.length === 0) { + this._debug && this._debug('Inbound: Skipping empty packet payload'); + return; + } + + payload = this._packetRW.read.read(payload); + + const type = payload[0]; + if (type === MESSAGE.USERAUTH_SUCCESS + && !this._server + && !this._authenticated) { + this._authenticated = true; + if (this._kex.negotiated.cs.compress === 'zlib@openssh.com') + this._packetRW.write = new ZlibPacketWriter(this); + if (this._kex.negotiated.sc.compress === 'zlib@openssh.com') + this._packetRW.read = new ZlibPacketReader(); + } + const handler = MESSAGE_HANDLERS[type]; + if (handler === undefined) { + this._debug && this._debug(`Inbound: Unsupported message type: ${type}`); + return; + } + + return handler(this, payload); +} + +function getCompatFlags(header) { + const software = header.versions.software; + + let flags = 0; + + for (const rule of COMPAT_CHECKS) { + if (typeof rule[0] === 'string') { + if (software === rule[0]) + flags |= rule[1]; + } else if (rule[0].test(software)) { + flags |= rule[1]; + } + } + + return flags; +} + +function modesToBytes(modes) { + const keys = Object.keys(modes); + const bytes = Buffer.allocUnsafe((5 * keys.length) + 1); + let b = 0; + + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (key === 'TTY_OP_END') + continue; + + const opcode = TERMINAL_MODE[key]; + if (opcode === undefined) + continue; + + const val = modes[key]; + if (typeof val === 'number' && isFinite(val)) { + bytes[b++] = opcode; + bytes[b++] = val >>> 24; + bytes[b++] = val >>> 16; + bytes[b++] = val >>> 8; + bytes[b++] = val; + } + } + + bytes[b++] = TERMINAL_MODE.TTY_OP_END; + + if (b < bytes.length) + return bufferSlice(bytes, 0, b); + + return bytes; +} + +module.exports = Protocol; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/SFTP.js b/reverse_engineering/node_modules/ssh2/lib/protocol/SFTP.js new file mode 100644 index 0000000..b10d9e5 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/SFTP.js @@ -0,0 +1,3778 @@ +'use strict'; + +const EventEmitter = require('events'); +const fs = require('fs'); +const { constants } = fs; +const { + Readable: ReadableStream, + Writable: WritableStream +} = require('stream'); +const { inherits, isDate } = require('util'); + +const FastBuffer = Buffer[Symbol.species]; + +const { + bufferCopy, + bufferSlice, + makeBufferParser, + writeUInt32BE, +} = require('./utils.js'); + +const ATTR = { + SIZE: 0x00000001, + UIDGID: 0x00000002, + PERMISSIONS: 0x00000004, + ACMODTIME: 0x00000008, + EXTENDED: 0x80000000, +}; + +// Large enough to store all possible attributes +const ATTRS_BUF = Buffer.alloc(28); + +const STATUS_CODE = { + OK: 0, + EOF: 1, + NO_SUCH_FILE: 2, + PERMISSION_DENIED: 3, + FAILURE: 4, + BAD_MESSAGE: 5, + NO_CONNECTION: 6, + CONNECTION_LOST: 7, + OP_UNSUPPORTED: 8 +}; + +const VALID_STATUS_CODES = new Map( + Object.values(STATUS_CODE).map((n) => [n, 1]) +); + +const STATUS_CODE_STR = { + [STATUS_CODE.OK]: 'No error', + [STATUS_CODE.EOF]: 'End of file', + [STATUS_CODE.NO_SUCH_FILE]: 'No such file or directory', + [STATUS_CODE.PERMISSION_DENIED]: 'Permission denied', + [STATUS_CODE.FAILURE]: 'Failure', + [STATUS_CODE.BAD_MESSAGE]: 'Bad message', + [STATUS_CODE.NO_CONNECTION]: 'No connection', + [STATUS_CODE.CONNECTION_LOST]: 'Connection lost', + [STATUS_CODE.OP_UNSUPPORTED]: 'Operation unsupported', +}; + +const REQUEST = { + INIT: 1, + OPEN: 3, + CLOSE: 4, + READ: 5, + WRITE: 6, + LSTAT: 7, + FSTAT: 8, + SETSTAT: 9, + FSETSTAT: 10, + OPENDIR: 11, + READDIR: 12, + REMOVE: 13, + MKDIR: 14, + RMDIR: 15, + REALPATH: 16, + STAT: 17, + RENAME: 18, + READLINK: 19, + SYMLINK: 20, + EXTENDED: 200 +}; + +const RESPONSE = { + VERSION: 2, + STATUS: 101, + HANDLE: 102, + DATA: 103, + NAME: 104, + ATTRS: 105, + EXTENDED: 201 +}; + +const OPEN_MODE = { + READ: 0x00000001, + WRITE: 0x00000002, + APPEND: 0x00000004, + CREAT: 0x00000008, + TRUNC: 0x00000010, + EXCL: 0x00000020 +}; + +const PKT_RW_OVERHEAD = 2 * 1024; +const MAX_REQID = 2 ** 32 - 1; +const CLIENT_VERSION_BUFFER = Buffer.from([ + 0, 0, 0, 5 /* length */, + REQUEST.INIT, + 0, 0, 0, 3 /* version */ +]); +const SERVER_VERSION_BUFFER = Buffer.from([ + 0, 0, 0, 5 /* length */, + RESPONSE.VERSION, + 0, 0, 0, 3 /* version */ +]); + +const RE_OPENSSH = /^SSH-2.0-(?:OpenSSH|dropbear)/; +const OPENSSH_MAX_PKT_LEN = 256 * 1024; + +const bufferParser = makeBufferParser(); + +const fakeStderr = { + readable: false, + writable: false, + push: (data) => {}, + once: () => {}, + on: () => {}, + emit: () => {}, + end: () => {}, +}; + +function noop() {} + +// Emulates enough of `Channel` to be able to be used as a drop-in replacement +// in order to process incoming data with as little overhead as possible +class SFTP extends EventEmitter { + constructor(client, chanInfo, cfg) { + super(); + + if (typeof cfg !== 'object' || !cfg) + cfg = {}; + + const remoteIdentRaw = client._protocol._remoteIdentRaw; + + this.server = !!cfg.server; + this._debug = (typeof cfg.debug === 'function' ? cfg.debug : undefined); + this._isOpenSSH = (remoteIdentRaw && RE_OPENSSH.test(remoteIdentRaw)); + + this._version = -1; + this._extensions = {}; + this._biOpt = cfg.biOpt; + this._pktLenBytes = 0; + this._pktLen = 0; + this._pktPos = 0; + this._pktType = 0; + this._pktData = undefined; + this._writeReqid = -1; + this._requests = {}; + this._maxInPktLen = OPENSSH_MAX_PKT_LEN; + this._maxOutPktLen = 34000; + this._maxReadLen = + (this._isOpenSSH ? OPENSSH_MAX_PKT_LEN : 34000) - PKT_RW_OVERHEAD; + this._maxWriteLen = + (this._isOpenSSH ? OPENSSH_MAX_PKT_LEN : 34000) - PKT_RW_OVERHEAD; + + this.maxOpenHandles = undefined; + + // Channel compatibility + this._client = client; + this._protocol = client._protocol; + this._callbacks = []; + this._hasX11 = false; + this._exit = { + code: undefined, + signal: undefined, + dump: undefined, + desc: undefined, + }; + this._waitWindow = false; // SSH-level backpressure + this._chunkcb = undefined; + this._buffer = []; + this.type = chanInfo.type; + this.subtype = undefined; + this.incoming = chanInfo.incoming; + this.outgoing = chanInfo.outgoing; + this.stderr = fakeStderr; + this.readable = true; + } + + // This handles incoming data to parse + push(data) { + if (data === null) { + cleanupRequests(this); + if (!this.readable) + return; + // No more incoming data from the remote side + this.readable = false; + this.emit('end'); + return; + } + /* + uint32 length + byte type + byte[length - 1] data payload + */ + let p = 0; + + while (p < data.length) { + if (this._pktLenBytes < 4) { + let nb = Math.min(4 - this._pktLenBytes, data.length - p); + this._pktLenBytes += nb; + + while (nb--) + this._pktLen = (this._pktLen << 8) + data[p++]; + + if (this._pktLenBytes < 4) + return; + if (this._pktLen === 0) + return doFatalSFTPError(this, 'Invalid packet length'); + if (this._pktLen > this._maxInPktLen) { + const max = this._maxInPktLen; + return doFatalSFTPError( + this, + `Packet length ${this._pktLen} exceeds max length of ${max}` + ); + } + if (p >= data.length) + return; + } + if (this._pktPos < this._pktLen) { + const nb = Math.min(this._pktLen - this._pktPos, data.length - p); + if (p !== 0 || nb !== data.length) { + if (nb === this._pktLen) { + this._pkt = new FastBuffer(data.buffer, data.byteOffset + p, nb); + } else { + if (!this._pkt) + this._pkt = Buffer.allocUnsafe(this._pktLen); + this._pkt.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._pktPos + ); + } + } else if (nb === this._pktLen) { + this._pkt = data; + } else { + if (!this._pkt) + this._pkt = Buffer.allocUnsafe(this._pktLen); + this._pkt.set(data, this._pktPos); + } + p += nb; + this._pktPos += nb; + if (this._pktPos < this._pktLen) + return; + } + + const type = this._pkt[0]; + const payload = this._pkt; + + // Prepare for next packet + this._pktLen = 0; + this._pktLenBytes = 0; + this._pkt = undefined; + this._pktPos = 0; + + const handler = (this.server + ? SERVER_HANDLERS[type] + : CLIENT_HANDLERS[type]); + if (!handler) + return doFatalSFTPError(this, `Unknown packet type ${type}`); + + if (this._version === -1) { + if (this.server) { + if (type !== REQUEST.INIT) + return doFatalSFTPError(this, `Expected INIT packet, got ${type}`); + } else if (type !== RESPONSE.VERSION) { + return doFatalSFTPError(this, `Expected VERSION packet, got ${type}`); + } + } + + if (handler(this, payload) === false) + return; + } + } + + end() { + this.destroy(); + } + destroy() { + if (this.outgoing.state === 'open' || this.outgoing.state === 'eof') { + this.outgoing.state = 'closing'; + this._protocol.channelClose(this.outgoing.id); + } + } + _init() { + this._init = noop; + if (!this.server) + sendOrBuffer(this, CLIENT_VERSION_BUFFER); + } + + // =========================================================================== + // Client-specific =========================================================== + // =========================================================================== + createReadStream(path, options) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + return new ReadStream(this, path, options); + } + createWriteStream(path, options) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + return new WriteStream(this, path, options); + } + open(path, flags_, attrs, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (typeof attrs === 'function') { + cb = attrs; + attrs = undefined; + } + + const flags = (typeof flags_ === 'number' ? flags_ : stringToFlags(flags_)); + if (flags === null) + throw new Error(`Unknown flags string: ${flags_}`); + + let attrsFlags = 0; + let attrsLen = 0; + if (typeof attrs === 'string' || typeof attrs === 'number') + attrs = { mode: attrs }; + if (typeof attrs === 'object' && attrs !== null) { + attrs = attrsToBytes(attrs); + attrsFlags = attrs.flags; + attrsLen = attrs.nb; + } + + /* + uint32 id + string filename + uint32 pflags + ATTRS attrs + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen + 4 + 4 + attrsLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.OPEN; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + writeUInt32BE(buf, flags, p += pathLen); + writeUInt32BE(buf, attrsFlags, p += 4); + if (attrsLen) { + p += 4; + + if (attrsLen === ATTRS_BUF.length) + buf.set(ATTRS_BUF, p); + else + bufferCopy(ATTRS_BUF, buf, 0, attrsLen, p); + + p += attrsLen; + } + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} OPEN` + ); + } + close(handle, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + + /* + uint32 id + string handle + */ + const handleLen = handle.length; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.CLOSE; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, handleLen, p); + buf.set(handle, p += 4); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} CLOSE` + ); + } + read(handle, buf, off, len, position, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + if (!Buffer.isBuffer(buf)) + throw new Error('buffer is not a Buffer'); + if (off >= buf.length) + throw new Error('offset is out of bounds'); + if (off + len > buf.length) + throw new Error('length extends beyond buffer'); + if (position === null) + throw new Error('null position currently unsupported'); + + read_(this, handle, buf, off, len, position, cb); + } + readData(handle, buf, off, len, position, cb) { + // Backwards compatibility + this.read(handle, buf, off, len, position, cb); + } + write(handle, buf, off, len, position, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + if (!Buffer.isBuffer(buf)) + throw new Error('buffer is not a Buffer'); + if (off > buf.length) + throw new Error('offset is out of bounds'); + if (off + len > buf.length) + throw new Error('length extends beyond buffer'); + if (position === null) + throw new Error('null position currently unsupported'); + + if (!len) { + cb && process.nextTick(cb, undefined, 0); + return; + } + + const maxDataLen = this._maxWriteLen; + const overflow = Math.max(len - maxDataLen, 0); + const origPosition = position; + + if (overflow) + len = maxDataLen; + + /* + uint32 id + string handle + uint64 offset + string data + */ + const handleLen = handle.length; + let p = 9; + const out = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen + 8 + 4 + len); + + writeUInt32BE(out, out.length - 4, 0); + out[4] = REQUEST.WRITE; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(out, reqid, 5); + + writeUInt32BE(out, handleLen, p); + out.set(handle, p += 4); + p += handleLen; + for (let i = 7; i >= 0; --i) { + out[p + i] = position & 0xFF; + position /= 256; + } + writeUInt32BE(out, len, p += 8); + bufferCopy(buf, out, off, off + len, p += 4); + + this._requests[reqid] = { + cb: (err) => { + if (err) { + if (typeof cb === 'function') + cb(err); + } else if (overflow) { + this.write(handle, + buf, + off + len, + overflow, + origPosition + len, + cb); + } else if (typeof cb === 'function') { + cb(undefined, off + len); + } + } + }; + + const isSent = sendOrBuffer(this, out); + if (this._debug) { + const how = (isSent ? 'Sent' : 'Buffered'); + this._debug(`SFTP: Outbound: ${how} WRITE (id:${reqid})`); + } + } + writeData(handle, buf, off, len, position, cb) { + // Backwards compatibility + this.write(handle, buf, off, len, position, cb); + } + fastGet(remotePath, localPath, opts, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + fastXfer(this, fs, remotePath, localPath, opts, cb); + } + fastPut(localPath, remotePath, opts, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + fastXfer(fs, this, localPath, remotePath, opts, cb); + } + readFile(path, options, callback_) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + let callback; + if (typeof callback_ === 'function') { + callback = callback_; + } else if (typeof options === 'function') { + callback = options; + options = undefined; + } + + if (typeof options === 'string') + options = { encoding: options, flag: 'r' }; + else if (!options) + options = { encoding: null, flag: 'r' }; + else if (typeof options !== 'object') + throw new TypeError('Bad arguments'); + + const encoding = options.encoding; + if (encoding && !Buffer.isEncoding(encoding)) + throw new Error(`Unknown encoding: ${encoding}`); + + // First stat the file, so we know the size. + let size; + let buffer; // Single buffer with file data + let buffers; // List for when size is unknown + let pos = 0; + let handle; + + // SFTPv3 does not support using -1 for read position, so we have to track + // read position manually + let bytesRead = 0; + + const flag = options.flag || 'r'; + + const read = () => { + if (size === 0) { + buffer = Buffer.allocUnsafe(8192); + this.read(handle, buffer, 0, 8192, bytesRead, afterRead); + } else { + this.read(handle, buffer, pos, size - pos, bytesRead, afterRead); + } + }; + + const afterRead = (er, nbytes) => { + let eof; + if (er) { + eof = (er.code === STATUS_CODE.EOF); + if (!eof) { + return this.close(handle, () => { + return callback && callback(er); + }); + } + } else { + eof = false; + } + + if (eof || (size === 0 && nbytes === 0)) + return close(); + + bytesRead += nbytes; + pos += nbytes; + if (size !== 0) { + if (pos === size) + close(); + else + read(); + } else { + // Unknown size, just read until we don't get bytes. + buffers.push(bufferSlice(buffer, 0, nbytes)); + read(); + } + }; + afterRead._wantEOFError = true; + + const close = () => { + this.close(handle, (er) => { + if (size === 0) { + // Collect the data into the buffers list. + buffer = Buffer.concat(buffers, pos); + } else if (pos < size) { + buffer = bufferSlice(buffer, 0, pos); + } + + if (encoding) + buffer = buffer.toString(encoding); + return callback && callback(er, buffer); + }); + }; + + this.open(path, flag, 0o666, (er, handle_) => { + if (er) + return callback && callback(er); + handle = handle_; + + const tryStat = (er, st) => { + if (er) { + // Try stat() for sftp servers that may not support fstat() for + // whatever reason + this.stat(path, (er_, st_) => { + if (er_) { + return this.close(handle, () => { + callback && callback(er); + }); + } + tryStat(null, st_); + }); + return; + } + + size = st.size || 0; + if (size === 0) { + // The kernel lies about many files. + // Go ahead and try to read some bytes. + buffers = []; + return read(); + } + + buffer = Buffer.allocUnsafe(size); + read(); + }; + this.fstat(handle, tryStat); + }); + } + writeFile(path, data, options, callback_) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + let callback; + if (typeof callback_ === 'function') { + callback = callback_; + } else if (typeof options === 'function') { + callback = options; + options = undefined; + } + + if (typeof options === 'string') + options = { encoding: options, mode: 0o666, flag: 'w' }; + else if (!options) + options = { encoding: 'utf8', mode: 0o666, flag: 'w' }; + else if (typeof options !== 'object') + throw new TypeError('Bad arguments'); + + if (options.encoding && !Buffer.isEncoding(options.encoding)) + throw new Error(`Unknown encoding: ${options.encoding}`); + + const flag = options.flag || 'w'; + this.open(path, flag, options.mode, (openErr, handle) => { + if (openErr) { + callback && callback(openErr); + } else { + const buffer = (Buffer.isBuffer(data) + ? data + : Buffer.from('' + data, options.encoding || 'utf8')); + const position = (/a/.test(flag) ? null : 0); + + // SFTPv3 does not support the notion of 'current position' + // (null position), so we just attempt to append to the end of the file + // instead + if (position === null) { + const tryStat = (er, st) => { + if (er) { + // Try stat() for sftp servers that may not support fstat() for + // whatever reason + this.stat(path, (er_, st_) => { + if (er_) { + return this.close(handle, () => { + callback && callback(er); + }); + } + tryStat(null, st_); + }); + return; + } + writeAll(this, handle, buffer, 0, buffer.length, st.size, callback); + }; + this.fstat(handle, tryStat); + return; + } + writeAll(this, handle, buffer, 0, buffer.length, position, callback); + } + }); + } + appendFile(path, data, options, callback_) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + let callback; + if (typeof callback_ === 'function') { + callback = callback_; + } else if (typeof options === 'function') { + callback = options; + options = undefined; + } + + if (typeof options === 'string') + options = { encoding: options, mode: 0o666, flag: 'a' }; + else if (!options) + options = { encoding: 'utf8', mode: 0o666, flag: 'a' }; + else if (typeof options !== 'object') + throw new TypeError('Bad arguments'); + + if (!options.flag) + options = Object.assign({ flag: 'a' }, options); + this.writeFile(path, data, options, callback); + } + exists(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + this.stat(path, (err) => { + cb && cb(err ? false : true); + }); + } + unlink(filename, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string filename + */ + const fnameLen = Buffer.byteLength(filename); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + fnameLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.REMOVE; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, fnameLen, p); + buf.utf8Write(filename, p += 4, fnameLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} REMOVE` + ); + } + rename(oldPath, newPath, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string oldpath + string newpath + */ + const oldLen = Buffer.byteLength(oldPath); + const newLen = Buffer.byteLength(newPath); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + oldLen + 4 + newLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.RENAME; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, oldLen, p); + buf.utf8Write(oldPath, p += 4, oldLen); + writeUInt32BE(buf, newLen, p += oldLen); + buf.utf8Write(newPath, p += 4, newLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} RENAME` + ); + } + mkdir(path, attrs, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + let flags = 0; + let attrsLen = 0; + + if (typeof attrs === 'function') { + cb = attrs; + attrs = undefined; + } + if (typeof attrs === 'object' && attrs !== null) { + attrs = attrsToBytes(attrs); + flags = attrs.flags; + attrsLen = attrs.nb; + } + + /* + uint32 id + string path + ATTRS attrs + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen + 4 + attrsLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.MKDIR; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + writeUInt32BE(buf, flags, p += pathLen); + if (attrsLen) { + p += 4; + + if (attrsLen === ATTRS_BUF.length) + buf.set(ATTRS_BUF, p); + else + bufferCopy(ATTRS_BUF, buf, 0, attrsLen, p); + + p += attrsLen; + } + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} MKDIR` + ); + } + rmdir(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.RMDIR; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} RMDIR` + ); + } + readdir(where, opts, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + if (typeof opts !== 'object' || opts === null) + opts = {}; + + const doFilter = (opts && opts.full ? false : true); + + if (!Buffer.isBuffer(where) && typeof where !== 'string') + throw new Error('missing directory handle or path'); + + if (typeof where === 'string') { + const entries = []; + let e = 0; + + const reread = (err, handle) => { + if (err) + return cb(err); + + this.readdir(handle, opts, (err, list) => { + const eof = (err && err.code === STATUS_CODE.EOF); + + if (err && !eof) + return this.close(handle, () => cb(err)); + + if (eof) { + return this.close(handle, (err) => { + if (err) + return cb(err); + cb(undefined, entries); + }); + } + + for (let i = 0; i < list.length; ++i, ++e) + entries[e] = list[i]; + + reread(undefined, handle); + }); + }; + return this.opendir(where, reread); + } + + /* + uint32 id + string handle + */ + const handleLen = where.length; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.READDIR; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, handleLen, p); + buf.set(where, p += 4); + + this._requests[reqid] = { + cb: (doFilter + ? (err, list) => { + if (typeof cb !== 'function') + return; + if (err) + return cb(err); + + for (let i = list.length - 1; i >= 0; --i) { + if (list[i].filename === '.' || list[i].filename === '..') + list.splice(i, 1); + } + + cb(undefined, list); + } + : cb) + }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} READDIR` + ); + } + fstat(handle, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + + /* + uint32 id + string handle + */ + const handleLen = handle.length; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.FSTAT; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, handleLen, p); + buf.set(handle, p += 4); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} FSTAT` + ); + } + stat(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.STAT; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} STAT` + ); + } + lstat(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.LSTAT; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} LSTAT` + ); + } + opendir(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.OPENDIR; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} OPENDIR` + ); + } + setstat(path, attrs, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + let flags = 0; + let attrsLen = 0; + + if (typeof attrs === 'object' && attrs !== null) { + attrs = attrsToBytes(attrs); + flags = attrs.flags; + attrsLen = attrs.nb; + } else if (typeof attrs === 'function') { + cb = attrs; + } + + /* + uint32 id + string path + ATTRS attrs + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen + 4 + attrsLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.SETSTAT; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + writeUInt32BE(buf, flags, p += pathLen); + if (attrsLen) { + p += 4; + + if (attrsLen === ATTRS_BUF.length) + buf.set(ATTRS_BUF, p); + else + bufferCopy(ATTRS_BUF, buf, 0, attrsLen, p); + + p += attrsLen; + } + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} SETSTAT` + ); + } + fsetstat(handle, attrs, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + + let flags = 0; + let attrsLen = 0; + + if (typeof attrs === 'object' && attrs !== null) { + attrs = attrsToBytes(attrs); + flags = attrs.flags; + attrsLen = attrs.nb; + } else if (typeof attrs === 'function') { + cb = attrs; + } + + /* + uint32 id + string handle + ATTRS attrs + */ + const handleLen = handle.length; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen + 4 + attrsLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.FSETSTAT; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, handleLen, p); + buf.set(handle, p += 4); + writeUInt32BE(buf, flags, p += handleLen); + if (attrsLen) { + p += 4; + + if (attrsLen === ATTRS_BUF.length) + buf.set(ATTRS_BUF, p); + else + bufferCopy(ATTRS_BUF, buf, 0, attrsLen, p); + + p += attrsLen; + } + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} FSETSTAT` + ); + } + futimes(handle, atime, mtime, cb) { + return this.fsetstat(handle, { + atime: toUnixTimestamp(atime), + mtime: toUnixTimestamp(mtime) + }, cb); + } + utimes(path, atime, mtime, cb) { + return this.setstat(path, { + atime: toUnixTimestamp(atime), + mtime: toUnixTimestamp(mtime) + }, cb); + } + fchown(handle, uid, gid, cb) { + return this.fsetstat(handle, { + uid: uid, + gid: gid + }, cb); + } + chown(path, uid, gid, cb) { + return this.setstat(path, { + uid: uid, + gid: gid + }, cb); + } + fchmod(handle, mode, cb) { + return this.fsetstat(handle, { + mode: mode + }, cb); + } + chmod(path, mode, cb) { + return this.setstat(path, { + mode: mode + }, cb); + } + readlink(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.READLINK; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { + cb: (err, names) => { + if (typeof cb !== 'function') + return; + if (err) + return cb(err); + if (!names || !names.length) + return cb(new Error('Response missing link info')); + cb(undefined, names[0].filename); + } + }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} READLINK` + ); + } + symlink(targetPath, linkPath, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string linkpath + string targetpath + */ + const linkLen = Buffer.byteLength(linkPath); + const targetLen = Buffer.byteLength(targetPath); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + linkLen + 4 + targetLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.SYMLINK; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + if (this._isOpenSSH) { + // OpenSSH has linkpath and targetpath positions switched + writeUInt32BE(buf, targetLen, p); + buf.utf8Write(targetPath, p += 4, targetLen); + writeUInt32BE(buf, linkLen, p += targetLen); + buf.utf8Write(linkPath, p += 4, linkLen); + } else { + writeUInt32BE(buf, linkLen, p); + buf.utf8Write(linkPath, p += 4, linkLen); + writeUInt32BE(buf, targetLen, p += linkLen); + buf.utf8Write(targetPath, p += 4, targetLen); + } + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} SYMLINK` + ); + } + realpath(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + /* + uint32 id + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.REALPATH; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, pathLen, p); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { + cb: (err, names) => { + if (typeof cb !== 'function') + return; + if (err) + return cb(err); + if (!names || !names.length) + return cb(new Error('Response missing path info')); + cb(undefined, names[0].filename); + } + }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} REALPATH` + ); + } + // extended requests + ext_openssh_rename(oldPath, newPath, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['posix-rename@openssh.com']; + if (!ext || ext !== '1') + throw new Error('Server does not support this extended request'); + + /* + uint32 id + string "posix-rename@openssh.com" + string oldpath + string newpath + */ + const oldLen = Buffer.byteLength(oldPath); + const newLen = Buffer.byteLength(newPath); + let p = 9; + const buf = + Buffer.allocUnsafe(4 + 1 + 4 + 4 + 24 + 4 + oldLen + 4 + newLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 24, p); + buf.utf8Write('posix-rename@openssh.com', p += 4, 24); + writeUInt32BE(buf, oldLen, p += 24); + buf.utf8Write(oldPath, p += 4, oldLen); + writeUInt32BE(buf, newLen, p += oldLen); + buf.utf8Write(newPath, p += 4, newLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + if (this._debug) { + const which = (isBuffered ? 'Buffered' : 'Sending'); + this._debug(`SFTP: Outbound: ${which} posix-rename@openssh.com`); + } + } + ext_openssh_statvfs(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['statvfs@openssh.com']; + if (!ext || ext !== '2') + throw new Error('Server does not support this extended request'); + + /* + uint32 id + string "statvfs@openssh.com" + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + 19 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 19, p); + buf.utf8Write('statvfs@openssh.com', p += 4, 19); + writeUInt32BE(buf, pathLen, p += 19); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { extended: 'statvfs@openssh.com', cb }; + + const isBuffered = sendOrBuffer(this, buf); + if (this._debug) { + const which = (isBuffered ? 'Buffered' : 'Sending'); + this._debug(`SFTP: Outbound: ${which} statvfs@openssh.com`); + } + } + ext_openssh_fstatvfs(handle, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['fstatvfs@openssh.com']; + if (!ext || ext !== '2') + throw new Error('Server does not support this extended request'); + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + + /* + uint32 id + string "fstatvfs@openssh.com" + string handle + */ + const handleLen = handle.length; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + 20 + 4 + handleLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 20, p); + buf.utf8Write('fstatvfs@openssh.com', p += 4, 20); + writeUInt32BE(buf, handleLen, p += 20); + buf.set(handle, p += 4); + + this._requests[reqid] = { extended: 'fstatvfs@openssh.com', cb }; + + const isBuffered = sendOrBuffer(this, buf); + if (this._debug) { + const which = (isBuffered ? 'Buffered' : 'Sending'); + this._debug(`SFTP: Outbound: ${which} fstatvfs@openssh.com`); + } + } + ext_openssh_hardlink(oldPath, newPath, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['hardlink@openssh.com']; + if (ext !== '1') + throw new Error('Server does not support this extended request'); + + /* + uint32 id + string "hardlink@openssh.com" + string oldpath + string newpath + */ + const oldLen = Buffer.byteLength(oldPath); + const newLen = Buffer.byteLength(newPath); + let p = 9; + const buf = + Buffer.allocUnsafe(4 + 1 + 4 + 4 + 20 + 4 + oldLen + 4 + newLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 20, p); + buf.utf8Write('hardlink@openssh.com', p += 4, 20); + writeUInt32BE(buf, oldLen, p += 20); + buf.utf8Write(oldPath, p += 4, oldLen); + writeUInt32BE(buf, newLen, p += oldLen); + buf.utf8Write(newPath, p += 4, newLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + if (this._debug) { + const which = (isBuffered ? 'Buffered' : 'Sending'); + this._debug(`SFTP: Outbound: ${which} hardlink@openssh.com`); + } + } + ext_openssh_fsync(handle, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['fsync@openssh.com']; + if (ext !== '1') + throw new Error('Server does not support this extended request'); + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + + /* + uint32 id + string "fsync@openssh.com" + string handle + */ + const handleLen = handle.length; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + 17 + 4 + handleLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 17, p); + buf.utf8Write('fsync@openssh.com', p += 4, 17); + writeUInt32BE(buf, handleLen, p += 17); + buf.set(handle, p += 4); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} fsync@openssh.com` + ); + } + ext_openssh_lsetstat(path, attrs, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['lsetstat@openssh.com']; + if (ext !== '1') + throw new Error('Server does not support this extended request'); + + let flags = 0; + let attrsLen = 0; + + if (typeof attrs === 'object' && attrs !== null) { + attrs = attrsToBytes(attrs); + flags = attrs.flags; + attrsLen = attrs.nb; + } else if (typeof attrs === 'function') { + cb = attrs; + } + + /* + uint32 id + string "lsetstat@openssh.com" + string path + ATTRS attrs + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = + Buffer.allocUnsafe(4 + 1 + 4 + 4 + 20 + 4 + pathLen + 4 + attrsLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 20, p); + buf.utf8Write('lsetstat@openssh.com', p += 4, 20); + + writeUInt32BE(buf, pathLen, p += 20); + buf.utf8Write(path, p += 4, pathLen); + + writeUInt32BE(buf, flags, p += pathLen); + if (attrsLen) { + p += 4; + + if (attrsLen === ATTRS_BUF.length) + buf.set(ATTRS_BUF, p); + else + bufferCopy(ATTRS_BUF, buf, 0, attrsLen, p); + + p += attrsLen; + } + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + if (this._debug) { + const status = (isBuffered ? 'Buffered' : 'Sending'); + this._debug(`SFTP: Outbound: ${status} lsetstat@openssh.com`); + } + } + ext_openssh_expandPath(path, cb) { + if (this.server) + throw new Error('Client-only method called in server mode'); + + const ext = this._extensions['expand-path@openssh.com']; + if (ext !== '1') + throw new Error('Server does not support this extended request'); + + /* + uint32 id + string "expand-path@openssh.com" + string path + */ + const pathLen = Buffer.byteLength(path); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + 23 + 4 + pathLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = this._writeReqid = (this._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 23, p); + buf.utf8Write('expand-path@openssh.com', p += 4, 23); + + writeUInt32BE(buf, pathLen, p += 20); + buf.utf8Write(path, p += 4, pathLen); + + this._requests[reqid] = { cb }; + + const isBuffered = sendOrBuffer(this, buf); + if (this._debug) { + const status = (isBuffered ? 'Buffered' : 'Sending'); + this._debug(`SFTP: Outbound: ${status} expand-path@openssh.com`); + } + } + // =========================================================================== + // Server-specific =========================================================== + // =========================================================================== + handle(reqid, handle) { + if (!this.server) + throw new Error('Server-only method called in client mode'); + + if (!Buffer.isBuffer(handle)) + throw new Error('handle is not a Buffer'); + + const handleLen = handle.length; + + if (handleLen > 256) + throw new Error('handle too large (> 256 bytes)'); + + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = RESPONSE.HANDLE; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, handleLen, p); + if (handleLen) + buf.set(handle, p += 4); + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} HANDLE` + ); + } + status(reqid, code, message) { + if (!this.server) + throw new Error('Server-only method called in client mode'); + + if (!VALID_STATUS_CODES.has(code)) + throw new Error(`Bad status code: ${code}`); + + message || (message = ''); + + const msgLen = Buffer.byteLength(message); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + 4 + msgLen + 4); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = RESPONSE.STATUS; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, code, p); + + writeUInt32BE(buf, msgLen, p += 4); + p += 4; + if (msgLen) { + buf.utf8Write(message, p, msgLen); + p += msgLen; + } + + writeUInt32BE(buf, 0, p); // Empty language tag + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} STATUS` + ); + } + data(reqid, data, encoding) { + if (!this.server) + throw new Error('Server-only method called in client mode'); + + const isBuffer = Buffer.isBuffer(data); + + if (!isBuffer && typeof data !== 'string') + throw new Error('data is not a Buffer or string'); + + let isUTF8; + if (!isBuffer && !encoding) { + encoding = undefined; + isUTF8 = true; + } + + const dataLen = ( + isBuffer + ? data.length + : Buffer.byteLength(data, encoding) + ); + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + dataLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = RESPONSE.DATA; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, dataLen, p); + if (dataLen) { + if (isBuffer) + buf.set(data, p += 4); + else if (isUTF8) + buf.utf8Write(data, p += 4, dataLen); + else + buf.write(data, p += 4, dataLen, encoding); + } + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} DATA` + ); + } + name(reqid, names) { + if (!this.server) + throw new Error('Server-only method called in client mode'); + + if (!Array.isArray(names)) { + if (typeof names !== 'object' || names === null) + throw new Error('names is not an object or array'); + names = [ names ]; + } + + const count = names.length; + let namesLen = 0; + let nameAttrs; + const attrs = []; + + for (let i = 0; i < count; ++i) { + const name = names[i]; + const filename = ( + !name || !name.filename || typeof name.filename !== 'string' + ? '' + : name.filename + ); + namesLen += 4 + Buffer.byteLength(filename); + const longname = ( + !name || !name.longname || typeof name.longname !== 'string' + ? '' + : name.longname + ); + namesLen += 4 + Buffer.byteLength(longname); + + if (typeof name.attrs === 'object' && name.attrs !== null) { + nameAttrs = attrsToBytes(name.attrs); + namesLen += 4 + nameAttrs.nb; + + if (nameAttrs.nb) { + let bytes; + + if (nameAttrs.nb === ATTRS_BUF.length) { + bytes = new Uint8Array(ATTRS_BUF); + } else { + bytes = new Uint8Array(nameAttrs.nb); + bufferCopy(ATTRS_BUF, bytes, 0, nameAttrs.nb, 0); + } + + nameAttrs.bytes = bytes; + } + + attrs.push(nameAttrs); + } else { + namesLen += 4; + attrs.push(null); + } + } + + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + namesLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = RESPONSE.NAME; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, count, p); + + p += 4; + + for (let i = 0; i < count; ++i) { + const name = names[i]; + + { + const filename = ( + !name || !name.filename || typeof name.filename !== 'string' + ? '' + : name.filename + ); + const len = Buffer.byteLength(filename); + writeUInt32BE(buf, len, p); + p += 4; + if (len) { + buf.utf8Write(filename, p, len); + p += len; + } + } + + { + const longname = ( + !name || !name.longname || typeof name.longname !== 'string' + ? '' + : name.longname + ); + const len = Buffer.byteLength(longname); + writeUInt32BE(buf, len, p); + p += 4; + if (len) { + buf.utf8Write(longname, p, len); + p += len; + } + } + + const attr = attrs[i]; + if (attr) { + writeUInt32BE(buf, attr.flags, p); + p += 4; + if (attr.flags && attr.bytes) { + buf.set(attr.bytes, p); + p += attr.nb; + } + } else { + writeUInt32BE(buf, 0, p); + p += 4; + } + } + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} NAME` + ); + } + attrs(reqid, attrs) { + if (!this.server) + throw new Error('Server-only method called in client mode'); + + if (typeof attrs !== 'object' || attrs === null) + throw new Error('attrs is not an object'); + + attrs = attrsToBytes(attrs); + const flags = attrs.flags; + const attrsLen = attrs.nb; + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + attrsLen); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = RESPONSE.ATTRS; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, flags, p); + if (attrsLen) { + p += 4; + + if (attrsLen === ATTRS_BUF.length) + buf.set(ATTRS_BUF, p); + else + bufferCopy(ATTRS_BUF, buf, 0, attrsLen, p); + + p += attrsLen; + } + + const isBuffered = sendOrBuffer(this, buf); + this._debug && this._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} ATTRS` + ); + } +} + +function tryCreateBuffer(size) { + try { + return Buffer.allocUnsafe(size); + } catch (ex) { + return ex; + } +} + +function read_(self, handle, buf, off, len, position, cb, req_) { + const maxDataLen = self._maxReadLen; + const overflow = Math.max(len - maxDataLen, 0); + + if (overflow) + len = maxDataLen; + + /* + uint32 id + string handle + uint64 offset + uint32 len + */ + const handleLen = handle.length; + let p = 9; + let pos = position; + const out = Buffer.allocUnsafe(4 + 1 + 4 + 4 + handleLen + 8 + 4); + + writeUInt32BE(out, out.length - 4, 0); + out[4] = REQUEST.READ; + const reqid = self._writeReqid = (self._writeReqid + 1) & MAX_REQID; + writeUInt32BE(out, reqid, 5); + + writeUInt32BE(out, handleLen, p); + out.set(handle, p += 4); + p += handleLen; + for (let i = 7; i >= 0; --i) { + out[p + i] = pos & 0xFF; + pos /= 256; + } + writeUInt32BE(out, len, p += 8); + + if (typeof cb !== 'function') + cb = noop; + + const req = (req_ || { + nb: 0, + position, + off, + origOff: off, + len: undefined, + overflow: undefined, + cb: (err, data, nb) => { + const len = req.len; + const overflow = req.overflow; + + if (err) { + if (cb._wantEOFError || err.code !== STATUS_CODE.EOF) + return cb(err); + } else if (nb > len) { + return cb(new Error('Received more data than requested')); + } else if (nb === len && overflow) { + req.nb += nb; + req.position += nb; + req.off += nb; + read_(self, handle, buf, req.off, overflow, req.position, cb, req); + return; + } + + if (req.origOff === 0 && buf.length === req.nb) + data = buf; + else + data = bufferSlice(buf, req.origOff, req.origOff + req.nb); + cb(undefined, req.nb + (nb || 0), data, req.position); + }, + buffer: undefined, + }); + + req.len = len; + req.overflow = overflow; + + // TODO: avoid creating multiple buffer slices when we need to re-call read_() + // because of overflow + req.buffer = bufferSlice(buf, off, off + len); + + self._requests[reqid] = req; + + const isBuffered = sendOrBuffer(self, out); + self._debug && self._debug( + `SFTP: Outbound: ${isBuffered ? 'Buffered' : 'Sending'} READ` + ); +} + +function fastXfer(src, dst, srcPath, dstPath, opts, cb) { + let concurrency = 64; + let chunkSize = 32768; + let onstep; + let mode; + let fileSize; + + if (typeof opts === 'function') { + cb = opts; + } else if (typeof opts === 'object' && opts !== null) { + if (typeof opts.concurrency === 'number' + && opts.concurrency > 0 + && !isNaN(opts.concurrency)) { + concurrency = opts.concurrency; + } + if (typeof opts.chunkSize === 'number' + && opts.chunkSize > 0 + && !isNaN(opts.chunkSize)) { + chunkSize = opts.chunkSize; + } + if (typeof opts.fileSize === 'number' + && opts.fileSize > 0 + && !isNaN(opts.fileSize)) { + fileSize = opts.fileSize; + } + if (typeof opts.step === 'function') + onstep = opts.step; + + if (typeof opts.mode === 'string' || typeof opts.mode === 'number') + mode = modeNum(opts.mode); + } + + // Internal state variables + let fsize; + let pdst = 0; + let total = 0; + let hadError = false; + let srcHandle; + let dstHandle; + let readbuf; + let bufsize = chunkSize * concurrency; + + function onerror(err) { + if (hadError) + return; + + hadError = true; + + let left = 0; + let cbfinal; + + if (srcHandle || dstHandle) { + cbfinal = () => { + if (--left === 0) + cb(err); + }; + if (srcHandle && (src === fs || src.outgoing.state === 'open')) + ++left; + if (dstHandle && (dst === fs || dst.outgoing.state === 'open')) + ++left; + if (srcHandle && (src === fs || src.outgoing.state === 'open')) + src.close(srcHandle, cbfinal); + if (dstHandle && (dst === fs || dst.outgoing.state === 'open')) + dst.close(dstHandle, cbfinal); + } else { + cb(err); + } + } + + src.open(srcPath, 'r', (err, sourceHandle) => { + if (err) + return onerror(err); + + srcHandle = sourceHandle; + + if (fileSize === undefined) + src.fstat(srcHandle, tryStat); + else + tryStat(null, { size: fileSize }); + + function tryStat(err, attrs) { + if (err) { + if (src !== fs) { + // Try stat() for sftp servers that may not support fstat() for + // whatever reason + src.stat(srcPath, (err_, attrs_) => { + if (err_) + return onerror(err); + tryStat(null, attrs_); + }); + return; + } + return onerror(err); + } + fsize = attrs.size; + + dst.open(dstPath, 'w', (err, destHandle) => { + if (err) + return onerror(err); + + dstHandle = destHandle; + + if (fsize <= 0) + return onerror(); + + // Use less memory where possible + while (bufsize > fsize) { + if (concurrency === 1) { + bufsize = fsize; + break; + } + bufsize -= chunkSize; + --concurrency; + } + + readbuf = tryCreateBuffer(bufsize); + if (readbuf instanceof Error) + return onerror(readbuf); + + if (mode !== undefined) { + dst.fchmod(dstHandle, mode, function tryAgain(err) { + if (err) { + // Try chmod() for sftp servers that may not support fchmod() + // for whatever reason + dst.chmod(dstPath, mode, (err_) => tryAgain()); + return; + } + startReads(); + }); + } else { + startReads(); + } + + function onread(err, nb, data, dstpos, datapos, origChunkLen) { + if (err) + return onerror(err); + + datapos = datapos || 0; + + dst.write(dstHandle, readbuf, datapos, nb, dstpos, writeCb); + + function writeCb(err) { + if (err) + return onerror(err); + + total += nb; + onstep && onstep(total, nb, fsize); + + if (nb < origChunkLen) + return singleRead(datapos, dstpos + nb, origChunkLen - nb); + + if (total === fsize) { + dst.close(dstHandle, (err) => { + dstHandle = undefined; + if (err) + return onerror(err); + src.close(srcHandle, (err) => { + srcHandle = undefined; + if (err) + return onerror(err); + cb(); + }); + }); + return; + } + + if (pdst >= fsize) + return; + + const chunk = + (pdst + chunkSize > fsize ? fsize - pdst : chunkSize); + singleRead(datapos, pdst, chunk); + pdst += chunk; + } + } + + function makeCb(psrc, pdst, chunk) { + return (err, nb, data) => { + onread(err, nb, data, pdst, psrc, chunk); + }; + } + + function singleRead(psrc, pdst, chunk) { + src.read(srcHandle, + readbuf, + psrc, + chunk, + pdst, + makeCb(psrc, pdst, chunk)); + } + + function startReads() { + let reads = 0; + let psrc = 0; + while (pdst < fsize && reads < concurrency) { + const chunk = + (pdst + chunkSize > fsize ? fsize - pdst : chunkSize); + singleRead(psrc, pdst, chunk); + psrc += chunk; + pdst += chunk; + ++reads; + } + } + }); + } + }); +} + +function writeAll(sftp, handle, buffer, offset, length, position, callback_) { + const callback = (typeof callback_ === 'function' ? callback_ : undefined); + + sftp.write(handle, + buffer, + offset, + length, + position, + (writeErr, written) => { + if (writeErr) { + return sftp.close(handle, () => { + callback && callback(writeErr); + }); + } + if (written === length) { + sftp.close(handle, callback); + } else { + offset += written; + length -= written; + position += written; + writeAll(sftp, handle, buffer, offset, length, position, callback); + } + }); +} + +class Stats { + constructor(initial) { + this.mode = (initial && initial.mode); + this.uid = (initial && initial.uid); + this.gid = (initial && initial.gid); + this.size = (initial && initial.size); + this.atime = (initial && initial.atime); + this.mtime = (initial && initial.mtime); + this.extended = (initial && initial.extended); + } + isDirectory() { + return ((this.mode & constants.S_IFMT) === constants.S_IFDIR); + } + isFile() { + return ((this.mode & constants.S_IFMT) === constants.S_IFREG); + } + isBlockDevice() { + return ((this.mode & constants.S_IFMT) === constants.S_IFBLK); + } + isCharacterDevice() { + return ((this.mode & constants.S_IFMT) === constants.S_IFCHR); + } + isSymbolicLink() { + return ((this.mode & constants.S_IFMT) === constants.S_IFLNK); + } + isFIFO() { + return ((this.mode & constants.S_IFMT) === constants.S_IFIFO); + } + isSocket() { + return ((this.mode & constants.S_IFMT) === constants.S_IFSOCK); + } +} + +function attrsToBytes(attrs) { + let flags = 0; + let nb = 0; + + if (typeof attrs === 'object' && attrs !== null) { + if (typeof attrs.size === 'number') { + flags |= ATTR.SIZE; + const val = attrs.size; + // Big Endian + ATTRS_BUF[nb++] = val / 72057594037927940; // 2**56 + ATTRS_BUF[nb++] = val / 281474976710656; // 2**48 + ATTRS_BUF[nb++] = val / 1099511627776; // 2**40 + ATTRS_BUF[nb++] = val / 4294967296; // 2**32 + ATTRS_BUF[nb++] = val / 16777216; // 2**24 + ATTRS_BUF[nb++] = val / 65536; // 2**16 + ATTRS_BUF[nb++] = val / 256; // 2**8 + ATTRS_BUF[nb++] = val; + } + if (typeof attrs.uid === 'number' && typeof attrs.gid === 'number') { + flags |= ATTR.UIDGID; + const uid = attrs.uid; + const gid = attrs.gid; + // Big Endian + ATTRS_BUF[nb++] = uid >>> 24; + ATTRS_BUF[nb++] = uid >>> 16; + ATTRS_BUF[nb++] = uid >>> 8; + ATTRS_BUF[nb++] = uid; + ATTRS_BUF[nb++] = gid >>> 24; + ATTRS_BUF[nb++] = gid >>> 16; + ATTRS_BUF[nb++] = gid >>> 8; + ATTRS_BUF[nb++] = gid; + } + if (typeof attrs.mode === 'number' || typeof attrs.mode === 'string') { + const mode = modeNum(attrs.mode); + flags |= ATTR.PERMISSIONS; + // Big Endian + ATTRS_BUF[nb++] = mode >>> 24; + ATTRS_BUF[nb++] = mode >>> 16; + ATTRS_BUF[nb++] = mode >>> 8; + ATTRS_BUF[nb++] = mode; + } + if ((typeof attrs.atime === 'number' || isDate(attrs.atime)) + && (typeof attrs.mtime === 'number' || isDate(attrs.mtime))) { + const atime = toUnixTimestamp(attrs.atime); + const mtime = toUnixTimestamp(attrs.mtime); + + flags |= ATTR.ACMODTIME; + // Big Endian + ATTRS_BUF[nb++] = atime >>> 24; + ATTRS_BUF[nb++] = atime >>> 16; + ATTRS_BUF[nb++] = atime >>> 8; + ATTRS_BUF[nb++] = atime; + ATTRS_BUF[nb++] = mtime >>> 24; + ATTRS_BUF[nb++] = mtime >>> 16; + ATTRS_BUF[nb++] = mtime >>> 8; + ATTRS_BUF[nb++] = mtime; + } + // TODO: extended attributes + } + + return { flags, nb }; +} + +function toUnixTimestamp(time) { + // eslint-disable-next-line no-self-compare + if (typeof time === 'number' && time === time) // Valid, non-NaN number + return time; + if (isDate(time)) + return parseInt(time.getTime() / 1000, 10); + throw new Error(`Cannot parse time: ${time}`); +} + +function modeNum(mode) { + // eslint-disable-next-line no-self-compare + if (typeof mode === 'number' && mode === mode) // Valid, non-NaN number + return mode; + if (typeof mode === 'string') + return modeNum(parseInt(mode, 8)); + throw new Error(`Cannot parse mode: ${mode}`); +} + +const stringFlagMap = { + 'r': OPEN_MODE.READ, + 'r+': OPEN_MODE.READ | OPEN_MODE.WRITE, + 'w': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE, + 'wx': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, + 'xw': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, + 'w+': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE, + 'wx+': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE + | OPEN_MODE.EXCL, + 'xw+': OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE + | OPEN_MODE.EXCL, + 'a': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.WRITE, + 'ax': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, + 'xa': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.WRITE | OPEN_MODE.EXCL, + 'a+': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE, + 'ax+': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE + | OPEN_MODE.EXCL, + 'xa+': OPEN_MODE.APPEND | OPEN_MODE.CREAT | OPEN_MODE.READ | OPEN_MODE.WRITE + | OPEN_MODE.EXCL +}; + +function stringToFlags(str) { + const flags = stringFlagMap[str]; + return (flags !== undefined ? flags : null); +} + +const flagsToString = (() => { + const stringFlagMapKeys = Object.keys(stringFlagMap); + return (flags) => { + for (let i = 0; i < stringFlagMapKeys.length; ++i) { + const key = stringFlagMapKeys[i]; + if (stringFlagMap[key] === flags) + return key; + } + return null; + }; +})(); + +function readAttrs(biOpt) { + /* + uint32 flags + uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE + uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID + uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID + uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS + uint32 atime present only if flag SSH_FILEXFER_ACMODTIME + uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME + uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED + string extended_type + string extended_data + ... more extended data (extended_type - extended_data pairs), + so that number of pairs equals extended_count + */ + const flags = bufferParser.readUInt32BE(); + if (flags === undefined) + return; + + const attrs = new Stats(); + if (flags & ATTR.SIZE) { + const size = bufferParser.readUInt64BE(biOpt); + if (size === undefined) + return; + attrs.size = size; + } + + if (flags & ATTR.UIDGID) { + const uid = bufferParser.readUInt32BE(); + const gid = bufferParser.readUInt32BE(); + if (gid === undefined) + return; + attrs.uid = uid; + attrs.gid = gid; + } + + if (flags & ATTR.PERMISSIONS) { + const mode = bufferParser.readUInt32BE(); + if (mode === undefined) + return; + attrs.mode = mode; + } + + if (flags & ATTR.ACMODTIME) { + const atime = bufferParser.readUInt32BE(); + const mtime = bufferParser.readUInt32BE(); + if (mtime === undefined) + return; + attrs.atime = atime; + attrs.mtime = mtime; + } + + if (flags & ATTR.EXTENDED) { + const count = bufferParser.readUInt32BE(); + if (count === undefined) + return; + const extended = {}; + for (let i = 0; i < count; ++i) { + const type = bufferParser.readString(true); + const data = bufferParser.readString(); + if (data === undefined) + return; + extended[type] = data; + } + attrs.extended = extended; + } + + return attrs; +} + +function sendOrBuffer(sftp, payload) { + const ret = tryWritePayload(sftp, payload); + if (ret !== undefined) { + sftp._buffer.push(ret); + return false; + } + return true; +} + +function tryWritePayload(sftp, payload) { + const outgoing = sftp.outgoing; + if (outgoing.state !== 'open') + return; + + if (outgoing.window === 0) { + sftp._waitWindow = true; // XXX: Unnecessary? + return payload; + } + + let ret; + const len = payload.length; + let p = 0; + + while (len - p > 0 && outgoing.window > 0) { + const actualLen = Math.min(len - p, outgoing.window, outgoing.packetSize); + outgoing.window -= actualLen; + if (outgoing.window === 0) { + sftp._waitWindow = true; + sftp._chunkcb = drainBuffer; + } + + if (p === 0 && actualLen === len) { + sftp._protocol.channelData(sftp.outgoing.id, payload); + } else { + sftp._protocol.channelData(sftp.outgoing.id, + bufferSlice(payload, p, p + actualLen)); + } + + p += actualLen; + } + + if (len - p > 0) { + if (p > 0) + ret = bufferSlice(payload, p, len); + else + ret = payload; // XXX: should never get here? + } + + return ret; +} + +function drainBuffer() { + this._chunkcb = undefined; + const buffer = this._buffer; + let i = 0; + while (i < buffer.length) { + const payload = buffer[i]; + const ret = tryWritePayload(this, payload); + if (ret !== undefined) { + if (ret !== payload) + buffer[i] = ret; + if (i > 0) + this._buffer = buffer.slice(i); + return; + } + ++i; + } + if (i > 0) + this._buffer = []; +} + +function doFatalSFTPError(sftp, msg, noDebug) { + const err = new Error(msg); + err.level = 'sftp-protocol'; + if (!noDebug && sftp._debug) + sftp._debug(`SFTP: Inbound: ${msg}`); + sftp.emit('error', err); + sftp.destroy(); + cleanupRequests(sftp); + return false; +} + +function cleanupRequests(sftp) { + const keys = Object.keys(sftp._requests); + if (keys.length === 0) + return; + + const reqs = sftp._requests; + sftp._requests = {}; + const err = new Error('No response from server'); + for (let i = 0; i < keys.length; ++i) { + const req = reqs[keys[i]]; + if (typeof req.cb === 'function') + req.cb(err); + } +} + +function requestLimits(sftp, cb) { + /* + uint32 id + string "limits@openssh.com" + */ + let p = 9; + const buf = Buffer.allocUnsafe(4 + 1 + 4 + 4 + 18); + + writeUInt32BE(buf, buf.length - 4, 0); + buf[4] = REQUEST.EXTENDED; + const reqid = sftp._writeReqid = (sftp._writeReqid + 1) & MAX_REQID; + writeUInt32BE(buf, reqid, 5); + + writeUInt32BE(buf, 18, p); + buf.utf8Write('limits@openssh.com', p += 4, 18); + + sftp._requests[reqid] = { extended: 'limits@openssh.com', cb }; + + const isBuffered = sendOrBuffer(sftp, buf); + if (sftp._debug) { + const which = (isBuffered ? 'Buffered' : 'Sending'); + sftp._debug(`SFTP: Outbound: ${which} limits@openssh.com`); + } +} + +const CLIENT_HANDLERS = { + [RESPONSE.VERSION]: (sftp, payload) => { + if (sftp._version !== -1) + return doFatalSFTPError(sftp, 'Duplicate VERSION packet'); + + const extensions = {}; + + /* + uint32 version + + */ + bufferParser.init(payload, 1); + let version = bufferParser.readUInt32BE(); + while (bufferParser.avail()) { + const extName = bufferParser.readString(true); + const extData = bufferParser.readString(true); + if (extData === undefined) { + version = undefined; + break; + } + extensions[extName] = extData; + } + bufferParser.clear(); + + if (version === undefined) + return doFatalSFTPError(sftp, 'Malformed VERSION packet'); + + if (sftp._debug) { + const names = Object.keys(extensions); + if (names.length) { + sftp._debug( + `SFTP: Inbound: Received VERSION (v${version}, exts:${names})` + ); + } else { + sftp._debug(`SFTP: Inbound: Received VERSION (v${version})`); + } + } + + sftp._version = version; + sftp._extensions = extensions; + + if (extensions['limits@openssh.com'] === '1') { + return requestLimits(sftp, (err, limits) => { + if (!err) { + if (limits.maxPktLen > 0) + sftp._maxOutPktLen = limits.maxPktLen; + if (limits.maxReadLen > 0) + sftp._maxReadLen = limits.maxReadLen; + if (limits.maxWriteLen > 0) + sftp._maxWriteLen = limits.maxWriteLen; + sftp.maxOpenHandles = ( + limits.maxOpenHandles > 0 ? limits.maxOpenHandles : Infinity + ); + } + sftp.emit('ready'); + }); + } + + sftp.emit('ready'); + }, + [RESPONSE.STATUS]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + uint32 error/status code + string error message (ISO-10646 UTF-8) + string language tag + */ + const errorCode = bufferParser.readUInt32BE(); + const errorMsg = bufferParser.readString(true); + const lang = bufferParser.skipString(); + bufferParser.clear(); + + if (lang === undefined) { + if (reqID !== undefined) + delete sftp._requests[reqID]; + return doFatalSFTPError(sftp, 'Malformed STATUS packet'); + } + + if (sftp._debug) { + const jsonMsg = JSON.stringify(errorMsg); + sftp._debug( + `SFTP: Inbound: Received STATUS (id:${reqID}, ${errorCode}, ${jsonMsg})` + ); + } + const req = sftp._requests[reqID]; + delete sftp._requests[reqID]; + if (req && typeof req.cb === 'function') { + if (errorCode === STATUS_CODE.OK) { + req.cb(); + return; + } + const err = new Error(errorMsg + || STATUS_CODE_STR[errorCode] + || 'Unknown status'); + err.code = errorCode; + req.cb(err); + } + }, + [RESPONSE.HANDLE]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + */ + const handle = bufferParser.readString(); + bufferParser.clear(); + + if (handle === undefined) { + if (reqID !== undefined) + delete sftp._requests[reqID]; + return doFatalSFTPError(sftp, 'Malformed HANDLE packet'); + } + + sftp._debug && sftp._debug(`SFTP: Inbound: Received HANDLE (id:${reqID})`); + + const req = sftp._requests[reqID]; + delete sftp._requests[reqID]; + if (req && typeof req.cb === 'function') + req.cb(undefined, handle); + }, + [RESPONSE.DATA]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + let req; + if (reqID !== undefined) { + req = sftp._requests[reqID]; + delete sftp._requests[reqID]; + } + /* + string data + */ + if (req && typeof req.cb === 'function') { + if (req.buffer) { + // We have already pre-allocated space to store the data + + const nb = bufferParser.readString(req.buffer); + bufferParser.clear(); + + if (nb !== undefined) { + sftp._debug && sftp._debug( + `SFTP: Inbound: Received DATA (id:${reqID}, ${nb})` + ); + req.cb(undefined, req.buffer, nb); + return; + } + } else { + const data = bufferParser.readString(); + bufferParser.clear(); + + if (data !== undefined) { + sftp._debug && sftp._debug( + `SFTP: Inbound: Received DATA (id:${reqID}, ${data.length})` + ); + req.cb(undefined, data); + return; + } + } + } else { + const nb = bufferParser.skipString(); + bufferParser.clear(); + if (nb !== undefined) { + sftp._debug && sftp._debug( + `SFTP: Inbound: Received DATA (id:${reqID}, ${nb})` + ); + return; + } + } + + return doFatalSFTPError(sftp, 'Malformed DATA packet'); + }, + [RESPONSE.NAME]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + let req; + if (reqID !== undefined) { + req = sftp._requests[reqID]; + delete sftp._requests[reqID]; + } + /* + uint32 count + repeats count times: + string filename + string longname + ATTRS attrs + */ + const count = bufferParser.readUInt32BE(); + if (count !== undefined) { + let names = []; + for (let i = 0; i < count; ++i) { + // We are going to assume UTF-8 for filenames despite the SFTPv3 + // spec not specifying an encoding because the specs for newer + // versions of the protocol all explicitly specify UTF-8 for + // filenames + const filename = bufferParser.readString(true); + + // `longname` only exists in SFTPv3 and since it typically will + // contain the filename, we assume it is also UTF-8 + const longname = bufferParser.readString(true); + + const attrs = readAttrs(sftp._biOpt); + if (attrs === undefined) { + names = undefined; + break; + } + names.push({ filename, longname, attrs }); + } + if (names !== undefined) { + sftp._debug && sftp._debug( + `SFTP: Inbound: Received NAME (id:${reqID}, ${names.length})` + ); + bufferParser.clear(); + if (req && typeof req.cb === 'function') + req.cb(undefined, names); + return; + } + } + + bufferParser.clear(); + return doFatalSFTPError(sftp, 'Malformed NAME packet'); + }, + [RESPONSE.ATTRS]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + let req; + if (reqID !== undefined) { + req = sftp._requests[reqID]; + delete sftp._requests[reqID]; + } + /* + ATTRS attrs + */ + const attrs = readAttrs(sftp._biOpt); + bufferParser.clear(); + if (attrs !== undefined) { + sftp._debug && sftp._debug(`SFTP: Inbound: Received ATTRS (id:${reqID})`); + if (req && typeof req.cb === 'function') + req.cb(undefined, attrs); + return; + } + + return doFatalSFTPError(sftp, 'Malformed ATTRS packet'); + }, + [RESPONSE.EXTENDED]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + if (reqID !== undefined) { + const req = sftp._requests[reqID]; + if (req) { + delete sftp._requests[reqID]; + switch (req.extended) { + case 'statvfs@openssh.com': + case 'fstatvfs@openssh.com': { + /* + uint64 f_bsize // file system block size + uint64 f_frsize // fundamental fs block size + uint64 f_blocks // number of blocks (unit f_frsize) + uint64 f_bfree // free blocks in file system + uint64 f_bavail // free blocks for non-root + uint64 f_files // total file inodes + uint64 f_ffree // free file inodes + uint64 f_favail // free file inodes for to non-root + uint64 f_fsid // file system id + uint64 f_flag // bit mask of f_flag values + uint64 f_namemax // maximum filename length + */ + const biOpt = sftp._biOpt; + const stats = { + f_bsize: bufferParser.readUInt64BE(biOpt), + f_frsize: bufferParser.readUInt64BE(biOpt), + f_blocks: bufferParser.readUInt64BE(biOpt), + f_bfree: bufferParser.readUInt64BE(biOpt), + f_bavail: bufferParser.readUInt64BE(biOpt), + f_files: bufferParser.readUInt64BE(biOpt), + f_ffree: bufferParser.readUInt64BE(biOpt), + f_favail: bufferParser.readUInt64BE(biOpt), + f_sid: bufferParser.readUInt64BE(biOpt), + f_flag: bufferParser.readUInt64BE(biOpt), + f_namemax: bufferParser.readUInt64BE(biOpt), + }; + if (stats.f_namemax === undefined) + break; + if (sftp._debug) { + sftp._debug( + 'SFTP: Inbound: Received EXTENDED_REPLY ' + + `(id:${reqID}, ${req.extended})` + ); + } + bufferParser.clear(); + if (typeof req.cb === 'function') + req.cb(undefined, stats); + return; + } + case 'limits@openssh.com': { + /* + uint64 max-packet-length + uint64 max-read-length + uint64 max-write-length + uint64 max-open-handles + */ + const limits = { + maxPktLen: bufferParser.readUInt64BE(), + maxReadLen: bufferParser.readUInt64BE(), + maxWriteLen: bufferParser.readUInt64BE(), + maxOpenHandles: bufferParser.readUInt64BE(), + }; + if (limits.maxOpenHandles === undefined) + break; + if (sftp._debug) { + sftp._debug( + 'SFTP: Inbound: Received EXTENDED_REPLY ' + + `(id:${reqID}, ${req.extended})` + ); + } + bufferParser.clear(); + if (typeof req.cb === 'function') + req.cb(undefined, limits); + return; + } + default: + // Unknown extended request + sftp._debug && sftp._debug( + `SFTP: Inbound: Received EXTENDED_REPLY (id:${reqID}, ???)` + ); + bufferParser.clear(); + if (typeof req.cb === 'function') + req.cb(); + return; + } + } else { + sftp._debug && sftp._debug( + `SFTP: Inbound: Received EXTENDED_REPLY (id:${reqID}, ???)` + ); + bufferParser.clear(); + return; + } + } + + bufferParser.clear(); + return doFatalSFTPError(sftp, 'Malformed EXTENDED_REPLY packet'); + }, +}; +const SERVER_HANDLERS = { + [REQUEST.INIT]: (sftp, payload) => { + if (sftp._version !== -1) + return doFatalSFTPError(sftp, 'Duplicate INIT packet'); + + const extensions = {}; + + /* + uint32 version + + */ + bufferParser.init(payload, 1); + let version = bufferParser.readUInt32BE(); + while (bufferParser.avail()) { + const extName = bufferParser.readString(true); + const extData = bufferParser.readString(true); + if (extData === undefined) { + version = undefined; + break; + } + extensions[extName] = extData; + } + bufferParser.clear(); + + if (version === undefined) + return doFatalSFTPError(sftp, 'Malformed INIT packet'); + + if (sftp._debug) { + const names = Object.keys(extensions); + if (names.length) { + sftp._debug( + `SFTP: Inbound: Received INIT (v${version}, exts:${names})` + ); + } else { + sftp._debug(`SFTP: Inbound: Received INIT (v${version})`); + } + } + + sendOrBuffer(sftp, SERVER_VERSION_BUFFER); + + sftp._version = version; + sftp._extensions = extensions; + sftp.emit('ready'); + }, + [REQUEST.OPEN]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string filename + uint32 pflags + ATTRS attrs + */ + const filename = bufferParser.readString(true); + const pflags = bufferParser.readUInt32BE(); + const attrs = readAttrs(sftp._biOpt); + bufferParser.clear(); + + if (attrs === undefined) + return doFatalSFTPError(sftp, 'Malformed OPEN packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received OPEN (id:${reqID})`); + + if (!sftp.emit('OPEN', reqID, filename, pflags, attrs)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.CLOSE]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + */ + const handle = bufferParser.readString(); + bufferParser.clear(); + + if (handle === undefined || handle.length > 256) + return doFatalSFTPError(sftp, 'Malformed CLOSE packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received CLOSE (id:${reqID})`); + + if (!sftp.emit('CLOSE', reqID, handle)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.READ]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + uint64 offset + uint32 len + */ + const handle = bufferParser.readString(); + const offset = bufferParser.readUInt64BE(sftp._biOpt); + const len = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (len === undefined || handle.length > 256) + return doFatalSFTPError(sftp, 'Malformed READ packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received READ (id:${reqID})`); + + if (!sftp.emit('READ', reqID, handle, offset, len)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.WRITE]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + uint64 offset + string data + */ + const handle = bufferParser.readString(); + const offset = bufferParser.readUInt64BE(sftp._biOpt); + const data = bufferParser.readString(); + bufferParser.clear(); + + if (data === undefined || handle.length > 256) + return doFatalSFTPError(sftp, 'Malformed WRITE packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received WRITE (id:${reqID})`); + + if (!sftp.emit('WRITE', reqID, handle, offset, data)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.LSTAT]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed LSTAT packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received LSTAT (id:${reqID})`); + + if (!sftp.emit('LSTAT', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.FSTAT]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + */ + const handle = bufferParser.readString(); + bufferParser.clear(); + + if (handle === undefined || handle.length > 256) + return doFatalSFTPError(sftp, 'Malformed FSTAT packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received FSTAT (id:${reqID})`); + + if (!sftp.emit('FSTAT', reqID, handle)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.SETSTAT]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + ATTRS attrs + */ + const path = bufferParser.readString(true); + const attrs = readAttrs(sftp._biOpt); + bufferParser.clear(); + + if (attrs === undefined) + return doFatalSFTPError(sftp, 'Malformed SETSTAT packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received SETSTAT (id:${reqID})`); + + if (!sftp.emit('SETSTAT', reqID, path, attrs)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.FSETSTAT]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + ATTRS attrs + */ + const handle = bufferParser.readString(); + const attrs = readAttrs(sftp._biOpt); + bufferParser.clear(); + + if (attrs === undefined || handle.length > 256) + return doFatalSFTPError(sftp, 'Malformed FSETSTAT packet'); + + sftp._debug && sftp._debug( + `SFTP: Inbound: Received FSETSTAT (id:${reqID})` + ); + + if (!sftp.emit('FSETSTAT', reqID, handle, attrs)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.OPENDIR]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed OPENDIR packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received OPENDIR (id:${reqID})`); + + if (!sftp.emit('OPENDIR', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.READDIR]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string handle + */ + const handle = bufferParser.readString(); + bufferParser.clear(); + + if (handle === undefined || handle.length > 256) + return doFatalSFTPError(sftp, 'Malformed READDIR packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received READDIR (id:${reqID})`); + + if (!sftp.emit('READDIR', reqID, handle)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.REMOVE]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed REMOVE packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received REMOVE (id:${reqID})`); + + if (!sftp.emit('REMOVE', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.MKDIR]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + ATTRS attrs + */ + const path = bufferParser.readString(true); + const attrs = readAttrs(sftp._biOpt); + bufferParser.clear(); + + if (attrs === undefined) + return doFatalSFTPError(sftp, 'Malformed MKDIR packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received MKDIR (id:${reqID})`); + + if (!sftp.emit('MKDIR', reqID, path, attrs)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.RMDIR]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed RMDIR packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received RMDIR (id:${reqID})`); + + if (!sftp.emit('RMDIR', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.REALPATH]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed REALPATH packet'); + + sftp._debug && sftp._debug( + `SFTP: Inbound: Received REALPATH (id:${reqID})` + ); + + if (!sftp.emit('REALPATH', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.STAT]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed STAT packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received STAT (id:${reqID})`); + + if (!sftp.emit('STAT', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.RENAME]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string oldpath + string newpath + */ + const oldPath = bufferParser.readString(true); + const newPath = bufferParser.readString(true); + bufferParser.clear(); + + if (newPath === undefined) + return doFatalSFTPError(sftp, 'Malformed RENAME packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received RENAME (id:${reqID})`); + + if (!sftp.emit('RENAME', reqID, oldPath, newPath)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.READLINK]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string path + */ + const path = bufferParser.readString(true); + bufferParser.clear(); + + if (path === undefined) + return doFatalSFTPError(sftp, 'Malformed READLINK packet'); + + sftp._debug && sftp._debug( + `SFTP: Inbound: Received READLINK (id:${reqID})` + ); + + if (!sftp.emit('READLINK', reqID, path)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.SYMLINK]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string linkpath + string targetpath + */ + const linkPath = bufferParser.readString(true); + const targetPath = bufferParser.readString(true); + bufferParser.clear(); + + if (targetPath === undefined) + return doFatalSFTPError(sftp, 'Malformed SYMLINK packet'); + + sftp._debug && sftp._debug(`SFTP: Inbound: Received SYMLINK (id:${reqID})`); + + let handled; + if (sftp._isOpenSSH) { + // OpenSSH has linkpath and targetpath positions switched + handled = sftp.emit('SYMLINK', reqID, targetPath, linkPath); + } else { + handled = sftp.emit('SYMLINK', reqID, linkPath, targetPath); + } + if (!handled) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, + [REQUEST.EXTENDED]: (sftp, payload) => { + bufferParser.init(payload, 1); + const reqID = bufferParser.readUInt32BE(); + /* + string extended-request + ... any request-specific data ... + */ + const extName = bufferParser.readString(true); + if (extName === undefined) { + bufferParser.clear(); + return doFatalSFTPError(sftp, 'Malformed EXTENDED packet'); + } + + let extData; + if (bufferParser.avail()) + extData = bufferParser.readRaw(); + bufferParser.clear(); + + sftp._debug && sftp._debug( + `SFTP: Inbound: Received EXTENDED (id:${reqID})` + ); + + if (!sftp.emit('EXTENDED', reqID, extName, extData)) { + // Automatically reject request if no handler for request type + sftp.status(reqID, STATUS_CODE.OP_UNSUPPORTED); + } + }, +}; + +// ============================================================================= +// ReadStream/WriteStream-related ============================================== +// ============================================================================= +const { + ERR_INVALID_ARG_TYPE, + ERR_OUT_OF_RANGE, + validateNumber +} = require('./node-fs-compat'); + +const kMinPoolSpace = 128; + +let pool; +// It can happen that we expect to read a large chunk of data, and reserve +// a large chunk of the pool accordingly, but the read() call only filled +// a portion of it. If a concurrently executing read() then uses the same pool, +// the "reserved" portion cannot be used, so we allow it to be re-used as a +// new pool later. +const poolFragments = []; + +function allocNewPool(poolSize) { + if (poolFragments.length > 0) + pool = poolFragments.pop(); + else + pool = Buffer.allocUnsafe(poolSize); + pool.used = 0; +} + +// Check the `this.start` and `this.end` of stream. +function checkPosition(pos, name) { + if (!Number.isSafeInteger(pos)) { + validateNumber(pos, name); + if (!Number.isInteger(pos)) + throw new ERR_OUT_OF_RANGE(name, 'an integer', pos); + throw new ERR_OUT_OF_RANGE(name, '>= 0 and <= 2 ** 53 - 1', pos); + } + if (pos < 0) + throw new ERR_OUT_OF_RANGE(name, '>= 0 and <= 2 ** 53 - 1', pos); +} + +function roundUpToMultipleOf8(n) { + return (n + 7) & ~7; // Align to 8 byte boundary. +} + +function ReadStream(sftp, path, options) { + if (options === undefined) + options = {}; + else if (typeof options === 'string') + options = { encoding: options }; + else if (options === null || typeof options !== 'object') + throw new TypeError('"options" argument must be a string or an object'); + else + options = Object.create(options); + + // A little bit bigger buffer and water marks by default + if (options.highWaterMark === undefined) + options.highWaterMark = 64 * 1024; + + // For backwards compat do not emit close on destroy. + options.emitClose = false; + options.autoDestroy = false; // Node 14 major change. + + ReadableStream.call(this, options); + + this.path = path; + this.flags = options.flags === undefined ? 'r' : options.flags; + this.mode = options.mode === undefined ? 0o666 : options.mode; + + this.start = options.start; + this.end = options.end; + this.autoClose = options.autoClose === undefined ? true : options.autoClose; + this.pos = 0; + this.bytesRead = 0; + this.closed = false; + + this.handle = options.handle === undefined ? null : options.handle; + this.sftp = sftp; + this._opening = false; + + if (this.start !== undefined) { + checkPosition(this.start, 'start'); + + this.pos = this.start; + } + + if (this.end === undefined) { + this.end = Infinity; + } else if (this.end !== Infinity) { + checkPosition(this.end, 'end'); + + if (this.start !== undefined && this.start > this.end) { + throw new ERR_OUT_OF_RANGE( + 'start', + `<= "end" (here: ${this.end})`, + this.start + ); + } + } + + this.on('end', function() { + if (this.autoClose) + this.destroy(); + }); + + if (!Buffer.isBuffer(this.handle)) + this.open(); +} +inherits(ReadStream, ReadableStream); + +ReadStream.prototype.open = function() { + if (this._opening) + return; + + this._opening = true; + + this.sftp.open(this.path, this.flags, this.mode, (er, handle) => { + this._opening = false; + + if (er) { + this.emit('error', er); + if (this.autoClose) + this.destroy(); + return; + } + + this.handle = handle; + this.emit('open', handle); + this.emit('ready'); + // Start the flow of data. + this.read(); + }); +}; + +ReadStream.prototype._read = function(n) { + if (!Buffer.isBuffer(this.handle)) + return this.once('open', () => this._read(n)); + + // XXX: safe to remove this? + if (this.destroyed) + return; + + if (!pool || pool.length - pool.used < kMinPoolSpace) { + // Discard the old pool. + allocNewPool(this.readableHighWaterMark + || this._readableState.highWaterMark); + } + + // Grab another reference to the pool in the case that while we're + // in the thread pool another read() finishes up the pool, and + // allocates a new one. + const thisPool = pool; + let toRead = Math.min(pool.length - pool.used, n); + const start = pool.used; + + if (this.end !== undefined) + toRead = Math.min(this.end - this.pos + 1, toRead); + + // Already read everything we were supposed to read! + // treat as EOF. + if (toRead <= 0) + return this.push(null); + + // the actual read. + this.sftp.read(this.handle, + pool, + pool.used, + toRead, + this.pos, + (er, bytesRead) => { + if (er) { + this.emit('error', er); + if (this.autoClose) + this.destroy(); + return; + } + let b = null; + + // Now that we know how much data we have actually read, re-wind the + // 'used' field if we can, and otherwise allow the remainder of our + // reservation to be used as a new pool later. + if (start + toRead === thisPool.used && thisPool === pool) { + thisPool.used = roundUpToMultipleOf8(thisPool.used + bytesRead - toRead); + } else { + // Round down to the next lowest multiple of 8 to ensure the new pool + // fragment start and end positions are aligned to an 8 byte boundary. + const alignedEnd = (start + toRead) & ~7; + const alignedStart = roundUpToMultipleOf8(start + bytesRead); + if (alignedEnd - alignedStart >= kMinPoolSpace) + poolFragments.push(thisPool.slice(alignedStart, alignedEnd)); + } + + if (bytesRead > 0) { + this.bytesRead += bytesRead; + b = thisPool.slice(start, start + bytesRead); + } + + // Move the pool positions, and internal position for reading. + this.pos += bytesRead; + + this.push(b); + }); + + pool.used = roundUpToMultipleOf8(pool.used + toRead); +}; + +ReadStream.prototype._destroy = function(err, cb) { + if (this._opening && !Buffer.isBuffer(this.handle)) { + this.once('open', closeStream.bind(null, this, cb, err)); + return; + } + + closeStream(this, cb, err); + this.handle = null; + this._opening = false; +}; + +function closeStream(stream, cb, err) { + if (!stream.handle) + return onclose(); + + stream.sftp.close(stream.handle, onclose); + + function onclose(er) { + er = er || err; + cb(er); + stream.closed = true; + if (!er) + stream.emit('close'); + } +} + +ReadStream.prototype.close = function(cb) { + this.destroy(null, cb); +}; + +Object.defineProperty(ReadStream.prototype, 'pending', { + get() { + return this.handle === null; + }, + configurable: true +}); + +// TODO: add `concurrency` setting to allow more than one in-flight WRITE +// request to server to improve throughput +function WriteStream(sftp, path, options) { + if (options === undefined) + options = {}; + else if (typeof options === 'string') + options = { encoding: options }; + else if (options === null || typeof options !== 'object') + throw new TypeError('"options" argument must be a string or an object'); + else + options = Object.create(options); + + // For backwards compat do not emit close on destroy. + options.emitClose = false; + options.autoDestroy = false; // Node 14 major change. + + WritableStream.call(this, options); + + this.path = path; + this.flags = options.flags === undefined ? 'w' : options.flags; + this.mode = options.mode === undefined ? 0o666 : options.mode; + + this.start = options.start; + this.autoClose = options.autoClose === undefined ? true : options.autoClose; + this.pos = 0; + this.bytesWritten = 0; + this.closed = false; + + this.handle = options.handle === undefined ? null : options.handle; + this.sftp = sftp; + this._opening = false; + + if (this.start !== undefined) { + checkPosition(this.start, 'start'); + + this.pos = this.start; + } + + if (options.encoding) + this.setDefaultEncoding(options.encoding); + + // Node v6.x only + this.on('finish', function() { + if (this._writableState.finalCalled) + return; + if (this.autoClose) + this.destroy(); + }); + + if (!Buffer.isBuffer(this.handle)) + this.open(); +} +inherits(WriteStream, WritableStream); + +WriteStream.prototype._final = function(cb) { + if (this.autoClose) + this.destroy(); + cb(); +}; + +WriteStream.prototype.open = function() { + if (this._opening) + return; + + this._opening = true; + + this.sftp.open(this.path, this.flags, this.mode, (er, handle) => { + this._opening = false; + + if (er) { + this.emit('error', er); + if (this.autoClose) + this.destroy(); + return; + } + + this.handle = handle; + + const tryAgain = (err) => { + if (err) { + // Try chmod() for sftp servers that may not support fchmod() for + // whatever reason + this.sftp.chmod(this.path, this.mode, (err_) => tryAgain()); + return; + } + + // SFTPv3 requires absolute offsets, no matter the open flag used + if (this.flags[0] === 'a') { + const tryStat = (err, st) => { + if (err) { + // Try stat() for sftp servers that may not support fstat() for + // whatever reason + this.sftp.stat(this.path, (err_, st_) => { + if (err_) { + this.destroy(); + this.emit('error', err); + return; + } + tryStat(null, st_); + }); + return; + } + + this.pos = st.size; + this.emit('open', handle); + this.emit('ready'); + }; + + this.sftp.fstat(handle, tryStat); + return; + } + + this.emit('open', handle); + this.emit('ready'); + }; + + this.sftp.fchmod(handle, this.mode, tryAgain); + }); +}; + +WriteStream.prototype._write = function(data, encoding, cb) { + if (!Buffer.isBuffer(data)) { + const err = new ERR_INVALID_ARG_TYPE('data', 'Buffer', data); + return this.emit('error', err); + } + + if (!Buffer.isBuffer(this.handle)) { + return this.once('open', function() { + this._write(data, encoding, cb); + }); + } + + this.sftp.write(this.handle, + data, + 0, + data.length, + this.pos, + (er, bytes) => { + if (er) { + if (this.autoClose) + this.destroy(); + return cb(er); + } + this.bytesWritten += bytes; + cb(); + }); + + this.pos += data.length; +}; + +WriteStream.prototype._writev = function(data, cb) { + if (!Buffer.isBuffer(this.handle)) { + return this.once('open', function() { + this._writev(data, cb); + }); + } + + const sftp = this.sftp; + const handle = this.handle; + let writesLeft = data.length; + + const onwrite = (er, bytes) => { + if (er) { + this.destroy(); + return cb(er); + } + this.bytesWritten += bytes; + if (--writesLeft === 0) + cb(); + }; + + // TODO: try to combine chunks to reduce number of requests to the server? + for (let i = 0; i < data.length; ++i) { + const chunk = data[i].chunk; + + sftp.write(handle, chunk, 0, chunk.length, this.pos, onwrite); + this.pos += chunk.length; + } +}; + +if (typeof WritableStream.prototype.destroy !== 'function') + WriteStream.prototype.destroy = ReadStream.prototype.destroy; + +WriteStream.prototype._destroy = ReadStream.prototype._destroy; +WriteStream.prototype.close = function(cb) { + if (cb) { + if (this.closed) { + process.nextTick(cb); + return; + } + this.on('close', cb); + } + + // If we are not autoClosing, we should call + // destroy on 'finish'. + if (!this.autoClose) + this.on('finish', this.destroy.bind(this)); + + this.end(); +}; + +// There is no shutdown() for files. +WriteStream.prototype.destroySoon = WriteStream.prototype.end; + +Object.defineProperty(WriteStream.prototype, 'pending', { + get() { + return this.handle === null; + }, + configurable: true +}); +// ============================================================================= + +module.exports = { + flagsToString, + OPEN_MODE, + SFTP, + Stats, + STATUS_CODE, + stringToFlags, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/constants.js b/reverse_engineering/node_modules/ssh2/lib/protocol/constants.js new file mode 100644 index 0000000..632b7aa --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/constants.js @@ -0,0 +1,344 @@ +'use strict'; + +const crypto = require('crypto'); + +let cpuInfo; +try { + cpuInfo = require('cpu-features')(); +} catch {} + +const { bindingAvailable } = require('./crypto.js'); + +const eddsaSupported = (() => { + if (typeof crypto.sign === 'function' + && typeof crypto.verify === 'function') { + const key = + '-----BEGIN PRIVATE KEY-----\r\nMC4CAQAwBQYDK2VwBCIEIHKj+sVa9WcD' + + '/q2DJUJaf43Kptc8xYuUQA4bOFj9vC8T\r\n-----END PRIVATE KEY-----'; + const data = Buffer.from('a'); + let sig; + let verified; + try { + sig = crypto.sign(null, data, key); + verified = crypto.verify(null, data, key, sig); + } catch {} + return (Buffer.isBuffer(sig) && sig.length === 64 && verified === true); + } + + return false; +})(); + +const curve25519Supported = (typeof crypto.diffieHellman === 'function' + && typeof crypto.generateKeyPairSync === 'function' + && typeof crypto.createPublicKey === 'function'); + +const DEFAULT_KEX = [ + // https://tools.ietf.org/html/rfc5656#section-10.1 + 'ecdh-sha2-nistp256', + 'ecdh-sha2-nistp384', + 'ecdh-sha2-nistp521', + + // https://tools.ietf.org/html/rfc4419#section-4 + 'diffie-hellman-group-exchange-sha256', + + // https://tools.ietf.org/html/rfc8268 + 'diffie-hellman-group14-sha256', + 'diffie-hellman-group15-sha512', + 'diffie-hellman-group16-sha512', + 'diffie-hellman-group17-sha512', + 'diffie-hellman-group18-sha512', +]; +if (curve25519Supported) { + DEFAULT_KEX.unshift('curve25519-sha256'); + DEFAULT_KEX.unshift('curve25519-sha256@libssh.org'); +} +const SUPPORTED_KEX = DEFAULT_KEX.concat([ + // https://tools.ietf.org/html/rfc4419#section-4 + 'diffie-hellman-group-exchange-sha1', + + 'diffie-hellman-group14-sha1', // REQUIRED + 'diffie-hellman-group1-sha1', // REQUIRED +]); + + +const DEFAULT_SERVER_HOST_KEY = [ + 'ecdsa-sha2-nistp256', + 'ecdsa-sha2-nistp384', + 'ecdsa-sha2-nistp521', + 'rsa-sha2-512', // RFC 8332 + 'rsa-sha2-256', // RFC 8332 + 'ssh-rsa', +]; +if (eddsaSupported) + DEFAULT_SERVER_HOST_KEY.unshift('ssh-ed25519'); +const SUPPORTED_SERVER_HOST_KEY = DEFAULT_SERVER_HOST_KEY.concat([ + 'ssh-dss', +]); + + +const DEFAULT_CIPHER = [ + // http://tools.ietf.org/html/rfc5647 + 'aes128-gcm', + 'aes128-gcm@openssh.com', + 'aes256-gcm', + 'aes256-gcm@openssh.com', + + // http://tools.ietf.org/html/rfc4344#section-4 + 'aes128-ctr', + 'aes192-ctr', + 'aes256-ctr', +]; +if (cpuInfo && cpuInfo.flags && !cpuInfo.flags.aes) { + // We know for sure the CPU does not support AES acceleration + if (bindingAvailable) + DEFAULT_CIPHER.unshift('chacha20-poly1305@openssh.com'); + else + DEFAULT_CIPHER.push('chacha20-poly1305@openssh.com'); +} else if (bindingAvailable && cpuInfo && cpuInfo.arch === 'x86') { + // Places chacha20-poly1305 immediately after GCM ciphers since GCM ciphers + // seem to outperform it on x86, but it seems to be faster than CTR ciphers + DEFAULT_CIPHER.splice(4, 0, 'chacha20-poly1305@openssh.com'); +} else { + DEFAULT_CIPHER.push('chacha20-poly1305@openssh.com'); +} +const SUPPORTED_CIPHER = DEFAULT_CIPHER.concat([ + 'aes256-cbc', + 'aes192-cbc', + 'aes128-cbc', + 'blowfish-cbc', + '3des-cbc', + + // http://tools.ietf.org/html/rfc4345#section-4: + 'arcfour256', + 'arcfour128', + + 'cast128-cbc', + 'arcfour', +]); + + +const DEFAULT_MAC = [ + 'hmac-sha2-256-etm@openssh.com', + 'hmac-sha2-512-etm@openssh.com', + 'hmac-sha1-etm@openssh.com', + 'hmac-sha2-256', + 'hmac-sha2-512', + 'hmac-sha1', +]; +const SUPPORTED_MAC = DEFAULT_MAC.concat([ + 'hmac-md5', + 'hmac-sha2-256-96', // first 96 bits of HMAC-SHA256 + 'hmac-sha2-512-96', // first 96 bits of HMAC-SHA512 + 'hmac-ripemd160', + 'hmac-sha1-96', // first 96 bits of HMAC-SHA1 + 'hmac-md5-96', // first 96 bits of HMAC-MD5 +]); + +const DEFAULT_COMPRESSION = [ + 'none', + 'zlib@openssh.com', // ZLIB (LZ77) compression, except + // compression/decompression does not start until after + // successful user authentication + 'zlib', // ZLIB (LZ77) compression +]; +const SUPPORTED_COMPRESSION = DEFAULT_COMPRESSION.concat([ +]); + + +const COMPAT = { + BAD_DHGEX: 1 << 0, + OLD_EXIT: 1 << 1, + DYN_RPORT_BUG: 1 << 2, + BUG_DHGEX_LARGE: 1 << 3, +}; + +module.exports = { + MESSAGE: { + // Transport layer protocol -- generic (1-19) + DISCONNECT: 1, + IGNORE: 2, + UNIMPLEMENTED: 3, + DEBUG: 4, + SERVICE_REQUEST: 5, + SERVICE_ACCEPT: 6, + + // Transport layer protocol -- algorithm negotiation (20-29) + KEXINIT: 20, + NEWKEYS: 21, + + // Transport layer protocol -- key exchange method-specific (30-49) + KEXDH_INIT: 30, + KEXDH_REPLY: 31, + + KEXDH_GEX_GROUP: 31, + KEXDH_GEX_INIT: 32, + KEXDH_GEX_REPLY: 33, + KEXDH_GEX_REQUEST: 34, + + KEXECDH_INIT: 30, + KEXECDH_REPLY: 31, + + // User auth protocol -- generic (50-59) + USERAUTH_REQUEST: 50, + USERAUTH_FAILURE: 51, + USERAUTH_SUCCESS: 52, + USERAUTH_BANNER: 53, + + // User auth protocol -- user auth method-specific (60-79) + USERAUTH_PASSWD_CHANGEREQ: 60, + + USERAUTH_PK_OK: 60, + + USERAUTH_INFO_REQUEST: 60, + USERAUTH_INFO_RESPONSE: 61, + + // Connection protocol -- generic (80-89) + GLOBAL_REQUEST: 80, + REQUEST_SUCCESS: 81, + REQUEST_FAILURE: 82, + + // Connection protocol -- channel-related (90-127) + CHANNEL_OPEN: 90, + CHANNEL_OPEN_CONFIRMATION: 91, + CHANNEL_OPEN_FAILURE: 92, + CHANNEL_WINDOW_ADJUST: 93, + CHANNEL_DATA: 94, + CHANNEL_EXTENDED_DATA: 95, + CHANNEL_EOF: 96, + CHANNEL_CLOSE: 97, + CHANNEL_REQUEST: 98, + CHANNEL_SUCCESS: 99, + CHANNEL_FAILURE: 100 + + // Reserved for client protocols (128-191) + + // Local extensions (192-155) + }, + DISCONNECT_REASON: { + HOST_NOT_ALLOWED_TO_CONNECT: 1, + PROTOCOL_ERROR: 2, + KEY_EXCHANGE_FAILED: 3, + RESERVED: 4, + MAC_ERROR: 5, + COMPRESSION_ERROR: 6, + SERVICE_NOT_AVAILABLE: 7, + PROTOCOL_VERSION_NOT_SUPPORTED: 8, + HOST_KEY_NOT_VERIFIABLE: 9, + CONNECTION_LOST: 10, + BY_APPLICATION: 11, + TOO_MANY_CONNECTIONS: 12, + AUTH_CANCELED_BY_USER: 13, + NO_MORE_AUTH_METHODS_AVAILABLE: 14, + ILLEGAL_USER_NAME: 15, + }, + DISCONNECT_REASON_STR: undefined, + CHANNEL_OPEN_FAILURE: { + ADMINISTRATIVELY_PROHIBITED: 1, + CONNECT_FAILED: 2, + UNKNOWN_CHANNEL_TYPE: 3, + RESOURCE_SHORTAGE: 4 + }, + TERMINAL_MODE: { + TTY_OP_END: 0, // Indicates end of options. + VINTR: 1, // Interrupt character; 255 if none. Similarly for the + // other characters. Not all of these characters are + // supported on all systems. + VQUIT: 2, // The quit character (sends SIGQUIT signal on POSIX + // systems). + VERASE: 3, // Erase the character to left of the cursor. + VKILL: 4, // Kill the current input line. + VEOF: 5, // End-of-file character (sends EOF from the + // terminal). + VEOL: 6, // End-of-line character in addition to carriage + // return and/or linefeed. + VEOL2: 7, // Additional end-of-line character. + VSTART: 8, // Continues paused output (normally control-Q). + VSTOP: 9, // Pauses output (normally control-S). + VSUSP: 10, // Suspends the current program. + VDSUSP: 11, // Another suspend character. + VREPRINT: 12, // Reprints the current input line. + VWERASE: 13, // Erases a word left of cursor. + VLNEXT: 14, // Enter the next character typed literally, even if + // it is a special character + VFLUSH: 15, // Character to flush output. + VSWTCH: 16, // Switch to a different shell layer. + VSTATUS: 17, // Prints system status line (load, command, pid, + // etc). + VDISCARD: 18, // Toggles the flushing of terminal output. + IGNPAR: 30, // The ignore parity flag. The parameter SHOULD be 0 + // if this flag is FALSE, and 1 if it is TRUE. + PARMRK: 31, // Mark parity and framing errors. + INPCK: 32, // Enable checking of parity errors. + ISTRIP: 33, // Strip 8th bit off characters. + INLCR: 34, // Map NL into CR on input. + IGNCR: 35, // Ignore CR on input. + ICRNL: 36, // Map CR to NL on input. + IUCLC: 37, // Translate uppercase characters to lowercase. + IXON: 38, // Enable output flow control. + IXANY: 39, // Any char will restart after stop. + IXOFF: 40, // Enable input flow control. + IMAXBEL: 41, // Ring bell on input queue full. + ISIG: 50, // Enable signals INTR, QUIT, [D]SUSP. + ICANON: 51, // Canonicalize input lines. + XCASE: 52, // Enable input and output of uppercase characters by + // preceding their lowercase equivalents with "\". + ECHO: 53, // Enable echoing. + ECHOE: 54, // Visually erase chars. + ECHOK: 55, // Kill character discards current line. + ECHONL: 56, // Echo NL even if ECHO is off. + NOFLSH: 57, // Don't flush after interrupt. + TOSTOP: 58, // Stop background jobs from output. + IEXTEN: 59, // Enable extensions. + ECHOCTL: 60, // Echo control characters as ^(Char). + ECHOKE: 61, // Visual erase for line kill. + PENDIN: 62, // Retype pending input. + OPOST: 70, // Enable output processing. + OLCUC: 71, // Convert lowercase to uppercase. + ONLCR: 72, // Map NL to CR-NL. + OCRNL: 73, // Translate carriage return to newline (output). + ONOCR: 74, // Translate newline to carriage return-newline + // (output). + ONLRET: 75, // Newline performs a carriage return (output). + CS7: 90, // 7 bit mode. + CS8: 91, // 8 bit mode. + PARENB: 92, // Parity enable. + PARODD: 93, // Odd parity, else even. + TTY_OP_ISPEED: 128, // Specifies the input baud rate in bits per second. + TTY_OP_OSPEED: 129, // Specifies the output baud rate in bits per second. + }, + CHANNEL_EXTENDED_DATATYPE: { + STDERR: 1, + }, + + SIGNALS: [ + 'ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT', 'QUIT', 'SEGV', 'TERM', 'USR1', + 'USR2', 'KILL', 'PIPE' + ].reduce((cur, val) => ({ ...cur, [val]: 1 }), {}), + + COMPAT, + COMPAT_CHECKS: [ + [ 'Cisco-1.25', COMPAT.BAD_DHGEX ], + [ /^Cisco-1\./, COMPAT.BUG_DHGEX_LARGE ], + [ /^[0-9.]+$/, COMPAT.OLD_EXIT ], // old SSH.com implementations + [ /^OpenSSH_5\.\d+/, COMPAT.DYN_RPORT_BUG ], + ], + + // KEX proposal-related + DEFAULT_KEX, + SUPPORTED_KEX, + DEFAULT_SERVER_HOST_KEY, + SUPPORTED_SERVER_HOST_KEY, + DEFAULT_CIPHER, + SUPPORTED_CIPHER, + DEFAULT_MAC, + SUPPORTED_MAC, + DEFAULT_COMPRESSION, + SUPPORTED_COMPRESSION, + + curve25519Supported, + eddsaSupported, +}; + +module.exports.DISCONNECT_REASON_BY_VALUE = + Array.from(Object.entries(module.exports.DISCONNECT_REASON)) + .reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {}); diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto.js b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto.js new file mode 100644 index 0000000..b4c3ecb --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto.js @@ -0,0 +1,1607 @@ +// TODO: +// * make max packet size configurable +// * if decompression is enabled, use `._packet` in decipher instances as +// input to (sync) zlib inflater with appropriate offset and length to +// avoid an additional copy of payload data before inflation +// * factor decompression status into packet length checks +'use strict'; + +const { + createCipheriv, createDecipheriv, createHmac, randomFillSync, timingSafeEqual +} = require('crypto'); + +const { readUInt32BE, writeUInt32BE } = require('./utils.js'); + +const FastBuffer = Buffer[Symbol.species]; +const MAX_SEQNO = 2 ** 32 - 1; +const EMPTY_BUFFER = Buffer.alloc(0); +const BUF_INT = Buffer.alloc(4); +const DISCARD_CACHE = new Map(); +const MAX_PACKET_SIZE = 35000; + +let binding; +let AESGCMCipher; +let ChaChaPolyCipher; +let GenericCipher; +let AESGCMDecipher; +let ChaChaPolyDecipher; +let GenericDecipher; +try { + binding = require('./crypto/build/Release/sshcrypto.node'); + ({ AESGCMCipher, ChaChaPolyCipher, GenericCipher, + AESGCMDecipher, ChaChaPolyDecipher, GenericDecipher } = binding); +} catch {} + +const CIPHER_STREAM = 1 << 0; +const CIPHER_INFO = (() => { + function info(sslName, blockLen, keyLen, ivLen, authLen, discardLen, flags) { + return { + sslName, + blockLen, + keyLen, + ivLen: (ivLen !== 0 || (flags & CIPHER_STREAM) + ? ivLen + : blockLen), + authLen, + discardLen, + stream: !!(flags & CIPHER_STREAM), + }; + } + + return { + 'chacha20-poly1305@openssh.com': + info('chacha20', 8, 64, 0, 16, 0, CIPHER_STREAM), + + 'aes128-gcm': info('aes-128-gcm', 16, 16, 12, 16, 0, CIPHER_STREAM), + 'aes256-gcm': info('aes-256-gcm', 16, 32, 12, 16, 0, CIPHER_STREAM), + 'aes128-gcm@openssh.com': + info('aes-128-gcm', 16, 16, 12, 16, 0, CIPHER_STREAM), + 'aes256-gcm@openssh.com': + info('aes-256-gcm', 16, 32, 12, 16, 0, CIPHER_STREAM), + + 'aes128-cbc': info('aes-128-cbc', 16, 16, 0, 0, 0, 0), + 'aes192-cbc': info('aes-192-cbc', 16, 24, 0, 0, 0, 0), + 'aes256-cbc': info('aes-256-cbc', 16, 32, 0, 0, 0, 0), + 'rijndael-cbc@lysator.liu.se': info('aes-256-cbc', 16, 32, 0, 0, 0, 0), + '3des-cbc': info('des-ede3-cbc', 8, 24, 0, 0, 0, 0), + 'blowfish-cbc': info('bf-cbc', 8, 16, 0, 0, 0, 0), + 'idea-cbc': info('idea-cbc', 8, 16, 0, 0, 0, 0), + 'cast128-cbc': info('cast-cbc', 8, 16, 0, 0, 0, 0), + + 'aes128-ctr': info('aes-128-ctr', 16, 16, 16, 0, 0, CIPHER_STREAM), + 'aes192-ctr': info('aes-192-ctr', 16, 24, 16, 0, 0, CIPHER_STREAM), + 'aes256-ctr': info('aes-256-ctr', 16, 32, 16, 0, 0, CIPHER_STREAM), + '3des-ctr': info('des-ede3', 8, 24, 8, 0, 0, CIPHER_STREAM), + 'blowfish-ctr': info('bf-ecb', 8, 16, 8, 0, 0, CIPHER_STREAM), + 'cast128-ctr': info('cast5-ecb', 8, 16, 8, 0, 0, CIPHER_STREAM), + + /* The "arcfour128" algorithm is the RC4 cipher, as described in + [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream + generated by the cipher MUST be discarded, and the first byte of the + first encrypted packet MUST be encrypted using the 1537th byte of + keystream. + + -- http://tools.ietf.org/html/rfc4345#section-4 */ + 'arcfour': info('rc4', 8, 16, 0, 0, 1536, CIPHER_STREAM), + 'arcfour128': info('rc4', 8, 16, 0, 0, 1536, CIPHER_STREAM), + 'arcfour256': info('rc4', 8, 32, 0, 0, 1536, CIPHER_STREAM), + 'arcfour512': info('rc4', 8, 64, 0, 0, 1536, CIPHER_STREAM), + }; +})(); + +const MAC_INFO = (() => { + function info(sslName, len, actualLen, isETM) { + return { + sslName, + len, + actualLen, + isETM, + }; + } + + return { + 'hmac-md5': info('md5', 16, 16, false), + 'hmac-md5-96': info('md5', 16, 12, false), + 'hmac-ripemd160': info('ripemd160', 20, 20, false), + 'hmac-sha1': info('sha1', 20, 20, false), + 'hmac-sha1-etm@openssh.com': info('sha1', 20, 20, true), + 'hmac-sha1-96': info('sha1', 20, 12, false), + 'hmac-sha2-256': info('sha256', 32, 32, false), + 'hmac-sha2-256-etm@openssh.com': info('sha256', 32, 32, true), + 'hmac-sha2-256-96': info('sha256', 32, 12, false), + 'hmac-sha2-512': info('sha512', 64, 64, false), + 'hmac-sha2-512-etm@openssh.com': info('sha512', 64, 64, true), + 'hmac-sha2-512-96': info('sha512', 64, 12, false), + }; +})(); + + +// Should only_be used during the initial handshake +class NullCipher { + constructor(seqno, onWrite) { + this.outSeqno = seqno; + this._onWrite = onWrite; + this._dead = false; + } + free() { + this._dead = true; + } + allocPacket(payloadLen) { + let pktLen = 4 + 1 + payloadLen; + let padLen = 8 - (pktLen & (8 - 1)); + if (padLen < 4) + padLen += 8; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + this._onWrite(packet); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + + +const POLY1305_ZEROS = Buffer.alloc(32); +const POLY1305_OUT_COMPUTE = Buffer.alloc(16); +let POLY1305_WASM_MODULE; +let POLY1305_RESULT_MALLOC; +let poly1305_auth; +class ChaChaPolyCipherNative { + constructor(config) { + const enc = config.outbound; + this.outSeqno = enc.seqno; + this._onWrite = enc.onWrite; + this._encKeyMain = enc.cipherKey.slice(0, 32); + this._encKeyPktLen = enc.cipherKey.slice(32); + this._dead = false; + } + free() { + this._dead = true; + } + allocPacket(payloadLen) { + let pktLen = 4 + 1 + payloadLen; + let padLen = 8 - ((pktLen - 4) & (8 - 1)); + if (padLen < 4) + padLen += 8; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + // Generate Poly1305 key + POLY1305_OUT_COMPUTE[0] = 0; // Set counter to 0 (little endian) + writeUInt32BE(POLY1305_OUT_COMPUTE, this.outSeqno, 12); + const polyKey = + createCipheriv('chacha20', this._encKeyMain, POLY1305_OUT_COMPUTE) + .update(POLY1305_ZEROS); + + // Encrypt packet length + const pktLenEnc = + createCipheriv('chacha20', this._encKeyPktLen, POLY1305_OUT_COMPUTE) + .update(packet.slice(0, 4)); + this._onWrite(pktLenEnc); + + // Encrypt rest of packet + POLY1305_OUT_COMPUTE[0] = 1; // Set counter to 1 (little endian) + const payloadEnc = + createCipheriv('chacha20', this._encKeyMain, POLY1305_OUT_COMPUTE) + .update(packet.slice(4)); + this._onWrite(payloadEnc); + + // Calculate Poly1305 MAC + poly1305_auth(POLY1305_RESULT_MALLOC, + pktLenEnc, + pktLenEnc.length, + payloadEnc, + payloadEnc.length, + polyKey); + const mac = Buffer.allocUnsafe(16); + mac.set( + new Uint8Array(POLY1305_WASM_MODULE.HEAPU8.buffer, + POLY1305_RESULT_MALLOC, + 16), + 0 + ); + this._onWrite(mac); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + +class ChaChaPolyCipherBinding { + constructor(config) { + const enc = config.outbound; + this.outSeqno = enc.seqno; + this._onWrite = enc.onWrite; + this._instance = new ChaChaPolyCipher(enc.cipherKey); + this._dead = false; + } + free() { + this._dead = true; + this._instance.free(); + } + allocPacket(payloadLen) { + let pktLen = 4 + 1 + payloadLen; + let padLen = 8 - ((pktLen - 4) & (8 - 1)); + if (padLen < 4) + padLen += 8; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen + 16/* MAC */); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + // Encrypts in-place + this._instance.encrypt(packet, this.outSeqno); + + this._onWrite(packet); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + + +class AESGCMCipherNative { + constructor(config) { + const enc = config.outbound; + this.outSeqno = enc.seqno; + this._onWrite = enc.onWrite; + this._encSSLName = enc.cipherInfo.sslName; + this._encKey = enc.cipherKey; + this._encIV = enc.cipherIV; + this._dead = false; + } + free() { + this._dead = true; + } + allocPacket(payloadLen) { + let pktLen = 4 + 1 + payloadLen; + let padLen = 16 - ((pktLen - 4) & (16 - 1)); + if (padLen < 4) + padLen += 16; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + const cipher = createCipheriv(this._encSSLName, this._encKey, this._encIV); + cipher.setAutoPadding(false); + + const lenData = packet.slice(0, 4); + cipher.setAAD(lenData); + this._onWrite(lenData); + + // Encrypt pad length, payload, and padding + const encrypted = cipher.update(packet.slice(4)); + this._onWrite(encrypted); + const final = cipher.final(); + // XXX: final.length === 0 always? + if (final.length) + this._onWrite(final); + + // Generate MAC + const tag = cipher.getAuthTag(); + this._onWrite(tag); + + // Increment counter in IV by 1 for next packet + ivIncrement(this._encIV); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + +class AESGCMCipherBinding { + constructor(config) { + const enc = config.outbound; + this.outSeqno = enc.seqno; + this._onWrite = enc.onWrite; + this._instance = new AESGCMCipher(enc.cipherInfo.sslName, + enc.cipherKey, + enc.cipherIV); + this._dead = false; + } + free() { + this._dead = true; + this._instance.free(); + } + allocPacket(payloadLen) { + let pktLen = 4 + 1 + payloadLen; + let padLen = 16 - ((pktLen - 4) & (16 - 1)); + if (padLen < 4) + padLen += 16; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen + 16/* authTag */); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + // Encrypts in-place + this._instance.encrypt(packet); + + this._onWrite(packet); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + + +class GenericCipherNative { + constructor(config) { + const enc = config.outbound; + this.outSeqno = enc.seqno; + this._onWrite = enc.onWrite; + this._encBlockLen = enc.cipherInfo.blockLen; + this._cipherInstance = createCipheriv(enc.cipherInfo.sslName, + enc.cipherKey, + enc.cipherIV); + this._macSSLName = enc.macInfo.sslName; + this._macKey = enc.macKey; + this._macActualLen = enc.macInfo.actualLen; + this._macETM = enc.macInfo.isETM; + this._aadLen = (this._macETM ? 4 : 0); + this._dead = false; + + const discardLen = enc.cipherInfo.discardLen; + if (discardLen) { + let discard = DISCARD_CACHE.get(discardLen); + if (discard === undefined) { + discard = Buffer.alloc(discardLen); + DISCARD_CACHE.set(discardLen, discard); + } + this._cipherInstance.update(discard); + } + } + free() { + this._dead = true; + } + allocPacket(payloadLen) { + const blockLen = this._encBlockLen; + + let pktLen = 4 + 1 + payloadLen; + let padLen = blockLen - ((pktLen - this._aadLen) & (blockLen - 1)); + if (padLen < 4) + padLen += blockLen; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + let mac; + if (this._macETM) { + // Encrypt pad length, payload, and padding + const lenBytes = new Uint8Array(packet.buffer, packet.byteOffset, 4); + const encrypted = this._cipherInstance.update( + new Uint8Array(packet.buffer, + packet.byteOffset + 4, + packet.length - 4) + ); + + this._onWrite(lenBytes); + this._onWrite(encrypted); + + // TODO: look into storing seqno as 4-byte buffer and incrementing like we + // do for AES-GCM IVs to avoid having to (re)write all 4 bytes every time + mac = createHmac(this._macSSLName, this._macKey); + writeUInt32BE(BUF_INT, this.outSeqno, 0); + mac.update(BUF_INT); + mac.update(lenBytes); + mac.update(encrypted); + } else { + // Encrypt length field, pad length, payload, and padding + const encrypted = this._cipherInstance.update(packet); + this._onWrite(encrypted); + + // TODO: look into storing seqno as 4-byte buffer and incrementing like we + // do for AES-GCM IVs to avoid having to (re)write all 4 bytes every time + mac = createHmac(this._macSSLName, this._macKey); + writeUInt32BE(BUF_INT, this.outSeqno, 0); + mac.update(BUF_INT); + mac.update(packet); + } + + let digest = mac.digest(); + if (digest.length > this._macActualLen) + digest = digest.slice(0, this._macActualLen); + this._onWrite(digest); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + +class GenericCipherBinding { + constructor(config) { + const enc = config.outbound; + this.outSeqno = enc.seqno; + this._onWrite = enc.onWrite; + this._encBlockLen = enc.cipherInfo.blockLen; + this._macLen = enc.macInfo.len; + this._macActualLen = enc.macInfo.actualLen; + this._aadLen = (enc.macInfo.isETM ? 4 : 0); + this._instance = new GenericCipher(enc.cipherInfo.sslName, + enc.cipherKey, + enc.cipherIV, + enc.macInfo.sslName, + enc.macKey, + enc.macInfo.isETM); + this._dead = false; + } + free() { + this._dead = true; + this._instance.free(); + } + allocPacket(payloadLen) { + const blockLen = this._encBlockLen; + + let pktLen = 4 + 1 + payloadLen; + let padLen = blockLen - ((pktLen - this._aadLen) & (blockLen - 1)); + if (padLen < 4) + padLen += blockLen; + pktLen += padLen; + + const packet = Buffer.allocUnsafe(pktLen + this._macLen); + + writeUInt32BE(packet, pktLen - 4, 0); + packet[4] = padLen; + + randomFillSync(packet, 5 + payloadLen, padLen); + + return packet; + } + encrypt(packet) { + // `packet` === unencrypted packet + + if (this._dead) + return; + + // Encrypts in-place + this._instance.encrypt(packet, this.outSeqno); + + if (this._macActualLen < this._macLen) { + packet = new FastBuffer(packet.buffer, + packet.byteOffset, + (packet.length + - (this._macLen - this._macActualLen))); + } + this._onWrite(packet); + + this.outSeqno = (this.outSeqno + 1) >>> 0; + } +} + + +class NullDecipher { + constructor(seqno, onPayload) { + this.inSeqno = seqno; + this._onPayload = onPayload; + this._len = 0; + this._lenBytes = 0; + this._packet = null; + this._packetPos = 0; + } + free() {} + decrypt(data, p, dataLen) { + while (p < dataLen) { + // Read packet length + if (this._lenBytes < 4) { + let nb = Math.min(4 - this._lenBytes, dataLen - p); + + this._lenBytes += nb; + while (nb--) + this._len = (this._len << 8) + data[p++]; + + if (this._lenBytes < 4) + return; + + if (this._len > MAX_PACKET_SIZE + || this._len < 8 + || (4 + this._len & 7) !== 0) { + throw new Error('Bad packet length'); + } + if (p >= dataLen) + return; + } + + // Read padding length, payload, and padding + if (this._packetPos < this._len) { + const nb = Math.min(this._len - this._packetPos, dataLen - p); + if (p !== 0 || nb !== dataLen) { + if (nb === this._len) { + this._packet = new FastBuffer(data.buffer, data.byteOffset + p, nb); + } else { + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._packetPos + ); + } + } else if (nb === this._len) { + this._packet = data; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(data, this._packetPos); + } + p += nb; + this._packetPos += nb; + if (this._packetPos < this._len) + return; + } + + const payload = (!this._packet + ? EMPTY_BUFFER + : new FastBuffer(this._packet.buffer, + this._packet.byteOffset + 1, + this._packet.length + - this._packet[0] - 1)); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + this._len = 0; + this._lenBytes = 0; + this._packet = null; + this._packetPos = 0; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +class ChaChaPolyDecipherNative { + constructor(config) { + const dec = config.inbound; + this.inSeqno = dec.seqno; + this._onPayload = dec.onPayload; + this._decKeyMain = dec.decipherKey.slice(0, 32); + this._decKeyPktLen = dec.decipherKey.slice(32); + this._len = 0; + this._lenBuf = Buffer.alloc(4); + this._lenPos = 0; + this._packet = null; + this._pktLen = 0; + this._mac = Buffer.allocUnsafe(16); + this._calcMac = Buffer.allocUnsafe(16); + this._macPos = 0; + } + free() {} + decrypt(data, p, dataLen) { + // `data` === encrypted data + + while (p < dataLen) { + // Read packet length + if (this._lenPos < 4) { + let nb = Math.min(4 - this._lenPos, dataLen - p); + while (nb--) + this._lenBuf[this._lenPos++] = data[p++]; + if (this._lenPos < 4) + return; + + POLY1305_OUT_COMPUTE[0] = 0; // Set counter to 0 (little endian) + writeUInt32BE(POLY1305_OUT_COMPUTE, this.inSeqno, 12); + + const decLenBytes = + createDecipheriv('chacha20', this._decKeyPktLen, POLY1305_OUT_COMPUTE) + .update(this._lenBuf); + this._len = readUInt32BE(decLenBytes, 0); + + if (this._len > MAX_PACKET_SIZE + || this._len < 8 + || (this._len & 7) !== 0) { + throw new Error('Bad packet length'); + } + } + + // Read padding length, payload, and padding + if (this._pktLen < this._len) { + if (p >= dataLen) + return; + const nb = Math.min(this._len - this._pktLen, dataLen - p); + let encrypted; + if (p !== 0 || nb !== dataLen) + encrypted = new Uint8Array(data.buffer, data.byteOffset + p, nb); + else + encrypted = data; + if (nb === this._len) { + this._packet = encrypted; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(encrypted, this._pktLen); + } + p += nb; + this._pktLen += nb; + if (this._pktLen < this._len || p >= dataLen) + return; + } + + // Read Poly1305 MAC + { + const nb = Math.min(16 - this._macPos, dataLen - p); + // TODO: avoid copying if entire MAC is in current chunk + if (p !== 0 || nb !== dataLen) { + this._mac.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._macPos + ); + } else { + this._mac.set(data, this._macPos); + } + p += nb; + this._macPos += nb; + if (this._macPos < 16) + return; + } + + // Generate Poly1305 key + POLY1305_OUT_COMPUTE[0] = 0; // Set counter to 0 (little endian) + writeUInt32BE(POLY1305_OUT_COMPUTE, this.inSeqno, 12); + const polyKey = + createCipheriv('chacha20', this._decKeyMain, POLY1305_OUT_COMPUTE) + .update(POLY1305_ZEROS); + + // Calculate and compare Poly1305 MACs + poly1305_auth(POLY1305_RESULT_MALLOC, + this._lenBuf, + 4, + this._packet, + this._packet.length, + polyKey); + + this._calcMac.set( + new Uint8Array(POLY1305_WASM_MODULE.HEAPU8.buffer, + POLY1305_RESULT_MALLOC, + 16), + 0 + ); + if (!timingSafeEqual(this._calcMac, this._mac)) + throw new Error('Invalid MAC'); + + // Decrypt packet + POLY1305_OUT_COMPUTE[0] = 1; // Set counter to 1 (little endian) + const packet = + createDecipheriv('chacha20', this._decKeyMain, POLY1305_OUT_COMPUTE) + .update(this._packet); + + const payload = new FastBuffer(packet.buffer, + packet.byteOffset + 1, + packet.length - packet[0] - 1); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + this._len = 0; + this._lenPos = 0; + this._packet = null; + this._pktLen = 0; + this._macPos = 0; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +class ChaChaPolyDecipherBinding { + constructor(config) { + const dec = config.inbound; + this.inSeqno = dec.seqno; + this._onPayload = dec.onPayload; + this._instance = new ChaChaPolyDecipher(dec.decipherKey); + this._len = 0; + this._lenBuf = Buffer.alloc(4); + this._lenPos = 0; + this._packet = null; + this._pktLen = 0; + this._mac = Buffer.allocUnsafe(16); + this._macPos = 0; + } + free() { + this._instance.free(); + } + decrypt(data, p, dataLen) { + // `data` === encrypted data + + while (p < dataLen) { + // Read packet length + if (this._lenPos < 4) { + let nb = Math.min(4 - this._lenPos, dataLen - p); + while (nb--) + this._lenBuf[this._lenPos++] = data[p++]; + if (this._lenPos < 4) + return; + + this._len = this._instance.decryptLen(this._lenBuf, this.inSeqno); + + if (this._len > MAX_PACKET_SIZE + || this._len < 8 + || (this._len & 7) !== 0) { + throw new Error('Bad packet length'); + } + + if (p >= dataLen) + return; + } + + // Read padding length, payload, and padding + if (this._pktLen < this._len) { + const nb = Math.min(this._len - this._pktLen, dataLen - p); + let encrypted; + if (p !== 0 || nb !== dataLen) + encrypted = new Uint8Array(data.buffer, data.byteOffset + p, nb); + else + encrypted = data; + if (nb === this._len) { + this._packet = encrypted; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(encrypted, this._pktLen); + } + p += nb; + this._pktLen += nb; + if (this._pktLen < this._len || p >= dataLen) + return; + } + + // Read Poly1305 MAC + { + const nb = Math.min(16 - this._macPos, dataLen - p); + // TODO: avoid copying if entire MAC is in current chunk + if (p !== 0 || nb !== dataLen) { + this._mac.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._macPos + ); + } else { + this._mac.set(data, this._macPos); + } + p += nb; + this._macPos += nb; + if (this._macPos < 16) + return; + } + + this._instance.decrypt(this._packet, this._mac, this.inSeqno); + + const payload = new FastBuffer(this._packet.buffer, + this._packet.byteOffset + 1, + this._packet.length - this._packet[0] - 1); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + this._len = 0; + this._lenPos = 0; + this._packet = null; + this._pktLen = 0; + this._macPos = 0; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +class AESGCMDecipherNative { + constructor(config) { + const dec = config.inbound; + this.inSeqno = dec.seqno; + this._onPayload = dec.onPayload; + this._decipherInstance = null; + this._decipherSSLName = dec.decipherInfo.sslName; + this._decipherKey = dec.decipherKey; + this._decipherIV = dec.decipherIV; + this._len = 0; + this._lenBytes = 0; + this._packet = null; + this._packetPos = 0; + this._pktLen = 0; + this._tag = Buffer.allocUnsafe(16); + this._tagPos = 0; + } + free() {} + decrypt(data, p, dataLen) { + // `data` === encrypted data + + while (p < dataLen) { + // Read packet length (unencrypted, but AAD) + if (this._lenBytes < 4) { + let nb = Math.min(4 - this._lenBytes, dataLen - p); + this._lenBytes += nb; + while (nb--) + this._len = (this._len << 8) + data[p++]; + if (this._lenBytes < 4) + return; + + if ((this._len + 20) > MAX_PACKET_SIZE + || this._len < 16 + || (this._len & 15) !== 0) { + throw new Error('Bad packet length'); + } + + this._decipherInstance = createDecipheriv( + this._decipherSSLName, + this._decipherKey, + this._decipherIV + ); + this._decipherInstance.setAutoPadding(false); + this._decipherInstance.setAAD(intToBytes(this._len)); + } + + // Read padding length, payload, and padding + if (this._pktLen < this._len) { + if (p >= dataLen) + return; + const nb = Math.min(this._len - this._pktLen, dataLen - p); + let decrypted; + if (p !== 0 || nb !== dataLen) { + decrypted = this._decipherInstance.update( + new Uint8Array(data.buffer, data.byteOffset + p, nb) + ); + } else { + decrypted = this._decipherInstance.update(data); + } + if (decrypted.length) { + if (nb === this._len) { + this._packet = decrypted; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(decrypted, this._packetPos); + } + this._packetPos += decrypted.length; + } + p += nb; + this._pktLen += nb; + if (this._pktLen < this._len || p >= dataLen) + return; + } + + // Read authentication tag + { + const nb = Math.min(16 - this._tagPos, dataLen - p); + if (p !== 0 || nb !== dataLen) { + this._tag.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._tagPos + ); + } else { + this._tag.set(data, this._tagPos); + } + p += nb; + this._tagPos += nb; + if (this._tagPos < 16) + return; + } + + { + // Verify authentication tag + this._decipherInstance.setAuthTag(this._tag); + + const decrypted = this._decipherInstance.final(); + + // XXX: this should never output any data since stream ciphers always + // return data from .update() and block ciphers must end on a multiple + // of the block length, which would have caused an exception to be + // thrown if the total input was not... + if (decrypted.length) { + if (this._packet) + this._packet.set(decrypted, this._packetPos); + else + this._packet = decrypted; + } + } + + const payload = (!this._packet + ? EMPTY_BUFFER + : new FastBuffer(this._packet.buffer, + this._packet.byteOffset + 1, + this._packet.length + - this._packet[0] - 1)); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + ivIncrement(this._decipherIV); + this._len = 0; + this._lenBytes = 0; + this._packet = null; + this._packetPos = 0; + this._pktLen = 0; + this._tagPos = 0; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +class AESGCMDecipherBinding { + constructor(config) { + const dec = config.inbound; + this.inSeqno = dec.seqno; + this._onPayload = dec.onPayload; + this._instance = new AESGCMDecipher(dec.decipherInfo.sslName, + dec.decipherKey, + dec.decipherIV); + this._len = 0; + this._lenBytes = 0; + this._packet = null; + this._pktLen = 0; + this._tag = Buffer.allocUnsafe(16); + this._tagPos = 0; + } + free() {} + decrypt(data, p, dataLen) { + // `data` === encrypted data + + while (p < dataLen) { + // Read packet length (unencrypted, but AAD) + if (this._lenBytes < 4) { + let nb = Math.min(4 - this._lenBytes, dataLen - p); + this._lenBytes += nb; + while (nb--) + this._len = (this._len << 8) + data[p++]; + if (this._lenBytes < 4) + return; + + if ((this._len + 20) > MAX_PACKET_SIZE + || this._len < 16 + || (this._len & 15) !== 0) { + throw new Error(`Bad packet length: ${this._len}`); + } + } + + // Read padding length, payload, and padding + if (this._pktLen < this._len) { + if (p >= dataLen) + return; + const nb = Math.min(this._len - this._pktLen, dataLen - p); + let encrypted; + if (p !== 0 || nb !== dataLen) + encrypted = new Uint8Array(data.buffer, data.byteOffset + p, nb); + else + encrypted = data; + if (nb === this._len) { + this._packet = encrypted; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(encrypted, this._pktLen); + } + p += nb; + this._pktLen += nb; + if (this._pktLen < this._len || p >= dataLen) + return; + } + + // Read authentication tag + { + const nb = Math.min(16 - this._tagPos, dataLen - p); + if (p !== 0 || nb !== dataLen) { + this._tag.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._tagPos + ); + } else { + this._tag.set(data, this._tagPos); + } + p += nb; + this._tagPos += nb; + if (this._tagPos < 16) + return; + } + + this._instance.decrypt(this._packet, this._len, this._tag); + + const payload = new FastBuffer(this._packet.buffer, + this._packet.byteOffset + 1, + this._packet.length - this._packet[0] - 1); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + this._len = 0; + this._lenBytes = 0; + this._packet = null; + this._pktLen = 0; + this._tagPos = 0; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +// TODO: test incremental .update()s vs. copying to _packet and doing a single +// .update() after entire packet read -- a single .update() would allow +// verifying MAC before decrypting for ETM MACs +class GenericDecipherNative { + constructor(config) { + const dec = config.inbound; + this.inSeqno = dec.seqno; + this._onPayload = dec.onPayload; + this._decipherInstance = createDecipheriv(dec.decipherInfo.sslName, + dec.decipherKey, + dec.decipherIV); + this._decipherInstance.setAutoPadding(false); + this._block = Buffer.allocUnsafe( + dec.macInfo.isETM ? 4 : dec.decipherInfo.blockLen + ); + this._blockSize = dec.decipherInfo.blockLen; + this._blockPos = 0; + this._len = 0; + this._packet = null; + this._packetPos = 0; + this._pktLen = 0; + this._mac = Buffer.allocUnsafe(dec.macInfo.actualLen); + this._macPos = 0; + this._macSSLName = dec.macInfo.sslName; + this._macKey = dec.macKey; + this._macActualLen = dec.macInfo.actualLen; + this._macETM = dec.macInfo.isETM; + this._macInstance = null; + + const discardLen = dec.decipherInfo.discardLen; + if (discardLen) { + let discard = DISCARD_CACHE.get(discardLen); + if (discard === undefined) { + discard = Buffer.alloc(discardLen); + DISCARD_CACHE.set(discardLen, discard); + } + this._decipherInstance.update(discard); + } + } + free() {} + decrypt(data, p, dataLen) { + // `data` === encrypted data + + while (p < dataLen) { + // Read first encrypted block + if (this._blockPos < this._block.length) { + const nb = Math.min(this._block.length - this._blockPos, dataLen - p); + if (p !== 0 || nb !== dataLen || nb < data.length) { + this._block.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._blockPos + ); + } else { + this._block.set(data, this._blockPos); + } + + p += nb; + this._blockPos += nb; + if (this._blockPos < this._block.length) + return; + + let decrypted; + let need; + if (this._macETM) { + this._len = need = readUInt32BE(this._block, 0); + } else { + // Decrypt first block to get packet length + decrypted = this._decipherInstance.update(this._block); + this._len = readUInt32BE(decrypted, 0); + need = 4 + this._len - this._blockSize; + } + + if (this._len > MAX_PACKET_SIZE + || this._len < 5 + || (need & (this._blockSize - 1)) !== 0) { + throw new Error('Bad packet length'); + } + + // Create MAC up front to calculate in parallel with decryption + this._macInstance = createHmac(this._macSSLName, this._macKey); + + writeUInt32BE(BUF_INT, this.inSeqno, 0); + this._macInstance.update(BUF_INT); + if (this._macETM) { + this._macInstance.update(this._block); + } else { + this._macInstance.update(new Uint8Array(decrypted.buffer, + decrypted.byteOffset, + 4)); + this._pktLen = decrypted.length - 4; + this._packetPos = this._pktLen; + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set( + new Uint8Array(decrypted.buffer, + decrypted.byteOffset + 4, + this._packetPos), + 0 + ); + } + + if (p >= dataLen) + return; + } + + // Read padding length, payload, and padding + if (this._pktLen < this._len) { + const nb = Math.min(this._len - this._pktLen, dataLen - p); + let encrypted; + if (p !== 0 || nb !== dataLen) + encrypted = new Uint8Array(data.buffer, data.byteOffset + p, nb); + else + encrypted = data; + if (this._macETM) + this._macInstance.update(encrypted); + const decrypted = this._decipherInstance.update(encrypted); + if (decrypted.length) { + if (nb === this._len) { + this._packet = decrypted; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(decrypted, this._packetPos); + } + this._packetPos += decrypted.length; + } + p += nb; + this._pktLen += nb; + if (this._pktLen < this._len || p >= dataLen) + return; + } + + // Read MAC + { + const nb = Math.min(this._macActualLen - this._macPos, dataLen - p); + if (p !== 0 || nb !== dataLen) { + this._mac.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._macPos + ); + } else { + this._mac.set(data, this._macPos); + } + p += nb; + this._macPos += nb; + if (this._macPos < this._macActualLen) + return; + } + + // Verify MAC + if (!this._macETM) + this._macInstance.update(this._packet); + let calculated = this._macInstance.digest(); + if (this._macActualLen < calculated.length) { + calculated = new Uint8Array(calculated.buffer, + calculated.byteOffset, + this._macActualLen); + } + if (!timingSafeEquals(calculated, this._mac)) + throw new Error('Invalid MAC'); + + const payload = new FastBuffer(this._packet.buffer, + this._packet.byteOffset + 1, + this._packet.length - this._packet[0] - 1); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + this._blockPos = 0; + this._len = 0; + this._packet = null; + this._packetPos = 0; + this._pktLen = 0; + this._macPos = 0; + this._macInstance = null; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +class GenericDecipherBinding { + constructor(config) { + const dec = config.inbound; + this.inSeqno = dec.seqno; + this._onPayload = dec.onPayload; + this._instance = new GenericDecipher(dec.decipherInfo.sslName, + dec.decipherKey, + dec.decipherIV, + dec.macInfo.sslName, + dec.macKey, + dec.macInfo.isETM, + dec.macInfo.actualLen); + this._block = Buffer.allocUnsafe( + dec.macInfo.isETM || dec.decipherInfo.stream + ? 4 + : dec.decipherInfo.blockLen + ); + this._blockPos = 0; + this._len = 0; + this._packet = null; + this._pktLen = 0; + this._mac = Buffer.allocUnsafe(dec.macInfo.actualLen); + this._macPos = 0; + this._macActualLen = dec.macInfo.actualLen; + this._macETM = dec.macInfo.isETM; + } + free() { + this._instance.free(); + } + decrypt(data, p, dataLen) { + // `data` === encrypted data + + while (p < dataLen) { + // Read first encrypted block + if (this._blockPos < this._block.length) { + const nb = Math.min(this._block.length - this._blockPos, dataLen - p); + if (p !== 0 || nb !== dataLen || nb < data.length) { + this._block.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._blockPos + ); + } else { + this._block.set(data, this._blockPos); + } + + p += nb; + this._blockPos += nb; + if (this._blockPos < this._block.length) + return; + + let need; + if (this._macETM) { + this._len = need = readUInt32BE(this._block, 0); + } else { + // Decrypt first block to get packet length + this._instance.decryptBlock(this._block); + this._len = readUInt32BE(this._block, 0); + need = 4 + this._len - this._block.length; + } + + if (this._len > MAX_PACKET_SIZE + || this._len < 5 + || (need & (this._block.length - 1)) !== 0) { + throw new Error('Bad packet length'); + } + + if (!this._macETM) { + this._pktLen = (this._block.length - 4); + if (this._pktLen) { + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set( + new Uint8Array(this._block.buffer, + this._block.byteOffset + 4, + this._pktLen), + 0 + ); + } + } + + if (p >= dataLen) + return; + } + + // Read padding length, payload, and padding + if (this._pktLen < this._len) { + const nb = Math.min(this._len - this._pktLen, dataLen - p); + let encrypted; + if (p !== 0 || nb !== dataLen) + encrypted = new Uint8Array(data.buffer, data.byteOffset + p, nb); + else + encrypted = data; + if (nb === this._len) { + this._packet = encrypted; + } else { + if (!this._packet) + this._packet = Buffer.allocUnsafe(this._len); + this._packet.set(encrypted, this._pktLen); + } + p += nb; + this._pktLen += nb; + if (this._pktLen < this._len || p >= dataLen) + return; + } + + // Read MAC + { + const nb = Math.min(this._macActualLen - this._macPos, dataLen - p); + if (p !== 0 || nb !== dataLen) { + this._mac.set( + new Uint8Array(data.buffer, data.byteOffset + p, nb), + this._macPos + ); + } else { + this._mac.set(data, this._macPos); + } + p += nb; + this._macPos += nb; + if (this._macPos < this._macActualLen) + return; + } + + // Decrypt and verify MAC + this._instance.decrypt(this._packet, + this.inSeqno, + this._block, + this._mac); + + const payload = new FastBuffer(this._packet.buffer, + this._packet.byteOffset + 1, + this._packet.length - this._packet[0] - 1); + + // Prepare for next packet + this.inSeqno = (this.inSeqno + 1) >>> 0; + this._blockPos = 0; + this._len = 0; + this._packet = null; + this._pktLen = 0; + this._macPos = 0; + this._macInstance = null; + + { + const ret = this._onPayload(payload); + if (ret !== undefined) + return (ret === false ? p : ret); + } + } + } +} + +// Increments unsigned, big endian counter (last 8 bytes) of AES-GCM IV +function ivIncrement(iv) { + // eslint-disable-next-line no-unused-expressions + ++iv[11] >>> 8 + && ++iv[10] >>> 8 + && ++iv[9] >>> 8 + && ++iv[8] >>> 8 + && ++iv[7] >>> 8 + && ++iv[6] >>> 8 + && ++iv[5] >>> 8 + && ++iv[4] >>> 8; +} + +const intToBytes = (() => { + const ret = Buffer.alloc(4); + return (n) => { + ret[0] = (n >>> 24); + ret[1] = (n >>> 16); + ret[2] = (n >>> 8); + ret[3] = n; + return ret; + }; +})(); + +function timingSafeEquals(a, b) { + if (a.length !== b.length) { + timingSafeEqual(a, a); + return false; + } + return timingSafeEqual(a, b); +} + +function createCipher(config) { + if (typeof config !== 'object' || config === null) + throw new Error('Invalid config'); + + if (typeof config.outbound !== 'object' || config.outbound === null) + throw new Error('Invalid outbound'); + + const outbound = config.outbound; + + if (typeof outbound.onWrite !== 'function') + throw new Error('Invalid outbound.onWrite'); + + if (typeof outbound.cipherInfo !== 'object' || outbound.cipherInfo === null) + throw new Error('Invalid outbound.cipherInfo'); + + if (!Buffer.isBuffer(outbound.cipherKey) + || outbound.cipherKey.length !== outbound.cipherInfo.keyLen) { + throw new Error('Invalid outbound.cipherKey'); + } + + if (outbound.cipherInfo.ivLen + && (!Buffer.isBuffer(outbound.cipherIV) + || outbound.cipherIV.length !== outbound.cipherInfo.ivLen)) { + throw new Error('Invalid outbound.cipherIV'); + } + + if (typeof outbound.seqno !== 'number' + || outbound.seqno < 0 + || outbound.seqno > MAX_SEQNO) { + throw new Error('Invalid outbound.seqno'); + } + + const forceNative = !!outbound.forceNative; + + switch (outbound.cipherInfo.sslName) { + case 'aes-128-gcm': + case 'aes-256-gcm': + return (AESGCMCipher && !forceNative + ? new AESGCMCipherBinding(config) + : new AESGCMCipherNative(config)); + case 'chacha20': + return (ChaChaPolyCipher && !forceNative + ? new ChaChaPolyCipherBinding(config) + : new ChaChaPolyCipherNative(config)); + default: { + if (typeof outbound.macInfo !== 'object' || outbound.macInfo === null) + throw new Error('Invalid outbound.macInfo'); + if (!Buffer.isBuffer(outbound.macKey) + || outbound.macKey.length !== outbound.macInfo.len) { + throw new Error('Invalid outbound.macKey'); + } + return (GenericCipher && !forceNative + ? new GenericCipherBinding(config) + : new GenericCipherNative(config)); + } + } +} + +function createDecipher(config) { + if (typeof config !== 'object' || config === null) + throw new Error('Invalid config'); + + if (typeof config.inbound !== 'object' || config.inbound === null) + throw new Error('Invalid inbound'); + + const inbound = config.inbound; + + if (typeof inbound.onPayload !== 'function') + throw new Error('Invalid inbound.onPayload'); + + if (typeof inbound.decipherInfo !== 'object' + || inbound.decipherInfo === null) { + throw new Error('Invalid inbound.decipherInfo'); + } + + if (!Buffer.isBuffer(inbound.decipherKey) + || inbound.decipherKey.length !== inbound.decipherInfo.keyLen) { + throw new Error('Invalid inbound.decipherKey'); + } + + if (inbound.decipherInfo.ivLen + && (!Buffer.isBuffer(inbound.decipherIV) + || inbound.decipherIV.length !== inbound.decipherInfo.ivLen)) { + throw new Error('Invalid inbound.decipherIV'); + } + + if (typeof inbound.seqno !== 'number' + || inbound.seqno < 0 + || inbound.seqno > MAX_SEQNO) { + throw new Error('Invalid inbound.seqno'); + } + + const forceNative = !!inbound.forceNative; + + switch (inbound.decipherInfo.sslName) { + case 'aes-128-gcm': + case 'aes-256-gcm': + return (AESGCMDecipher && !forceNative + ? new AESGCMDecipherBinding(config) + : new AESGCMDecipherNative(config)); + case 'chacha20': + return (ChaChaPolyDecipher && !forceNative + ? new ChaChaPolyDecipherBinding(config) + : new ChaChaPolyDecipherNative(config)); + default: { + if (typeof inbound.macInfo !== 'object' || inbound.macInfo === null) + throw new Error('Invalid inbound.macInfo'); + if (!Buffer.isBuffer(inbound.macKey) + || inbound.macKey.length !== inbound.macInfo.len) { + throw new Error('Invalid inbound.macKey'); + } + return (GenericDecipher && !forceNative + ? new GenericDecipherBinding(config) + : new GenericDecipherNative(config)); + } + } +} + +module.exports = { + CIPHER_INFO, + MAC_INFO, + bindingAvailable: !!binding, + init: (() => { + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + POLY1305_WASM_MODULE = await require('./crypto/poly1305.js')(); + POLY1305_RESULT_MALLOC = POLY1305_WASM_MODULE._malloc(16); + poly1305_auth = POLY1305_WASM_MODULE.cwrap( + 'poly1305_auth', + null, + ['number', 'array', 'number', 'array', 'number', 'array'] + ); + } catch (ex) { + return reject(ex); + } + resolve(); + }); + })(), + + NullCipher, + createCipher, + NullDecipher, + createDecipher, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/binding.gyp b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/binding.gyp new file mode 100644 index 0000000..29c3282 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/binding.gyp @@ -0,0 +1,14 @@ +{ + 'targets': [ + { + 'target_name': 'sshcrypto', + 'include_dirs': [ + "> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" + +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 1,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,sshcrypto.target.mk)))),) + include sshcrypto.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = cd $(srcdir); /usr/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/config.gypi -I/usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/home/vitalii/.cache/node-gyp/14.17.6/include/node/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/home/vitalii/.cache/node-gyp/14.17.6" "-Dnode_gyp_dir=/usr/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/home/vitalii/.cache/node-gyp/14.17.6/<(target_arch)/node.lib" "-Dmodule_root_dir=/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/ssh2/lib/protocol/crypto" "-Dnode_engine=v8" binding.gyp +Makefile: $(srcdir)/../../../../../../../../../.cache/node-gyp/14.17.6/include/node/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../../../../../../usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto.node.d b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto.node.d new file mode 100644 index 0000000..320d7f9 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto.node.d @@ -0,0 +1 @@ +cmd_Release/obj.target/sshcrypto.node := g++ -shared -pthread -rdynamic -m64 -Wl,-soname=sshcrypto.node -o Release/obj.target/sshcrypto.node -Wl,--start-group Release/obj.target/sshcrypto/src/binding.o -Wl,--end-group diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d new file mode 100644 index 0000000..2c2990d --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d @@ -0,0 +1,117 @@ +cmd_Release/obj.target/sshcrypto/src/binding.o := g++ '-DNODE_GYP_MODULE_NAME=sshcrypto' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D__STDC_FORMAT_MACROS' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DBUILDING_NODE_EXTENSION' -I/home/vitalii/.cache/node-gyp/14.17.6/include/node -I/home/vitalii/.cache/node-gyp/14.17.6/src -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/config -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/openssl/include -I/home/vitalii/.cache/node-gyp/14.17.6/deps/uv/include -I/home/vitalii/.cache/node-gyp/14.17.6/deps/zlib -I/home/vitalii/.cache/node-gyp/14.17.6/deps/v8/include -I../../../../../nan -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -O3 -fno-omit-frame-pointer -fno-rtti -fno-exceptions -std=gnu++1y -MMD -MF ./Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d.raw -c -o Release/obj.target/sshcrypto/src/binding.o ../src/binding.cc +Release/obj.target/sshcrypto/src/binding.o: ../src/binding.cc \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/cppgc/common.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-internal.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-platform.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_buffer.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h \ + ../../../../../nan/nan.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/errno.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/version.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/unix.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/threadpool.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/linux.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/node_object_wrap.h \ + ../../../../../nan/nan_callbacks.h \ + ../../../../../nan/nan_callbacks_12_inl.h \ + ../../../../../nan/nan_maybe_43_inl.h \ + ../../../../../nan/nan_converters.h \ + ../../../../../nan/nan_converters_43_inl.h ../../../../../nan/nan_new.h \ + ../../../../../nan/nan_implementation_12_inl.h \ + ../../../../../nan/nan_persistent_12_inl.h ../../../../../nan/nan_weak.h \ + ../../../../../nan/nan_object_wrap.h ../../../../../nan/nan_private.h \ + ../../../../../nan/nan_typedarray_contents.h \ + ../../../../../nan/nan_json.h ../../../../../nan/nan_scriptorigin.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/err.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/e_os2.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/opensslconf.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/./opensslconf_asm.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/././archs/linux-x86_64/asm/include/openssl/opensslconf.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/opensslv.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/ossl_typ.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bio.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/crypto.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/safestack.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/stack.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/cryptoerr.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/symhacks.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bioerr.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/lhash.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/evp.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/evperr.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/objects.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/obj_mac.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/asn1.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/asn1err.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bn.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bnerr.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/objectserr.h \ + /home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/hmac.h +../src/binding.cc: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/cppgc/common.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-internal.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8config.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/v8-platform.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_buffer.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node.h: +../../../../../nan/nan.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/errno.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/version.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/unix.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/threadpool.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/uv/linux.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/node_object_wrap.h: +../../../../../nan/nan_callbacks.h: +../../../../../nan/nan_callbacks_12_inl.h: +../../../../../nan/nan_maybe_43_inl.h: +../../../../../nan/nan_converters.h: +../../../../../nan/nan_converters_43_inl.h: +../../../../../nan/nan_new.h: +../../../../../nan/nan_implementation_12_inl.h: +../../../../../nan/nan_persistent_12_inl.h: +../../../../../nan/nan_weak.h: +../../../../../nan/nan_object_wrap.h: +../../../../../nan/nan_private.h: +../../../../../nan/nan_typedarray_contents.h: +../../../../../nan/nan_json.h: +../../../../../nan/nan_scriptorigin.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/err.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/e_os2.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/opensslconf.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/./opensslconf_asm.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/././archs/linux-x86_64/asm/include/openssl/opensslconf.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/opensslv.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/ossl_typ.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bio.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/crypto.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/safestack.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/stack.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/cryptoerr.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/symhacks.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bioerr.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/lhash.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/evp.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/evperr.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/objects.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/obj_mac.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/asn1.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/asn1err.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bn.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/bnerr.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/objectserr.h: +/home/vitalii/.cache/node-gyp/14.17.6/include/node/openssl/hmac.h: diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d new file mode 100644 index 0000000..ece811f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d @@ -0,0 +1 @@ +cmd_Release/sshcrypto.node := rm -rf "Release/sshcrypto.node" && cp -af "Release/obj.target/sshcrypto.node" "Release/sshcrypto.node" diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto.node b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto.node new file mode 100755 index 0000000000000000000000000000000000000000..8ee354f9b11af4864fd8e6be0041f1ec1340fe01 GIT binary patch literal 86400 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ʺp|1AJj3{U&bOKICmG+%{7sDi5x6K9`=@wD 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 literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto/src/binding.o b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto/src/binding.o new file mode 100644 index 0000000000000000000000000000000000000000..6881b821c6f7d2ea4faec299e857c75367881774 GIT binary patch literal 142480 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ʺp|1AJj3{U&bOKICmG+%{7sDi5x6K9`=@wD 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 literal 0 HcmV?d00001 diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/binding.Makefile b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/binding.Makefile new file mode 100644 index 0000000..64db433 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/binding.Makefile @@ -0,0 +1,6 @@ +# This file is generated by gyp; do not edit. + +export builddir_name ?= ./build/. +.PHONY: all +all: + $(MAKE) sshcrypto diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/config.gypi b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/config.gypi new file mode 100644 index 0000000..f8d47de --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/config.gypi @@ -0,0 +1,205 @@ +# Do not edit. File was generated by node-gyp's "configure" step +{ + "target_defaults": { + "cflags": [], + "default_configuration": "Release", + "defines": [], + "include_dirs": [], + "libraries": [] + }, + "variables": { + "asan": 0, + "build_v8_with_gn": "false", + "coverage": "false", + "dcheck_always_on": 0, + "debug_nghttp2": "false", + "debug_node": "false", + "enable_lto": "false", + "enable_pgo_generate": "false", + "enable_pgo_use": "false", + "error_on_warn": "false", + "force_dynamic_crt": 0, + "gas_version": "2.30", + "host_arch": "x64", + "icu_data_in": "../../deps/icu-tmp/icudt69l.dat", + "icu_endianness": "l", + "icu_gyp_path": "tools/icu/icu-generic.gyp", + "icu_path": "deps/icu-small", + "icu_small": "false", + "icu_ver_major": "69", + "is_debug": 0, + "llvm_version": "0.0", + "napi_build_version": "8", + "node_byteorder": "little", + "node_debug_lib": "false", + "node_enable_d8": "false", + "node_install_npm": "true", + "node_module_version": 83, + "node_no_browser_globals": "false", + "node_prefix": "/", + "node_release_urlbase": "https://nodejs.org/download/release/", + "node_section_ordering_info": "", + "node_shared": "false", + "node_shared_brotli": "false", + "node_shared_cares": "false", + "node_shared_http_parser": "false", + "node_shared_libuv": "false", + "node_shared_nghttp2": "false", + "node_shared_openssl": "false", + "node_shared_zlib": "false", + "node_tag": "", + "node_target_type": "executable", + "node_use_bundled_v8": "true", + "node_use_dtrace": "false", + "node_use_etw": "false", + "node_use_node_code_cache": "true", + "node_use_node_snapshot": "true", + "node_use_openssl": "true", + "node_use_v8_platform": "true", + "node_with_ltcg": "false", + "node_without_node_options": "false", + "openssl_fips": "", + "openssl_is_fips": "false", + "ossfuzz": "false", + "shlib_suffix": "so.83", + "target_arch": "x64", + "v8_enable_31bit_smis_on_64bit_arch": 0, + "v8_enable_gdbjit": 0, + "v8_enable_i18n_support": 1, + "v8_enable_inspector": 1, + "v8_enable_lite_mode": 0, + "v8_enable_object_print": 1, + "v8_enable_pointer_compression": 0, + "v8_no_strict_aliasing": 1, + "v8_optimized_debug": 1, + "v8_promise_internal_field_count": 1, + "v8_random_seed": 0, + "v8_trace_maps": 0, + "v8_use_siphash": 1, + "want_separate_host_toolset": 0, + "nodedir": "/home/vitalii/.cache/node-gyp/14.17.6", + "standalone_static_library": 1, + "target": "v14.17.6", + "cache_lock_stale": "60000", + "ham_it_up": "", + "legacy_bundling": "", + "sign_git_tag": "", + "user_agent": "npm/6.14.15 node/v14.17.6 linux x64", + "always_auth": "", + "bin_links": "true", + "key": "", + "allow_same_version": "", + "description": "true", + "fetch_retries": "2", + "heading": "npm", + "if_present": "", + "init_version": "1.0.0", + "user": "", + "prefer_online": "", + "force": "", + "only": "", + "read_only": "", + "cache_min": "10", + "init_license": "ISC", + "editor": "vi", + "rollback": "true", + "tag_version_prefix": "v", + "cache_max": "Infinity", + "timing": "", + "userconfig": "/home/vitalii/.npmrc", + "engine_strict": "", + "init_author_name": "", + "init_author_url": "", + "preid": "", + "tmp": "/tmp", + "depth": "Infinity", + "package_lock_only": "", + "save_dev": "", + "usage": "", + "metrics_registry": "https://registry.npmjs.org/", + "otp": "", + "package_lock": "true", + "progress": "true", + "https_proxy": "", + "save_prod": "", + "audit": "true", + "cidr": "", + "onload_script": "", + "sso_type": "oauth", + "rebuild_bundle": "true", + "save_bundle": "", + "shell": "/bin/bash", + "dry_run": "", + "format_package_lock": "true", + "prefix": "/usr", + "scope": "", + "browser": "", + "cache_lock_wait": "10000", + "ignore_prepublish": "", + "registry": "https://registry.npmjs.org/", + "save_optional": "", + "searchopts": "", + "versions": "", + "cache": "/home/vitalii/.npm", + "send_metrics": "", + "global_style": "", + "ignore_scripts": "", + "version": "", + "local_address": "", + "viewer": "man", + "node_gyp": "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js", + "audit_level": "low", + "prefer_offline": "", + "color": "true", + "sign_git_commit": "", + "fetch_retry_mintimeout": "10000", + "maxsockets": "50", + "offline": "", + "sso_poll_frequency": "500", + "umask": "0002", + "fund": "true", + "fetch_retry_maxtimeout": "60000", + "logs_max": "10", + "message": "%s", + "ca": "", + "cert": "", + "global": "", + "link": "", + "access": "", + "also": "", + "save": "true", + "unicode": "true", + "production": "true", + "before": "", + "long": "", + "searchlimit": "20", + "unsafe_perm": "true", + "update_notifier": "true", + "auth_type": "legacy", + "node_version": "14.17.6", + "tag": "latest", + "git_tag_version": "true", + "commit_hooks": "true", + "script_shell": "", + "shrinkwrap": "true", + "fetch_retry_factor": "10", + "save_exact": "", + "strict_ssl": "true", + "dev": "", + "globalconfig": "/usr/etc/npmrc", + "init_module": "/home/vitalii/.npm-init.js", + "parseable": "", + "globalignorefile": "/usr/etc/npmignore", + "cache_lock_retries": "10", + "searchstaleness": "900", + "node_options": "", + "save_prefix": "^", + "scripts_prepend_node_path": "warn-only", + "group": "1000", + "init_author_email": "", + "searchexclude": "", + "git": "git", + "optional": "true", + "json": "" + } +} diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/sshcrypto.target.mk b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/sshcrypto.target.mk new file mode 100644 index 0000000..04a5e8e --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/build/sshcrypto.target.mk @@ -0,0 +1,161 @@ +# This file is generated by gyp; do not edit. + +TOOLSET := target +TARGET := sshcrypto +DEFS_Debug := \ + '-DNODE_GYP_MODULE_NAME=sshcrypto' \ + '-DUSING_UV_SHARED=1' \ + '-DUSING_V8_SHARED=1' \ + '-DV8_DEPRECATION_WARNINGS=1' \ + '-DV8_DEPRECATION_WARNINGS' \ + '-DV8_IMMINENT_DEPRECATION_WARNINGS' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-D__STDC_FORMAT_MACROS' \ + '-DOPENSSL_NO_PINSHARED' \ + '-DOPENSSL_THREADS' \ + '-DBUILDING_NODE_EXTENSION' \ + '-DDEBUG' \ + '-D_DEBUG' \ + '-DV8_ENABLE_CHECKS' + +# Flags passed to all source files. +CFLAGS_Debug := \ + -fPIC \ + -pthread \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -m64 \ + -O3 \ + -g \ + -O0 + +# Flags passed to only C files. +CFLAGS_C_Debug := + +# Flags passed to only C++ files. +CFLAGS_CC_Debug := \ + -fno-rtti \ + -fno-exceptions \ + -std=gnu++1y + +INCS_Debug := \ + -I/home/vitalii/.cache/node-gyp/14.17.6/include/node \ + -I/home/vitalii/.cache/node-gyp/14.17.6/src \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/config \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/openssl/include \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/uv/include \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/zlib \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/v8/include \ + -I$(srcdir)/../../../../nan + +DEFS_Release := \ + '-DNODE_GYP_MODULE_NAME=sshcrypto' \ + '-DUSING_UV_SHARED=1' \ + '-DUSING_V8_SHARED=1' \ + '-DV8_DEPRECATION_WARNINGS=1' \ + '-DV8_DEPRECATION_WARNINGS' \ + '-DV8_IMMINENT_DEPRECATION_WARNINGS' \ + '-D_LARGEFILE_SOURCE' \ + '-D_FILE_OFFSET_BITS=64' \ + '-D__STDC_FORMAT_MACROS' \ + '-DOPENSSL_NO_PINSHARED' \ + '-DOPENSSL_THREADS' \ + '-DBUILDING_NODE_EXTENSION' + +# Flags passed to all source files. +CFLAGS_Release := \ + -fPIC \ + -pthread \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -m64 \ + -O3 \ + -O3 \ + -fno-omit-frame-pointer + +# Flags passed to only C files. +CFLAGS_C_Release := + +# Flags passed to only C++ files. +CFLAGS_CC_Release := \ + -fno-rtti \ + -fno-exceptions \ + -std=gnu++1y + +INCS_Release := \ + -I/home/vitalii/.cache/node-gyp/14.17.6/include/node \ + -I/home/vitalii/.cache/node-gyp/14.17.6/src \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/config \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/openssl/openssl/include \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/uv/include \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/zlib \ + -I/home/vitalii/.cache/node-gyp/14.17.6/deps/v8/include \ + -I$(srcdir)/../../../../nan + +OBJS := \ + $(obj).target/$(TARGET)/src/binding.o + +# Add to the list of files we specially track dependencies for. +all_deps += $(OBJS) + +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual. +$(OBJS): TOOLSET := $(TOOLSET) +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) + +# Suffix rules, putting all outputs into $(obj). + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# Try building from generated source, too. + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) + +# End of this set of suffix rules +### Rules for final target. +LDFLAGS_Debug := \ + -pthread \ + -rdynamic \ + -m64 + +LDFLAGS_Release := \ + -pthread \ + -rdynamic \ + -m64 + +LIBS := + +$(obj).target/sshcrypto.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) +$(obj).target/sshcrypto.node: LIBS := $(LIBS) +$(obj).target/sshcrypto.node: TOOLSET := $(TOOLSET) +$(obj).target/sshcrypto.node: $(OBJS) FORCE_DO_CMD + $(call do_cmd,solink_module) + +all_deps += $(obj).target/sshcrypto.node +# Add target alias +.PHONY: sshcrypto +sshcrypto: $(builddir)/sshcrypto.node + +# Copy this to the executable output path. +$(builddir)/sshcrypto.node: TOOLSET := $(TOOLSET) +$(builddir)/sshcrypto.node: $(obj).target/sshcrypto.node FORCE_DO_CMD + $(call do_cmd,copy) + +all_deps += $(builddir)/sshcrypto.node +# Short alias for building this executable. +.PHONY: sshcrypto.node +sshcrypto.node: $(obj).target/sshcrypto.node $(builddir)/sshcrypto.node + +# Add executable to "all" target. +.PHONY: all +all: $(builddir)/sshcrypto.node + diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/poly1305.js b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/poly1305.js new file mode 100644 index 0000000..a6953fe --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/crypto/poly1305.js @@ -0,0 +1,43 @@ + +var createPoly1305 = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(createPoly1305) { + createPoly1305 = createPoly1305 || {}; + + +var b;b||(b=typeof createPoly1305 !== 'undefined' ? createPoly1305 : {});var q,r;b.ready=new Promise(function(a,c){q=a;r=c});var u={},w;for(w in b)b.hasOwnProperty(w)&&(u[w]=b[w]);var x="object"===typeof window,y="function"===typeof importScripts,z="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node,B="",C,D,E,F,G; +if(z)B=y?require("path").dirname(B)+"/":__dirname+"/",C=function(a,c){var d=H(a);if(d)return c?d:d.toString();F||(F=require("fs"));G||(G=require("path"));a=G.normalize(a);return F.readFileSync(a,c?null:"utf8")},E=function(a){a=C(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a},D=function(a,c,d){var e=H(a);e&&c(e);F||(F=require("fs"));G||(G=require("path"));a=G.normalize(a);F.readFile(a,function(f,l){f?d(f):c(l.buffer)})},1=m){var oa=g.charCodeAt(++v);m=65536+((m&1023)<<10)|oa&1023}if(127>=m){if(k>=n)break;h[k++]=m}else{if(2047>=m){if(k+1>=n)break;h[k++]=192|m>>6}else{if(65535>=m){if(k+2>=n)break;h[k++]=224|m>>12}else{if(k+3>=n)break;h[k++]=240|m>>18;h[k++]=128|m>>12&63}h[k++]=128|m>>6&63}h[k++]=128|m&63}}h[k]= +0}}return p},array:function(g){var p=O(g.length);Q.set(g,p);return p}},l=N(a),A=[];a=0;if(e)for(var t=0;t=n);)++k;if(16h?n+=String.fromCharCode(h):(h-=65536,n+=String.fromCharCode(55296|h>>10,56320|h&1023))}}else n+=String.fromCharCode(h)}g=n}}else g="";else g="boolean"===c?!!g:g;return g}(d);0!==a&&fa(a);return d}var ea="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0,ha,Q,P; +function ia(){var a=L.buffer;ha=a;b.HEAP8=Q=new Int8Array(a);b.HEAP16=new Int16Array(a);b.HEAP32=new Int32Array(a);b.HEAPU8=P=new Uint8Array(a);b.HEAPU16=new Uint16Array(a);b.HEAPU32=new Uint32Array(a);b.HEAPF32=new Float32Array(a);b.HEAPF64=new Float64Array(a)}var R,ja=[],ka=[],la=[];function ma(){var a=b.preRun.shift();ja.unshift(a)}var S=0,T=null,U=null;b.preloadedImages={};b.preloadedAudios={}; +function K(a){if(b.onAbort)b.onAbort(a);I(a);M=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");r(a);throw a;}var V="data:application/octet-stream;base64,",W;W="data:application/octet-stream;base64,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";if(!W.startsWith(V)){var na=W;W=b.locateFile?b.locateFile(na,B):B+na}function pa(){var a=W;try{if(a==W&&J)return new Uint8Array(J);var c=H(a);if(c)return c;if(E)return E(a);throw"both async and sync fetching of the wasm failed";}catch(d){K(d)}} +function qa(){if(!J&&(x||y)){if("function"===typeof fetch&&!W.startsWith("file://"))return fetch(W,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+W+"'";return a.arrayBuffer()}).catch(function(){return pa()});if(D)return new Promise(function(a,c){D(W,function(d){a(new Uint8Array(d))},c)})}return Promise.resolve().then(function(){return pa()})} +function X(a){for(;0>4;f=(f&15)<<4|l>>2;var t=(l&3)<<6|A;c+=String.fromCharCode(e);64!==l&&(c+=String.fromCharCode(f));64!==A&&(c+=String.fromCharCode(t))}while(d>>=0;if(2147483648=d;d*=2){var e=c*(1+.2/d);e=Math.min(e,a+100663296);e=Math.max(a,e);0>>16);ia();var f=1;break a}catch(l){}f=void 0}if(f)return!0}return!1}}; +(function(){function a(f){b.asm=f.exports;L=b.asm.b;ia();R=b.asm.j;ka.unshift(b.asm.c);S--;b.monitorRunDependencies&&b.monitorRunDependencies(S);0==S&&(null!==T&&(clearInterval(T),T=null),U&&(f=U,U=null,f()))}function c(f){a(f.instance)}function d(f){return qa().then(function(l){return WebAssembly.instantiate(l,e)}).then(f,function(l){I("failed to asynchronously prepare wasm: "+l);K(l)})}var e={a:sa};S++;b.monitorRunDependencies&&b.monitorRunDependencies(S);if(b.instantiateWasm)try{return b.instantiateWasm(e, +a)}catch(f){return I("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return J||"function"!==typeof WebAssembly.instantiateStreaming||W.startsWith(V)||W.startsWith("file://")||"function"!==typeof fetch?d(c):fetch(W,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(c,function(l){I("wasm streaming compile failed: "+l);I("falling back to ArrayBuffer instantiation");return d(c)})})})().catch(r);return{}})(); +b.___wasm_call_ctors=function(){return(b.___wasm_call_ctors=b.asm.c).apply(null,arguments)};b._poly1305_auth=function(){return(b._poly1305_auth=b.asm.d).apply(null,arguments)};var da=b.stackSave=function(){return(da=b.stackSave=b.asm.e).apply(null,arguments)},fa=b.stackRestore=function(){return(fa=b.stackRestore=b.asm.f).apply(null,arguments)},O=b.stackAlloc=function(){return(O=b.stackAlloc=b.asm.g).apply(null,arguments)};b._malloc=function(){return(b._malloc=b.asm.h).apply(null,arguments)}; +b._free=function(){return(b._free=b.asm.i).apply(null,arguments)};b.cwrap=function(a,c,d,e){d=d||[];var f=d.every(function(l){return"number"===l});return"string"!==c&&f&&!e?N(a):function(){return ca(a,c,d,arguments)}};var Y;U=function ta(){Y||Z();Y||(U=ta)}; +function Z(){function a(){if(!Y&&(Y=!0,b.calledRun=!0,!M)){X(ka);q(b);if(b.onRuntimeInitialized)b.onRuntimeInitialized();if(b.postRun)for("function"==typeof b.postRun&&(b.postRun=[b.postRun]);b.postRun.length;){var c=b.postRun.shift();la.unshift(c)}X(la)}}if(!(0 +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace node; +using namespace v8; +using namespace std; + +struct MarkPopErrorOnReturn { + MarkPopErrorOnReturn() { ERR_set_mark(); } + ~MarkPopErrorOnReturn() { ERR_pop_to_mark(); } +}; + +enum ErrorType { + kErrNone, + kErrOpenSSL, + kErrBadIVLen, + kErrBadKeyLen, + kErrAADFailure, + kErrTagFailure, + kErrPartialEncrypt, + kErrBadCipherName, + kErrBadHMACName, + kErrBadHMACLen, + kErrBadInit, + kErrPartialDecrypt, + kErrInvalidMAC, + kErrBadBlockLen +}; + +#define MAX_MAC_LEN 64 + +#define POLY1305_KEYLEN 32 +#define POLY1305_TAGLEN 16 +class ChaChaPolyCipher : public ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("ChaChaPolyCipher").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + SetPrototypeMethod(tpl, "encrypt", Encrypt); + SetPrototypeMethod(tpl, "free", Free); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + + Nan::Set(target, + Nan::New("ChaChaPolyCipher").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit ChaChaPolyCipher() + : ctx_main_(nullptr), + ctx_pktlen_(nullptr), + md_ctx_(nullptr), + polykey_(nullptr) {} + + ~ChaChaPolyCipher() { + clear(); + } + + void clear() { + if (ctx_pktlen_) { + EVP_CIPHER_CTX_cleanup(ctx_pktlen_); + EVP_CIPHER_CTX_free(ctx_pktlen_); + ctx_pktlen_ = nullptr; + } + if (ctx_main_) { + EVP_CIPHER_CTX_cleanup(ctx_main_); + EVP_CIPHER_CTX_free(ctx_main_); + ctx_main_ = nullptr; + } + if (polykey_) { + EVP_PKEY_free(polykey_); + polykey_ = nullptr; + } + if (md_ctx_) { + EVP_MD_CTX_free(md_ctx_); + md_ctx_ = nullptr; + } + // `polykey_ctx_` is not explicitly freed as it is freed implicitly when + // `md_ctx_` is freed + } + + ErrorType init(unsigned char* keys, size_t keys_len) { + ErrorType r = kErrNone; + const EVP_CIPHER* const cipher = EVP_get_cipherbyname("chacha20"); + + if (keys_len != 64) { + r = kErrBadKeyLen; + goto out; + } + + if (cipher == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if ((ctx_pktlen_ = EVP_CIPHER_CTX_new()) == nullptr + || (ctx_main_ = EVP_CIPHER_CTX_new()) == nullptr + || (md_ctx_ = EVP_MD_CTX_new()) == nullptr + || EVP_EncryptInit_ex(ctx_pktlen_, + cipher, + nullptr, + keys + 32, + nullptr) != 1 + || EVP_EncryptInit_ex(ctx_main_, + cipher, + nullptr, + keys, + nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_CIPHER_CTX_iv_length(ctx_pktlen_) != 16) { + r = kErrBadIVLen; + goto out; + } + +out: + return r; + } + + ErrorType encrypt(unsigned char* packet, + uint32_t packet_len, + uint32_t seqno) { + ErrorType r = kErrNone; + size_t sig_len = 16; + int outlen = 0; + + // `packet` layout: + // + uint32_t data_len = packet_len - POLY1305_TAGLEN; + + unsigned char polykey[POLY1305_KEYLEN] = {0}; + + uint8_t seqbuf[16] = {0}; + ((uint8_t*)(seqbuf))[12] = (seqno >> 24) & 0xff; + ((uint8_t*)(seqbuf))[13] = (seqno >> 16) & 0xff; + ((uint8_t*)(seqbuf))[14] = (seqno >> 8) & 0xff; + ((uint8_t*)(seqbuf))[15] = seqno & 0xff; + + // Generate Poly1305 key + if (EVP_EncryptInit_ex(ctx_main_, nullptr, nullptr, nullptr, seqbuf) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_EncryptUpdate(ctx_main_, + polykey, + &outlen, + polykey, + sizeof(polykey)) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != sizeof(polykey)) { + r = kErrPartialEncrypt; + goto out; + } + + // Encrypt packet length + if (EVP_EncryptInit_ex(ctx_pktlen_, + nullptr, + nullptr, + nullptr, + seqbuf) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_EncryptUpdate(ctx_pktlen_, packet, &outlen, packet, 4) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != 4) { + r = kErrPartialEncrypt; + goto out; + } + + // Encrypt rest of packet + seqbuf[0] = 1; + if (EVP_EncryptInit_ex(ctx_main_, nullptr, nullptr, nullptr, seqbuf) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_EncryptUpdate(ctx_main_, + packet + 4, + &outlen, + packet + 4, + data_len - 4) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != data_len - 4) { + r = kErrPartialEncrypt; + goto out; + } + + // Poly1305 over ciphertext + if (polykey_) { + if (EVP_PKEY_CTX_ctrl(polykey_ctx_, + -1, + EVP_PKEY_OP_SIGNCTX, + EVP_PKEY_CTRL_SET_MAC_KEY, + sizeof(polykey), + (void*)polykey) <= 0) { + r = kErrOpenSSL; + goto out; + } + } else { + polykey_ = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, + nullptr, + polykey, + sizeof(polykey)); + if (polykey_ == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if (!EVP_DigestSignInit(md_ctx_, + &polykey_ctx_, + nullptr, + nullptr, + polykey_)) { + r = kErrOpenSSL; + goto out; + } + } + + // Generate and write Poly1305 tag + if (EVP_DigestSign(md_ctx_, + packet + data_len, + &sig_len, + packet, + data_len) != 1) { + r = kErrOpenSSL; + goto out; + } + + out: + return r; + } + + static NAN_METHOD(New) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid keys"); + + ChaChaPolyCipher* obj = new ChaChaPolyCipher(); + ErrorType r = obj->init( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]) + ); + if (r != kErrNone) { + if (r == kErrOpenSSL) { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + obj->clear(); + delete obj; + return Nan::ThrowError(msg_buf); + } + obj->clear(); + delete obj; + switch (r) { + case kErrBadKeyLen: + return Nan::ThrowError("Invalid keys length"); + case kErrBadIVLen: + return Nan::ThrowError("Invalid IV length"); + default: + return Nan::ThrowError("Unknown init failure"); + } + } + + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } + + static NAN_METHOD(Encrypt) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + ChaChaPolyCipher* obj = ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid packet"); + + if (!info[1]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid sequence number"); + + ErrorType r = obj->encrypt( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]), + Nan::To(info[1]).FromJust() + ); + switch (r) { + case kErrNone: + return; + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown encrypt failure"); + } + } + + static NAN_METHOD(Free) { + ChaChaPolyCipher* obj = ObjectWrap::Unwrap(info.Holder()); + obj->clear(); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + EVP_CIPHER_CTX* ctx_main_; + EVP_CIPHER_CTX* ctx_pktlen_; + EVP_MD_CTX* md_ctx_; + EVP_PKEY* polykey_; + EVP_PKEY_CTX* polykey_ctx_; +}; + +class AESGCMCipher : public ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("AESGCMCipher").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + SetPrototypeMethod(tpl, "encrypt", Encrypt); + SetPrototypeMethod(tpl, "free", Free); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + + Nan::Set(target, + Nan::New("AESGCMCipher").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit AESGCMCipher() : ctx_(nullptr) {} + + ~AESGCMCipher() { + clear(); + } + + void clear() { + if (ctx_) { + EVP_CIPHER_CTX_cleanup(ctx_); + EVP_CIPHER_CTX_free(ctx_); + ctx_ = nullptr; + } + } + + ErrorType init(const char* name, + unsigned char* key, + size_t key_len, + unsigned char* iv, + size_t iv_len) { + ErrorType r = kErrNone; + + const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name); + if (cipher == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if (cipher != EVP_aes_128_gcm() && cipher != EVP_aes_256_gcm()) { + r = kErrBadCipherName; + goto out; + } + + if ((ctx_ = EVP_CIPHER_CTX_new()) == nullptr + || EVP_EncryptInit_ex(ctx_, cipher, nullptr, nullptr, nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_AEAD_SET_IVLEN, iv_len, nullptr)) { + r = kErrOpenSSL; + goto out; + } + + //~ if (iv_len != static_cast(EVP_CIPHER_CTX_iv_length(ctx_))) { + //~ r = kErrBadIVLen; + //~ goto out; + //~ } + + if (key_len != static_cast(EVP_CIPHER_CTX_key_length(ctx_))) { + if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) { + r = kErrBadKeyLen; + goto out; + } + } + + // Set key and IV + if (EVP_EncryptInit_ex(ctx_, nullptr, nullptr, key, iv) != 1) { + r = kErrOpenSSL; + goto out; + } + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) { + r = kErrOpenSSL; + goto out; + } + + // Disable padding + EVP_CIPHER_CTX_set_padding(ctx_, 0); + +out: + return r; + } + + ErrorType encrypt(unsigned char* packet, uint32_t packet_len) { + ErrorType r = kErrNone; + + // `packet` layout: + // + uint32_t data_len = packet_len - 16; + + int outlen = 0; + + // Increment IV + unsigned char lastiv[1]; + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_IV_GEN, 1, lastiv)) { + r = kErrOpenSSL; + goto out; + } + + // Set AAD (the packet length) + if (!EVP_EncryptUpdate(ctx_, nullptr, &outlen, packet, 4)) { + r = kErrOpenSSL; + goto out; + } + if (outlen != 4) { + r = kErrAADFailure; + goto out; + } + + // Encrypt everything but the packet length + if (EVP_EncryptUpdate(ctx_, + packet + 4, + &outlen, + packet + 4, + data_len - 4) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != data_len - 4) { + r = kErrPartialEncrypt; + goto out; + } + + // Generate authentication tag + if (!EVP_EncryptFinal_ex(ctx_, nullptr, &outlen)) { + r = kErrOpenSSL; + goto out; + } + + // Write authentication tag + if (EVP_CIPHER_CTX_ctrl(ctx_, + EVP_CTRL_AEAD_GET_TAG, + 16, + packet + data_len) != 1) { + r = kErrOpenSSL; + goto out; + } + +out: + return r; + } + + static NAN_METHOD(New) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + if (!info[0]->IsString()) + return Nan::ThrowTypeError("Missing/Invalid OpenSSL cipher name"); + + if (!Buffer::HasInstance(info[1])) + return Nan::ThrowTypeError("Missing/Invalid key"); + + if (!Buffer::HasInstance(info[2])) + return Nan::ThrowTypeError("Missing/Invalid iv"); + + const Nan::Utf8String cipher_name(info[0]); + + AESGCMCipher* obj = new AESGCMCipher(); + ErrorType r = obj->init( + *cipher_name, + reinterpret_cast(Buffer::Data(info[1])), + Buffer::Length(info[1]), + reinterpret_cast(Buffer::Data(info[2])), + Buffer::Length(info[2]) + ); + if (r != kErrNone) { + if (r == kErrOpenSSL) { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + obj->clear(); + delete obj; + return Nan::ThrowError(msg_buf); + } + obj->clear(); + delete obj; + switch (r) { + case kErrBadKeyLen: + return Nan::ThrowError("Invalid keys length"); + case kErrBadIVLen: + return Nan::ThrowError("Invalid IV length"); + case kErrBadCipherName: + return Nan::ThrowError("Invalid AES GCM cipher name"); + default: + return Nan::ThrowError("Unknown init failure"); + } + } + + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } + + static NAN_METHOD(Encrypt) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + AESGCMCipher* obj = ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid packet"); + + ErrorType r = obj->encrypt( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]) + ); + switch (r) { + case kErrNone: + return; + case kErrAADFailure: + return Nan::ThrowError("Error setting AAD"); + case kErrPartialEncrypt: + return Nan::ThrowError("Failed to completely encrypt packet"); + case kErrTagFailure: + return Nan::ThrowError("Error generating authentication tag"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown encrypt failure"); + } + } + + static NAN_METHOD(Free) { + AESGCMCipher* obj = ObjectWrap::Unwrap(info.Holder()); + obj->clear(); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + EVP_CIPHER_CTX* ctx_; +}; + +class GenericCipher : public ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("GenericCipher").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + SetPrototypeMethod(tpl, "encrypt", Encrypt); + SetPrototypeMethod(tpl, "free", Free); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + + Nan::Set(target, + Nan::New("GenericCipher").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit GenericCipher() + : ctx_(nullptr), + ctx_hmac_(nullptr), + hmac_len_(0), + is_etm_(0) {} + + ~GenericCipher() { + clear(); + } + + void clear() { + if (ctx_) { + EVP_CIPHER_CTX_cleanup(ctx_); + EVP_CIPHER_CTX_free(ctx_); + ctx_ = nullptr; + } + if (ctx_hmac_) { + HMAC_CTX_free(ctx_hmac_); + ctx_hmac_ = nullptr; + } + } + + ErrorType init(const char* name, + unsigned char* key, + size_t key_len, + unsigned char* iv, + size_t iv_len, + const char* hmac_name, + unsigned char* hmac_key, + size_t hmac_key_len, + int is_etm) { + ErrorType r = kErrNone; + + const EVP_MD* md; + const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name); + if (cipher == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if ((ctx_ = EVP_CIPHER_CTX_new()) == nullptr + || EVP_EncryptInit_ex(ctx_, cipher, nullptr, nullptr, nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + + if (iv_len != static_cast(EVP_CIPHER_CTX_iv_length(ctx_))) { + r = kErrBadIVLen; + goto out; + } + + if (key_len != static_cast(EVP_CIPHER_CTX_key_length(ctx_))) { + if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) { + r = kErrBadKeyLen; + goto out; + } + } + + // Set key and IV + if (EVP_EncryptInit_ex(ctx_, nullptr, nullptr, key, iv) != 1) { + r = kErrOpenSSL; + goto out; + } + + // Disable padding + EVP_CIPHER_CTX_set_padding(ctx_, 0); + + if (cipher == EVP_rc4()) { + /* The "arcfour128" algorithm is the RC4 cipher, as described in + [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream + generated by the cipher MUST be discarded, and the first byte of the + first encrypted packet MUST be encrypted using the 1537th byte of + keystream. + + -- http://tools.ietf.org/html/rfc4345#section-4 */ + unsigned char zeros[1536] = {0}; + int outlen = sizeof(zeros); + if (EVP_EncryptUpdate(ctx_, + zeros, + &outlen, + zeros, + sizeof(zeros)) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != sizeof(zeros)) { + r = kErrBadInit; + goto out; + } + } + + md = EVP_get_digestbyname(hmac_name); + if (md == nullptr) { + r = kErrBadHMACName; + goto out; + } + + if ((ctx_hmac_ = HMAC_CTX_new()) == nullptr + || HMAC_Init_ex(ctx_hmac_, hmac_key, hmac_key_len, md, nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + + hmac_len_ = HMAC_size(ctx_hmac_); + is_etm_ = is_etm; + +out: + return r; + } + + ErrorType encrypt(unsigned char* packet, + uint32_t packet_len, + uint32_t seqno) { + ErrorType r = kErrNone; + + // `packet` layout: + // + uint32_t data_len = packet_len - hmac_len_; + + int outlen; + + uint8_t seqbuf[4] = {0}; + ((uint8_t*)(seqbuf))[0] = (seqno >> 24) & 0xff; + ((uint8_t*)(seqbuf))[1] = (seqno >> 16) & 0xff; + ((uint8_t*)(seqbuf))[2] = (seqno >> 8) & 0xff; + ((uint8_t*)(seqbuf))[3] = seqno & 0xff; + + if (is_etm_) { + // Encrypt everything but packet length + if (EVP_EncryptUpdate(ctx_, + packet + 4, + &outlen, + packet + 4, + data_len - 4) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != data_len - 4) { + r = kErrPartialEncrypt; + goto out; + } + + // HMAC over unencrypted packet length and ciphertext + { + unsigned int outlen = hmac_len_; + if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1 + || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1 + || HMAC_Update(ctx_hmac_, packet, data_len) != 1 + || HMAC_Final(ctx_hmac_, packet + data_len, &outlen) != 1) { + r = kErrOpenSSL; + goto out; + } + if (outlen != hmac_len_) { + r = kErrBadHMACLen; + goto out; + } + } + } else { + // HMAC over plaintext + { + unsigned int outlen = hmac_len_; + if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1 + || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1 + || HMAC_Update(ctx_hmac_, packet, data_len) != 1 + || HMAC_Final(ctx_hmac_, packet + data_len, &outlen) != 1) { + r = kErrOpenSSL; + goto out; + } + if (outlen != hmac_len_) { + r = kErrBadHMACLen; + goto out; + } + } + + // Encrypt packet + if (EVP_EncryptUpdate(ctx_, + packet, + &outlen, + packet, + data_len) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != data_len) { + + r = kErrPartialEncrypt; + goto out; + } + } + +out: + return r; + } + + static NAN_METHOD(New) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + if (!info[0]->IsString()) + return Nan::ThrowTypeError("Missing/Invalid cipher name"); + + if (!Buffer::HasInstance(info[1])) + return Nan::ThrowTypeError("Missing/Invalid cipher key"); + + if (!Buffer::HasInstance(info[2])) + return Nan::ThrowTypeError("Missing/Invalid cipher IV"); + + if (!info[3]->IsString()) + return Nan::ThrowTypeError("Missing/Invalid HMAC name"); + + if (!Buffer::HasInstance(info[4])) + return Nan::ThrowTypeError("Missing/Invalid HMAC key"); + + if (!info[5]->IsBoolean()) + return Nan::ThrowTypeError("Missing/Invalid HMAC ETM flag"); + + const Nan::Utf8String cipher_name(info[0]); + const Nan::Utf8String mac_name(info[3]); + int is_etm = (Nan::To(info[5]).FromJust() ? 1 : 0); + + GenericCipher* obj = new GenericCipher(); + ErrorType r = obj->init( + *cipher_name, + reinterpret_cast(Buffer::Data(info[1])), + Buffer::Length(info[1]), + reinterpret_cast(Buffer::Data(info[2])), + Buffer::Length(info[2]), + *mac_name, + reinterpret_cast(Buffer::Data(info[4])), + Buffer::Length(info[4]), + is_etm + ); + if (r != kErrNone) { + if (r == kErrOpenSSL) { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + obj->clear(); + delete obj; + return Nan::ThrowError(msg_buf); + } + obj->clear(); + delete obj; + switch (r) { + case kErrBadKeyLen: + return Nan::ThrowError("Invalid keys length"); + case kErrBadIVLen: + return Nan::ThrowError("Invalid IV length"); + case kErrBadCipherName: + return Nan::ThrowError("Invalid cipher name"); + case kErrBadHMACName: + return Nan::ThrowError("Invalid MAC name"); + case kErrBadInit: + return Nan::ThrowError("Failed to properly initialize cipher"); + default: + return Nan::ThrowError("Unknown init failure"); + } + } + + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } + + static NAN_METHOD(Encrypt) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + GenericCipher* obj = ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid packet"); + + if (!info[1]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid sequence number"); + + ErrorType r = obj->encrypt( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]), + Nan::To(info[1]).FromJust() + ); + switch (r) { + case kErrNone: + return; + case kErrPartialEncrypt: + return Nan::ThrowError("Failed to completely encrypt packet"); + case kErrBadHMACLen: + return Nan::ThrowError("Unexpected HMAC length"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown encrypt failure"); + } + } + + static NAN_METHOD(Free) { + GenericCipher* obj = ObjectWrap::Unwrap(info.Holder()); + obj->clear(); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + EVP_CIPHER_CTX* ctx_; + HMAC_CTX* ctx_hmac_; + unsigned int hmac_len_; + int is_etm_; +}; + +// ============================================================================= + +class ChaChaPolyDecipher : public ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("ChaChaPolyDecipher").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + SetPrototypeMethod(tpl, "decrypt", Decrypt); + SetPrototypeMethod(tpl, "decryptLen", DecryptLen); + SetPrototypeMethod(tpl, "free", Free); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + + Nan::Set(target, + Nan::New("ChaChaPolyDecipher").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit ChaChaPolyDecipher() + : ctx_main_(nullptr), + ctx_pktlen_(nullptr), + md_ctx_(nullptr), + polykey_(nullptr) {} + + ~ChaChaPolyDecipher() { + clear(); + } + + void clear() { + if (ctx_pktlen_) { + EVP_CIPHER_CTX_cleanup(ctx_pktlen_); + EVP_CIPHER_CTX_free(ctx_pktlen_); + ctx_pktlen_ = nullptr; + } + if (ctx_main_) { + EVP_CIPHER_CTX_cleanup(ctx_main_); + EVP_CIPHER_CTX_free(ctx_main_); + ctx_main_ = nullptr; + } + if (polykey_) { + EVP_PKEY_free(polykey_); + polykey_ = nullptr; + } + if (md_ctx_) { + EVP_MD_CTX_free(md_ctx_); + md_ctx_ = nullptr; + } + // `polykey_ctx_` is not explicitly freed as it is freed implicitly when + // `md_ctx_` is freed + } + + ErrorType init(unsigned char* keys, size_t keys_len) { + ErrorType r = kErrNone; + const EVP_CIPHER* const cipher = EVP_get_cipherbyname("chacha20"); + + if (keys_len != 64) { + r = kErrBadKeyLen; + goto out; + } + + if (cipher == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if ((ctx_pktlen_ = EVP_CIPHER_CTX_new()) == nullptr + || (ctx_main_ = EVP_CIPHER_CTX_new()) == nullptr + || (md_ctx_ = EVP_MD_CTX_new()) == nullptr + || EVP_DecryptInit_ex(ctx_pktlen_, + cipher, + nullptr, + keys + 32, + nullptr) != 1 + || EVP_DecryptInit_ex(ctx_main_, + cipher, + nullptr, + keys, + nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_CIPHER_CTX_iv_length(ctx_pktlen_) != 16) { + r = kErrBadIVLen; + goto out; + } + +out: + return r; + } + + ErrorType decrypt_length(unsigned char* data, + size_t data_len, + uint32_t seqno, + uint32_t* packet_length) { + ErrorType r = kErrNone; + int outlen; + + unsigned char dec_length_bytes[4]; + + uint8_t seqbuf[16] = {0}; + ((uint8_t*)(seqbuf))[12] = (seqno >> 24) & 0xff; + ((uint8_t*)(seqbuf))[13] = (seqno >> 16) & 0xff; + ((uint8_t*)(seqbuf))[14] = (seqno >> 8) & 0xff; + ((uint8_t*)(seqbuf))[15] = seqno & 0xff; + + if (EVP_DecryptInit_ex(ctx_pktlen_, + nullptr, + nullptr, + nullptr, + seqbuf) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_DecryptUpdate(ctx_pktlen_, + dec_length_bytes, + &outlen, + data, + data_len) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != 4) { + r = kErrPartialDecrypt; + goto out; + } + + *packet_length = (uint32_t)dec_length_bytes[0] << 24 + | (uint32_t)dec_length_bytes[1] << 16 + | (uint32_t)dec_length_bytes[2] << 8 + | (uint32_t)dec_length_bytes[3]; + memcpy(length_bytes, data, data_len); +out: + return r; + } + + ErrorType decrypt(unsigned char* packet, + uint32_t packet_len, + unsigned char* mac, + uint32_t seqno) { + ErrorType r = kErrNone; + size_t sig_len = 16; + int outlen = 0; + + // `packet` layout: + // + + unsigned char polykey[POLY1305_KEYLEN] = {0}; + unsigned char calc_mac[POLY1305_TAGLEN] = {0}; + + uint8_t seqbuf[16] = {0}; + ((uint8_t*)(seqbuf))[12] = (seqno >> 24) & 0xff; + ((uint8_t*)(seqbuf))[13] = (seqno >> 16) & 0xff; + ((uint8_t*)(seqbuf))[14] = (seqno >> 8) & 0xff; + ((uint8_t*)(seqbuf))[15] = seqno & 0xff; + + // Generate Poly1305 key + if (EVP_EncryptInit_ex(ctx_main_, nullptr, nullptr, nullptr, seqbuf) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_EncryptUpdate(ctx_main_, + polykey, + &outlen, + polykey, + sizeof(polykey)) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != sizeof(polykey)) { + r = kErrPartialEncrypt; + goto out; + } + + // Poly1305 over ciphertext + if (polykey_) { + if (EVP_PKEY_CTX_ctrl(polykey_ctx_, + -1, + EVP_PKEY_OP_SIGNCTX, + EVP_PKEY_CTRL_SET_MAC_KEY, + sizeof(polykey), + (void*)polykey) <= 0) { + r = kErrOpenSSL; + goto out; + } + } else { + polykey_ = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, + nullptr, + polykey, + sizeof(polykey)); + if (polykey_ == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if (!EVP_DigestSignInit(md_ctx_, + &polykey_ctx_, + nullptr, + nullptr, + polykey_)) { + r = kErrOpenSSL; + goto out; + } + } + if (EVP_DigestSignUpdate(md_ctx_, + length_bytes, + sizeof(length_bytes)) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_DigestSignUpdate(md_ctx_, packet, packet_len) != 1) { + r = kErrOpenSSL; + goto out; + } + + // Generate Poly1305 MAC + if (EVP_DigestSignFinal(md_ctx_, calc_mac, &sig_len) != 1) { + r = kErrOpenSSL; + goto out; + } + + // Compare MACs + if (CRYPTO_memcmp(mac, calc_mac, sizeof(calc_mac))) { + r = kErrInvalidMAC; + goto out; + } + + // Decrypt packet + seqbuf[0] = 1; + if (EVP_DecryptInit_ex(ctx_main_, nullptr, nullptr, nullptr, seqbuf) != 1) { + r = kErrOpenSSL; + goto out; + } + if (EVP_DecryptUpdate(ctx_main_, + packet, + &outlen, + packet, + packet_len) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != packet_len) { + r = kErrPartialDecrypt; + goto out; + } + + out: + return r; + } + + static NAN_METHOD(New) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid keys"); + + ChaChaPolyDecipher* obj = new ChaChaPolyDecipher(); + ErrorType r = obj->init( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]) + ); + if (r != kErrNone) { + if (r == kErrOpenSSL) { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + obj->clear(); + delete obj; + return Nan::ThrowError(msg_buf); + } + obj->clear(); + delete obj; + switch (r) { + case kErrBadKeyLen: + return Nan::ThrowError("Invalid keys length"); + case kErrBadIVLen: + return Nan::ThrowError("Invalid IV length"); + default: + return Nan::ThrowError("Unknown init failure"); + } + } + + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } + + static NAN_METHOD(DecryptLen) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + ChaChaPolyDecipher* obj = + ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0]) || Buffer::Length(info[0]) != 4) + return Nan::ThrowTypeError("Missing/Invalid length bytes"); + + if (!info[1]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid sequence number"); + + unsigned char* length_bytes = + reinterpret_cast(Buffer::Data(info[0])); + + uint32_t dec_packet_length; + ErrorType r = obj->decrypt_length( + length_bytes, + Buffer::Length(info[0]), + Nan::To(info[1]).FromJust(), + &dec_packet_length + ); + + switch (r) { + case kErrNone: + return info.GetReturnValue().Set(dec_packet_length); + case kErrPartialDecrypt: + return Nan::ThrowError("Failed to completely decrypt packet length"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown decrypt failure"); + } + } + + static NAN_METHOD(Decrypt) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + ChaChaPolyDecipher* obj = + ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid packet"); + + if (!Buffer::HasInstance(info[1]) + || Buffer::Length(info[1]) != POLY1305_TAGLEN) { + return Nan::ThrowTypeError("Missing/Invalid mac"); + } + + if (!info[2]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid sequence number"); + + ErrorType r = obj->decrypt( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]), + reinterpret_cast(Buffer::Data(info[1])), + Nan::To(info[2]).FromJust() + ); + + switch (r) { + case kErrNone: + return; + case kErrInvalidMAC: + return Nan::ThrowError("Invalid MAC"); + case kErrPartialDecrypt: + return Nan::ThrowError("Failed to completely decrypt packet length"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown decrypt failure"); + } + } + + static NAN_METHOD(Free) { + ChaChaPolyDecipher* obj = + ObjectWrap::Unwrap(info.Holder()); + obj->clear(); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + unsigned char length_bytes[4]; + EVP_CIPHER_CTX* ctx_main_; + EVP_CIPHER_CTX* ctx_pktlen_; + EVP_MD_CTX* md_ctx_; + EVP_PKEY* polykey_; + EVP_PKEY_CTX* polykey_ctx_; +}; + +class AESGCMDecipher : public ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("AESGCMDecipher").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + SetPrototypeMethod(tpl, "decrypt", Decrypt); + SetPrototypeMethod(tpl, "free", Free); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + + Nan::Set(target, + Nan::New("AESGCMDecipher").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit AESGCMDecipher() : ctx_(nullptr) {} + + ~AESGCMDecipher() { + clear(); + } + + void clear() { + if (ctx_) { + EVP_CIPHER_CTX_cleanup(ctx_); + EVP_CIPHER_CTX_free(ctx_); + ctx_ = nullptr; + } + } + + ErrorType init(const char* name, + unsigned char* key, + size_t key_len, + unsigned char* iv, + size_t iv_len) { + ErrorType r = kErrNone; + + const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name); + if (cipher == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if (cipher != EVP_aes_128_gcm() && cipher != EVP_aes_256_gcm()) { + r = kErrBadCipherName; + goto out; + } + + if ((ctx_ = EVP_CIPHER_CTX_new()) == nullptr + || EVP_DecryptInit_ex(ctx_, cipher, nullptr, nullptr, nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_AEAD_SET_IVLEN, iv_len, nullptr)) { + r = kErrOpenSSL; + goto out; + } + + //~ if (iv_len != static_cast(EVP_CIPHER_CTX_iv_length(ctx_))) { + //~ r = kErrBadIVLen; + //~ goto out; + //~ } + + if (key_len != static_cast(EVP_CIPHER_CTX_key_length(ctx_))) { + if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) { + r = kErrBadKeyLen; + goto out; + } + } + + // Set key and IV + if (EVP_DecryptInit_ex(ctx_, nullptr, nullptr, key, iv) != 1) { + r = kErrOpenSSL; + goto out; + } + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) { + r = kErrOpenSSL; + goto out; + } + + // Disable padding + EVP_CIPHER_CTX_set_padding(ctx_, 0); + +out: + return r; + } + + ErrorType decrypt(unsigned char* packet, + uint32_t packet_len, + unsigned char* length_bytes, + unsigned char* tag) { + ErrorType r = kErrNone; + + // `packet` layout: + // + + int outlen; + + // Increment IV + unsigned char lastiv[1]; + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_IV_GEN, 1, lastiv)) { + r = kErrOpenSSL; + goto out; + } + + // Set AAD (the packet length) + if (!EVP_DecryptUpdate(ctx_, nullptr, &outlen, length_bytes, 4)) { + r = kErrOpenSSL; + goto out; + } + if (outlen != 4) { + r = kErrAADFailure; + goto out; + } + + // Decrypt everything but the packet length + if (EVP_DecryptUpdate(ctx_, packet, &outlen, packet, packet_len) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != packet_len) { + r = kErrPartialDecrypt; + goto out; + } + + // Set authentication tag + if (EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_AEAD_SET_TAG, 16, tag) != 1) { + r = kErrOpenSSL; + goto out; + } + + // Verify authentication tag + if (!EVP_DecryptFinal_ex(ctx_, nullptr, &outlen)) { + r = kErrOpenSSL; + goto out; + } + +out: + return r; + } + + static NAN_METHOD(New) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + if (!info[0]->IsString()) + return Nan::ThrowTypeError("Missing/Invalid OpenSSL cipher name"); + + if (!Buffer::HasInstance(info[1])) + return Nan::ThrowTypeError("Missing/Invalid key"); + + if (!Buffer::HasInstance(info[2])) + return Nan::ThrowTypeError("Missing/Invalid iv"); + + const Nan::Utf8String cipher_name(info[0]); + + AESGCMDecipher* obj = new AESGCMDecipher(); + ErrorType r = obj->init( + *cipher_name, + reinterpret_cast(Buffer::Data(info[1])), + Buffer::Length(info[1]), + reinterpret_cast(Buffer::Data(info[2])), + Buffer::Length(info[2]) + ); + if (r != kErrNone) { + if (r == kErrOpenSSL) { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + obj->clear(); + delete obj; + return Nan::ThrowError(msg_buf); + } + obj->clear(); + delete obj; + switch (r) { + case kErrBadKeyLen: + return Nan::ThrowError("Invalid keys length"); + case kErrBadIVLen: + return Nan::ThrowError("Invalid IV length"); + case kErrBadCipherName: + return Nan::ThrowError("Invalid AES GCM cipher name"); + default: + return Nan::ThrowError("Unknown init failure"); + } + } + + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } + + static NAN_METHOD(Decrypt) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + AESGCMDecipher* obj = ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid packet"); + + if (!info[1]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid length"); + + if (!Buffer::HasInstance(info[2]) || Buffer::Length(info[2]) != 16) + return Nan::ThrowTypeError("Missing/Invalid tag"); + + uint32_t length = Nan::To(info[1]).FromJust(); + unsigned char length_bytes[4]; + length_bytes[0] = (length >> 24) & 0xFF; + length_bytes[1] = (length >> 16) & 0xFF; + length_bytes[2] = (length >> 8) & 0xFF; + length_bytes[3] = length & 0xFF; + + ErrorType r = obj->decrypt( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]), + length_bytes, + reinterpret_cast(Buffer::Data(info[2])) + ); + switch (r) { + case kErrNone: + return; + case kErrAADFailure: + return Nan::ThrowError("Error setting AAD"); + case kErrPartialDecrypt: + return Nan::ThrowError("Failed to completely decrypt packet"); + case kErrTagFailure: + return Nan::ThrowError("Error generating authentication tag"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown decrypt failure"); + } + } + + static NAN_METHOD(Free) { + AESGCMDecipher* obj = ObjectWrap::Unwrap(info.Holder()); + obj->clear(); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + EVP_CIPHER_CTX* ctx_; +}; + +class GenericDecipher : public ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("GenericDecipher").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + SetPrototypeMethod(tpl, "decryptBlock", DecryptBlock); + SetPrototypeMethod(tpl, "decrypt", Decrypt); + SetPrototypeMethod(tpl, "free", Free); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + + Nan::Set(target, + Nan::New("GenericDecipher").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit GenericDecipher() + : ctx_(nullptr), + ctx_hmac_(nullptr), + hmac_len_(0), + is_etm_(0) {} + + ~GenericDecipher() { + clear(); + } + + void clear() { + if (ctx_) { + EVP_CIPHER_CTX_cleanup(ctx_); + EVP_CIPHER_CTX_free(ctx_); + ctx_ = nullptr; + } + if (ctx_hmac_) { + HMAC_CTX_free(ctx_hmac_); + ctx_hmac_ = nullptr; + } + } + + ErrorType init(const char* name, + unsigned char* key, + size_t key_len, + unsigned char* iv, + size_t iv_len, + const char* hmac_name, + unsigned char* hmac_key, + size_t hmac_key_len, + int is_etm, + size_t hmac_actual_len) { + ErrorType r = kErrNone; + + const EVP_MD* md; + const EVP_CIPHER* const cipher = EVP_get_cipherbyname(name); + if (cipher == nullptr) { + r = kErrOpenSSL; + goto out; + } + + if ((ctx_ = EVP_CIPHER_CTX_new()) == nullptr + || EVP_DecryptInit_ex(ctx_, cipher, nullptr, nullptr, nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + + if (iv_len != static_cast(EVP_CIPHER_CTX_iv_length(ctx_))) { + r = kErrBadIVLen; + goto out; + } + + if (key_len != static_cast(EVP_CIPHER_CTX_key_length(ctx_))) { + if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) { + r = kErrBadKeyLen; + goto out; + } + } + + // Set key and IV + if (EVP_DecryptInit_ex(ctx_, nullptr, nullptr, key, iv) != 1) { + r = kErrOpenSSL; + goto out; + } + + // Disable padding + EVP_CIPHER_CTX_set_padding(ctx_, 0); + + if (cipher == EVP_rc4()) { + /* The "arcfour128" algorithm is the RC4 cipher, as described in + [SCHNEIER], using a 128-bit key. The first 1536 bytes of keystream + generated by the cipher MUST be discarded, and the first byte of the + first encrypted packet MUST be encrypted using the 1537th byte of + keystream. + + -- http://tools.ietf.org/html/rfc4345#section-4 */ + unsigned char zeros[1536] = {0}; + int outlen = sizeof(zeros); + if (EVP_DecryptUpdate(ctx_, + zeros, + &outlen, + zeros, + sizeof(zeros)) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != sizeof(zeros)) { + r = kErrBadInit; + goto out; + } + } + + md = EVP_get_digestbyname(hmac_name); + if (md == nullptr) { + r = kErrBadHMACName; + goto out; + } + + if ((ctx_hmac_ = HMAC_CTX_new()) == nullptr + || HMAC_Init_ex(ctx_hmac_, hmac_key, hmac_key_len, md, nullptr) != 1) { + r = kErrOpenSSL; + goto out; + } + + hmac_len_ = HMAC_size(ctx_hmac_); + hmac_actual_len_ = hmac_actual_len; + is_etm_ = is_etm; + switch (EVP_CIPHER_CTX_mode(ctx_)) { + case EVP_CIPH_STREAM_CIPHER: + case EVP_CIPH_CTR_MODE: + is_stream_ = 1; + break; + default: + is_stream_ = 0; + } + block_size_ = EVP_CIPHER_CTX_block_size(ctx_); + +out: + return r; + } + + ErrorType decrypt_block(unsigned char* data, uint32_t data_len) { + ErrorType r = kErrNone; + + int outlen; + + if (!is_stream_ && data_len != block_size_) { + r = kErrBadBlockLen; + goto out; + } + + // Decrypt block + if (EVP_DecryptUpdate(ctx_, data, &outlen, data, data_len) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != data_len) { + r = kErrPartialDecrypt; + goto out; + } + +out: + return r; + } + + ErrorType decrypt(unsigned char* packet, + uint32_t packet_len, + uint32_t seqno, + unsigned char* first_block, + uint32_t first_block_len, + unsigned char* mac, + uint32_t mac_len) { + ErrorType r = kErrNone; + + int outlen; + unsigned char calc_mac[MAX_MAC_LEN] = {0}; + + uint8_t seqbuf[4] = {0}; + ((uint8_t*)(seqbuf))[0] = (seqno >> 24) & 0xff; + ((uint8_t*)(seqbuf))[1] = (seqno >> 16) & 0xff; + ((uint8_t*)(seqbuf))[2] = (seqno >> 8) & 0xff; + ((uint8_t*)(seqbuf))[3] = seqno & 0xff; + + if (is_etm_) { + // `first_block` for ETM should just be the unencrypted packet length + if (first_block_len != 4) { + r = kErrBadBlockLen; + goto out; + } + + // HMAC over unencrypted packet length and ciphertext + { + unsigned int outlen = hmac_len_; + if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1 + || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1 + || HMAC_Update(ctx_hmac_, first_block, 4) != 1 + || HMAC_Update(ctx_hmac_, packet, packet_len) != 1 + || HMAC_Final(ctx_hmac_, calc_mac, &outlen) != 1) { + r = kErrOpenSSL; + goto out; + } + + if (outlen != hmac_len_ || mac_len != hmac_len_) { + r = kErrBadHMACLen; + goto out; + } + + // Compare MACs + if (CRYPTO_memcmp(mac, calc_mac, hmac_len_)) { + r = kErrInvalidMAC; + goto out; + } + } + + // Decrypt packet + if (EVP_DecryptUpdate(ctx_, packet, &outlen, packet, packet_len) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != packet_len) { + r = kErrPartialDecrypt; + goto out; + } + } else { + // `first_block` for non-ETM should be a completely decrypted first block + if (!is_stream_ && first_block_len != block_size_) { + r = kErrBadBlockLen; + goto out; + } + + const int offset = (is_stream_ ? 0 : block_size_ - 4); + // Decrypt the rest of the packet + if (EVP_DecryptUpdate(ctx_, + packet + offset, + &outlen, + packet + offset, + packet_len - offset) != 1) { + r = kErrOpenSSL; + goto out; + } + if (static_cast(outlen) != packet_len - offset) { + r = kErrPartialDecrypt; + goto out; + } + + // HMAC over plaintext + { + unsigned int outlen = hmac_len_; + if (HMAC_Init_ex(ctx_hmac_, nullptr, 0, nullptr, nullptr) != 1 + || HMAC_Update(ctx_hmac_, seqbuf, sizeof(seqbuf)) != 1 + || HMAC_Update(ctx_hmac_, first_block, 4) != 1 + || HMAC_Update(ctx_hmac_, packet, packet_len) != 1 + || HMAC_Final(ctx_hmac_, calc_mac, &outlen) != 1) { + r = kErrOpenSSL; + goto out; + } + + if (outlen != hmac_len_ || mac_len != hmac_actual_len_) { + r = kErrBadHMACLen; + goto out; + } + + // Compare MACs + if (CRYPTO_memcmp(mac, calc_mac, hmac_actual_len_)) { + r = kErrInvalidMAC; + goto out; + } + } + } + +out: + return r; + } + + static NAN_METHOD(New) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + if (!info[0]->IsString()) + return Nan::ThrowTypeError("Missing/Invalid decipher name"); + + if (!Buffer::HasInstance(info[1])) + return Nan::ThrowTypeError("Missing/Invalid decipher key"); + + if (!Buffer::HasInstance(info[2])) + return Nan::ThrowTypeError("Missing/Invalid decipher IV"); + + if (!info[3]->IsString()) + return Nan::ThrowTypeError("Missing/Invalid HMAC name"); + + if (!Buffer::HasInstance(info[4])) + return Nan::ThrowTypeError("Missing/Invalid HMAC key"); + + if (!info[5]->IsBoolean()) + return Nan::ThrowTypeError("Missing/Invalid HMAC ETM flag"); + + if (!info[6]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid HMAC ETM flag"); + + const Nan::Utf8String cipher_name(info[0]); + const Nan::Utf8String mac_name(info[3]); + int is_etm = (Nan::To(info[5]).FromJust() ? 1 : 0); + + GenericDecipher* obj = new GenericDecipher(); + ErrorType r = obj->init( + *cipher_name, + reinterpret_cast(Buffer::Data(info[1])), + Buffer::Length(info[1]), + reinterpret_cast(Buffer::Data(info[2])), + Buffer::Length(info[2]), + *mac_name, + reinterpret_cast(Buffer::Data(info[4])), + Buffer::Length(info[4]), + is_etm, + Nan::To(info[6]).FromJust() + ); + if (r != kErrNone) { + if (r == kErrOpenSSL) { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + obj->clear(); + delete obj; + return Nan::ThrowError(msg_buf); + } + obj->clear(); + delete obj; + switch (r) { + case kErrBadKeyLen: + return Nan::ThrowError("Invalid decipher key length"); + case kErrBadIVLen: + return Nan::ThrowError("Invalid decipher IV length"); + case kErrBadCipherName: + return Nan::ThrowError("Invalid decipher name"); + case kErrBadHMACName: + return Nan::ThrowError("Invalid MAC name"); + case kErrBadInit: + return Nan::ThrowError("Failed to properly initialize decipher"); + default: + return Nan::ThrowError("Unknown init failure"); + } + } + + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } + + static NAN_METHOD(DecryptBlock) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + GenericDecipher* obj = ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid block"); + + ErrorType r = obj->decrypt_block( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]) + ); + switch (r) { + case kErrNone: + return; + case kErrBadBlockLen: + return Nan::ThrowError("Invalid block length"); + case kErrPartialDecrypt: + return Nan::ThrowError("Failed to completely decrypt packet"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown decrypt failure"); + } + } + + static NAN_METHOD(Decrypt) { + MarkPopErrorOnReturn mark_pop_error_on_return; + + GenericDecipher* obj = ObjectWrap::Unwrap(info.Holder()); + + if (!Buffer::HasInstance(info[0])) + return Nan::ThrowTypeError("Missing/Invalid packet"); + + if (!info[1]->IsUint32()) + return Nan::ThrowTypeError("Missing/Invalid sequence number"); + + if (!Buffer::HasInstance(info[2])) + return Nan::ThrowTypeError("Missing/Invalid first block"); + + if (!Buffer::HasInstance(info[3])) + return Nan::ThrowTypeError("Missing/Invalid MAC"); + + ErrorType r = obj->decrypt( + reinterpret_cast(Buffer::Data(info[0])), + Buffer::Length(info[0]), + Nan::To(info[1]).FromJust(), + reinterpret_cast(Buffer::Data(info[2])), + Buffer::Length(info[2]), + reinterpret_cast(Buffer::Data(info[3])), + Buffer::Length(info[3]) + ); + switch (r) { + case kErrNone: + return; + case kErrBadBlockLen: + return Nan::ThrowError("Invalid block length"); + case kErrPartialDecrypt: + return Nan::ThrowError("Failed to completely decrypt packet"); + case kErrBadHMACLen: + return Nan::ThrowError("Unexpected HMAC length"); + case kErrInvalidMAC: + return Nan::ThrowError("Invalid MAC"); + case kErrOpenSSL: { + char msg_buf[128] = {0}; + ERR_error_string_n(ERR_get_error(), msg_buf, sizeof(msg_buf)); + ERR_clear_error(); + return Nan::ThrowError(msg_buf); + } + default: + return Nan::ThrowError("Unknown decrypt failure"); + } + } + + static NAN_METHOD(Free) { + GenericDecipher* obj = ObjectWrap::Unwrap(info.Holder()); + obj->clear(); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + EVP_CIPHER_CTX* ctx_; + HMAC_CTX* ctx_hmac_; + unsigned int hmac_len_; + unsigned int hmac_actual_len_; + uint8_t is_etm_; + uint8_t is_stream_; + uint32_t block_size_; +}; + + +NAN_MODULE_INIT(init) { + ChaChaPolyCipher::Init(target); + AESGCMCipher::Init(target); + GenericCipher::Init(target); + + ChaChaPolyDecipher::Init(target); + AESGCMDecipher::Init(target); + GenericDecipher::Init(target); +} + +NODE_MODULE(sshcrypto, init) diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/handlers.js b/reverse_engineering/node_modules/ssh2/lib/protocol/handlers.js new file mode 100644 index 0000000..35fb9f2 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/handlers.js @@ -0,0 +1,16 @@ +'use strict'; + +const MESSAGE_HANDLERS = new Array(256); +[ + require('./kex.js').HANDLERS, + require('./handlers.misc.js'), +].forEach((handlers) => { + // eslint-disable-next-line prefer-const + for (let [type, handler] of Object.entries(handlers)) { + type = +type; + if (isFinite(type) && type >= 0 && type < MESSAGE_HANDLERS.length) + MESSAGE_HANDLERS[type] = handler; + } +}); + +module.exports = MESSAGE_HANDLERS; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/handlers.misc.js b/reverse_engineering/node_modules/ssh2/lib/protocol/handlers.misc.js new file mode 100644 index 0000000..647564b --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/handlers.misc.js @@ -0,0 +1,1214 @@ +'use strict'; + +const { + bufferSlice, + bufferParser, + doFatalError, + sigSSHToASN1, + writeUInt32BE, +} = require('./utils.js'); + +const { + CHANNEL_OPEN_FAILURE, + COMPAT, + MESSAGE, + TERMINAL_MODE, +} = require('./constants.js'); + +const { + parseKey, +} = require('./keyParser.js'); + +const TERMINAL_MODE_BY_VALUE = + Array.from(Object.entries(TERMINAL_MODE)) + .reduce((obj, [key, value]) => ({ ...obj, [key]: value }), {}); + +module.exports = { + // Transport layer protocol ================================================== + [MESSAGE.DISCONNECT]: (self, payload) => { + /* + byte SSH_MSG_DISCONNECT + uint32 reason code + string description in ISO-10646 UTF-8 encoding + string language tag + */ + bufferParser.init(payload, 1); + const reason = bufferParser.readUInt32BE(); + const desc = bufferParser.readString(true); + const lang = bufferParser.readString(); + bufferParser.clear(); + + if (lang === undefined) { + return doFatalError( + self, + 'Inbound: Malformed DISCONNECT packet' + ); + } + + self._debug && self._debug( + `Inbound: Received DISCONNECT (${reason}, "${desc}")` + ); + + const handler = self._handlers.DISCONNECT; + handler && handler(self, reason, desc); + }, + [MESSAGE.IGNORE]: (self, payload) => { + /* + byte SSH_MSG_IGNORE + string data + */ + self._debug && self._debug('Inbound: Received IGNORE'); + }, + [MESSAGE.UNIMPLEMENTED]: (self, payload) => { + /* + byte SSH_MSG_UNIMPLEMENTED + uint32 packet sequence number of rejected message + */ + bufferParser.init(payload, 1); + const seqno = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (seqno === undefined) { + return doFatalError( + self, + 'Inbound: Malformed UNIMPLEMENTED packet' + ); + } + + self._debug + && self._debug(`Inbound: Received UNIMPLEMENTED (seqno ${seqno})`); + }, + [MESSAGE.DEBUG]: (self, payload) => { + /* + byte SSH_MSG_DEBUG + boolean always_display + string message in ISO-10646 UTF-8 encoding [RFC3629] + string language tag [RFC3066] + */ + bufferParser.init(payload, 1); + const display = bufferParser.readBool(); + const msg = bufferParser.readString(true); + const lang = bufferParser.readString(); + bufferParser.clear(); + + if (lang === undefined) { + return doFatalError( + self, + 'Inbound: Malformed DEBUG packet' + ); + } + + self._debug && self._debug('Inbound: Received DEBUG'); + + const handler = self._handlers.DEBUG; + handler && handler(self, display, msg); + }, + [MESSAGE.SERVICE_REQUEST]: (self, payload) => { + /* + byte SSH_MSG_SERVICE_REQUEST + string service name + */ + bufferParser.init(payload, 1); + const name = bufferParser.readString(true); + bufferParser.clear(); + + if (name === undefined) { + return doFatalError( + self, + 'Inbound: Malformed SERVICE_REQUEST packet' + ); + } + + self._debug && self._debug(`Inbound: Received SERVICE_REQUEST (${name})`); + + const handler = self._handlers.SERVICE_REQUEST; + handler && handler(self, name); + }, + [MESSAGE.SERVICE_ACCEPT]: (self, payload) => { + // S->C + /* + byte SSH_MSG_SERVICE_ACCEPT + string service name + */ + bufferParser.init(payload, 1); + const name = bufferParser.readString(true); + bufferParser.clear(); + + if (name === undefined) { + return doFatalError( + self, + 'Inbound: Malformed SERVICE_ACCEPT packet' + ); + } + + self._debug && self._debug(`Inbound: Received SERVICE_ACCEPT (${name})`); + + const handler = self._handlers.SERVICE_ACCEPT; + handler && handler(self, name); + }, + + // User auth protocol -- generic ============================================= + [MESSAGE.USERAUTH_REQUEST]: (self, payload) => { + /* + byte SSH_MSG_USERAUTH_REQUEST + string user name in ISO-10646 UTF-8 encoding [RFC3629] + string service name in US-ASCII + string method name in US-ASCII + .... method specific fields + */ + bufferParser.init(payload, 1); + const user = bufferParser.readString(true); + const service = bufferParser.readString(true); + const method = bufferParser.readString(true); + let methodData; + let methodDesc; + switch (method) { + case 'none': + methodData = null; + break; + case 'password': { + /* + boolean + string plaintext password in ISO-10646 UTF-8 encoding [RFC3629] + [string new password] + */ + const isChange = bufferParser.readBool(); + if (isChange !== undefined) { + methodData = bufferParser.readString(true); + if (methodData !== undefined && isChange) { + const newPassword = bufferParser.readString(true); + if (newPassword !== undefined) + methodData = { oldPassword: methodData, newPassword }; + else + methodData = undefined; + } + } + break; + } + case 'publickey': { + /* + boolean + string public key algorithm name + string public key blob + [string signature] + */ + const hasSig = bufferParser.readBool(); + if (hasSig !== undefined) { + const keyAlgo = bufferParser.readString(true); + const key = bufferParser.readString(); + if (hasSig) { + const blobEnd = bufferParser.pos(); + let signature = bufferParser.readString(); + if (signature !== undefined) { + if (signature.length > (4 + keyAlgo.length + 4) + && signature.utf8Slice(4, 4 + keyAlgo.length) === keyAlgo) { + // Skip algoLen + algo + sigLen + signature = bufferSlice(signature, 4 + keyAlgo.length + 4); + } + + signature = sigSSHToASN1(signature, keyAlgo); + if (signature) { + const sessionID = self._kex.sessionID; + const blob = Buffer.allocUnsafe(4 + sessionID.length + blobEnd); + writeUInt32BE(blob, sessionID.length, 0); + blob.set(sessionID, 4); + blob.set( + new Uint8Array(payload.buffer, payload.byteOffset, blobEnd), + 4 + sessionID.length + ); + methodData = { + keyAlgo, + key, + signature, + blob, + }; + } + } + } else { + methodData = { keyAlgo, key }; + methodDesc = 'publickey -- check'; + } + } + break; + } + case 'hostbased': { + /* + string public key algorithm for host key + string public host key and certificates for client host + string client host name expressed as the FQDN in US-ASCII + string user name on the client host in ISO-10646 UTF-8 encoding + [RFC3629] + string signature + */ + const keyAlgo = bufferParser.readString(true); + const key = bufferParser.readString(); + const localHostname = bufferParser.readString(true); + const localUsername = bufferParser.readString(true); + + const blobEnd = bufferParser.pos(); + let signature = bufferParser.readString(); + if (signature !== undefined) { + if (signature.length > (4 + keyAlgo.length + 4) + && signature.utf8Slice(4, 4 + keyAlgo.length) === keyAlgo) { + // Skip algoLen + algo + sigLen + signature = bufferSlice(signature, 4 + keyAlgo.length + 4); + } + + signature = sigSSHToASN1(signature, keyAlgo); + if (signature !== undefined) { + const sessionID = self._kex.sessionID; + const blob = Buffer.allocUnsafe(4 + sessionID.length + blobEnd); + writeUInt32BE(blob, sessionID.length, 0); + blob.set(sessionID, 4); + blob.set( + new Uint8Array(payload.buffer, payload.byteOffset, blobEnd), + 4 + sessionID.length + ); + methodData = { + keyAlgo, + key, + signature, + blob, + localHostname, + localUsername, + }; + } + } + break; + } + case 'keyboard-interactive': + /* + string language tag (as defined in [RFC-3066]) + string submethods (ISO-10646 UTF-8) + */ + // Skip/ignore language field -- it's deprecated in RFC 4256 + bufferParser.skipString(); + + methodData = bufferParser.readList(); + break; + default: + if (method !== undefined) + methodData = bufferParser.readRaw(); + } + bufferParser.clear(); + + if (methodData === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_REQUEST packet' + ); + } + + if (methodDesc === undefined) + methodDesc = method; + + self._authsQueue.push(method); + + self._debug + && self._debug(`Inbound: Received USERAUTH_REQUEST (${methodDesc})`); + + const handler = self._handlers.USERAUTH_REQUEST; + handler && handler(self, user, service, method, methodData); + }, + [MESSAGE.USERAUTH_FAILURE]: (self, payload) => { + // S->C + /* + byte SSH_MSG_USERAUTH_FAILURE + name-list authentications that can continue + boolean partial success + */ + bufferParser.init(payload, 1); + const authMethods = bufferParser.readList(); + const partialSuccess = bufferParser.readBool(); + bufferParser.clear(); + + if (partialSuccess === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_FAILURE packet' + ); + } + + self._debug + && self._debug(`Inbound: Received USERAUTH_FAILURE (${authMethods})`); + + self._authsQueue.shift(); + const handler = self._handlers.USERAUTH_FAILURE; + handler && handler(self, authMethods, partialSuccess); + }, + [MESSAGE.USERAUTH_SUCCESS]: (self, payload) => { + // S->C + /* + byte SSH_MSG_USERAUTH_SUCCESS + */ + self._debug && self._debug('Inbound: Received USERAUTH_SUCCESS'); + + self._authsQueue.shift(); + const handler = self._handlers.USERAUTH_SUCCESS; + handler && handler(self); + }, + [MESSAGE.USERAUTH_BANNER]: (self, payload) => { + // S->C + /* + byte SSH_MSG_USERAUTH_BANNER + string message in ISO-10646 UTF-8 encoding [RFC3629] + string language tag [RFC3066] + */ + bufferParser.init(payload, 1); + const msg = bufferParser.readString(true); + const lang = bufferParser.readString(); + bufferParser.clear(); + + if (lang === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_BANNER packet' + ); + } + + self._debug && self._debug('Inbound: Received USERAUTH_BANNER'); + + const handler = self._handlers.USERAUTH_BANNER; + handler && handler(self, msg); + }, + + // User auth protocol -- method-specific ===================================== + 60: (self, payload) => { + if (!self._authsQueue.length) { + self._debug + && self._debug('Inbound: Received payload type 60 without auth'); + return; + } + + switch (self._authsQueue[0]) { + case 'password': { + // S->C + /* + byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ + string prompt in ISO-10646 UTF-8 encoding [RFC3629] + string language tag [RFC3066] + */ + bufferParser.init(payload, 1); + const prompt = bufferParser.readString(true); + const lang = bufferParser.readString(); + bufferParser.clear(); + + if (lang === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_PASSWD_CHANGEREQ packet' + ); + } + + self._debug + && self._debug('Inbound: Received USERAUTH_PASSWD_CHANGEREQ'); + + const handler = self._handlers.USERAUTH_PASSWD_CHANGEREQ; + handler && handler(self, prompt); + break; + } + case 'publickey': { + // S->C + /* + byte SSH_MSG_USERAUTH_PK_OK + string public key algorithm name from the request + string public key blob from the request + */ + bufferParser.init(payload, 1); + const keyAlgo = bufferParser.readString(true); + const key = bufferParser.readString(); + bufferParser.clear(); + + if (key === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_PK_OK packet' + ); + } + + self._debug && self._debug('Inbound: Received USERAUTH_PK_OK'); + + self._authsQueue.shift(); + const handler = self._handlers.USERAUTH_PK_OK; + handler && handler(self, keyAlgo, key); + break; + } + case 'keyboard-interactive': { + // S->C + /* + byte SSH_MSG_USERAUTH_INFO_REQUEST + string name (ISO-10646 UTF-8) + string instruction (ISO-10646 UTF-8) + string language tag (as defined in [RFC-3066]) + int num-prompts + string prompt[1] (ISO-10646 UTF-8) + boolean echo[1] + ... + string prompt[num-prompts] (ISO-10646 UTF-8) + boolean echo[num-prompts] + */ + bufferParser.init(payload, 1); + const name = bufferParser.readString(true); + const instructions = bufferParser.readString(true); + bufferParser.readString(); // skip lang + const numPrompts = bufferParser.readUInt32BE(); + let prompts; + if (numPrompts !== undefined) { + prompts = new Array(numPrompts); + let i; + for (i = 0; i < numPrompts; ++i) { + const prompt = bufferParser.readString(true); + const echo = bufferParser.readBool(); + if (echo === undefined) + break; + prompts[i] = { prompt, echo }; + } + if (i !== numPrompts) + prompts = undefined; + } + bufferParser.clear(); + + if (prompts === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_INFO_REQUEST packet' + ); + } + + self._debug && self._debug('Inbound: Received USERAUTH_INFO_REQUEST'); + + const handler = self._handlers.USERAUTH_INFO_REQUEST; + handler && handler(self, name, instructions, prompts); + break; + } + default: + self._debug + && self._debug('Inbound: Received unexpected payload type 60'); + } + }, + 61: (self, payload) => { + if (!self._authsQueue.length) { + self._debug + && self._debug('Inbound: Received payload type 61 without auth'); + return; + } + /* + byte SSH_MSG_USERAUTH_INFO_RESPONSE + int num-responses + string response[1] (ISO-10646 UTF-8) + ... + string response[num-responses] (ISO-10646 UTF-8) + */ + if (self._authsQueue[0] !== 'keyboard-interactive') { + return doFatalError( + self, + 'Inbound: Received unexpected payload type 61' + ); + } + bufferParser.init(payload, 1); + const numResponses = bufferParser.readUInt32BE(); + let responses; + if (numResponses !== undefined) { + responses = new Array(numResponses); + let i; + for (i = 0; i < numResponses; ++i) { + const response = bufferParser.readString(true); + if (response === undefined) + break; + responses[i] = response; + } + if (i !== numResponses) + responses = undefined; + } + bufferParser.clear(); + + if (responses === undefined) { + return doFatalError( + self, + 'Inbound: Malformed USERAUTH_INFO_RESPONSE packet' + ); + } + + self._debug && self._debug('Inbound: Received USERAUTH_INFO_RESPONSE'); + + const handler = self._handlers.USERAUTH_INFO_RESPONSE; + handler && handler(self, responses); + }, + + // Connection protocol -- generic ============================================ + [MESSAGE.GLOBAL_REQUEST]: (self, payload) => { + /* + byte SSH_MSG_GLOBAL_REQUEST + string request name in US-ASCII only + boolean want reply + .... request-specific data follows + */ + bufferParser.init(payload, 1); + const name = bufferParser.readString(true); + const wantReply = bufferParser.readBool(); + let data; + if (wantReply !== undefined) { + switch (name) { + case 'tcpip-forward': + case 'cancel-tcpip-forward': { + /* + string address to bind (e.g., "0.0.0.0") + uint32 port number to bind + */ + const bindAddr = bufferParser.readString(true); + const bindPort = bufferParser.readUInt32BE(); + if (bindPort !== undefined) + data = { bindAddr, bindPort }; + break; + } + case 'streamlocal-forward@openssh.com': + case 'cancel-streamlocal-forward@openssh.com': { + /* + string socket path + */ + const socketPath = bufferParser.readString(true); + if (socketPath !== undefined) + data = { socketPath }; + break; + } + case 'no-more-sessions@openssh.com': + data = null; + break; + case 'hostkeys-00@openssh.com': { + data = []; + while (bufferParser.avail() > 0) { + const keyRaw = bufferParser.readString(); + if (keyRaw === undefined) { + data = undefined; + break; + } + const key = parseKey(keyRaw); + if (!(key instanceof Error)) + data.push(key); + } + break; + } + default: + data = bufferParser.readRaw(); + } + } + bufferParser.clear(); + + if (data === undefined) { + return doFatalError( + self, + 'Inbound: Malformed GLOBAL_REQUEST packet' + ); + } + + self._debug && self._debug(`Inbound: GLOBAL_REQUEST (${name})`); + + const handler = self._handlers.GLOBAL_REQUEST; + if (handler) + handler(self, name, wantReply, data); + else + self.requestFailure(); // Auto reject + }, + [MESSAGE.REQUEST_SUCCESS]: (self, payload) => { + /* + byte SSH_MSG_REQUEST_SUCCESS + .... response specific data + */ + const data = (payload.length > 1 ? bufferSlice(payload, 1) : null); + + self._debug && self._debug('Inbound: REQUEST_SUCCESS'); + + const handler = self._handlers.REQUEST_SUCCESS; + handler && handler(self, data); + }, + [MESSAGE.REQUEST_FAILURE]: (self, payload) => { + /* + byte SSH_MSG_REQUEST_FAILURE + */ + self._debug && self._debug('Inbound: Received REQUEST_FAILURE'); + + const handler = self._handlers.REQUEST_FAILURE; + handler && handler(self); + }, + + // Connection protocol -- channel-related ==================================== + [MESSAGE.CHANNEL_OPEN]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_OPEN + string channel type in US-ASCII only + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + .... channel type specific data follows + */ + bufferParser.init(payload, 1); + const type = bufferParser.readString(true); + const sender = bufferParser.readUInt32BE(); + const window = bufferParser.readUInt32BE(); + const packetSize = bufferParser.readUInt32BE(); + let channelInfo; + + switch (type) { + case 'forwarded-tcpip': // S->C + case 'direct-tcpip': { // C->S + /* + string address that was connected / host to connect + uint32 port that was connected / port to connect + string originator IP address + uint32 originator port + */ + const destIP = bufferParser.readString(true); + const destPort = bufferParser.readUInt32BE(); + const srcIP = bufferParser.readString(true); + const srcPort = bufferParser.readUInt32BE(); + if (srcPort !== undefined) { + channelInfo = { + type, + sender, + window, + packetSize, + data: { destIP, destPort, srcIP, srcPort } + }; + } + break; + } + case 'forwarded-streamlocal@openssh.com': // S->C + case 'direct-streamlocal@openssh.com': { // C->S + /* + string socket path + string reserved for future use + + (direct-streamlocal@openssh.com additionally has:) + uint32 reserved + */ + const socketPath = bufferParser.readString(true); + if (socketPath !== undefined) { + channelInfo = { + type, + sender, + window, + packetSize, + data: { socketPath } + }; + } + break; + } + case 'x11': { // S->C + /* + string originator address (e.g., "192.168.7.38") + uint32 originator port + */ + const srcIP = bufferParser.readString(true); + const srcPort = bufferParser.readUInt32BE(); + if (srcPort !== undefined) { + channelInfo = { + type, + sender, + window, + packetSize, + data: { srcIP, srcPort } + }; + } + break; + } + default: + // Includes: + // 'session' (C->S) + // 'auth-agent@openssh.com' (S->C) + channelInfo = { + type, + sender, + window, + packetSize, + data: {} + }; + } + bufferParser.clear(); + + if (channelInfo === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_OPEN packet' + ); + } + + self._debug && self._debug(`Inbound: CHANNEL_OPEN (s:${sender}, ${type})`); + + const handler = self._handlers.CHANNEL_OPEN; + if (handler) { + handler(self, channelInfo); + } else { + self.channelOpenFail( + channelInfo.sender, + CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED, + '', + '' + ); + } + }, + [MESSAGE.CHANNEL_OPEN_CONFIRMATION]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION + uint32 recipient channel + uint32 sender channel + uint32 initial window size + uint32 maximum packet size + .... channel type specific data follows + */ + // "The 'recipient channel' is the channel number given in the + // original open request, and 'sender channel' is the channel number + // allocated by the other side." + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + const sender = bufferParser.readUInt32BE(); + const window = bufferParser.readUInt32BE(); + const packetSize = bufferParser.readUInt32BE(); + const data = (bufferParser.avail() ? bufferParser.readRaw() : undefined); + bufferParser.clear(); + + if (packetSize === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_OPEN_CONFIRMATION packet' + ); + } + + self._debug && self._debug( + `Inbound: CHANNEL_OPEN_CONFIRMATION (r:${recipient}, s:${sender})` + ); + + const handler = self._handlers.CHANNEL_OPEN_CONFIRMATION; + if (handler) + handler(self, { recipient, sender, window, packetSize, data }); + }, + [MESSAGE.CHANNEL_OPEN_FAILURE]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_OPEN_FAILURE + uint32 recipient channel + uint32 reason code + string description in ISO-10646 UTF-8 encoding [RFC3629] + string language tag [RFC3066] + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + const reason = bufferParser.readUInt32BE(); + const description = bufferParser.readString(true); + const lang = bufferParser.readString(); + bufferParser.clear(); + + if (lang === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_OPEN_FAILURE packet' + ); + } + + self._debug + && self._debug(`Inbound: CHANNEL_OPEN_FAILURE (r:${recipient})`); + + const handler = self._handlers.CHANNEL_OPEN_FAILURE; + handler && handler(self, recipient, reason, description); + }, + [MESSAGE.CHANNEL_WINDOW_ADJUST]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_WINDOW_ADJUST + uint32 recipient channel + uint32 bytes to add + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + const bytesToAdd = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (bytesToAdd === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_WINDOW_ADJUST packet' + ); + } + + self._debug && self._debug( + `Inbound: CHANNEL_WINDOW_ADJUST (r:${recipient}, ${bytesToAdd})` + ); + + const handler = self._handlers.CHANNEL_WINDOW_ADJUST; + handler && handler(self, recipient, bytesToAdd); + }, + [MESSAGE.CHANNEL_DATA]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_DATA + uint32 recipient channel + string data + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + const data = bufferParser.readString(); + bufferParser.clear(); + + if (data === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_DATA packet' + ); + } + + self._debug + && self._debug(`Inbound: CHANNEL_DATA (r:${recipient}, ${data.length})`); + + const handler = self._handlers.CHANNEL_DATA; + handler && handler(self, recipient, data); + }, + [MESSAGE.CHANNEL_EXTENDED_DATA]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_EXTENDED_DATA + uint32 recipient channel + uint32 data_type_code + string data + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + const type = bufferParser.readUInt32BE(); + const data = bufferParser.readString(); + bufferParser.clear(); + + if (data === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_EXTENDED_DATA packet' + ); + } + + self._debug && self._debug( + `Inbound: CHANNEL_EXTENDED_DATA (r:${recipient}, ${data.length})` + ); + + const handler = self._handlers.CHANNEL_EXTENDED_DATA; + handler && handler(self, recipient, data, type); + }, + [MESSAGE.CHANNEL_EOF]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_EOF + uint32 recipient channel + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (recipient === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_EOF packet' + ); + } + + self._debug && self._debug(`Inbound: CHANNEL_EOF (r:${recipient})`); + + const handler = self._handlers.CHANNEL_EOF; + handler && handler(self, recipient); + }, + [MESSAGE.CHANNEL_CLOSE]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_CLOSE + uint32 recipient channel + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (recipient === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_CLOSE packet' + ); + } + + self._debug && self._debug(`Inbound: CHANNEL_CLOSE (r:${recipient})`); + + const handler = self._handlers.CHANNEL_CLOSE; + handler && handler(self, recipient); + }, + [MESSAGE.CHANNEL_REQUEST]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_REQUEST + uint32 recipient channel + string request type in US-ASCII characters only + boolean want reply + .... type-specific data follows + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + const type = bufferParser.readString(true); + const wantReply = bufferParser.readBool(); + let data; + if (wantReply !== undefined) { + switch (type) { + case 'exit-status': // S->C + /* + uint32 exit_status + */ + data = bufferParser.readUInt32BE(); + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ${data})` + ); + break; + case 'exit-signal': { // S->C + /* + string signal name (without the "SIG" prefix) + boolean core dumped + string error message in ISO-10646 UTF-8 encoding + string language tag + */ + let signal; + let coreDumped; + if (self._compatFlags & COMPAT.OLD_EXIT) { + /* + Instead of `signal name` and `core dumped`, we have just: + uint32 signal number + */ + const num = bufferParser.readUInt32BE(); + switch (num) { + case 1: + signal = 'HUP'; + break; + case 2: + signal = 'INT'; + break; + case 3: + signal = 'QUIT'; + break; + case 6: + signal = 'ABRT'; + break; + case 9: + signal = 'KILL'; + break; + case 14: + signal = 'ALRM'; + break; + case 15: + signal = 'TERM'; + break; + default: + if (num !== undefined) { + // Unknown or OS-specific + signal = `UNKNOWN (${num})`; + } + } + coreDumped = false; + } else { + signal = bufferParser.readString(true); + coreDumped = bufferParser.readBool(); + if (coreDumped === undefined) + signal = undefined; + } + const errorMessage = bufferParser.readString(true); + if (bufferParser.skipString() !== undefined) + data = { signal, coreDumped, errorMessage }; + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ${signal})` + ); + break; + } + case 'pty-req': { // C->S + /* + string TERM environment variable value (e.g., vt100) + uint32 terminal width, characters (e.g., 80) + uint32 terminal height, rows (e.g., 24) + uint32 terminal width, pixels (e.g., 640) + uint32 terminal height, pixels (e.g., 480) + string encoded terminal modes + */ + const term = bufferParser.readString(true); + const cols = bufferParser.readUInt32BE(); + const rows = bufferParser.readUInt32BE(); + const width = bufferParser.readUInt32BE(); + const height = bufferParser.readUInt32BE(); + const modesBinary = bufferParser.readString(); + if (modesBinary !== undefined) { + bufferParser.init(modesBinary, 1); + let modes = {}; + while (bufferParser.avail()) { + const opcode = bufferParser.readByte(); + if (opcode === TERMINAL_MODE.TTY_OP_END) + break; + const name = TERMINAL_MODE_BY_VALUE[opcode]; + const value = bufferParser.readUInt32BE(); + if (opcode === undefined + || name === undefined + || value === undefined) { + modes = undefined; + break; + } + modes[name] = value; + } + if (modes !== undefined) + data = { term, cols, rows, width, height, modes }; + } + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type})` + ); + break; + } + case 'window-change': { // C->S + /* + uint32 terminal width, columns + uint32 terminal height, rows + uint32 terminal width, pixels + uint32 terminal height, pixels + */ + const cols = bufferParser.readUInt32BE(); + const rows = bufferParser.readUInt32BE(); + const width = bufferParser.readUInt32BE(); + const height = bufferParser.readUInt32BE(); + if (height !== undefined) + data = { cols, rows, width, height }; + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type})` + ); + break; + } + case 'x11-req': { // C->S + /* + boolean single connection + string x11 authentication protocol + string x11 authentication cookie + uint32 x11 screen number + */ + const single = bufferParser.readBool(); + const protocol = bufferParser.readString(true); + const cookie = bufferParser.readString(); + const screen = bufferParser.readUInt32BE(); + if (screen !== undefined) + data = { single, protocol, cookie, screen }; + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type})` + ); + break; + } + case 'env': { // C->S + /* + string variable name + string variable value + */ + const name = bufferParser.readString(true); + const value = bufferParser.readString(true); + if (value !== undefined) + data = { name, value }; + if (self._debug) { + self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ` + + `${name}=${value})` + ); + } + break; + } + case 'shell': // C->S + data = null; // No extra data + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type})` + ); + break; + case 'exec': // C->S + /* + string command + */ + data = bufferParser.readString(true); + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ${data})` + ); + break; + case 'subsystem': // C->S + /* + string subsystem name + */ + data = bufferParser.readString(true); + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ${data})` + ); + break; + case 'signal': // C->S + /* + string signal name (without the "SIG" prefix) + */ + data = bufferParser.readString(true); + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ${data})` + ); + break; + case 'xon-xoff': // C->S + /* + boolean client can do + */ + data = bufferParser.readBool(); + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type}: ${data})` + ); + break; + case 'auth-agent-req@openssh.com': // C-S + data = null; // No extra data + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type})` + ); + break; + default: + data = (bufferParser.avail() ? bufferParser.readRaw() : null); + self._debug && self._debug( + `Inbound: CHANNEL_REQUEST (r:${recipient}, ${type})` + ); + } + } + bufferParser.clear(); + + if (data === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_REQUEST packet' + ); + } + + const handler = self._handlers.CHANNEL_REQUEST; + handler && handler(self, recipient, type, wantReply, data); + }, + [MESSAGE.CHANNEL_SUCCESS]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_SUCCESS + uint32 recipient channel + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (recipient === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_SUCCESS packet' + ); + } + + self._debug && self._debug(`Inbound: CHANNEL_SUCCESS (r:${recipient})`); + + const handler = self._handlers.CHANNEL_SUCCESS; + handler && handler(self, recipient); + }, + [MESSAGE.CHANNEL_FAILURE]: (self, payload) => { + /* + byte SSH_MSG_CHANNEL_FAILURE + uint32 recipient channel + */ + bufferParser.init(payload, 1); + const recipient = bufferParser.readUInt32BE(); + bufferParser.clear(); + + if (recipient === undefined) { + return doFatalError( + self, + 'Inbound: Malformed CHANNEL_FAILURE packet' + ); + } + + self._debug && self._debug(`Inbound: CHANNEL_FAILURE (r:${recipient})`); + + const handler = self._handlers.CHANNEL_FAILURE; + handler && handler(self, recipient); + }, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/kex.js b/reverse_engineering/node_modules/ssh2/lib/protocol/kex.js new file mode 100644 index 0000000..507c88a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/kex.js @@ -0,0 +1,1831 @@ +'use strict'; + +const { + createDiffieHellman, + createDiffieHellmanGroup, + createECDH, + createHash, + createPublicKey, + diffieHellman, + generateKeyPairSync, + randomFillSync, +} = require('crypto'); + +const { Ber } = require('asn1'); + +const { + COMPAT, + curve25519Supported, + DEFAULT_KEX, + DEFAULT_SERVER_HOST_KEY, + DEFAULT_CIPHER, + DEFAULT_MAC, + DEFAULT_COMPRESSION, + DISCONNECT_REASON, + MESSAGE, +} = require('./constants.js'); +const { + CIPHER_INFO, + createCipher, + createDecipher, + MAC_INFO, +} = require('./crypto.js'); +const { parseDERKey } = require('./keyParser.js'); +const { + bufferFill, + bufferParser, + convertSignature, + doFatalError, + FastBuffer, + sigSSHToASN1, + writeUInt32BE, +} = require('./utils.js'); +const { + PacketReader, + PacketWriter, + ZlibPacketReader, + ZlibPacketWriter, +} = require('./zlib.js'); + +let MESSAGE_HANDLERS; + +const GEX_MIN_BITS = 2048; // RFC 8270 +const GEX_MAX_BITS = 8192; // RFC 8270 + +const EMPTY_BUFFER = Buffer.alloc(0); + +// Client/Server +function kexinit(self) { + /* + byte SSH_MSG_KEXINIT + byte[16] cookie (random bytes) + name-list kex_algorithms + name-list server_host_key_algorithms + name-list encryption_algorithms_client_to_server + name-list encryption_algorithms_server_to_client + name-list mac_algorithms_client_to_server + name-list mac_algorithms_server_to_client + name-list compression_algorithms_client_to_server + name-list compression_algorithms_server_to_client + name-list languages_client_to_server + name-list languages_server_to_client + boolean first_kex_packet_follows + uint32 0 (reserved for future extension) + */ + + let payload; + if (self._compatFlags & COMPAT.BAD_DHGEX) { + const entry = self._offer.lists.kex; + let kex = entry.array; + let found = false; + for (let i = 0; i < kex.length; ++i) { + if (kex[i].indexOf('group-exchange') !== -1) { + if (!found) { + found = true; + // Copy array lazily + kex = kex.slice(); + } + kex.splice(i--, 1); + } + } + if (found) { + let len = 1 + 16 + self._offer.totalSize + 1 + 4; + const newKexBuf = Buffer.from(kex.join(',')); + len -= (entry.buffer.length - newKexBuf.length); + + const all = self._offer.lists.all; + const rest = new Uint8Array( + all.buffer, + all.byteOffset + 4 + entry.buffer.length, + all.length - (4 + entry.buffer.length) + ); + + payload = Buffer.allocUnsafe(len); + writeUInt32BE(payload, newKexBuf.length, 0); + payload.set(newKexBuf, 4); + payload.set(rest, 4 + newKexBuf.length); + } + } + + if (payload === undefined) { + payload = Buffer.allocUnsafe(1 + 16 + self._offer.totalSize + 1 + 4); + self._offer.copyAllTo(payload, 17); + } + + self._debug && self._debug('Outbound: Sending KEXINIT'); + + payload[0] = MESSAGE.KEXINIT; + randomFillSync(payload, 1, 16); + + // Zero-fill first_kex_packet_follows and reserved bytes + bufferFill(payload, 0, payload.length - 5); + + self._kexinit = payload; + + // Needed to correct the starting position in allocated "packets" when packets + // will be buffered due to active key exchange + self._packetRW.write.allocStart = 0; + + // TODO: only create single buffer and set _kexinit as slice of packet instead + { + const p = self._packetRW.write.allocStartKEX; + const packet = self._packetRW.write.alloc(payload.length, true); + packet.set(payload, p); + self._cipher.encrypt(self._packetRW.write.finalize(packet, true)); + } +} + +function handleKexInit(self, payload) { + /* + byte SSH_MSG_KEXINIT + byte[16] cookie (random bytes) + name-list kex_algorithms + name-list server_host_key_algorithms + name-list encryption_algorithms_client_to_server + name-list encryption_algorithms_server_to_client + name-list mac_algorithms_client_to_server + name-list mac_algorithms_server_to_client + name-list compression_algorithms_client_to_server + name-list compression_algorithms_server_to_client + name-list languages_client_to_server + name-list languages_server_to_client + boolean first_kex_packet_follows + uint32 0 (reserved for future extension) + */ + const init = { + kex: undefined, + serverHostKey: undefined, + cs: { + cipher: undefined, + mac: undefined, + compress: undefined, + lang: undefined, + }, + sc: { + cipher: undefined, + mac: undefined, + compress: undefined, + lang: undefined, + }, + }; + + bufferParser.init(payload, 17); + + if ((init.kex = bufferParser.readList()) === undefined + || (init.serverHostKey = bufferParser.readList()) === undefined + || (init.cs.cipher = bufferParser.readList()) === undefined + || (init.sc.cipher = bufferParser.readList()) === undefined + || (init.cs.mac = bufferParser.readList()) === undefined + || (init.sc.mac = bufferParser.readList()) === undefined + || (init.cs.compress = bufferParser.readList()) === undefined + || (init.sc.compress = bufferParser.readList()) === undefined + || (init.cs.lang = bufferParser.readList()) === undefined + || (init.sc.lang = bufferParser.readList()) === undefined) { + bufferParser.clear(); + return doFatalError( + self, + 'Received malformed KEXINIT', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + const pos = bufferParser.pos(); + const firstFollows = (pos < payload.length && payload[pos] === 1); + bufferParser.clear(); + + const local = self._offer; + const remote = init; + + let localKex = local.lists.kex.array; + if (self._compatFlags & COMPAT.BAD_DHGEX) { + let found = false; + for (let i = 0; i < localKex.length; ++i) { + if (localKex[i].indexOf('group-exchange') !== -1) { + if (!found) { + found = true; + // Copy array lazily + localKex = localKex.slice(); + } + localKex.splice(i--, 1); + } + } + } + + let clientList; + let serverList; + let i; + const debug = self._debug; + + debug && debug('Inbound: Handshake in progress'); + + // Key exchange method ======================================================= + debug && debug(`Handshake: (local) KEX method: ${localKex}`); + debug && debug(`Handshake: (remote) KEX method: ${remote.kex}`); + if (self._server) { + serverList = localKex; + clientList = remote.kex; + } else { + serverList = remote.kex; + clientList = localKex; + } + // Check for agreeable key exchange algorithm + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching key exchange algorithm'); + return doFatalError( + self, + 'Handshake failed: no matching key exchange algorithm', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.kex = clientList[i]; + debug && debug(`Handshake: KEX algorithm: ${clientList[i]}`); + if (firstFollows && (!remote.kex.length || clientList[i] !== remote.kex[0])) { + // Ignore next inbound packet, it was a wrong first guess at KEX algorithm + self._skipNextInboundPacket = true; + } + + + // Server host key format ==================================================== + const localSrvHostKey = local.lists.serverHostKey.array; + debug && debug(`Handshake: (local) Host key format: ${localSrvHostKey}`); + debug && debug( + `Handshake: (remote) Host key format: ${remote.serverHostKey}` + ); + if (self._server) { + serverList = localSrvHostKey; + clientList = remote.serverHostKey; + } else { + serverList = remote.serverHostKey; + clientList = localSrvHostKey; + } + // Check for agreeable server host key format + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching host key format'); + return doFatalError( + self, + 'Handshake failed: no matching host key format', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.serverHostKey = clientList[i]; + debug && debug(`Handshake: Host key format: ${clientList[i]}`); + + + // Client->Server cipher ===================================================== + const localCSCipher = local.lists.cs.cipher.array; + debug && debug(`Handshake: (local) C->S cipher: ${localCSCipher}`); + debug && debug(`Handshake: (remote) C->S cipher: ${remote.cs.cipher}`); + if (self._server) { + serverList = localCSCipher; + clientList = remote.cs.cipher; + } else { + serverList = remote.cs.cipher; + clientList = localCSCipher; + } + // Check for agreeable client->server cipher + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching C->S cipher'); + return doFatalError( + self, + 'Handshake failed: no matching C->S cipher', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.cs.cipher = clientList[i]; + debug && debug(`Handshake: C->S Cipher: ${clientList[i]}`); + + + // Server->Client cipher ===================================================== + const localSCCipher = local.lists.sc.cipher.array; + debug && debug(`Handshake: (local) S->C cipher: ${localSCCipher}`); + debug && debug(`Handshake: (remote) S->C cipher: ${remote.sc.cipher}`); + if (self._server) { + serverList = localSCCipher; + clientList = remote.sc.cipher; + } else { + serverList = remote.sc.cipher; + clientList = localSCCipher; + } + // Check for agreeable server->client cipher + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching S->C cipher'); + return doFatalError( + self, + 'Handshake failed: no matching S->C cipher', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.sc.cipher = clientList[i]; + debug && debug(`Handshake: S->C cipher: ${clientList[i]}`); + + + // Client->Server MAC ======================================================== + const localCSMAC = local.lists.cs.mac.array; + debug && debug(`Handshake: (local) C->S MAC: ${localCSMAC}`); + debug && debug(`Handshake: (remote) C->S MAC: ${remote.cs.mac}`); + if (CIPHER_INFO[init.cs.cipher].authLen > 0) { + init.cs.mac = ''; + debug && debug('Handshake: C->S MAC: '); + } else { + if (self._server) { + serverList = localCSMAC; + clientList = remote.cs.mac; + } else { + serverList = remote.cs.mac; + clientList = localCSMAC; + } + // Check for agreeable client->server hmac algorithm + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching C->S MAC'); + return doFatalError( + self, + 'Handshake failed: no matching C->S MAC', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.cs.mac = clientList[i]; + debug && debug(`Handshake: C->S MAC: ${clientList[i]}`); + } + + + // Server->Client MAC ======================================================== + const localSCMAC = local.lists.sc.mac.array; + debug && debug(`Handshake: (local) S->C MAC: ${localSCMAC}`); + debug && debug(`Handshake: (remote) S->C MAC: ${remote.sc.mac}`); + if (CIPHER_INFO[init.sc.cipher].authLen > 0) { + init.sc.mac = ''; + debug && debug('Handshake: S->C MAC: '); + } else { + if (self._server) { + serverList = localSCMAC; + clientList = remote.sc.mac; + } else { + serverList = remote.sc.mac; + clientList = localSCMAC; + } + // Check for agreeable server->client hmac algorithm + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching S->C MAC'); + return doFatalError( + self, + 'Handshake failed: no matching S->C MAC', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.sc.mac = clientList[i]; + debug && debug(`Handshake: S->C MAC: ${clientList[i]}`); + } + + + // Client->Server compression ================================================ + const localCSCompress = local.lists.cs.compress.array; + debug && debug(`Handshake: (local) C->S compression: ${localCSCompress}`); + debug && debug(`Handshake: (remote) C->S compression: ${remote.cs.compress}`); + if (self._server) { + serverList = localCSCompress; + clientList = remote.cs.compress; + } else { + serverList = remote.cs.compress; + clientList = localCSCompress; + } + // Check for agreeable client->server compression algorithm + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching C->S compression'); + return doFatalError( + self, + 'Handshake failed: no matching C->S compression', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.cs.compress = clientList[i]; + debug && debug(`Handshake: C->S compression: ${clientList[i]}`); + + + // Server->Client compression ================================================ + const localSCCompress = local.lists.sc.compress.array; + debug && debug(`Handshake: (local) S->C compression: ${localSCCompress}`); + debug && debug(`Handshake: (remote) S->C compression: ${remote.sc.compress}`); + if (self._server) { + serverList = localSCCompress; + clientList = remote.sc.compress; + } else { + serverList = remote.sc.compress; + clientList = localSCCompress; + } + // Check for agreeable server->client compression algorithm + for (i = 0; + i < clientList.length && serverList.indexOf(clientList[i]) === -1; + ++i); + if (i === clientList.length) { + // No suitable match found! + debug && debug('Handshake: No matching S->C compression'); + return doFatalError( + self, + 'Handshake failed: no matching S->C compression', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + init.sc.compress = clientList[i]; + debug && debug(`Handshake: S->C compression: ${clientList[i]}`); + + init.cs.lang = ''; + init.sc.lang = ''; + + // XXX: hack -- find a better way to do this + if (self._kex) { + if (!self._kexinit) { + // We received a rekey request, but we haven't sent a KEXINIT in response + // yet + kexinit(self); + } + self._decipher._onPayload = onKEXPayload.bind(self, { firstPacket: false }); + } + + self._kex = createKeyExchange(init, self, payload); + self._kex.start(); +} + +const createKeyExchange = (() => { + function convertToMpint(buf) { + let idx = 0; + let length = buf.length; + while (buf[idx] === 0x00) { + ++idx; + --length; + } + let newBuf; + if (buf[idx] & 0x80) { + newBuf = Buffer.allocUnsafe(1 + length); + newBuf[0] = 0; + buf.copy(newBuf, 1, idx); + buf = newBuf; + } else if (length !== buf.length) { + newBuf = Buffer.allocUnsafe(length); + buf.copy(newBuf, 0, idx); + buf = newBuf; + } + return buf; + } + + class KeyExchange { + constructor(negotiated, protocol, remoteKexinit) { + this._protocol = protocol; + + this.sessionID = (protocol._kex ? protocol._kex.sessionID : undefined); + this.negotiated = negotiated; + this._step = 1; + this._public = null; + this._dh = null; + this._sentNEWKEYS = false; + this._receivedNEWKEYS = false; + this._finished = false; + this._hostVerified = false; + + // Data needed for initializing cipher/decipher/etc. + this._kexinit = protocol._kexinit; + this._remoteKexinit = remoteKexinit; + this._identRaw = protocol._identRaw; + this._remoteIdentRaw = protocol._remoteIdentRaw; + this._hostKey = undefined; + this._dhData = undefined; + this._sig = undefined; + } + finish() { + if (this._finished) + return false; + this._finished = true; + + const isServer = this._protocol._server; + const negotiated = this.negotiated; + + const pubKey = this.convertPublicKey(this._dhData); + let secret = this.computeSecret(this._dhData); + if (secret instanceof Error) { + secret.message = + `Error while computing DH secret (${this.type}): ${secret.message}`; + secret.level = 'handshake'; + return doFatalError( + this._protocol, + secret, + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + const hash = createHash(this.hashName); + // V_C + hashString(hash, (isServer ? this._remoteIdentRaw : this._identRaw)); + // "V_S" + hashString(hash, (isServer ? this._identRaw : this._remoteIdentRaw)); + // "I_C" + hashString(hash, (isServer ? this._remoteKexinit : this._kexinit)); + // "I_S" + hashString(hash, (isServer ? this._kexinit : this._remoteKexinit)); + // "K_S" + const serverPublicHostKey = (isServer + ? this._hostKey.getPublicSSH() + : this._hostKey); + hashString(hash, serverPublicHostKey); + + if (this.type === 'groupex') { + // Group exchange-specific + const params = this.getDHParams(); + const num = Buffer.allocUnsafe(4); + // min (uint32) + writeUInt32BE(num, this._minBits, 0); + hash.update(num); + // preferred (uint32) + writeUInt32BE(num, this._prefBits, 0); + hash.update(num); + // max (uint32) + writeUInt32BE(num, this._maxBits, 0); + hash.update(num); + // prime + hashString(hash, params.prime); + // generator + hashString(hash, params.generator); + } + + // method-specific data sent by client + hashString(hash, (isServer ? pubKey : this.getPublicKey())); + // method-specific data sent by server + const serverPublicKey = (isServer ? this.getPublicKey() : pubKey); + hashString(hash, serverPublicKey); + // shared secret ("K") + hashString(hash, secret); + + // "H" + const exchangeHash = hash.digest(); + + if (!isServer) { + bufferParser.init(this._sig, 0); + const sigType = bufferParser.readString(true); + + if (!sigType) { + return doFatalError( + this._protocol, + 'Malformed packet while reading signature', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + if (sigType !== negotiated.serverHostKey) { + return doFatalError( + this._protocol, + `Wrong signature type: ${sigType}, ` + + `expected: ${negotiated.serverHostKey}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + // "s" + let sigValue = bufferParser.readString(); + + bufferParser.clear(); + + if (sigValue === undefined) { + return doFatalError( + this._protocol, + 'Malformed packet while reading signature', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + if (!(sigValue = sigSSHToASN1(sigValue, sigType))) { + return doFatalError( + this._protocol, + 'Malformed signature', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + let parsedHostKey; + { + bufferParser.init(this._hostKey, 0); + const name = bufferParser.readString(true); + const hostKey = this._hostKey.slice(bufferParser.pos()); + bufferParser.clear(); + parsedHostKey = parseDERKey(hostKey, name); + if (parsedHostKey instanceof Error) { + parsedHostKey.level = 'handshake'; + return doFatalError( + this._protocol, + parsedHostKey, + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + } + + let hashAlgo; + // Check if we need to override the default hash algorithm + switch (this.negotiated.serverHostKey) { + case 'rsa-sha2-256': hashAlgo = 'sha256'; break; + case 'rsa-sha2-512': hashAlgo = 'sha512'; break; + } + + this._protocol._debug + && this._protocol._debug('Verifying signature ...'); + + const verified = parsedHostKey.verify(exchangeHash, sigValue, hashAlgo); + if (verified !== true) { + if (verified instanceof Error) { + this._protocol._debug && this._protocol._debug( + `Signature verification failed: ${verified.stack}` + ); + } else { + this._protocol._debug && this._protocol._debug( + 'Signature verification failed' + ); + } + return doFatalError( + this._protocol, + 'Handshake failed: signature verification failed', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug('Verified signature'); + } else { + // Server + + let hashAlgo; + // Check if we need to override the default hash algorithm + switch (this.negotiated.serverHostKey) { + case 'rsa-sha2-256': hashAlgo = 'sha256'; break; + case 'rsa-sha2-512': hashAlgo = 'sha512'; break; + } + + this._protocol._debug && this._protocol._debug( + 'Generating signature ...' + ); + + let signature = this._hostKey.sign(exchangeHash, hashAlgo); + if (signature instanceof Error) { + return doFatalError( + this._protocol, + 'Handshake failed: signature generation failed for ' + + `${this._hostKey.type} host key: ${signature.message}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + signature = convertSignature(signature, this._hostKey.type); + if (signature === false) { + return doFatalError( + this._protocol, + 'Handshake failed: signature conversion failed for ' + + `${this._hostKey.type} host key`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + // Send KEX reply + /* + byte SSH_MSG_KEXDH_REPLY + / SSH_MSG_KEX_DH_GEX_REPLY + / SSH_MSG_KEX_ECDH_REPLY + string server public host key and certificates (K_S) + string + string signature of H + */ + const sigType = this.negotiated.serverHostKey; + const sigTypeLen = Buffer.byteLength(sigType); + const sigLen = 4 + sigTypeLen + 4 + signature.length; + let p = this._protocol._packetRW.write.allocStartKEX; + const packet = this._protocol._packetRW.write.alloc( + 1 + + 4 + serverPublicHostKey.length + + 4 + serverPublicKey.length + + 4 + sigLen, + true + ); + + packet[p] = MESSAGE.KEXDH_REPLY; + + writeUInt32BE(packet, serverPublicHostKey.length, ++p); + packet.set(serverPublicHostKey, p += 4); + + writeUInt32BE(packet, + serverPublicKey.length, + p += serverPublicHostKey.length); + packet.set(serverPublicKey, p += 4); + + writeUInt32BE(packet, sigLen, p += serverPublicKey.length); + + writeUInt32BE(packet, sigTypeLen, p += 4); + packet.utf8Write(sigType, p += 4, sigTypeLen); + + writeUInt32BE(packet, signature.length, p += sigTypeLen); + packet.set(signature, p += 4); + + if (this._protocol._debug) { + let type; + switch (this.type) { + case 'group': + type = 'KEXDH_REPLY'; + break; + case 'groupex': + type = 'KEXDH_GEX_REPLY'; + break; + default: + type = 'KEXECDH_REPLY'; + } + this._protocol._debug(`Outbound: Sending ${type}`); + } + this._protocol._cipher.encrypt( + this._protocol._packetRW.write.finalize(packet, true) + ); + } + trySendNEWKEYS(this); + + const completeHandshake = () => { + if (!this.sessionID) + this.sessionID = exchangeHash; + + { + const newSecret = Buffer.allocUnsafe(4 + secret.length); + writeUInt32BE(newSecret, secret.length, 0); + newSecret.set(secret, 4); + secret = newSecret; + } + + // Initialize new ciphers, deciphers, etc. + + const csCipherInfo = CIPHER_INFO[negotiated.cs.cipher]; + const scCipherInfo = CIPHER_INFO[negotiated.sc.cipher]; + + const csIV = generateKEXVal(csCipherInfo.ivLen, + this.hashName, + secret, + exchangeHash, + this.sessionID, + 'A'); + const scIV = generateKEXVal(scCipherInfo.ivLen, + this.hashName, + secret, + exchangeHash, + this.sessionID, + 'B'); + const csKey = generateKEXVal(csCipherInfo.keyLen, + this.hashName, + secret, + exchangeHash, + this.sessionID, + 'C'); + const scKey = generateKEXVal(scCipherInfo.keyLen, + this.hashName, + secret, + exchangeHash, + this.sessionID, + 'D'); + let csMacInfo; + let csMacKey; + if (!csCipherInfo.authLen) { + csMacInfo = MAC_INFO[negotiated.cs.mac]; + csMacKey = generateKEXVal(csMacInfo.len, + this.hashName, + secret, + exchangeHash, + this.sessionID, + 'E'); + } + let scMacInfo; + let scMacKey; + if (!scCipherInfo.authLen) { + scMacInfo = MAC_INFO[negotiated.sc.mac]; + scMacKey = generateKEXVal(scMacInfo.len, + this.hashName, + secret, + exchangeHash, + this.sessionID, + 'F'); + } + + const config = { + inbound: { + onPayload: this._protocol._onPayload, + seqno: this._protocol._decipher.inSeqno, + decipherInfo: (!isServer ? scCipherInfo : csCipherInfo), + decipherIV: (!isServer ? scIV : csIV), + decipherKey: (!isServer ? scKey : csKey), + macInfo: (!isServer ? scMacInfo : csMacInfo), + macKey: (!isServer ? scMacKey : csMacKey), + }, + outbound: { + onWrite: this._protocol._onWrite, + seqno: this._protocol._cipher.outSeqno, + cipherInfo: (isServer ? scCipherInfo : csCipherInfo), + cipherIV: (isServer ? scIV : csIV), + cipherKey: (isServer ? scKey : csKey), + macInfo: (isServer ? scMacInfo : csMacInfo), + macKey: (isServer ? scMacKey : csMacKey), + }, + }; + this._protocol._cipher && this._protocol._cipher.free(); + this._protocol._decipher && this._protocol._decipher.free(); + this._protocol._cipher = createCipher(config); + this._protocol._decipher = createDecipher(config); + + const rw = { + read: undefined, + write: undefined, + }; + switch (negotiated.cs.compress) { + case 'zlib': // starts immediately + if (isServer) + rw.read = new ZlibPacketReader(); + else + rw.write = new ZlibPacketWriter(this._protocol); + break; + case 'zlib@openssh.com': + // Starts after successful user authentication + + if (this._protocol._authenticated) { + // If a rekey happens and this compression method is selected and + // we already authenticated successfully, we need to start + // immediately instead + if (isServer) + rw.read = new ZlibPacketReader(); + else + rw.write = new ZlibPacketWriter(this._protocol); + break; + } + // FALLTHROUGH + default: + // none -- never any compression/decompression + + if (isServer) + rw.read = new PacketReader(); + else + rw.write = new PacketWriter(this._protocol); + } + switch (negotiated.sc.compress) { + case 'zlib': // starts immediately + if (isServer) + rw.write = new ZlibPacketWriter(this._protocol); + else + rw.read = new ZlibPacketReader(); + break; + case 'zlib@openssh.com': + // Starts after successful user authentication + + if (this._protocol._authenticated) { + // If a rekey happens and this compression method is selected and + // we already authenticated successfully, we need to start + // immediately instead + if (isServer) + rw.write = new ZlibPacketWriter(this._protocol); + else + rw.read = new ZlibPacketReader(); + break; + } + // FALLTHROUGH + default: + // none -- never any compression/decompression + + if (isServer) + rw.write = new PacketWriter(this._protocol); + else + rw.read = new PacketReader(); + } + this._protocol._packetRW.read.cleanup(); + this._protocol._packetRW.write.cleanup(); + this._protocol._packetRW = rw; + + // Cleanup/reset various state + this._public = null; + this._dh = null; + this._kexinit = this._protocol._kexinit = undefined; + this._remoteKexinit = undefined; + this._identRaw = undefined; + this._remoteIdentRaw = undefined; + this._hostKey = undefined; + this._dhData = undefined; + this._sig = undefined; + + this._protocol._onHandshakeComplete(negotiated); + + return false; + }; + if (!isServer) + return completeHandshake(); + this.finish = completeHandshake; + } + + start() { + if (!this._protocol._server) { + if (this._protocol._debug) { + let type; + switch (this.type) { + case 'group': + type = 'KEXDH_INIT'; + break; + default: + type = 'KEXECDH_INIT'; + } + this._protocol._debug(`Outbound: Sending ${type}`); + } + + const pubKey = this.getPublicKey(); + + let p = this._protocol._packetRW.write.allocStartKEX; + const packet = this._protocol._packetRW.write.alloc( + 1 + 4 + pubKey.length, + true + ); + packet[p] = MESSAGE.KEXDH_INIT; + writeUInt32BE(packet, pubKey.length, ++p); + packet.set(pubKey, p += 4); + this._protocol._cipher.encrypt( + this._protocol._packetRW.write.finalize(packet, true) + ); + } + } + getPublicKey() { + this.generateKeys(); + + const key = this._public; + + if (key) + return this.convertPublicKey(key); + } + convertPublicKey(key) { + let newKey; + let idx = 0; + let len = key.length; + while (key[idx] === 0x00) { + ++idx; + --len; + } + + if (key[idx] & 0x80) { + newKey = Buffer.allocUnsafe(1 + len); + newKey[0] = 0; + key.copy(newKey, 1, idx); + return newKey; + } + + if (len !== key.length) { + newKey = Buffer.allocUnsafe(len); + key.copy(newKey, 0, idx); + key = newKey; + } + return key; + } + computeSecret(otherPublicKey) { + this.generateKeys(); + + try { + return convertToMpint(this._dh.computeSecret(otherPublicKey)); + } catch (ex) { + return ex; + } + } + parse(payload) { + const type = payload[0]; + switch (this._step) { + case 1: + if (this._protocol._server) { + // Server + if (type !== MESSAGE.KEXDH_INIT) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ${MESSAGE.KEXDH_INIT}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Received DH Init' + ); + /* + byte SSH_MSG_KEXDH_INIT + / SSH_MSG_KEX_ECDH_INIT + string + */ + bufferParser.init(payload, 1); + const dhData = bufferParser.readString(); + bufferParser.clear(); + if (dhData === undefined) { + return doFatalError( + this._protocol, + 'Received malformed KEX*_INIT', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + // Client public key + this._dhData = dhData; + + let hostKey = + this._protocol._hostKeys[this.negotiated.serverHostKey]; + if (Array.isArray(hostKey)) + hostKey = hostKey[0]; + this._hostKey = hostKey; + + this.finish(); + } else { + // Client + if (type !== MESSAGE.KEXDH_REPLY) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ${MESSAGE.KEXDH_REPLY}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Received DH Reply' + ); + /* + byte SSH_MSG_KEXDH_REPLY + / SSH_MSG_KEX_DH_GEX_REPLY + / SSH_MSG_KEX_ECDH_REPLY + string server public host key and certificates (K_S) + string + string signature of H + */ + bufferParser.init(payload, 1); + let hostPubKey; + let dhData; + let sig; + if ((hostPubKey = bufferParser.readString()) === undefined + || (dhData = bufferParser.readString()) === undefined + || (sig = bufferParser.readString()) === undefined) { + bufferParser.clear(); + return doFatalError( + this._protocol, + 'Received malformed KEX*_REPLY', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + bufferParser.clear(); + + // Check that the host public key type matches what was negotiated + // during KEXINIT swap + bufferParser.init(hostPubKey, 0); + const hostPubKeyType = bufferParser.readString(true); + bufferParser.clear(); + if (hostPubKeyType === undefined) { + return doFatalError( + this._protocol, + 'Received malformed host public key', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + if (hostPubKeyType !== this.negotiated.serverHostKey) { + // Check if we need to make an exception + switch (this.negotiated.serverHostKey) { + case 'rsa-sha2-256': + case 'rsa-sha2-512': + if (hostPubKeyType === 'ssh-rsa') + break; + // FALLTHROUGH + default: + return doFatalError( + this._protocol, + 'Host key does not match negotiated type', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + } + + this._hostKey = hostPubKey; + this._dhData = dhData; + this._sig = sig; + + let checked = false; + let ret; + if (this._protocol._hostVerifier === undefined) { + ret = true; + this._protocol._debug && this._protocol._debug( + 'Host accepted by default (no verification)' + ); + } else { + ret = this._protocol._hostVerifier(hostPubKey, (permitted) => { + if (checked) + return; + checked = true; + if (permitted === false) { + this._protocol._debug && this._protocol._debug( + 'Host denied (verification failed)' + ); + return doFatalError( + this._protocol, + 'Host denied (verification failed)', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Host accepted (verified)' + ); + this._hostVerified = true; + if (this._receivedNEWKEYS) + this.finish(); + else + trySendNEWKEYS(this); + }); + } + if (ret === undefined) { + // Async host verification + ++this._step; + return; + } + checked = true; + if (ret === false) { + this._protocol._debug && this._protocol._debug( + 'Host denied (verification failed)' + ); + return doFatalError( + this._protocol, + 'Host denied (verification failed)', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Host accepted (verified)' + ); + this._hostVerified = true; + trySendNEWKEYS(this); + } + ++this._step; + break; + case 2: + if (type !== MESSAGE.NEWKEYS) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ${MESSAGE.NEWKEYS}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Inbound: NEWKEYS' + ); + this._receivedNEWKEYS = true; + ++this._step; + if (this._protocol._server || this._hostVerified) + return this.finish(); + + // Signal to current decipher that we need to change to a new decipher + // for the next packet + return false; + default: + return doFatalError( + this._protocol, + `Received unexpected packet ${type} after NEWKEYS`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + } + } + + class Curve25519Exchange extends KeyExchange { + constructor(hashName, ...args) { + super(...args); + + this.type = '25519'; + this.hashName = hashName; + this._keys = null; + } + generateKeys() { + if (!this._keys) + this._keys = generateKeyPairSync('x25519'); + } + getPublicKey() { + this.generateKeys(); + + const key = this._keys.publicKey.export({ type: 'spki', format: 'der' }); + return key.slice(-32); // HACK: avoids parsing DER/BER header + } + convertPublicKey(key) { + let newKey; + let idx = 0; + let len = key.length; + while (key[idx] === 0x00) { + ++idx; + --len; + } + + if (key.length === 32) + return key; + + if (len !== key.length) { + newKey = Buffer.allocUnsafe(len); + key.copy(newKey, 0, idx); + key = newKey; + } + return key; + } + computeSecret(otherPublicKey) { + this.generateKeys(); + + try { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // algorithm + asnWriter.startSequence(); + asnWriter.writeOID('1.3.101.110'); // id-X25519 + asnWriter.endSequence(); + + // PublicKey + asnWriter.startSequence(Ber.BitString); + asnWriter.writeByte(0x00); + // XXX: hack to write a raw buffer without a tag -- yuck + asnWriter._ensure(otherPublicKey.length); + otherPublicKey.copy(asnWriter._buf, + asnWriter._offset, + 0, + otherPublicKey.length); + asnWriter._offset += otherPublicKey.length; + asnWriter.endSequence(); + asnWriter.endSequence(); + + return convertToMpint(diffieHellman({ + privateKey: this._keys.privateKey, + publicKey: createPublicKey({ + key: asnWriter.buffer, + type: 'spki', + format: 'der', + }), + })); + } catch (ex) { + return ex; + } + } + } + + class ECDHExchange extends KeyExchange { + constructor(curveName, hashName, ...args) { + super(...args); + + this.type = 'ecdh'; + this.curveName = curveName; + this.hashName = hashName; + } + generateKeys() { + if (!this._dh) { + this._dh = createECDH(this.curveName); + this._public = this._dh.generateKeys(); + } + } + } + + class DHGroupExchange extends KeyExchange { + constructor(hashName, ...args) { + super(...args); + + this.type = 'groupex'; + this.hashName = hashName; + this._prime = null; + this._generator = null; + this._minBits = GEX_MIN_BITS; + this._prefBits = dhEstimate(this.negotiated); + if (this._protocol._compatFlags & COMPAT.BUG_DHGEX_LARGE) + this._prefBits = Math.min(this._prefBits, 4096); + this._maxBits = GEX_MAX_BITS; + } + start() { + if (this._protocol._server) + return; + this._protocol._debug && this._protocol._debug( + 'Outbound: Sending KEXDH_GEX_REQUEST' + ); + let p = this._protocol._packetRW.write.allocStartKEX; + const packet = this._protocol._packetRW.write.alloc( + 1 + 4 + 4 + 4, + true + ); + packet[p] = MESSAGE.KEXDH_GEX_REQUEST; + writeUInt32BE(packet, this._minBits, ++p); + writeUInt32BE(packet, this._prefBits, p += 4); + writeUInt32BE(packet, this._maxBits, p += 4); + this._protocol._cipher.encrypt( + this._protocol._packetRW.write.finalize(packet, true) + ); + } + generateKeys() { + if (!this._dh && this._prime && this._generator) { + this._dh = createDiffieHellman(this._prime, this._generator); + this._public = this._dh.generateKeys(); + } + } + setDHParams(prime, generator) { + if (!Buffer.isBuffer(prime)) + throw new Error('Invalid prime value'); + if (!Buffer.isBuffer(generator)) + throw new Error('Invalid generator value'); + this._prime = prime; + this._generator = generator; + } + getDHParams() { + if (this._dh) { + return { + prime: convertToMpint(this._dh.getPrime()), + generator: convertToMpint(this._dh.getGenerator()), + }; + } + } + parse(payload) { + const type = payload[0]; + switch (this._step) { + case 1: + if (this._protocol._server) { + if (type !== MESSAGE.KEXDH_GEX_REQUEST) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ` + + MESSAGE.KEXDH_GEX_REQUEST, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + // TODO: allow user implementation to provide safe prime and + // generator on demand to support group exchange on server side + return doFatalError( + this._protocol, + 'Group exchange not implemented for server', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + if (type !== MESSAGE.KEXDH_GEX_GROUP) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ${MESSAGE.KEXDH_GEX_GROUP}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + + this._protocol._debug && this._protocol._debug( + 'Received DH GEX Group' + ); + + /* + byte SSH_MSG_KEX_DH_GEX_GROUP + mpint p, safe prime + mpint g, generator for subgroup in GF(p) + */ + bufferParser.init(payload, 1); + let prime; + let gen; + if ((prime = bufferParser.readString()) === undefined + || (gen = bufferParser.readString()) === undefined) { + bufferParser.clear(); + return doFatalError( + this._protocol, + 'Received malformed KEXDH_GEX_GROUP', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + bufferParser.clear(); + + // TODO: validate prime + this.setDHParams(prime, gen); + this.generateKeys(); + const pubkey = this.getPublicKey(); + + this._protocol._debug && this._protocol._debug( + 'Outbound: Sending KEXDH_GEX_INIT' + ); + + let p = this._protocol._packetRW.write.allocStartKEX; + const packet = + this._protocol._packetRW.write.alloc(1 + 4 + pubkey.length, true); + packet[p] = MESSAGE.KEXDH_GEX_INIT; + writeUInt32BE(packet, pubkey.length, ++p); + packet.set(pubkey, p += 4); + this._protocol._cipher.encrypt( + this._protocol._packetRW.write.finalize(packet, true) + ); + + ++this._step; + break; + case 2: + if (this._protocol._server) { + if (type !== MESSAGE.KEXDH_GEX_INIT) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ${MESSAGE.KEXDH_GEX_INIT}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Received DH GEX Init' + ); + return doFatalError( + this._protocol, + 'Group exchange not implemented for server', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } else if (type !== MESSAGE.KEXDH_GEX_REPLY) { + return doFatalError( + this._protocol, + `Received packet ${type} instead of ${MESSAGE.KEXDH_GEX_REPLY}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + this._protocol._debug && this._protocol._debug( + 'Received DH GEX Reply' + ); + this._step = 1; + payload[0] = MESSAGE.KEXDH_REPLY; + this.parse = KeyExchange.prototype.parse; + this.parse(payload); + } + } + } + + class DHExchange extends KeyExchange { + constructor(groupName, hashName, ...args) { + super(...args); + + this.type = 'group'; + this.groupName = groupName; + this.hashName = hashName; + } + start() { + if (!this._protocol._server) { + this._protocol._debug && this._protocol._debug( + 'Outbound: Sending KEXDH_INIT' + ); + const pubKey = this.getPublicKey(); + let p = this._protocol._packetRW.write.allocStartKEX; + const packet = + this._protocol._packetRW.write.alloc(1 + 4 + pubKey.length, true); + packet[p] = MESSAGE.KEXDH_INIT; + writeUInt32BE(packet, pubKey.length, ++p); + packet.set(pubKey, p += 4); + this._protocol._cipher.encrypt( + this._protocol._packetRW.write.finalize(packet, true) + ); + } + } + generateKeys() { + if (!this._dh) { + this._dh = createDiffieHellmanGroup(this.groupName); + this._public = this._dh.generateKeys(); + } + } + getDHParams() { + if (this._dh) { + return { + prime: convertToMpint(this._dh.getPrime()), + generator: convertToMpint(this._dh.getGenerator()), + }; + } + } + } + + return (negotiated, ...args) => { + if (typeof negotiated !== 'object' || negotiated === null) + throw new Error('Invalid negotiated argument'); + const kexType = negotiated.kex; + if (typeof kexType === 'string') { + args = [negotiated, ...args]; + switch (kexType) { + case 'curve25519-sha256': + case 'curve25519-sha256@libssh.org': + if (!curve25519Supported) + break; + return new Curve25519Exchange('sha256', ...args); + + case 'ecdh-sha2-nistp256': + return new ECDHExchange('prime256v1', 'sha256', ...args); + case 'ecdh-sha2-nistp384': + return new ECDHExchange('secp384r1', 'sha384', ...args); + case 'ecdh-sha2-nistp521': + return new ECDHExchange('secp521r1', 'sha512', ...args); + + case 'diffie-hellman-group1-sha1': + return new DHExchange('modp2', 'sha1', ...args); + case 'diffie-hellman-group14-sha1': + return new DHExchange('modp14', 'sha1', ...args); + case 'diffie-hellman-group14-sha256': + return new DHExchange('modp14', 'sha256', ...args); + case 'diffie-hellman-group15-sha512': + return new DHExchange('modp15', 'sha512', ...args); + case 'diffie-hellman-group16-sha512': + return new DHExchange('modp16', 'sha512', ...args); + case 'diffie-hellman-group17-sha512': + return new DHExchange('modp17', 'sha512', ...args); + case 'diffie-hellman-group18-sha512': + return new DHExchange('modp18', 'sha512', ...args); + + case 'diffie-hellman-group-exchange-sha1': + return new DHGroupExchange('sha1', ...args); + case 'diffie-hellman-group-exchange-sha256': + return new DHGroupExchange('sha256', ...args); + } + throw new Error(`Unsupported key exchange algorithm: ${kexType}`); + } + throw new Error(`Invalid key exchange type: ${kexType}`); + }; +})(); + +const KexInit = (() => { + const KEX_PROPERTY_NAMES = [ + 'kex', + 'serverHostKey', + ['cs', 'cipher' ], + ['sc', 'cipher' ], + ['cs', 'mac' ], + ['sc', 'mac' ], + ['cs', 'compress' ], + ['sc', 'compress' ], + ['cs', 'lang' ], + ['sc', 'lang' ], + ]; + return class KexInit { + constructor(obj) { + if (typeof obj !== 'object' || obj === null) + throw new TypeError('Argument must be an object'); + + const lists = { + kex: undefined, + serverHostKey: undefined, + cs: { + cipher: undefined, + mac: undefined, + compress: undefined, + lang: undefined, + }, + sc: { + cipher: undefined, + mac: undefined, + compress: undefined, + lang: undefined, + }, + + all: undefined, + }; + let totalSize = 0; + for (const prop of KEX_PROPERTY_NAMES) { + let base; + let val; + let desc; + let key; + if (typeof prop === 'string') { + base = lists; + val = obj[prop]; + desc = key = prop; + } else { + const parent = prop[0]; + base = lists[parent]; + key = prop[1]; + val = obj[parent][key]; + desc = `${parent}.${key}`; + } + const entry = { array: undefined, buffer: undefined }; + if (Buffer.isBuffer(val)) { + entry.array = ('' + val).split(','); + entry.buffer = val; + totalSize += 4 + val.length; + } else { + if (typeof val === 'string') + val = val.split(','); + if (Array.isArray(val)) { + entry.array = val; + entry.buffer = Buffer.from(val.join(',')); + } else { + throw new TypeError(`Invalid \`${desc}\` type: ${typeof val}`); + } + totalSize += 4 + entry.buffer.length; + } + base[key] = entry; + } + + const all = Buffer.allocUnsafe(totalSize); + lists.all = all; + + let allPos = 0; + for (const prop of KEX_PROPERTY_NAMES) { + let data; + if (typeof prop === 'string') + data = lists[prop].buffer; + else + data = lists[prop[0]][prop[1]].buffer; + allPos = writeUInt32BE(all, data.length, allPos); + all.set(data, allPos); + allPos += data.length; + } + + this.totalSize = totalSize; + this.lists = lists; + } + copyAllTo(buf, offset) { + const src = this.lists.all; + if (typeof offset !== 'number') + throw new TypeError(`Invalid offset value: ${typeof offset}`); + if (buf.length - offset < src.length) + throw new Error('Insufficient space to copy list'); + buf.set(src, offset); + return src.length; + } + }; +})(); + +const hashString = (() => { + const LEN = Buffer.allocUnsafe(4); + return (hash, buf) => { + writeUInt32BE(LEN, buf.length, 0); + hash.update(LEN); + hash.update(buf); + }; +})(); + +function generateKEXVal(len, hashName, secret, exchangeHash, sessionID, char) { + let ret; + if (len) { + let digest = createHash(hashName) + .update(secret) + .update(exchangeHash) + .update(char) + .update(sessionID) + .digest(); + while (digest.length < len) { + const chunk = createHash(hashName) + .update(secret) + .update(exchangeHash) + .update(digest) + .digest(); + const extended = Buffer.allocUnsafe(digest.length + chunk.length); + extended.set(digest, 0); + extended.set(chunk, digest.length); + digest = extended; + } + if (digest.length === len) + ret = digest; + else + ret = new FastBuffer(digest.buffer, digest.byteOffset, len); + } else { + ret = EMPTY_BUFFER; + } + return ret; +} + +function onKEXPayload(state, payload) { + // XXX: move this to the Decipher implementations? + if (payload.length === 0) { + this._debug && this._debug('Inbound: Skipping empty packet payload'); + return; + } + + if (this._skipNextInboundPacket) { + this._skipNextInboundPacket = false; + return; + } + + payload = this._packetRW.read.read(payload); + + const type = payload[0]; + switch (type) { + case MESSAGE.DISCONNECT: + case MESSAGE.IGNORE: + case MESSAGE.UNIMPLEMENTED: + case MESSAGE.DEBUG: + if (!MESSAGE_HANDLERS) + MESSAGE_HANDLERS = require('./handlers.js'); + return MESSAGE_HANDLERS[type](this, payload); + case MESSAGE.KEXINIT: + if (!state.firstPacket) { + return doFatalError( + this, + 'Received extra KEXINIT during handshake', + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + state.firstPacket = false; + return handleKexInit(this, payload); + default: + if (type < 20 || type > 49) { + return doFatalError( + this, + `Received unexpected packet type ${type}`, + 'handshake', + DISCONNECT_REASON.KEY_EXCHANGE_FAILED + ); + } + } + + return this._kex.parse(payload); +} + +function dhEstimate(neg) { + const csCipher = CIPHER_INFO[neg.cs.cipher]; + const scCipher = CIPHER_INFO[neg.sc.cipher]; + // XXX: if OpenSSH's `umac-*` MACs are ever supported, their key lengths will + // also need to be considered when calculating `bits` + const bits = Math.max( + 0, + (csCipher.sslName === 'des-ede3-cbc' ? 14 : csCipher.keyLen), + csCipher.blockLen, + csCipher.ivLen, + (scCipher.sslName === 'des-ede3-cbc' ? 14 : scCipher.keyLen), + scCipher.blockLen, + scCipher.ivLen + ) * 8; + if (bits <= 112) + return 2048; + if (bits <= 128) + return 3072; + if (bits <= 192) + return 7680; + return 8192; +} + +function trySendNEWKEYS(kex) { + if (!kex._sentNEWKEYS) { + kex._protocol._debug && kex._protocol._debug( + 'Outbound: Sending NEWKEYS' + ); + const p = kex._protocol._packetRW.write.allocStartKEX; + const packet = kex._protocol._packetRW.write.alloc(1, true); + packet[p] = MESSAGE.NEWKEYS; + kex._protocol._cipher.encrypt( + kex._protocol._packetRW.write.finalize(packet, true) + ); + kex._sentNEWKEYS = true; + } +} + +module.exports = { + KexInit, + kexinit, + onKEXPayload, + DEFAULT_KEXINIT: new KexInit({ + kex: DEFAULT_KEX, + serverHostKey: DEFAULT_SERVER_HOST_KEY, + cs: { + cipher: DEFAULT_CIPHER, + mac: DEFAULT_MAC, + compress: DEFAULT_COMPRESSION, + lang: [], + }, + sc: { + cipher: DEFAULT_CIPHER, + mac: DEFAULT_MAC, + compress: DEFAULT_COMPRESSION, + lang: [], + }, + }), + HANDLERS: { + [MESSAGE.KEXINIT]: handleKexInit, + }, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/keyParser.js b/reverse_engineering/node_modules/ssh2/lib/protocol/keyParser.js new file mode 100644 index 0000000..9860e3f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/keyParser.js @@ -0,0 +1,1481 @@ +// TODO: +// * utilize `crypto.create(Private|Public)Key()` and `keyObject.export()` +// * handle multi-line header values (OpenSSH)? +// * more thorough validation? +'use strict'; + +const { + createDecipheriv, + createECDH, + createHash, + createHmac, + createSign, + createVerify, + getCiphers, + sign: sign_, + verify: verify_, +} = require('crypto'); +const supportedOpenSSLCiphers = getCiphers(); + +const { Ber } = require('asn1'); +const bcrypt_pbkdf = require('bcrypt-pbkdf').pbkdf; + +const { CIPHER_INFO } = require('./crypto.js'); +const { eddsaSupported, SUPPORTED_CIPHER } = require('./constants.js'); +const { + bufferSlice, + makeBufferParser, + readString, + readUInt32BE, + writeUInt32BE, +} = require('./utils.js'); + +const SYM_HASH_ALGO = Symbol('Hash Algorithm'); +const SYM_PRIV_PEM = Symbol('Private key PEM'); +const SYM_PUB_PEM = Symbol('Public key PEM'); +const SYM_PUB_SSH = Symbol('Public key SSH'); +const SYM_DECRYPTED = Symbol('Decrypted Key'); + +// Create OpenSSL cipher name -> SSH cipher name conversion table +const CIPHER_INFO_OPENSSL = Object.create(null); +{ + const keys = Object.keys(CIPHER_INFO); + for (let i = 0; i < keys.length; ++i) { + const cipherName = CIPHER_INFO[keys[i]].sslName; + if (!cipherName || CIPHER_INFO_OPENSSL[cipherName]) + continue; + CIPHER_INFO_OPENSSL[cipherName] = CIPHER_INFO[keys[i]]; + } +} + +const binaryKeyParser = makeBufferParser(); + +function makePEM(type, data) { + data = data.base64Slice(0, data.length); + let formatted = data.replace(/.{64}/g, '$&\n'); + if (data.length & 63) + formatted += '\n'; + return `-----BEGIN ${type} KEY-----\n${formatted}-----END ${type} KEY-----`; +} + +function combineBuffers(buf1, buf2) { + const result = Buffer.allocUnsafe(buf1.length + buf2.length); + result.set(buf1, 0); + result.set(buf2, buf1.length); + return result; +} + +function skipFields(buf, nfields) { + const bufLen = buf.length; + let pos = (buf._pos || 0); + for (let i = 0; i < nfields; ++i) { + const left = (bufLen - pos); + if (pos >= bufLen || left < 4) + return false; + const len = readUInt32BE(buf, pos); + if (left < 4 + len) + return false; + pos += 4 + len; + } + buf._pos = pos; + return true; +} + +function genOpenSSLRSAPub(n, e) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // algorithm + asnWriter.startSequence(); + asnWriter.writeOID('1.2.840.113549.1.1.1'); // rsaEncryption + // algorithm parameters (RSA has none) + asnWriter.writeNull(); + asnWriter.endSequence(); + + // subjectPublicKey + asnWriter.startSequence(Ber.BitString); + asnWriter.writeByte(0x00); + asnWriter.startSequence(); + asnWriter.writeBuffer(n, Ber.Integer); + asnWriter.writeBuffer(e, Ber.Integer); + asnWriter.endSequence(); + asnWriter.endSequence(); + asnWriter.endSequence(); + return makePEM('PUBLIC', asnWriter.buffer); +} + +function genOpenSSHRSAPub(n, e) { + const publicKey = Buffer.allocUnsafe(4 + 7 + 4 + e.length + 4 + n.length); + + writeUInt32BE(publicKey, 7, 0); + publicKey.utf8Write('ssh-rsa', 4, 7); + + let i = 4 + 7; + writeUInt32BE(publicKey, e.length, i); + publicKey.set(e, i += 4); + + writeUInt32BE(publicKey, n.length, i += e.length); + publicKey.set(n, i + 4); + + return publicKey; +} + +const genOpenSSLRSAPriv = (() => { + function genRSAASN1Buf(n, e, d, p, q, dmp1, dmq1, iqmp) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + asnWriter.writeInt(0x00, Ber.Integer); + asnWriter.writeBuffer(n, Ber.Integer); + asnWriter.writeBuffer(e, Ber.Integer); + asnWriter.writeBuffer(d, Ber.Integer); + asnWriter.writeBuffer(p, Ber.Integer); + asnWriter.writeBuffer(q, Ber.Integer); + asnWriter.writeBuffer(dmp1, Ber.Integer); + asnWriter.writeBuffer(dmq1, Ber.Integer); + asnWriter.writeBuffer(iqmp, Ber.Integer); + asnWriter.endSequence(); + return asnWriter.buffer; + } + + function bigIntFromBuffer(buf) { + return BigInt(`0x${buf.hexSlice(0, buf.length)}`); + } + + function bigIntToBuffer(bn) { + let hex = bn.toString(16); + if ((hex.length & 1) !== 0) { + hex = `0${hex}`; + } else { + const sigbit = hex.charCodeAt(0); + // BER/DER integers require leading zero byte to denote a positive value + // when first byte >= 0x80 + if (sigbit === 56/* '8' */ + || sigbit === 57/* '9' */ + || (sigbit >= 97/* 'a' */ && sigbit <= 102/* 'f' */)) { + hex = `00${hex}`; + } + } + return Buffer.from(hex, 'hex'); + } + + return function genOpenSSLRSAPriv(n, e, d, iqmp, p, q) { + const bn_d = bigIntFromBuffer(d); + const dmp1 = bigIntToBuffer(bn_d % (bigIntFromBuffer(p) - 1n)); + const dmq1 = bigIntToBuffer(bn_d % (bigIntFromBuffer(q) - 1n)); + return makePEM('RSA PRIVATE', + genRSAASN1Buf(n, e, d, p, q, dmp1, dmq1, iqmp)); + }; +})(); + +function genOpenSSLDSAPub(p, q, g, y) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // algorithm + asnWriter.startSequence(); + asnWriter.writeOID('1.2.840.10040.4.1'); // id-dsa + // algorithm parameters + asnWriter.startSequence(); + asnWriter.writeBuffer(p, Ber.Integer); + asnWriter.writeBuffer(q, Ber.Integer); + asnWriter.writeBuffer(g, Ber.Integer); + asnWriter.endSequence(); + asnWriter.endSequence(); + + // subjectPublicKey + asnWriter.startSequence(Ber.BitString); + asnWriter.writeByte(0x00); + asnWriter.writeBuffer(y, Ber.Integer); + asnWriter.endSequence(); + asnWriter.endSequence(); + return makePEM('PUBLIC', asnWriter.buffer); +} + +function genOpenSSHDSAPub(p, q, g, y) { + const publicKey = Buffer.allocUnsafe( + 4 + 7 + 4 + p.length + 4 + q.length + 4 + g.length + 4 + y.length + ); + + writeUInt32BE(publicKey, 7, 0); + publicKey.utf8Write('ssh-dss', 4, 7); + + let i = 4 + 7; + writeUInt32BE(publicKey, p.length, i); + publicKey.set(p, i += 4); + + writeUInt32BE(publicKey, q.length, i += p.length); + publicKey.set(q, i += 4); + + writeUInt32BE(publicKey, g.length, i += q.length); + publicKey.set(g, i += 4); + + writeUInt32BE(publicKey, y.length, i += g.length); + publicKey.set(y, i + 4); + + return publicKey; +} + +function genOpenSSLDSAPriv(p, q, g, y, x) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + asnWriter.writeInt(0x00, Ber.Integer); + asnWriter.writeBuffer(p, Ber.Integer); + asnWriter.writeBuffer(q, Ber.Integer); + asnWriter.writeBuffer(g, Ber.Integer); + asnWriter.writeBuffer(y, Ber.Integer); + asnWriter.writeBuffer(x, Ber.Integer); + asnWriter.endSequence(); + return makePEM('DSA PRIVATE', asnWriter.buffer); +} + +function genOpenSSLEdPub(pub) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // algorithm + asnWriter.startSequence(); + asnWriter.writeOID('1.3.101.112'); // id-Ed25519 + asnWriter.endSequence(); + + // PublicKey + asnWriter.startSequence(Ber.BitString); + asnWriter.writeByte(0x00); + // XXX: hack to write a raw buffer without a tag -- yuck + asnWriter._ensure(pub.length); + asnWriter._buf.set(pub, asnWriter._offset); + asnWriter._offset += pub.length; + asnWriter.endSequence(); + asnWriter.endSequence(); + return makePEM('PUBLIC', asnWriter.buffer); +} + +function genOpenSSHEdPub(pub) { + const publicKey = Buffer.allocUnsafe(4 + 11 + 4 + pub.length); + + writeUInt32BE(publicKey, 11, 0); + publicKey.utf8Write('ssh-ed25519', 4, 11); + + writeUInt32BE(publicKey, pub.length, 15); + publicKey.set(pub, 19); + + return publicKey; +} + +function genOpenSSLEdPriv(priv) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // version + asnWriter.writeInt(0x00, Ber.Integer); + + // algorithm + asnWriter.startSequence(); + asnWriter.writeOID('1.3.101.112'); // id-Ed25519 + asnWriter.endSequence(); + + // PrivateKey + asnWriter.startSequence(Ber.OctetString); + asnWriter.writeBuffer(priv, Ber.OctetString); + asnWriter.endSequence(); + asnWriter.endSequence(); + return makePEM('PRIVATE', asnWriter.buffer); +} + +function genOpenSSLECDSAPub(oid, Q) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // algorithm + asnWriter.startSequence(); + asnWriter.writeOID('1.2.840.10045.2.1'); // id-ecPublicKey + // algorithm parameters (namedCurve) + asnWriter.writeOID(oid); + asnWriter.endSequence(); + + // subjectPublicKey + asnWriter.startSequence(Ber.BitString); + asnWriter.writeByte(0x00); + // XXX: hack to write a raw buffer without a tag -- yuck + asnWriter._ensure(Q.length); + asnWriter._buf.set(Q, asnWriter._offset); + asnWriter._offset += Q.length; + // end hack + asnWriter.endSequence(); + asnWriter.endSequence(); + return makePEM('PUBLIC', asnWriter.buffer); +} + +function genOpenSSHECDSAPub(oid, Q) { + let curveName; + switch (oid) { + case '1.2.840.10045.3.1.7': + // prime256v1/secp256r1 + curveName = 'nistp256'; + break; + case '1.3.132.0.34': + // secp384r1 + curveName = 'nistp384'; + break; + case '1.3.132.0.35': + // secp521r1 + curveName = 'nistp521'; + break; + default: + return; + } + + const publicKey = Buffer.allocUnsafe(4 + 19 + 4 + 8 + 4 + Q.length); + + writeUInt32BE(publicKey, 19, 0); + publicKey.utf8Write(`ecdsa-sha2-${curveName}`, 4, 19); + + writeUInt32BE(publicKey, 8, 23); + publicKey.utf8Write(curveName, 27, 8); + + writeUInt32BE(publicKey, Q.length, 35); + publicKey.set(Q, 39); + + return publicKey; +} + +function genOpenSSLECDSAPriv(oid, pub, priv) { + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + // version + asnWriter.writeInt(0x01, Ber.Integer); + // privateKey + asnWriter.writeBuffer(priv, Ber.OctetString); + // parameters (optional) + asnWriter.startSequence(0xA0); + asnWriter.writeOID(oid); + asnWriter.endSequence(); + // publicKey (optional) + asnWriter.startSequence(0xA1); + asnWriter.startSequence(Ber.BitString); + asnWriter.writeByte(0x00); + // XXX: hack to write a raw buffer without a tag -- yuck + asnWriter._ensure(pub.length); + asnWriter._buf.set(pub, asnWriter._offset); + asnWriter._offset += pub.length; + // end hack + asnWriter.endSequence(); + asnWriter.endSequence(); + asnWriter.endSequence(); + return makePEM('EC PRIVATE', asnWriter.buffer); +} + +function genOpenSSLECDSAPubFromPriv(curveName, priv) { + const tempECDH = createECDH(curveName); + tempECDH.setPrivateKey(priv); + return tempECDH.getPublicKey(); +} + +const BaseKey = { + sign: (() => { + if (typeof sign_ === 'function') { + return function sign(data, algo) { + const pem = this[SYM_PRIV_PEM]; + if (pem === null) + return new Error('No private key available'); + if (!algo || typeof algo !== 'string') + algo = this[SYM_HASH_ALGO]; + try { + return sign_(algo, data, pem); + } catch (ex) { + return ex; + } + }; + } + return function sign(data, algo) { + const pem = this[SYM_PRIV_PEM]; + if (pem === null) + return new Error('No private key available'); + if (!algo || typeof algo !== 'string') + algo = this[SYM_HASH_ALGO]; + const signature = createSign(algo); + signature.update(data); + try { + return signature.sign(pem); + } catch (ex) { + return ex; + } + }; + })(), + verify: (() => { + if (typeof verify_ === 'function') { + return function verify(data, signature, algo) { + const pem = this[SYM_PUB_PEM]; + if (pem === null) + return new Error('No public key available'); + if (!algo || typeof algo !== 'string') + algo = this[SYM_HASH_ALGO]; + try { + return verify_(algo, data, pem, signature); + } catch (ex) { + return ex; + } + }; + } + return function verify(data, signature, algo) { + const pem = this[SYM_PUB_PEM]; + if (pem === null) + return new Error('No public key available'); + if (!algo || typeof algo !== 'string') + algo = this[SYM_HASH_ALGO]; + const verifier = createVerify(algo); + verifier.update(data); + try { + return verifier.verify(pem, signature); + } catch (ex) { + return ex; + } + }; + })(), + isPrivateKey: function isPrivateKey() { + return (this[SYM_PRIV_PEM] !== null); + }, + getPrivatePEM: function getPrivatePEM() { + return this[SYM_PRIV_PEM]; + }, + getPublicPEM: function getPublicPEM() { + return this[SYM_PUB_PEM]; + }, + getPublicSSH: function getPublicSSH() { + return this[SYM_PUB_SSH]; + }, + equals: function equals(key) { + const parsed = parseKey(key); + if (parsed instanceof Error) + return false; + return ( + this.type === parsed.type + && this[SYM_PRIV_PEM] === parsed[SYM_PRIV_PEM] + && this[SYM_PUB_PEM] === parsed[SYM_PUB_PEM] + && this[SYM_PUB_SSH] === parsed[SYM_PUB_SSH] + ); + }, +}; + + +function OpenSSH_Private(type, comment, privPEM, pubPEM, pubSSH, algo, + decrypted) { + this.type = type; + this.comment = comment; + this[SYM_PRIV_PEM] = privPEM; + this[SYM_PUB_PEM] = pubPEM; + this[SYM_PUB_SSH] = pubSSH; + this[SYM_HASH_ALGO] = algo; + this[SYM_DECRYPTED] = decrypted; +} +OpenSSH_Private.prototype = BaseKey; +{ + const regexp = /^-----BEGIN OPENSSH PRIVATE KEY-----(?:\r\n|\n)([\s\S]+)(?:\r\n|\n)-----END OPENSSH PRIVATE KEY-----$/; + OpenSSH_Private.parse = (str, passphrase) => { + const m = regexp.exec(str); + if (m === null) + return null; + let ret; + const data = Buffer.from(m[1], 'base64'); + if (data.length < 31) // magic (+ magic null term.) + minimum field lengths + return new Error('Malformed OpenSSH private key'); + const magic = data.utf8Slice(0, 15); + if (magic !== 'openssh-key-v1\0') + return new Error(`Unsupported OpenSSH key magic: ${magic}`); + + const cipherName = readString(data, 15, true); + if (cipherName === undefined) + return new Error('Malformed OpenSSH private key'); + if (cipherName !== 'none' && SUPPORTED_CIPHER.indexOf(cipherName) === -1) + return new Error(`Unsupported cipher for OpenSSH key: ${cipherName}`); + + const kdfName = readString(data, data._pos, true); + if (kdfName === undefined) + return new Error('Malformed OpenSSH private key'); + if (kdfName !== 'none') { + if (cipherName === 'none') + return new Error('Malformed OpenSSH private key'); + if (kdfName !== 'bcrypt') + return new Error(`Unsupported kdf name for OpenSSH key: ${kdfName}`); + if (!passphrase) { + return new Error( + 'Encrypted private OpenSSH key detected, but no passphrase given' + ); + } + } else if (cipherName !== 'none') { + return new Error('Malformed OpenSSH private key'); + } + + let encInfo; + let cipherKey; + let cipherIV; + if (cipherName !== 'none') + encInfo = CIPHER_INFO[cipherName]; + const kdfOptions = readString(data, data._pos); + if (kdfOptions === undefined) + return new Error('Malformed OpenSSH private key'); + if (kdfOptions.length) { + switch (kdfName) { + case 'none': + return new Error('Malformed OpenSSH private key'); + case 'bcrypt': + /* + string salt + uint32 rounds + */ + const salt = readString(kdfOptions, 0); + if (salt === undefined || kdfOptions._pos + 4 > kdfOptions.length) + return new Error('Malformed OpenSSH private key'); + const rounds = readUInt32BE(kdfOptions, kdfOptions._pos); + const gen = Buffer.allocUnsafe(encInfo.keyLen + encInfo.ivLen); + const r = bcrypt_pbkdf(passphrase, + passphrase.length, + salt, + salt.length, + gen, + gen.length, + rounds); + if (r !== 0) + return new Error('Failed to generate information to decrypt key'); + cipherKey = bufferSlice(gen, 0, encInfo.keyLen); + cipherIV = bufferSlice(gen, encInfo.keyLen, gen.length); + break; + } + } else if (kdfName !== 'none') { + return new Error('Malformed OpenSSH private key'); + } + + if (data._pos + 3 >= data.length) + return new Error('Malformed OpenSSH private key'); + const keyCount = readUInt32BE(data, data._pos); + data._pos += 4; + + if (keyCount > 0) { + // TODO: place sensible limit on max `keyCount` + + // Read public keys first + for (let i = 0; i < keyCount; ++i) { + const pubData = readString(data, data._pos); + if (pubData === undefined) + return new Error('Malformed OpenSSH private key'); + const type = readString(pubData, 0, true); + if (type === undefined) + return new Error('Malformed OpenSSH private key'); + } + + let privBlob = readString(data, data._pos); + if (privBlob === undefined) + return new Error('Malformed OpenSSH private key'); + + if (cipherKey !== undefined) { + // Encrypted private key(s) + if (privBlob.length < encInfo.blockLen + || (privBlob.length % encInfo.blockLen) !== 0) { + return new Error('Malformed OpenSSH private key'); + } + try { + const options = { authTagLength: encInfo.authLen }; + const decipher = createDecipheriv(encInfo.sslName, + cipherKey, + cipherIV, + options); + if (encInfo.authLen > 0) { + if (data.length - data._pos < encInfo.authLen) + return new Error('Malformed OpenSSH private key'); + decipher.setAuthTag( + bufferSlice(data, data._pos, data._pos += encInfo.authLen) + ); + } + privBlob = combineBuffers(decipher.update(privBlob), + decipher.final()); + } catch (ex) { + return ex; + } + } + // Nothing should we follow the private key(s), except a possible + // authentication tag for relevant ciphers + if (data._pos !== data.length) + return new Error('Malformed OpenSSH private key'); + + ret = parseOpenSSHPrivKeys(privBlob, keyCount, cipherKey !== undefined); + } else { + ret = []; + } + // This will need to change if/when OpenSSH ever starts storing multiple + // keys in their key files + return ret[0]; + }; + + function parseOpenSSHPrivKeys(data, nkeys, decrypted) { + const keys = []; + /* + uint32 checkint + uint32 checkint + string privatekey1 + string comment1 + string privatekey2 + string comment2 + ... + string privatekeyN + string commentN + char 1 + char 2 + char 3 + ... + char padlen % 255 + */ + if (data.length < 8) + return new Error('Malformed OpenSSH private key'); + const check1 = readUInt32BE(data, 0); + const check2 = readUInt32BE(data, 4); + if (check1 !== check2) { + if (decrypted) { + return new Error( + 'OpenSSH key integrity check failed -- bad passphrase?' + ); + } + return new Error('OpenSSH key integrity check failed'); + } + data._pos = 8; + let i; + let oid; + for (i = 0; i < nkeys; ++i) { + let algo; + let privPEM; + let pubPEM; + let pubSSH; + // The OpenSSH documentation for the key format actually lies, the + // entirety of the private key content is not contained with a string + // field, it's actually the literal contents of the private key, so to be + // able to find the end of the key data you need to know the layout/format + // of each key type ... + const type = readString(data, data._pos, true); + if (type === undefined) + return new Error('Malformed OpenSSH private key'); + + switch (type) { + case 'ssh-rsa': { + /* + string n -- public + string e -- public + string d -- private + string iqmp -- private + string p -- private + string q -- private + */ + const n = readString(data, data._pos); + if (n === undefined) + return new Error('Malformed OpenSSH private key'); + const e = readString(data, data._pos); + if (e === undefined) + return new Error('Malformed OpenSSH private key'); + const d = readString(data, data._pos); + if (d === undefined) + return new Error('Malformed OpenSSH private key'); + const iqmp = readString(data, data._pos); + if (iqmp === undefined) + return new Error('Malformed OpenSSH private key'); + const p = readString(data, data._pos); + if (p === undefined) + return new Error('Malformed OpenSSH private key'); + const q = readString(data, data._pos); + if (q === undefined) + return new Error('Malformed OpenSSH private key'); + + pubPEM = genOpenSSLRSAPub(n, e); + pubSSH = genOpenSSHRSAPub(n, e); + privPEM = genOpenSSLRSAPriv(n, e, d, iqmp, p, q); + algo = 'sha1'; + break; + } + case 'ssh-dss': { + /* + string p -- public + string q -- public + string g -- public + string y -- public + string x -- private + */ + const p = readString(data, data._pos); + if (p === undefined) + return new Error('Malformed OpenSSH private key'); + const q = readString(data, data._pos); + if (q === undefined) + return new Error('Malformed OpenSSH private key'); + const g = readString(data, data._pos); + if (g === undefined) + return new Error('Malformed OpenSSH private key'); + const y = readString(data, data._pos); + if (y === undefined) + return new Error('Malformed OpenSSH private key'); + const x = readString(data, data._pos); + if (x === undefined) + return new Error('Malformed OpenSSH private key'); + + pubPEM = genOpenSSLDSAPub(p, q, g, y); + pubSSH = genOpenSSHDSAPub(p, q, g, y); + privPEM = genOpenSSLDSAPriv(p, q, g, y, x); + algo = 'sha1'; + break; + } + case 'ssh-ed25519': { + if (!eddsaSupported) + return new Error(`Unsupported OpenSSH private key type: ${type}`); + /* + * string public key + * string private key + public key + */ + const edpub = readString(data, data._pos); + if (edpub === undefined || edpub.length !== 32) + return new Error('Malformed OpenSSH private key'); + const edpriv = readString(data, data._pos); + if (edpriv === undefined || edpriv.length !== 64) + return new Error('Malformed OpenSSH private key'); + + pubPEM = genOpenSSLEdPub(edpub); + pubSSH = genOpenSSHEdPub(edpub); + privPEM = genOpenSSLEdPriv(bufferSlice(edpriv, 0, 32)); + algo = null; + break; + } + case 'ecdsa-sha2-nistp256': + algo = 'sha256'; + oid = '1.2.840.10045.3.1.7'; + // FALLTHROUGH + case 'ecdsa-sha2-nistp384': + if (algo === undefined) { + algo = 'sha384'; + oid = '1.3.132.0.34'; + } + // FALLTHROUGH + case 'ecdsa-sha2-nistp521': { + if (algo === undefined) { + algo = 'sha512'; + oid = '1.3.132.0.35'; + } + /* + string curve name + string Q -- public + string d -- private + */ + // TODO: validate curve name against type + if (!skipFields(data, 1)) // Skip curve name + return new Error('Malformed OpenSSH private key'); + const ecpub = readString(data, data._pos); + if (ecpub === undefined) + return new Error('Malformed OpenSSH private key'); + const ecpriv = readString(data, data._pos); + if (ecpriv === undefined) + return new Error('Malformed OpenSSH private key'); + + pubPEM = genOpenSSLECDSAPub(oid, ecpub); + pubSSH = genOpenSSHECDSAPub(oid, ecpub); + privPEM = genOpenSSLECDSAPriv(oid, ecpub, ecpriv); + break; + } + default: + return new Error(`Unsupported OpenSSH private key type: ${type}`); + } + + const privComment = readString(data, data._pos, true); + if (privComment === undefined) + return new Error('Malformed OpenSSH private key'); + + keys.push( + new OpenSSH_Private(type, privComment, privPEM, pubPEM, pubSSH, algo, + decrypted) + ); + } + let cnt = 0; + for (i = data._pos; i < data.length; ++i) { + if (data[i] !== (++cnt % 255)) + return new Error('Malformed OpenSSH private key'); + } + + return keys; + } +} + + +function OpenSSH_Old_Private(type, comment, privPEM, pubPEM, pubSSH, algo, + decrypted) { + this.type = type; + this.comment = comment; + this[SYM_PRIV_PEM] = privPEM; + this[SYM_PUB_PEM] = pubPEM; + this[SYM_PUB_SSH] = pubSSH; + this[SYM_HASH_ALGO] = algo; + this[SYM_DECRYPTED] = decrypted; +} +OpenSSH_Old_Private.prototype = BaseKey; +{ + const regexp = /^-----BEGIN (RSA|DSA|EC) PRIVATE KEY-----(?:\r\n|\n)((?:[^:]+:\s*[\S].*(?:\r\n|\n))*)([\s\S]+)(?:\r\n|\n)-----END (RSA|DSA|EC) PRIVATE KEY-----$/; + OpenSSH_Old_Private.parse = (str, passphrase) => { + const m = regexp.exec(str); + if (m === null) + return null; + let privBlob = Buffer.from(m[3], 'base64'); + let headers = m[2]; + let decrypted = false; + if (headers !== undefined) { + // encrypted key + headers = headers.split(/\r\n|\n/g); + for (let i = 0; i < headers.length; ++i) { + const header = headers[i]; + let sepIdx = header.indexOf(':'); + if (header.slice(0, sepIdx) === 'DEK-Info') { + const val = header.slice(sepIdx + 2); + sepIdx = val.indexOf(','); + if (sepIdx === -1) + continue; + const cipherName = val.slice(0, sepIdx).toLowerCase(); + if (supportedOpenSSLCiphers.indexOf(cipherName) === -1) { + return new Error( + `Cipher (${cipherName}) not supported ` + + 'for encrypted OpenSSH private key' + ); + } + const encInfo = CIPHER_INFO_OPENSSL[cipherName]; + if (!encInfo) { + return new Error( + `Cipher (${cipherName}) not supported ` + + 'for encrypted OpenSSH private key' + ); + } + const cipherIV = Buffer.from(val.slice(sepIdx + 1), 'hex'); + if (cipherIV.length !== encInfo.ivLen) + return new Error('Malformed encrypted OpenSSH private key'); + if (!passphrase) { + return new Error( + 'Encrypted OpenSSH private key detected, but no passphrase given' + ); + } + const ivSlice = bufferSlice(cipherIV, 0, 8); + let cipherKey = createHash('md5') + .update(passphrase) + .update(ivSlice) + .digest(); + while (cipherKey.length < encInfo.keyLen) { + cipherKey = combineBuffers( + cipherKey, + createHash('md5') + .update(cipherKey) + .update(passphrase) + .update(ivSlice) + .digest() + ); + } + if (cipherKey.length > encInfo.keyLen) + cipherKey = bufferSlice(cipherKey, 0, encInfo.keyLen); + try { + const decipher = createDecipheriv(cipherName, cipherKey, cipherIV); + decipher.setAutoPadding(false); + privBlob = combineBuffers(decipher.update(privBlob), + decipher.final()); + decrypted = true; + } catch (ex) { + return ex; + } + } + } + } + + let type; + let privPEM; + let pubPEM; + let pubSSH; + let algo; + let reader; + let errMsg = 'Malformed OpenSSH private key'; + if (decrypted) + errMsg += '. Bad passphrase?'; + switch (m[1]) { + case 'RSA': + type = 'ssh-rsa'; + privPEM = makePEM('RSA PRIVATE', privBlob); + try { + reader = new Ber.Reader(privBlob); + reader.readSequence(); + reader.readInt(); // skip version + const n = reader.readString(Ber.Integer, true); + if (n === null) + return new Error(errMsg); + const e = reader.readString(Ber.Integer, true); + if (e === null) + return new Error(errMsg); + pubPEM = genOpenSSLRSAPub(n, e); + pubSSH = genOpenSSHRSAPub(n, e); + } catch { + return new Error(errMsg); + } + algo = 'sha1'; + break; + case 'DSA': + type = 'ssh-dss'; + privPEM = makePEM('DSA PRIVATE', privBlob); + try { + reader = new Ber.Reader(privBlob); + reader.readSequence(); + reader.readInt(); // skip version + const p = reader.readString(Ber.Integer, true); + if (p === null) + return new Error(errMsg); + const q = reader.readString(Ber.Integer, true); + if (q === null) + return new Error(errMsg); + const g = reader.readString(Ber.Integer, true); + if (g === null) + return new Error(errMsg); + const y = reader.readString(Ber.Integer, true); + if (y === null) + return new Error(errMsg); + pubPEM = genOpenSSLDSAPub(p, q, g, y); + pubSSH = genOpenSSHDSAPub(p, q, g, y); + } catch { + return new Error(errMsg); + } + algo = 'sha1'; + break; + case 'EC': + let ecSSLName; + let ecPriv; + let ecOID; + try { + reader = new Ber.Reader(privBlob); + reader.readSequence(); + reader.readInt(); // skip version + ecPriv = reader.readString(Ber.OctetString, true); + reader.readByte(); // Skip "complex" context type byte + const offset = reader.readLength(); // Skip context length + if (offset !== null) { + reader._offset = offset; + ecOID = reader.readOID(); + if (ecOID === null) + return new Error(errMsg); + switch (ecOID) { + case '1.2.840.10045.3.1.7': + // prime256v1/secp256r1 + ecSSLName = 'prime256v1'; + type = 'ecdsa-sha2-nistp256'; + algo = 'sha256'; + break; + case '1.3.132.0.34': + // secp384r1 + ecSSLName = 'secp384r1'; + type = 'ecdsa-sha2-nistp384'; + algo = 'sha384'; + break; + case '1.3.132.0.35': + // secp521r1 + ecSSLName = 'secp521r1'; + type = 'ecdsa-sha2-nistp521'; + algo = 'sha512'; + break; + default: + return new Error(`Unsupported private key EC OID: ${ecOID}`); + } + } else { + return new Error(errMsg); + } + } catch { + return new Error(errMsg); + } + privPEM = makePEM('EC PRIVATE', privBlob); + const pubBlob = genOpenSSLECDSAPubFromPriv(ecSSLName, ecPriv); + pubPEM = genOpenSSLECDSAPub(ecOID, pubBlob); + pubSSH = genOpenSSHECDSAPub(ecOID, pubBlob); + break; + } + + return new OpenSSH_Old_Private(type, '', privPEM, pubPEM, pubSSH, algo, + decrypted); + }; +} + + +function PPK_Private(type, comment, privPEM, pubPEM, pubSSH, algo, decrypted) { + this.type = type; + this.comment = comment; + this[SYM_PRIV_PEM] = privPEM; + this[SYM_PUB_PEM] = pubPEM; + this[SYM_PUB_SSH] = pubSSH; + this[SYM_HASH_ALGO] = algo; + this[SYM_DECRYPTED] = decrypted; +} +PPK_Private.prototype = BaseKey; +{ + const EMPTY_PASSPHRASE = Buffer.alloc(0); + const PPK_IV = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + const PPK_PP1 = Buffer.from([0, 0, 0, 0]); + const PPK_PP2 = Buffer.from([0, 0, 0, 1]); + const regexp = /^PuTTY-User-Key-File-2: (ssh-(?:rsa|dss))\r?\nEncryption: (aes256-cbc|none)\r?\nComment: ([^\r\n]*)\r?\nPublic-Lines: \d+\r?\n([\s\S]+?)\r?\nPrivate-Lines: \d+\r?\n([\s\S]+?)\r?\nPrivate-MAC: ([^\r\n]+)/; + PPK_Private.parse = (str, passphrase) => { + const m = regexp.exec(str); + if (m === null) + return null; + // m[1] = key type + // m[2] = encryption type + // m[3] = comment + // m[4] = base64-encoded public key data: + // for "ssh-rsa": + // string "ssh-rsa" + // mpint e (public exponent) + // mpint n (modulus) + // for "ssh-dss": + // string "ssh-dss" + // mpint p (modulus) + // mpint q (prime) + // mpint g (base number) + // mpint y (public key parameter: g^x mod p) + // m[5] = base64-encoded private key data: + // for "ssh-rsa": + // mpint d (private exponent) + // mpint p (prime 1) + // mpint q (prime 2) + // mpint iqmp ([inverse of q] mod p) + // for "ssh-dss": + // mpint x (private key parameter) + // m[6] = SHA1 HMAC over: + // string name of algorithm ("ssh-dss", "ssh-rsa") + // string encryption type + // string comment + // string public key data + // string private-plaintext (including the final padding) + const cipherName = m[2]; + const encrypted = (cipherName !== 'none'); + if (encrypted && !passphrase) { + return new Error( + 'Encrypted PPK private key detected, but no passphrase given' + ); + } + + let privBlob = Buffer.from(m[5], 'base64'); + + if (encrypted) { + const encInfo = CIPHER_INFO[cipherName]; + let cipherKey = combineBuffers( + createHash('sha1').update(PPK_PP1).update(passphrase).digest(), + createHash('sha1').update(PPK_PP2).update(passphrase).digest() + ); + if (cipherKey.length > encInfo.keyLen) + cipherKey = bufferSlice(cipherKey, 0, encInfo.keyLen); + try { + const decipher = createDecipheriv(encInfo.sslName, + cipherKey, + PPK_IV); + decipher.setAutoPadding(false); + privBlob = combineBuffers(decipher.update(privBlob), + decipher.final()); + } catch (ex) { + return ex; + } + } + + const type = m[1]; + const comment = m[3]; + const pubBlob = Buffer.from(m[4], 'base64'); + + const mac = m[6]; + const typeLen = type.length; + const cipherNameLen = cipherName.length; + const commentLen = Buffer.byteLength(comment); + const pubLen = pubBlob.length; + const privLen = privBlob.length; + const macData = Buffer.allocUnsafe(4 + typeLen + + 4 + cipherNameLen + + 4 + commentLen + + 4 + pubLen + + 4 + privLen); + let p = 0; + + writeUInt32BE(macData, typeLen, p); + macData.utf8Write(type, p += 4, typeLen); + writeUInt32BE(macData, cipherNameLen, p += typeLen); + macData.utf8Write(cipherName, p += 4, cipherNameLen); + writeUInt32BE(macData, commentLen, p += cipherNameLen); + macData.utf8Write(comment, p += 4, commentLen); + writeUInt32BE(macData, pubLen, p += commentLen); + macData.set(pubBlob, p += 4); + writeUInt32BE(macData, privLen, p += pubLen); + macData.set(privBlob, p + 4); + + if (!passphrase) + passphrase = EMPTY_PASSPHRASE; + + const calcMAC = createHmac( + 'sha1', + createHash('sha1') + .update('putty-private-key-file-mac-key') + .update(passphrase) + .digest() + ).update(macData).digest('hex'); + + if (calcMAC !== mac) { + if (encrypted) { + return new Error( + 'PPK private key integrity check failed -- bad passphrase?' + ); + } + return new Error('PPK private key integrity check failed'); + } + + let pubPEM; + let pubSSH; + let privPEM; + pubBlob._pos = 0; + skipFields(pubBlob, 1); // skip (duplicate) key type + switch (type) { + case 'ssh-rsa': { + const e = readString(pubBlob, pubBlob._pos); + if (e === undefined) + return new Error('Malformed PPK public key'); + const n = readString(pubBlob, pubBlob._pos); + if (n === undefined) + return new Error('Malformed PPK public key'); + const d = readString(privBlob, 0); + if (d === undefined) + return new Error('Malformed PPK private key'); + const p = readString(privBlob, privBlob._pos); + if (p === undefined) + return new Error('Malformed PPK private key'); + const q = readString(privBlob, privBlob._pos); + if (q === undefined) + return new Error('Malformed PPK private key'); + const iqmp = readString(privBlob, privBlob._pos); + if (iqmp === undefined) + return new Error('Malformed PPK private key'); + pubPEM = genOpenSSLRSAPub(n, e); + pubSSH = genOpenSSHRSAPub(n, e); + privPEM = genOpenSSLRSAPriv(n, e, d, iqmp, p, q); + break; + } + case 'ssh-dss': { + const p = readString(pubBlob, pubBlob._pos); + if (p === undefined) + return new Error('Malformed PPK public key'); + const q = readString(pubBlob, pubBlob._pos); + if (q === undefined) + return new Error('Malformed PPK public key'); + const g = readString(pubBlob, pubBlob._pos); + if (g === undefined) + return new Error('Malformed PPK public key'); + const y = readString(pubBlob, pubBlob._pos); + if (y === undefined) + return new Error('Malformed PPK public key'); + const x = readString(privBlob, 0); + if (x === undefined) + return new Error('Malformed PPK private key'); + + pubPEM = genOpenSSLDSAPub(p, q, g, y); + pubSSH = genOpenSSHDSAPub(p, q, g, y); + privPEM = genOpenSSLDSAPriv(p, q, g, y, x); + break; + } + } + + return new PPK_Private(type, comment, privPEM, pubPEM, pubSSH, 'sha1', + encrypted); + }; +} + + +function OpenSSH_Public(type, comment, pubPEM, pubSSH, algo) { + this.type = type; + this.comment = comment; + this[SYM_PRIV_PEM] = null; + this[SYM_PUB_PEM] = pubPEM; + this[SYM_PUB_SSH] = pubSSH; + this[SYM_HASH_ALGO] = algo; + this[SYM_DECRYPTED] = false; +} +OpenSSH_Public.prototype = BaseKey; +{ + let regexp; + if (eddsaSupported) + regexp = /^(((?:ssh-(?:rsa|dss|ed25519))|ecdsa-sha2-nistp(?:256|384|521))(?:-cert-v0[01]@openssh.com)?) ([A-Z0-9a-z/+=]+)(?:$|\s+([\S].*)?)$/; + else + regexp = /^(((?:ssh-(?:rsa|dss))|ecdsa-sha2-nistp(?:256|384|521))(?:-cert-v0[01]@openssh.com)?) ([A-Z0-9a-z/+=]+)(?:$|\s+([\S].*)?)$/; + OpenSSH_Public.parse = (str) => { + const m = regexp.exec(str); + if (m === null) + return null; + // m[1] = full type + // m[2] = base type + // m[3] = base64-encoded public key + // m[4] = comment + + const fullType = m[1]; + const baseType = m[2]; + const data = Buffer.from(m[3], 'base64'); + const comment = (m[4] || ''); + + const type = readString(data, data._pos, true); + if (type === undefined || type.indexOf(baseType) !== 0) + return new Error('Malformed OpenSSH public key'); + + return parseDER(data, baseType, comment, fullType); + }; +} + + +function RFC4716_Public(type, comment, pubPEM, pubSSH, algo) { + this.type = type; + this.comment = comment; + this[SYM_PRIV_PEM] = null; + this[SYM_PUB_PEM] = pubPEM; + this[SYM_PUB_SSH] = pubSSH; + this[SYM_HASH_ALGO] = algo; + this[SYM_DECRYPTED] = false; +} +RFC4716_Public.prototype = BaseKey; +{ + const regexp = /^---- BEGIN SSH2 PUBLIC KEY ----(?:\r?\n)((?:.{0,72}\r?\n)+)---- END SSH2 PUBLIC KEY ----$/; + const RE_DATA = /^[A-Z0-9a-z/+=\r\n]+$/; + const RE_HEADER = /^([\x21-\x39\x3B-\x7E]{1,64}): ((?:[^\\]*\\\r?\n)*[^\r\n]+)\r?\n/gm; + const RE_HEADER_ENDS = /\\\r?\n/g; + RFC4716_Public.parse = (str) => { + let m = regexp.exec(str); + if (m === null) + return null; + + const body = m[1]; + let dataStart = 0; + let comment = ''; + + while (m = RE_HEADER.exec(body)) { + const headerName = m[1]; + const headerValue = m[2].replace(RE_HEADER_ENDS, ''); + if (headerValue.length > 1024) { + RE_HEADER.lastIndex = 0; + return new Error('Malformed RFC4716 public key'); + } + + dataStart = RE_HEADER.lastIndex; + + if (headerName.toLowerCase() === 'comment') { + comment = headerValue; + if (comment.length > 1 + && comment.charCodeAt(0) === 34/* '"' */ + && comment.charCodeAt(comment.length - 1) === 34/* '"' */) { + comment = comment.slice(1, -1); + } + } + } + + let data = body.slice(dataStart); + if (!RE_DATA.test(data)) + return new Error('Malformed RFC4716 public key'); + + data = Buffer.from(data, 'base64'); + + const type = readString(data, 0, true); + if (type === undefined) + return new Error('Malformed RFC4716 public key'); + + let pubPEM = null; + let pubSSH = null; + switch (type) { + case 'ssh-rsa': { + const e = readString(data, data._pos); + if (e === undefined) + return new Error('Malformed RFC4716 public key'); + const n = readString(data, data._pos); + if (n === undefined) + return new Error('Malformed RFC4716 public key'); + pubPEM = genOpenSSLRSAPub(n, e); + pubSSH = genOpenSSHRSAPub(n, e); + break; + } + case 'ssh-dss': { + const p = readString(data, data._pos); + if (p === undefined) + return new Error('Malformed RFC4716 public key'); + const q = readString(data, data._pos); + if (q === undefined) + return new Error('Malformed RFC4716 public key'); + const g = readString(data, data._pos); + if (g === undefined) + return new Error('Malformed RFC4716 public key'); + const y = readString(data, data._pos); + if (y === undefined) + return new Error('Malformed RFC4716 public key'); + pubPEM = genOpenSSLDSAPub(p, q, g, y); + pubSSH = genOpenSSHDSAPub(p, q, g, y); + break; + } + default: + return new Error('Malformed RFC4716 public key'); + } + + return new RFC4716_Public(type, comment, pubPEM, pubSSH, 'sha1'); + }; +} + + +function parseDER(data, baseType, comment, fullType) { + if (!isSupportedKeyType(baseType)) + return new Error(`Unsupported OpenSSH public key type: ${baseType}`); + + let algo; + let oid; + let pubPEM = null; + let pubSSH = null; + + switch (baseType) { + case 'ssh-rsa': { + const e = readString(data, data._pos || 0); + if (e === undefined) + return new Error('Malformed OpenSSH public key'); + const n = readString(data, data._pos); + if (n === undefined) + return new Error('Malformed OpenSSH public key'); + pubPEM = genOpenSSLRSAPub(n, e); + pubSSH = genOpenSSHRSAPub(n, e); + algo = 'sha1'; + break; + } + case 'ssh-dss': { + const p = readString(data, data._pos || 0); + if (p === undefined) + return new Error('Malformed OpenSSH public key'); + const q = readString(data, data._pos); + if (q === undefined) + return new Error('Malformed OpenSSH public key'); + const g = readString(data, data._pos); + if (g === undefined) + return new Error('Malformed OpenSSH public key'); + const y = readString(data, data._pos); + if (y === undefined) + return new Error('Malformed OpenSSH public key'); + pubPEM = genOpenSSLDSAPub(p, q, g, y); + pubSSH = genOpenSSHDSAPub(p, q, g, y); + algo = 'sha1'; + break; + } + case 'ssh-ed25519': { + const edpub = readString(data, data._pos || 0); + if (edpub === undefined || edpub.length !== 32) + return new Error('Malformed OpenSSH public key'); + pubPEM = genOpenSSLEdPub(edpub); + pubSSH = genOpenSSHEdPub(edpub); + algo = null; + break; + } + case 'ecdsa-sha2-nistp256': + algo = 'sha256'; + oid = '1.2.840.10045.3.1.7'; + // FALLTHROUGH + case 'ecdsa-sha2-nistp384': + if (algo === undefined) { + algo = 'sha384'; + oid = '1.3.132.0.34'; + } + // FALLTHROUGH + case 'ecdsa-sha2-nistp521': { + if (algo === undefined) { + algo = 'sha512'; + oid = '1.3.132.0.35'; + } + // TODO: validate curve name against type + if (!skipFields(data, 1)) // Skip curve name + return new Error('Malformed OpenSSH public key'); + const ecpub = readString(data, data._pos || 0); + if (ecpub === undefined) + return new Error('Malformed OpenSSH public key'); + pubPEM = genOpenSSLECDSAPub(oid, ecpub); + pubSSH = genOpenSSHECDSAPub(oid, ecpub); + break; + } + default: + return new Error(`Unsupported OpenSSH public key type: ${baseType}`); + } + + return new OpenSSH_Public(fullType, comment, pubPEM, pubSSH, algo); +} + +function isSupportedKeyType(type) { + switch (type) { + case 'ssh-rsa': + case 'ssh-dss': + case 'ecdsa-sha2-nistp256': + case 'ecdsa-sha2-nistp384': + case 'ecdsa-sha2-nistp521': + return true; + case 'ssh-ed25519': + if (eddsaSupported) + return true; + // FALLTHROUGH + default: + return false; + } +} + +function isParsedKey(val) { + if (!val) + return false; + return (typeof val[SYM_DECRYPTED] === 'boolean'); +} + +function parseKey(data, passphrase) { + if (isParsedKey(data)) + return data; + + let origBuffer; + if (Buffer.isBuffer(data)) { + origBuffer = data; + data = data.utf8Slice(0, data.length).trim(); + } else if (typeof data === 'string') { + data = data.trim(); + } else { + return new Error('Key data must be a Buffer or string'); + } + + // eslint-disable-next-line eqeqeq + if (passphrase != undefined) { + if (typeof passphrase === 'string') + passphrase = Buffer.from(passphrase); + else if (!Buffer.isBuffer(passphrase)) + return new Error('Passphrase must be a string or Buffer when supplied'); + } + + let ret; + + // First try as printable string format (e.g. PEM) + + // Private keys + if ((ret = OpenSSH_Private.parse(data, passphrase)) !== null) + return ret; + if ((ret = OpenSSH_Old_Private.parse(data, passphrase)) !== null) + return ret; + if ((ret = PPK_Private.parse(data, passphrase)) !== null) + return ret; + + // Public keys + if ((ret = OpenSSH_Public.parse(data)) !== null) + return ret; + if ((ret = RFC4716_Public.parse(data)) !== null) + return ret; + + // Finally try as a binary format if we were originally passed binary data + if (origBuffer) { + binaryKeyParser.init(origBuffer, 0); + const type = binaryKeyParser.readString(true); + if (type !== undefined) { + data = binaryKeyParser.readRaw(); + if (data !== undefined) { + ret = parseDER(data, type, '', type); + // Ignore potentially useless errors in case the data was not actually + // in the binary format + if (ret instanceof Error) + ret = null; + } + } + binaryKeyParser.clear(); + } + + if (ret) + return ret; + + return new Error('Unsupported key format'); +} + +module.exports = { + isParsedKey, + isSupportedKeyType, + parseDERKey: (data, type) => parseDER(data, type, '', type), + parseKey, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/node-fs-compat.js b/reverse_engineering/node_modules/ssh2/lib/protocol/node-fs-compat.js new file mode 100644 index 0000000..80ed71f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/node-fs-compat.js @@ -0,0 +1,115 @@ +'use strict'; + +const assert = require('assert'); +const { inspect } = require('util'); + +// Only use this for integers! Decimal numbers do not work with this function. +function addNumericalSeparator(val) { + let res = ''; + let i = val.length; + const start = val[0] === '-' ? 1 : 0; + for (; i >= start + 4; i -= 3) + res = `_${val.slice(i - 3, i)}${res}`; + return `${val.slice(0, i)}${res}`; +} + +function oneOf(expected, thing) { + assert(typeof thing === 'string', '`thing` has to be of type string'); + if (Array.isArray(expected)) { + const len = expected.length; + assert(len > 0, 'At least one expected value needs to be specified'); + expected = expected.map((i) => String(i)); + if (len > 2) { + return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` + + expected[len - 1]; + } else if (len === 2) { + return `one of ${thing} ${expected[0]} or ${expected[1]}`; + } + return `of ${thing} ${expected[0]}`; + } + return `of ${thing} ${String(expected)}`; +} + + +exports.ERR_INTERNAL_ASSERTION = class ERR_INTERNAL_ASSERTION extends Error { + constructor(message) { + super(); + Error.captureStackTrace(this, ERR_INTERNAL_ASSERTION); + + const suffix = 'This is caused by either a bug in ssh2 ' + + 'or incorrect usage of ssh2 internals.\n' + + 'Please open an issue with this stack trace at ' + + 'https://github.com/mscdex/ssh2/issues\n'; + + this.message = (message === undefined ? suffix : `${message}\n${suffix}`); + } +}; + +const MAX_32BIT_INT = 2 ** 32; +const MAX_32BIT_BIGINT = (() => { + try { + return new Function('return 2n ** 32n')(); + } catch {} +})(); +exports.ERR_OUT_OF_RANGE = class ERR_OUT_OF_RANGE extends RangeError { + constructor(str, range, input, replaceDefaultBoolean) { + super(); + Error.captureStackTrace(this, ERR_OUT_OF_RANGE); + + assert(range, 'Missing "range" argument'); + let msg = (replaceDefaultBoolean + ? str + : `The value of "${str}" is out of range.`); + let received; + if (Number.isInteger(input) && Math.abs(input) > MAX_32BIT_INT) { + received = addNumericalSeparator(String(input)); + } else if (typeof input === 'bigint') { + received = String(input); + if (input > MAX_32BIT_BIGINT || input < -MAX_32BIT_BIGINT) + received = addNumericalSeparator(received); + received += 'n'; + } else { + received = inspect(input); + } + msg += ` It must be ${range}. Received ${received}`; + + this.message = msg; + } +}; + +class ERR_INVALID_ARG_TYPE extends TypeError { + constructor(name, expected, actual) { + super(); + Error.captureStackTrace(this, ERR_INVALID_ARG_TYPE); + + assert(typeof name === 'string', `'name' must be a string`); + + // determiner: 'must be' or 'must not be' + let determiner; + if (typeof expected === 'string' && expected.startsWith('not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + let msg; + if (name.endsWith(' argument')) { + // For cases like 'first argument' + msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`; + } else { + const type = (name.includes('.') ? 'property' : 'argument'); + msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`; + } + + msg += `. Received type ${typeof actual}`; + + this.message = msg; + } +} +exports.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE; + +exports.validateNumber = function validateNumber(value, name) { + if (typeof value !== 'number') + throw new ERR_INVALID_ARG_TYPE(name, 'number', value); +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/utils.js b/reverse_engineering/node_modules/ssh2/lib/protocol/utils.js new file mode 100644 index 0000000..0dab875 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/utils.js @@ -0,0 +1,356 @@ +'use strict'; + +const Ber = require('asn1').Ber; + +let DISCONNECT_REASON; + +const FastBuffer = Buffer[Symbol.species]; +const TypedArrayFill = Object.getPrototypeOf(Uint8Array.prototype).fill; + +function readUInt32BE(buf, offset) { + return (buf[offset++] * 16777216) + + (buf[offset++] * 65536) + + (buf[offset++] * 256) + + buf[offset]; +} + +function bufferCopy(src, dest, srcStart, srcEnd, destStart) { + if (!destStart) + destStart = 0; + if (srcEnd > src.length) + srcEnd = src.length; + let nb = srcEnd - srcStart; + const destLeft = (dest.length - destStart); + if (nb > destLeft) + nb = destLeft; + dest.set(new Uint8Array(src.buffer, src.byteOffset + srcStart, nb), + destStart); + return nb; +} + +function bufferSlice(buf, start, end) { + if (end === undefined) + end = buf.length; + return new FastBuffer(buf.buffer, buf.byteOffset + start, end - start); +} + +function makeBufferParser() { + let pos = 0; + let buffer; + + const self = { + init: (buf, start) => { + buffer = buf; + pos = (typeof start === 'number' ? start : 0); + }, + pos: () => pos, + length: () => (buffer ? buffer.length : 0), + avail: () => (buffer && pos < buffer.length ? buffer.length - pos : 0), + clear: () => { + buffer = undefined; + }, + readUInt32BE: () => { + if (!buffer || pos + 3 >= buffer.length) + return; + return (buffer[pos++] * 16777216) + + (buffer[pos++] * 65536) + + (buffer[pos++] * 256) + + buffer[pos++]; + }, + readUInt64BE: (behavior) => { + if (!buffer || pos + 7 >= buffer.length) + return; + switch (behavior) { + case 'always': + return BigInt(`0x${buffer.hexSlice(pos, pos += 8)}`); + case 'maybe': + if (buffer[pos] > 0x1F) + return BigInt(`0x${buffer.hexSlice(pos, pos += 8)}`); + // FALLTHROUGH + default: + return (buffer[pos++] * 72057594037927940) + + (buffer[pos++] * 281474976710656) + + (buffer[pos++] * 1099511627776) + + (buffer[pos++] * 4294967296) + + (buffer[pos++] * 16777216) + + (buffer[pos++] * 65536) + + (buffer[pos++] * 256) + + buffer[pos++]; + } + }, + skip: (n) => { + if (buffer && n > 0) + pos += n; + }, + skipString: () => { + const len = self.readUInt32BE(); + if (len === undefined) + return; + pos += len; + return (pos <= buffer.length ? len : undefined); + }, + readByte: () => { + if (buffer && pos < buffer.length) + return buffer[pos++]; + }, + readBool: () => { + if (buffer && pos < buffer.length) + return !!buffer[pos++]; + }, + readList: () => { + const list = self.readString(true); + if (list === undefined) + return; + return (list ? list.split(',') : []); + }, + readString: (dest, maxLen) => { + if (typeof dest === 'number') { + maxLen = dest; + dest = undefined; + } + + const len = self.readUInt32BE(); + if (len === undefined) + return; + + if ((buffer.length - pos) < len + || (typeof maxLen === 'number' && len > maxLen)) { + return; + } + + if (dest) { + if (Buffer.isBuffer(dest)) + return bufferCopy(buffer, dest, pos, pos += len); + return buffer.utf8Slice(pos, pos += len); + } + return bufferSlice(buffer, pos, pos += len); + }, + readRaw: (len) => { + if (!buffer) + return; + if (typeof len !== 'number') + return bufferSlice(buffer, pos, pos += (buffer.length - pos)); + if ((buffer.length - pos) >= len) + return bufferSlice(buffer, pos, pos += len); + }, + }; + + return self; +} + +function makeError(msg, level, fatal) { + const err = new Error(msg); + if (typeof level === 'boolean') { + fatal = level; + err.level = 'protocol'; + } else { + err.level = level || 'protocol'; + } + err.fatal = !!fatal; + return err; +} + +function writeUInt32BE(buf, value, offset) { + buf[offset++] = (value >>> 24); + buf[offset++] = (value >>> 16); + buf[offset++] = (value >>> 8); + buf[offset++] = value; + return offset; +} + +const utilBufferParser = makeBufferParser(); + +module.exports = { + bufferCopy, + bufferSlice, + FastBuffer, + bufferFill: (buf, value, start, end) => { + return TypedArrayFill.call(buf, value, start, end); + }, + makeError, + doFatalError: (protocol, msg, level, reason) => { + let err; + if (DISCONNECT_REASON === undefined) + ({ DISCONNECT_REASON } = require('./utils.js')); + if (msg instanceof Error) { + // doFatalError(protocol, err[, reason]) + err = msg; + if (typeof level !== 'number') + reason = DISCONNECT_REASON.PROTOCOL_ERROR; + else + reason = level; + } else { + // doFatalError(protocol, msg[, level[, reason]]) + err = makeError(msg, level, true); + } + if (typeof reason !== 'number') + reason = DISCONNECT_REASON.PROTOCOL_ERROR; + protocol.disconnect(reason); + protocol._destruct(); + protocol._onError(err); + return Infinity; + }, + readUInt32BE, + writeUInt32BE, + writeUInt32LE: (buf, value, offset) => { + buf[offset++] = value; + buf[offset++] = (value >>> 8); + buf[offset++] = (value >>> 16); + buf[offset++] = (value >>> 24); + return offset; + }, + makeBufferParser, + bufferParser: makeBufferParser(), + readString: (buffer, start, dest, maxLen) => { + if (typeof dest === 'number') { + maxLen = dest; + dest = undefined; + } + + if (start === undefined) + start = 0; + + const left = (buffer.length - start); + if (start < 0 || start >= buffer.length || left < 4) + return; + + const len = readUInt32BE(buffer, start); + if (left < (4 + len) || (typeof maxLen === 'number' && len > maxLen)) + return; + + start += 4; + const end = start + len; + buffer._pos = end; + + if (dest) { + if (Buffer.isBuffer(dest)) + return bufferCopy(buffer, dest, start, end); + return buffer.utf8Slice(start, end); + } + return bufferSlice(buffer, start, end); + }, + sigSSHToASN1: (sig, type) => { + switch (type) { + case 'ssh-dss': { + if (sig.length > 40) + return sig; + // Change bare signature r and s values to ASN.1 BER values for OpenSSL + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + let r = sig.slice(0, 20); + let s = sig.slice(20); + if (r[0] & 0x80) { + const rNew = Buffer.allocUnsafe(21); + rNew[0] = 0x00; + r.copy(rNew, 1); + r = rNew; + } else if (r[0] === 0x00 && !(r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] & 0x80) { + const sNew = Buffer.allocUnsafe(21); + sNew[0] = 0x00; + s.copy(sNew, 1); + s = sNew; + } else if (s[0] === 0x00 && !(s[1] & 0x80)) { + s = s.slice(1); + } + asnWriter.writeBuffer(r, Ber.Integer); + asnWriter.writeBuffer(s, Ber.Integer); + asnWriter.endSequence(); + return asnWriter.buffer; + } + case 'ecdsa-sha2-nistp256': + case 'ecdsa-sha2-nistp384': + case 'ecdsa-sha2-nistp521': { + utilBufferParser.init(sig, 0); + const r = utilBufferParser.readString(); + const s = utilBufferParser.readString(); + utilBufferParser.clear(); + if (r === undefined || s === undefined) + return; + + const asnWriter = new Ber.Writer(); + asnWriter.startSequence(); + asnWriter.writeBuffer(r, Ber.Integer); + asnWriter.writeBuffer(s, Ber.Integer); + asnWriter.endSequence(); + return asnWriter.buffer; + } + default: + return sig; + } + }, + convertSignature: (signature, keyType) => { + switch (keyType) { + case 'ssh-dss': { + if (signature.length <= 40) + return signature; + // This is a quick and dirty way to get from BER encoded r and s that + // OpenSSL gives us, to just the bare values back to back (40 bytes + // total) like OpenSSH (and possibly others) are expecting + const asnReader = new Ber.Reader(signature); + asnReader.readSequence(); + let r = asnReader.readString(Ber.Integer, true); + let s = asnReader.readString(Ber.Integer, true); + let rOffset = 0; + let sOffset = 0; + if (r.length < 20) { + const rNew = Buffer.allocUnsafe(20); + rNew.set(r, 1); + r = rNew; + r[0] = 0; + } + if (s.length < 20) { + const sNew = Buffer.allocUnsafe(20); + sNew.set(s, 1); + s = sNew; + s[0] = 0; + } + if (r.length > 20 && r[0] === 0) + rOffset = 1; + if (s.length > 20 && s[0] === 0) + sOffset = 1; + const newSig = + Buffer.allocUnsafe((r.length - rOffset) + (s.length - sOffset)); + bufferCopy(r, newSig, rOffset, r.length, 0); + bufferCopy(s, newSig, sOffset, s.length, r.length - rOffset); + return newSig; + } + case 'ecdsa-sha2-nistp256': + case 'ecdsa-sha2-nistp384': + case 'ecdsa-sha2-nistp521': { + if (signature[0] === 0) + return signature; + // Convert SSH signature parameters to ASN.1 BER values for OpenSSL + const asnReader = new Ber.Reader(signature); + asnReader.readSequence(); + const r = asnReader.readString(Ber.Integer, true); + const s = asnReader.readString(Ber.Integer, true); + if (r === null || s === null) + return; + const newSig = Buffer.allocUnsafe(4 + r.length + 4 + s.length); + writeUInt32BE(newSig, r.length, 0); + newSig.set(r, 4); + writeUInt32BE(newSig, s.length, 4 + r.length); + newSig.set(s, 4 + 4 + r.length); + return newSig; + } + } + + return signature; + }, + sendPacket: (proto, packet, bypass) => { + if (!bypass && proto._kexinit !== undefined) { + // We're currently in the middle of a handshake + + if (proto._queue === undefined) + proto._queue = []; + proto._queue.push(packet); + proto._debug && proto._debug('Outbound: ... packet queued'); + return false; + } + proto._cipher.encrypt(packet); + return true; + }, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/protocol/zlib.js b/reverse_engineering/node_modules/ssh2/lib/protocol/zlib.js new file mode 100644 index 0000000..f68319a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/lib/protocol/zlib.js @@ -0,0 +1,255 @@ +'use strict'; + +const { kMaxLength } = require('buffer'); +const { + createInflate, + constants: { + DEFLATE, + INFLATE, + Z_DEFAULT_CHUNK, + Z_DEFAULT_COMPRESSION, + Z_DEFAULT_MEMLEVEL, + Z_DEFAULT_STRATEGY, + Z_DEFAULT_WINDOWBITS, + Z_PARTIAL_FLUSH, + } +} = require('zlib'); +const ZlibHandle = createInflate()._handle.constructor; + +function processCallback() { + throw new Error('Should not get here'); +} + +function zlibOnError(message, errno, code) { + const self = this._owner; + // There is no way to cleanly recover. + // Continuing only obscures problems. + + const error = new Error(message); + error.errno = errno; + error.code = code; + self._err = error; +} + +function _close(engine) { + // Caller may invoke .close after a zlib error (which will null _handle). + if (!engine._handle) + return; + + engine._handle.close(); + engine._handle = null; +} + +class Zlib { + constructor(mode) { + const windowBits = Z_DEFAULT_WINDOWBITS; + const level = Z_DEFAULT_COMPRESSION; + const memLevel = Z_DEFAULT_MEMLEVEL; + const strategy = Z_DEFAULT_STRATEGY; + const dictionary = undefined; + + this._err = undefined; + this._writeState = new Uint32Array(2); + this._chunkSize = Z_DEFAULT_CHUNK; + this._maxOutputLength = kMaxLength; + this._outBuffer = Buffer.allocUnsafe(this._chunkSize); + this._outOffset = 0; + + this._handle = new ZlibHandle(mode); + this._handle._owner = this; + this._handle.onerror = zlibOnError; + this._handle.init(windowBits, + level, + memLevel, + strategy, + this._writeState, + processCallback, + dictionary); + } + + writeSync(chunk, retChunks) { + const handle = this._handle; + if (!handle) + throw new Error('Invalid Zlib instance'); + + let availInBefore = chunk.length; + let availOutBefore = this._chunkSize - this._outOffset; + let inOff = 0; + let availOutAfter; + let availInAfter; + + let buffers; + let nread = 0; + const state = this._writeState; + let buffer = this._outBuffer; + let offset = this._outOffset; + const chunkSize = this._chunkSize; + + while (true) { + handle.writeSync(Z_PARTIAL_FLUSH, + chunk, // in + inOff, // in_off + availInBefore, // in_len + buffer, // out + offset, // out_off + availOutBefore); // out_len + if (this._err) + throw this._err; + + availOutAfter = state[0]; + availInAfter = state[1]; + + const inDelta = availInBefore - availInAfter; + const have = availOutBefore - availOutAfter; + + if (have > 0) { + const out = (offset === 0 && have === buffer.length + ? buffer + : buffer.slice(offset, offset + have)); + offset += have; + if (!buffers) + buffers = out; + else if (buffers.push === undefined) + buffers = [buffers, out]; + else + buffers.push(out); + nread += out.byteLength; + + if (nread > this._maxOutputLength) { + _close(this); + throw new Error( + `Output length exceeded maximum of ${this._maxOutputLength}` + ); + } + } else if (have !== 0) { + throw new Error('have should not go down'); + } + + // Exhausted the output buffer, or used all the input create a new one. + if (availOutAfter === 0 || offset >= chunkSize) { + availOutBefore = chunkSize; + offset = 0; + buffer = Buffer.allocUnsafe(chunkSize); + } + + if (availOutAfter === 0) { + // Not actually done. Need to reprocess. + // Also, update the availInBefore to the availInAfter value, + // so that if we have to hit it a third (fourth, etc.) time, + // it'll have the correct byte counts. + inOff += inDelta; + availInBefore = availInAfter; + } else { + break; + } + } + + this._outBuffer = buffer; + this._outOffset = offset; + + if (nread === 0) + buffers = Buffer.alloc(0); + + if (retChunks) { + buffers.totalLen = nread; + return buffers; + } + + if (buffers.push === undefined) + return buffers; + + const output = Buffer.allocUnsafe(nread); + for (let i = 0, p = 0; i < buffers.length; ++i) { + const buf = buffers[i]; + output.set(buf, p); + p += buf.length; + } + return output; + } +} + +class ZlibPacketWriter { + constructor(protocol) { + this.allocStart = 0; + this.allocStartKEX = 0; + this._protocol = protocol; + this._zlib = new Zlib(DEFLATE); + } + + cleanup() { + if (this._zlib) + _close(this._zlib); + } + + alloc(payloadSize, force) { + return Buffer.allocUnsafe(payloadSize); + } + + finalize(payload, force) { + if (this._protocol._kexinit === undefined || force) { + const output = this._zlib.writeSync(payload, true); + const packet = this._protocol._cipher.allocPacket(output.totalLen); + if (output.push === undefined) { + packet.set(output, 5); + } else { + for (let i = 0, p = 5; i < output.length; ++i) { + const chunk = output[i]; + packet.set(chunk, p); + p += chunk.length; + } + } + return packet; + } + return payload; + } +} + +class PacketWriter { + constructor(protocol) { + this.allocStart = 5; + this.allocStartKEX = 5; + this._protocol = protocol; + } + + cleanup() {} + + alloc(payloadSize, force) { + if (this._protocol._kexinit === undefined || force) + return this._protocol._cipher.allocPacket(payloadSize); + return Buffer.allocUnsafe(payloadSize); + } + + finalize(packet, force) { + return packet; + } +} + +class ZlibPacketReader { + constructor() { + this._zlib = new Zlib(INFLATE); + } + + cleanup() { + if (this._zlib) + _close(this._zlib); + } + + read(data) { + return this._zlib.writeSync(data, false); + } +} + +class PacketReader { + cleanup() {} + + read(data) { + return data; + } +} + +module.exports = { + PacketReader, + PacketWriter, + ZlibPacketReader, + ZlibPacketWriter, +}; diff --git a/reverse_engineering/node_modules/ssh2/lib/server.js b/reverse_engineering/node_modules/ssh2/lib/server.js index 6d359d0..11c15a1 100644 --- a/reverse_engineering/node_modules/ssh2/lib/server.js +++ b/reverse_engineering/node_modules/ssh2/lib/server.js @@ -1,1156 +1,1363 @@ -var net = require('net'); -var EventEmitter = require('events').EventEmitter; -var listenerCount = EventEmitter.listenerCount; -var inherits = require('util').inherits; - -var ssh2_streams = require('ssh2-streams'); -var parseKey = ssh2_streams.utils.parseKey; -var genPublicKey = ssh2_streams.utils.genPublicKey; -var decryptKey = ssh2_streams.utils.decryptKey; -var SSH2Stream = ssh2_streams.SSH2Stream; -var SFTPStream = ssh2_streams.SFTPStream; -var consts = ssh2_streams.constants; -var DISCONNECT_REASON = consts.DISCONNECT_REASON; -var CHANNEL_OPEN_FAILURE = consts.CHANNEL_OPEN_FAILURE; -var ALGORITHMS = consts.ALGORITHMS; - -var Channel = require('./Channel'); -var KeepaliveManager = require('./keepalivemgr'); - -var MAX_CHANNEL = Math.pow(2, 32) - 1; -var MAX_PENDING_AUTHS = 10; - -var kaMgr; - -function Server(cfg, listener) { - if (!(this instanceof Server)) - return new Server(cfg, listener); - - var hostKeys = { - 'ssh-rsa': null, - 'ssh-dss': null, - 'ecdsa-sha2-nistp256': null, - 'ecdsa-sha2-nistp384': null, - 'ecdsa-sha2-nistp521': null - }; - - var hostKeys_ = cfg.hostKeys; - if (!Array.isArray(hostKeys_)) - throw new Error('hostKeys must be an array'); - - var i; - for (i = 0; i < hostKeys_.length; ++i) { - var privateKey; - if (Buffer.isBuffer(hostKeys_[i]) || typeof hostKeys_[i] === 'string') - privateKey = parseKey(hostKeys_[i]); - else - privateKey = parseKey(hostKeys_[i].key); - if (privateKey instanceof Error) - throw new Error('Cannot parse privateKey: ' + privateKey.message); - if (!privateKey.private) - throw new Error('privateKey value contains an invalid private key'); - if (hostKeys[privateKey.fulltype]) - continue; - if (privateKey.encryption) { - if (typeof hostKeys_[i].passphrase !== 'string') - throw new Error('Missing passphrase for encrypted private key'); - decryptKey(privateKey, hostKeys_[i].passphrase); - } - hostKeys[privateKey.fulltype] = { - privateKey: privateKey, - publicKey: genPublicKey(privateKey) +// TODO: +// * convert listenerCount() usage to emit() return value checking? +// * emit error when connection severed early (e.g. before handshake) +// * add '.connected' or similar property to connection objects to allow +// immediate connection status checking +'use strict'; + +const { Server: netServer } = require('net'); +const EventEmitter = require('events'); +const { listenerCount } = EventEmitter; + +const { + CHANNEL_OPEN_FAILURE, + DEFAULT_CIPHER, + DEFAULT_COMPRESSION, + DEFAULT_KEX, + DEFAULT_MAC, + DEFAULT_SERVER_HOST_KEY, + DISCONNECT_REASON, + DISCONNECT_REASON_BY_VALUE, + SUPPORTED_CIPHER, + SUPPORTED_COMPRESSION, + SUPPORTED_KEX, + SUPPORTED_MAC, + SUPPORTED_SERVER_HOST_KEY, +} = require('./protocol/constants.js'); +const { init: cryptoInit } = require('./protocol/crypto.js'); +const { KexInit } = require('./protocol/kex.js'); +const { parseKey } = require('./protocol/keyParser.js'); +const Protocol = require('./protocol/Protocol.js'); +const { SFTP } = require('./protocol/SFTP.js'); +const { writeUInt32BE } = require('./protocol/utils.js'); + +const { + Channel, + MAX_WINDOW, + PACKET_SIZE, + windowAdjust, + WINDOW_THRESHOLD, +} = require('./Channel.js'); + +const { + ChannelManager, + generateAlgorithmList, + isWritable, + onChannelOpenFailure, + onCHANNEL_CLOSE, +} = require('./utils.js'); + +const MAX_PENDING_AUTHS = 10; + +class AuthContext extends EventEmitter { + constructor(protocol, username, service, method, cb) { + super(); + + this.username = this.user = username; + this.service = service; + this.method = method; + this._initialResponse = false; + this._finalResponse = false; + this._multistep = false; + this._cbfinal = (allowed, methodsLeft, isPartial) => { + if (!this._finalResponse) { + this._finalResponse = true; + cb(this, allowed, methodsLeft, isPartial); + } }; + this._protocol = protocol; } - var algorithms = { - kex: undefined, - kexBuf: undefined, - cipher: undefined, - cipherBuf: undefined, - serverHostKey: undefined, - serverHostKeyBuf: undefined, - hmac: undefined, - hmacBuf: undefined, - compress: undefined, - compressBuf: undefined - }; - if (typeof cfg.algorithms === 'object' && cfg.algorithms !== null) { - var algosSupported; - var algoList; - - algoList = cfg.algorithms.kex; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_KEX; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported key exchange algorithm: ' + algoList[i]); - } - algorithms.kex = algoList; - } + accept() { + this._cleanup && this._cleanup(); + this._initialResponse = true; + this._cbfinal(true); + } + reject(methodsLeft, isPartial) { + this._cleanup && this._cleanup(); + this._initialResponse = true; + this._cbfinal(false, methodsLeft, isPartial); + } +} - algoList = cfg.algorithms.cipher; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_CIPHER; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported cipher algorithm: ' + algoList[i]); - } - algorithms.cipher = algoList; - } - algoList = cfg.algorithms.serverHostKey; - var copied = false; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_SERVER_HOST_KEY; - for (i = algoList.length - 1; i >= 0; --i) { - if (algosSupported.indexOf(algoList[i]) === -1) { - throw new Error('Unsupported server host key algorithm: ' - + algoList[i]); - } - if (!hostKeys[algoList[i]]) { - // Silently discard for now - if (!copied) { - algoList = algoList.slice(); - copied = true; - } - algoList.splice(i, 1); - } - } - if (algoList.length > 0) - algorithms.serverHostKey = algoList; - } +class KeyboardAuthContext extends AuthContext { + constructor(protocol, username, service, method, submethods, cb) { + super(protocol, username, service, method, cb); - algoList = cfg.algorithms.hmac; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_HMAC; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported HMAC algorithm: ' + algoList[i]); + this._multistep = true; + + this._cb = undefined; + this._onInfoResponse = (responses) => { + const callback = this._cb; + if (callback) { + this._cb = undefined; + callback(responses); } - algorithms.hmac = algoList; + }; + this.submethods = submethods; + this.on('abort', () => { + this._cb && this._cb(new Error('Authentication request aborted')); + }); + } + + prompt(prompts, title, instructions, cb) { + if (!Array.isArray(prompts)) + prompts = [ prompts ]; + + if (typeof title === 'function') { + cb = title; + title = instructions = undefined; + } else if (typeof instructions === 'function') { + cb = instructions; + instructions = undefined; + } else if (typeof cb !== 'function') { + cb = undefined; } - algoList = cfg.algorithms.compress; - if (Array.isArray(algoList) && algoList.length > 0) { - algosSupported = ALGORITHMS.SUPPORTED_COMPRESS; - for (i = 0; i < algoList.length; ++i) { - if (algosSupported.indexOf(algoList[i]) === -1) - throw new Error('Unsupported compression algorithm: ' + algoList[i]); + for (let i = 0; i < prompts.length; ++i) { + if (typeof prompts[i] === 'string') { + prompts[i] = { + prompt: prompts[i], + echo: true + }; } - algorithms.compress = algoList; } + + this._cb = cb; + this._initialResponse = true; + + this._protocol.authInfoReq(title, instructions, prompts); } +} - // Make sure we at least have some kind of valid list of support key - // formats - if (algorithms.serverHostKey === undefined) { - var hostKeyAlgos = Object.keys(hostKeys); - for (i = hostKeyAlgos.length - 1; i >= 0; --i) { - if (!hostKeys[hostKeyAlgos[i]]) - hostKeyAlgos.splice(i, 1); - } - algorithms.serverHostKey = hostKeyAlgos; +class PKAuthContext extends AuthContext { + constructor(protocol, username, service, method, pkInfo, cb) { + super(protocol, username, service, method, cb); + + this.key = { algo: pkInfo.keyAlgo, data: pkInfo.key }; + this.signature = pkInfo.signature; + this.blob = pkInfo.blob; } - if (!kaMgr - && Server.KEEPALIVE_INTERVAL > 0 - && Server.KEEPALIVE_CLIENT_INTERVAL > 0 - && Server.KEEPALIVE_CLIENT_COUNT_MAX >= 0) { - kaMgr = new KeepaliveManager(Server.KEEPALIVE_INTERVAL, - Server.KEEPALIVE_CLIENT_INTERVAL, - Server.KEEPALIVE_CLIENT_COUNT_MAX); + accept() { + if (!this.signature) { + this._initialResponse = true; + this._protocol.authPKOK(this.key.algo, this.key.data); + } else { + AuthContext.prototype.accept.call(this); + } } +} - var self = this; +class HostbasedAuthContext extends AuthContext { + constructor(protocol, username, service, method, pkInfo, cb) { + super(protocol, username, service, method, cb); - EventEmitter.call(this); + this.key = { algo: pkInfo.keyAlgo, data: pkInfo.key }; + this.signature = pkInfo.signature; + this.blob = pkInfo.blob; + this.localHostname = pkInfo.localHostname; + this.localUsername = pkInfo.localUsername; + } +} - if (typeof listener === 'function') - self.on('connection', listener); +class PwdAuthContext extends AuthContext { + constructor(protocol, username, service, method, password, cb) { + super(protocol, username, service, method, cb); - var streamcfg = { - algorithms: algorithms, - hostKeys: hostKeys, - server: true - }; - var keys; - var len; - for (i = 0, keys = Object.keys(cfg), len = keys.length; i < len; ++i) { - var key = keys[i]; - if (key === 'privateKey' - || key === 'publicKey' - || key === 'passphrase' - || key === 'algorithms' - || key === 'hostKeys' - || key === 'server') { - continue; - } - streamcfg[key] = cfg[key]; + this.password = password; + this._changeCb = undefined; } - if (typeof streamcfg.debug === 'function') { - var oldDebug = streamcfg.debug; - var cfgKeys = Object.keys(streamcfg); + requestChange(prompt, cb) { + if (this._changeCb) + throw new Error('Change request already in progress'); + if (typeof prompt !== 'string') + throw new Error('prompt argument must be a string'); + if (typeof cb !== 'function') + throw new Error('Callback argument must be a function'); + this._changeCb = cb; + this._protocol.authPasswdChg(prompt); } +} - this._srv = new net.Server(function(socket) { - if (self._connections >= self.maxConnections) { - socket.destroy(); - return; - } - ++self._connections; - socket.once('close', function(had_err) { - --self._connections; - - // since joyent/node#993bb93e0a, we have to "read past EOF" in order to - // get an `end` event on streams. thankfully adding this does not - // negatively affect node versions pre-joyent/node#993bb93e0a. - sshstream.read(); - }).on('error', function(err) { - sshstream.reset(); - sshstream.emit('error', err); - }); - var conncfg = streamcfg; +class Session extends EventEmitter { + constructor(client, info, localChan) { + super(); - // prepend debug output with a unique identifier in case there are multiple - // clients connected at the same time - if (oldDebug) { - conncfg = {}; - for (var i = 0, key; i < cfgKeys.length; ++i) { - key = cfgKeys[i]; - conncfg[key] = streamcfg[key]; + this.type = 'session'; + this.subtype = undefined; + this._ending = false; + this._channel = undefined; + this._chanInfo = { + type: 'session', + incoming: { + id: localChan, + window: MAX_WINDOW, + packetSize: PACKET_SIZE, + state: 'open' + }, + outgoing: { + id: info.sender, + window: info.window, + packetSize: info.packetSize, + state: 'open' } - var debugPrefix = '[' + process.hrtime().join('.') + '] '; - conncfg.debug = function(msg) { - oldDebug(debugPrefix + msg); - }; - } - - var sshstream = new SSH2Stream(conncfg); - var client = new Client(sshstream, socket); - - socket.pipe(sshstream).pipe(socket); + }; + } +} - // silence pre-header errors - function onClientPreHeaderError(err) {} - client.on('error', onClientPreHeaderError); - sshstream.once('header', function(header) { - if (sshstream._readableState.ended) { - // already disconnected internally in SSH2Stream due to incompatible - // protocol version - return; - } else if (!listenerCount(self, 'connection')) { - // auto reject - return sshstream.disconnect(DISCONNECT_REASON.BY_APPLICATION); +class Server extends EventEmitter { + constructor(cfg, listener) { + super(); + + if (typeof cfg !== 'object' || cfg === null) + throw new Error('Missing configuration object'); + + const hostKeys = Object.create(null); + const hostKeyAlgoOrder = []; + + const hostKeys_ = cfg.hostKeys; + if (!Array.isArray(hostKeys_)) + throw new Error('hostKeys must be an array'); + + const cfgAlgos = ( + typeof cfg.algorithms === 'object' && cfg.algorithms !== null + ? cfg.algorithms + : {} + ); + + const hostKeyAlgos = generateAlgorithmList( + cfgAlgos.serverHostKey, + DEFAULT_SERVER_HOST_KEY, + SUPPORTED_SERVER_HOST_KEY + ); + for (let i = 0; i < hostKeys_.length; ++i) { + let privateKey; + if (Buffer.isBuffer(hostKeys_[i]) || typeof hostKeys_[i] === 'string') + privateKey = parseKey(hostKeys_[i]); + else + privateKey = parseKey(hostKeys_[i].key, hostKeys_[i].passphrase); + + if (privateKey instanceof Error) + throw new Error(`Cannot parse privateKey: ${privateKey.message}`); + + if (Array.isArray(privateKey)) { + // OpenSSH's newer format only stores 1 key for now + privateKey = privateKey[0]; } - client.removeListener('error', onClientPreHeaderError); + if (privateKey.getPrivatePEM() === null) + throw new Error('privateKey value contains an invalid private key'); + + // Discard key if we already found a key of the same type + if (hostKeyAlgoOrder.includes(privateKey.type)) + continue; + + if (privateKey.type === 'ssh-rsa') { + // SSH supports multiple signature hashing algorithms for RSA, so we add + // the algorithms in the desired order + let sha1Pos = hostKeyAlgos.indexOf('ssh-rsa'); + const sha256Pos = hostKeyAlgos.indexOf('rsa-sha2-256'); + const sha512Pos = hostKeyAlgos.indexOf('rsa-sha2-512'); + if (sha1Pos === -1) { + // Fall back to giving SHA1 the lowest priority + sha1Pos = Infinity; + } + [sha1Pos, sha256Pos, sha512Pos].sort(compareNumbers).forEach((pos) => { + if (pos === -1) + return; - self.emit('connection', - client, - { ip: socket.remoteAddress, header: header }); - }); - }).on('error', function(err) { - self.emit('error', err); - }).on('listening', function() { - self.emit('listening'); - }).on('close', function() { - self.emit('close'); - }); - this._connections = 0; - this.maxConnections = Infinity; -} -inherits(Server, EventEmitter); - -Server.prototype.listen = function() { - this._srv.listen.apply(this._srv, arguments); - return this; -}; - -Server.prototype.address = function() { - return this._srv.address(); -}; - -Server.prototype.getConnections = function(cb) { - this._srv.getConnections(cb); -}; - -Server.prototype.close = function(cb) { - this._srv.close(cb); - return this; -}; - -Server.prototype.ref = function() { - this._srv.ref(); -}; - -Server.prototype.unref = function() { - this._srv.unref(); -}; - - -function Client(stream, socket) { - EventEmitter.call(this); - - var self = this; - - this._sshstream = stream; - var channels = this._channels = {}; - this._curChan = -1; - this._sock = socket; - this.noMoreSessions = false; - this.authenticated = false; - - stream.on('end', function() { - self.emit('end'); - }).on('close', function(hasErr) { - self.emit('close', hasErr); - }).on('error', function(err) { - self.emit('error', err); - }).on('drain', function() { - self.emit('drain'); - }).on('continue', function() { - self.emit('continue'); - }); - - var exchanges = 0; - var acceptedAuthSvc = false; - var pendingAuths = []; - var authCtx; - - // begin service/auth-related ================================================ - stream.on('SERVICE_REQUEST', function(service) { - if (exchanges === 0 - || acceptedAuthSvc - || self.authenticated - || service !== 'ssh-userauth') - return stream.disconnect(DISCONNECT_REASON.SERVICE_NOT_AVAILABLE); - - acceptedAuthSvc = true; - stream.serviceAccept(service); - }).on('USERAUTH_REQUEST', onUSERAUTH_REQUEST); - function onUSERAUTH_REQUEST(username, service, method, methodData) { - if (exchanges === 0 - || (authCtx - && (authCtx.username !== username || authCtx.service !== service)) - // TODO: support hostbased auth - || (method !== 'password' - && method !== 'publickey' - && method !== 'hostbased' - && method !== 'keyboard-interactive' - && method !== 'none') - || pendingAuths.length === MAX_PENDING_AUTHS) - return stream.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); - else if (service !== 'ssh-connection') - return stream.disconnect(DISCONNECT_REASON.SERVICE_NOT_AVAILABLE); - - // XXX: this really shouldn't be reaching into private state ... - stream._state.authMethod = method; - - var ctx; - if (method === 'keyboard-interactive') { - ctx = new KeyboardAuthContext(stream, username, service, method, - methodData, onAuthDecide); - } else if (method === 'publickey') { - ctx = new PKAuthContext(stream, username, service, method, methodData, - onAuthDecide); - } else if (method === 'hostbased') { - ctx = new HostbasedAuthContext(stream, username, service, method, - methodData, onAuthDecide); - } else if (method === 'password') { - ctx = new PwdAuthContext(stream, username, service, method, methodData, - onAuthDecide); - } else if (method === 'none') - ctx = new AuthContext(stream, username, service, method, onAuthDecide); - - if (authCtx) { - if (!authCtx._initialResponse) - return pendingAuths.push(ctx); - else if (authCtx._multistep && !this._finalResponse) { - // RFC 4252 says to silently abort the current auth request if a new - // auth request comes in before the final response from an auth method - // that requires additional request/response exchanges -- this means - // keyboard-interactive for now ... - authCtx._cleanup && authCtx._cleanup(); - authCtx.emit('abort'); - } - } + let type; + switch (pos) { + case sha1Pos: type = 'ssh-rsa'; break; + case sha256Pos: type = 'rsa-sha2-256'; break; + case sha512Pos: type = 'rsa-sha2-512'; break; + default: return; + } - authCtx = ctx; + // Store same RSA key under each hash algorithm name for convenience + hostKeys[type] = privateKey; - if (listenerCount(self, 'authentication')) - self.emit('authentication', authCtx); - else - authCtx.reject(); - } - function onAuthDecide(ctx, allowed, methodsLeft, isPartial) { - if (authCtx === ctx && !self.authenticated) { - if (allowed) { - stream.removeListener('USERAUTH_REQUEST', onUSERAUTH_REQUEST); - authCtx = undefined; - self.authenticated = true; - stream.authSuccess(); - pendingAuths = []; - self.emit('ready'); + hostKeyAlgoOrder.push(type); + }); } else { - stream.authFailure(methodsLeft, isPartial); - if (pendingAuths.length) { - authCtx = pendingAuths.pop(); - if (listenerCount(self, 'authentication')) - self.emit('authentication', authCtx); - else - authCtx.reject(); - } + hostKeys[privateKey.type] = privateKey; + hostKeyAlgoOrder.push(privateKey.type); } } - } - // end service/auth-related ================================================== - - var unsentGlobalRequestsReplies = []; - - function sendReplies() { - var reply; - while (unsentGlobalRequestsReplies.length > 0 - && unsentGlobalRequestsReplies[0].type) { - reply = unsentGlobalRequestsReplies.shift(); - if (reply.type === 'SUCCESS') - stream.requestSuccess(reply.buf); - if (reply.type === 'FAILURE') - stream.requestFailure(); - } - } - stream.on('GLOBAL_REQUEST', function(name, wantReply, data) { - var reply = { - type: null, - buf: null + const algorithms = { + kex: generateAlgorithmList(cfgAlgos.kex, DEFAULT_KEX, SUPPORTED_KEX), + serverHostKey: hostKeyAlgoOrder, + cs: { + cipher: generateAlgorithmList( + cfgAlgos.cipher, + DEFAULT_CIPHER, + SUPPORTED_CIPHER + ), + mac: generateAlgorithmList(cfgAlgos.hmac, DEFAULT_MAC, SUPPORTED_MAC), + compress: generateAlgorithmList( + cfgAlgos.compress, + DEFAULT_COMPRESSION, + SUPPORTED_COMPRESSION + ), + lang: [], + }, + sc: undefined, }; + algorithms.sc = algorithms.cs; - function setReply(type, buf) { - reply.type = type; - reply.buf = buf; - sendReplies(); - } + if (typeof listener === 'function') + this.on('connection', listener); - if (wantReply) - unsentGlobalRequestsReplies.push(reply); - - if ((name === 'tcpip-forward' - || name === 'cancel-tcpip-forward' - || name === 'no-more-sessions@openssh.com' - || name === 'streamlocal-forward@openssh.com' - || name === 'cancel-streamlocal-forward@openssh.com') - && listenerCount(self, 'request') - && self.authenticated) { - var accept; - var reject; - - if (wantReply) { - var replied = false; - accept = function(chosenPort) { - if (replied) - return; - replied = true; - var bufPort; - if (name === 'tcpip-forward' - && data.bindPort === 0 - && typeof chosenPort === 'number') { - bufPort = new Buffer(4); - bufPort.writeUInt32BE(chosenPort, 0, true); - } - setReply('SUCCESS', bufPort); - }; - reject = function() { - if (replied) - return; - replied = true; - setReply('FAILURE'); - }; - } + const origDebug = (typeof cfg.debug === 'function' ? cfg.debug : undefined); + const ident = (cfg.ident ? Buffer.from(cfg.ident) : undefined); + const offer = new KexInit(algorithms); - if (name === 'no-more-sessions@openssh.com') { - self.noMoreSessions = true; - accept && accept(); + this._srv = new netServer((socket) => { + if (this._connections >= this.maxConnections) { + socket.destroy(); return; } + ++this._connections; + socket.once('close', () => { + --this._connections; + }); - self.emit('request', accept, reject, name, data); - } else if (wantReply) - setReply('FAILURE'); - }); - - stream.on('CHANNEL_OPEN', function(info) { - // do early reject in some cases to prevent wasteful channel allocation - if ((info.type === 'session' && self.noMoreSessions) - || !self.authenticated) { - var reasonCode = CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED; - return stream.channelOpenFail(info.sender, reasonCode); - } + let debug; + if (origDebug) { + // Prepend debug output with a unique identifier in case there are + // multiple clients connected at the same time + const debugPrefix = `[${process.hrtime().join('.')}] `; + debug = (msg) => { + origDebug(`${debugPrefix}${msg}`); + }; + } - var localChan = nextChannel(self); - var accept; - var reject; - var replied = false; - if (localChan === false) { - // auto-reject due to no channels available - return stream.channelOpenFail(info.sender, - CHANNEL_OPEN_FAILURE.RESOURCE_SHORTAGE); - } + // eslint-disable-next-line no-use-before-define + new Client(socket, hostKeys, ident, offer, debug, this, cfg); + }).on('error', (err) => { + this.emit('error', err); + }).on('listening', () => { + this.emit('listening'); + }).on('close', () => { + this.emit('close'); + }); + this._connections = 0; + this.maxConnections = Infinity; + } - // be optimistic, reserve channel to prevent another request from trying to - // take the same channel - channels[localChan] = true; + injectSocket(socket) { + this._srv.emit('connection', socket); + } - reject = function() { - if (replied) - return; + listen(...args) { + this._srv.listen(...args); + return this; + } - replied = true; + address() { + return this._srv.address(); + } - delete channels[localChan]; + getConnections(cb) { + this._srv.getConnections(cb); + return this; + } - var reasonCode = CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED; - return stream.channelOpenFail(info.sender, reasonCode); - }; + close(cb) { + this._srv.close(cb); + return this; + } - switch (info.type) { - case 'session': - if (listenerCount(self, 'session')) { - accept = function() { - if (replied) - return; + ref() { + this._srv.ref(); + return this; + } - replied = true; + unref() { + this._srv.unref(); + return this; + } +} +Server.KEEPALIVE_CLIENT_INTERVAL = 15000; +Server.KEEPALIVE_CLIENT_COUNT_MAX = 3; - stream.channelOpenConfirm(info.sender, - localChan, - Channel.MAX_WINDOW, - Channel.PACKET_SIZE); - return new Session(self, info, localChan); - }; +class Client extends EventEmitter { + constructor(socket, hostKeys, ident, offer, debug, server, srvCfg) { + super(); + + let exchanges = 0; + let acceptedAuthSvc = false; + let pendingAuths = []; + let authCtx; + let kaTimer; + let onPacket; + const unsentGlobalRequestsReplies = []; + this._sock = socket; + this._chanMgr = new ChannelManager(this); + this._debug = debug; + this.noMoreSessions = false; + this.authenticated = false; + + // Silence pre-header errors + function onClientPreHeaderError(err) {} + this.on('error', onClientPreHeaderError); - self.emit('session', accept, reject); - } else - reject(); - break; - case 'direct-tcpip': - if (listenerCount(self, 'tcpip')) { - accept = function() { - if (replied) - return; + const DEBUG_HANDLER = (!debug ? undefined : (p, display, msg) => { + debug(`Debug output from client: ${JSON.stringify(msg)}`); + }); - replied = true; + const kaIntvl = ( + typeof srvCfg.keepaliveInterval === 'number' + && isFinite(srvCfg.keepaliveInterval) + && srvCfg.keepaliveInterval > 0 + ? srvCfg.keepaliveInterval + : ( + typeof Server.KEEPALIVE_CLIENT_INTERVAL === 'number' + && isFinite(Server.KEEPALIVE_CLIENT_INTERVAL) + && Server.KEEPALIVE_CLIENT_INTERVAL > 0 + ? Server.KEEPALIVE_CLIENT_INTERVAL + : -1 + ) + ); + const kaCountMax = ( + typeof srvCfg.keepaliveCountMax === 'number' + && isFinite(srvCfg.keepaliveCountMax) + && srvCfg.keepaliveCountMax >= 0 + ? srvCfg.keepaliveCountMax + : ( + typeof Server.KEEPALIVE_CLIENT_COUNT_MAX === 'number' + && isFinite(Server.KEEPALIVE_CLIENT_COUNT_MAX) + && Server.KEEPALIVE_CLIENT_COUNT_MAX >= 0 + ? Server.KEEPALIVE_CLIENT_COUNT_MAX + : -1 + ) + ); + let kaCurCount = 0; + if (kaIntvl !== -1 && kaCountMax !== -1) { + this.once('ready', () => { + const onClose = () => { + clearInterval(kaTimer); + }; + this.on('close', onClose).on('end', onClose); + kaTimer = setInterval(() => { + if (++kaCurCount > kaCountMax) { + clearInterval(kaTimer); + const err = new Error('Keepalive timeout'); + err.level = 'client-timeout'; + this.emit('error', err); + this.end(); + } else { + // XXX: if the server ever starts sending real global requests to + // the client, we will need to add a dummy callback here to + // keep the correct reply order + proto.ping(); + } + }, kaIntvl); + }); + // TODO: re-verify keepalive behavior with OpenSSH + onPacket = () => { + kaTimer && kaTimer.refresh(); + kaCurCount = 0; + }; + } - stream.channelOpenConfirm(info.sender, - localChan, - Channel.MAX_WINDOW, - Channel.PACKET_SIZE); - - var chaninfo = { - type: undefined, - incoming: { - id: localChan, - window: Channel.MAX_WINDOW, - packetSize: Channel.PACKET_SIZE, - state: 'open' - }, - outgoing: { - id: info.sender, - window: info.window, - packetSize: info.packetSize, - state: 'open' - } - }; + const proto = this._protocol = new Protocol({ + server: true, + hostKeys, + ident, + offer, + onPacket, + greeting: srvCfg.greeting, + banner: srvCfg.banner, + onWrite: (data) => { + if (isWritable(socket)) + socket.write(data); + }, + onError: (err) => { + if (!proto._destruct) + socket.removeAllListeners('data'); + this.emit('error', err); + try { + socket.end(); + } catch {} + }, + onHeader: (header) => { + this.removeListener('error', onClientPreHeaderError); + + const info = { + ip: socket.remoteAddress, + family: socket.remoteFamily, + port: socket.remotePort, + header, + }; + if (!server.emit('connection', this, info)) { + // auto reject + proto.disconnect(DISCONNECT_REASON.BY_APPLICATION); + socket.end(); + return; + } - return new Channel(chaninfo, self); - }; + if (header.greeting) + this.emit('greeting', header.greeting); + }, + onHandshakeComplete: (negotiated) => { + if (++exchanges > 1) + this.emit('rekey'); + this.emit('handshake', negotiated); + }, + debug, + messageHandlers: { + DEBUG: DEBUG_HANDLER, + DISCONNECT: (p, reason, desc) => { + if (reason !== DISCONNECT_REASON.BY_APPLICATION) { + if (!desc) { + desc = DISCONNECT_REASON_BY_VALUE[reason]; + if (desc === undefined) + desc = `Unexpected disconnection reason: ${reason}`; + } + const err = new Error(desc); + err.code = reason; + this.emit('error', err); + } + socket.end(); + }, + CHANNEL_OPEN: (p, info) => { + // Handle incoming requests from client + + // Do early reject in some cases to prevent wasteful channel + // allocation + if ((info.type === 'session' && this.noMoreSessions) + || !this.authenticated) { + const reasonCode = CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED; + return proto.channelOpenFail(info.sender, reasonCode); + } - self.emit('tcpip', accept, reject, info.data); - } else - reject(); - break; - case 'direct-streamlocal@openssh.com': - if (listenerCount(self, 'openssh.streamlocal')) { - accept = function() { + let localChan = -1; + let reason; + let replied = false; + + let accept; + const reject = () => { if (replied) return; - replied = true; - stream.channelOpenConfirm(info.sender, - localChan, - Channel.MAX_WINDOW, - Channel.PACKET_SIZE); - - var chaninfo = { - type: undefined, - incoming: { - id: localChan, - window: Channel.MAX_WINDOW, - packetSize: Channel.PACKET_SIZE, - state: 'open' - }, - outgoing: { - id: info.sender, - window: info.window, - packetSize: info.packetSize, - state: 'open' + if (reason === undefined) { + if (localChan === -1) + reason = CHANNEL_OPEN_FAILURE.RESOURCE_SHORTAGE; + else + reason = CHANNEL_OPEN_FAILURE.CONNECT_FAILED; + } + + proto.channelOpenFail(info.sender, reason, ''); + }; + const reserveChannel = () => { + localChan = this._chanMgr.add(); + + if (localChan === -1) { + reason = CHANNEL_OPEN_FAILURE.RESOURCE_SHORTAGE; + if (debug) { + debug('Automatic rejection of incoming channel open: ' + + 'no channels available'); } - }; + } - return new Channel(chaninfo, self); + return (localChan !== -1); }; - self.emit('openssh.streamlocal', accept, reject, info.data); - } else - reject(); - break; - default: - // auto-reject unsupported channel types - reject(); - } - }); + const data = info.data; + switch (info.type) { + case 'session': + if (listenerCount(this, 'session') && reserveChannel()) { + accept = () => { + if (replied) + return; + replied = true; - stream.on('NEWKEYS', function() { - if (++exchanges > 1) - self.emit('rekey'); - }); + const instance = new Session(this, info, localChan); + this._chanMgr.update(localChan, instance); - if (kaMgr) { - this.once('ready', function() { - kaMgr.add(stream); - }); - } -} -inherits(Client, EventEmitter); + proto.channelOpenConfirm(info.sender, + localChan, + MAX_WINDOW, + PACKET_SIZE); -Client.prototype.end = function() { - return this._sshstream.disconnect(DISCONNECT_REASON.BY_APPLICATION); -}; + return instance; + }; -Client.prototype.x11 = function(originAddr, originPort, cb) { - var opts = { - originAddr: originAddr, - originPort: originPort - }; - return openChannel(this, 'x11', opts, cb); -}; - -Client.prototype.forwardOut = function(boundAddr, boundPort, remoteAddr, - remotePort, cb) { - var opts = { - boundAddr: boundAddr, - boundPort: boundPort, - remoteAddr: remoteAddr, - remotePort: remotePort - }; - return openChannel(this, 'forwarded-tcpip', opts, cb); -}; + this.emit('session', accept, reject); + return; + } + break; + case 'direct-tcpip': + if (listenerCount(this, 'tcpip') && reserveChannel()) { + accept = () => { + if (replied) + return; + replied = true; + + const chanInfo = { + type: undefined, + incoming: { + id: localChan, + window: MAX_WINDOW, + packetSize: PACKET_SIZE, + state: 'open' + }, + outgoing: { + id: info.sender, + window: info.window, + packetSize: info.packetSize, + state: 'open' + } + }; + + const stream = new Channel(this, chanInfo, { server: true }); + this._chanMgr.update(localChan, stream); + + proto.channelOpenConfirm(info.sender, + localChan, + MAX_WINDOW, + PACKET_SIZE); + + return stream; + }; + + this.emit('tcpip', accept, reject, data); + return; + } + break; + case 'direct-streamlocal@openssh.com': + if (listenerCount(this, 'openssh.streamlocal') + && reserveChannel()) { + accept = () => { + if (replied) + return; + replied = true; + + const chanInfo = { + type: undefined, + incoming: { + id: localChan, + window: MAX_WINDOW, + packetSize: PACKET_SIZE, + state: 'open' + }, + outgoing: { + id: info.sender, + window: info.window, + packetSize: info.packetSize, + state: 'open' + } + }; + + const stream = new Channel(this, chanInfo, { server: true }); + this._chanMgr.update(localChan, stream); + + proto.channelOpenConfirm(info.sender, + localChan, + MAX_WINDOW, + PACKET_SIZE); + + return stream; + }; + + this.emit('openssh.streamlocal', accept, reject, data); + return; + } + break; + default: + // Automatically reject any unsupported channel open requests + reason = CHANNEL_OPEN_FAILURE.UNKNOWN_CHANNEL_TYPE; + if (debug) { + debug('Automatic rejection of unsupported incoming channel open' + + ` type: ${info.type}`); + } + } -Client.prototype.openssh_forwardOutStreamLocal = function(socketPath, cb) { - var opts = { - socketPath: socketPath - }; - return openChannel(this, 'forwarded-streamlocal@openssh.com', opts, cb); -}; - -Client.prototype.rekey = function(cb) { - var stream = this._sshstream; - var ret = true; - var error; - - try { - ret = stream.rekey(); - } catch (ex) { - error = ex; - } + if (reason === undefined) { + reason = CHANNEL_OPEN_FAILURE.ADMINISTRATIVELY_PROHIBITED; + if (debug) { + debug('Automatic rejection of unexpected incoming channel open' + + ` for: ${info.type}`); + } + } - // TODO: re-throw error if no callback? + reject(); + }, + CHANNEL_OPEN_CONFIRMATION: (p, info) => { + const channel = this._chanMgr.get(info.recipient); + if (typeof channel !== 'function') + return; - if (typeof cb === 'function') { - if (error) { - process.nextTick(function() { - cb(error); - }); - } else - this.once('rekey', cb); - } + const chanInfo = { + type: channel.type, + incoming: { + id: info.recipient, + window: MAX_WINDOW, + packetSize: PACKET_SIZE, + state: 'open' + }, + outgoing: { + id: info.sender, + window: info.window, + packetSize: info.packetSize, + state: 'open' + } + }; - return ret; -}; - -function Session(client, info, localChan) { - this.subtype = undefined; - - var ending = false; - var self = this; - var outgoingId = info.sender; - var channel; - - var chaninfo = { - type: 'session', - incoming: { - id: localChan, - window: Channel.MAX_WINDOW, - packetSize: Channel.PACKET_SIZE, - state: 'open' - }, - outgoing: { - id: info.sender, - window: info.window, - packetSize: info.packetSize, - state: 'open' - } - }; + const instance = new Channel(this, chanInfo, { server: true }); + this._chanMgr.update(info.recipient, instance); + channel(undefined, instance); + }, + CHANNEL_OPEN_FAILURE: (p, recipient, reason, description) => { + const channel = this._chanMgr.get(recipient); + if (typeof channel !== 'function') + return; - function onREQUEST(info) { - var replied = false; - var accept; - var reject; - - if (info.wantReply) { - // "real session" requests will have custom accept behaviors - if (info.request !== 'shell' - && info.request !== 'exec' - && info.request !== 'subsystem') { - accept = function() { - if (replied || ending || channel) + const info = { reason, description }; + onChannelOpenFailure(this, recipient, info, channel); + }, + CHANNEL_DATA: (p, recipient, data) => { + let channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) return; - replied = true; + if (channel.constructor === Session) { + channel = channel._channel; + if (!channel) + return; + } - return client._sshstream.channelSuccess(outgoingId); - }; - } + // The remote party should not be sending us data if there is no + // window space available ... + // TODO: raise error on data with not enough window? + if (channel.incoming.window === 0) + return; - reject = function() { - if (replied || ending || channel) - return; + channel.incoming.window -= data.length; - replied = true; + if (channel.push(data) === false) { + channel._waitChanDrain = true; + return; + } - return client._sshstream.channelFailure(outgoingId); - }; - } + if (channel.incoming.window <= WINDOW_THRESHOLD) + windowAdjust(channel); + }, + CHANNEL_EXTENDED_DATA: (p, recipient, data, type) => { + // NOOP -- should not be sent by client + }, + CHANNEL_WINDOW_ADJUST: (p, recipient, amount) => { + let channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; - if (ending) { - reject && reject(); - return; - } + if (channel.constructor === Session) { + channel = channel._channel; + if (!channel) + return; + } - switch (info.request) { - // "pre-real session start" requests - case 'env': - if (listenerCount(self, 'env')) { - self.emit('env', accept, reject, { - key: info.key, - val: info.val - }); - } else - reject && reject(); - break; - case 'pty-req': - if (listenerCount(self, 'pty')) { - self.emit('pty', accept, reject, { - cols: info.cols, - rows: info.rows, - width: info.width, - height: info.height, - term: info.term, - modes: info.modes, - }); - } else - reject && reject(); - break; - case 'window-change': - if (listenerCount(self, 'window-change')) { - self.emit('window-change', accept, reject, { - cols: info.cols, - rows: info.rows, - width: info.width, - height: info.height - }); - } else - reject && reject(); - break; - case 'x11-req': - if (listenerCount(self, 'x11')) { - self.emit('x11', accept, reject, { - single: info.single, - protocol: info.protocol, - cookie: info.cookie, - screen: info.screen - }); - } else - reject && reject(); - break; - // "post-real session start" requests - case 'signal': - if (listenerCount(self, 'signal')) { - self.emit('signal', accept, reject, { - name: info.signal - }); - } else - reject && reject(); - break; - // XXX: is `auth-agent-req@openssh.com` really "post-real session start"? - case 'auth-agent-req@openssh.com': - if (listenerCount(self, 'auth-agent')) - self.emit('auth-agent', accept, reject); - else - reject && reject(); - break; - // "real session start" requests - case 'shell': - if (listenerCount(self, 'shell')) { - accept = function() { - if (replied || ending || channel) + // The other side is allowing us to send `amount` more bytes of data + channel.outgoing.window += amount; + + if (channel._waitWindow) { + channel._waitWindow = false; + + if (channel._chunk) { + channel._write(channel._chunk, null, channel._chunkcb); + } else if (channel._chunkcb) { + channel._chunkcb(); + } else if (channel._chunkErr) { + channel.stderr._write(channel._chunkErr, + null, + channel._chunkcbErr); + } else if (channel._chunkcbErr) { + channel._chunkcbErr(); + } + } + }, + CHANNEL_SUCCESS: (p, recipient) => { + let channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; + + if (channel.constructor === Session) { + channel = channel._channel; + if (!channel) return; + } - replied = true; + if (channel._callbacks.length) + channel._callbacks.shift()(false); + }, + CHANNEL_FAILURE: (p, recipient) => { + let channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; - if (info.wantReply) - client._sshstream.channelSuccess(outgoingId); + if (channel.constructor === Session) { + channel = channel._channel; + if (!channel) + return; + } - channel = new Channel(chaninfo, client, { server: true }); + if (channel._callbacks.length) + channel._callbacks.shift()(true); + }, + CHANNEL_REQUEST: (p, recipient, type, wantReply, data) => { + const session = this._chanMgr.get(recipient); + if (typeof session !== 'object' || session === null) + return; - channel.subtype = self.subtype = info.request; + let replied = false; + let accept; + let reject; - return channel; - }; + if (session.constructor !== Session) { + // normal Channel instance + if (wantReply) + proto.channelFailure(session.outgoing.id); + return; + } - self.emit('shell', accept, reject); - } else - reject && reject(); - break; - case 'exec': - if (listenerCount(self, 'exec')) { - accept = function() { - if (replied || ending || channel) - return; + if (wantReply) { + // "real session" requests will have custom accept behaviors + if (type !== 'shell' + && type !== 'exec' + && type !== 'subsystem') { + accept = () => { + if (replied || session._ending || session._channel) + return; + replied = true; + + proto.channelSuccess(session._chanInfo.outgoing.id); + }; + } + + reject = () => { + if (replied || session._ending || session._channel) + return; + replied = true; + + proto.channelFailure(session._chanInfo.outgoing.id); + }; + } - replied = true; + if (session._ending) { + reject && reject(); + return; + } - if (info.wantReply) - client._sshstream.channelSuccess(outgoingId); + switch (type) { + // "pre-real session start" requests + case 'env': + if (listenerCount(session, 'env')) { + session.emit('env', accept, reject, { + key: data.name, + val: data.value + }); + return; + } + break; + case 'pty-req': + if (listenerCount(session, 'pty')) { + session.emit('pty', accept, reject, data); + return; + } + break; + case 'window-change': + if (listenerCount(session, 'window-change')) + session.emit('window-change', accept, reject, data); + else + reject && reject(); + break; + case 'x11-req': + if (listenerCount(session, 'x11')) { + session.emit('x11', accept, reject, data); + return; + } + break; + // "post-real session start" requests + case 'signal': + if (listenerCount(session, 'signal')) { + session.emit('signal', accept, reject, { + name: data + }); + return; + } + break; + // XXX: is `auth-agent-req@openssh.com` really "post-real session + // start"? + case 'auth-agent-req@openssh.com': + if (listenerCount(session, 'auth-agent')) { + session.emit('auth-agent', accept, reject); + return; + } + break; + // "real session start" requests + case 'shell': + if (listenerCount(session, 'shell')) { + accept = () => { + if (replied || session._ending || session._channel) + return; + replied = true; + + if (wantReply) + proto.channelSuccess(session._chanInfo.outgoing.id); + + const channel = new Channel( + this, session._chanInfo, { server: true } + ); + + channel.subtype = session.subtype = type; + session._channel = channel; + + return channel; + }; + + session.emit('shell', accept, reject); + return; + } + break; + case 'exec': + if (listenerCount(session, 'exec')) { + accept = () => { + if (replied || session._ending || session._channel) + return; + replied = true; + + if (wantReply) + proto.channelSuccess(session._chanInfo.outgoing.id); + + const channel = new Channel( + this, session._chanInfo, { server: true } + ); + + channel.subtype = session.subtype = type; + session._channel = channel; + + return channel; + }; + + session.emit('exec', accept, reject, { + command: data + }); + return; + } + break; + case 'subsystem': { + let useSFTP = (data === 'sftp'); + accept = () => { + if (replied || session._ending || session._channel) + return; + replied = true; + + if (wantReply) + proto.channelSuccess(session._chanInfo.outgoing.id); + + let instance; + if (useSFTP) { + instance = new SFTP(this, session._chanInfo, { + server: true, + debug, + }); + } else { + instance = new Channel( + this, session._chanInfo, { server: true } + ); + instance.subtype = + session.subtype = `${type}:${data}`; + } + session._channel = instance; + + return instance; + }; + + if (data === 'sftp') { + if (listenerCount(session, 'sftp')) { + session.emit('sftp', accept, reject); + return; + } + useSFTP = false; + } + if (listenerCount(session, 'subsystem')) { + session.emit('subsystem', accept, reject, { + name: data + }); + return; + } + break; + } + } + debug && debug( + `Automatic rejection of incoming channel request: ${type}` + ); + reject && reject(); + }, + CHANNEL_EOF: (p, recipient) => { + let channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; - channel = new Channel(chaninfo, client, { server: true }); + if (channel.constructor === Session) { + if (!channel._ending) { + channel._ending = true; + channel.emit('eof'); + channel.emit('end'); + } + channel = channel._channel; + if (!channel) + return; + } - channel.subtype = self.subtype = info.request; + if (channel.incoming.state !== 'open') + return; + channel.incoming.state = 'eof'; + + if (channel.readable) + channel.push(null); + }, + CHANNEL_CLOSE: (p, recipient) => { + let channel = this._chanMgr.get(recipient); + if (typeof channel !== 'object' || channel === null) + return; - return channel; - }; + if (channel.constructor === Session) { + channel._ending = true; + channel.emit('close'); + channel = channel._channel; + if (!channel) + return; + } - self.emit('exec', accept, reject, { - command: info.command - }); - } else - reject && reject(); - break; - case 'subsystem': - accept = function() { - if (replied || ending || channel) + onCHANNEL_CLOSE(this, recipient, channel); + }, + // Begin service/auth-related ========================================== + SERVICE_REQUEST: (p, service) => { + if (exchanges === 0 + || acceptedAuthSvc + || this.authenticated + || service !== 'ssh-userauth') { + proto.disconnect(DISCONNECT_REASON.SERVICE_NOT_AVAILABLE); + socket.end(); return; + } - replied = true; + acceptedAuthSvc = true; + proto.serviceAccept(service); + }, + USERAUTH_REQUEST: (p, username, service, method, methodData) => { + if (exchanges === 0 + || this.authenticated + || (authCtx + && (authCtx.username !== username + || authCtx.service !== service)) + // TODO: support hostbased auth + || (method !== 'password' + && method !== 'publickey' + && method !== 'hostbased' + && method !== 'keyboard-interactive' + && method !== 'none') + || pendingAuths.length === MAX_PENDING_AUTHS) { + proto.disconnect(DISCONNECT_REASON.PROTOCOL_ERROR); + socket.end(); + return; + } else if (service !== 'ssh-connection') { + proto.disconnect(DISCONNECT_REASON.SERVICE_NOT_AVAILABLE); + socket.end(); + return; + } - if (info.wantReply) - client._sshstream.channelSuccess(outgoingId); + let ctx; + switch (method) { + case 'keyboard-interactive': + ctx = new KeyboardAuthContext(proto, username, service, method, + methodData, onAuthDecide); + break; + case 'publickey': + ctx = new PKAuthContext(proto, username, service, method, + methodData, onAuthDecide); + break; + case 'hostbased': + ctx = new HostbasedAuthContext(proto, username, service, method, + methodData, onAuthDecide); + break; + case 'password': + if (authCtx + && authCtx instanceof PwdAuthContext + && authCtx._changeCb) { + const cb = authCtx._changeCb; + authCtx._changeCb = undefined; + cb(methodData.newPassword); + return; + } + ctx = new PwdAuthContext(proto, username, service, method, + methodData, onAuthDecide); + break; + case 'none': + ctx = new AuthContext(proto, username, service, method, + onAuthDecide); + break; + } - channel = new Channel(chaninfo, client, { server: true }); + if (authCtx) { + if (!authCtx._initialResponse) { + return pendingAuths.push(ctx); + } else if (authCtx._multistep && !authCtx._finalResponse) { + // RFC 4252 says to silently abort the current auth request if a + // new auth request comes in before the final response from an + // auth method that requires additional request/response exchanges + // -- this means keyboard-interactive for now ... + authCtx._cleanup && authCtx._cleanup(); + authCtx.emit('abort'); + } + } - channel.subtype = self.subtype = (info.request + ':' + info.subsystem); + authCtx = ctx; - if (info.subsystem === 'sftp') { - var sftp = new SFTPStream({ - server: true, - debug: client._sshstream.debug - }); - channel.pipe(sftp).pipe(channel); + if (listenerCount(this, 'authentication')) + this.emit('authentication', authCtx); + else + authCtx.reject(); + }, + USERAUTH_INFO_RESPONSE: (p, responses) => { + if (authCtx && authCtx instanceof KeyboardAuthContext) + authCtx._onInfoResponse(responses); + }, + // End service/auth-related ============================================ + GLOBAL_REQUEST: (p, name, wantReply, data) => { + const reply = { + type: null, + buf: null + }; - return sftp; - } else - return channel; - }; + function setReply(type, buf) { + reply.type = type; + reply.buf = buf; + sendReplies(); + } - if (info.subsystem === 'sftp' && listenerCount(self, 'sftp')) - self.emit('sftp', accept, reject); - else if (info.subsystem !== 'sftp' && listenerCount(self, 'subsystem')) { - self.emit('subsystem', accept, reject, { - name: info.subsystem - }); - } else - reject && reject(); - break; - default: - reject && reject(); - } - } - function onEOF() { - ending = true; - self.emit('eof'); - self.emit('end'); - } - function onCLOSE() { - ending = true; - self.emit('close'); - } - client._sshstream - .on('CHANNEL_REQUEST:' + localChan, onREQUEST) - .once('CHANNEL_EOF:' + localChan, onEOF) - .once('CHANNEL_CLOSE:' + localChan, onCLOSE); -} -inherits(Session, EventEmitter); + if (wantReply) + unsentGlobalRequestsReplies.push(reply); + + if ((name === 'tcpip-forward' + || name === 'cancel-tcpip-forward' + || name === 'no-more-sessions@openssh.com' + || name === 'streamlocal-forward@openssh.com' + || name === 'cancel-streamlocal-forward@openssh.com') + && listenerCount(this, 'request') + && this.authenticated) { + let accept; + let reject; + + if (wantReply) { + let replied = false; + accept = (chosenPort) => { + if (replied) + return; + replied = true; + let bufPort; + if (name === 'tcpip-forward' + && data.bindPort === 0 + && typeof chosenPort === 'number') { + bufPort = Buffer.allocUnsafe(4); + writeUInt32BE(bufPort, chosenPort, 0); + } + setReply('SUCCESS', bufPort); + }; + reject = () => { + if (replied) + return; + replied = true; + setReply('FAILURE'); + }; + } + + if (name === 'no-more-sessions@openssh.com') { + this.noMoreSessions = true; + accept && accept(); + return; + } + this.emit('request', accept, reject, name, data); + } else if (wantReply) { + setReply('FAILURE'); + } + }, + }, + }); -function AuthContext(stream, username, service, method, cb) { - EventEmitter.call(this); + socket.pause(); + cryptoInit.then(() => { + socket.on('data', (data) => { + try { + proto.parse(data, 0, data.length); + } catch (ex) { + this.emit('error', ex); + try { + if (isWritable(socket)) + socket.end(); + } catch {} + } + }); + socket.resume(); + }).catch((err) => { + this.emit('error', err); + try { + if (isWritable(socket)) + socket.end(); + } catch {} + }); + socket.on('error', (err) => { + err.level = 'socket'; + this.emit('error', err); + }).once('end', () => { + debug && debug('Socket ended'); + proto.cleanup(); + this.emit('end'); + }).once('close', () => { + debug && debug('Socket closed'); + proto.cleanup(); + this.emit('close'); + + const err = new Error('No response from server'); + + // Simulate error for pending channels and close any open channels + this._chanMgr.cleanup(err); + }); - var self = this; + const onAuthDecide = (ctx, allowed, methodsLeft, isPartial) => { + if (authCtx === ctx && !this.authenticated) { + if (allowed) { + authCtx = undefined; + this.authenticated = true; + proto.authSuccess(); + pendingAuths = []; + this.emit('ready'); + } else { + proto.authFailure(methodsLeft, isPartial); + if (pendingAuths.length) { + authCtx = pendingAuths.pop(); + if (listenerCount(this, 'authentication')) + this.emit('authentication', authCtx); + else + authCtx.reject(); + } + } + } + }; - this.username = this.user = username; - this.service = service; - this.method = method; - this._initialResponse = false; - this._finalResponse = false; - this._multistep = false; - this._cbfinal = function(allowed, methodsLeft, isPartial) { - if (!self._finalResponse) { - self._finalResponse = true; - cb(self, allowed, methodsLeft, isPartial); - } - }; - this._stream = stream; -} -inherits(AuthContext, EventEmitter); -AuthContext.prototype.accept = function() { - this._cleanup && this._cleanup(); - this._initialResponse = true; - this._cbfinal(true); -}; -AuthContext.prototype.reject = function(methodsLeft, isPartial) { - this._cleanup && this._cleanup(); - this._initialResponse = true; - this._cbfinal(false, methodsLeft, isPartial); -}; - -var RE_KBINT_SUBMETHODS = /[ \t\r\n]*,[ \t\r\n]*/g; -function KeyboardAuthContext(stream, username, service, method, submethods, cb) { - AuthContext.call(this, stream, username, service, method, cb); - this._multistep = true; - - var self = this; - - this._cb = undefined; - this._onInfoResponse = function(responses) { - if (self._cb) { - var callback = self._cb; - self._cb = undefined; - callback(responses); + function sendReplies() { + while (unsentGlobalRequestsReplies.length > 0 + && unsentGlobalRequestsReplies[0].type) { + const reply = unsentGlobalRequestsReplies.shift(); + if (reply.type === 'SUCCESS') + proto.requestSuccess(reply.buf); + if (reply.type === 'FAILURE') + proto.requestFailure(); + } } - }; - this.submethods = submethods.split(RE_KBINT_SUBMETHODS); - this.on('abort', function() { - self._cb && self._cb(new Error('Authentication request aborted')); - }); -} -inherits(KeyboardAuthContext, AuthContext); -KeyboardAuthContext.prototype._cleanup = function() { - this._stream.removeListener('USERAUTH_INFO_RESPONSE', this._onInfoResponse); -}; -KeyboardAuthContext.prototype.prompt = function(prompts, title, instructions, - cb) { - if (!Array.isArray(prompts)) - prompts = [ prompts ]; - - if (typeof title === 'function') { - cb = title; - title = instructions = undefined; - } else if (typeof instructions === 'function') { - cb = instructions; - instructions = undefined; } - for (var i = 0; i < prompts.length; ++i) { - if (typeof prompts[i] === 'string') { - prompts[i] = { - prompt: prompts[i], - echo: true - }; + end() { + if (this._sock && isWritable(this._sock)) { + this._protocol.disconnect(DISCONNECT_REASON.BY_APPLICATION); + this._sock.end(); } + return this; } - this._cb = cb; - this._initialResponse = true; - this._stream.once('USERAUTH_INFO_RESPONSE', this._onInfoResponse); - - return this._stream.authInfoReq(title, instructions, prompts); -}; - -function PKAuthContext(stream, username, service, method, pkInfo, cb) { - AuthContext.call(this, stream, username, service, method, cb); - - this.key = { algo: pkInfo.keyAlgo, data: pkInfo.key }; - this.signature = pkInfo.signature; - var sigAlgo; - if (this.signature) { - switch (pkInfo.keyAlgo) { - case 'ssh-rsa': - sigAlgo = 'RSA-SHA1'; - break; - case 'ssh-dss': - sigAlgo = 'DSA-SHA1'; - break; - case 'ecdsa-sha2-nistp256': - sigAlgo = 'sha256'; - break; - case 'ecdsa-sha2-nistp384': - sigAlgo = 'sha384'; - break; - case 'ecdsa-sha2-nistp521': - sigAlgo = 'sha512'; - break; - } + x11(originAddr, originPort, cb) { + const opts = { originAddr, originPort }; + openChannel(this, 'x11', opts, cb); + return this; } - this.sigAlgo = sigAlgo; - this.blob = pkInfo.blob; -} -inherits(PKAuthContext, AuthContext); -PKAuthContext.prototype.accept = function() { - if (!this.signature) { - this._initialResponse = true; - this._stream.authPKOK(this.key.algo, this.key.data); - } else - AuthContext.prototype.accept.call(this); -}; - -function HostbasedAuthContext(stream, username, service, method, pkInfo, cb) { - AuthContext.call(this, stream, username, service, method, cb); - - this.key = { algo: pkInfo.keyAlgo, data: pkInfo.key }; - this.signature = pkInfo.signature; - var sigAlgo; - if (this.signature) { - switch (pkInfo.keyAlgo) { - case 'ssh-rsa': - sigAlgo = 'RSA-SHA1'; - break; - case 'ssh-dss': - sigAlgo = 'DSA-SHA1'; - break; - case 'ecdsa-sha2-nistp256': - sigAlgo = 'sha256'; - break; - case 'ecdsa-sha2-nistp384': - sigAlgo = 'sha384'; - break; - case 'ecdsa-sha2-nistp521': - sigAlgo = 'sha512'; - break; - } + + forwardOut(boundAddr, boundPort, remoteAddr, remotePort, cb) { + const opts = { boundAddr, boundPort, remoteAddr, remotePort }; + openChannel(this, 'forwarded-tcpip', opts, cb); + return this; + } + + openssh_forwardOutStreamLocal(socketPath, cb) { + const opts = { socketPath }; + openChannel(this, 'forwarded-streamlocal@openssh.com', opts, cb); + return this; } - this.sigAlgo = sigAlgo; - this.blob = pkInfo.blob; - this.localHostname = pkInfo.localHostname; - this.localUsername = pkInfo.localUsername; -} -inherits(HostbasedAuthContext, AuthContext); -function PwdAuthContext(stream, username, service, method, password, cb) { - AuthContext.call(this, stream, username, service, method, cb); + rekey(cb) { + let error; + + try { + this._protocol.rekey(); + } catch (ex) { + error = ex; + } - this.password = password; + // TODO: re-throw error if no callback? + + if (typeof cb === 'function') { + if (error) + process.nextTick(cb, error); + else + this.once('rekey', cb); + } + } } -inherits(PwdAuthContext, AuthContext); function openChannel(self, type, opts, cb) { - // ask the client to open a channel for some purpose - // (e.g. a forwarded TCP connection) - var localChan = nextChannel(self); - var initWindow = Channel.MAX_WINDOW; - var maxPacket = Channel.PACKET_SIZE; - var ret = true; - - if (localChan === false) - return cb(new Error('No free channels available')); + // Ask the client to open a channel for some purpose (e.g. a forwarded TCP + // connection) + const initWindow = MAX_WINDOW; + const maxPacket = PACKET_SIZE; if (typeof opts === 'function') { cb = opts; opts = {}; } - self._channels[localChan] = true; + const wrapper = (err, stream) => { + cb(err, stream); + }; + wrapper.type = type; - var sshstream = self._sshstream; - sshstream.once('CHANNEL_OPEN_CONFIRMATION:' + localChan, function(info) { - sshstream.removeAllListeners('CHANNEL_OPEN_FAILURE:' + localChan); + const localChan = self._chanMgr.add(wrapper); - var chaninfo = { - type: type, - incoming: { - id: localChan, - window: initWindow, - packetSize: maxPacket, - state: 'open' - }, - outgoing: { - id: info.sender, - window: info.window, - packetSize: info.packetSize, - state: 'open' - } - }; - cb(undefined, new Channel(chaninfo, self, { server: true })); - }).once('CHANNEL_OPEN_FAILURE:' + localChan, function(info) { - sshstream.removeAllListeners('CHANNEL_OPEN_CONFIRMATION:' + localChan); - - delete self._channels[localChan]; - - var err = new Error('(SSH) Channel open failure: ' + info.description); - err.reason = info.reason; - err.lang = info.lang; - cb(err); - }); - - if (type === 'forwarded-tcpip') - ret = sshstream.forwardedTcpip(localChan, initWindow, maxPacket, opts); - else if (type === 'x11') - ret = sshstream.x11(localChan, initWindow, maxPacket, opts); - else if (type === 'forwarded-streamlocal@openssh.com') { - ret = sshstream.openssh_forwardedStreamLocal(localChan, - initWindow, - maxPacket, - opts); + if (localChan === -1) { + cb(new Error('No free channels available')); + return; } - return ret; + switch (type) { + case 'forwarded-tcpip': + self._protocol.forwardedTcpip(localChan, initWindow, maxPacket, opts); + break; + case 'x11': + self._protocol.x11(localChan, initWindow, maxPacket, opts); + break; + case 'forwarded-streamlocal@openssh.com': + self._protocol.openssh_forwardedStreamLocal( + localChan, initWindow, maxPacket, opts + ); + break; + default: + throw new Error(`Unsupported channel type: ${type}`); + } } -function nextChannel(self) { - // get the next available channel number - - // fast path - if (self._curChan < MAX_CHANNEL) - return ++self._curChan; - - // slower lookup path - for (var i = 0, channels = self._channels; i < MAX_CHANNEL; ++i) - if (!channels[i]) - return i; - - return false; +function compareNumbers(a, b) { + return a - b; } - -Server.createServer = function(cfg, listener) { - return new Server(cfg, listener); -}; -Server.KEEPALIVE_INTERVAL = 1000; -Server.KEEPALIVE_CLIENT_INTERVAL = 15000; -Server.KEEPALIVE_CLIENT_COUNT_MAX = 3; - module.exports = Server; +module.exports.IncomingClient = Client; diff --git a/reverse_engineering/node_modules/ssh2/lib/utils.js b/reverse_engineering/node_modules/ssh2/lib/utils.js index f513b95..04d4b96 100644 --- a/reverse_engineering/node_modules/ssh2/lib/utils.js +++ b/reverse_engineering/node_modules/ssh2/lib/utils.js @@ -1,5 +1,332 @@ -exports.spliceOne = function(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); +'use strict'; + +const { SFTP } = require('./protocol/SFTP.js'); + +const MAX_CHANNEL = 2 ** 32 - 1; + +function onChannelOpenFailure(self, recipient, info, cb) { + self._chanMgr.remove(recipient); + if (typeof cb !== 'function') + return; + + let err; + if (info instanceof Error) { + err = info; + } else if (typeof info === 'object' && info !== null) { + err = new Error(`(SSH) Channel open failure: ${info.description}`); + err.reason = info.reason; + } else { + err = new Error( + '(SSH) Channel open failure: server closed channel unexpectedly' + ); + err.reason = ''; + } + + cb(err); +} + +function onCHANNEL_CLOSE(self, recipient, channel, err, dead) { + if (typeof channel === 'function') { + // We got CHANNEL_CLOSE instead of CHANNEL_OPEN_FAILURE when + // requesting to open a channel + onChannelOpenFailure(self, recipient, err, channel); + return; + } + if (typeof channel !== 'object' + || channel === null + || channel.incoming.state === 'closed') { + return; + } + + channel.incoming.state = 'closed'; + + if (channel.readable) + channel.push(null); + if (channel.server) { + if (channel.stderr.writable) + channel.stderr.end(); + } else if (channel.stderr.readable) { + channel.stderr.push(null); + } + + if (channel.constructor !== SFTP + && (channel.outgoing.state === 'open' + || channel.outgoing.state === 'eof') + && !dead) { + channel.close(); + } + if (channel.outgoing.state === 'closing') + channel.outgoing.state = 'closed'; + + self._chanMgr.remove(recipient); + + const readState = channel._readableState; + const writeState = channel._writableState; + if (writeState && !writeState.ending && !writeState.finished && !dead) + channel.end(); + + // Take care of any outstanding channel requests + const chanCallbacks = channel._callbacks; + channel._callbacks = []; + for (let i = 0; i < chanCallbacks.length; ++i) + chanCallbacks[i](true); + + if (channel.server) { + if (!channel.readable + || channel.destroyed + || (readState && readState.endEmitted)) { + channel.emit('close'); + } else { + channel.once('end', () => channel.emit('close')); + } + } else { + let doClose; + switch (channel.type) { + case 'direct-streamlocal@openssh.com': + case 'direct-tcpip': + doClose = () => channel.emit('close'); + break; + default: { + // Align more with node child processes, where the close event gets + // the same arguments as the exit event + const exit = channel._exit; + doClose = () => { + if (exit.code === null) + channel.emit('close', exit.code, exit.signal, exit.dump, exit.desc); + else + channel.emit('close', exit.code); + }; + } + } + if (!channel.readable + || channel.destroyed + || (readState && readState.endEmitted)) { + doClose(); + } else { + channel.once('end', doClose); + } + + const errReadState = channel.stderr._readableState; + if (!channel.stderr.readable + || channel.stderr.destroyed + || (errReadState && errReadState.endEmitted)) { + channel.stderr.emit('close'); + } else { + channel.stderr.once('end', () => channel.stderr.emit('close')); + } + } +} + +class ChannelManager { + constructor(client) { + this._client = client; + this._channels = {}; + this._cur = -1; + this._count = 0; + } + add(val) { + // Attempt to reserve an id + + let id; + // Optimized paths + if (this._cur < MAX_CHANNEL) { + id = ++this._cur; + } else if (this._count === 0) { + // Revert and reset back to fast path once we no longer have any channels + // open + this._cur = 0; + id = 0; + } else { + // Slower lookup path + + // This path is triggered we have opened at least MAX_CHANNEL channels + // while having at least one channel open at any given time, so we have + // to search for a free id. + const channels = this._channels; + for (let i = 0; i < MAX_CHANNEL; ++i) { + if (channels[i] === undefined) { + id = i; + break; + } + } + } + + if (id === undefined) + return -1; + + this._channels[id] = (val || true); + ++this._count; + + return id; + } + update(id, val) { + if (typeof id !== 'number' || id < 0 || id >= MAX_CHANNEL || !isFinite(id)) + throw new Error(`Invalid channel id: ${id}`); + + if (val && this._channels[id]) + this._channels[id] = val; + } + get(id) { + if (typeof id !== 'number' || id < 0 || id >= MAX_CHANNEL || !isFinite(id)) + throw new Error(`Invalid channel id: ${id}`); + + return this._channels[id]; + } + remove(id) { + if (typeof id !== 'number' || id < 0 || id >= MAX_CHANNEL || !isFinite(id)) + throw new Error(`Invalid channel id: ${id}`); + + if (this._channels[id]) { + delete this._channels[id]; + if (this._count) + --this._count; + } + } + cleanup(err) { + const channels = this._channels; + this._channels = {}; + this._cur = -1; + this._count = 0; + + const chanIDs = Object.keys(channels); + const client = this._client; + for (let i = 0; i < chanIDs.length; ++i) { + const id = +chanIDs[i]; + const channel = channels[id]; + onCHANNEL_CLOSE(client, id, channel._channel || channel, err, true); + } + } +} + +const isRegExp = (() => { + const toString = Object.prototype.toString; + return (val) => toString.call(val) === '[object RegExp]'; +})(); + +function generateAlgorithmList(algoList, defaultList, supportedList) { + if (Array.isArray(algoList) && algoList.length > 0) { + // Exact list + for (let i = 0; i < algoList.length; ++i) { + if (supportedList.indexOf(algoList[i]) === -1) + throw new Error(`Unsupported algorithm: ${algoList[i]}`); + } + return algoList; + } + + if (typeof algoList === 'object' && algoList !== null) { + // Operations based on the default list + const keys = Object.keys(algoList); + let list = defaultList; + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + let val = algoList[key]; + switch (key) { + case 'append': + if (!Array.isArray(val)) + val = [val]; + if (Array.isArray(val)) { + for (let j = 0; j < val.length; ++j) { + const append = val[j]; + if (typeof append === 'string') { + if (!append || list.indexOf(append) !== -1) + continue; + if (supportedList.indexOf(append) === -1) + throw new Error(`Unsupported algorithm: ${append}`); + if (list === defaultList) + list = list.slice(); + list.push(append); + } else if (isRegExp(append)) { + for (let k = 0; k < supportedList.length; ++k) { + const algo = supportedList[k]; + if (append.test(algo)) { + if (list.indexOf(algo) !== -1) + continue; + if (list === defaultList) + list = list.slice(); + list.push(algo); + } + } + } + } + } + break; + case 'prepend': + if (!Array.isArray(val)) + val = [val]; + if (Array.isArray(val)) { + for (let j = val.length; j >= 0; --j) { + const prepend = val[j]; + if (typeof prepend === 'string') { + if (!prepend || list.indexOf(prepend) !== -1) + continue; + if (supportedList.indexOf(prepend) === -1) + throw new Error(`Unsupported algorithm: ${prepend}`); + if (list === defaultList) + list = list.slice(); + list.unshift(prepend); + } else if (isRegExp(prepend)) { + for (let k = supportedList.length; k >= 0; --k) { + const algo = supportedList[k]; + if (prepend.test(algo)) { + if (list.indexOf(algo) !== -1) + continue; + if (list === defaultList) + list = list.slice(); + list.unshift(algo); + } + } + } + } + } + break; + case 'remove': + if (!Array.isArray(val)) + val = [val]; + if (Array.isArray(val)) { + for (let j = 0; j < val.length; ++j) { + const search = val[j]; + if (typeof search === 'string') { + if (!search) + continue; + const idx = list.indexOf(search); + if (idx === -1) + continue; + if (list === defaultList) + list = list.slice(); + list.splice(idx, 1); + } else if (isRegExp(search)) { + for (let k = 0; k < list.length; ++k) { + if (search.test(list[k])) { + if (list === defaultList) + list = list.slice(); + list.splice(k, 1); + --k; + } + } + } + } + } + break; + } + } + + return list; + } + + return defaultList; +} + +module.exports = { + ChannelManager, + generateAlgorithmList, + onChannelOpenFailure, + onCHANNEL_CLOSE, + isWritable: (stream) => { + // XXX: hack to workaround regression in node + // See: https://github.com/nodejs/node/issues/36029 + return (stream + && stream.writable + && stream._readableState + && stream._readableState.ended === false); + }, }; diff --git a/reverse_engineering/node_modules/ssh2/package.json b/reverse_engineering/node_modules/ssh2/package.json index 7c7dd13..b26f985 100644 --- a/reverse_engineering/node_modules/ssh2/package.json +++ b/reverse_engineering/node_modules/ssh2/package.json @@ -1,23 +1,83 @@ -{ "name": "ssh2", - "version": "0.5.4", - "author": "Brian White ", - "description": "SSH2 client and server modules written in pure JavaScript for node.js", - "main": "./lib/client", - "engines": { "node": ">=0.10.0" }, +{ + "_from": "ssh2@1.4.0", + "_id": "ssh2@1.4.0", + "_inBundle": false, + "_integrity": "sha512-XvXwcXKvS452DyQvCa6Ct+chpucwc/UyxgliYz+rWXJ3jDHdtBb9xgmxJdMmnIn5bpgGAEV3KaEsH98ZGPHqwg==", + "_location": "/ssh2", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "ssh2@1.4.0", + "name": "ssh2", + "escapedName": "ssh2", + "rawSpec": "1.4.0", + "saveSpec": null, + "fetchSpec": "1.4.0" + }, + "_requiredBy": [ + "/tunnel-ssh" + ], + "_resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.4.0.tgz", + "_shasum": "e32e8343394364c922bad915a5a7fecd67d0f5c5", + "_spec": "ssh2@1.4.0", + "_where": "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering/node_modules/tunnel-ssh", + "author": { + "name": "Brian White", + "email": "mscdex@mscdex.net" + }, + "bugs": { + "url": "https://github.com/mscdex/ssh2/issues" + }, + "bundleDependencies": false, "dependencies": { - "ssh2-streams": "~0.1.15" + "asn1": "^0.2.4", + "bcrypt-pbkdf": "^1.0.2", + "cpu-features": "0.0.2", + "nan": "^2.15.0" }, + "deprecated": false, + "description": "SSH2 client and server modules written in pure JavaScript for node.js", "devDependencies": { - "semver": "^5.1.0" + "@mscdex/eslint-config": "^1.0.0", + "eslint": "^7.0.0" + }, + "engines": { + "node": ">=10.16.0" + }, + "homepage": "https://github.com/mscdex/ssh2#readme", + "keywords": [ + "ssh", + "ssh2", + "sftp", + "secure", + "shell", + "exec", + "remote", + "client" + ], + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/mscdex/ssh2/raw/master/LICENSE" + } + ], + "main": "./lib/index.js", + "name": "ssh2", + "optionalDependencies": { + "cpu-features": "0.0.2", + "nan": "^2.15.0" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/mscdex/ssh2.git" }, "scripts": { + "install": "node install.js", + "lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js examples lib test", + "lint:fix": "npm run lint -- --fix", + "rebuild": "node install.js", "test": "node test/test.js" }, - "keywords": [ "ssh", "ssh2", "sftp", "secure", "shell", "exec", "remote", "client" ], - "licenses": [ { "type": "MIT", "url": "http://github.com/mscdex/ssh2/raw/master/LICENSE" } ], - "repository" : { "type": "git", "url": "http://github.com/mscdex/ssh2.git" } - -,"_resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.5.4.tgz" -,"_integrity": "sha1-G/a2soyW6u8mf01sRqWiUXpZnic=" -,"_from": "ssh2@0.5.4" -} \ No newline at end of file + "version": "1.4.0" +} diff --git a/reverse_engineering/node_modules/ssh2/test/common.js b/reverse_engineering/node_modules/ssh2/test/common.js new file mode 100644 index 0000000..a531924 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/common.js @@ -0,0 +1,316 @@ +'use strict'; + +const assert = require('assert'); +const { readFileSync } = require('fs'); +const { join } = require('path'); +const { inspect } = require('util'); + +const Client = require('../lib/client.js'); +const Server = require('../lib/server.js'); +const { parseKey } = require('../lib/protocol/keyParser.js'); + +const mustCallChecks = []; + +const DEFAULT_TEST_TIMEOUT = 30 * 1000; + +function noop() {} + +function runCallChecks(exitCode) { + if (exitCode !== 0) return; + + const failed = mustCallChecks.filter((context) => { + if ('minimum' in context) { + context.messageSegment = `at least ${context.minimum}`; + return context.actual < context.minimum; + } + context.messageSegment = `exactly ${context.exact}`; + return context.actual !== context.exact; + }); + + failed.forEach((context) => { + console.error('Mismatched %s function calls. Expected %s, actual %d.', + context.name, + context.messageSegment, + context.actual); + console.error(context.stack.split('\n').slice(2).join('\n')); + }); + + if (failed.length) + process.exit(1); +} + +function mustCall(fn, exact) { + return _mustCallInner(fn, exact, 'exact'); +} + +function mustCallAtLeast(fn, minimum) { + return _mustCallInner(fn, minimum, 'minimum'); +} + +function _mustCallInner(fn, criteria = 1, field) { + if (process._exiting) + throw new Error('Cannot use common.mustCall*() in process exit handler'); + + if (typeof fn === 'number') { + criteria = fn; + fn = noop; + } else if (fn === undefined) { + fn = noop; + } + + if (typeof criteria !== 'number') + throw new TypeError(`Invalid ${field} value: ${criteria}`); + + const context = { + [field]: criteria, + actual: 0, + stack: inspect(new Error()), + name: fn.name || '' + }; + + // Add the exit listener only once to avoid listener leak warnings + if (mustCallChecks.length === 0) + process.on('exit', runCallChecks); + + mustCallChecks.push(context); + + function wrapped(...args) { + ++context.actual; + return fn.call(this, ...args); + } + // TODO: remove origFn? + wrapped.origFn = fn; + + return wrapped; +} + +function getCallSite(top) { + const originalStackFormatter = Error.prepareStackTrace; + Error.prepareStackTrace = (err, stack) => + `${stack[0].getFileName()}:${stack[0].getLineNumber()}`; + const err = new Error(); + Error.captureStackTrace(err, top); + // With the V8 Error API, the stack is not formatted until it is accessed + // eslint-disable-next-line no-unused-expressions + err.stack; + Error.prepareStackTrace = originalStackFormatter; + return err.stack; +} + +function mustNotCall(msg) { + const callSite = getCallSite(mustNotCall); + return function mustNotCall(...args) { + args = args.map(inspect).join(', '); + const argsInfo = (args.length > 0 + ? `\ncalled with arguments: ${args}` + : ''); + assert.fail( + `${msg || 'function should not have been called'} at ${callSite}` + + argsInfo); + }; +} + +function setup(title, configs) { + const { + client: clientCfg_, + server: serverCfg_, + allReady: allReady_, + timeout: timeout_, + debug, + noForceClientReady, + noForceServerReady, + noClientError, + noServerError, + } = configs; + + // Make shallow copies of client/server configs to avoid mutating them when + // multiple tests share the same config object reference + let clientCfg; + if (clientCfg_) + clientCfg = { ...clientCfg_ }; + let serverCfg; + if (serverCfg_) + serverCfg = { ...serverCfg_ }; + + let clientClose = false; + let clientReady = false; + let serverClose = false; + let serverReady = false; + const msg = (text) => { + return `${title}: ${text}`; + }; + + const timeout = (typeof timeout_ === 'number' + ? timeout_ + : DEFAULT_TEST_TIMEOUT); + + const allReady = (typeof allReady_ === 'function' ? allReady_ : undefined); + + if (debug) { + if (clientCfg) { + clientCfg.debug = (...args) => { + console.log(`[${title}][CLIENT]`, ...args); + }; + } + if (serverCfg) { + serverCfg.debug = (...args) => { + console.log(`[${title}][SERVER]`, ...args); + }; + } + } + + let timer; + let client; + let clientReadyFn; + let server; + let serverReadyFn; + if (clientCfg) { + client = new Client(); + if (!noClientError) + client.on('error', onError); + clientReadyFn = (noForceClientReady ? onReady : mustCall(onReady)); + client.on('ready', clientReadyFn) + .on('close', mustCall(onClose)); + } else { + clientReady = clientClose = true; + } + + if (serverCfg) { + server = new Server(serverCfg); + if (!noServerError) + server.on('error', onError); + serverReadyFn = (noForceServerReady ? onReady : mustCall(onReady)); + server.on('connection', mustCall((conn) => { + if (!noServerError) + conn.on('error', onError); + conn.on('ready', serverReadyFn); + server.close(); + })).on('close', mustCall(onClose)); + } else { + serverReady = serverClose = true; + } + + function onError(err) { + const which = (this === client ? 'client' : 'server'); + assert(false, msg(`Unexpected ${which} error: ${err.stack}\n`)); + } + + function onReady() { + if (this === client) { + assert(!clientReady, + msg('Received multiple ready events for client')); + clientReady = true; + } else { + assert(!serverReady, + msg('Received multiple ready events for server')); + serverReady = true; + } + clientReady && serverReady && allReady && allReady(); + } + + function onClose() { + if (this === client) { + assert(!clientClose, + msg('Received multiple close events for client')); + clientClose = true; + } else { + assert(!serverClose, + msg('Received multiple close events for server')); + serverClose = true; + } + if (clientClose && serverClose) + clearTimeout(timer); + } + + process.nextTick(mustCall(() => { + function connectClient() { + if (clientCfg.sock) { + clientCfg.sock.connect(server.address().port, 'localhost'); + } else { + clientCfg.host = 'localhost'; + clientCfg.port = server.address().port; + } + try { + client.connect(clientCfg); + } catch (ex) { + ex.message = msg(ex.message); + throw ex; + } + } + + if (server) { + server.listen(0, 'localhost', mustCall(() => { + if (timeout >= 0) { + timer = setTimeout(() => { + assert(false, msg('Test timed out')); + }, timeout); + } + if (client) + connectClient(); + })); + } + })); + + return { client, server }; +} + +const FIXTURES_DIR = join(__dirname, 'fixtures'); +const fixture = (() => { + const cache = new Map(); + return (file) => { + const existing = cache.get(file); + if (existing !== undefined) + return existing; + + const result = readFileSync(join(FIXTURES_DIR, file)); + cache.set(file, result); + return result; + }; +})(); +const fixtureKey = (() => { + const cache = new Map(); + return (file, passphrase, bypass) => { + if (typeof passphrase === 'boolean') { + bypass = passphrase; + passphrase = undefined; + } + if (typeof bypass !== 'boolean' || !bypass) { + const existing = cache.get(file); + if (existing !== undefined) + return existing; + } + const fullPath = join(FIXTURES_DIR, file); + const raw = fixture(file); + let key = parseKey(raw, passphrase); + if (Array.isArray(key)) + key = key[0]; + const result = { key, raw, fullPath }; + cache.set(file, result); + return result; + }; +})(); + +function setupSimple(debug, title) { + const { client, server } = setup(title, { + client: { username: 'Password User', password: '12345' }, + server: { hostKeys: [ fixtureKey('ssh_host_rsa_key').raw ] }, + debug, + }); + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })); + })); + return { client, server }; +} + +module.exports = { + fixture, + fixtureKey, + FIXTURES_DIR, + mustCall, + mustCallAtLeast, + mustNotCall, + setup, + setupSimple, +}; diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/https_cert.pem b/reverse_engineering/node_modules/ssh2/test/fixtures/https_cert.pem new file mode 100644 index 0000000..49e1045 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/https_cert.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIUPtNIRfp8v8RsObCr+9LVosWVD/QwDQYJKoZIhvcNAQEL +BQAwbTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcM +CVNvbWUtQ2l0eTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIw +EAYDVQQDDAlsb2NhbGhvc3QwHhcNMjAxMjIwMDQwNTM1WhcNMzAxMjE4MDQwNTM1 +WjBtMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTESMBAGA1UEBwwJ +U29tZS1DaXR5MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQ +BgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJ/m96/mBMFoUWUOFSvvmJjHj/XxnO89ClCcCIFA6bJNCJMFZV3m853HAhP9g3kF +M3hL0c96GKS5IsRJiNUMrIUYrWCPh1yUJCNfczyGbBJNcEoRhfqCuuzjA5U7jAil +jqLWBP+ZI0tKRuQXX4bDHp51qDESscxNHZQp0+Lho86y4XjZPnT1OYd5rl3D6D82 +AElOrGOtsj7KmHl3eYhQoKNDlCGa5ZK+L05rsClU5m/LXyGmf5QtOIF00JqJ7KS4 +mX3ZF+XE/+3gkXLJyOCOYFDLjGY7WjsJXz3Wm6pktW8NGqhMaaRfIINqtCQkDgMk +gTjF3TtEA/M2DsGU2edL3qm/ibQ4z88dMVkLGZ6DWZg5oGwZR0W8jRAauhWO01Qq +JSLF3Rhvj4VasF4Hj6sI2HQcgGlDFqPNs/ErTA91mN/+yzXzCYIGBUeF5cSbIsLL +TNo6fCHKRIYqpHYCQjwBYQh/2R4/o/BHHkePVWDN0dg2VAyrp/YhV3YTfs3M4ond +yx2CoW1FJHPlhsmGH3A6PlWe2dRgu9f0ZejOX+eefqkkJtrVbmxfVCB9KET7TrV1 +lBX/V6bnFwmT0fygeBHd0aR+h8dvIs3E/wovLp4MZjtT97p+IMcGUcH9AmbFlXgi +VOnYx4/3WLuqGpyurDaCWwJDmtdCDoclZeZ3ef+IEi3/AgMBAAGjUzBRMB0GA1Ud +DgQWBBTQsY4pBOEhu4+hJb5KqaxKNBMPLTAfBgNVHSMEGDAWgBTQsY4pBOEhu4+h +Jb5KqaxKNBMPLTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBf ++YfOSlOw79aCdtU40OH51QFJxuK54ryxpzRcpBeDE57HfnuNHAM+z+5xVu8+qaRn +jo27ylmLLmzlWV946Yb+fyxIZb37KNXiIYehPTYyiG9MYmE3kEH/kLEvU8SQ6zO5 +6CVP3RN+HP1ZdgHi4Zq6DLsngr/ma8nAXuRUgsvLogB2yrtTJTlMB5631ahdD3U8 +kInPa1FlWYjq0QvllzMJ2q/uUG8kMLZRArqKMxb6j5hqHZuA2PAhb1h2K54doOWt +26HdGPVBxZcnE7HUUqKMAxAf++vmYicDTSv6rsEONxmG9cn0SQWzUnr3G6zZ4uxF +9wlvl5/VN6jT9XtS9rpZfwOVLigmuhMFkUCxTTN0eHOh0u76QSk2nphxumIj1vc+ +I9G/KNk0R3G+7AyjDK2WIxaqUTChpBfytQoiiQCOYEL+KlJboWhYL7mfeBT2flzH +H3/LfF61Y8V2H5pjX1x+e/FghA5OFiHsrgoJVegVYu6v0JyCzNwGaSvnpu8QZcOZ +lT6d4UKS8JmIuq2w7iru6cURBRzMfBZ4qaX3Gm/NSDfi6q/8aL/mogzQHg91lrFz +AXZUkb+WGikJ6TEgL9M4qBHwgssk7ayEejBhIuLxQD654Py8P8diEt/77iY0qsS9 +EEw/onPXr9nLLeIcigQEa2+14msAb2I7a2/RhlUW+Q== +-----END CERTIFICATE----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/https_key.pem b/reverse_engineering/node_modules/ssh2/test/fixtures/https_key.pem new file mode 100644 index 0000000..3be6a97 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/https_key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +k77w3OGObcFv4zxCOoFxcXXc3MCyw3r8 +-----END PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa new file mode 100644 index 0000000..a8722ab --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH +NzAAAAgQDg+DsMAituSW/NJpWVy2w7xN6Uu/IfCqpy38CFBW+mBnOX7OzPulI+1uZxXRLy +UKiQDAegXCqSHMCo5ACZhw2BRwq74J4VA5fOFGdwcacTQo1zKDF64wvyVSgQE/E2PSFLKu +NHHtRFnjvq6WrgTQsL9aif2FBWS5q0MGahzXhNkQAAABUAn1ASRSRcIVsWqrrZubFQq4pU +OlMAAACBALcKIRLTtYG5+N/vzEULdsXSGToDRth6X5Yjb7c0UotAmy9VGrnmN5IO+//1em +2USHeSoO+5shRq92zdggdQwNaXXzU301huIETztfRwGHOfUGZbzJmIqdzLhdziFhneAzaN +zVeUFyIqvWL1Q89WgC2Uh3DY/lK/gIhRK7WD0cDAAAAAgC882WUEEig48DVyjbNi1xf8rG +svyypMHSs2rj6pja2Upfm+C5AKKU387x8Vj/Kz291ROIl7h/AhmKOlwdxwPZOG5ffDygaW +Tlo4/JagwP9HmTsK1Tyd1chuyMk9cNLdgWFsCGGHY2RcEwccq9panvvtKp57HqDaT1W7AS +g2spT9AAAB8G4oDW5uKA1uAAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS7 +8h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl8 +4UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHN +eE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOg +NG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4g +RPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtY +PRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP +8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYW +wIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0AAAAVAIoWASGAfFqckLwvtPRNCzow +TTl1AAAAEm5ldyBvcGVuc3NoIGZvcm1hdAECAwQFBgc= +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub new file mode 100644 index 0000000..d5b662d --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHNeE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtYPRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0= new openssh format diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub.result new file mode 100644 index 0000000..7b8d66e --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "new openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8K\nqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUD\nl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZL\nmrQwZqHNeE2RAhUAn1ASRSRcIVsWqrrZubFQq4pUOlMCgYEAtwohEtO1gbn43+/M\nRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2C\nB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVD\nz1aALZSHcNj+Ur+AiFErtYPRwMADgYQAAoGALzzZZQQSKDjwNXKNs2LXF/ysay/L\nKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PK\nBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnse\noNpPVbsBKDaylP0=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHNeE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtYPRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0=", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.result new file mode 100644 index 0000000..0d93248 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "new openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8K\nqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUD\nl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZL\nmrQwZqHNeE2RAhUAn1ASRSRcIVsWqrrZubFQq4pUOlMCgYEAtwohEtO1gbn43+/M\nRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2C\nB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVD\nz1aALZSHcNj+Ur+AiFErtYPRwMADgYQAAoGALzzZZQQSKDjwNXKNs2LXF/ysay/L\nKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PK\nBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnse\noNpPVbsBKDaylP0=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAOD4OwwCK25Jb80mlZXLbDvE3pS78h8KqnLfwIUFb6YGc5fs7M+6Uj7W5nFdEvJQqJAMB6BcKpIcwKjkAJmHDYFHCrvgnhUDl84UZ3BxpxNCjXMoMXrjC/JVKBAT8TY9IUsq40ce1EWeO+rpauBNCwv1qJ/YUFZLmrQwZqHNeE2RAAAAFQCfUBJFJFwhWxaqutm5sVCrilQ6UwAAAIEAtwohEtO1gbn43+/MRQt2xdIZOgNG2HpfliNvtzRSi0CbL1UaueY3kg77//V6bZRId5Kg77myFGr3bN2CB1DA1pdfNTfTWG4gRPO19HAYc59QZlvMmYip3MuF3OIWGd4DNo3NV5QXIiq9YvVDz1aALZSHcNj+Ur+AiFErtYPRwMAAAACALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAopTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3VyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0=", + "private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBvAIBAAKBgQDg+DsMAituSW/NJpWVy2w7xN6Uu/IfCqpy38CFBW+mBnOX7OzP\nulI+1uZxXRLyUKiQDAegXCqSHMCo5ACZhw2BRwq74J4VA5fOFGdwcacTQo1zKDF6\n4wvyVSgQE/E2PSFLKuNHHtRFnjvq6WrgTQsL9aif2FBWS5q0MGahzXhNkQIVAJ9Q\nEkUkXCFbFqq62bmxUKuKVDpTAoGBALcKIRLTtYG5+N/vzEULdsXSGToDRth6X5Yj\nb7c0UotAmy9VGrnmN5IO+//1em2USHeSoO+5shRq92zdggdQwNaXXzU301huIETz\ntfRwGHOfUGZbzJmIqdzLhdziFhneAzaNzVeUFyIqvWL1Q89WgC2Uh3DY/lK/gIhR\nK7WD0cDAAoGALzzZZQQSKDjwNXKNs2LXF/ysay/LKkwdKzauPqmNrZSl+b4LkAop\nTfzvHxWP8rPb3VE4iXuH8CGYo6XB3HA9k4bl98PKBpZOWjj8lqDA/0eZOwrVPJ3V\nyG7IyT1w0t2BYWwIYYdjZFwTBxyr2lqe++0qnnseoNpPVbsBKDaylP0CFQCKFgEh\ngHxanJC8L7T0TQs6ME05dQ==\n-----END DSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc new file mode 100644 index 0000000..392f214 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc @@ -0,0 +1,22 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBgJ5gXYn +/2IFE2+CrAxYR8AAAAEAAAAAEAAAGxAAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz +0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0 +w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vy +k1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/pr +s7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n +/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0Yue +nUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQT +mYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlR +hBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQAAAgDIGP0oYyi7sTk0HdU9 +uWZLaDhHpW4Z8xTzfgUDbxoTYQ2igO90O32vSqW/cC2QKWTFuPCFnsCerHAIGzX/eyxlCQ +VyNa7VrhbNjIKAHBF3XMcRVRbW2SdYq8tHSkeZHr5EuO5dRfJ7wsR8flkPb4O4viNlIbvF +Ake8dsZEOhcnVNiv+NMR9mTq8l91wR60tr3XiWzCMkEYrJiWOfQuZSvzYi7dUmFxQuEZfQ +vIPkZD3L6XdaAz/r6YAONFAbtUMAOaUxOGV9puSsunSosAvmi+NcJ9iUM2FpAu561gp+Tv +RRcgXHxLGuzTNASiMaTN3M+HenqUh3RWmWauL5wSR7DbrH7Vq47YTnVjtg8xcZnMCfOx2D +Wz775hD6uyLwbkxKMaNMf8p4sOcXsSpHNqKmfkUxQBpNRp6Vg5W+AVaAkyXQng2LRt6txJ +Xv5zBiSFdsobkrWko/ONfGKfG+zVP+LIVcghLpp71GZQX6Ci02vB55pvk8k0G91H3INn/c +t6Q5zY5pK9VZwxjZ29psm7V+FdeD1g8VQ1Rp9muq6zDXHKKyqkBK/oGCM9UhBHFjki0gBR +v6LY/iXsz/eG14svhLjM5zYFSX7jUOI9b/PnhhL7Mos4wguHN2EjfGWuC07PkkqDPoqSwn +cC91OKhub6yqZsqvBz9BcV+2FxVNPNKzRdzA== +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub new file mode 100644 index 0000000..c2b1190 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vyk1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/prs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0YuenUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQ== diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub.result new file mode 100644 index 0000000..d15133a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KM\nIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfV\nHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vy\nk1bw7ske+ImLAhUA517JOoXXp2rC8hPMpSx0hPtF0d0CgYBsMerhmMT0/416hJV/\nprs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/I\njU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK\n6eRJfrZuaq0YuenUa9AuFwnjPAOBhAACgYBwjDUjp9jaJu46eobNK8CWJL/Noi2f\nXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuC\nx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/\nC2XBGgEuRdgyqQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vyk1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/prs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0YuenUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQ==", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.result new file mode 100644 index 0000000..2271c47 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "new openssh format encrypted", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KM\nIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfV\nHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vy\nk1bw7ske+ImLAhUA517JOoXXp2rC8hPMpSx0hPtF0d0CgYBsMerhmMT0/416hJV/\nprs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/I\njU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK\n6eRJfrZuaq0YuenUa9AuFwnjPAOBhAACgYBwjDUjp9jaJu46eobNK8CWJL/Noi2f\nXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuC\nx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/\nC2XBGgEuRdgyqQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAPKhVnFGWb0KLibdYnJz0RwFy/mt98KMIdByHKQWRm9UjoVJk1ypuQpnj+bqFnxCzCFSU9OUj0/Xe0Wuk+kF2BtMO0w+ZYfVHCqEaaIJ1D/iLqi8aBbYs552l9+P0DsFUlTE0D/AvKTQ2PsztFq7wHUTQVmnj4vyk1bw7ske+ImLAAAAFQDnXsk6hdenasLyE8ylLHSE+0XR3QAAAIBsMerhmMT0/416hJV/prs7crOX0e0gF8C7kar/ILj5WULX7k143+4lgluoogrPXbd5fXgOnqdQawow8a/IjU62Sz6n/qfHLJtQ2sJOK2Vkj5NF2UCcRHrewqJw9nDCS7yYh3c+gUfIBcIRkEJK6eRJfrZuaq0YuenUa9AuFwnjPAAAAIBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQTmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQ==", + "private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBugIBAAKBgQDyoVZxRlm9Ci4m3WJyc9EcBcv5rffCjCHQchykFkZvVI6FSZNc\nqbkKZ4/m6hZ8QswhUlPTlI9P13tFrpPpBdgbTDtMPmWH1RwqhGmiCdQ/4i6ovGgW\n2LOedpffj9A7BVJUxNA/wLyk0Nj7M7Rau8B1E0FZp4+L8pNW8O7JHviJiwIVAOde\nyTqF16dqwvITzKUsdIT7RdHdAoGAbDHq4ZjE9P+NeoSVf6a7O3Kzl9HtIBfAu5Gq\n/yC4+VlC1+5NeN/uJYJbqKIKz123eX14Dp6nUGsKMPGvyI1Otks+p/6nxyybUNrC\nTitlZI+TRdlAnER63sKicPZwwku8mId3PoFHyAXCEZBCSunkSX62bmqtGLnp1GvQ\nLhcJ4zwCgYBwjDUjp9jaJu46eobNK8CWJL/Noi2fXTtFZFgUFRwkr/FXLLsOckQT\nmYxaWcxP4NwuvMyI25tOueM0RvAIR7J3Afc5pbuCx6dIgiOf2gRClQU5OlqhrnMW\n2BQXlRhBKBNMp5LjM5t46KTBkjh/30//s4Kimrp/C2XBGgEuRdgyqQIUSNLlRVPv\nMC3Q3P3ajY1DdZvi9z8=\n-----END DSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm new file mode 100644 index 0000000..38566b4 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm @@ -0,0 +1,23 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA +AAGAAAABD01pNY1+DTCAHuI6mcjB0YAAAAEAAAAAEAAAGyAAAAB3NzaC1kc3MAAACBAPLA +N0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJ +iP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79s +ZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYf +EThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrL +OnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/q +MsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pS +UiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjL +qLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxsAAAIA +PDupGK4wMtROtFZqo7vduzkHJuDrE/tAwGqiD2pKMova7WaKM0EUznwcl3gtmhHvFeY+NJ +3Uc9sQcX/9n3y6NAYsC+eZeqe7Sy2GWVyqxOUJHpZqfsKYJidG61TBgKgx+JXAeidYdz4L +4cEapwwocOptbY3ZRFmszekq5xPomnkP9DeSQG6l4eYSv7OpeAHlFj2KCmJMVEZDOl6RyJ +KCqOpfEJIIVoCmna/hQdd9ptLVFmbX/VShgLjvUwfBggJtZNPb5jx+PMy+I0ylywaCIG5K +JQAqust6dzFBx3mBoO4kZPBHlb8XwQ4HYLYph0Ur/lINsHrpLxgmtEw7zzs73Nshl6go2V +uvBtcZ5ywAMk+8CLP5ZgpiGBxlMtFGowp/5zuJxRpc9FgdfxnnVWDyzcQ/YvX9lwzb6cNz +bXeLPsKjOSLPV7G/RFIiuCAOa97ZCM8Ho4FhdNYOGilmjuxV7FJiTc7KP2r+Wh3oxsV7AB +Q6Thj06b2mX3iE4hqLaMKIVE1zs22nMlUtFJv8YY1ZWBihUVlnR9vWgIH7ODoZOwNWBlLd +Qfyfi8w3KgJWj5oVNAM7WniNFQjfNxEbrPklfYg93deVE/LhPghs9I7fsIeHY/p8GtsO/S +amTcjkYi6pUuT8m7IeFYQ8cWvGnbaYz6/9+ni+0aoUL93GKHQw1+mBUVuswVZXBF1WVCf+ +LMgZ +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub new file mode 100644 index 0000000..d9eb1a5 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYfEThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxs= diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub.result new file mode 100644 index 0000000..6a918a8 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASsGByqGSM44BAEwggEeAoGBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4Yw\nCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5\nGGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5A\nosJr7v5twVftAhUAuQBrIqBygHNgndkMCi1GUpg2QFcCgYBxYfEThMIXPQkSer3s\nnKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1X\nApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMs\nMu2RSKkK6f08J0vsESnKU4nmnwOBhQACgYEAxH8NZyntzihIAHnx1Lbo7h1sPi4R\nhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3q\nhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi\n7GdZG8Q0tuyfXxs=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYfEThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxs=", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.result new file mode 100644 index 0000000..27ae40b --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_dsa_enc_gcm.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "new openssh format encrypted gcm", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASsGByqGSM44BAEwggEeAoGBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4Yw\nCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5\nGGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5A\nosJr7v5twVftAhUAuQBrIqBygHNgndkMCi1GUpg2QFcCgYBxYfEThMIXPQkSer3s\nnKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1X\nApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMs\nMu2RSKkK6f08J0vsESnKU4nmnwOBhQACgYEAxH8NZyntzihIAHnx1Lbo7h1sPi4R\nhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3q\nhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi\n7GdZG8Q0tuyfXxs=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAPLAN0jFExSJiCvw7p2W2v5tqvXIG4YwCglrl2wnGOMBGmfaeIcxZErzW00hOxq+NvDIlK43kJiP98Vz0XTHIW6DpkE9DcC5GGA6nDZn9L+BSrBL8NhuBlz2ekgWOTCqnDC7Il/iyUCMi79sZPOEg/bMExWJlB5AosJr7v5twVftAAAAFQC5AGsioHKAc2Cd2QwKLUZSmDZAVwAAAIBxYfEThMIXPQkSer3snKJfDz0uvc1y/6htsjXLk93TAAi3LSD2dGqYs5s0WfzO4RnFso0EovrLOnIbqU1XApr6CPKAVX2REsXFWWF3VixEHIEF1Q9gIvHdYgAxSxtwYvOPpAwDmaPxWeV5/qMsMu2RSKkK6f08J0vsESnKU4nmnwAAAIEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyWENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4un8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxs=", + "private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBuwIBAAKBgQDywDdIxRMUiYgr8O6dltr+bar1yBuGMAoJa5dsJxjjARpn2niH\nMWRK81tNITsavjbwyJSuN5CYj/fFc9F0xyFug6ZBPQ3AuRhgOpw2Z/S/gUqwS/DY\nbgZc9npIFjkwqpwwuyJf4slAjIu/bGTzhIP2zBMViZQeQKLCa+7+bcFX7QIVALkA\nayKgcoBzYJ3ZDAotRlKYNkBXAoGAcWHxE4TCFz0JEnq97JyiXw89Lr3Ncv+obbI1\ny5Pd0wAIty0g9nRqmLObNFn8zuEZxbKNBKL6yzpyG6lNVwKa+gjygFV9kRLFxVlh\nd1YsRByBBdUPYCLx3WIAMUsbcGLzj6QMA5mj8Vnlef6jLDLtkUipCun9PCdL7BEp\nylOJ5p8CgYEAxH8NZyntzihIAHnx1Lbo7h1sPi4RhcpKK5pSUiaKoWxkjseqUsyW\nENt6DTByIdGhBNrOp9/vw2R5CSUkxuI0TlI8bj3qhq/B3bspx1GWjLqLfKbeVi4u\nn8CrooRRq2g8+nYLu2EWbF/56pEEzws6DptlDJQi7GdZG8Q0tuyfXxsCFG8ERflm\nOIBFUymTHP8ZeVOgNm/1\n-----END DSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa new file mode 100644 index 0000000..114e078 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTjIb0On/AzYDLFRi+g3fGdAIF72KFG +iZBpP8oKZ8bsncH9ULtVV9517cNcRNuDETQtvLqoCdIn7TipYo8Jv/lKAAAAsA6ULqEOlC +6hAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVG +L6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+U +oAAAAfVd3jjve28r7FhY6Uo//cKIM1rBeWZG16b8bjyVyFswAAABJuZXcgb3BlbnNzaCBm +b3JtYXQBAgMEBQYH +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub new file mode 100644 index 0000000..8ebee0f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVGL6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+Uo= new openssh format diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub.result new file mode 100644 index 0000000..b430d73 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "new openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4yG9Dp/wM2AyxUYvoN3xnQCBe9ih\nRomQaT/KCmfG7J3B/VC7VVfede3DXETbgxE0Lby6qAnSJ+04qWKPCb/5Sg==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVGL6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+Uo=", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.result new file mode 100644 index 0000000..4affa3e --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "new openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4yG9Dp/wM2AyxUYvoN3xnQCBe9ih\nRomQaT/KCmfG7J3B/VC7VVfede3DXETbgxE0Lby6qAnSJ+04qWKPCb/5Sg==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOMhvQ6f8DNgMsVGL6Dd8Z0AgXvYoUaJkGk/ygpnxuydwf1Qu1VX3nXtw1xE24MRNC28uqgJ0iftOKlijwm/+Uo=", + "private": "-----BEGIN EC PRIVATE KEY-----\nMHYCAQEEH1Xd4473tvK+xYWOlKP/3CiDNawXlmRtem/G48lchbOgCgYIKoZIzj0D\nAQehRANCAATjIb0On/AzYDLFRi+g3fGdAIF72KFGiZBpP8oKZ8bsncH9ULtVV951\n7cNcRNuDETQtvLqoCdIn7TipYo8Jv/lK\n-----END EC PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc new file mode 100644 index 0000000..08fe2d1 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc @@ -0,0 +1,10 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBqNbb13W +CKfO7B1vpwJDwbAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz +dHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTp +r+04Ebm1fkyp8RgpFsmvLXLt/dKU0AAADA86k3lHnP6pfD977mwEtKxHOJm44wx8NsdBwN +mNLqxlxUE520nsXjDgpgNU0MF9JDnc1kdhSy8PcdTAAH5+k6bpf3gotPrltPUBMFQdPqst +5kVS7zOgaxv1qZnlyhOqEdNR3Hee09gJByRrAojtcs+sPI7Nba879NPMb5c5K+gKhONHsa +wLAnz66eFQH5iLjd2MwrV4gJe0x6NGCSI2kyzNlxFsoIl7IcHlJHyyuaSlEOFWQJB8cbB4 +BVZB+/8yAx +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub new file mode 100644 index 0000000..3d87cb2 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0= diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub.result new file mode 100644 index 0000000..dcca403 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmJuPPvO8/8SExmtb8kN0q9iCIQBM\n1Qox+DY05XEqV/755NHKksVzV2hOmv7TgRubV+TKnxGCkWya8tcu390pTQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.result new file mode 100644 index 0000000..9fe2c73 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "new openssh format encrypted", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmJuPPvO8/8SExmtb8kN0q9iCIQBM\n1Qox+DY05XEqV/755NHKksVzV2hOmv7TgRubV+TKnxGCkWya8tcu390pTQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLFc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=", + "private": "-----BEGIN EC PRIVATE KEY-----\nMHgCAQEEIQDG2nALLBBmkBnw1QvdW4ClRfF3Zl3CcRHujsYz9CLvf6AKBggqhkjO\nPQMBB6FEA0IABJibjz7zvP/EhMZrW/JDdKvYgiEATNUKMfg2NOVxKlf++eTRypLF\nc1doTpr+04Ebm1fkyp8RgpFsmvLXLt/dKU0=\n-----END EC PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm new file mode 100644 index 0000000..84178ba --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm @@ -0,0 +1,10 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA +AAGAAAABAHURyWtYwqVbjholNpL6opAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlz +dHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDx +XcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsUAAADAFqKM/ylVkJ/ZA40ZROrW +LNgrttf2+lpVkADwXWzhuESFPPzERKlbHVsVtbiiYmPkLnY1s5VM4zXIj7xyO9YNA9KcM5 +GHOKUL2/NmDaTyGgc9s3BGu/ibpjSeOd1rtGAB4cw1s9ifbXBQd3qDbqzaEmovs3MGaGHD +c3VagdxhsppjrPjZ+B40Pzs9QkSGutsSJDpH9wVIu4OLr89TquTU3PVACDRU03lPPENVbt +rh2IMJeEQyNINQHtfVwordj8LMOEsBjyQ1aqHNva/iKyTBiw== +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub new file mode 100644 index 0000000..61b0b99 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDxXcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsU= diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub.result new file mode 100644 index 0000000..1078648 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEz6mlrA3G+R0ds5oHfKCxG55N0gqJ\nP45CQAf/kukPFdwPqLkBHxP++sKxn3/L7wbFTyCa+DhSzOvosN9pAFmexQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDxXcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsU=", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.result new file mode 100644 index 0000000..626aedf --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ecdsa_enc_gcm.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "new openssh format encrypted gcm", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEz6mlrA3G+R0ds5oHfKCxG55N0gqJ\nP45CQAf/kukPFdwPqLkBHxP++sKxn3/L7wbFTyCa+DhSzOvosN9pAFmexQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBM+ppawNxvkdHbOaB3ygsRueTdIKiT+OQkAH/5LpDxXcD6i5AR8T/vrCsZ9/y+8GxU8gmvg4Uszr6LDfaQBZnsU=", + "private": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIHQfJ+4ZNcwSBaCR5kwrR6HjUsTF//R1F983RSTR8vbJoAoGCCqGSM49\nAwEHoUQDQgAEz6mlrA3G+R0ds5oHfKCxG55N0gqJP45CQAf/kukPFdwPqLkBHxP+\n+sKxn3/L7wbFTyCa+DhSzOvosN9pAFmexQ==\n-----END EC PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519 b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519 new file mode 100644 index 0000000..7ae3165 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCyOMGts0WaAdug9NeXbGn2Jrt4wwiO64dumxV2a1IgKQAAAJBOfs+eTn7P +ngAAAAtzc2gtZWQyNTUxOQAAACCyOMGts0WaAdug9NeXbGn2Jrt4wwiO64dumxV2a1IgKQ +AAAEBgQKxJoToGE/Xi4UkYR+FXfin4jG8NTcZ13rJ4CDnCfLI4wa2zRZoB26D015dsafYm +u3jDCI7rh26bFXZrUiApAAAAB3Rlc3RpbmcBAgMEBQY= +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub new file mode 100644 index 0000000..c85c7d1 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILI4wa2zRZoB26D015dsafYmu3jDCI7rh26bFXZrUiAp testing diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub.result new file mode 100644 index 0000000..3c9ca29 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-ed25519", + "comment": "testing", + "public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAsjjBrbNFmgHboPTXl2xp9ia7eMMIjuuHbpsVdmtSICk=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAC3NzaC1lZDI1NTE5AAAAILI4wa2zRZoB26D015dsafYmu3jDCI7rh26bFXZrUiAp", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.result new file mode 100644 index 0000000..705fa99 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_ed25519.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-ed25519", + "comment": "testing", + "public": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAsjjBrbNFmgHboPTXl2xp9ia7eMMIjuuHbpsVdmtSICk=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAC3NzaC1lZDI1NTE5AAAAILI4wa2zRZoB26D015dsafYmu3jDCI7rh26bFXZrUiAp", + "private": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIGBArEmhOgYT9eLhSRhH4Vd+KfiMbw1NxnXesngIOcJ8\n-----END PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa new file mode 100644 index 0000000..ccded2a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEA4q6eZdx7LYh46PcZNcS3CnO7GuYsEJZeTj5LQSgp21IyTelaBPpr +ijnMwKa+pLQt5TEobpKFFNecPdT6oPoOKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHM +BNkoTFeGrursPkqYRJ0HL4CqYqRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKb +zibJc64JFM7tUoK6Vl64YiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs +8zjxsf6c6N2tKXkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38 +KvTx3wjNQwAAA8hLhVBxS4VQcQAAAAdzc2gtcnNhAAABAQDirp5l3HstiHjo9xk1xLcKc7 +sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+l +fQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg6 +4MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u +2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28 +uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1DAAAAAwEAAQAAAQAmShSbZBiyYkD6KPLr +MCUy8MWED6kVzDB1yvPvN5eKYmH44xe/i4UqvgSl7gR50a2G7zzDIKC2Go1brGQBWPuXRa +ZtOjQygeD4rMHBiH/b7zfy4pQyKDfITTHOFXWE8ERiyL00bAZt09icCy92rQaq8IY/+U56 +sPPJH9UAYG9nEev8opFjAWToFDu0U2+dC+lbqLlXDqDRo75NlnDFmgUoja3y2eFr9A0Cc+ +hjecrdxyJFsCJfEfaLWtBnZb886gqzzvfbHImSQtBAKERcSxuki7uxMoP67g3iQOXa65uz +8kFWRNmbQTGQttakoUaybh1t9eLpBqvVON/4Kg0THShRAAAAgFBTz2ajBK/R/crOSL9VK1 +f7oQv2iJTRVfnUs0r+qPGgf/a/5UwkGRj0KfEWBp3qYD+keShnPr6PDPFrm8UmIdUX8AY7 +3tWT2K/JQVlzJNuINsw+DNjn4M17Z25q0LPmReRWL0nRc2w6W/hmQ/Jmqz6w8Qc4+xpeqS +/HG5feliVnAAAAgQD90a+5Ky3o/2YtueqRf/3dKoiMgGB7JAOzye4dDKGABSlWuQ4N4xEI +CW5MSTp7i/uobTF/tyFO3tTSyb5b2Xwbn/kLO0vgvFCdUGR2BQfN3mcT92T0Gn3JDF3Wym +i2mgU6qnPf+eu+RKZQ9IiyNGny61ROUQa0R0z0pgiAfA89xwAAAIEA5KE9i6hHmigJwfD7 +/AGI4ujyWIVpNyrTdXG3HAPhsdoFuG5ggHggrPuuBF9wNcosrhL20VNOQGHg15gWZIVudu +0qxky4ivQs67Sk9XUjuvTnf+VubM51rIsmh4atKJFSSZo78DEcTRt8aXLrSNvGQ4WPRweM +2Z0YGfMMDM9KJKUAAAASbmV3IG9wZW5zc2ggZm9ybWF0AQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub new file mode 100644 index 0000000..133afc9 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D new openssh format diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub.result new file mode 100644 index 0000000..dd8a8b4 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "new openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.result new file mode 100644 index 0000000..d1ada9c --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "new openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEA4q6eZdx7LYh46PcZNcS3CnO7GuYsEJZeTj5LQSgp21IyTela\nBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoOKKMe6oH/pX0BNyAEB9KFZfZgh0v4\nJ4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYqRdINy1sgDU6jUIOuDD5XZzlpDXb1\nftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64YiPgxsNXOJYMTrelVJYebtsNrJFm\nh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKXkk9G4EDKKip4g0bzDmD/fREPQ9vL\ni59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjNQwIDAQABAoIBACZKFJtkGLJiQPoo\n8uswJTLwxYQPqRXMMHXK8+83l4piYfjjF7+LhSq+BKXuBHnRrYbvPMMgoLYajVus\nZAFY+5dFpm06NDKB4PiswcGIf9vvN/LilDIoN8hNMc4VdYTwRGLIvTRsBm3T2JwL\nL3atBqrwhj/5Tnqw88kf1QBgb2cR6/yikWMBZOgUO7RTb50L6VuouVcOoNGjvk2W\ncMWaBSiNrfLZ4Wv0DQJz6GN5yt3HIkWwIl8R9ota0GdlvzzqCrPO99sciZJC0EAo\nRFxLG6SLu7Eyg/ruDeJA5drrm7PyQVZE2ZtBMZC21qShRrJuHW314ukGq9U43/gq\nDRMdKFECgYEA/dGvuSst6P9mLbnqkX/93SqIjIBgeyQDs8nuHQyhgAUpVrkODeMR\nCAluTEk6e4v7qG0xf7chTt7U0sm+W9l8G5/5CztL4LxQnVBkdgUHzd5nE/dk9Bp9\nyQxd1spotpoFOqpz3/nrvkSmUPSIsjRp8utUTlEGtEdM9KYIgHwPPccCgYEA5KE9\ni6hHmigJwfD7/AGI4ujyWIVpNyrTdXG3HAPhsdoFuG5ggHggrPuuBF9wNcosrhL2\n0VNOQGHg15gWZIVudu0qxky4ivQs67Sk9XUjuvTnf+VubM51rIsmh4atKJFSSZo7\n8DEcTRt8aXLrSNvGQ4WPRweM2Z0YGfMMDM9KJKUCgYB7Yh0b1EOjCdQv0jqWtDNB\n+dUbB6Te92jdUwHvGR7AzsGDqL2OPp0e3QbDCq3lNO0GuN3hCbKlVmj6dpuUpqpP\n+3ni3dZKzwAZGOVdAaEDkGNnL1Hh36bZvqs3KHmymjiEhiuB60mP2mtG2zg/+H6w\nWXlIANdTd32PR87GNohqLQKBgA36ic/LJy2Wuxn/iPicg2kUQxUEey1jUfCBVmfB\nGQCNywG+xem07pKFBNvBlhPD27187VhZFpS7J0snQl89BUcCMzZSpIniagizT86u\nLdQVez4HohvG98zn6SAqLNYpJHXZl0aVShywzIeJ/jbDMTkZpmv6WzNG9p1HjfoO\nhoL9AoGAUFPPZqMEr9H9ys5Iv1UrV/uhC/aIlNFV+dSzSv6o8aB/9r/lTCQZGPQp\n8RYGnepgP6R5KGc+vo8M8WubxSYh1RfwBjve1ZPYr8lBWXMk24g2zD4M2OfgzXtn\nbmrQs+ZF5FYvSdFzbDpb+GZD8marPrDxBzj7Gl6pL8cbl96WJWc=\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc new file mode 100644 index 0000000..09aa65d --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc @@ -0,0 +1,28 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAS8H9Cyk +rueA/Ue6tOb1MOAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs +0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iW +dwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQO +oOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhD +TS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLa +I5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7AAAD4GeinUMcN5H0RP +KnXzIsYGq4rG+pEYNL0WyXCOFnyHzr6cASFYa/ViRVRN5H2dDoc0i2tcQStvDt2AfBxP97 +xbTEmRhLkKW7Sxif+bRRpNt2sO1y7ThufOZ8ZSJdbUYf9nc++k5GMZZUTtkFGhFIyhdyl+ +ZReuQFrc1Fv0/JV0K72uLSMSSMvunFjnGchch98Z1t0jEuiym8AIAwFtlvRpbOOySJhHun +fClEOahNvgzkgpqvviged7Gl9Kh3Fpp57ke1087WUF4hdgG2wuLqRq3Jq2kNvTKVi6+PMv +Kz5cLl6beqAJpbkJCpujzrmffo5NHh94R/v8DbAWCyrkjB6NHjOPIVnKaDmXixkcJ489W3 +PQF0kZ9kLrNU2yP1hBLjikr1zollw6xXC5eEpUsIrNcAHrofTMCMsGKuZhlEgTNe0cEATp +ycxi4gHdA6kNSDnMPwOv9rLDZDkgqCqIzxjZCWabqRHwiyoN3CrdDsJNrk8jSqF5epuzXA +EjrPUvu+sgFHIWDJOij+HQCvCgmdO/W7NkL/xCEx6QagjoJhapGICnq6CXPO5vBQeK7AMV +KWUPB1jdxxlHdrSUYU9v11j0SPUM51AMpWA89GZmuQbe/tK14W35VjtL9aGKsz9Ubio029 +O23HJXMxM9Dd6EYXAR9xMLFDTcLT03kjRlL/4XFS4fJqbTGDtuQNqRO3QK/myVAYjgnXwz +X1s77WeIK3sOMwTIXaHReUiQ1Cw+WmkXOhefePT+HrkyDlJk3ikgPUy2s5QW5/d6Lmolwb +mcS9JUfaai0ysP3v1bew8go/IHiUD/X9AkjkKM2kfS1NcPSi18r2721e6RqZiIHxSoyKvq +yUmwiS1kUklSuhlTORBvbclbv4HTwp1iJfu/6zsMqVJc2E8H6WUw3kTeh9fhDMpTY5NArF +KD2aRIYHFvOKav+0vSbQ/KqmKeiTvyZaV7q6giRxVLxBddl4+ucD+FybPJZSebRQ+0QT1j +aUDSpp541zW0rX7sCiZ6sFUybCPVDM1uA5gTAP015OD/FS342gi+Y04K0jBSjlApuy6BQx +sMEQbR3weMmnodbhCtbcgDZDagSFNPlDud0GJl9IWV4hO/K1f9a+Ox3G27Jq4YC2PFgTDb +aYib4xAXPUHJpoWsstSjpMnfgKcS3AGRdJ/jxlKRWV/NXFf4DYIwpzITqFMF+4VqXCa2AS +JWOcSxOK92UqCcZEs8RED3x9dF9E2yBBwHeuwDvH3c9x/nsM/cjDY+EE9VcEUOxF6qMOhO +CiRtEihEAYM46XeFzcSOQrwWPcKu3WTv3IpnzTaofBxV065CUn +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub new file mode 100644 index 0000000..0e80f0f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iWdwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQOoOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhDTS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLaI5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7 diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub.result new file mode 100644 index 0000000..ee0fd94 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIQogj50bNLnGXsp96TW\nCjet3VaMWzAeGM47O4L6O1yg28v+hl6FPwhUP0Pc10cUWZhYJTGIdqTg/IlncKSw\nXXfhph2+GuscSraD6c9fsgj2L4up18yjztwfVm4PHbU6Vdt5fDGQ8UkVEPRyJGB0\nDqDoycfwGjHWch2T/nmCu1Kpl9fnbQs6+b7y8hAAca7KBcR/6Fv4ijunA5k8aDMh\nZfQ31IQ00u3C9TlQbpUgWr92iT8Y7AhCLOjhPeMCyXxbWQD3uBqllnAu7htblC+T\nLstjfkn1xzhy2iOZ9b6M7e5SDuU6r8pHKk8YqSm5TFuGOyMJYYdGCiccx9yifkJJ\n+wIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iWdwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQOoOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhDTS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLaI5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.result new file mode 100644 index 0000000..a0f0fed --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "new openssh format encrypted", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIQogj50bNLnGXsp96TW\nCjet3VaMWzAeGM47O4L6O1yg28v+hl6FPwhUP0Pc10cUWZhYJTGIdqTg/IlncKSw\nXXfhph2+GuscSraD6c9fsgj2L4up18yjztwfVm4PHbU6Vdt5fDGQ8UkVEPRyJGB0\nDqDoycfwGjHWch2T/nmCu1Kpl9fnbQs6+b7y8hAAca7KBcR/6Fv4ijunA5k8aDMh\nZfQ31IQ00u3C9TlQbpUgWr92iT8Y7AhCLOjhPeMCyXxbWQD3uBqllnAu7htblC+T\nLstjfkn1xzhy2iOZ9b6M7e5SDuU6r8pHKk8YqSm5TFuGOyMJYYdGCiccx9yifkJJ\n+wIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC8hCiCPnRs0ucZeyn3pNYKN63dVoxbMB4Yzjs7gvo7XKDby/6GXoU/CFQ/Q9zXRxRZmFglMYh2pOD8iWdwpLBdd+GmHb4a6xxKtoPpz1+yCPYvi6nXzKPO3B9Wbg8dtTpV23l8MZDxSRUQ9HIkYHQOoOjJx/AaMdZyHZP+eYK7UqmX1+dtCzr5vvLyEABxrsoFxH/oW/iKO6cDmTxoMyFl9DfUhDTS7cL1OVBulSBav3aJPxjsCEIs6OE94wLJfFtZAPe4GqWWcC7uG1uUL5Muy2N+SfXHOHLaI5n1vozt7lIO5TqvykcqTxipKblMW4Y7Iwlhh0YKJxzH3KJ+Qkn7", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAvIQogj50bNLnGXsp96TWCjet3VaMWzAeGM47O4L6O1yg28v+\nhl6FPwhUP0Pc10cUWZhYJTGIdqTg/IlncKSwXXfhph2+GuscSraD6c9fsgj2L4up\n18yjztwfVm4PHbU6Vdt5fDGQ8UkVEPRyJGB0DqDoycfwGjHWch2T/nmCu1Kpl9fn\nbQs6+b7y8hAAca7KBcR/6Fv4ijunA5k8aDMhZfQ31IQ00u3C9TlQbpUgWr92iT8Y\n7AhCLOjhPeMCyXxbWQD3uBqllnAu7htblC+TLstjfkn1xzhy2iOZ9b6M7e5SDuU6\nr8pHKk8YqSm5TFuGOyMJYYdGCiccx9yifkJJ+wIDAQABAoIBAD1UXX1p5iSVRHvk\nttWLOdsfHCA7DPSJpfD5/wkwZkozq112czqxu3WzNv1SDaG3zSYMyvhmsfevUka2\nSQG7gmkWHEIXwQYu4Qhpcmb5gS+BfN4g+MNtHwmoUUWkDqTilbTi7xX5ZicpWIIo\nlI3DF16++JzUwAc1mYeMmd4bF+3quh93xW7hhrcQ31+D9kzqt6nLG1d9+IVpMbhD\nnNB9zapkZHwnz6YYhb5waMOHr6U902TyGgKyjq3Z/PkMJ0zKg01roUtQs9oQOIZF\nvueF2hwyzHqeIgpqhWJl9HMpfdym6Lh2lwguK3KYwNIMFQg+gNBWruYlH6SGfylq\n0wB5xIECgYEA8FdyEDd4TbVBKIXzzmY6zYmN/Q9uiz0IjbeYYzuRxZ4a7stE/t8n\nM5UxxkqeD8rtRAQJyFDGPAhFeeOpIfzEVPG+5s72pI69+9aE/gCGA91+sOSnLoiJ\nPW1I7SouZfCeaaRQxSSIMjsCea2s6yraujGZJyPEWSkG5TijY8+vzDsCgYEAyMxX\nCYvqlRTaT5lAkRTFLqf0/NSpRoCnG7qSPUyJjxJsVfYFLv1FZCyyrA+SaIyufjoT\nKutKE31r7wre5bkjRRenIcTkR/tdNRdkWsB/ysZ9Cp43FIPTXS5gxTQxOaJyRGvJ\n9MW0m8N1pMvPIsagzoxxvzgU9ZOejs2NQ69qXUECgYBq7DxOgp7+0zhdsto4ZLqc\nXinQ/2CKiWiYw6kD3KiJZkFNIxla2iQyiplOQjv3gqvzqmg/uc+3PWbLR0EjYbRm\npfXr8P9BTk+vDky0Q79bUNrgD5lg1lVYApqDCFUD/Pw8u2FDk3EUB7SeNWnMZZBR\nbWdZRkw/7kSnDX+DFA59qQKBgG9v0AHxT4/LEdlJEOczYrcg6TqDfyosbhFaepxg\nZJstO0h9j6TjVGZi1AnfXn59TL2q10ZjbCni2krAerF9DNDkbpG0Joi4PKMhR0WC\nPam4fF6vLZxKCLxW58epzoPQ3p+QPnWEX1ZupFR/84W2PDpFAT+BDUi40y8nbnWY\n3WvBAoGADjh0hEkq3sy6oWt0m1NjGU1yxKV+geg48BFnu2LVSFv1rw1V7X8XFEYl\nP1B3sEpOOpPGuoz+r2E9PrsdMuYNOmVlRFRpe7pm7zyhzdFYBvLE2btJqv1PmxFu\ncEkrXJS/ETxkKdMaoUbYHcKiTIMi2pDrdJtg6oHcipm0yTBZkKs=\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm new file mode 100644 index 0000000..442a4f5 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm @@ -0,0 +1,29 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA +AAGAAAABBJL2YVn88iqv/H9bFiyW2PAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQAB +AAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0 +ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMf +zpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab +9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBU +rzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/AA +AD4Ktd9gUs9KHBmWTVFnDofcB6P1dZJsYHAapQgNXZtx5SjwgfBpP5aBLtSjN1iHFE+3XC +Cofc9UJ8fbytwT7LCEQIzo3KJaOhVzgJN+lrjtFouWsw0Y1q2JONHvvNJ5A9nGjIGbp3du +4TAMSgVAvxZBEYez4ajhb2NL7TE56AjOxW4n/M2ZDJLCo11F3ON3Eq6MirHZMgGKo/lbOc +SaBld7tzqknye+1fKVlnCLyu+v0KCbATBypRsMeX1+E/D8L5cMIgRSe97swqiWeG9yBhQi +xahbWDpmU34nz1cxc9H7KnL1rbbOxrr4OEdMOHNBQjbLlpJpnSJ3XvEGP74zjfd5zMocgx +rnqreMmY+eDEObkw33+XD5ROYJT+SW/zI+r3SeIjS3UPh0ucU5nipBvXfkUezek9i/FN1X +CY7xJnAZGGKU0JSqiVW3JWXp18v8lmo3ACvXeotJfUGkwvJOeO2N4Qb7RTIzivLV5Q5Plf +zHWqHE57UqDL/Ya7SrX1FaqqhOHOlS1mqPQ+/VdsOSP5fJcXN+oKoL7jPr2WlmtFjo8PKc +rpgKC3DhUzvRXnNYotG7trbPOGJbBRgoxTQ06rlChoaBp7kUKqNNBxXhFQCeN0sCb90fHV +c+X3Yy8oUsAIxxmCymuVV8gRzLD6OdqQRBthEUQktNJLhv4mSufwSfsLDluEc7YEOrsJhx +jk57TmkFFyLj++IAKi80FnSkRfSBQF3dTSrBZ4BIHWnek8V6goxhy6lRMaFoTow2foknvr +VHgiNGvimOM3ESYVcOwt3YQqbUG/7b4jRlY3nNBJcsbxGe54B8zaoLt5pQNRxUuHc3fR4R +haWHR6IWsfey7jAlRzrJAVVEEj4d6yvJ4bLqWGmoim5QlrePRuRFyV4FNb8N6hJ9gvWY9f +HUT9TwxArDIMzu4T1khwRoFU45XN0U6xHEPcT/pZ2C5jJSSQ5W/SyBudexjMMPRKf2EIeD +gjv8vIhdtkmxHv7bapaaYeYX5gtKYl+McRollDxVC8Kr48RmOVJnK4aFBQ99Wu7SXDbwas +vcvVHI+zUiRGjU01/CU/Tf4GTodAlmZIuqKmBTX/KvVj6ZiK0BsZuEl9qom+l4rlazaahY +FdL5M4u0qt7rVirWJWgWzmPXZ+MCK0Fs70ORvqRGxVMilhQcWsng3ZXnHaYiBRhk31KqF+ +BEPEh79OknD0okKed2YYfg8vdUR+noENybrsIleP1aKBBmQCNbKU04N/9Su+wxX8YfGhYU +kPST35Wg45zER9gZGsREnON4sQTng9LHB5CrJCo/MowcZG/ycqL1mxemApZ9nYUrjA8HJi +zDwRHHUtkkLNG8Cmyg== +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub new file mode 100644 index 0000000..d5c7685 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMfzpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBUrzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/ diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub.result new file mode 100644 index 0000000..0f00545 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHpo5IWtXPtrOfKs8ePe\nvLL776W8behIi5ckR7qlwqLk3QWXlxrVUZcaZKp5zhNBEzEkEqptXeZNRDGu1VXE\n3lxUGgSHNlxdEtbiKBLzVdCV6Q44iHT5o1BblH/aBhiyikEDH86cpqqIh2EDYbmq\n2HdZkm9PmvlMCsQMRngj3feaPyX1oyjtCU6955xI9Xk47btKaH5nIWm/RwvWGydy\nbL23Uau2dmR6fLrtekn5T6T9gPZfheBzfoDzi3BsW1ZFWR7CyNOzqZFncTDwVK8z\nxfTpwp7UVqAYUOCxR2B5ZU7XfvxPdEF14XtacY/BZLSYmorYs9PRlOYeCFot4rDa\n/wIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMfzpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBUrzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.result new file mode 100644 index 0000000..127ce3d --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_new_rsa_enc_gcm.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "new openssh format encrypted gcm", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHpo5IWtXPtrOfKs8ePe\nvLL776W8behIi5ckR7qlwqLk3QWXlxrVUZcaZKp5zhNBEzEkEqptXeZNRDGu1VXE\n3lxUGgSHNlxdEtbiKBLzVdCV6Q44iHT5o1BblH/aBhiyikEDH86cpqqIh2EDYbmq\n2HdZkm9PmvlMCsQMRngj3feaPyX1oyjtCU6955xI9Xk47btKaH5nIWm/RwvWGydy\nbL23Uau2dmR6fLrtekn5T6T9gPZfheBzfoDzi3BsW1ZFWR7CyNOzqZFncTDwVK8z\nxfTpwp7UVqAYUOCxR2B5ZU7XfvxPdEF14XtacY/BZLSYmorYs9PRlOYeCFot4rDa\n/wIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDMemjkha1c+2s58qzx4968svvvpbxt6EiLlyRHuqXCouTdBZeXGtVRlxpkqnnOE0ETMSQSqm1d5k1EMa7VVcTeXFQaBIc2XF0S1uIoEvNV0JXpDjiIdPmjUFuUf9oGGLKKQQMfzpymqoiHYQNhuarYd1mSb0+a+UwKxAxGeCPd95o/JfWjKO0JTr3nnEj1eTjtu0pofmchab9HC9YbJ3JsvbdRq7Z2ZHp8uu16SflPpP2A9l+F4HN+gPOLcGxbVkVZHsLI07OpkWdxMPBUrzPF9OnCntRWoBhQ4LFHYHllTtd+/E90QXXhe1pxj8FktJiaitiz09GU5h4IWi3isNr/", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzHpo5IWtXPtrOfKs8ePevLL776W8behIi5ckR7qlwqLk3QWX\nlxrVUZcaZKp5zhNBEzEkEqptXeZNRDGu1VXE3lxUGgSHNlxdEtbiKBLzVdCV6Q44\niHT5o1BblH/aBhiyikEDH86cpqqIh2EDYbmq2HdZkm9PmvlMCsQMRngj3feaPyX1\noyjtCU6955xI9Xk47btKaH5nIWm/RwvWGydybL23Uau2dmR6fLrtekn5T6T9gPZf\nheBzfoDzi3BsW1ZFWR7CyNOzqZFncTDwVK8zxfTpwp7UVqAYUOCxR2B5ZU7XfvxP\ndEF14XtacY/BZLSYmorYs9PRlOYeCFot4rDa/wIDAQABAoIBAQCCb7uluxhh7gfy\niTmFfETDvrEzqFfRDJHqadm83/WJeXvg+gY/X+CgEXHGsXDN4j5qzbgjKBBoC9dS\nHxdWA0Z4ShFkH2tZZAYDVIwj4CLVpR9b8bRiZ6wvX71rtzsPFIYf52Tkz1nif3pk\nUaBkoJm5SDkdTmBLjafSXkkuUskeeAV7gx+fzWqSpcKmhTqjnQfdlmD8OSIq4jjD\nagiHmmfBhZ4NOvF/E9UBydqFV8GNyfSFC6kC2LYmiQD1hvqNhMdYVjh99V1L3ZPq\nHMSQVAOv5WgpLTLKY8MFNBbqqp0eKhatRNA8q9O23jADDp3fubKV0aUQSrRZz0y9\nPmmEJnTRAoGBAPZoL+p+AbI5yTg01LdsaQL2f3Ieb3CGudesmjAVnI3QEoC6gxGX\n4cbmBSCY+vBzh2RJNJcS+Rq6VmJZA930Tb0npHiQYOohB7BFOCbBJ2L18g/JdNpi\nVb3wqFs9NG1GFOOV6iGtV/6t4CRTKtAbd695YZAJ5S6DDvMrH9pTnAKrAoGBANRw\nVuLfBTFhSKvFz+0W0yy6Sn0koXjpp1ifC0BWLwHiA/IZjAY7qmsNQZxWdleWLP28\nRNaac3vMJO/HFD4IyL59Zli+kREGKazvZM1dvOs0mgdVMTPMsT57wcJr5OSxqCvJ\nD3NkcgFuA1e3jVC5p/wUJCi/lhyFPx3z1C5vRqj9AoGBANeyYmd5wFBcp1ktXhvm\nqZIvZ2blX5X4ScyTSjHXaUD2qIvJORz4gGqVRl2/rMM5zoYqUwAAWtFb1mynEWyF\nBFwVzLLBaCTrnwhdv4alRK4rL6dEKadVt0ra1PVxgWg6leSXgenTDRli6bfCmdKs\niLuxnIbzMozhqv+Qe4Sp9gKbAoGBALWBThsEpXEtR2PL3P0atU7P0/jcJUIjkCF9\nsaVEfWFEdE6TWTmyHMbeSqKClRX8b3BTPRWGXQj2wNBE7Zya8LkgdyN3noZHF7Bz\n0VJNtq3XAYsmVKWHTCCwqDmu6aAj0iWm4ZabyXRDRIPbhdfk6AvOQZ63IlA34Fd9\nDlqmJF8ZAoGAIJzfMDT2LvlMOHqpKgelS4ZTHEmqqJZM5rXdsZwYqcyekjz25COE\nTJwme3xIt3kSZEcOauGHCgUVeBcE6GwZbQ1WoNIvazhnUXeErOeoxQ+ZqdfC8iyT\nUn/P27yx/FcwDdubQhbgxZ5M+pu+0OQ1WPu02LQZQrX7x4a6isYtTDo=\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa new file mode 100644 index 0000000..f2ae4d4 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvQIBAAKBgQDs+n9ZKhwYNr1V2uGn0C/2MSTM4KB4puy4jR5ubRTT1yq5SbzK +RQlCjfplDN//Eqa6aiFmvGKA3RKUtPtBmD96EHW1mvr7O+Pc8z8L/4zg9tkVQR6V +WBKgBhVwZHDzzs5+Ag2j54BZfcaGMcNGhTE9DcZYeI/t6FhOxgpID3EA/QIVAMyI +czBU74xB48IMoamlEhc5Lh+3AoGBAMuy2h9K9+oQIPcTcsD/mtmhOYlw2ZPCJV2b +WFeZ3QxAujenBzEp0oqht8tdj+BE7Er+CWT2Ab/A92MrjYUaGaPjdF5+K6CSPMUX +rK8nBabSBJ+ELqTo/8vHJ2eVWIUJBwCzbw3ryitH7LD3gyEr2NuQQJE++wyWPBHK +M3SFOft6AoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFycz +bUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/ +xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvWAhUAr/vy +ahuEz4UFGhB8IIeLWQUO5FA= +-----END DSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub new file mode 100644 index 0000000..a7fd375 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs749zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3oWE7GCkgPcQD9AAAAFQDMiHMwVO+MQePCDKGppRIXOS4ftwAAAIEAy7LaH0r36hAg9xNywP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuNhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeDISvY25BAkT77DJY8EcozdIU5+3oAAACBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvW old openssh format diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub.result new file mode 100644 index 0000000..05f8140 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "old openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBuDCCASwGByqGSM44BAEwggEfAoGBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim\n7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs7\n49zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3o\nWE7GCkgPcQD9AhUAzIhzMFTvjEHjwgyhqaUSFzkuH7cCgYEAy7LaH0r36hAg9xNy\nwP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuN\nhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeD\nISvY25BAkT77DJY8EcozdIU5+3oDgYUAAoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc\n+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMn\nOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5c\niuO0ltu90L9+2YvW\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs749zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3oWE7GCkgPcQD9AAAAFQDMiHMwVO+MQePCDKGppRIXOS4ftwAAAIEAy7LaH0r36hAg9xNywP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuNhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeDISvY25BAkT77DJY8EcozdIU5+3oAAACBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvW", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.result new file mode 100644 index 0000000..d21d1cb --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBuDCCASwGByqGSM44BAEwggEfAoGBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim\n7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs7\n49zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3o\nWE7GCkgPcQD9AhUAzIhzMFTvjEHjwgyhqaUSFzkuH7cCgYEAy7LaH0r36hAg9xNy\nwP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuN\nhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeD\nISvY25BAkT77DJY8EcozdIU5+3oDgYUAAoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc\n+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMn\nOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5c\niuO0ltu90L9+2YvW\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAOz6f1kqHBg2vVXa4afQL/YxJMzgoHim7LiNHm5tFNPXKrlJvMpFCUKN+mUM3/8SprpqIWa8YoDdEpS0+0GYP3oQdbWa+vs749zzPwv/jOD22RVBHpVYEqAGFXBkcPPOzn4CDaPngFl9xoYxw0aFMT0Nxlh4j+3oWE7GCkgPcQD9AAAAFQDMiHMwVO+MQePCDKGppRIXOS4ftwAAAIEAy7LaH0r36hAg9xNywP+a2aE5iXDZk8IlXZtYV5ndDEC6N6cHMSnSiqG3y12P4ETsSv4JZPYBv8D3YyuNhRoZo+N0Xn4roJI8xResrycFptIEn4QupOj/y8cnZ5VYhQkHALNvDevKK0fssPeDISvY25BAkT77DJY8EcozdIU5+3oAAACBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFyczbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/xXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvW", + "private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBvQIBAAKBgQDs+n9ZKhwYNr1V2uGn0C/2MSTM4KB4puy4jR5ubRTT1yq5SbzK\nRQlCjfplDN//Eqa6aiFmvGKA3RKUtPtBmD96EHW1mvr7O+Pc8z8L/4zg9tkVQR6V\nWBKgBhVwZHDzzs5+Ag2j54BZfcaGMcNGhTE9DcZYeI/t6FhOxgpID3EA/QIVAMyI\nczBU74xB48IMoamlEhc5Lh+3AoGBAMuy2h9K9+oQIPcTcsD/mtmhOYlw2ZPCJV2b\nWFeZ3QxAujenBzEp0oqht8tdj+BE7Er+CWT2Ab/A92MrjYUaGaPjdF5+K6CSPMUX\nrK8nBabSBJ+ELqTo/8vHJ2eVWIUJBwCzbw3ryitH7LD3gyEr2NuQQJE++wyWPBHK\nM3SFOft6AoGBAOdrYUJ38yjc9tnrvLWsB1KlkYhc+UbTMSRKfA8Yo/Xs5QldFycz\nbUtsFGdLvqPol0pww2LqeKUQ8zVIF56Aw3SxmPMnOzRVQXpUI7z2W3/Ie4/i2Lu/\nxXos8ZHnIu+e7SLJRHe+RGNvISbsQhk+vnpNQP5ciuO0ltu90L9+2YvWAhUAr/vy\nahuEz4UFGhB8IIeLWQUO5FA=\n-----END DSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc new file mode 100644 index 0000000..57064cd --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc @@ -0,0 +1,15 @@ +-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,3239878D1E2D496289CE9CD2CB639BE8 + +k8/4Ax6UcnImNvEuybHwa9OHZHeCpKmq3Cu/q29a9AkTnktAWVmU9rQFch5CweDH +TEuRN+ZHecHrrMPR0fTpjXzZTxmU3549BQ2DfMSAdikPNKtBvhJwpT2se0rJ9M98 +p2xJQNhpxXT6f4Hy8m6QvjP5iTmlnQrrVBjV05ih9TLLQb4Y4NlydC08OyEcEoJV +w43G69sv2ws/tUVr7XSUtv8l+51ywSm42Pw6YOVlMZ7y+XB/uWmFNMz5gLN17tkc +wikhgvNnMWGLqb/AruuKPp5FrGRIC19DKRzDSPF5WlzLBdd2TQKDltknDj08AQMJ +bDsImbePteqhU+D7GiN2pVAD2b5kCZlFzYG43/Q8R3+O2l0Lvq5VBIqNB7LyJfTy +DL8XX0gzHk7FgG5MfLYin/qp7upnDXeSnIm8A2tlBYh9YzG3q/a53c5V2NomWjX0 +zvS+C7+w5NDwDRT5t+kecMhmHWNBuE/Pbvy0DaZQ/nnsC6TlkcaROJ0fiY3Da8E6 +EYvM4uKaZudsOOapwx0ZXHu2GZgLnly0p2Cd0Yf9t2UX9uySfwdL2TNw8nLVNVkh +aBE/x9LkKPWqOBV8tg/9ITGys/qgZh0A1r+RGmj/tII= +-----END DSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub new file mode 100644 index 0000000..18f5804 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAP25RC69mW4t09jpaine5ZRHmOtqNJa2nbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAiQDKMD/ikWqq/AAAAFQC/rPmzFozpCeLbFQykOaDGFZaqaQAAAIEAw1hJAYQzn/ZboF/xXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29JJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SOlVxxEkYneg7RH9Seh+U3rRacrh4AAACAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAo= diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub.result new file mode 100644 index 0000000..ad14260 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ssh-dss", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP25RC69mW4t09jpaine5ZRHmOtqNJa2\nnbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T\n+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAi\nQDKMD/ikWqq/AhUAv6z5sxaM6Qni2xUMpDmgxhWWqmkCgYEAw1hJAYQzn/ZboF/x\nXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29\nJJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SO\nlVxxEkYneg7RH9Seh+U3rRacrh4DgYQAAoGAOX41OCxx8mTuxpON/uZn6GwvK/m0\nK9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7p\nLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n\n/IO5uUbWoPK5iAo=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAP25RC69mW4t09jpaine5ZRHmOtqNJa2nbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAiQDKMD/ikWqq/AAAAFQC/rPmzFozpCeLbFQykOaDGFZaqaQAAAIEAw1hJAYQzn/ZboF/xXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29JJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SOlVxxEkYneg7RH9Seh+U3rRacrh4AAACAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAo=", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.result new file mode 100644 index 0000000..18c5271 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_dsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP25RC69mW4t09jpaine5ZRHmOtqNJa2\nnbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T\n+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAi\nQDKMD/ikWqq/AhUAv6z5sxaM6Qni2xUMpDmgxhWWqmkCgYEAw1hJAYQzn/ZboF/x\nXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29\nJJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SO\nlVxxEkYneg7RH9Seh+U3rRacrh4DgYQAAoGAOX41OCxx8mTuxpON/uZn6GwvK/m0\nK9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7p\nLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n\n/IO5uUbWoPK5iAo=\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAP25RC69mW4t09jpaine5ZRHmOtqNJa2nbsRrSsZkvGXxbJ7ojxsybWf4kAAI4GpsGMzlrFrlMEpHQfebJAn+zJwGS+loR7T+gNz8JoVIgPF9dabXVymcygl4FB/sNAmV4XK3OjvSW1NCKdSkwZZr/gz5JBo1qAiQDKMD/ikWqq/AAAAFQC/rPmzFozpCeLbFQykOaDGFZaqaQAAAIEAw1hJAYQzn/ZboF/xXDHzP49uRpIIoyaSfUz5W3+Lpi/CBkOIGaGOuitwcpTfzBSZIDZ9ORs9fq5oBh29JJcAdBNgVXfzThSiGvBgU4UIj41MlG4PG6St88VXCy0niEXWmjSkdcW3hZ0ai0SOlVxxEkYneg7RH9Seh+U3rRacrh4AAACAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71AOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6bEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAo=", + "private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBvAIBAAKBgQD9uUQuvZluLdPY6Wop3uWUR5jrajSWtp27Ea0rGZLxl8Wye6I8\nbMm1n+JAACOBqbBjM5axa5TBKR0H3myQJ/sycBkvpaEe0/oDc/CaFSIDxfXWm11c\npnMoJeBQf7DQJleFytzo70ltTQinUpMGWa/4M+SQaNagIkAyjA/4pFqqvwIVAL+s\n+bMWjOkJ4tsVDKQ5oMYVlqppAoGBAMNYSQGEM5/2W6Bf8Vwx8z+PbkaSCKMmkn1M\n+Vt/i6YvwgZDiBmhjrorcHKU38wUmSA2fTkbPX6uaAYdvSSXAHQTYFV3804Uohrw\nYFOFCI+NTJRuDxukrfPFVwstJ4hF1po0pHXFt4WdGotEjpVccRJGJ3oO0R/Unofl\nN60WnK4eAoGAOX41OCxx8mTuxpON/uZn6GwvK/m0K9fr/UmIX8D4Mp8PgnPLC71A\nOwLy1HrCVi3ohCqeSY2C1uf1VWUVlSqMH85Pxc7pLtuULoQdCgiYt1agVrioFSP6\nbEyFdV8vGxA4YGh6cUSkeFZBJBrdNM4VmYBeT+3n/IO5uUbWoPK5iAoCFQCdYU1l\nO1pCZ3Jhf/YDAAnfQHAtMxAQEBAQEBAQEBAQEBAQEBA=\n-----END DSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa new file mode 100644 index 0000000..f4170ac --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJx7zPcbJg1zUAsBhKbmN0eOjbr+/W2qGSZTCP/c0mz4oAoGCCqGSM49 +AwEHoUQDQgAELN85t86lbEONGsyPNDxD/P2f9D9/ePBT3ZpAeVYUdyrVO00jO4JE +FPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ== +-----END EC PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub new file mode 100644 index 0000000..8f39dd6 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzfObfOpWxDjRrMjzQ8Q/z9n/Q/f3jwU92aQHlWFHcq1TtNIzuCRBT3ypVXOIbQvaGWw2jXltbLACG5+Ls4oDE= old openssh format diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub.result new file mode 100644 index 0000000..68f3c14 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "old openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELN85t86lbEONGsyPNDxD/P2f9D9/\nePBT3ZpAeVYUdyrVO00jO4JEFPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzfObfOpWxDjRrMjzQ8Q/z9n/Q/f3jwU92aQHlWFHcq1TtNIzuCRBT3ypVXOIbQvaGWw2jXltbLACG5+Ls4oDE=", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.result new file mode 100644 index 0000000..cfabd13 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELN85t86lbEONGsyPNDxD/P2f9D9/\nePBT3ZpAeVYUdyrVO00jO4JEFPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCzfObfOpWxDjRrMjzQ8Q/z9n/Q/f3jwU92aQHlWFHcq1TtNIzuCRBT3ypVXOIbQvaGWw2jXltbLACG5+Ls4oDE=", + "private": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIJx7zPcbJg1zUAsBhKbmN0eOjbr+/W2qGSZTCP/c0mz4oAoGCCqGSM49\nAwEHoUQDQgAELN85t86lbEONGsyPNDxD/P2f9D9/ePBT3ZpAeVYUdyrVO00jO4JE\nFPfKlVc4htC9oZbDaNeW1ssAIbn4uzigMQ==\n-----END EC PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc new file mode 100644 index 0000000..7e118d8 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,4BE217089AE8B7311672C159E0690AB4 + +AkqjOP53cDHrdkJFRVLHYS7fSPVcIa4BgKegLwqRUqJOvEOnn5j6RYCh2CMdPjwN +rdw26Gc0V++xeMISAbrX4TGAQPWyDyiuoCffTIAfbkNq8YQR/sNJjNmZEgtCs6+O +4iBQ8TMXO+7oWRC221FDbTIhB6k4lXXph/HzdW0/Y2A= +-----END EC PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub new file mode 100644 index 0000000..8efc1fe --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA4KgjqWJj9PR55PeF7t7PTXdx7cvMDqNkq4UTMjoXA5WtQYdoC2sxJnI5Psqvtrfa13C31gY8TlFAZ1cClnoBk= diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub.result new file mode 100644 index 0000000..3b3064f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDgqCOpYmP09Hnk94Xu3s9Nd3Hty8\nwOo2SrhRMyOhcDla1Bh2gLazEmcjk+yq+2t9rXcLfWBjxOUUBnVwKWegGQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA4KgjqWJj9PR55PeF7t7PTXdx7cvMDqNkq4UTMjoXA5WtQYdoC2sxJnI5Psqvtrfa13C31gY8TlFAZ1cClnoBk=", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.result new file mode 100644 index 0000000..423f6e2 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_ecdsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ecdsa-sha2-nistp256", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDgqCOpYmP09Hnk94Xu3s9Nd3Hty8\nwOo2SrhRMyOhcDla1Bh2gLazEmcjk+yq+2t9rXcLfWBjxOUUBnVwKWegGQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA4KgjqWJj9PR55PeF7t7PTXdx7cvMDqNkq4UTMjoXA5WtQYdoC2sxJnI5Psqvtrfa13C31gY8TlFAZ1cClnoBk=", + "private": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIA7fGKE3wZkXb6jMcMriZujktUQ6FTC0SoTAa6fKDXY8oAoGCCqGSM49\nAwEHoUQDQgAEDgqCOpYmP09Hnk94Xu3s9Nd3Hty8wOo2SrhRMyOhcDla1Bh2gLaz\nEmcjk+yq+2t9rXcLfWBjxOUUBnVwKWegGQcHBwcHBwc=\n-----END EC PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa new file mode 100644 index 0000000..2eadbb0 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA8wISnx2xWoeZur8yn/8NPykUY2mYyxn1n0mE5WJSo+mclFFS +mnN08WCt856AO8PMPuAn9cw0j3qJe0SKTnoMYSp+4fBsq6YHOGJvlRATF9SJkSIx +wBCYsMT+cf78vzhKRJrXAfJ/LWzV7b5gThHxj+Jby+fE/yePi8+Mb39UwYWGEFf+ +uRxcQIeuDX/VjPNtNKQPuO+HRi67WNXPFoUNmFXv1Ymn61S5duvVCxL8XdHXHdnZ +gIJ87CTlLBGPV/U9HrGJfl0AQ/jvMsvAV4IhMZMlV5QS2QigK7rkfBVe7k0NIWQ7 +Vwk5iunUpmUNVhKARdznvb8CJJm0ZEx4F2n8cQIDAQABAoIBAQCtZR46cSp6qWU1 +DnamGYyvM7W7lb6TtYtAxGnSb0z+bpPudPSXBqk8DrswqTlg674SY0nAJpyegFYX +Ifn6MzYgIv10ZGR2OjrOrdZmq5ikGWCrsZWEMZNyFq5kUwivvQ+pUj72wbyjghRH +1t7K9hzCiUbtAQzc77KKlWbkrBujFSp5EPNT67j5vV29WnZFbkPdUmfkM/ca/CZc +CWwvyAx19aFGyw3BsFhWQP5C9waT+QI9QZrVOA+8wTT11OcR6PT0oKdEmSYCKgHJ +JuYDWZ2XX2R2d5YNoxiqIZbCqQ/ayJuLOjLgQ1mx17pUyMNP3PoZCQXOi4jZWHZZ ++3/jqvJNAoGBAPmoL03KPvLVtHByEdxzPPfnonpYjfjlD4FvXgSQjdAcrTy4O06t +bDf4hMgUHQmDCyUakO45wyYwP0ISapQSBWniryjR/7U7/G/dX45fKRUeNoMvpmSC +qSEMAbd31Inpzuu5k0Y8p3hvoexeYlhbRkBL1ryx1LgIvC0TkWR+e6EvAoGBAPku +pHcpi3t2wewmP6f1krxtOLyvVt5RKaRjZ/2gNtzLPXL6ulQR5hufYlLKgyyyf2gJ +HxVFhCkfRjwVHV8qdIJc+Q4mjnjOeNfvqnzWOlSfZFegyWvOPW7hTX0/jZYGOb4I +7fzYyUPHnlu73twmshJMTzE1Ju7RdJXyLtg8xpRfAoGBAKjlyELXTWjZfP4Jnd3H +NHr+gSRGHp5A0RGe9zsdVGNz0xteA/mBR9JB1grJ2K8jsXmDlIMmHskKIPGhJetQ +mcr9qcRy9Yx1rZ08ZbYa2N9JllV/+hDLeII77jlh3y8CN5Ov81u0ExReaWxQmjXu +YgODix4TLLboae4Q6+7Rxu/PAoGAOZ04N7kqX/ygb+qUE1Crgde7I51i93pKp5C4 +baMKrFhtt9UTGfcdfkuG31+lnsMSxEo/npp5KUzq319+cA+P6sh2aXguvu32cO8g +O0cJK6HDAKPTjpKcD7QWR5xXL1X3KeJErI6vUnWoPsuchsiHqcVtFhKVEujpDPZ3 +MFY1D/8CgYBvv5mBb2kBf2/2JHp3lP/Q6LepEBkZk9dvoEU6/5xLvA5gEXR0MUj8 +g97Z1duGdXD/uEVRuRuOJkk4p8YmSM7t34st3lF06wdJUGcKvmZpp2ee+CdLwESi +GDCwcP5pcii56TVr09uHITWei4jFm+3Ye3h092dvPyNoEiJOgk2lsg== +-----END RSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub new file mode 100644 index 0000000..1eaa7e0 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDzAhKfHbFah5m6vzKf/w0/KRRjaZjLGfWfSYTlYlKj6ZyUUVKac3TxYK3znoA7w8w+4Cf1zDSPeol7RIpOegxhKn7h8Gyrpgc4Ym+VEBMX1ImRIjHAEJiwxP5x/vy/OEpEmtcB8n8tbNXtvmBOEfGP4lvL58T/J4+Lz4xvf1TBhYYQV/65HFxAh64Nf9WM8200pA+474dGLrtY1c8WhQ2YVe/ViafrVLl269ULEvxd0dcd2dmAgnzsJOUsEY9X9T0esYl+XQBD+O8yy8BXgiExkyVXlBLZCKAruuR8FV7uTQ0hZDtXCTmK6dSmZQ1WEoBF3Oe9vwIkmbRkTHgXafxx old openssh format diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub.result new file mode 100644 index 0000000..720438a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "old openssh format", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8wISnx2xWoeZur8yn/8N\nPykUY2mYyxn1n0mE5WJSo+mclFFSmnN08WCt856AO8PMPuAn9cw0j3qJe0SKTnoM\nYSp+4fBsq6YHOGJvlRATF9SJkSIxwBCYsMT+cf78vzhKRJrXAfJ/LWzV7b5gThHx\nj+Jby+fE/yePi8+Mb39UwYWGEFf+uRxcQIeuDX/VjPNtNKQPuO+HRi67WNXPFoUN\nmFXv1Ymn61S5duvVCxL8XdHXHdnZgIJ87CTlLBGPV/U9HrGJfl0AQ/jvMsvAV4Ih\nMZMlV5QS2QigK7rkfBVe7k0NIWQ7Vwk5iunUpmUNVhKARdznvb8CJJm0ZEx4F2n8\ncQIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDzAhKfHbFah5m6vzKf/w0/KRRjaZjLGfWfSYTlYlKj6ZyUUVKac3TxYK3znoA7w8w+4Cf1zDSPeol7RIpOegxhKn7h8Gyrpgc4Ym+VEBMX1ImRIjHAEJiwxP5x/vy/OEpEmtcB8n8tbNXtvmBOEfGP4lvL58T/J4+Lz4xvf1TBhYYQV/65HFxAh64Nf9WM8200pA+474dGLrtY1c8WhQ2YVe/ViafrVLl269ULEvxd0dcd2dmAgnzsJOUsEY9X9T0esYl+XQBD+O8yy8BXgiExkyVXlBLZCKAruuR8FV7uTQ0hZDtXCTmK6dSmZQ1WEoBF3Oe9vwIkmbRkTHgXafxx", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.result new file mode 100644 index 0000000..affc996 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8wISnx2xWoeZur8yn/8N\nPykUY2mYyxn1n0mE5WJSo+mclFFSmnN08WCt856AO8PMPuAn9cw0j3qJe0SKTnoM\nYSp+4fBsq6YHOGJvlRATF9SJkSIxwBCYsMT+cf78vzhKRJrXAfJ/LWzV7b5gThHx\nj+Jby+fE/yePi8+Mb39UwYWGEFf+uRxcQIeuDX/VjPNtNKQPuO+HRi67WNXPFoUN\nmFXv1Ymn61S5duvVCxL8XdHXHdnZgIJ87CTlLBGPV/U9HrGJfl0AQ/jvMsvAV4Ih\nMZMlV5QS2QigK7rkfBVe7k0NIWQ7Vwk5iunUpmUNVhKARdznvb8CJJm0ZEx4F2n8\ncQIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDzAhKfHbFah5m6vzKf/w0/KRRjaZjLGfWfSYTlYlKj6ZyUUVKac3TxYK3znoA7w8w+4Cf1zDSPeol7RIpOegxhKn7h8Gyrpgc4Ym+VEBMX1ImRIjHAEJiwxP5x/vy/OEpEmtcB8n8tbNXtvmBOEfGP4lvL58T/J4+Lz4xvf1TBhYYQV/65HFxAh64Nf9WM8200pA+474dGLrtY1c8WhQ2YVe/ViafrVLl269ULEvxd0dcd2dmAgnzsJOUsEY9X9T0esYl+XQBD+O8yy8BXgiExkyVXlBLZCKAruuR8FV7uTQ0hZDtXCTmK6dSmZQ1WEoBF3Oe9vwIkmbRkTHgXafxx", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA8wISnx2xWoeZur8yn/8NPykUY2mYyxn1n0mE5WJSo+mclFFS\nmnN08WCt856AO8PMPuAn9cw0j3qJe0SKTnoMYSp+4fBsq6YHOGJvlRATF9SJkSIx\nwBCYsMT+cf78vzhKRJrXAfJ/LWzV7b5gThHxj+Jby+fE/yePi8+Mb39UwYWGEFf+\nuRxcQIeuDX/VjPNtNKQPuO+HRi67WNXPFoUNmFXv1Ymn61S5duvVCxL8XdHXHdnZ\ngIJ87CTlLBGPV/U9HrGJfl0AQ/jvMsvAV4IhMZMlV5QS2QigK7rkfBVe7k0NIWQ7\nVwk5iunUpmUNVhKARdznvb8CJJm0ZEx4F2n8cQIDAQABAoIBAQCtZR46cSp6qWU1\nDnamGYyvM7W7lb6TtYtAxGnSb0z+bpPudPSXBqk8DrswqTlg674SY0nAJpyegFYX\nIfn6MzYgIv10ZGR2OjrOrdZmq5ikGWCrsZWEMZNyFq5kUwivvQ+pUj72wbyjghRH\n1t7K9hzCiUbtAQzc77KKlWbkrBujFSp5EPNT67j5vV29WnZFbkPdUmfkM/ca/CZc\nCWwvyAx19aFGyw3BsFhWQP5C9waT+QI9QZrVOA+8wTT11OcR6PT0oKdEmSYCKgHJ\nJuYDWZ2XX2R2d5YNoxiqIZbCqQ/ayJuLOjLgQ1mx17pUyMNP3PoZCQXOi4jZWHZZ\n+3/jqvJNAoGBAPmoL03KPvLVtHByEdxzPPfnonpYjfjlD4FvXgSQjdAcrTy4O06t\nbDf4hMgUHQmDCyUakO45wyYwP0ISapQSBWniryjR/7U7/G/dX45fKRUeNoMvpmSC\nqSEMAbd31Inpzuu5k0Y8p3hvoexeYlhbRkBL1ryx1LgIvC0TkWR+e6EvAoGBAPku\npHcpi3t2wewmP6f1krxtOLyvVt5RKaRjZ/2gNtzLPXL6ulQR5hufYlLKgyyyf2gJ\nHxVFhCkfRjwVHV8qdIJc+Q4mjnjOeNfvqnzWOlSfZFegyWvOPW7hTX0/jZYGOb4I\n7fzYyUPHnlu73twmshJMTzE1Ju7RdJXyLtg8xpRfAoGBAKjlyELXTWjZfP4Jnd3H\nNHr+gSRGHp5A0RGe9zsdVGNz0xteA/mBR9JB1grJ2K8jsXmDlIMmHskKIPGhJetQ\nmcr9qcRy9Yx1rZ08ZbYa2N9JllV/+hDLeII77jlh3y8CN5Ov81u0ExReaWxQmjXu\nYgODix4TLLboae4Q6+7Rxu/PAoGAOZ04N7kqX/ygb+qUE1Crgde7I51i93pKp5C4\nbaMKrFhtt9UTGfcdfkuG31+lnsMSxEo/npp5KUzq319+cA+P6sh2aXguvu32cO8g\nO0cJK6HDAKPTjpKcD7QWR5xXL1X3KeJErI6vUnWoPsuchsiHqcVtFhKVEujpDPZ3\nMFY1D/8CgYBvv5mBb2kBf2/2JHp3lP/Q6LepEBkZk9dvoEU6/5xLvA5gEXR0MUj8\ng97Z1duGdXD/uEVRuRuOJkk4p8YmSM7t34st3lF06wdJUGcKvmZpp2ee+CdLwESi\nGDCwcP5pcii56TVr09uHITWei4jFm+3Ye3h092dvPyNoEiJOgk2lsg==\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc new file mode 100644 index 0000000..e5b6398 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,1380F5ADA0E0B636860A6BF78D47D6B2 + +ICLCebZN4+91mTQwByj210FD3D7kCxFA6kZ5fZ1TG34RzGynOSgUSdxPaXBHO4hC +DjS7lv6vrtaXPxlz5MVAhb6n0+X1pZDu5Wh5xjtkOt9yt4YPNKkvDPazSFBTHDth +jURe/aCLwXa+N5g5v1G/asb5dufA96tiPD8jjsBPm6RPq/444jAnLkid6YwTRLCk +a+IZZ+sX8onOq2xJM5NhsJxCEp5yquQCdyjvBBEBk5PExvWDHz4BIkK0WDR86IX/ +j4baAbTREiwP+EmVw1uogijvS+9nWPv3dQrtWwNQQNdWE2jJnsuDv44VAh1QQD7A +Txz2Y2A6IyzQsDxr6fL4JidVZOeeOXagYOBceZMs4IdNVJ52LJ9fqWtH1Eavj0za +c9zLgFN547l/Uqc334BQTkWhA9zGNkYJo4GCl/zjL2C6ce9gp0l6aBwSRyBmfH21 +pxFYqO/LQOSTbupeGzkNOpeNm/XtdOHe2N+2fiMO8hqEr6tOR4dsEUVBLCWt3tpD +C4jT3TtXKvx4qPV5N0w/umgXDd01Npk02k+wiQRnPBczFYLfRpceV/7MGtttV86/ +Ldl2p00q+JB6TzkHfOa4dA8oZJAwz3RPwmGYt/riJS4JOIpQGCs9lU3zgi7NTt4L +T9YAlAP3fjG1n3vy1uktKfRa+AoSqgS/pTJgB2srs6vxw3kt/V825cVyzSfGdQM/ +2oinmrbMAs0tRpTiHyqc/FjVRTW/8+LoSv/o6ZpN2x4jxkW/7cBH0Pcytvw8svd2 +Q+h92cfHuiNWi5tuiUkeDfjWEXo6ssVFA2t1ebTOk5y2wwPVAURf/jVxhEpFm4iY +PCIqwCwNSs1S05zAaIQ39ltBETj4Y46715GuYKsqLDYhv2lAIAlWXWgQ/N0tYVS6 +Oi/Qp9XFSEeyym5vzX/2ck1SJePvHvHewiABJjYzq3wlvIdWE6V3tJ3MRXRhlKNf +4bG8caItSG1n/QIeguNZI+A2Pu8AIdKjjKsnVcn3mikuKfcCAICZwf6m3Bd+Al7G +lrsJxyPqhhbPN1/t0w30tu8QuTSV+uMx4ZCKoUc6yJMQRmoM0RJ626re51IT2ikk +gB4f3Ms1VbB176it2L/zbXUAaxeE7Cbdcp/5058ksbuE0yA7JB+a2vQHFqw8Xxsb +qdKc4m4jkCdvaA5oNnGoG4milYukp1WVCGJeLD7gspTHR5dDYsOQgHvkxu+Ukor+ +0+1yvf8R6pRJWMoV0VvNkuSBUqcx94A+xLaEYCkB78Koum8xlPA1OA7VVkMVjQSk +r6c/iANbNV20IVz1TBpg9J1rQOGisbE43yRkH+aMgHnAnhk+UgK584QOH6eJpGZT +yBwes57P1kgT5VubavoJbeZLL6B70Sn/sKoLzxxruzPKmsmufJNK9klB7lu5f4gj +lvKtuNaiWbux1+fQmU+05nM1WW7s5Nm9MVUCfS5RxUq8SRqC7W17ouHEssW6mJT1 +jHK1xhoxX05X/T0NfdPzbG7S7+DG18Q6jnyHb28LeKLXv33sEUrT5z7+Nx4JS4XM +ZeMzPdRgYJw9vLQSYdksj0cNBb8UpAiG410lICrbPGWJh9d2KzhNKlfk/vLHia1V +-----END RSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub new file mode 100644 index 0000000..806ab91 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHLfm98g0aHjbQJcjbamutwkWTMY426a4IdwGrpAOv806h6wBXNcOj2VJbgeQ2/XkQ0RY78fGrHSacaadGsT9E5sRGyvkr/WtDpBokXrgpP15OvhfTaSMVTcty6qknndpu7P5nmSipdn9fQR9TyNRyAajhn+UINuquGfxyLL30W4IBqSISOcXKc0pScTdMOIOmkxxY+vQFydQpWF0a3TopKKa4b3sQJgqc0MJkREllT6U+0U4+YufoW6zZyMNIS2gxWUlGUiA5XveWSaYIXCaPQmps4WoO9AlrM7z1sTcG5yXn0kEUvTmBYUOUlffiBgXzArt4Pmm8gVklR5UH98y5 diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub.result new file mode 100644 index 0000000..b4aad7b --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.pub.result @@ -0,0 +1,8 @@ +{ + "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxy35vfINGh420CXI22pr\nrcJFkzGONumuCHcBq6QDr/NOoesAVzXDo9lSW4HkNv15ENEWO/Hxqx0mnGmnRrE/\nRObERsr5K/1rQ6QaJF64KT9eTr4X02kjFU3LcuqpJ53abuz+Z5koqXZ/X0EfU8jU\ncgGo4Z/lCDbqrhn8ciy99FuCAakiEjnFynNKUnE3TDiDppMcWPr0BcnUKVhdGt06\nKSimuG97ECYKnNDCZERJZU+lPtFOPmLn6Fus2cjDSEtoMVlJRlIgOV73lkmmCFwm\nj0JqbOFqDvQJazO89bE3Bucl59JBFL05gWFDlJX34gYF8wK7eD5pvIFZJUeVB/fM\nuQIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDHLfm98g0aHjbQJcjbamutwkWTMY426a4IdwGrpAOv806h6wBXNcOj2VJbgeQ2/XkQ0RY78fGrHSacaadGsT9E5sRGyvkr/WtDpBokXrgpP15OvhfTaSMVTcty6qknndpu7P5nmSipdn9fQR9TyNRyAajhn+UINuquGfxyLL30W4IBqSISOcXKc0pScTdMOIOmkxxY+vQFydQpWF0a3TopKKa4b3sQJgqc0MJkREllT6U+0U4+YufoW6zZyMNIS2gxWUlGUiA5XveWSaYIXCaPQmps4WoO9AlrM7z1sTcG5yXn0kEUvTmBYUOUlffiBgXzArt4Pmm8gVklR5UH98y5", + "private": null +} + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.result new file mode 100644 index 0000000..fddff0f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxy35vfINGh420CXI22pr\nrcJFkzGONumuCHcBq6QDr/NOoesAVzXDo9lSW4HkNv15ENEWO/Hxqx0mnGmnRrE/\nRObERsr5K/1rQ6QaJF64KT9eTr4X02kjFU3LcuqpJ53abuz+Z5koqXZ/X0EfU8jU\ncgGo4Z/lCDbqrhn8ciy99FuCAakiEjnFynNKUnE3TDiDppMcWPr0BcnUKVhdGt06\nKSimuG97ECYKnNDCZERJZU+lPtFOPmLn6Fus2cjDSEtoMVlJRlIgOV73lkmmCFwm\nj0JqbOFqDvQJazO89bE3Bucl59JBFL05gWFDlJX34gYF8wK7eD5pvIFZJUeVB/fM\nuQIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDHLfm98g0aHjbQJcjbamutwkWTMY426a4IdwGrpAOv806h6wBXNcOj2VJbgeQ2/XkQ0RY78fGrHSacaadGsT9E5sRGyvkr/WtDpBokXrgpP15OvhfTaSMVTcty6qknndpu7P5nmSipdn9fQR9TyNRyAajhn+UINuquGfxyLL30W4IBqSISOcXKc0pScTdMOIOmkxxY+vQFydQpWF0a3TopKKa4b3sQJgqc0MJkREllT6U+0U4+YufoW6zZyMNIS2gxWUlGUiA5XveWSaYIXCaPQmps4WoO9AlrM7z1sTcG5yXn0kEUvTmBYUOUlffiBgXzArt4Pmm8gVklR5UH98y5", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAxy35vfINGh420CXI22prrcJFkzGONumuCHcBq6QDr/NOoesA\nVzXDo9lSW4HkNv15ENEWO/Hxqx0mnGmnRrE/RObERsr5K/1rQ6QaJF64KT9eTr4X\n02kjFU3LcuqpJ53abuz+Z5koqXZ/X0EfU8jUcgGo4Z/lCDbqrhn8ciy99FuCAaki\nEjnFynNKUnE3TDiDppMcWPr0BcnUKVhdGt06KSimuG97ECYKnNDCZERJZU+lPtFO\nPmLn6Fus2cjDSEtoMVlJRlIgOV73lkmmCFwmj0JqbOFqDvQJazO89bE3Bucl59JB\nFL05gWFDlJX34gYF8wK7eD5pvIFZJUeVB/fMuQIDAQABAoIBAGuSfhZDGyZm+Q2T\nypYONNekW7Uyh29K5640r9dGfqNRkb9LT2TKab4dSiiXz2yPmwolEpAPjIjw9oB1\nY11/rv8Eby8YwlgqxvrCL0hDS80jJ0j5y55nYwZHfMC00eTOkUFlh8Tl6BsWH5aP\ncl7q0So9kTtCAw1bs4WSDVCQr4q/x7fZRQWeWudi4IjnCv5vn1Pgot7XxDwdFNQG\nDrkUHvYXv0M2OCdl7YN0D/bHQon5ney0YU10mtqGbkcEmu0woykW1Bc539b9AoD3\nxI6LVyY6/OEwGu5ctKolIVJjsguwfLJ9WR7SenR5nTzjJyxMdSfXtXkKPX2NZxpO\nziNYnm0CgYEA/afEFBu5Ld/TjYatdf7ezZe9iDx6vBzWmMtwkhr3OHCzVP1OIaB0\nSTsCWrTdoLFTMOizUHjj71vX5v5G4aCgaMXQnSDf13mxrFzR36w5oyJOBLjkHhol\nf0ROO7QCXK1hjBAUvnKwLPQvx1CAkDB9z+cT/BJwRCarfeLhrd/sGEMCgYEAyQVN\nOGIdRVBs3Q/8dbtaz+7LOv6IBZm2y9TKHKmfBm1txAsgkqRl7cfVTyczgAZfS/RB\nzrAje5UA+phCSPtyb5B+K1i/eHw7xDZrw8wauAKY8ILSadS9ZA0mU+7XCqsWhNqN\nrvuB5dttsTDgyXnMxCbYqCWAcyKn8jBh1cDo5VMCgYBe3iMQnjnI9YCK2wb/LZ6o\n6Aqj7HK+7k44gUYN7vXtbwEzVTWmj/tN9DryL9kAI7IIhc+i1kPxnrkGFK3v7wJv\njSRzz/rH/SS9YU3BSQmZgNgLHhd7Rq4lhid4Xt/PR61HFDCd9gj8FyvTcMFUrD4x\nxqwLx92jL49OGs/rFueXPwKBgBi46jJQ/sCTj4/wc2AXVqfT+nKa8yedK/oNhX3Y\n7pHfy2wc4jimt1JzDSza6V6JahbxR1agGv0L6j7nkt9e7UgDQUEbfRDYVpFfEAnY\nhEC1MRIDRNV3MIOpilkwOoo5WF+mcV5f2C3ouqjcFgkxTZmiHWswkYeXb4g9owqi\n2wG5AoGAb6/btpj3Ql+qYXRUH/cWPlLeFbKiGaAJ+Kn5RwlEW8D//FjKuV7fL7BN\nhvaDJUpwP9klNRny3IK6FWuFI0KDup0nyrIbS07h2rOCl/+g2erDuS5sofpu2zWU\nZDArpSmpU9EF6S8CvbbZmYvWzYUhYD/sEqIR+KSowNM4PA7g7fwKCgoKCgoKCgoK\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256 b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256 new file mode 100644 index 0000000..ceed070 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256 @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,5C3291414FA514EE9647898A2D5315FD + +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 +-----END RSA PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub new file mode 100644 index 0000000..0df674a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDOHBVYZ041e+MqbjY+oSRiNNO1nDK1l0P6blyAyi4gwWfEOGSkqBZr+vCGnSj3/BNWsCcECbsG2TBMkoxCmXLc32rgQRz76/vON0gRaAzm+oi4N1hSSN7S/xX3XEwkH5OM/g9WKJvzerGejIExT9C6jzCvznlRdSTnntJrgwuf8ubyOfffXht66X/klC5+XeDI8SORiIr/E7q8QUpjcYYjgRgJHTjjh47xDGQOkcL+ceZb1/ufbU+4r7m8Ume/+fQuOTXcD13yKd1Na7auXMHL8Orh8YHvgwbFCVPOFDDEyReNgLLEaGGHJOuWaf55N+7J4CSDRkRqjz1tFqdqqHwdRr0/pJP77mjEe89Cx4iu+BDrT72/SPKo5bwDoXBa2TxSdoVHT9idjsUPDfwshD4eHtwyhrZkEiNY8Qp+F57I9MSgRT62zdO/vZ5wzEYDJC3DBXPw3owvpGdJEjSOhTD0rOFctNs/dKlwAXnU6QUAE1qgd9P+O3GIhYiPkrw3XsbF39VeouroYIbljv4KyDb+wQMk2U2wzUE/ZV/AVjV0OK/3colr43uxEhl6D48pWejzpQ6DMFKuL5pcxzZzIlBVmwwNsNb3DoWQ+a1gepyimp1ocUlv28JPqMMiarm/Kka86KY+fzcHUUPQXpz8R4edOLA2hQSudYdTcNmcAOpwMw== diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub.result new file mode 100644 index 0000000..3f23304 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.pub.result @@ -0,0 +1,6 @@ +{ "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzhwVWGdONXvjKm42PqEk\nYjTTtZwytZdD+m5cgMouIMFnxDhkpKgWa/rwhp0o9/wTVrAnBAm7BtkwTJKMQply\n3N9q4EEc++v7zjdIEWgM5vqIuDdYUkje0v8V91xMJB+TjP4PViib83qxnoyBMU/Q\nuo8wr855UXUk557Sa4MLn/Lm8jn3314beul/5JQufl3gyPEjkYiK/xO6vEFKY3GG\nI4EYCR0444eO8QxkDpHC/nHmW9f7n21PuK+5vFJnv/n0Ljk13A9d8indTWu2rlzB\ny/Dq4fGB74MGxQlTzhQwxMkXjYCyxGhhhyTrlmn+eTfuyeAkg0ZEao89bRanaqh8\nHUa9P6ST++5oxHvPQseIrvgQ60+9v0jyqOW8A6FwWtk8UnaFR0/YnY7FDw38LIQ+\nHh7cMoa2ZBIjWPEKfheeyPTEoEU+ts3Tv72ecMxGAyQtwwVz8N6ML6RnSRI0joUw\n9KzhXLTbP3SpcAF51OkFABNaoHfT/jtxiIWIj5K8N17Gxd/VXqLq6GCG5Y7+Csg2\n/sEDJNlNsM1BP2VfwFY1dDiv93KJa+N7sRIZeg+PKVno86UOgzBSri+aXMc2cyJQ\nVZsMDbDW9w6FkPmtYHqcopqdaHFJb9vCT6jDImq5vypGvOimPn83B1FD0F6c/EeH\nnTiwNoUErnWHU3DZnADqcDMCAwEAAQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAACAQDOHBVYZ041e+MqbjY+oSRiNNO1nDK1l0P6blyAyi4gwWfEOGSkqBZr+vCGnSj3/BNWsCcECbsG2TBMkoxCmXLc32rgQRz76/vON0gRaAzm+oi4N1hSSN7S/xX3XEwkH5OM/g9WKJvzerGejIExT9C6jzCvznlRdSTnntJrgwuf8ubyOfffXht66X/klC5+XeDI8SORiIr/E7q8QUpjcYYjgRgJHTjjh47xDGQOkcL+ceZb1/ufbU+4r7m8Ume/+fQuOTXcD13yKd1Na7auXMHL8Orh8YHvgwbFCVPOFDDEyReNgLLEaGGHJOuWaf55N+7J4CSDRkRqjz1tFqdqqHwdRr0/pJP77mjEe89Cx4iu+BDrT72/SPKo5bwDoXBa2TxSdoVHT9idjsUPDfwshD4eHtwyhrZkEiNY8Qp+F57I9MSgRT62zdO/vZ5wzEYDJC3DBXPw3owvpGdJEjSOhTD0rOFctNs/dKlwAXnU6QUAE1qgd9P+O3GIhYiPkrw3XsbF39VeouroYIbljv4KyDb+wQMk2U2wzUE/ZV/AVjV0OK/3colr43uxEhl6D48pWejzpQ6DMFKuL5pcxzZzIlBVmwwNsNb3DoWQ+a1gepyimp1ocUlv28JPqMMiarm/Kka86KY+fzcHUUPQXpz8R4edOLA2hQSudYdTcNmcAOpwMw==", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.result new file mode 100644 index 0000000..8cf3c91 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/openssh_old_rsa_enc_aes256.result @@ -0,0 +1,6 @@ +{ "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzhwVWGdONXvjKm42PqEk\nYjTTtZwytZdD+m5cgMouIMFnxDhkpKgWa/rwhp0o9/wTVrAnBAm7BtkwTJKMQply\n3N9q4EEc++v7zjdIEWgM5vqIuDdYUkje0v8V91xMJB+TjP4PViib83qxnoyBMU/Q\nuo8wr855UXUk557Sa4MLn/Lm8jn3314beul/5JQufl3gyPEjkYiK/xO6vEFKY3GG\nI4EYCR0444eO8QxkDpHC/nHmW9f7n21PuK+5vFJnv/n0Ljk13A9d8indTWu2rlzB\ny/Dq4fGB74MGxQlTzhQwxMkXjYCyxGhhhyTrlmn+eTfuyeAkg0ZEao89bRanaqh8\nHUa9P6ST++5oxHvPQseIrvgQ60+9v0jyqOW8A6FwWtk8UnaFR0/YnY7FDw38LIQ+\nHh7cMoa2ZBIjWPEKfheeyPTEoEU+ts3Tv72ecMxGAyQtwwVz8N6ML6RnSRI0joUw\n9KzhXLTbP3SpcAF51OkFABNaoHfT/jtxiIWIj5K8N17Gxd/VXqLq6GCG5Y7+Csg2\n/sEDJNlNsM1BP2VfwFY1dDiv93KJa+N7sRIZeg+PKVno86UOgzBSri+aXMc2cyJQ\nVZsMDbDW9w6FkPmtYHqcopqdaHFJb9vCT6jDImq5vypGvOimPn83B1FD0F6c/EeH\nnTiwNoUErnWHU3DZnADqcDMCAwEAAQ==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAACAQDOHBVYZ041e+MqbjY+oSRiNNO1nDK1l0P6blyAyi4gwWfEOGSkqBZr+vCGnSj3/BNWsCcECbsG2TBMkoxCmXLc32rgQRz76/vON0gRaAzm+oi4N1hSSN7S/xX3XEwkH5OM/g9WKJvzerGejIExT9C6jzCvznlRdSTnntJrgwuf8ubyOfffXht66X/klC5+XeDI8SORiIr/E7q8QUpjcYYjgRgJHTjjh47xDGQOkcL+ceZb1/ufbU+4r7m8Ume/+fQuOTXcD13yKd1Na7auXMHL8Orh8YHvgwbFCVPOFDDEyReNgLLEaGGHJOuWaf55N+7J4CSDRkRqjz1tFqdqqHwdRr0/pJP77mjEe89Cx4iu+BDrT72/SPKo5bwDoXBa2TxSdoVHT9idjsUPDfwshD4eHtwyhrZkEiNY8Qp+F57I9MSgRT62zdO/vZ5wzEYDJC3DBXPw3owvpGdJEjSOhTD0rOFctNs/dKlwAXnU6QUAE1qgd9P+O3GIhYiPkrw3XsbF39VeouroYIbljv4KyDb+wQMk2U2wzUE/ZV/AVjV0OK/3colr43uxEhl6D48pWejzpQ6DMFKuL5pcxzZzIlBVmwwNsNb3DoWQ+a1gepyimp1ocUlv28JPqMMiarm/Kka86KY+fzcHUUPQXpz8R4edOLA2hQSudYdTcNmcAOpwMw==", + "private": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/encrypted-dsa.ppk b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc similarity index 100% rename from reverse_engineering/node_modules/ssh2-streams/test/fixtures/encrypted-dsa.ppk rename to reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc.result new file mode 100644 index 0000000..68edda7 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_dsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-dss", + "comment": "dsa-key-20141202", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAJn2I8YefRo3BsEeinQt8KQ4cEyArAs7\nY/W733oRSYOIzWF1Ju124ysKrmg2okv+05CYcjV3Yp4AzQeomYAlgmB/7xCEnWaE\nnxCwAxmrrJMmPrkwNjHOIi7yM5QOE90IM/Q+IJA4EPBfSb+Xr8fYhrp53KNHVSnc\n2KkOqpo2FsIjAhUAuDZT+dBqslKqtgfNlYf8OY9088ECgYAeSGom9LLNdzcwCHnG\nfxKNnEz355KITADTxiIpBvnQW+eDHwQvIw6V2Oc73bKCu5ZirZmIMW5w6KjQVwku\nQBoF9Koq/2u6VeevtL9pD6TBzSLMVw5pV3PmE4/C/eLiaUxZLIHdbzpqPkAvAUBr\nXKkj0ijzcNzCp1fuF8H0pvR8yQOBhAACgYAmvV+kqWhUgDYwNNz1qDaoS8XdsOpo\nnutZ/0stRQ66mKAy8kNVNNQ6oUx1XFl1WUt4iyFY/2Rz2fZhLz5/TbZRK5ygo666\nWgnxB/Ud4GAx/BPQTghOJJOL00vJk+8jVCGNDc942V6nFXznDMXwqxhRCW6dm+2l\nTh7ntrli8mCk5g==\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1kc3MAAACBAJn2I8YefRo3BsEeinQt8KQ4cEyArAs7Y/W733oRSYOIzWF1Ju124ysKrmg2okv+05CYcjV3Yp4AzQeomYAlgmB/7xCEnWaEnxCwAxmrrJMmPrkwNjHOIi7yM5QOE90IM/Q+IJA4EPBfSb+Xr8fYhrp53KNHVSnc2KkOqpo2FsIjAAAAFQC4NlP50GqyUqq2B82Vh/w5j3TzwQAAAIAeSGom9LLNdzcwCHnGfxKNnEz355KITADTxiIpBvnQW+eDHwQvIw6V2Oc73bKCu5ZirZmIMW5w6KjQVwkuQBoF9Koq/2u6VeevtL9pD6TBzSLMVw5pV3PmE4/C/eLiaUxZLIHdbzpqPkAvAUBrXKkj0ijzcNzCp1fuF8H0pvR8yQAAAIAmvV+kqWhUgDYwNNz1qDaoS8XdsOponutZ/0stRQ66mKAy8kNVNNQ6oUx1XFl1WUt4iyFY/2Rz2fZhLz5/TbZRK5ygo666WgnxB/Ud4GAx/BPQTghOJJOL00vJk+8jVCGNDc942V6nFXznDMXwqxhRCW6dm+2lTh7ntrli8mCk5g==", + "private": "-----BEGIN DSA PRIVATE KEY-----\nMIIBugIBAAKBgQCZ9iPGHn0aNwbBHop0LfCkOHBMgKwLO2P1u996EUmDiM1hdSbt\nduMrCq5oNqJL/tOQmHI1d2KeAM0HqJmAJYJgf+8QhJ1mhJ8QsAMZq6yTJj65MDYx\nziIu8jOUDhPdCDP0PiCQOBDwX0m/l6/H2Ia6edyjR1Up3NipDqqaNhbCIwIVALg2\nU/nQarJSqrYHzZWH/DmPdPPBAoGAHkhqJvSyzXc3MAh5xn8SjZxM9+eSiEwA08Yi\nKQb50Fvngx8ELyMOldjnO92ygruWYq2ZiDFucOio0FcJLkAaBfSqKv9rulXnr7S/\naQ+kwc0izFcOaVdz5hOPwv3i4mlMWSyB3W86aj5ALwFAa1ypI9Io83DcwqdX7hfB\n9Kb0fMkCgYAmvV+kqWhUgDYwNNz1qDaoS8XdsOponutZ/0stRQ66mKAy8kNVNNQ6\noUx1XFl1WUt4iyFY/2Rz2fZhLz5/TbZRK5ygo666WgnxB/Ud4GAx/BPQTghOJJOL\n00vJk+8jVCGNDc942V6nFXznDMXwqxhRCW6dm+2lTh7ntrli8mCk5gIUCJZKAMAz\nkyr2vl2Pe48adi8Vs9s=\n-----END DSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa new file mode 100644 index 0000000..4504f18 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa @@ -0,0 +1,26 @@ +PuTTY-User-Key-File-2: ssh-rsa +Encryption: none +Comment: rsa-key-20150522 +Public-Lines: 6 +AAAAB3NzaC1yc2EAAAABJQAAAQB1quqP0rhl78NOLD4lj+1x5FGAqZ3aqo6GiEPz +KOaQmy86FuJMK0nHj3gUKTa/Kvaa+8PZyeu+uVseHg47YrynCOcJEEnpqvbArc8M +xMWuUnTUMrjvokGDOBBiQu4UAE4bybpgXkNHJfbrcDVgivmv3Ikn8PVIZ1rLBMLZ +6Lzn0rjPjFD0X4WqsAJW2SFiZnsjMZtVL2TWadNTyyfjjm2NCRBvd32VLohkSe9Q +BZBD6MW8YQyBKUnEF/7WNY0eehDVrfx1YqPOV1bDwFUhRaAYpLDLDR0KCAPvx7qb +8G5Cq0TIBsEr3H8ztNRcOTQoaKgn0T18M7cyS4ykoNLYW4Zx +Private-Lines: 14 +AAABACyF3DZraF3sBLXLjSL4MFSblHXfUHxAiPSiQzlpa/9dUCPRTrUJddzOgHZU +yJtcXU9mLm4VDRe7wZyxbSs6Hd5WZUGzIuLLEUH8k4hKdE/MLDSdkhV7qhX5iaij +tAeRaammRoVUGXTd7rnzGx2cXnnkvkZ22VmqkQ6MLg1DTmWNfOO9cdwFGdQawf/n +yUV0nTkWsHXy5Qrozq9wRFk8eyw+pFllxqavsNftZX8VDiQt27JLZPTU4LGkH660 +3gq1KhNS/l05TlXnMZGjlcPN8UEaBzmCWRezhJSttjs5Kgp1K3yDf4ozMR/HWOCj +Jq8fd3VIgli6ML8yjr/c0A0T9MUAAACBAL1/byxHiCvY/2C+/L5T+ZZq13jdZuYK +MmOFaNITgEdNGWSIFYRzhLKGXj7awQWOIW6chj470GNOfQjFL1TvXhbwfqW6esDa +kETOYQPYQHZijABcn7uurMUm/bu5x/z9gYkAfniOCI5vmvMvJ09JcZ0iUmFWDZZY +fAutBvrt+n/vAAAAgQCe9jrA51wn1/wzKmWF+2+OWFUG9usheIcEbHB8mxLguLfU ++x4i+2vLo0FtXEPAw+Bt7Tge4t0m6USiVZXtW/QKsh0kMj4mNVHFz+XXw4l1QOYv +n5TjnLepiP7majXv4GHI2eOcHkyly4sIkj4jNLYqvT86hMxW4IC+jtJEWhn/nwAA +AIEAlJ8cExu2WrWukTDJQHrVegtvdJUhNjol2wLucPuWwSxKuB8FHYwaPRYRkf3d +DkZ53hhjJZ0BVkAaQ28uqM09xKD+q1H4/r0nnbtlV4uHLl3cCD5mGrH8I/iDPJX4 +fFIqCa0+n1D6RzvDqs1QIu+PGSp0K6vHOOS5fP0ZpuT025E= +Private-MAC: 4ca26008c85b901f4d2766b0924c25e527678d7e diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa.result new file mode 100644 index 0000000..9ac4d2f --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "rsa-key-20150522", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBHzANBgkqhkiG9w0BAQEFAAOCAQwAMIIBBwKCAQB1quqP0rhl78NOLD4lj+1x\n5FGAqZ3aqo6GiEPzKOaQmy86FuJMK0nHj3gUKTa/Kvaa+8PZyeu+uVseHg47Yryn\nCOcJEEnpqvbArc8MxMWuUnTUMrjvokGDOBBiQu4UAE4bybpgXkNHJfbrcDVgivmv\n3Ikn8PVIZ1rLBMLZ6Lzn0rjPjFD0X4WqsAJW2SFiZnsjMZtVL2TWadNTyyfjjm2N\nCRBvd32VLohkSe9QBZBD6MW8YQyBKUnEF/7WNY0eehDVrfx1YqPOV1bDwFUhRaAY\npLDLDR0KCAPvx7qb8G5Cq0TIBsEr3H8ztNRcOTQoaKgn0T18M7cyS4ykoNLYW4Zx\nAgEl\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAABJQAAAQB1quqP0rhl78NOLD4lj+1x5FGAqZ3aqo6GiEPzKOaQmy86FuJMK0nHj3gUKTa/Kvaa+8PZyeu+uVseHg47YrynCOcJEEnpqvbArc8MxMWuUnTUMrjvokGDOBBiQu4UAE4bybpgXkNHJfbrcDVgivmv3Ikn8PVIZ1rLBMLZ6Lzn0rjPjFD0X4WqsAJW2SFiZnsjMZtVL2TWadNTyyfjjm2NCRBvd32VLohkSe9QBZBD6MW8YQyBKUnEF/7WNY0eehDVrfx1YqPOV1bDwFUhRaAYpLDLDR0KCAPvx7qb8G5Cq0TIBsEr3H8ztNRcOTQoaKgn0T18M7cyS4ykoNLYW4Zx", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIIEoAIBAAKCAQB1quqP0rhl78NOLD4lj+1x5FGAqZ3aqo6GiEPzKOaQmy86FuJM\nK0nHj3gUKTa/Kvaa+8PZyeu+uVseHg47YrynCOcJEEnpqvbArc8MxMWuUnTUMrjv\nokGDOBBiQu4UAE4bybpgXkNHJfbrcDVgivmv3Ikn8PVIZ1rLBMLZ6Lzn0rjPjFD0\nX4WqsAJW2SFiZnsjMZtVL2TWadNTyyfjjm2NCRBvd32VLohkSe9QBZBD6MW8YQyB\nKUnEF/7WNY0eehDVrfx1YqPOV1bDwFUhRaAYpLDLDR0KCAPvx7qb8G5Cq0TIBsEr\n3H8ztNRcOTQoaKgn0T18M7cyS4ykoNLYW4ZxAgElAoIBACyF3DZraF3sBLXLjSL4\nMFSblHXfUHxAiPSiQzlpa/9dUCPRTrUJddzOgHZUyJtcXU9mLm4VDRe7wZyxbSs6\nHd5WZUGzIuLLEUH8k4hKdE/MLDSdkhV7qhX5iaijtAeRaammRoVUGXTd7rnzGx2c\nXnnkvkZ22VmqkQ6MLg1DTmWNfOO9cdwFGdQawf/nyUV0nTkWsHXy5Qrozq9wRFk8\neyw+pFllxqavsNftZX8VDiQt27JLZPTU4LGkH6603gq1KhNS/l05TlXnMZGjlcPN\n8UEaBzmCWRezhJSttjs5Kgp1K3yDf4ozMR/HWOCjJq8fd3VIgli6ML8yjr/c0A0T\n9MUCgYEAvX9vLEeIK9j/YL78vlP5lmrXeN1m5goyY4Vo0hOAR00ZZIgVhHOEsoZe\nPtrBBY4hbpyGPjvQY059CMUvVO9eFvB+pbp6wNqQRM5hA9hAdmKMAFyfu66sxSb9\nu7nH/P2BiQB+eI4Ijm+a8y8nT0lxnSJSYVYNllh8C60G+u36f+8CgYEAnvY6wOdc\nJ9f8MyplhftvjlhVBvbrIXiHBGxwfJsS4Li31PseIvtry6NBbVxDwMPgbe04HuLd\nJulEolWV7Vv0CrIdJDI+JjVRxc/l18OJdUDmL5+U45y3qYj+5mo17+BhyNnjnB5M\npcuLCJI+IzS2Kr0/OoTMVuCAvo7SRFoZ/58CgYBM0sw0i7O+v8F6P5blYFBtaZWf\ns7QYEfjAkAfmdpvJ4Px03Tkn284DL439zk5AhbqGydWO2fqJH9HTH4HkKbCF1x6W\nNtfRpLcHIzwWUMAv/nAb0oXyJDg0QD1Z8V7qBehn+UgHXCz7eVp+Q4x6FtsIWgW4\nwgWCI99DAPT98cZrNwKBgBEvYEw0sAROs3snLZHxqzH7tipENRhgDpixxvi20ZvA\n8Ud1GAPIJ1RJACd/mJ83xTxQ/yXvAybNHC05r1fuQ+V7ChHAPhH37SokUDMAYeMp\nnFgs7YBj+C4A+PZQq+KUzE0Qovwe84eLoFP0ImSrwKqsrOO7VFxrTDBGyp+bCbrF\nAoGBAJSfHBMbtlq1rpEwyUB61XoLb3SVITY6JdsC7nD7lsEsSrgfBR2MGj0WEZH9\n3Q5Ged4YYyWdAVZAGkNvLqjNPcSg/qtR+P69J527ZVeLhy5d3Ag+Zhqx/CP4gzyV\n+HxSKgmtPp9Q+kc7w6rNUCLvjxkqdCurxzjkuXz9Gabk9NuR\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2-streams/test/fixtures/encrypted-rsa.ppk b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc similarity index 100% rename from reverse_engineering/node_modules/ssh2-streams/test/fixtures/encrypted-rsa.ppk rename to reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc.result new file mode 100644 index 0000000..f9ff958 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/ppk_rsa_enc.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "rsa-key-20141119", + "public": "-----BEGIN PUBLIC KEY-----\nMIGcMA0GCSqGSIb3DQEBAQUAA4GKADCBhgKBgGsFYRMBUDIma40bnePBM0OVshwf\nmWsS9zHqXHlszoQqDReY4gf3pWpSNLt5FFNMP2WkEDyFiGSs6M7H3f8lYH+lxU3z\n8HcNgeyFP04FbUMKSs3C63alsnahk4GKuGECv7GpYWvfnnUWpvNoIhek4q5uvgRw\njAKKkGXo/EtRJ8eDAgEl\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAABJQAAAIBrBWETAVAyJmuNG53jwTNDlbIcH5lrEvcx6lx5bM6EKg0XmOIH96VqUjS7eRRTTD9lpBA8hYhkrOjOx93/JWB/pcVN8/B3DYHshT9OBW1DCkrNwut2pbJ2oZOBirhhAr+xqWFr3551FqbzaCIXpOKubr4EcIwCipBl6PxLUSfHgw==", + "private": "-----BEGIN RSA PRIVATE KEY-----\nMIICWQIBAAKBgGsFYRMBUDIma40bnePBM0OVshwfmWsS9zHqXHlszoQqDReY4gf3\npWpSNLt5FFNMP2WkEDyFiGSs6M7H3f8lYH+lxU3z8HcNgeyFP04FbUMKSs3C63al\nsnahk4GKuGECv7GpYWvfnnUWpvNoIhek4q5uvgRwjAKKkGXo/EtRJ8eDAgElAoGA\nU+GfHLvXEozQ1mHA8MfcEmCShL7SMVQN2wPL8HfgImYl7+aHpWE8de1nmdtwy6p2\n4PY2PUYQ9PY57i3zL8NZd8WQ7Rg0RBHDlndaFeF4Ef0uLboqYd/xN0rzfy55z7hW\nOL+8VhoxTrBUvveOhZwBPkOeHfxmkVz3xbbrg3kNlo0CQQDJYPKtCs/l46KJmN3l\nUANdI4QIuWQ+Zllz7p94FfdotnkvqG++Bp1wOqJSCih6UViwLfvpNZtGMCtk46WN\nhc0zAkEAiAyN4WUs/0x4WovG956J1A+uSEKeWzuqfpGGbWgZ9XfnPnk+1Al8FOW1\ntu9WWrMPIavQnZW/dXxhkeNWTH78cQJBALkM+qzZgMVpZO0ksDqA4H8Zt5lQafQm\nsxCWFf+le5CnraFqWNghwRsFcpCTtn486bamy89hsUdqiL2S6ygaFoECQFDk3r1e\nwM8mjMA3b2LM+AGMyH3+GPf59qwfLVXPMgeTZubgTt7w4f6WbAvoQS8Crw0aDVbH\nvfLUVbCwr9p1BM0CQFSBjCa/fzeICVkPFBaKQUmXjQ3IcPTOr90mSAiPnAAppSwT\nj5SYSfE9rSVb+EhQ0hk2VKWIfocNHBD1MAN9zb4=\n-----END RSA PRIVATE KEY-----" +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub new file mode 100644 index 0000000..3bfd6e8 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub @@ -0,0 +1,9 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: "2048-bit RSA" +AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKC +nbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCH +S/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1m +gJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW +61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc +9lK/C2jItA3fwq9PHfCM1D +---- END SSH2 PUBLIC KEY ---- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub.result new file mode 100644 index 0000000..fcc0553 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "2048-bit RSA", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub new file mode 100644 index 0000000..e42f5c1 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub @@ -0,0 +1,10 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: 2048-bit RSA +AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKC +nbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCH +S/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1m +gJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW +61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc +9lK/C2jItA3fwq9PHfCM1D +---- END SSH2 PUBLIC KEY ---- + diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub.result new file mode 100644 index 0000000..fcc0553 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa2.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "2048-bit RSA", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub new file mode 100644 index 0000000..24a107b --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: this is a special \ +multi-line comment\ + how cool is that not? +AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKC +nbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCH +S/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1m +gJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW +61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc +9lK/C2jItA3fwq9PHfCM1D +---- END SSH2 PUBLIC KEY ---- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub.result new file mode 100644 index 0000000..25dae67 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa3.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "this is a special multi-line comment how cool is that not?", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub new file mode 100644 index 0000000..0454a85 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Comment: "this is a special \ +multi-line comment\ + how cool is that not?" +AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKC +nbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCH +S/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1m +gJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW +61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc +9lK/C2jItA3fwq9PHfCM1D +---- END SSH2 PUBLIC KEY ---- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub.result new file mode 100644 index 0000000..25dae67 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa4.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "this is a special multi-line comment how cool is that not?", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub new file mode 100644 index 0000000..14608c1 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub @@ -0,0 +1,8 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKC +nbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCH +S/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1m +gJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW +61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc +9lK/C2jItA3fwq9PHfCM1D +---- END SSH2 PUBLIC KEY ---- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub.result new file mode 100644 index 0000000..a61d779 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa5.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub new file mode 100644 index 0000000..24a2261 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub @@ -0,0 +1,13 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +Subject: "nodejs" +x-foo: something\ +completely\ +different +Comment: "Foo bar baz" +AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKC +nbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCH +S/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1m +gJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW +61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc +9lK/C2jItA3fwq9PHfCM1D +---- END SSH2 PUBLIC KEY ---- diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub.result b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub.result new file mode 100644 index 0000000..ed7a4f5 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/keyParser/rfc4716_rsa6.pub.result @@ -0,0 +1,7 @@ +{ + "type": "ssh-rsa", + "comment": "Foo bar baz", + "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4q6eZdx7LYh46PcZNcS3\nCnO7GuYsEJZeTj5LQSgp21IyTelaBPprijnMwKa+pLQt5TEobpKFFNecPdT6oPoO\nKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHMBNkoTFeGrursPkqYRJ0HL4CqYq\nRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKbzibJc64JFM7tUoK6Vl64\nYiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs8zjxsf6c6N2tKX\nkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38KvTx3wjN\nQwIDAQAB\n-----END PUBLIC KEY-----", + "publicSSH": "AAAAB3NzaC1yc2EAAAADAQABAAABAQDirp5l3HstiHjo9xk1xLcKc7sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+lfQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg64MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1D", + "private": null +} diff --git a/reverse_engineering/node_modules/ssh2/test/fixtures/openssh_new_rsa b/reverse_engineering/node_modules/ssh2/test/fixtures/openssh_new_rsa new file mode 100644 index 0000000..ccded2a --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/fixtures/openssh_new_rsa @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEA4q6eZdx7LYh46PcZNcS3CnO7GuYsEJZeTj5LQSgp21IyTelaBPpr +ijnMwKa+pLQt5TEobpKFFNecPdT6oPoOKKMe6oH/pX0BNyAEB9KFZfZgh0v4J4IOiO0KHM +BNkoTFeGrursPkqYRJ0HL4CqYqRdINy1sgDU6jUIOuDD5XZzlpDXb1ftZoCei9OHSWrMKb +zibJc64JFM7tUoK6Vl64YiPgxsNXOJYMTrelVJYebtsNrJFmh3XXQABDVutWMYb8I6IrNs +8zjxsf6c6N2tKXkk9G4EDKKip4g0bzDmD/fREPQ9vLi59N+ZsyjWCKKE3PZSvwtoyLQN38 +KvTx3wjNQwAAA8hLhVBxS4VQcQAAAAdzc2gtcnNhAAABAQDirp5l3HstiHjo9xk1xLcKc7 +sa5iwQll5OPktBKCnbUjJN6VoE+muKOczApr6ktC3lMShukoUU15w91Pqg+g4oox7qgf+l +fQE3IAQH0oVl9mCHS/gngg6I7QocwE2ShMV4au6uw+SphEnQcvgKpipF0g3LWyANTqNQg6 +4MPldnOWkNdvV+1mgJ6L04dJaswpvOJslzrgkUzu1SgrpWXrhiI+DGw1c4lgxOt6VUlh5u +2w2skWaHdddAAENW61Yxhvwjois2zzOPGx/pzo3a0peST0bgQMoqKniDRvMOYP99EQ9D28 +uLn035mzKNYIooTc9lK/C2jItA3fwq9PHfCM1DAAAAAwEAAQAAAQAmShSbZBiyYkD6KPLr +MCUy8MWED6kVzDB1yvPvN5eKYmH44xe/i4UqvgSl7gR50a2G7zzDIKC2Go1brGQBWPuXRa +ZtOjQygeD4rMHBiH/b7zfy4pQyKDfITTHOFXWE8ERiyL00bAZt09icCy92rQaq8IY/+U56 +sPPJH9UAYG9nEev8opFjAWToFDu0U2+dC+lbqLlXDqDRo75NlnDFmgUoja3y2eFr9A0Cc+ +hjecrdxyJFsCJfEfaLWtBnZb886gqzzvfbHImSQtBAKERcSxuki7uxMoP67g3iQOXa65uz +8kFWRNmbQTGQttakoUaybh1t9eLpBqvVON/4Kg0THShRAAAAgFBTz2ajBK/R/crOSL9VK1 +f7oQv2iJTRVfnUs0r+qPGgf/a/5UwkGRj0KfEWBp3qYD+keShnPr6PDPFrm8UmIdUX8AY7 +3tWT2K/JQVlzJNuINsw+DNjn4M17Z25q0LPmReRWL0nRc2w6W/hmQ/Jmqz6w8Qc4+xpeqS +/HG5feliVnAAAAgQD90a+5Ky3o/2YtueqRf/3dKoiMgGB7JAOzye4dDKGABSlWuQ4N4xEI +CW5MSTp7i/uobTF/tyFO3tTSyb5b2Xwbn/kLO0vgvFCdUGR2BQfN3mcT92T0Gn3JDF3Wym +i2mgU6qnPf+eu+RKZQ9IiyNGny61ROUQa0R0z0pgiAfA89xwAAAIEA5KE9i6hHmigJwfD7 +/AGI4ujyWIVpNyrTdXG3HAPhsdoFuG5ggHggrPuuBF9wNcosrhL20VNOQGHg15gWZIVudu +0qxky4ivQs67Sk9XUjuvTnf+VubM51rIsmh4atKJFSSZo78DEcTRt8aXLrSNvGQ4WPRweM +2Z0YGfMMDM9KJKUAAAASbmV3IG9wZW5zc2ggZm9ybWF0AQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/reverse_engineering/node_modules/ssh2/test/test-client-server.js b/reverse_engineering/node_modules/ssh2/test/test-client-server.js deleted file mode 100644 index f8d3854..0000000 --- a/reverse_engineering/node_modules/ssh2/test/test-client-server.js +++ /dev/null @@ -1,1902 +0,0 @@ -var Client = require('../lib/client'); -var Server = require('../lib/server'); -var OPEN_MODE = require('ssh2-streams').SFTPStream.OPEN_MODE; -var STATUS_CODE = require('ssh2-streams').SFTPStream.STATUS_CODE; -var utils = require('ssh2-streams').utils; - -var semver = require('semver'); - -var net = require('net'); -var fs = require('fs'); -var crypto = require('crypto'); -var path = require('path'); -var join = path.join; -var inspect = require('util').inspect; -var assert = require('assert'); - -var t = -1; -var group = path.basename(__filename, '.js') + '/'; -var fixturesdir = join(__dirname, 'fixtures'); - -var USER = 'nodejs'; -var PASSWORD = 'FLUXCAPACITORISTHEPOWER'; -var MD5_HOST_FINGERPRINT = '64254520742d3d0792e918f3ce945a64'; -var KEY_RSA_BAD = fs.readFileSync(join(fixturesdir, 'bad_rsa_private_key')); -var HOST_KEY_RSA = fs.readFileSync(join(fixturesdir, 'ssh_host_rsa_key')); -var HOST_KEY_DSA = fs.readFileSync(join(fixturesdir, 'ssh_host_dsa_key')); -var HOST_KEY_ECDSA = fs.readFileSync(join(fixturesdir, 'ssh_host_ecdsa_key')); -var CLIENT_KEY_ENC_RSA = fs.readFileSync(join(fixturesdir, 'id_rsa_enc')); -var CLIENT_KEY_ENC_RSA_PUB = utils.parseKey(CLIENT_KEY_ENC_RSA); -utils.decryptKey(CLIENT_KEY_ENC_RSA_PUB, 'foobarbaz'); -CLIENT_KEY_ENC_RSA_PUB = utils.genPublicKey(CLIENT_KEY_ENC_RSA_PUB); -var CLIENT_KEY_PPK_RSA = fs.readFileSync(join(fixturesdir, 'id_rsa.ppk')); -var CLIENT_KEY_PPK_RSA_PUB = utils.parseKey(CLIENT_KEY_PPK_RSA); -var CLIENT_KEY_RSA = fs.readFileSync(join(fixturesdir, 'id_rsa')); -var CLIENT_KEY_RSA_PUB = utils.genPublicKey(utils.parseKey(CLIENT_KEY_RSA)); -var CLIENT_KEY_DSA = fs.readFileSync(join(fixturesdir, 'id_dsa')); -var CLIENT_KEY_DSA_PUB = utils.genPublicKey(utils.parseKey(CLIENT_KEY_DSA)); -if (semver.gte(process.version, '5.2.0')) { - var CLIENT_KEY_ECDSA = fs.readFileSync(join(fixturesdir, 'id_ecdsa')); - var CLIENT_KEY_ECDSA_PUB = utils.genPublicKey( - utils.parseKey(CLIENT_KEY_ECDSA) - ); -} -var DEBUG = false; - -var tests = [ - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - privateKey: CLIENT_KEY_RSA - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'publickey', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-rsa', - makeMsg('Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_RSA_PUB.public, - ctx.key.data, - makeMsg('Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('RSA-SHA1'); - var pem = CLIENT_KEY_RSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg('Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with an RSA key' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - privateKey: CLIENT_KEY_ENC_RSA, - passphrase: 'foobarbaz', - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'publickey', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-rsa', - makeMsg('Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_ENC_RSA_PUB.public, - ctx.key.data, - makeMsg('Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('RSA-SHA1'); - var pem = CLIENT_KEY_ENC_RSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg('Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with an encrypted RSA key' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - privateKey: CLIENT_KEY_PPK_RSA - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'publickey', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-rsa', - makeMsg('Unexpected key algo: ' + ctx.key.algo)); - if (ctx.signature) { - var verifier = crypto.createVerify('RSA-SHA1'); - var pem = CLIENT_KEY_PPK_RSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg('Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with an RSA key (PPK)' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - privateKey: CLIENT_KEY_DSA - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'publickey', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-dss', - makeMsg('Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_DSA_PUB.public, - ctx.key.data, - makeMsg('Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('DSA-SHA1'); - var pem = CLIENT_KEY_DSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg('Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with a DSA key' - }, - { run: function() { - if (semver.lt(process.version, '5.2.0')) - return next(); - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - privateKey: CLIENT_KEY_ECDSA - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'publickey', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ecdsa-sha2-nistp256', - makeMsg('Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_ECDSA_PUB.public, - ctx.key.data, - makeMsg('Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('sha256'); - var pem = CLIENT_KEY_ECDSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg('Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with a ECDSA key' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: 'asdf', - algorithms: { - serverHostKey: ['ssh-dss'] - } - }, - { hostKeys: [HOST_KEY_DSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === 'asdf', - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Server with DSA host key' - }, - { run: function() { - if (semver.lt(process.version, '5.2.0')) - return next(); - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: 'asdf' - }, - { hostKeys: [HOST_KEY_ECDSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === 'asdf', - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Server with ECDSA host key' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: 'asdf', - algorithms: { - serverHostKey: 'ssh-rsa' - } - }, - { hostKeys: [HOST_KEY_RSA, HOST_KEY_DSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === 'asdf', - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Server with multiple host keys (RSA selected)' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: 'asdf', - algorithms: { - serverHostKey: 'ssh-dss' - } - }, - { hostKeys: [HOST_KEY_RSA, HOST_KEY_DSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === 'asdf', - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Server with multiple host keys (DSA selected)' - }, - { run: function() { - var client; - var server; - var r; - var hostname = 'foo'; - var username = 'bar'; - - r = setup( - this, - { username: USER, - privateKey: CLIENT_KEY_RSA, - localHostname: hostname, - localUsername: username - }, - { hostKeys: [ HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - if (ctx.method === 'hostbased') { - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-rsa', - makeMsg('Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_RSA_PUB.public, - ctx.key.data, - makeMsg('Public key mismatch')); - assert(ctx.signature, - makeMsg('Expected signature')); - assert(ctx.localHostname === hostname, - makeMsg('Wrong local hostname')); - assert(ctx.localUsername === username, - makeMsg('Wrong local username')); - var verifier = crypto.createVerify('RSA-SHA1'); - var pem = CLIENT_KEY_RSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg('Could not verify hostbased signature')); - ctx.accept(); - } else - ctx.reject(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with hostbased' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === PASSWORD, - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Authenticate with a password' - }, - { run: function() { - var client; - var server; - var r; - var verified = false; - - r = setup( - this, - { username: USER, - password: PASSWORD, - hostHash: 'md5', - hostVerifier: function(hash) { - assert(hash === MD5_HOST_FINGERPRINT, - makeMsg('Host fingerprint mismatch')); - return (verified = true); - } - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }).on('close', function() { - assert(verified, makeMsg('Failed to verify host fingerprint')); - }); - }, - what: 'Verify host fingerprint' - }, - { run: function() { - var client; - var server; - var r; - var out = ''; - var outErr = ''; - var exitArgs; - var closeArgs; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(); - session.once('exec', function(accept, reject, info) { - assert(info.command === 'foo --bar', - makeMsg('Wrong exec command: ' + info.command)); - var stream = accept(); - stream.stderr.write('stderr data!\n'); - stream.write('stdout data!\n'); - stream.exit(100); - stream.end(); - conn.end(); - }); - }); - }); - }); - client.on('ready', function() { - client.exec('foo --bar', function(err, stream) { - assert(!err, makeMsg('Unexpected exec error: ' + err)); - stream.on('data', function(d) { - out += d; - }).on('exit', function(code) { - exitArgs = new Array(arguments.length); - for (var i = 0; i < exitArgs.length; ++i) - exitArgs[i] = arguments[i]; - }).on('close', function(code) { - closeArgs = new Array(arguments.length); - for (var i = 0; i < closeArgs.length; ++i) - closeArgs[i] = arguments[i]; - }).stderr.on('data', function(d) { - outErr += d; - }); - }); - }).on('end', function() { - assert.deepEqual(exitArgs, - [100], - makeMsg('Wrong exit args: ' + inspect(exitArgs))); - assert.deepEqual(closeArgs, - [100], - makeMsg('Wrong close args: ' + inspect(closeArgs))); - assert(out === 'stdout data!\n', - makeMsg('Wrong stdout data: ' + inspect(out))); - assert(outErr === 'stderr data!\n', - makeMsg('Wrong stderr data: ' + inspect(outErr))); - }); - }, - what: 'Simple exec' - }, - { run: function() { - var client; - var server; - var r; - var out = ''; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(), - env = {}; - session.once('env', function(accept, reject, info) { - env[info.key] = info.val; - accept && accept(); - }).once('exec', function(accept, reject, info) { - assert(info.command === 'foo --bar', - makeMsg('Wrong exec command: ' + info.command)); - var stream = accept(); - stream.write(''+env.SSH2NODETEST); - stream.exit(100); - stream.end(); - conn.end(); - }); - }); - }); - }); - client.on('ready', function() { - client.exec('foo --bar', - { env: { SSH2NODETEST: 'foo' } }, - function(err, stream) { - assert(!err, makeMsg('Unexpected exec error: ' + err)); - stream.on('data', function(d) { - out += d; - }); - }); - }).on('end', function() { - assert(out === 'foo', - makeMsg('Wrong stdout data: ' + inspect(out))); - }); - }, - what: 'Exec with environment set' - }, - { run: function() { - var client; - var server; - var r; - var out = ''; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(); - var ptyInfo; - session.once('pty', function(accept, reject, info) { - ptyInfo = info; - accept && accept(); - }).once('exec', function(accept, reject, info) { - assert(info.command === 'foo --bar', - makeMsg('Wrong exec command: ' + info.command)); - var stream = accept(); - stream.write(JSON.stringify(ptyInfo)); - stream.exit(100); - stream.end(); - conn.end(); - }); - }); - }); - }); - var pty = { - rows: 2, - cols: 4, - width: 0, - height: 0, - term: 'vt220', - modes: {} - }; - client.on('ready', function() { - client.exec('foo --bar', - { pty: pty }, - function(err, stream) { - assert(!err, makeMsg('Unexpected exec error: ' + err)); - stream.on('data', function(d) { - out += d; - }); - }); - }).on('end', function() { - assert.deepEqual(JSON.parse(out), - pty, - makeMsg('Wrong stdout data: ' + inspect(out))); - }); - }, - what: 'Exec with pty set' - }, - { run: function() { - var client; - var server; - var r; - var out = ''; - - r = setup( - this, - { username: USER, - password: PASSWORD, - agent: '/foo/bar/baz' - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(); - var authAgentReq = false; - session.once('auth-agent', function(accept, reject) { - authAgentReq = true; - accept && accept(); - }).once('exec', function(accept, reject, info) { - assert(info.command === 'foo --bar', - makeMsg('Wrong exec command: ' + info.command)); - var stream = accept(); - stream.write(inspect(authAgentReq)); - stream.exit(100); - stream.end(); - conn.end(); - }); - }); - }); - }); - client.on('ready', function() { - client.exec('foo --bar', - { agentForward: true }, - function(err, stream) { - assert(!err, makeMsg('Unexpected exec error: ' + err)); - stream.on('data', function(d) { - out += d; - }); - }); - }).on('end', function() { - assert(out === 'true', - makeMsg('Wrong stdout data: ' + inspect(out))); - }); - }, - what: 'Exec with OpenSSH agent forwarding' - }, - { run: function() { - var client; - var server; - var r; - var out = ''; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(); - var x11 = false; - session.once('x11', function(accept, reject, info) { - x11 = true; - accept && accept(); - }).once('exec', function(accept, reject, info) { - assert(info.command === 'foo --bar', - makeMsg('Wrong exec command: ' + info.command)); - var stream = accept(); - stream.write(inspect(x11)); - stream.exit(100); - stream.end(); - conn.end(); - }); - }); - }); - }); - client.on('ready', function() { - client.exec('foo --bar', - { x11: true }, - function(err, stream) { - assert(!err, makeMsg('Unexpected exec error: ' + err)); - stream.on('data', function(d) { - out += d; - }); - }); - }).on('end', function() { - assert(out === 'true', - makeMsg('Wrong stdout data: ' + inspect(out))); - }); - }, - what: 'Exec with X11 forwarding' - }, - { run: function() { - var client; - var server; - var r; - var out = ''; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(); - var sawPty = false; - session.once('pty', function(accept, reject, info) { - sawPty = true; - accept && accept(); - }).once('shell', function(accept, reject) { - var stream = accept(); - stream.write('Cowabunga dude! ' + inspect(sawPty)); - stream.end(); - conn.end(); - }); - }); - }); - }); - client.on('ready', function() { - client.shell(function(err, stream) { - assert(!err, makeMsg('Unexpected exec error: ' + err)); - stream.on('data', function(d) { - out += d; - }); - }); - }).on('end', function() { - assert(out === 'Cowabunga dude! true', - makeMsg('Wrong stdout data: ' + inspect(out))); - }); - }, - what: 'Simple shell' - }, - { run: function() { - var client; - var server; - var r; - var expHandle = new Buffer([1, 2, 3, 4]); - var sawOpenS = false; - var sawCloseS = false; - var sawOpenC = false; - var sawCloseC = false; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.once('session', function(accept, reject) { - var session = accept(); - session.once('sftp', function(accept, reject) { - if (accept) { - var sftp = accept(); - sftp.once('OPEN', function(id, filename, flags, attrs) { - assert(id === 0, - makeMsg('Unexpected sftp request ID: ' + id)); - assert(filename === 'node.js', - makeMsg('Unexpected filename: ' + filename)); - assert(flags === OPEN_MODE.READ, - makeMsg('Unexpected flags: ' + flags)); - sawOpenS = true; - sftp.handle(id, expHandle); - sftp.once('CLOSE', function(id, handle) { - assert(id === 1, - makeMsg('Unexpected sftp request ID: ' + id)); - assert.deepEqual(handle, - expHandle, - makeMsg('Wrong sftp file handle: ' - + inspect(handle))); - sawCloseS = true; - sftp.status(id, STATUS_CODE.OK); - conn.end(); - }); - }); - } - }); - }); - }); - }); - client.on('ready', function() { - client.sftp(function(err, sftp) { - assert(!err, makeMsg('Unexpected sftp error: ' + err)); - sftp.open('node.js', 'r', function(err, handle) { - assert(!err, makeMsg('Unexpected sftp error: ' + err)); - assert.deepEqual(handle, - expHandle, - makeMsg('Wrong sftp file handle: ' - + inspect(handle))); - sawOpenC = true; - sftp.close(handle, function(err) { - assert(!err, makeMsg('Unexpected sftp error: ' + err)); - sawCloseC = true; - }); - }); - }); - }).on('end', function() { - assert(sawOpenS, makeMsg('Expected sftp open()')); - assert(sawOpenC, makeMsg('Expected sftp open() callback')); - assert(sawCloseS, makeMsg('Expected sftp open()')); - assert(sawOpenC, makeMsg('Expected sftp close() callback')); - }); - }, - what: 'Simple SFTP' - }, - { run: function() { - var client; - var server; - var state = { - readies: 0, - closes: 0 - }; - var clientcfg = { - username: USER, - password: PASSWORD - }; - var servercfg = { - hostKeys: [HOST_KEY_RSA] - }; - var reconnect = false; - - client = new Client(), - server = new Server(servercfg); - - function onReady() { - assert(++state.readies <= 4, - makeMsg('Wrong ready count: ' + state.readies)); - } - function onClose() { - assert(++state.closes <= 3, - makeMsg('Wrong close count: ' + state.closes)); - if (state.closes === 2) - server.close(); - else if (state.closes === 3) - next(); - } - - server.listen(0, 'localhost', function() { - clientcfg.host = 'localhost'; - clientcfg.port = server.address().port; - client.connect(clientcfg); - }); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', onReady); - }).on('close', onClose); - client.on('ready', function() { - onReady(); - if (reconnect) - client.end(); - else { - reconnect = true; - client.connect(clientcfg); - } - }).on('close', onClose); - }, - what: 'connect() on connected client' - }, - { run: function() { - var client = new Client({ - username: USER, - password: PASSWORD - }); - - assert.throws(function() { - client.exec('uptime', function(err, stream) { - assert(false, makeMsg('Callback unexpectedly called')); - }); - }); - next(); - }, - what: 'Throw when not connected' - }, - { run: function() { - var client; - var server; - var r; - var calledBack = 0; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }); - }); - client.on('ready', function() { - function callback(err, stream) { - assert(err, makeMsg('Expected error')); - assert(err.message === 'No response from server', - makeMsg('Wrong error message: ' + err.message)); - ++calledBack; - } - client.exec('uptime', callback); - client.shell(callback); - client.sftp(callback); - client.end(); - }).on('close', function() { - // give the callbacks a chance to execute - process.nextTick(function() { - assert(calledBack === 3, - makeMsg('Only ' - + calledBack - + '/3 outstanding callbacks called')); - }); - }); - }, - what: 'Outstanding callbacks called on disconnect' - }, - { run: function() { - var client = new Client({ - username: USER, - password: PASSWORD - }); - - assert.throws(function() { - client.exec('uptime', function(err, stream) { - assert(false, makeMsg('Callback unexpectedly called')); - }); - }); - next(); - }, - what: 'Throw when not connected' - }, - { run: function() { - var client; - var server; - var r; - var calledBack = 0; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - session.once('exec', function(accept, reject, info) { - var stream = accept(); - stream.exit(0); - stream.end(); - }); - }); - }); - }); - client.on('ready', function() { - function callback(err, stream) { - assert(!err, makeMsg('Unexpected error: ' + err)); - stream.resume(); - if (++calledBack === 3) - client.end(); - } - client.exec('foo', callback); - client.exec('bar', callback); - client.exec('baz', callback); - }).on('end', function() { - assert(calledBack === 3, - makeMsg('Only ' - + calledBack - + '/3 callbacks called')); - }); - }, - what: 'Pipelined requests' - }, - { run: function() { - var client; - var server; - var r; - var calledBack = 0; - - r = setup( - this, - { username: USER, - password: PASSWORD, - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - var reqs = []; - conn.on('session', function(accept, reject) { - if (reqs.length === 0) { - conn.rekey(function(err) { - assert(!err, makeMsg('Unexpected rekey error: ' + err)); - reqs.forEach(function(accept) { - var session = accept(); - session.once('exec', function(accept, reject, info) { - var stream = accept(); - stream.exit(0); - stream.end(); - }); - }); - }); - } - reqs.push(accept); - }); - }); - }); - client.on('ready', function() { - function callback(err, stream) { - assert(!err, makeMsg('Unexpected error: ' + err)); - stream.resume(); - if (++calledBack === 3) - client.end(); - } - client.exec('foo', callback); - client.exec('bar', callback); - client.exec('baz', callback); - }).on('end', function() { - assert(calledBack === 3, - makeMsg('Only ' - + calledBack - + '/3 callbacks called')); - }); - }, - what: 'Pipelined requests with intermediate rekeying' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - session.once('exec', function(accept, reject, info) { - var stream = accept(); - stream.exit(0); - stream.end(); - }); - }); - }); - }); - client.on('ready', function() { - client.exec('foo', function(err, stream) { - assert(!err, makeMsg('Unexpected error: ' + err)); - stream.on('exit', function(code, signal) { - client.end(); - }); - }); - }); - }, - what: 'Ignore outgoing after stream close' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - accept().on('sftp', function(accept, reject) { - var sftp = accept(); - // XXX: hack to get channel ... - var channel = sftp._readableState.pipes; - - channel.unpipe(sftp); - sftp.unpipe(channel); - - channel.exit(127); - channel.close(); - }); - }); - }); - }); - client.on('ready', function() { - var timeout = setTimeout(function() { - assert(false, makeMsg('Unexpected SFTP timeout')); - }, 1000); - client.sftp(function(err, sftp) { - clearTimeout(timeout); - assert(err, makeMsg('Expected error')); - assert(err.code === 127, - makeMsg('Expected exit code 127, saw: ' + err.code)); - client.end(); - }); - }); - }, - what: 'SFTP server aborts with exit-status' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD, - sock: new net.Socket() - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() {}); - }); - client.on('ready', function() { - client.end(); - }); - }, - what: 'Double pipe on unconnected, passed in net.Socket' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }); - conn.on('request', function(accept, reject, name, info) { - accept(); - conn.forwardOut('good', 0, 'remote', 12345, function(err, ch) { - if (err) { - assert(!err, makeMsg('Unexpected error: ' + err)); - } - conn.forwardOut('bad', 0, 'remote', 12345, function(err, ch) { - assert(err, makeMsg('Should receive error')); - client.end(); - }); - }); - }); - }); - - client.on('ready', function() { - // request forwarding - client.forwardIn('good', 0, function(err, port) { - if (err) { - assert(!err, makeMsg('Unexpected error: ' + err)); - } - }); - }); - client.on('tcp connection', function(details, accept, reject) { - accept(); - }); - }, - what: 'Client auto-rejects unrequested, allows requested forwarded-tcpip' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA], - greeting: 'Hello world!' - } - ); - client = r.client; - server = r.server; - - var sawGreeting = false; - - client.on('greeting', function(greeting) { - assert.strictEqual(greeting, 'Hello world!\r\n'); - sawGreeting = true; - }); - client.on('banner', function(message) { - assert.fail(null, null, makeMsg('Unexpected banner')); - }); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(sawGreeting, makeMsg('Client did not see greeting')); - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === PASSWORD, - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Server greeting' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA], - banner: 'Hello world!' - } - ); - client = r.client; - server = r.server; - - var sawBanner = false; - - client.on('greeting', function(greeting) { - assert.fail(null, null, makeMsg('Unexpected greeting')); - }); - client.on('banner', function(message) { - assert.strictEqual(message, 'Hello world!\r\n'); - sawBanner = true; - }); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(sawBanner, makeMsg('Client did not see banner')); - assert(ctx.method === 'password', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg('Unexpected username: ' + ctx.username)); - assert(ctx.password === PASSWORD, - makeMsg('Unexpected password: ' + ctx.password)); - ctx.accept(); - }).on('ready', function() { - conn.end(); - }); - }); - }, - what: 'Server banner' - }, - { run: function() { - var client; - var server; - var r; - var fastRejectSent = false; - - function sendAcceptLater(accept) { - if (fastRejectSent) - accept(); - else - setImmediate(sendAcceptLater, accept); - } - - r = setup( - this, - { username: USER }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }); - - conn.on('request', function(accept, reject, name, info) { - if (info.bindAddr === 'fastReject') { - // Will call reject on 'fastReject' soon - reject(); - fastRejectSent = true; - } else - // but accept on 'slowAccept' later - sendAcceptLater(accept); - }); - }); - - client.on('ready', function() { - var replyCnt = 0; - - client.forwardIn('slowAccept', 0, function(err) { - assert(!err, makeMsg('Unexpected error: ' + err)); - if (++replyCnt === 2) - client.end(); - }); - - client.forwardIn('fastReject', 0, function(err) { - assert(err, makeMsg('Should receive error')); - if (++replyCnt === 2) - client.end(); - }); - }); - }, - what: 'Server responds to global requests in the right order' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - var timer; - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - session.once('subsystem', function(accept, reject, info) { - assert.equal(info.name, 'netconf'); - - // Prevent success reply from being sent - conn._sshstream.channelSuccess = function() {}; - - var stream = accept(); - stream.close(); - timer = setTimeout(function() { - throw new Error(makeMsg('Expected client callback')); - }, 50); - }); - }); - }); - }); - client.on('ready', function() { - client.subsys('netconf', function(err, stream) { - clearTimeout(timer); - assert(err); - client.end(); - }); - }); - }, - what: 'Cleanup outstanding channel requests on channel close' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER, - password: PASSWORD - }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - var timer; - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - session.once('exec', function(accept, reject, info) { - var stream = accept(); - // Write enough to bring the Client's channel window to 0 - // (currently 1MB) - var buf = new Buffer(2048); - for (var i = 0; i < 1000; ++i) - stream.write(buf); - stream.exit(0); - stream.close(); - }); - }); - }); - }); - client.on('ready', function() { - client.exec('foo', function(err, stream) { - var sawClose = false; - assert(!err, makeMsg('Unexpected error')); - client._sshstream.on('CHANNEL_CLOSE:' + stream.incoming.id, onClose); - function onClose() { - // This handler gets called *after* the internal handler, so we - // should have seen `stream`'s `close` event already if the bug - // exists - assert(!sawClose, makeMsg('Premature close event')); - client.end(); - } - stream.on('close', function() { - sawClose = true; - }); - }); - }); - }, - what: 'Channel emits close prematurely' - }, - { run: function() { - var client; - var server; - var r; - - r = setup( - this, - { username: USER }, - { hostKeys: [HOST_KEY_RSA], ident: 'OpenSSH_5.3' } - ); - client = r.client; - server = r.server; - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }); - conn.once('request', function(accept, reject, name, info) { - assert(name === 'tcpip-forward', - makeMsg('Unexpected request: ' + name)); - accept(1337); - conn.forwardOut('good', 0, 'remote', 12345, function(err, ch) { - assert(!err, makeMsg('Unexpected error: ' + err)); - client.end(); - }); - }); - }); - - client.on('ready', function() { - // request forwarding - client.forwardIn('good', 0, function(err, port) { - assert(!err, makeMsg('Unexpected error: ' + err)); - assert(port === 1337, makeMsg('Bad bound port: ' + port)); - }); - }); - client.on('tcp connection', function(details, accept, reject) { - assert(details.destIP === 'good', - makeMsg('Bad incoming destIP: ' + details.destIP)); - assert(details.destPort === 1337, - makeMsg('Bad incoming destPort: ' + details.destPort)); - assert(details.srcIP === 'remote', - makeMsg('Bad incoming srcIP: ' + details.srcIP)); - assert(details.srcPort === 12345, - makeMsg('Bad incoming srcPort: ' + details.srcPort)); - accept(); - }); - }, - what: 'OpenSSH 5.x workaround for binding on port 0' - }, - { run: function() { - var client; - var server; - var r; - var srvError; - var cliError; - - r = setup( - this, - { username: USER, - algorithms: { - cipher: [ 'aes128-cbc' ] - } - }, - { hostKeys: [HOST_KEY_RSA], - algorithms: { - cipher: [ 'aes128-ctr' ] - } - } - ); - client = r.client; - server = r.server; - - // Remove default client error handler added by `setup()` since we are - // expecting an error in this case - client.removeAllListeners('error'); - - function onError(err) { - if (this === client) { - assert(!cliError, makeMsg('Unexpected multiple client errors')); - cliError = err; - } else { - assert(!srvError, makeMsg('Unexpected multiple server errors')); - srvError = err; - } - assert(/handshake failed/i.test(err.message), - makeMsg('Wrong error message')); - } - - server.on('connection', function(conn) { - // Remove default server connection error handler added by `setup()` - // since we are expecting an error in this case - conn.removeAllListeners('error'); - - function onGoodHandshake() { - assert(false, makeMsg('Handshake should have failed')); - } - conn.on('authentication', onGoodHandshake); - conn.on('ready', onGoodHandshake); - - conn.on('error', onError); - }); - - client.on('ready', function() { - assert(false, makeMsg('Handshake should have failed')); - }); - client.on('error', onError); - client.on('close', function() { - assert(cliError, makeMsg('Expected client error')); - assert(srvError, makeMsg('Expected client error')); - }); - }, - what: 'Handshake errors are emitted' - }, - { run: function() { - var client; - var server; - var r; - var cliError; - - r = setup( - this, - { username: USER, privateKey: KEY_RSA_BAD }, - { hostKeys: [HOST_KEY_RSA] } - ); - client = r.client; - server = r.server; - - // Remove default client error handler added by `setup()` since we are - // expecting an error in this case - client.removeAllListeners('error'); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - assert(ctx.method === 'publickey' || ctx.method === 'none', - makeMsg('Unexpected auth method: ' + ctx.method)); - assert(!ctx.signature, makeMsg('Unexpected signature')); - if (ctx.method === 'none') - return ctx.reject(); - ctx.accept(); - }); - conn.on('ready', function() { - assert(false, makeMsg('Authentication should have failed')); - }); - }); - - client.on('ready', function() { - assert(false, makeMsg('Authentication should have failed')); - }); - client.on('error', function(err) { - if (cliError) { - assert(/all configured/i.test(err.message), - makeMsg('Wrong error message')); - } else { - cliError = err; - assert(/signing/i.test(err.message), makeMsg('Wrong error message')); - } - }); - client.on('close', function() { - assert(cliError, makeMsg('Expected client error')); - }); - }, - what: 'Client signing errors are caught and emitted' - }, - { run: function() { - var client; - var server; - var r; - var srvError; - var cliError; - - r = setup( - this, - { username: USER, password: 'foo' }, - { hostKeys: [KEY_RSA_BAD] } - ); - client = r.client; - server = r.server; - - // Remove default client error handler added by `setup()` since we are - // expecting an error in this case - client.removeAllListeners('error'); - - server.on('connection', function(conn) { - // Remove default server connection error handler added by `setup()` - // since we are expecting an error in this case - conn.removeAllListeners('error'); - - conn.once('error', function(err) { - assert(/signing/i.test(err.message), makeMsg('Wrong error message')); - srvError = err; - }); - conn.on('authentication', function(ctx) { - assert(false, makeMsg('Handshake should have failed')); - }); - conn.on('ready', function() { - assert(false, makeMsg('Authentication should have failed')); - }); - }); - - client.on('ready', function() { - assert(false, makeMsg('Handshake should have failed')); - }); - client.on('error', function(err) { - assert(!cliError, makeMsg('Unexpected multiple client errors')); - assert(/KEY_EXCHANGE_FAILED/.test(err.message), - makeMsg('Wrong error message')); - cliError = err; - }); - client.on('close', function() { - assert(srvError, makeMsg('Expected server error')); - assert(cliError, makeMsg('Expected client error')); - }); - }, - what: 'Server signing errors are caught and emitted' - }, -]; - -function setup(self, clientcfg, servercfg) { - self.state = { - clientReady: false, - serverReady: false, - clientClose: false, - serverClose: false - }; - - if (DEBUG) { - console.log('========================================================\n' - + '[TEST] ' - + self.what - + '\n========================================================'); - clientcfg.debug = function(str) { - console.log('[CLIENT] ' + str); - }; - servercfg.debug = function(str) { - console.log('[SERVER] ' + str); - }; - } - - var client = new Client(); - var server = new Server(servercfg); - - server.on('error', onError) - .on('connection', function(conn) { - conn.on('error', onError) - .on('ready', onReady); - server.close(); - }) - .on('close', onClose); - client.on('error', onError) - .on('ready', onReady) - .on('close', onClose); - - function onError(err) { - var which = (this === client ? 'client' : 'server'); - assert(false, makeMsg('Unexpected ' + which + ' error: ' + err)); - } - function onReady() { - if (this === client) { - assert(!self.state.clientReady, - makeMsg('Received multiple ready events for client')); - self.state.clientReady = true; - } else { - assert(!self.state.serverReady, - makeMsg('Received multiple ready events for server')); - self.state.serverReady = true; - } - if (self.state.clientReady && self.state.serverReady) - self.onReady && self.onReady(); - } - function onClose() { - if (this === client) { - assert(!self.state.clientClose, - makeMsg('Received multiple close events for client')); - self.state.clientClose = true; - } else { - assert(!self.state.serverClose, - makeMsg('Received multiple close events for server')); - self.state.serverClose = true; - } - if (self.state.clientClose && self.state.serverClose) - next(); - } - - process.nextTick(function() { - server.listen(0, 'localhost', function() { - if (clientcfg.sock) - clientcfg.sock.connect(server.address().port, 'localhost'); - else { - clientcfg.host = 'localhost'; - clientcfg.port = server.address().port; - } - client.connect(clientcfg); - }); - }); - return { client: client, server: server }; -} - -function next() { - if (Array.isArray(process._events.exit)) - process._events.exit = process._events.exit[1]; - if (++t === tests.length) - return; - - var v = tests[t]; - v.run.call(v); -} - -function makeMsg(what, msg) { - if (msg === undefined) - msg = what; - if (tests[t]) - what = tests[t].what; - else - what = ''; - return '[' + group + what + ']: ' + msg; -} - -process.once('uncaughtException', function(err) { - if (t > -1 && !/(?:^|\n)AssertionError: /i.test(''+err)) - console.log(makeMsg('Unexpected Exception:')); - throw err; -}); -process.once('exit', function() { - assert(t === tests.length, - makeMsg('_exit', - 'Only finished ' + t + '/' + tests.length + ' tests')); -}); - -next(); diff --git a/reverse_engineering/node_modules/ssh2/test/test-exec.js b/reverse_engineering/node_modules/ssh2/test/test-exec.js new file mode 100644 index 0000000..86b2e31 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-exec.js @@ -0,0 +1,578 @@ +'use strict'; + +const assert = require('assert'); +const { inspect } = require('util'); + +const { + mustCall, + mustCallAtLeast, + setupSimple, +} = require('./common.js'); + +const DEBUG = false; + +const setup = setupSimple.bind(undefined, DEBUG); + +{ + const { client, server } = setup('Simple exec()'); + + const COMMAND = 'foo --bar'; + const STDOUT_DATA = 'stdout data!\n'; + const STDERR_DATA = 'stderr data!\n'; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject, info) => { + assert(info.command === COMMAND, + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.stderr.write(STDERR_DATA); + stream.write(STDOUT_DATA); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let out = ''; + let outErr = ''; + const events = []; + const EXPECTED_EVENTS = [ 'exit', 'close' ]; + const EXPECTED_EXIT_CLOSE_ARGS = [ 100 ]; + client.on('close', mustCall(() => { + assert(out === STDOUT_DATA, `Wrong stdout data: ${inspect(out)}`); + assert(outErr === STDERR_DATA, `Wrong stderr data: ${inspect(outErr)}`); + assert.deepStrictEqual( + events, + EXPECTED_EVENTS, + `Wrong command event order: ${events}` + ); + })).exec(COMMAND, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.on('data', mustCallAtLeast((d) => { + out += d; + })).on('exit', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong exit args: ${inspect(args)}`); + events.push('exit'); + })).on('close', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong close args: ${inspect(args)}`); + events.push('close'); + })).stderr.on('data', mustCallAtLeast((d) => { + outErr += d; + })); + })); + })); +} + +{ + const { client, server } = setup('Simple exec() (exit signal)'); + + const COMMAND = 'foo --bar'; + const STDOUT_DATA = 'stdout data!\n'; + const STDERR_DATA = 'stderr data!\n'; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject, info) => { + assert(info.command === COMMAND, + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.stderr.write(STDERR_DATA); + stream.write(STDOUT_DATA); + assert.throws(() => stream.exit('SIGFAKE')); + stream.exit('SIGKILL'); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let out = ''; + let outErr = ''; + const events = []; + const EXPECTED_EVENTS = [ 'exit', 'close' ]; + const EXPECTED_EXIT_CLOSE_ARGS = [ null, 'SIGKILL', false, '' ]; + client.on('close', mustCall(() => { + assert(out === STDOUT_DATA, `Wrong stdout data: ${inspect(out)}`); + assert(outErr === STDERR_DATA, `Wrong stderr data: ${inspect(outErr)}`); + assert.deepStrictEqual( + events, + EXPECTED_EVENTS, + `Wrong command event order: ${events}` + ); + })).exec(COMMAND, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.on('data', mustCallAtLeast((d) => { + out += d; + })).on('exit', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong exit args: ${inspect(args)}`); + events.push('exit'); + })).on('close', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong close args: ${inspect(args)}`); + events.push('close'); + })).stderr.on('data', mustCallAtLeast((d) => { + outErr += d; + })); + })); + })); +} + +{ + const { client, server } = setup('Simple exec() (exit signal -- no "SIG")'); + + const COMMAND = 'foo --bar'; + const STDOUT_DATA = 'stdout data!\n'; + const STDERR_DATA = 'stderr data!\n'; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject, info) => { + assert(info.command === COMMAND, + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.stderr.write(STDERR_DATA); + stream.write(STDOUT_DATA); + assert.throws(() => stream.exit('FAKE')); + stream.exit('KILL'); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let out = ''; + let outErr = ''; + const events = []; + const EXPECTED_EVENTS = [ 'exit', 'close' ]; + const EXPECTED_EXIT_CLOSE_ARGS = [ null, 'SIGKILL', false, '' ]; + client.on('close', mustCall(() => { + assert(out === STDOUT_DATA, `Wrong stdout data: ${inspect(out)}`); + assert(outErr === STDERR_DATA, `Wrong stderr data: ${inspect(outErr)}`); + assert.deepStrictEqual( + events, + EXPECTED_EVENTS, + `Wrong command event order: ${events}` + ); + })).exec(COMMAND, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.on('data', mustCallAtLeast((d) => { + out += d; + })).on('exit', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong exit args: ${inspect(args)}`); + events.push('exit'); + })).on('close', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong close args: ${inspect(args)}`); + events.push('close'); + })).stderr.on('data', mustCallAtLeast((d) => { + outErr += d; + })); + })); + })); +} + +{ + const { client, server } = setup('Exec with signal()'); + + const COMMAND = 'foo --bar'; + const STDOUT_DATA = 'stdout data!\n'; + const STDERR_DATA = 'stderr data!\n'; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let stream; + accept().on('exec', mustCall((accept, reject, info) => { + assert(info.command === COMMAND, + `Wrong exec command: ${info.command}`); + stream = accept(); + stream.stderr.write(STDERR_DATA); + stream.write(STDOUT_DATA); + })).on('signal', mustCall((accept, reject, info) => { + assert(info.name === 'INT', `Wrong client signal name: ${info.name}`); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let out = ''; + let outErr = ''; + const events = []; + const EXPECTED_EVENTS = [ 'exit', 'close' ]; + const EXPECTED_EXIT_CLOSE_ARGS = [ 100 ]; + client.on('close', mustCall(() => { + assert(out === STDOUT_DATA, `Wrong stdout data: ${inspect(out)}`); + assert(outErr === STDERR_DATA, `Wrong stderr data: ${inspect(outErr)}`); + assert.deepStrictEqual( + events, + EXPECTED_EVENTS, + `Wrong command event order: ${events}` + ); + })).exec(COMMAND, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + const sendSignal = (() => { + let sent = false; + return () => { + if (sent) + return; + sent = true; + assert.throws(() => stream.signal('FAKE')); + assert.throws(() => stream.signal('SIGFAKE')); + stream.signal('SIGINT'); + }; + })(); + stream.on('data', mustCallAtLeast((d) => { + out += d; + sendSignal(); + })).on('exit', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong exit args: ${inspect(args)}`); + events.push('exit'); + })).on('close', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong close args: ${inspect(args)}`); + events.push('close'); + })).stderr.on('data', mustCallAtLeast((d) => { + outErr += d; + })); + })); + })); +} + +{ + const { client, server } = setup('Exec with signal() -- no "SIG"'); + + const COMMAND = 'foo --bar'; + const STDOUT_DATA = 'stdout data!\n'; + const STDERR_DATA = 'stderr data!\n'; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let stream; + accept().on('exec', mustCall((accept, reject, info) => { + assert(info.command === COMMAND, + `Wrong exec command: ${info.command}`); + stream = accept(); + stream.stderr.write(STDERR_DATA); + stream.write(STDOUT_DATA); + })).on('signal', mustCall((accept, reject, info) => { + assert(info.name === 'INT', `Wrong client signal name: ${info.name}`); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let out = ''; + let outErr = ''; + const events = []; + const EXPECTED_EVENTS = [ 'exit', 'close' ]; + const EXPECTED_EXIT_CLOSE_ARGS = [ 100 ]; + client.on('close', mustCall(() => { + assert(out === STDOUT_DATA, `Wrong stdout data: ${inspect(out)}`); + assert(outErr === STDERR_DATA, `Wrong stderr data: ${inspect(outErr)}`); + assert.deepStrictEqual( + events, + EXPECTED_EVENTS, + `Wrong command event order: ${events}` + ); + })).exec(COMMAND, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + const sendSignal = (() => { + let sent = false; + return () => { + if (sent) + return; + sent = true; + stream.signal('INT'); + }; + })(); + stream.on('data', mustCallAtLeast((d) => { + out += d; + sendSignal(); + })).on('exit', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong exit args: ${inspect(args)}`); + events.push('exit'); + })).on('close', mustCall((...args) => { + assert.deepStrictEqual(args, + EXPECTED_EXIT_CLOSE_ARGS, + `Wrong close args: ${inspect(args)}`); + events.push('close'); + })).stderr.on('data', mustCallAtLeast((d) => { + outErr += d; + })); + })); + })); +} + +{ + const { client, server } = setup('Exec with environment set'); + + const env = { SSH2NODETEST: 'foo' }; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('env', mustCall((accept, reject, info) => { + accept && accept(); + assert(info.key === Object.keys(env)[0], + 'Wrong env key'); + assert(info.val === Object.values(env)[0], + 'Wrong env value'); + })).on('exec', mustCall((accept, reject, info) => { + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo --bar', { env }, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.resume(); + })); + })); +} + +{ + const { client, server } = setup('Exec with setWindow()'); + + const dimensions = { + rows: 60, + cols: 115, + height: 480, + width: 640, + }; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('window-change', mustCall((accept, reject, info) => { + accept && accept(); + assert.deepStrictEqual(info, dimensions, 'Wrong dimensions'); + })).on('exec', mustCall((accept, reject, info) => { + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo --bar', mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.setWindow(...Object.values(dimensions)); + stream.resume(); + })); + })); +} + +{ + const { client, server } = setup('Exec with pty set'); + + const pty = { + rows: 2, + cols: 4, + width: 0, + height: 0, + term: 'vt220', + modes: {}, + }; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let sawPty = false; + accept().on('pty', mustCall((accept, reject, info) => { + assert.deepStrictEqual(info, pty, 'Wrong pty info'); + sawPty = true; + accept && accept(); + })).on('exec', mustCall((accept, reject, info) => { + assert(sawPty, 'Expected pty to be set up'); + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo --bar', { pty }, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.resume(); + })); + })); +} + +{ + const { client, server } = setup('Exec with X11 forwarding'); + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let sawX11 = false; + accept().on('x11', mustCall((accept, reject, info) => { + assert.strictEqual(info.single, + false, + `Wrong x11 single: ${info.single}`); + assert.strictEqual(info.screen, + 0, + `Wrong x11 screen: ${info.screen}`); + assert.strictEqual(info.protocol, + 'MIT-MAGIC-COOKIE-1', + `Wrong x11 protocol: ${info.protocol}`); + assert(Buffer.isBuffer(info.cookie), 'Expected cookie Buffer'); + assert.strictEqual( + info.cookie.length, + 32, + `Invalid x11 cookie length: ${info.cookie.length}` + ); + sawX11 = true; + accept && accept(); + })).on('exec', mustCall((accept, reject, info) => { + assert(sawX11, 'Expected x11 before exec'); + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + conn.x11('127.0.0.1', 4321, mustCall((err, xstream) => { + assert(!err, `Unexpected x11() error: ${err}`); + xstream.resume(); + xstream.on('end', mustCall(() => { + stream.exit(100); + stream.end(); + conn.end(); + })).end(); + })); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.on('x11', mustCall((info, accept, reject) => { + assert.strictEqual(info.srcIP, + '127.0.0.1', + `Invalid x11 srcIP: ${info.srcIP}`); + assert.strictEqual(info.srcPort, + 4321, + `Invalid x11 srcPort: ${info.srcPort}`); + accept(); + })).exec('foo --bar', { x11: true }, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.resume(); + })); + })); +} + +{ + const { client, server } = setup( + 'Exec with X11 forwarding (custom X11 settings)' + ); + + const x11 = { + single: true, + screen: 1234, + protocol: 'YUMMY-MAGIC-COOKIE-1', + cookie: '00112233445566778899001122334455', + }; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let sawX11 = false; + accept().on('x11', mustCall((accept, reject, info) => { + assert.strictEqual(info.single, + x11.single, + `Wrong x11 single: ${info.single}`); + assert.strictEqual(info.screen, + x11.screen, + `Wrong x11 screen: ${info.screen}`); + assert.strictEqual(info.protocol, + x11.protocol, + `Wrong x11 protocol: ${info.protocol}`); + assert(Buffer.isBuffer(info.cookie), 'Expected cookie Buffer'); + assert.strictEqual(info.cookie.toString(), + x11.cookie, + `Wrong x11 cookie: ${info.cookie}`); + sawX11 = true; + accept && accept(); + })).on('exec', mustCall((accept, reject, info) => { + assert(sawX11, 'Expected x11 before exec'); + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + conn.x11('127.0.0.1', 4321, mustCall((err, xstream) => { + assert(!err, `Unexpected x11() error: ${err}`); + xstream.resume(); + xstream.on('end', mustCall(() => { + stream.exit(100); + stream.end(); + conn.end(); + })).end(); + })); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.on('x11', mustCall((info, accept, reject) => { + assert.strictEqual(info.srcIP, + '127.0.0.1', + `Invalid x11 srcIP: ${info.srcIP}`); + assert.strictEqual(info.srcPort, + 4321, + `Invalid x11 srcPort: ${info.srcPort}`); + accept(); + })).exec('foo --bar', { x11 }, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.resume(); + })); + })); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-integration-openssh.js b/reverse_engineering/node_modules/ssh2/test/test-integration-openssh.js new file mode 100644 index 0000000..2baf682 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-integration-openssh.js @@ -0,0 +1,481 @@ +// TODO: add more rekey tests that at least include switching from no +// compression to compression and vice versa +'use strict'; + +const assert = require('assert'); +const { spawn, spawnSync } = require('child_process'); +const { chmodSync, readdirSync } = require('fs'); +const { join } = require('path'); +const readline = require('readline'); + +const Server = require('../lib/server.js'); + +const { + fixture, + fixtureKey, + FIXTURES_DIR, + mustCall, + mustCallAtLeast, +} = require('./common.js'); + +const SPAWN_OPTS = { windowsHide: true }; +const CLIENT_TIMEOUT = 5000; + +const debug = false; +const opensshPath = 'ssh'; +let opensshVer; + +// TODO: figure out why this test is failing on Windows +if (process.platform === 'win32') { + console.log('Skipping OpenSSH integration tests on Windows'); + process.exit(0); +} + +// Fix file modes to avoid OpenSSH client complaints about keys' permissions +for (const file of readdirSync(FIXTURES_DIR, { withFileTypes: true })) { + if (file.isFile()) + chmodSync(join(FIXTURES_DIR, file.name), 0o600); +} + +{ + // Get OpenSSH client version first + const { + error, stderr, stdout + } = spawnSync(opensshPath, ['-V'], SPAWN_OPTS); + + if (error) { + console.error('OpenSSH client is required for these tests'); + process.exitCode = 5; + return; + } + + const re = /^OpenSSH_([\d.]+)/; + let m = re.exec(stdout.toString()); + if (!m || !m[1]) { + m = re.exec(stderr.toString()); + if (!m || !m[1]) { + console.error('OpenSSH client is required for these tests'); + process.exitCode = 5; + return; + } + } + + opensshVer = m[1]; + console.log(`Testing with OpenSSH version: ${opensshVer}`); +} + + +// Key-based authentication +[ + { desc: 'RSA user key (old OpenSSH)', + clientKey: fixtureKey('id_rsa') }, + { desc: 'RSA user key (new OpenSSH)', + clientKey: fixtureKey('openssh_new_rsa') }, + { desc: 'DSA user key', + clientKey: fixtureKey('id_dsa') }, + { desc: 'ECDSA user key', + clientKey: fixtureKey('id_ecdsa') }, +].forEach((test) => { + const { desc, clientKey } = test; + const username = 'KeyUser'; + const { server } = setup( + desc, + { + client: { + username, + privateKeyPath: clientKey.fullPath, + }, + server: { hostKeys: [ fixture('ssh_host_rsa_key') ] }, + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCallAtLeast((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 2: + case 3: + if (authAttempt === 3) + assert(ctx.signature, 'Missing publickey signature'); + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + default: + assert(false, 'Unexpected number of auth attempts'); + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + // We should not expect any further auth attempts after we verify a + // signature + authAttempt = Infinity; + } + ctx.accept(); + }, 2)).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + })); + })); + })); +}); + + +// Different host key types +[ + { desc: 'RSA host key (old OpenSSH)', + hostKey: fixture('id_rsa') }, + { desc: 'RSA host key (new OpenSSH)', + hostKey: fixture('openssh_new_rsa') }, + { desc: 'DSA host key', + hostKey: fixture('ssh_host_dsa_key') }, + { desc: 'ECDSA host key', + hostKey: fixture('ssh_host_ecdsa_key') }, + { desc: 'PPK', + hostKey: fixture('id_rsa.ppk') }, +].forEach((test) => { + const { desc, hostKey } = test; + const clientKey = fixtureKey('openssh_new_rsa'); + const username = 'KeyUser'; + const { server } = setup( + desc, + { + client: { + username, + privateKeyPath: clientKey.fullPath, + }, + server: { hostKeys: [ hostKey ] }, + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCallAtLeast((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 2: + case 3: + if (authAttempt === 3) + assert(ctx.signature, 'Missing publickey signature'); + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + default: + assert(false, 'Unexpected number of auth attempts'); + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + // We should not expect any further auth attempts after we verify a + // signature + authAttempt = Infinity; + } + ctx.accept(); + }, 2)).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + })); + })); + })); +}); + + +// Various edge cases +{ + const clientKey = fixtureKey('openssh_new_rsa'); + const username = 'KeyUser'; + const { server } = setup( + 'Server closes stdin too early', + { + client: { + username, + privateKeyPath: clientKey.fullPath, + }, + server: { hostKeys: [ fixture('ssh_host_rsa_key') ] }, + debug, + } + ); + + server.on('_child', mustCall((childProc) => { + childProc.stderr.once('data', mustCall((data) => { + childProc.stdin.end(); + })); + childProc.stdin.write('ping'); + })).on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCallAtLeast((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 2: + case 3: + if (authAttempt === 3) + assert(ctx.signature, 'Missing publickey signature'); + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + default: + assert(false, 'Unexpected number of auth attempts'); + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + // We should not expect any further auth attempts after we verify a + // signature + authAttempt = Infinity; + } + ctx.accept(); + }, 2)).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject) => { + const stream = accept(); + stream.stdin.on('data', mustCallAtLeast((data) => { + stream.stdout.write('pong on stdout'); + stream.stderr.write('pong on stderr'); + })).on('end', mustCall(() => { + stream.stdout.write('pong on stdout'); + stream.stderr.write('pong on stderr'); + stream.exit(0); + stream.close(); + })); + })); + })); + })); + })); +} +{ + const clientKey = fixtureKey('openssh_new_rsa'); + const username = 'KeyUser'; + const { server } = setup( + 'Rekey', + { + client: { + username, + privateKeyPath: clientKey.fullPath, + }, + server: { hostKeys: [ fixture('ssh_host_rsa_key') ] }, + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCallAtLeast((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 2: + case 3: + if (authAttempt === 3) + assert(ctx.signature, 'Missing publickey signature'); + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + default: + assert(false, 'Unexpected number of auth attempts'); + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + // We should not expect any further auth attempts after we verify a + // signature + authAttempt = Infinity; + } + ctx.accept(); + }, 2)).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + const session = accept(); + conn.rekey(); + session.on('exec', mustCall((accept, reject) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + })); + })); + })); +} + + +function setup(title, configs) { + const { + client: clientCfg, + server: serverCfg, + allReady: allReady_, + timeout: timeout_, + debug, + noForceServerReady, + } = configs; + let clientClose = false; + let serverClose = false; + let serverReady = false; + let client; + const msg = (text) => { + return `${title}: ${text}`; + }; + + const timeout = (typeof timeout_ === 'number' + ? timeout_ + : CLIENT_TIMEOUT); + + const allReady = (typeof allReady_ === 'function' ? allReady_ : undefined); + + if (debug) { + serverCfg.debug = (...args) => { + console.log(`[${title}][SERVER]`, ...args); + }; + } + + const serverReadyFn = (noForceServerReady ? onReady : mustCall(onReady)); + const server = new Server(serverCfg); + + server.on('error', onError) + .on('connection', mustCall((conn) => { + conn.on('error', onError) + .on('ready', serverReadyFn); + server.close(); + })) + .on('close', mustCall(onClose)); + + function onError(err) { + const which = (arguments.length >= 3 ? 'client' : 'server'); + assert(false, msg(`Unexpected ${which} error: ${err}`)); + } + + function onReady() { + assert(!serverReady, msg('Received multiple ready events for server')); + serverReady = true; + allReady && allReady(); + } + + function onClose() { + if (arguments.length >= 3) { + assert(!clientClose, msg('Received multiple close events for client')); + clientClose = true; + } else { + assert(!serverClose, msg('Received multiple close events for server')); + serverClose = true; + } + } + + process.nextTick(mustCall(() => { + server.listen(0, 'localhost', mustCall(() => { + const args = [ + '-o', 'UserKnownHostsFile=/dev/null', + '-o', 'StrictHostKeyChecking=no', + '-o', 'CheckHostIP=no', + '-o', 'ConnectTimeout=3', + '-o', 'GlobalKnownHostsFile=/dev/null', + '-o', 'GSSAPIAuthentication=no', + '-o', 'IdentitiesOnly=yes', + '-o', 'BatchMode=yes', + '-o', 'VerifyHostKeyDNS=no', + + '-vvvvvv', + '-T', + '-o', 'KbdInteractiveAuthentication=no', + '-o', 'HostbasedAuthentication=no', + '-o', 'PasswordAuthentication=no', + '-o', 'PubkeyAuthentication=yes', + '-o', 'PreferredAuthentications=publickey' + ]; + + if (clientCfg.privateKeyPath) + args.push('-o', `IdentityFile=${clientCfg.privateKeyPath}`); + + if (!/^[0-6]\./.test(opensshVer)) { + // OpenSSH 7.0+ disables DSS/DSA host (and user) key support by + // default, so we explicitly enable it here + args.push('-o', 'HostKeyAlgorithms=+ssh-dss'); + args.push('-o', 'PubkeyAcceptedKeyTypes=+ssh-dss'); + } + + args.push('-p', server.address().port.toString(), + '-l', clientCfg.username, + 'localhost', + 'uptime'); + + client = spawn(opensshPath, args, SPAWN_OPTS); + server.emit('_child', client); + + if (debug) { + readline.createInterface({ + input: client.stdout + }).on('line', (line) => { + console.log(`[${title}][CLIENT][STDOUT]`, line); + }); + readline.createInterface({ + input: client.stderr + }).on('line', (line) => { + console.error(`[${title}][CLIENT][STDERR]`, line); + }); + } else { + client.stdout.resume(); + client.stderr.resume(); + } + + client.on('error', (err) => { + onError(err, null, null); + }).on('exit', (code) => { + clearTimeout(client.timer); + if (code !== 0) + return onError(new Error(`Non-zero exit code ${code}`), null, null); + onClose(null, null, null); + }); + + client.timer = setTimeout(() => { + assert(false, msg('Client timeout')); + }, timeout); + })); + })); + + return { server }; +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-misc-client-server.js b/reverse_engineering/node_modules/ssh2/test/test-misc-client-server.js new file mode 100644 index 0000000..f875a7d --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-misc-client-server.js @@ -0,0 +1,1428 @@ +'use strict'; + +const assert = require('assert'); +const { createHash } = require('crypto'); +const http = require('http'); +const https = require('https'); +const net = require('net'); +const { Transform } = require('stream'); +const { inspect } = require('util'); + +const Client = require('../lib/client.js'); +const { + SSHTTPAgent: HTTPAgent, + SSHTTPSAgent: HTTPSAgent, +} = require('../lib/http-agents.js'); +const Server = require('../lib/server.js'); +const { KexInit } = require('../lib/protocol/kex.js'); + +const { + fixture, + mustCall, + mustCallAtLeast, + mustNotCall, + setup: setup_, + setupSimple, +} = require('./common.js'); + +const KEY_RSA_BAD = fixture('bad_rsa_private_key'); +const HOST_RSA_MD5 = '64254520742d3d0792e918f3ce945a64'; +const clientCfg = { username: 'foo', password: 'bar' }; +const serverCfg = { hostKeys: [ fixture('ssh_host_rsa_key') ] }; + +const debug = false; + +const setup = setupSimple.bind(undefined, debug); + + +{ + const { server } = setup_( + 'Verify host fingerprint (sync success, hostHash set)', + { + client: { + ...clientCfg, + hostHash: 'md5', + hostVerifier: mustCall((hash) => { + assert(hash === HOST_RSA_MD5, 'Host fingerprint mismatch'); + return true; + }), + }, + server: serverCfg, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} + +{ + const { server } = setup_( + 'Verify host fingerprint (sync success, hostHash not set)', + { + client: { + ...clientCfg, + hostVerifier: mustCall((key) => { + assert(Buffer.isBuffer(key), 'Expected buffer'); + let hash = createHash('md5'); + hash.update(key); + hash = hash.digest('hex'); + assert(hash === HOST_RSA_MD5, 'Host fingerprint mismatch'); + return true; + }), + }, + server: serverCfg, + } + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} + +{ + const { server } = setup_( + 'Verify host fingerprint (async success)', + { + client: { + ...clientCfg, + hostVerifier: mustCall((key, cb) => { + assert(Buffer.isBuffer(key), 'Expected buffer'); + let hash = createHash('md5'); + hash.update(key); + hash = hash.digest('hex'); + assert(hash === HOST_RSA_MD5, 'Host fingerprint mismatch'); + process.nextTick(cb, true); + }), + }, + server: serverCfg, + } + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} + +{ + const { client, server } = setup_( + 'Verify host fingerprint (sync failure)', + { + client: { + ...clientCfg, + hostVerifier: mustCall((key) => { + return false; + }), + }, + server: serverCfg, + + noForceClientReady: true, + noForceServerReady: true, + }, + ); + + client.removeAllListeners('error'); + client.on('ready', mustNotCall()) + .on('error', mustCall((err) => { + assert(/verification failed/.test(err.message), + 'Wrong client error message'); + })); + + server.on('connection', mustCall((conn) => { + conn.removeAllListeners('error'); + + conn.on('authentication', mustNotCall()) + .on('ready', mustNotCall()) + .on('error', mustCall((err) => { + assert(/KEY_EXCHANGE_FAILED/.test(err.message), + 'Wrong server error message'); + })); + })); +} + +{ + // connect() on connected client + + const clientCfg_ = { ...clientCfg }; + const client = new Client(); + const server = new Server(serverCfg); + + server.listen(0, 'localhost', mustCall(() => { + clientCfg_.host = 'localhost'; + clientCfg_.port = server.address().port; + client.connect(clientCfg_); + })); + + let connections = 0; + server.on('connection', mustCall((conn) => { + if (++connections === 2) + server.close(); + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => {})); + }, 2)).on('close', mustCall(() => {})); + + let reconnect = false; + client.on('ready', mustCall(() => { + if (reconnect) { + client.end(); + } else { + reconnect = true; + client.connect(clientCfg_); + } + }, 2)).on('close', mustCall(() => {}, 2)); +} + +{ + // Throw when not connected + + const client = new Client({ + username: 'foo', + password: 'bar', + }); + + assert.throws(mustCall(() => { + client.exec('uptime', mustNotCall()); + })); +} + +{ + const { client, server } = setup( + 'Outstanding callbacks called on disconnect' + ); + + server.on('connection', mustCall((conn) => { + conn.on('session', mustCall(() => {}, 3)); + })); + + client.on('ready', mustCall(() => { + function callback(err, stream) { + assert(err, 'Expected error'); + assert(err.message === 'No response from server', + `Wrong error message: ${err.message}`); + } + client.exec('uptime', mustCall(callback)); + client.shell(mustCall(callback)); + client.sftp(mustCall(callback)); + client.end(); + })); +} + +{ + const { client, server } = setup('Pipelined requests'); + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + const session = accept(); + session.on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + }, 3)); + })); + })); + + client.on('ready', mustCall(() => { + let calledBack = 0; + function callback(err, stream) { + assert(!err, `Unexpected error: ${err}`); + stream.resume(); + if (++calledBack === 3) + client.end(); + } + client.exec('foo', mustCall(callback)); + client.exec('bar', mustCall(callback)); + client.exec('baz', mustCall(callback)); + })); +} + +{ + const { client, server } = setup( + 'Pipelined requests with intermediate rekeying' + ); + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + const reqs = []; + conn.on('session', mustCall((accept, reject) => { + if (reqs.length === 0) { + conn.rekey(mustCall((err) => { + assert(!err, `Unexpected rekey error: ${err}`); + reqs.forEach((accept) => { + const session = accept(); + session.on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + }); + })); + } + reqs.push(accept); + }, 3)); + })); + })); + + client.on('ready', mustCall(() => { + let calledBack = 0; + function callback(err, stream) { + assert(!err, `Unexpected error: ${err}`); + stream.resume(); + if (++calledBack === 3) + client.end(); + } + client.exec('foo', mustCall(callback)); + client.exec('bar', mustCall(callback)); + client.exec('baz', mustCall(callback)); + })); +} + +{ + const { client, server } = setup('Ignore outgoing after stream close'); + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + const session = accept(); + session.on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo', mustCall((err, stream) => { + assert(!err, `Unexpected error: ${err}`); + stream.on('exit', mustCall((code, signal) => { + client.end(); + })); + })); + })); +} + +{ + const { client, server } = setup_( + 'Double pipe on unconnected, passed in net.Socket', + { + client: { + ...clientCfg, + sock: new net.Socket(), + }, + server: serverCfg, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => {})); + })); + client.on('ready', mustCall(() => { + client.end(); + })); +} + +{ + const { client, server } = setup( + 'Client auto-rejects inbound connections to unknown bound address' + ); + + const assignedPort = 31337; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('request', mustCall((accept, reject, name, info) => { + assert(name === 'tcpip-forward', 'Wrong request name'); + assert.deepStrictEqual( + info, + { bindAddr: 'good', bindPort: 0 }, + 'Wrong request info' + ); + accept(assignedPort); + conn.forwardOut(info.bindAddr, + assignedPort, + 'remote', + 12345, + mustCall((err, ch) => { + assert(!err, `Unexpected error: ${err}`); + conn.forwardOut('bad', + assignedPort, + 'remote', + 12345, + mustCall((err, ch) => { + assert(err, 'Should receive error'); + client.end(); + })); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + // request forwarding + client.forwardIn('good', 0, mustCall((err, port) => { + assert(!err, `Unexpected error: ${err}`); + assert(port === assignedPort, 'Wrong assigned port'); + })); + })).on('tcp connection', mustCall((details, accept, reject) => { + assert.deepStrictEqual( + details, + { destIP: 'good', + destPort: assignedPort, + srcIP: 'remote', + srcPort: 12345 + }, + 'Wrong connection details' + ); + accept(); + })); +} + +{ + const { client, server } = setup( + 'Client auto-rejects inbound connections to unknown bound port' + ); + + const assignedPort = 31337; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('request', mustCall((accept, reject, name, info) => { + assert(name === 'tcpip-forward', 'Wrong request name'); + assert.deepStrictEqual( + info, + { bindAddr: 'good', bindPort: 0 }, + 'Wrong request info' + ); + accept(assignedPort); + conn.forwardOut(info.bindAddr, + assignedPort, + 'remote', + 12345, + mustCall((err, ch) => { + assert(!err, `Unexpected error: ${err}`); + conn.forwardOut(info.bindAddr, + 99999, + 'remote', + 12345, + mustCall((err, ch) => { + assert(err, 'Should receive error'); + client.end(); + })); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + // request forwarding + client.forwardIn('good', 0, mustCall((err, port) => { + assert(!err, `Unexpected error: ${err}`); + assert(port === assignedPort, 'Wrong assigned port'); + })); + })).on('tcp connection', mustCall((details, accept, reject) => { + assert.deepStrictEqual( + details, + { destIP: 'good', + destPort: assignedPort, + srcIP: 'remote', + srcPort: 12345 + }, + 'Wrong connection details' + ); + accept(); + })); +} + +{ + const GREETING = 'Hello world!'; + + const { client, server } = setup_( + 'Server greeting', + { + client: { + ...clientCfg, + ident: 'node.js rules', + }, + server: { + ...serverCfg, + greeting: GREETING, + } + }, + ); + + let sawGreeting = false; + + server.on('connection', mustCall((conn, info) => { + assert.deepStrictEqual(info.header, { + identRaw: 'SSH-2.0-node.js rules', + greeting: '', + versions: { + protocol: '2.0', + software: 'node.js' + }, + comments: 'rules' + }); + conn.on('handshake', mustCall((details) => { + assert(sawGreeting, 'Client did not see greeting before handshake'); + })).on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); + + client.on('greeting', mustCall((greeting) => { + assert.strictEqual(greeting, `${GREETING}\r\n`); + sawGreeting = true; + })).on('banner', mustNotCall()); +} + +{ + const { client, server } = setup_( + 'Correct ident parsing', + { + client: { + ...clientCfg, + ident: 'node.js rules\n', + }, + server: serverCfg, + + noServerError: true, + noClientError: true, + noForceServerReady: true, + noForceClientReady: true, + }, + ); + + server.on('connection', mustCall((conn, info) => { + assert.deepStrictEqual(info.header, { + identRaw: 'SSH-2.0-node.js rules', + greeting: '', + versions: { + protocol: '2.0', + software: 'node.js' + }, + comments: 'rules' + }); + conn.once('error', mustCall((err) => { + assert(/bad packet length/i.test(err.message), 'Wrong error message'); + })); + conn.on('handshake', mustNotCall()) + .on('authentication', mustNotCall()) + .on('ready', mustNotCall()); + })); + + client.on('greeting', mustNotCall()) + .on('banner', mustNotCall()) + .on('ready', mustNotCall()); +} + +{ + const BANNER = 'Hello world!'; + + const { client, server } = setup_( + 'Server banner', + { + client: clientCfg, + server: { + ...serverCfg, + banner: BANNER, + } + }, + ); + + let sawBanner = false; + + server.on('connection', mustCall((conn) => { + conn.on('handshake', mustCall((details) => { + assert(!sawBanner, 'Client saw banner too early'); + })).on('authentication', mustCall((ctx) => { + assert(sawBanner, 'Client did not see banner before auth'); + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); + + client.on('greeting', mustNotCall()) + .on('banner', mustCall((message) => { + assert.strictEqual(message, 'Hello world!\r\n'); + sawBanner = true; + })); +} + +{ + const { client, server } = setup( + 'Server responds to global requests in the right order' + ); + + function sendAcceptLater(accept) { + if (fastRejectSent) + accept(); + else + setImmediate(sendAcceptLater, accept); + } + + let fastRejectSent = false; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('request', mustCall((accept, reject, name, info) => { + if (info.bindAddr === 'fastReject') { + // Will call reject on 'fastReject' soon ... + reject(); + fastRejectSent = true; + } else { + // ... but accept on 'slowAccept' later + sendAcceptLater(accept); + } + }, 2)); + })); + })); + + client.on('ready', mustCall(() => { + let replyCnt = 0; + + client.forwardIn('slowAccept', 0, mustCall((err) => { + assert(!err, `Unexpected error: ${err}`); + if (++replyCnt === 2) + client.end(); + })); + + client.forwardIn('fastReject', 0, mustCall((err) => { + assert(err, 'Expected error'); + if (++replyCnt === 2) + client.end(); + })); + })); +} + +{ + const { client, server } = setup( + 'Cleanup outstanding channel requests on channel close' + ); + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + const session = accept(); + session.on('subsystem', mustCall((accept, reject, info) => { + assert(info.name === 'netconf', `Wrong subsystem name: ${info.name}`); + + // XXX: hack to prevent success reply from being sent + conn._protocol.channelSuccess = () => {}; + + accept().close(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.subsys('netconf', mustCall((err, stream) => { + assert(err, 'Expected error'); + client.end(); + })); + })); +} + +{ + const { client, server } = setup_( + 'Handshake errors are emitted', + { + client: { + ...clientCfg, + algorithms: { cipher: [ 'aes128-cbc' ] }, + }, + server: { + ...serverCfg, + algorithms: { cipher: [ 'aes128-ctr' ] }, + }, + + noForceClientReady: true, + noForceServerReady: true, + }, + ); + + client.removeAllListeners('error'); + + function onError(err) { + assert.strictEqual(err.level, 'handshake'); + assert(/handshake failed/i.test(err.message), 'Wrong error message'); + } + + server.on('connection', mustCall((conn) => { + conn.removeAllListeners('error'); + + conn.on('authentication', mustNotCall()) + .on('ready', mustNotCall()) + .on('handshake', mustNotCall()) + .on('error', mustCall(onError)) + .on('close', mustCall(() => {})); + })); + + client.on('ready', mustNotCall()) + .on('error', mustCall(onError)) + .on('close', mustCall(() => {})); +} + +{ + const { client, server } = setup_( + 'Client signing errors are caught and emitted', + { + client: { + username: 'foo', + privateKey: KEY_RSA_BAD, + }, + server: serverCfg, + + noForceClientReady: true, + noForceServerReady: true, + }, + ); + + client.removeAllListeners('error'); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(!ctx.signature, 'Unexpected signature'); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + ctx.accept(); + break; + } + }, 2)).on('ready', mustNotCall()).on('close', mustCall(() => {})); + })); + + let cliError; + client.on('ready', mustNotCall()).on('error', mustCall((err) => { + if (cliError) { + assert(/all configured/i.test(err.message), 'Wrong error message'); + } else { + cliError = err; + assert(/signing/i.test(err.message), 'Wrong error message'); + } + }, 2)).on('close', mustCall(() => {})); +} + +{ + const { client, server } = setup_( + 'Server signing errors are caught and emitted', + { + client: clientCfg, + server: { hostKeys: [KEY_RSA_BAD] }, + + noForceClientReady: true, + noForceServerReady: true, + }, + ); + + client.removeAllListeners('error'); + + server.on('connection', mustCall((conn) => { + conn.removeAllListeners('error'); + + conn.on('error', mustCall((err) => { + assert(/signature generation failed/i.test(err.message), + 'Wrong error message'); + })).on('authentication', mustNotCall()) + .on('ready', mustNotCall()) + .on('close', mustCall(() => {})); + })); + + client.on('ready', mustNotCall()).on('error', mustCall((err) => { + assert(/KEY_EXCHANGE_FAILED/.test(err.message), 'Wrong error message'); + })).on('close', mustCall(() => {})); +} + +{ + const { client, server } = setup_( + 'Rekeying with AES-GCM', + { + client: { + ...clientCfg, + algorithms: { cipher: [ 'aes128-gcm@openssh.com' ] }, + }, + server: { + ...serverCfg, + algorithms: { cipher: [ 'aes128-gcm@openssh.com' ] }, + }, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + const reqs = []; + conn.on('session', mustCall((accept, reject) => { + if (reqs.length === 0) { + conn.rekey(mustCall((err) => { + assert(!err, `Unexpected rekey error: ${err}`); + reqs.forEach((accept) => { + const session = accept(); + session.on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + }); + })); + } + reqs.push(accept); + }, 3)); + })); + })); + + client.on('ready', mustCall(() => { + let calledBack = 0; + function callback(err, stream) { + assert(!err, `Unexpected error: ${err}`); + stream.resume(); + if (++calledBack === 3) + client.end(); + } + client.exec('foo', mustCall(callback)); + client.exec('bar', mustCall(callback)); + client.exec('baz', mustCall(callback)); + })); +} + +{ + const { client, server } = setup_( + 'Switch from no compression to compression', + { + client: { + ...clientCfg, + algorithms: { compress: [ 'none' ] }, + }, + server: { + ...serverCfg, + algorithms: { compress: [ 'none', 'zlib@openssh.com' ] }, + }, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + const reqs = []; + conn.on('session', mustCall((accept, reject) => { + if (reqs.length === 0) { + // XXX: hack to change algorithms after initial handshake + client._protocol._offer = new KexInit({ + kex: [ 'ecdh-sha2-nistp256' ], + serverHostKey: [ 'rsa-sha2-256' ], + cs: { + cipher: [ 'aes128-gcm@openssh.com' ], + mac: [], + compress: [ 'zlib@openssh.com' ], + lang: [], + }, + sc: { + cipher: [ 'aes128-gcm@openssh.com' ], + mac: [], + compress: [ 'zlib@openssh.com' ], + lang: [], + }, + }); + + conn.rekey(mustCall((err) => { + assert(!err, `Unexpected rekey error: ${err}`); + reqs.forEach((accept) => { + const session = accept(); + session.on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + }); + })); + } + reqs.push(accept); + }, 3)); + })); + })); + + let handshakes = 0; + client.on('handshake', mustCall((info) => { + switch (++handshakes) { + case 1: + assert(info.cs.compress === 'none', 'wrong compress value'); + assert(info.sc.compress === 'none', 'wrong compress value'); + break; + case 2: + assert(info.cs.compress === 'zlib@openssh.com', + 'wrong compress value'); + assert(info.sc.compress === 'zlib@openssh.com', + 'wrong compress value'); + break; + } + }, 2)).on('ready', mustCall(() => { + let calledBack = 0; + function callback(err, stream) { + assert(!err, `Unexpected error: ${err}`); + stream.resume(); + if (++calledBack === 3) + client.end(); + } + client.exec('foo', mustCall(callback)); + client.exec('bar', mustCall(callback)); + client.exec('baz', mustCall(callback)); + })); +} + +{ + const { client, server } = setup_( + 'Switch from compression to no compression', + { + client: { + ...clientCfg, + algorithms: { compress: [ 'zlib' ] }, + }, + server: { + ...serverCfg, + algorithms: { compress: [ 'zlib', 'none' ] }, + } + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + const reqs = []; + conn.on('session', mustCall((accept, reject) => { + if (reqs.length === 0) { + // XXX: hack to change algorithms after initial handshake + client._protocol._offer = new KexInit({ + kex: [ 'ecdh-sha2-nistp256' ], + serverHostKey: [ 'rsa-sha2-256' ], + cs: { + cipher: [ 'aes128-gcm@openssh.com' ], + mac: [], + compress: [ 'none' ], + lang: [], + }, + sc: { + cipher: [ 'aes128-gcm@openssh.com' ], + mac: [], + compress: [ 'none' ], + lang: [], + }, + }); + + conn.rekey(mustCall((err) => { + assert(!err, `Unexpected rekey error: ${err}`); + reqs.forEach((accept) => { + const session = accept(); + session.on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + stream.exit(0); + stream.end(); + })); + }); + })); + } + reqs.push(accept); + }, 3)); + })); + })); + + let handshakes = 0; + client.on('handshake', mustCall((info) => { + switch (++handshakes) { + case 1: + assert(info.cs.compress === 'zlib', 'wrong compress value'); + assert(info.sc.compress === 'zlib', 'wrong compress value'); + break; + case 2: + assert(info.cs.compress === 'none', 'wrong compress value'); + assert(info.sc.compress === 'none', 'wrong compress value'); + break; + } + }, 2)).on('ready', mustCall(() => { + let calledBack = 0; + function callback(err, stream) { + assert(!err, `Unexpected error: ${err}`); + stream.resume(); + if (++calledBack === 3) + client.end(); + } + client.exec('foo', mustCall(callback)); + client.exec('bar', mustCall(callback)); + client.exec('baz', mustCall(callback)); + })); +} + +{ + const { client, server } = setup_( + 'Large data compression', + { + client: { + ...clientCfg, + algorithms: { compress: [ 'zlib' ] }, + }, + server: { + ...serverCfg, + algorithms: { compress: [ 'zlib' ] }, + } + }, + ); + + const chunk = Buffer.alloc(1024 * 1024, 'a'); + const chunkCount = 10; + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject, info) => { + const stream = accept(); + for (let i = 0; i < chunkCount; ++i) + stream.write(chunk); + stream.exit(0); + stream.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo', mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + let nb = 0; + stream.on('data', mustCallAtLeast((data) => { + nb += data.length; + })).on('end', mustCall(() => { + assert(nb === (chunkCount * chunk.length), + `Wrong stream byte count: ${nb}`); + client.end(); + })); + })); + })); +} + +{ + const { client, server } = setup_( + 'Debug output', + { + client: { + ...clientCfg, + debug: mustCallAtLeast((msg) => { + assert(typeof msg === 'string', + `Wrong debug argument type: ${typeof msg}`); + assert(msg.length > 0, 'Unexpected empty debug message'); + }), + }, + server: { + ...serverCfg, + debug: mustCallAtLeast((msg) => { + assert(typeof msg === 'string', + `Wrong debug argument type: ${typeof msg}`); + assert(msg.length > 0, 'Unexpected empty debug message'); + }), + }, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('exec', mustCall((accept, reject, info) => { + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo --bar', mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.resume(); + })); + })); +} + +{ + const { server } = setup_( + 'HTTP agent', + { + // No automatic client, the agent will create one + + server: serverCfg, + + debug, + }, + ); + + let httpServer; + server.on('listening', () => { + httpServer = http.createServer((req, res) => { + httpServer.close(); + res.end('hello world!'); + }); + httpServer.listen(0, 'localhost', () => { + const agent = new HTTPAgent({ + host: 'localhost', + port: server.address().port, + username: 'foo', + password: 'bar', + }); + http.get({ + host: 'localhost', + port: httpServer.address().port, + agent, + headers: { Connection: 'close' }, + }, (res) => { + assert(res.statusCode === 200, + `Wrong http status code: ${res.statusCode}`); + let buf = ''; + res.on('data', mustCallAtLeast((chunk) => { + buf += chunk; + })).on('end', mustCall(() => { + assert(buf === 'hello world!', + `Wrong http response body: ${inspect(buf)}`); + })); + }); + }); + }); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('tcpip', mustCall((accept, reject, info) => { + assert(info.destIP === 'localhost', `Wrong destIP: ${info.destIP}`); + assert(info.destPort === httpServer.address().port, + `Wrong destPort: ${info.destPort}`); + assert(info.srcIP === 'localhost', `Wrong srcIP: ${info.srcIP}`); + + const stream = accept(); + const tcp = new net.Socket(); + tcp.pipe(stream).pipe(tcp); + tcp.connect(httpServer.address().port, 'localhost'); + })); + })); + })); +} + +{ + const { server } = setup_( + 'HTTPS agent', + { + // No automatic client, the agent will create one + + server: serverCfg, + + debug, + }, + ); + + let httpsServer; + server.on('listening', () => { + httpsServer = https.createServer({ + key: fixture('https_key.pem'), + cert: fixture('https_cert.pem'), + }, (req, res) => { + httpsServer.close(); + res.end('hello world!'); + }); + httpsServer.listen(0, 'localhost', () => { + const agent = new HTTPSAgent({ + host: 'localhost', + port: server.address().port, + username: 'foo', + password: 'bar', + }); + https.get({ + host: 'localhost', + port: httpsServer.address().port, + agent, + headers: { Connection: 'close' }, + ca: fixture('https_cert.pem'), + }, (res) => { + assert(res.statusCode === 200, + `Wrong http status code: ${res.statusCode}`); + let buf = ''; + res.on('data', mustCallAtLeast((chunk) => { + buf += chunk; + })).on('end', mustCall(() => { + assert(buf === 'hello world!', + `Wrong http response body: ${inspect(buf)}`); + })); + }).on('error', (err) => { + // This workaround is necessary for some reason on node < v14.x + if (!/write after end/i.test(err.message)) + throw err; + }); + }); + }); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('tcpip', mustCall((accept, reject, info) => { + assert(info.destIP === 'localhost', `Wrong destIP: ${info.destIP}`); + assert(info.destPort === httpsServer.address().port, + `Wrong destPort: ${info.destPort}`); + assert(info.srcIP === 'localhost', `Wrong srcIP: ${info.srcIP}`); + + const stream = accept(); + const tcp = new net.Socket(); + tcp.pipe(stream).pipe(tcp); + tcp.connect(httpsServer.address().port, 'localhost'); + })); + })); + })); +} + +[ + { desc: 'remove/append/prepend (regexps)', + config: { + remove: /.*/, + append: /gcm/, + prepend: /ctr/, + }, + expected: [ + 'aes128-ctr', + 'aes192-ctr', + 'aes256-ctr', + 'aes128-gcm', + 'aes128-gcm@openssh.com', + 'aes256-gcm', + 'aes256-gcm@openssh.com', + ], + }, + { desc: 'remove/append/prepend (strings)', + config: { + remove: /.*/, + append: 'aes256-ctr', + prepend: [ 'aes256-gcm', 'aes128-gcm' ], + }, + expected: [ + 'aes256-gcm', + 'aes128-gcm', + 'aes256-ctr', + ], + }, +].forEach((info) => { + const { client, server } = setup_( + `Client algorithms option (${info.desc})`, + { + client: { + ...clientCfg, + algorithms: { cipher: info.config }, + }, + server: serverCfg, + + debug, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); + client.on('ready', mustCall(() => { + // XXX: hack to easily verify computed offer + const offer = client._protocol._offer.lists; + assert.deepStrictEqual( + offer.cs.cipher.array, + info.expected, + `Wrong algorithm list: ${offer.cs.cipher.array}` + ); + })); +}); + +{ + const { client } = setup_( + `Safely end() from Client 'error' event handler`, + { + client: clientCfg, + noClientError: true, + noForceClientReady: true, + }, + ); + + const badServer = net.createServer((s) => {}); + badServer.listen(0, 'localhost', mustCall(() => { + badServer.unref(); + + client.on('error', mustCallAtLeast((err) => { + client.end(); + })).on('ready', mustNotCall()).on('close', mustCall(() => {})); + client.connect({ + host: 'localhost', + port: badServer.address().port, + user: 'foo', + password: 'bar', + readyTimeout: 1, + }); + })); +} + +{ + const { client } = setup_( + 'Client error should be emitted on bad/nonexistent greeting', + { + client: clientCfg, + noClientError: true, + noForceClientReady: true, + }, + ); + + const badServer = net.createServer(mustCall((s) => { + badServer.close(); + s.end(); + })).listen(0, 'localhost', mustCall(() => { + client.on('error', mustCall((err) => { + client.end(); + })).on('ready', mustNotCall()).on('close', mustCall(() => {})); + client.connect({ + host: 'localhost', + port: badServer.address().port, + user: 'foo', + password: 'bar', + }); + })); +} + +{ + const { client } = setup_( + 'Only one client error on connection failure', + { + client: clientCfg, + noClientError: true, + noForceClientReady: true, + }, + ); + + client.on('error', mustCall((err) => { + assert.strictEqual(err.syscall, 'getaddrinfo'); + })); + client.connect({ + host: 'blerbblubblubblerb', + port: 9999, + user: 'foo', + password: 'bar' + }); +} + +{ + const { client, server } = setup( + 'Client should remove reserved channels on incoming channel rejection' + ); + + const assignedPort = 31337; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('request', mustCall((accept, reject, name, info) => { + assert(name === 'tcpip-forward', 'Wrong request name'); + assert.deepStrictEqual( + info, + { bindAddr: 'good', bindPort: 0 }, + 'Wrong request info' + ); + accept(assignedPort); + conn.forwardOut(info.bindAddr, + assignedPort, + 'remote', + 12345, + mustCall((err, ch) => { + assert(err, 'Should receive error'); + client.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + // request forwarding + client.forwardIn('good', 0, mustCall((err, port) => { + assert(!err, `Unexpected error: ${err}`); + assert(port === assignedPort, 'Wrong assigned port'); + })); + })).on('tcp connection', mustCall((details, accept, reject) => { + assert.deepStrictEqual( + details, + { destIP: 'good', + destPort: assignedPort, + srcIP: 'remote', + srcPort: 12345 + }, + 'Wrong connection details' + ); + assert.strictEqual(Object.keys(client._chanMgr._channels).length, 1); + assert.strictEqual(client._chanMgr._count, 1); + reject(); + assert.strictEqual(Object.keys(client._chanMgr._channels).length, 0); + assert.strictEqual(client._chanMgr._count, 0); + })); +} + +{ + // Allow injected sockets + + const socket = new Transform({ + emitClose: true, + autoDestroy: true, + transform: (chunk, encoding, cb) => { + cb(); + }, + }); + socket.remoteAddress = '127.0.0.1'; + socket.remotePort = '12345'; + socket.remoteFamily = 'IPv4'; + socket.push(Buffer.from('SSH-2.0-foo\r\n')); + + const server = new Server(serverCfg); + server.on('connection', mustCall((conn, info) => { + assert.strictEqual(info.header.versions.software, 'foo'); + assert.strictEqual(info.ip, '127.0.0.1'); + assert.strictEqual(info.port, '12345'); + assert.strictEqual(info.family, 'IPv4'); + conn.on('ready', mustNotCall()); + conn.on('close', mustCall()); + socket.end(); + })); + server.injectSocket(socket); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-openssh.js b/reverse_engineering/node_modules/ssh2/test/test-openssh.js index ae2c4b0..67e1b86 100644 --- a/reverse_engineering/node_modules/ssh2/test/test-openssh.js +++ b/reverse_engineering/node_modules/ssh2/test/test-openssh.js @@ -1,459 +1,261 @@ -var Server = require('../lib/server'); -var utils = require('ssh2-streams').utils; - -var semver = require('semver'); - -var fs = require('fs'); -var crypto = require('crypto'); -var path = require('path'); -var join = path.join; -var assert = require('assert'); -var spawn = require('child_process').spawn; -var exec = require('child_process').exec; - -var t = -1; -var group = path.basename(__filename, '.js') + '/'; -var fixturesdir = join(__dirname, 'fixtures'); - -var CLIENT_TIMEOUT = 5000; -var USER = 'nodejs'; -var HOST_KEY_RSA = fs.readFileSync(join(fixturesdir, 'ssh_host_rsa_key')); -var HOST_KEY_DSA = fs.readFileSync(join(fixturesdir, 'ssh_host_dsa_key')); -var HOST_KEY_ECDSA = fs.readFileSync(join(fixturesdir, 'ssh_host_ecdsa_key')); -var CLIENT_KEY_RSA_PATH = join(fixturesdir, 'id_rsa'); -var CLIENT_KEY_RSA = fs.readFileSync(CLIENT_KEY_RSA_PATH); -var CLIENT_KEY_RSA_PUB = utils.genPublicKey(utils.parseKey(CLIENT_KEY_RSA)); -var CLIENT_KEY_DSA_PATH = join(fixturesdir, 'id_dsa'); -var CLIENT_KEY_DSA = fs.readFileSync(CLIENT_KEY_DSA_PATH); -var CLIENT_KEY_DSA_PUB = utils.genPublicKey(utils.parseKey(CLIENT_KEY_DSA)); -if (semver.gte(process.version, '5.2.0')) { - var CLIENT_KEY_ECDSA_PATH = join(fixturesdir, 'id_ecdsa'); - var CLIENT_KEY_ECDSA = fs.readFileSync(CLIENT_KEY_ECDSA_PATH); - var CLIENT_KEY_ECDSA_PUB = utils.genPublicKey( - utils.parseKey(CLIENT_KEY_ECDSA) - ); -} -var opensshVer; -var DEBUG = false; - -// Fix file modes to avoid OpenSSH client complaints about keys' permissions -fs.readdirSync(fixturesdir).forEach(function(file) { - fs.chmodSync(join(fixturesdir, file), '0600'); -}); - -var tests = [ - { run: function() { - var what = this.what; - var server; - - server = setup( - this, - { privateKeyPath: CLIENT_KEY_RSA_PATH }, - { hostKeys: [HOST_KEY_RSA] } - ); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - if (ctx.method === 'none') - return ctx.reject(); - assert(ctx.method === 'publickey', - makeMsg(what, 'Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg(what, 'Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-rsa', - makeMsg(what, 'Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_RSA_PUB.public, - ctx.key.data, - makeMsg(what, 'Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('RSA-SHA1'); - var pem = CLIENT_KEY_RSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg(what, 'Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - if (session) { - session.on('exec', function(accept, reject) { - var stream = accept(); - if (stream) { - stream.exit(0); - stream.end(); - } - }).on('pty', function(accept, reject) { - accept && accept(); - }); - } - }); - }); - }); +'use strict'; + +const assert = require('assert'); +const { inspect } = require('util'); + +const { + fixture, + mustCall, + mustCallAtLeast, + setup: setup_, +} = require('./common.js'); + +const debug = false; + +const clientCfg = { username: 'foo', password: 'bar' }; +const serverCfg = { hostKeys: [ fixture('ssh_host_rsa_key') ] }; + +{ + const { client, server } = setup_( + 'Exec with OpenSSH agent forwarding', + { + client: { + ...clientCfg, + agent: '/path/to/agent', + }, + server: serverCfg, + + debug, }, - what: 'Authenticate with an RSA key' - }, - { run: function() { - var what = this.what; - var server; - - server = setup( - this, - { privateKeyPath: CLIENT_KEY_DSA_PATH }, - { hostKeys: [HOST_KEY_RSA] } - ); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - if (ctx.method === 'none') - return ctx.reject(); - assert(ctx.method === 'publickey', - makeMsg(what, 'Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg(what, 'Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ssh-dss', - makeMsg(what, 'Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_DSA_PUB.public, - ctx.key.data, - makeMsg(what, 'Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('DSA-SHA1'); - var pem = CLIENT_KEY_DSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg(what, 'Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - if (session) { - session.on('exec', function(accept, reject) { - var stream = accept(); - if (stream) { - stream.exit(0); - stream.end(); - } - }).on('pty', function(accept, reject) { - accept && accept(); - }); - } - }); - }); - }); - }, - what: 'Authenticate with a DSA key' - }, - { run: function() { - if (semver.lt(process.version, '5.2.0')) - return next(); - var what = this.what; - var server; - - server = setup( - this, - { privateKeyPath: CLIENT_KEY_ECDSA_PATH }, - { hostKeys: [HOST_KEY_RSA] } - ); - - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - if (ctx.method === 'none') - return ctx.reject(); - assert(ctx.method === 'publickey', - makeMsg(what, 'Unexpected auth method: ' + ctx.method)); - assert(ctx.username === USER, - makeMsg(what, 'Unexpected username: ' + ctx.username)); - assert(ctx.key.algo === 'ecdsa-sha2-nistp256', - makeMsg(what, 'Unexpected key algo: ' + ctx.key.algo)); - assert.deepEqual(CLIENT_KEY_ECDSA_PUB.public, - ctx.key.data, - makeMsg(what, 'Public key mismatch')); - if (ctx.signature) { - var verifier = crypto.createVerify('sha256'); - var pem = CLIENT_KEY_ECDSA_PUB.publicOrig; - verifier.update(ctx.blob); - assert(verifier.verify(pem, ctx.signature), - makeMsg(what, 'Could not verify PK signature')); - ctx.accept(); - } else - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - if (session) { - session.on('exec', function(accept, reject) { - var stream = accept(); - if (stream) { - stream.exit(0); - stream.end(); - } - }).on('pty', function(accept, reject) { - accept && accept(); - }); - } - }); - }); - }); - }, - what: 'Authenticate with a ECDSA key' - }, - { run: function() { - var server; + ); - server = setup( - this, - { privateKeyPath: CLIENT_KEY_RSA_PATH }, - { hostKeys: [HOST_KEY_DSA] } - ); + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let sawAuthAgent = false; + accept().on('auth-agent', mustCall((accept, reject) => { + sawAuthAgent = true; + accept && accept(); + })).on('exec', mustCall((accept, reject, info) => { + assert(sawAuthAgent, 'Expected auth-agent before exec'); + assert(info.command === 'foo --bar', + `Wrong exec command: ${info.command}`); + const stream = accept(); + stream.exit(100); + stream.end(); + conn.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.exec('foo --bar', { agentForward: true }, mustCall((err, stream) => { + assert(!err, `Unexpected exec error: ${err}`); + stream.resume(); + })); + })); +} - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - if (session) { - session.on('exec', function(accept, reject) { - var stream = accept(); - if (stream) { - stream.exit(0); - stream.end(); - } - }).on('pty', function(accept, reject) { - accept && accept(); - }); - } - }); - }); - }); +{ + const { client, server } = setup_( + 'OpenSSH forwarded UNIX socket connection', + { + client: clientCfg, + server: { + ...serverCfg, + ident: 'OpenSSH_7.1', + }, + + debug, }, - what: 'Server with DSA host key' - }, - { run: function() { - if (semver.lt(process.version, '5.2.0')) - return next(); - var server; + ); - server = setup( - this, - { privateKeyPath: CLIENT_KEY_RSA_PATH }, - { hostKeys: [HOST_KEY_ECDSA] } - ); + const socketPath = '/foo'; + const events = []; + const expected = [ + ['client', 'openssh_forwardInStreamLocal'], + ['server', 'streamlocal-forward@openssh.com', { socketPath }], + ['client', 'forward callback'], + ['client', 'unix connection', { socketPath }], + ['client', 'socket data', '1'], + ['server', 'socket data', '2'], + ['client', 'socket end'], + ['server', 'cancel-streamlocal-forward@openssh.com', { socketPath }], + ['client', 'cancel callback'] + ]; + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.once('request', mustCall((accept, reject, name, info) => { + events.push(['server', name, info]); + assert(name === 'streamlocal-forward@openssh.com', + `Wrong request name: ${name}`); + accept(); + conn.openssh_forwardOutStreamLocal(socketPath, + mustCall((err, ch) => { + assert(!err, `Unexpected error: ${err}`); + ch.write('1'); + ch.on('data', mustCallAtLeast((data) => { + events.push(['server', 'socket data', data.toString()]); + ch.close(); + })); + })); + + conn.on('request', mustCall((accept, reject, name, info) => { + events.push(['server', name, info]); + assert(name === 'cancel-streamlocal-forward@openssh.com', + `Wrong request name: ${name}`); + accept(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + // request forwarding + events.push(['client', 'openssh_forwardInStreamLocal']); + client.openssh_forwardInStreamLocal(socketPath, mustCall((err) => { + assert(!err, `Unexpected error: ${err}`); + events.push(['client', 'forward callback']); + })); + client.on('unix connection', mustCall((info, accept, reject) => { + events.push(['client', 'unix connection', info]); + const stream = accept(); + stream.on('data', mustCallAtLeast((data) => { + events.push(['client', 'socket data', data.toString()]); + stream.write('2'); + })).on('end', mustCall(() => { + events.push(['client', 'socket end']); + client.openssh_unforwardInStreamLocal(socketPath, + mustCall((err) => { + assert(!err, `Unexpected error: ${err}`); + events.push(['client', 'cancel callback']); + client.end(); + })); + })); + })); + })).on('close', mustCall(() => { + assert.deepStrictEqual( + events, + expected, + 'Events mismatch\n' + + `Actual:\n${inspect(events)}\n` + + `Expected:\n${inspect(expected)}` + ); + })); +} - server.on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - if (session) { - session.on('exec', function(accept, reject) { - var stream = accept(); - if (stream) { - stream.exit(0); - stream.end(); - } - }).on('pty', function(accept, reject) { - accept && accept(); - }); - } - }); - }); - }); +{ + const { client, server } = setup_( + 'OpenSSH UNIX socket connection', + { + client: clientCfg, + server: { + ...serverCfg, + ident: 'OpenSSH_8.0', + }, + + debug, }, - what: 'Server with ECDSA host key' - }, - { run: function() { - var server; - var what = this.what; + ); - server = setup( - this, - { privateKeyPath: CLIENT_KEY_RSA_PATH }, - { hostKeys: [HOST_KEY_RSA] } - ); + const socketPath = '/foo/bar/baz'; + const response = 'Hello World'; + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('openssh.streamlocal', mustCall((accept, reject, info) => { + assert.deepStrictEqual( + info, + { socketPath }, + `Wrong info: ${inspect(info)}` + ); + + const stream = accept(); + stream.on('close', mustCall(() => { + client.end(); + })).end(response); + stream.resume(); + })); + })); + })); + + client.on('ready', mustCall(() => { + client.openssh_forwardOutStreamLocal(socketPath, mustCall((err, stream) => { + assert(!err, `Unexpected error: ${err}`); + let buf = ''; + stream.on('data', mustCallAtLeast((data) => { + buf += data; + })).on('close', mustCall(() => { + assert(buf === response, `Wrong response: ${inspect(buf)}`); + })); + })); + })); +} - server.on('_child', function(childProc) { - childProc.stderr.once('data', function(data) { - childProc.stdin.end(); - }); - childProc.stdin.write('ping'); - }).on('connection', function(conn) { - conn.on('authentication', function(ctx) { - ctx.accept(); - }).on('ready', function() { - conn.on('session', function(accept, reject) { - var session = accept(); - assert(session, makeMsg(what, 'Missing session')); - session.on('exec', function(accept, reject) { - var stream = accept(); - assert(stream, makeMsg(what, 'Missing exec stream')); - stream.stdin.on('data', function(data) { - stream.stdout.write('pong on stdout'); - stream.stderr.write('pong on stderr'); - }).on('end', function() { - stream.stdout.write('pong on stdout'); - stream.stderr.write('pong on stderr'); - stream.exit(0); - stream.close(); - }); - }).on('pty', function(accept, reject) { - accept && accept(); - }); - }); - }); - }); +{ + const { client, server } = setup_( + 'OpenSSH 5.x workaround for binding on port 0', + { + client: clientCfg, + server: { + ...serverCfg, + ident: 'OpenSSH_5.3', + }, + + debug, }, - what: 'Server closes stdin too early' - }, -]; + ); -function setup(self, clientcfg, servercfg) { - self.state = { - serverReady: false, - clientClose: false, - serverClose: false + const boundAddr = 'good'; + const boundPort = 1337; + const tcpInfo = { + destIP: boundAddr, + destPort: boundPort, + srcIP: 'remote', + srcPort: 12345, }; - var client; - var server = new Server(servercfg); - - server.on('error', onError) - .on('connection', function(conn) { - conn.on('error', onError) - .on('ready', onReady); - server.close(); - }) - .on('close', onClose); - - function onError(err) { - var which = (arguments.length >= 3 ? 'client' : 'server'); - assert(false, makeMsg(self.what, 'Unexpected ' + which + ' error: ' + err)); - } - function onReady() { - assert(!self.state.serverReady, - makeMsg(self.what, 'Received multiple ready events for server')); - self.state.serverReady = true; - self.onReady && self.onReady(); - } - function onClose() { - if (arguments.length >= 3) { - assert(!self.state.clientClose, - makeMsg(self.what, 'Received multiple close events for client')); - self.state.clientClose = true; - } else { - assert(!self.state.serverClose, - makeMsg(self.what, 'Received multiple close events for server')); - self.state.serverClose = true; - } - if (self.state.clientClose && self.state.serverClose) - next(); - } - - process.nextTick(function() { - server.listen(0, 'localhost', function() { - var cmd = 'ssh'; - var args = ['-o', 'UserKnownHostsFile=/dev/null', - '-o', 'StrictHostKeyChecking=no', - '-o', 'CheckHostIP=no', - '-o', 'ConnectTimeout=3', - '-o', 'GlobalKnownHostsFile=/dev/null', - '-o', 'GSSAPIAuthentication=no', - '-o', 'IdentitiesOnly=yes', - '-o', 'BatchMode=yes', - '-o', 'VerifyHostKeyDNS=no', - - '-vvvvvv', - '-T', - '-o', 'KbdInteractiveAuthentication=no', - '-o', 'HostbasedAuthentication=no', - '-o', 'PasswordAuthentication=no', - '-o', 'PubkeyAuthentication=yes', - '-o', 'PreferredAuthentications=publickey']; - if (clientcfg.privateKeyPath) - args.push('-o', 'IdentityFile=' + clientcfg.privateKeyPath); - if (!/^[0-6]\./.test(opensshVer)) { - // OpenSSH 7.0+ disables DSS/DSA host (and user) key support by - // default, so we explicitly enable it here - args.push('-o', 'HostKeyAlgorithms=+ssh-dss'); - } - args.push('-p', server.address().port.toString(), - '-l', USER, - 'localhost', - 'uptime'); - - client = spawn(cmd, args); - server.emit('_child', client); - if (DEBUG) { - client.stdout.pipe(process.stdout); - client.stderr.pipe(process.stderr); - } else { - client.stdout.resume(); - client.stderr.resume(); - } - client.on('error', function(err) { - onError(err, null, null); - }).on('exit', function(code) { - clearTimeout(client.timer); - if (code !== 0) - return onError(new Error('Non-zero exit code ' + code), null, null); - onClose(null, null, null); - }); - - client.timer = setTimeout(function() { - assert(false, makeMsg(self.what, 'Client timeout')); - }, CLIENT_TIMEOUT); - }); - }); - return server; + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('request', mustCall((accept, reject, name, info) => { + assert(name === 'tcpip-forward', `Unexpected request: ${name}`); + assert(info.bindAddr === boundAddr, `Wrong addr: ${info.bindAddr}`); + assert(info.bindPort === 0, `Wrong port: ${info.bindPort}`); + accept(boundPort); + conn.forwardOut(boundAddr, + 0, + tcpInfo.srcIP, + tcpInfo.srcPort, + mustCall((err, ch) => { + assert(!err, `Unexpected error: ${err}`); + client.end(); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + // request forwarding + client.forwardIn(boundAddr, 0, mustCall((err, port) => { + assert(!err, `Unexpected error: ${err}`); + assert(port === boundPort, `Bad bound port: ${port}`); + })); + })).on('tcp connection', mustCall((details, accept, reject) => { + assert.deepStrictEqual( + details, + tcpInfo, + `Wrong tcp details: ${inspect(details)}` + ); + accept(); + })); } - -function next() { - if (Array.isArray(process._events.exit)) - process._events.exit = process._events.exit[1]; - if (++t === tests.length) - return; - - var v = tests[t]; - v.run.call(v); -} - -function makeMsg(what, msg) { - return '[' + group + what + ']: ' + msg; -} - -process.once('uncaughtException', function(err) { - if (t > -1 && !/(?:^|\n)AssertionError: /i.test(''+err)) - console.log(makeMsg(tests[t].what, 'Unexpected Exception:')); - throw err; -}); -process.once('exit', function() { - assert(t === tests.length, - makeMsg('_exit', - 'Only finished ' + t + '/' + tests.length + ' tests')); -}); - - -// Get OpenSSH client version first -exec('ssh -V', function(err, stdout, stderr) { - if (err) { - console.log('OpenSSH client is required for these tests'); - process.exitCode = 5; - return; - } - var re = /^OpenSSH_([\d\.]+)/; - var m = re.exec(stdout.toString()); - if (!m || !m[1]) { - m = re.exec(stderr.toString()); - if (!m || !m[1]) { - console.log('OpenSSH client is required for these tests'); - process.exitCode = 5; - return; - } - } - opensshVer = m[1]; - next(); -}); diff --git a/reverse_engineering/node_modules/ssh2/test/test-protocol-crypto.js b/reverse_engineering/node_modules/ssh2/test/test-protocol-crypto.js new file mode 100644 index 0000000..8cae94c --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-protocol-crypto.js @@ -0,0 +1,609 @@ +'use strict'; + +const assert = require('assert'); +const { randomBytes } = require('crypto'); + +const { + CIPHER_INFO, + MAC_INFO, + bindingAvailable, + NullCipher, + createCipher, + NullDecipher, + createDecipher, + init: cryptoInit, +} = require('../lib/protocol/crypto.js'); + +(async () => { + await cryptoInit; + + console.log(`Crypto binding ${bindingAvailable ? '' : 'not '}available`); + { + const PAIRS = [ + // cipher, decipher + ['native', 'native'], + ['binding', 'native'], + ['native', 'binding'], + ['binding', 'binding'], + ].slice(0, bindingAvailable ? 4 : 1); + + [ + { cipher: null }, + { cipher: 'chacha20-poly1305@openssh.com' }, + { cipher: 'aes128-gcm@openssh.com' }, + { cipher: 'aes128-cbc', mac: 'hmac-sha1-etm@openssh.com' }, + { cipher: 'aes128-ctr', mac: 'hmac-sha1' }, + { cipher: 'arcfour', mac: 'hmac-sha2-256-96' }, + ].forEach((testConfig) => { + for (const pair of PAIRS) { + function onCipherData(data) { + ciphered = Buffer.concat([ciphered, data]); + } + + function onDecipherPayload(payload) { + deciphered.push(payload); + } + + function reset() { + ciphered = Buffer.alloc(0); + deciphered = []; + } + + function reinit() { + if (testConfig.cipher === null) { + cipher = new NullCipher(1, onCipherData); + decipher = new NullDecipher(1, onDecipherPayload); + } else { + cipher = createCipher(config); + decipher = createDecipher(config); + } + } + + let ciphered; + let deciphered; + let cipher; + let decipher; + let macSize; + let packet; + let payload; + let cipherInfo; + let config; + + console.log('Testing cipher: %s, mac: %s (%s encrypt, %s decrypt) ...', + testConfig.cipher, + testConfig.mac + || (testConfig.cipher === null ? '' : ''), + pair[0], + pair[1]); + + if (testConfig.cipher === null) { + cipher = new NullCipher(1, onCipherData); + decipher = new NullDecipher(1, onDecipherPayload); + macSize = 0; + } else { + cipherInfo = CIPHER_INFO[testConfig.cipher]; + let macInfo; + let macKey; + if (testConfig.mac) { + macInfo = MAC_INFO[testConfig.mac]; + macKey = randomBytes(macInfo.len); + macSize = macInfo.actualLen; + } else if (cipherInfo.authLen) { + macSize = cipherInfo.authLen; + } else { + throw new Error('Missing MAC for cipher'); + } + const key = randomBytes(cipherInfo.keyLen); + const iv = (cipherInfo.ivLen + ? randomBytes(cipherInfo.ivLen) + : Buffer.alloc(0)); + config = { + outbound: { + onWrite: onCipherData, + cipherInfo, + cipherKey: Buffer.from(key), + cipherIV: Buffer.from(iv), + seqno: 1, + macInfo, + macKey: (macKey && Buffer.from(macKey)), + forceNative: (pair[0] === 'native'), + }, + inbound: { + onPayload: onDecipherPayload, + decipherInfo: cipherInfo, + decipherKey: Buffer.from(key), + decipherIV: Buffer.from(iv), + seqno: 1, + macInfo, + macKey: (macKey && Buffer.from(macKey)), + forceNative: (pair[1] === 'native'), + }, + }; + cipher = createCipher(config); + decipher = createDecipher(config); + + if (pair[0] === 'binding') + assert(/binding/i.test(cipher.constructor.name)); + else + assert(/native/i.test(cipher.constructor.name)); + if (pair[1] === 'binding') + assert(/binding/i.test(decipher.constructor.name)); + else + assert(/native/i.test(decipher.constructor.name)); + } + + let expectedSeqno; + // Test zero-length payload ============================================ + payload = Buffer.alloc(0); + expectedSeqno = 2; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual(decipher.decrypt(ciphered, 0, ciphered.length), + undefined); + + assert.strictEqual(cipher.outSeqno, expectedSeqno); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test single byte payload ============================================ + payload = Buffer.from([ 0xEF ]); + expectedSeqno = 3; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual(decipher.decrypt(ciphered, 0, ciphered.length), + undefined); + + assert.strictEqual(cipher.outSeqno, 3); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test large payload ================================================== + payload = randomBytes(32 * 1024); + expectedSeqno = 4; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual(decipher.decrypt(ciphered, 0, ciphered.length), + undefined); + + assert.strictEqual(cipher.outSeqno, expectedSeqno); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test sequnce number rollover ======================================== + payload = randomBytes(4); + expectedSeqno = 0; + cipher.outSeqno = decipher.inSeqno = (2 ** 32) - 1; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual(decipher.decrypt(ciphered, 0, ciphered.length), + undefined); + + assert.strictEqual(cipher.outSeqno, expectedSeqno); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test chunked input -- split length bytes ============================ + payload = randomBytes(32 * 768); + expectedSeqno = 1; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual(decipher.decrypt(ciphered, 0, 2), undefined); + assert.strictEqual(decipher.decrypt(ciphered, 2, ciphered.length), + undefined); + + assert.strictEqual(cipher.outSeqno, expectedSeqno); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test chunked input -- split length from payload ===================== + payload = randomBytes(32 * 768); + expectedSeqno = 2; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual(decipher.decrypt(ciphered, 0, 4), undefined); + assert.strictEqual(decipher.decrypt(ciphered, 4, ciphered.length), + undefined); + + assert.strictEqual(cipher.outSeqno, expectedSeqno); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test chunked input -- split length and payload from MAC ============= + payload = randomBytes(32 * 768); + expectedSeqno = 3; + + reset(); + packet = cipher.allocPacket(payload.length); + payload.copy(packet, 5); + cipher.encrypt(packet); + assert.strictEqual( + decipher.decrypt(ciphered, 0, ciphered.length - macSize), + undefined + ); + assert.strictEqual( + decipher.decrypt(ciphered, + ciphered.length - macSize, + ciphered.length), + undefined + ); + + assert.strictEqual(cipher.outSeqno, expectedSeqno); + assert(ciphered.length >= 9 + macSize); + assert.strictEqual(decipher.inSeqno, cipher.outSeqno); + assert.strictEqual(deciphered.length, 1); + assert.deepStrictEqual(deciphered[0], payload); + + // Test packet length checks =========================================== + [0, 2 ** 32 - 1].forEach((n) => { + reset(); + packet = cipher.allocPacket(0); + packet.writeUInt32BE(n, 0); // Overwrite packet length field + cipher.encrypt(packet); + let threw = false; + try { + decipher.decrypt(ciphered, 0, ciphered.length); + } catch (ex) { + threw = true; + assert(ex instanceof Error); + assert(/packet length/i.test(ex.message)); + } + if (!threw) + throw new Error('Expected error'); + + // Recreate deciphers since errors leave them in an unusable state. + // We recreate the ciphers as well so that internal states of both + // ends match again. + reinit(); + }); + + // Test minimum padding length check =================================== + if (testConfig.cipher !== null) { + let payloadLen; + const blockLen = cipherInfo.blockLen; + if (/chacha|gcm/i.test(testConfig.cipher) + || /etm/i.test(testConfig.mac)) { + payloadLen = blockLen - 2; + } else { + payloadLen = blockLen - 6; + } + const minLen = 4 + 1 + payloadLen + (blockLen + 1); + // We don't do strict equality checks here since the length of the + // returned Buffer can vary due to implementation details. + assert(cipher.allocPacket(payloadLen).length >= minLen); + } + + // ===================================================================== + cipher.free(); + decipher.free(); + if (testConfig.cipher === null) + break; + } + }); + } + + // Test createCipher()/createDecipher() exceptions + { + [ + [ + [true, null], + /invalid config/i + ], + [ + [{}], + [/invalid outbound/i, /invalid inbound/i] + ], + [ + [{ outbound: {}, inbound: {} }], + [/invalid outbound\.onWrite/i, /invalid inbound\.onPayload/i] + ], + [ + [ + { outbound: { + onWrite: () => {}, + cipherInfo: true + }, + inbound: { + onPayload: () => {}, + decipherInfo: true + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: null + }, + inbound: { + onPayload: () => {}, + decipherInfo: null + }, + }, + ], + [/invalid outbound\.cipherInfo/i, /invalid inbound\.decipherInfo/i] + ], + [ + [ + { outbound: { + onWrite: () => {}, + cipherInfo: {}, + cipherKey: {}, + }, + inbound: { + onPayload: () => {}, + decipherInfo: {}, + decipherKey: {}, + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 32 }, + cipherKey: Buffer.alloc(8), + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 32 }, + decipherKey: Buffer.alloc(8), + }, + }, + ], + [/invalid outbound\.cipherKey/i, /invalid inbound\.decipherKey/i] + ], + [ + [ + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 12 }, + cipherKey: Buffer.alloc(1), + cipherIV: true + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 12 }, + decipherKey: Buffer.alloc(1), + cipherIV: true + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 12 }, + cipherKey: Buffer.alloc(1), + cipherIV: null + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 12 }, + decipherKey: Buffer.alloc(1), + cipherIV: null + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 12 }, + cipherKey: Buffer.alloc(1), + cipherIV: {} + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 12 }, + decipherKey: Buffer.alloc(1), + cipherIV: {} + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 12 }, + cipherKey: Buffer.alloc(1), + cipherIV: Buffer.alloc(1) + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 12 }, + decipherKey: Buffer.alloc(1), + cipherIV: Buffer.alloc(1) + }, + }, + ], + [/invalid outbound\.cipherIV/i, /invalid inbound\.decipherIV/i] + ], + [ + [ + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0 }, + cipherKey: Buffer.alloc(1), + seqno: true + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0 }, + decipherKey: Buffer.alloc(1), + seqno: true + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0 }, + cipherKey: Buffer.alloc(1), + seqno: -1 + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0 }, + decipherKey: Buffer.alloc(1), + seqno: -1 + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0 }, + cipherKey: Buffer.alloc(1), + seqno: 2 ** 32 + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0 }, + decipherKey: Buffer.alloc(1), + seqno: 2 ** 32 + }, + }, + ], + [/invalid outbound\.seqno/i, /invalid inbound\.seqno/i] + ], + [ + [ + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0 + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0 + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: true + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: true + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: null + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: null + }, + }, + ], + [/invalid outbound\.macInfo/i, /invalid inbound\.macInfo/i] + ], + [ + [ + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 } + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 } + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 }, + macKey: true + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 }, + macKey: true + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 }, + macKey: null + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 }, + macKey: null + }, + }, + { outbound: { + onWrite: () => {}, + cipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + cipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 }, + macKey: Buffer.alloc(1) + }, + inbound: { + onPayload: () => {}, + decipherInfo: { keyLen: 1, ivLen: 0, sslName: 'foo' }, + decipherKey: Buffer.alloc(1), + seqno: 0, + macInfo: { keyLen: 16 }, + macKey: Buffer.alloc(1) + }, + }, + ], + [/invalid outbound\.macKey/i, /invalid inbound\.macKey/i] + ], + ].forEach((testCase) => { + let errorChecks = testCase[1]; + if (!Array.isArray(errorChecks)) + errorChecks = [errorChecks[0], errorChecks[0]]; + for (const input of testCase[0]) { + assert.throws(() => createCipher(input), errorChecks[0]); + assert.throws(() => createDecipher(input), errorChecks[1]); + } + }); + } +})(); diff --git a/reverse_engineering/node_modules/ssh2/test/test-protocol-keyparser.js b/reverse_engineering/node_modules/ssh2/test/test-protocol-keyparser.js new file mode 100644 index 0000000..850d405 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-protocol-keyparser.js @@ -0,0 +1,145 @@ +'use strict'; + +const assert = require('assert'); +const { readdirSync, readFileSync } = require('fs'); +const { inspect } = require('util'); + +const { parseKey } = require('../lib/protocol/keyParser.js'); + +const { EDDSA_SUPPORTED } = require('../lib/protocol/constants.js'); + +const BASE_PATH = `${__dirname}/fixtures/keyParser`; + +function failMsg(name, message, exit) { + const msg = `[${name}] ${message}`; + if (!exit) + return msg; + console.error(msg); + process.exit(1); +} + +readdirSync(BASE_PATH).forEach((name) => { + if (/\.result$/i.test(name)) + return; + if (/ed25519/i.test(name) && !EDDSA_SUPPORTED) + return; + + const isPublic = /\.pub$/i.test(name); + const isEncrypted = /_enc/i.test(name); + const isPPK = /^ppk_/i.test(name); + const key = readFileSync(`${BASE_PATH}/${name}`); + let res; + if (isEncrypted) + res = parseKey(key, (isPPK ? 'node.js' : 'password')); + else + res = parseKey(key); + let expected = JSON.parse( + readFileSync(`${BASE_PATH}/${name}.result`, 'utf8') + ); + if (typeof expected === 'string') { + if (!(res instanceof Error)) + failMsg(name, `Expected error: ${expected}`, true); + assert.strictEqual( + expected, + res.message, + failMsg(name, + 'Error message mismatch.\n' + + `Expected: ${inspect(expected)}\n` + + `Received: ${inspect(res.message)}`) + ); + } else if (res instanceof Error) { + failMsg(name, `Unexpected error: ${res.stack}`, true); + } else { + if (Array.isArray(expected) && !Array.isArray(res)) + failMsg(name, 'Expected array but did not receive one', true); + if (!Array.isArray(expected) && Array.isArray(res)) + failMsg(name, 'Received array but did not expect one', true); + + if (!Array.isArray(res)) { + res = [res]; + expected = [expected]; + } else if (res.length !== expected.length) { + failMsg(name, + `Expected ${expected.length} keys, but received ${res.length}`, + true); + } + + res.forEach((curKey, i) => { + const details = { + type: curKey.type, + comment: curKey.comment, + public: curKey.getPublicPEM(), + publicSSH: curKey.getPublicSSH() + && curKey.getPublicSSH().toString('base64'), + private: curKey.getPrivatePEM() + }; + assert.deepStrictEqual( + details, + expected[i], + failMsg(name, + 'Parser output mismatch.\n' + + `Expected: ${inspect(expected[i])}\n\n` + + `Received: ${inspect(details)}`) + ); + }); + } + + if (isEncrypted && !isPublic) { + // Make sure parsing encrypted keys without a passhprase or incorrect + // passphrase results in an appropriate error + const err = parseKey(key); + if (!(err instanceof Error)) + failMsg(name, 'Expected error during parse without passphrase', true); + if (!/no passphrase/i.test(err.message)) { + failMsg(name, + `Error during parse without passphrase: ${err.message}`, + true); + } + } + + if (!isPublic) { + // Try signing and verifying to make sure the private/public key PEMs are + // correct + const data = Buffer.from('hello world'); + res.forEach((curKey) => { + let result = curKey.sign(data); + if (result instanceof Error) { + failMsg(name, + `Error while signing data with key: ${result.message}`, + true); + } + result = curKey.verify(data, result); + if (result instanceof Error) { + failMsg(name, + `Error while verifying signed data with key: ${result.message}`, + true); + } + if (!result) + failMsg(name, 'Failed to verify signed data with key', true); + }); + if (res.length === 1 && !isPPK) { + const pubFile = readFileSync(`${BASE_PATH}/${name}.pub`); + const pubParsed = parseKey(pubFile); + if (!(pubParsed instanceof Error)) { + let result = res[0].sign(data); + if (result instanceof Error) { + failMsg(name, + `Error while signing data with key: ${result.message}`, + true); + } + result = pubParsed.verify(data, result); + if (result instanceof Error) { + failMsg(name, + 'Error while verifying signed data with separate public key: ' + + result.message, + true); + } + if (!result) { + failMsg(name, + 'Failed to verify signed data with separate public key', + true); + } + } + } + } +}); diff --git a/reverse_engineering/node_modules/ssh2/test/test-server-hostkeys.js b/reverse_engineering/node_modules/ssh2/test/test-server-hostkeys.js new file mode 100644 index 0000000..3093864 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-server-hostkeys.js @@ -0,0 +1,136 @@ +'use strict'; + +const assert = require('assert'); + +const { + fixtureKey, + mustCall, + setup, +} = require('./common.js'); + +const debug = false; + +[ + { desc: 'RSA user key (old OpenSSH)', + hostKey: fixtureKey('id_rsa') }, + { desc: 'RSA user key (new OpenSSH)', + hostKey: fixtureKey('openssh_new_rsa') }, + { desc: 'DSA host key', + hostKey: fixtureKey('ssh_host_dsa_key') }, + { desc: 'ECDSA host key', + hostKey: fixtureKey('ssh_host_ecdsa_key') }, + { desc: 'PPK', + hostKey: fixtureKey('id_rsa.ppk') }, +].forEach((test) => { + const { desc, hostKey } = test; + const clientKey = fixtureKey('openssh_new_rsa'); + const username = 'KeyUser'; + const { server } = setup( + desc, + { + client: { + username, + privateKey: clientKey.raw, + algorithms: { + serverHostKey: [ hostKey.key.type ], + } + }, + server: { hostKeys: [ hostKey.raw ] }, + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 3: + assert(ctx.signature, 'Missing publickey signature'); + // FALLTHROUGH + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + } + ctx.accept(); + }, 3)).on('ready', mustCall(() => { + conn.end(); + })); + })); +}); + + +{ + const RSA_KEY = fixtureKey('ssh_host_rsa_key'); + const ECDSA_KEY = fixtureKey('ssh_host_ecdsa_key'); + [ RSA_KEY, ECDSA_KEY ].forEach((key) => { + const selKeyType = key.key.type; + const clientKey = fixtureKey('openssh_new_rsa'); + const username = 'KeyUser'; + const { client, server } = setup( + `Multiple host key types (${key.type} selected)`, + { + client: { + username, + privateKey: clientKey.raw, + algorithms: { + serverHostKey: [ selKeyType ], + } + }, + server: { hostKeys: [ RSA_KEY.raw, ECDSA_KEY.raw ] }, + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 3: + assert(ctx.signature, 'Missing publickey signature'); + // FALLTHROUGH + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + } + ctx.accept(); + }, 3)).on('ready', mustCall(() => { + conn.end(); + })); + })); + client.on('handshake', mustCall((info) => { + assert(info.serverHostKey === selKeyType, 'Wrong host key selected'); + })); + }); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-sftp.js b/reverse_engineering/node_modules/ssh2/test/test-sftp.js new file mode 100644 index 0000000..50e56f5 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-sftp.js @@ -0,0 +1,782 @@ +'use strict'; + +const assert = require('assert'); +const { constants } = require('fs'); + +const { + fixture, + mustCall, + mustCallAtLeast, + mustNotCall, + setup: setup_, + setupSimple +} = require('./common.js'); + +const { OPEN_MODE, Stats, STATUS_CODE } = require('../lib/protocol/SFTP.js'); + +const DEBUG = false; + +setup('open', mustCall((client, server) => { + const path_ = '/tmp/foo.txt'; + const handle_ = Buffer.from('node.js'); + const pflags_ = (OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE); + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert(pflags === pflags_, `Wrong flags: ${flagsToHuman(pflags)}`); + server.handle(id, handle_); + server.end(); + })); + client.open(path_, 'w', mustCall((err, handle) => { + assert(!err, `Unexpected open() error: ${err}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + })); +})); + +setup('close', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + server.on('CLOSE', mustCall((id, handle) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.close(handle_, mustCall((err) => { + assert(!err, `Unexpected close() error: ${err}`); + })); +})); + +setup('read', mustCall((client, server) => { + const expected = Buffer.from('node.jsnode.jsnode.jsnode.jsnode.jsnode.js'); + const handle_ = Buffer.from('node.js'); + const buf = Buffer.alloc(expected.length); + server.on('READ', mustCall((id, handle, offset, len) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert(offset === 5, `Wrong read offset: ${offset}`); + assert(len === buf.length, `Wrong read len: ${len}`); + server.data(id, expected); + server.end(); + })); + client.read(handle_, buf, 0, buf.length, 5, mustCall((err, nb) => { + assert(!err, `Unexpected read() error: ${err}`); + assert.deepStrictEqual(buf, expected, 'read data mismatch'); + })); +})); + +setup('read (overflow)', mustCall((client, server) => { + const maxChunk = client._maxReadLen; + const expected = Buffer.alloc(3 * maxChunk, 'Q'); + const handle_ = Buffer.from('node.js'); + const buf = Buffer.alloc(expected.length, 0); + let reqs = 0; + server.on('READ', mustCall((id, handle, offset, len) => { + ++reqs; + assert.strictEqual(id, reqs - 1, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert.strictEqual(offset, + (reqs - 1) * maxChunk, + `Wrong read offset: ${offset}`); + server.data(id, expected.slice(offset, offset + len)); + if (reqs === 3) + server.end(); + }, 3)); + client.read(handle_, buf, 0, buf.length, 0, mustCall((err, nb) => { + assert(!err, `Unexpected read() error: ${err}`); + assert.deepStrictEqual(buf, expected); + assert.strictEqual(nb, buf.length, 'read nb mismatch'); + })); +})); + +setup('write', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + const buf = Buffer.from('node.jsnode.jsnode.jsnode.jsnode.jsnode.js'); + server.on('WRITE', mustCall((id, handle, offset, data) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert(offset === 5, `Wrong write offset: ${offset}`); + assert.deepStrictEqual(data, buf, 'write data mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.write(handle_, buf, 0, buf.length, 5, mustCall((err, nb) => { + assert(!err, `Unexpected write() error: ${err}`); + assert.strictEqual(nb, buf.length, 'wrong bytes written'); + })); +})); + +setup('write (overflow)', mustCall((client, server) => { + const maxChunk = client._maxWriteLen; + const handle_ = Buffer.from('node.js'); + const buf = Buffer.allocUnsafe(3 * maxChunk); + let reqs = 0; + server.on('WRITE', mustCall((id, handle, offset, data) => { + ++reqs; + assert.strictEqual(id, reqs - 1, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert.strictEqual(offset, + (reqs - 1) * maxChunk, + `Wrong write offset: ${offset}`); + assert((offset + data.length) <= buf.length, 'bad offset'); + assert.deepStrictEqual(data, + buf.slice(offset, offset + data.length), + 'write data mismatch'); + server.status(id, STATUS_CODE.OK); + if (reqs === 3) + server.end(); + }, 3)); + client.write(handle_, buf, 0, buf.length, 0, mustCall((err, nb) => { + assert(!err, `Unexpected write() error: ${err}`); + assert.strictEqual(nb, buf.length, 'wrote bytes written'); + })); +})); + +setup('lstat', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const attrs_ = new Stats({ + size: 10 * 1024, + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.on('LSTAT', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.attrs(id, attrs_); + server.end(); + })); + client.lstat(path_, mustCall((err, attrs) => { + assert(!err, `Unexpected lstat() error: ${err}`); + assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch'); + })); +})); + +setup('fstat', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + const attrs_ = new Stats({ + size: 10 * 1024, + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.on('FSTAT', mustCall((id, handle) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.attrs(id, attrs_); + server.end(); + })); + client.fstat(handle_, mustCall((err, attrs) => { + assert(!err, `Unexpected fstat() error: ${err}`); + assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch'); + })); +})); + +setup('setstat', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const attrs_ = new Stats({ + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.on('SETSTAT', mustCall((id, path, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.setstat(path_, attrs_, mustCall((err) => { + assert(!err, `Unexpected setstat() error: ${err}`); + })); +})); + +setup('fsetstat', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + const attrs_ = new Stats({ + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.on('FSETSTAT', mustCall((id, handle, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.fsetstat(handle_, attrs_, mustCall((err) => { + assert(!err, `Unexpected fsetstat() error: ${err}`); + })); +})); + +setup('opendir', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + const path_ = '/tmp'; + server.on('OPENDIR', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.handle(id, handle_); + server.end(); + })); + client.opendir(path_, mustCall((err, handle) => { + assert(!err, `Unexpected opendir() error: ${err}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + })); +})); + +setup('readdir', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + const list_ = [ + { filename: '.', + longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .', + attrs: new Stats({ + mode: 0o755 | constants.S_IFDIR, + size: 4096, + uid: 9001, + gid: 8001, + atime: 1415599549, + mtime: 1415599590 + }) + }, + { filename: '..', + longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..', + attrs: new Stats({ + mode: 0o755 | constants.S_IFDIR, + size: 4096, + uid: 0, + gid: 0, + atime: 1368729954, + mtime: 1368729999 + }) + }, + { filename: 'foo', + longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo', + attrs: new Stats({ + mode: 0o777 | constants.S_IFDIR, + size: 4096, + uid: 9001, + gid: 8001, + atime: 1368729954, + mtime: 1368729999 + }) + }, + { filename: 'bar', + longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar', + attrs: new Stats({ + mode: 0o644 | constants.S_IFREG, + size: 513901992, + uid: 9001, + gid: 8001, + atime: 1259972199, + mtime: 1259972199 + }) + } + ]; + server.on('READDIR', mustCall((id, handle) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.name(id, list_); + server.end(); + })); + client.readdir(handle_, mustCall((err, list) => { + assert(!err, `Unexpected readdir() error: ${err}`); + assert.deepStrictEqual(list, + list_.slice(2), + 'dir list mismatch'); + })); +})); + +setup('readdir (full)', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + const list_ = [ + { filename: '.', + longname: 'drwxr-xr-x 56 nodejs nodejs 4096 Nov 10 01:05 .', + attrs: new Stats({ + mode: 0o755 | constants.S_IFDIR, + size: 4096, + uid: 9001, + gid: 8001, + atime: 1415599549, + mtime: 1415599590 + }) + }, + { filename: '..', + longname: 'drwxr-xr-x 4 root root 4096 May 16 2013 ..', + attrs: new Stats({ + mode: 0o755 | constants.S_IFDIR, + size: 4096, + uid: 0, + gid: 0, + atime: 1368729954, + mtime: 1368729999 + }) + }, + { filename: 'foo', + longname: 'drwxrwxrwx 2 nodejs nodejs 4096 Mar 8 2009 foo', + attrs: new Stats({ + mode: 0o777 | constants.S_IFDIR, + size: 4096, + uid: 9001, + gid: 8001, + atime: 1368729954, + mtime: 1368729999 + }) + }, + { filename: 'bar', + longname: '-rw-r--r-- 1 nodejs nodejs 513901992 Dec 4 2009 bar', + attrs: new Stats({ + mode: 0o644 | constants.S_IFREG, + size: 513901992, + uid: 9001, + gid: 8001, + atime: 1259972199, + mtime: 1259972199 + }) + } + ]; + server.on('READDIR', mustCall((id, handle) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.name(id, list_); + server.end(); + })); + client.readdir(handle_, { full: true }, mustCall((err, list) => { + assert(!err, `Unexpected readdir() error: ${err}`); + assert.deepStrictEqual(list, list_, 'dir list mismatch'); + })); +})); + +setup('readdir (EOF)', mustCall((client, server) => { + const handle_ = Buffer.from('node.js'); + server.on('READDIR', mustCall((id, handle) => { + assert(id === 0, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.status(id, STATUS_CODE.EOF); + server.end(); + })); + client.readdir(handle_, mustCall((err, list) => { + assert(err && err.code === STATUS_CODE.EOF, + `Expected EOF, got: ${err}`); + })); +})); + +setup('unlink', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + server.on('REMOVE', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.unlink(path_, mustCall((err) => { + assert(!err, `Unexpected unlink() error: ${err}`); + })); +})); + +setup('mkdir', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + server.on('MKDIR', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.mkdir(path_, mustCall((err) => { + assert(!err, `Unexpected mkdir() error: ${err}`); + })); +})); + +setup('rmdir', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + server.on('RMDIR', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.rmdir(path_, mustCall((err) => { + assert(!err, `Unexpected rmdir() error: ${err}`); + })); +})); + +setup('realpath', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const name_ = { filename: '/tmp/foo' }; + server.on('REALPATH', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.name(id, name_); + server.end(); + })); + client.realpath(path_, mustCall((err, name) => { + assert(!err, `Unexpected realpath() error: ${err}`); + assert.deepStrictEqual(name, name_.filename, 'name mismatch'); + })); +})); + +setup('stat', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const attrs_ = new Stats({ + mode: 0o644 | constants.S_IFREG, + size: 10 * 1024, + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.on('STAT', mustCall((id, path) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + server.attrs(id, attrs_); + server.end(); + })); + client.stat(path_, mustCall((err, attrs) => { + assert(!err, `Unexpected stat() error: ${err}`); + assert.deepStrictEqual(attrs, attrs_, 'attrs mismatch'); + const expectedTypes = { + isDirectory: false, + isFile: true, + isBlockDevice: false, + isCharacterDevice: false, + isSymbolicLink: false, + isFIFO: false, + isSocket: false + }; + for (const [fn, expect] of Object.entries(expectedTypes)) + assert(attrs[fn]() === expect, `attrs.${fn}() failed`); + })); +})); + +setup('rename', mustCall((client, server) => { + const oldPath_ = '/foo/bar/baz'; + const newPath_ = '/tmp/foo'; + server.on('RENAME', mustCall((id, oldPath, newPath) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(oldPath === oldPath_, `Wrong old path: ${oldPath}`); + assert(newPath === newPath_, `Wrong new path: ${newPath}`); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.rename(oldPath_, newPath_, mustCall((err) => { + assert(!err, `Unexpected rename() error: ${err}`); + })); +})); + +setup('readlink', mustCall((client, server) => { + const linkPath_ = '/foo/bar/baz'; + const name = { filename: '/tmp/foo' }; + server.on('READLINK', mustCall((id, linkPath) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(linkPath === linkPath_, `Wrong link path: ${linkPath}`); + server.name(id, name); + server.end(); + })); + client.readlink(linkPath_, mustCall((err, targetPath) => { + assert(!err, `Unexpected readlink() error: ${err}`); + assert(targetPath === name.filename, + `Wrong target path: ${targetPath}`); + })); +})); + +setup('symlink', mustCall((client, server) => { + const linkPath_ = '/foo/bar/baz'; + const targetPath_ = '/tmp/foo'; + server.on('SYMLINK', mustCall((id, linkPath, targetPath) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(linkPath === linkPath_, `Wrong link path: ${linkPath}`); + assert(targetPath === targetPath_, `Wrong target path: ${targetPath}`); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.symlink(targetPath_, linkPath_, mustCall((err) => { + assert(!err, `Unexpected symlink() error: ${err}`); + })); +})); + +setup('readFile', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const handle_ = Buffer.from('hi mom!'); + const data_ = Buffer.from('hello world'); + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`); + server.handle(id, handle_); + })).on('FSTAT', mustCall((id, handle) => { + assert(id === 1, `Wrong request id: ${id}`); + const attrs = new Stats({ + size: data_.length, + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.attrs(id, attrs); + })).on('READ', mustCall((id, handle, offset, len) => { + assert(id === 2, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert(offset === 0, `Wrong read offset: ${offset}`); + server.data(id, data_); + })).on('CLOSE', mustCall((id, handle) => { + assert(id === 3, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.readFile(path_, mustCall((err, buf) => { + assert(!err, `Unexpected error: ${err}`); + assert.deepStrictEqual(buf, data_, 'data mismatch'); + })); +})); + +setup('readFile (no size from fstat)', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const handle_ = Buffer.from('hi mom!'); + const data_ = Buffer.from('hello world'); + let reads = 0; + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`); + server.handle(id, handle_); + })).on('FSTAT', mustCall((id, handle) => { + assert(id === 1, `Wrong request id: ${id}`); + const attrs = new Stats({ + uid: 9001, + gid: 9001, + atime: (Date.now() / 1000) | 0, + mtime: (Date.now() / 1000) | 0 + }); + server.attrs(id, attrs); + })).on('READ', mustCall((id, handle, offset, len) => { + assert(++reads + 1 === id, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + switch (id) { + case 2: + assert(offset === 0, `Wrong read offset for first read: ${offset}`); + server.data(id, data_); + break; + case 3: + assert(offset === data_.length, + `Wrong read offset for second read: ${offset}`); + server.status(id, STATUS_CODE.EOF); + break; + } + }, 2)).on('CLOSE', mustCall((id, handle) => { + assert(id === 4, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + client.readFile(path_, mustCall((err, buf) => { + assert(!err, `Unexpected error: ${err}`); + assert.deepStrictEqual(buf, data_, 'data mismatch'); + })); +})); + +setup('ReadStream', mustCall((client, server) => { + let reads = 0; + const path_ = '/foo/bar/baz'; + const handle_ = Buffer.from('hi mom!'); + const data_ = Buffer.from('hello world'); + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`); + server.handle(id, handle_); + })).on('READ', mustCall((id, handle, offset, len) => { + assert(id === ++reads, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + if (reads === 1) { + assert(offset === 0, `Wrong read offset: ${offset}`); + server.data(id, data_); + } else { + server.status(id, STATUS_CODE.EOF); + } + }, 2)).on('CLOSE', mustCall((id, handle) => { + assert(id === 3, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + let buf = []; + client.createReadStream(path_).on('readable', mustCallAtLeast(function() { + let chunk; + while ((chunk = this.read()) !== null) + buf.push(chunk); + })).on('end', mustCall(() => { + buf = Buffer.concat(buf); + assert.deepStrictEqual(buf, data_, 'data mismatch'); + })); +})); + +setup('ReadStream (fewer bytes than requested)', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + const handle_ = Buffer.from('hi mom!'); + const data_ = Buffer.from('hello world'); + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + server.handle(id, handle_); + })).on('READ', mustCallAtLeast((id, handle, offset, len) => { + if (offset > data_.length) { + server.status(id, STATUS_CODE.EOF); + } else { + // Only read 4 bytes at a time + server.data(id, data_.slice(offset, offset + 4)); + } + })).on('CLOSE', mustCall((id, handle) => { + server.status(id, STATUS_CODE.OK); + server.end(); + })); + let buf = []; + client.createReadStream(path_).on('readable', mustCallAtLeast(function() { + let chunk; + while ((chunk = this.read()) !== null) + buf.push(chunk); + })).on('end', mustCall(() => { + buf = Buffer.concat(buf); + assert.deepStrictEqual(buf, data_, 'data mismatch'); + })); +})); + +setup('ReadStream (error)', mustCall((client, server) => { + const path_ = '/foo/bar/baz'; + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert(pflags === OPEN_MODE.READ, `Wrong flags: ${flagsToHuman(pflags)}`); + server.status(id, STATUS_CODE.NO_SUCH_FILE); + server.end(); + })); + client.createReadStream(path_).on('error', mustCall((err) => { + assert(err.code === STATUS_CODE.NO_SUCH_FILE); + })); +})); + +setup('WriteStream', mustCall((client, server) => { + let writes = 0; + const path_ = '/foo/bar/baz'; + const handle_ = Buffer.from('hi mom!'); + const data_ = Buffer.from('hello world'); + const pflags_ = OPEN_MODE.TRUNC | OPEN_MODE.CREAT | OPEN_MODE.WRITE; + server.on('OPEN', mustCall((id, path, pflags, attrs) => { + assert(id === 0, `Wrong request id: ${id}`); + assert(path === path_, `Wrong path: ${path}`); + assert(pflags === pflags_, `Wrong flags: ${flagsToHuman(pflags)}`); + server.handle(id, handle_); + })).on('FSETSTAT', mustCall((id, handle, attrs) => { + assert(id === 1, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert.strictEqual(attrs.mode, 0o666, 'Wrong file mode'); + server.status(id, STATUS_CODE.OK); + })).on('WRITE', mustCall((id, handle, offset, data) => { + assert(id === ++writes + 1, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + assert(offset === ((writes - 1) * data_.length), + `Wrong write offset: ${offset}`); + assert.deepStrictEqual(data, data_, 'Wrong data'); + server.status(id, STATUS_CODE.OK); + }, 3)).on('CLOSE', mustCall((id, handle) => { + assert(id === 5, `Wrong request id: ${id}`); + assert.deepStrictEqual(handle, handle_, 'handle mismatch'); + server.status(id, STATUS_CODE.OK); + server.end(); + })); + + const writer = client.createWriteStream(path_); + writer.cork && writer.cork(); + writer.write(data_); + writer.write(data_); + writer.write(data_); + writer.uncork && writer.uncork(); + writer.end(); +})); + +{ + const { client, server } = setup_( + 'SFTP server aborts with exit-status', + { + client: { username: 'foo', password: 'bar' }, + server: { hostKeys: [ fixture('ssh_host_rsa_key') ] }, + }, + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + ctx.accept(); + })).on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('sftp', mustCall((accept, reject) => { + const sftp = accept(); + + // XXX: hack + sftp._protocol.exitStatus(sftp.outgoing.id, 127); + sftp._protocol.channelClose(sftp.outgoing.id); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + const timeout = setTimeout(mustNotCall(), 1000); + client.sftp(mustCall((err, sftp) => { + clearTimeout(timeout); + assert(err, 'Expected error'); + assert(err.code === 127, `Expected exit code 127, saw: ${err.code}`); + client.end(); + })); + })); +} + + +// ============================================================================= +function setup(title, cb) { + const { client, server } = setupSimple(DEBUG, title); + let clientSFTP; + let serverSFTP; + + const onSFTP = mustCall(() => { + if (clientSFTP && serverSFTP) + cb(clientSFTP, serverSFTP); + }, 2); + + client.on('ready', mustCall(() => { + client.sftp(mustCall((err, sftp) => { + assert(!err, `[${title}] Unexpected client sftp start error: ${err}`); + sftp.on('close', mustCall(() => { + client.end(); + })); + clientSFTP = sftp; + onSFTP(); + })); + })); + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + accept().on('sftp', mustCall((accept, reject) => { + const sftp = accept(); + sftp.on('close', mustCall(() => { + conn.end(); + })); + serverSFTP = sftp; + onSFTP(); + })); + })); + })); + })); +} + +function flagsToHuman(flags) { + const ret = []; + + for (const [name, value] of Object.entries(OPEN_MODE)) { + if (flags & value) + ret.push(name); + } + + return ret.join(' | '); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-shell.js b/reverse_engineering/node_modules/ssh2/test/test-shell.js new file mode 100644 index 0000000..debba11 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-shell.js @@ -0,0 +1,109 @@ +'use strict'; + +const assert = require('assert'); +const { inspect } = require('util'); + +const { + mustCall, + mustCallAtLeast, + setupSimple, +} = require('./common.js'); + +const DEBUG = false; + +const setup = setupSimple.bind(undefined, DEBUG); + +{ + const { client, server } = setup('Simple shell()'); + + const OUTPUT = 'shell output!\n'; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + const session = accept(); + session.on('pty', mustCall((accept, reject, info) => { + accept(); + session.on('shell', mustCall((accept, reject) => { + let input = ''; + const stream = accept(); + stream.write(OUTPUT); + stream.on('data', mustCallAtLeast((data) => { + input += data; + if (input === 'exit\n') { + stream.end(); + conn.end(); + } + })); + })); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let output = ''; + client.on('close', mustCall(() => { + assert(output === OUTPUT, `Wrong shell output: ${inspect(output)}`); + })).shell(mustCall((err, stream) => { + assert(!err, `Unexpected shell error: ${err}`); + stream.write('exit\n'); + stream.on('data', mustCallAtLeast((d) => { + output += d; + })).on('close', mustCall(() => {})); + })); + })); +} + +{ + const { client, server } = setup('Shell with environment set'); + + const OUTPUT = 'shell output!\n'; + const clientEnv = { SSH2NODETEST: 'foo' }; + + server.on('connection', mustCall((conn) => { + conn.on('ready', mustCall(() => { + conn.on('session', mustCall((accept, reject) => { + let pty = false; + let env = false; + accept().on('pty', mustCall((accept, reject, info) => { + accept(); + pty = true; + })).on('env', mustCall((accept, reject, info) => { + accept && accept(); + env = true; + assert(info.key === Object.keys(clientEnv)[0], + `Wrong env key: ${inspect(info.key)}`); + assert(info.val === Object.values(clientEnv)[0], + `Wrong env value: ${inspect(info.val)}`); + })).on('shell', mustCall((accept, reject) => { + assert(pty, 'Expected pty before shell'); + assert(env, 'Expected env before shell'); + let input = ''; + const stream = accept(); + stream.write(OUTPUT); + stream.on('data', mustCallAtLeast((data) => { + input += data; + if (input === 'exit\n') { + stream.end(); + conn.end(); + } + })); + })); + })); + })); + })); + + client.on('ready', mustCall(() => { + let output = ''; + client.on('close', mustCall(() => { + assert(output === OUTPUT, `Wrong shell output: ${inspect(output)}`); + })).shell({ env: clientEnv }, mustCall((err, stream) => { + assert(!err, `Unexpected shell error: ${err}`); + stream.write('exit\n'); + stream.on('data', mustCallAtLeast((d) => { + output += d; + })).on('close', mustCall(() => {})); + })); + })); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-userauth-agent-openssh.js b/reverse_engineering/node_modules/ssh2/test/test-userauth-agent-openssh.js new file mode 100644 index 0000000..55d1a25 --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-userauth-agent-openssh.js @@ -0,0 +1,109 @@ +'use strict'; + +const assert = require('assert'); +const { spawnSync } = require('child_process'); + +const debug = false; +const SPAWN_OPTS = { windowsHide: true }; + +// TODO: figure out why this test is failing on Windows +if (process.platform === 'win32') { + console.log('Skipping ssh-agent test on Windows'); + process.exit(0); +} + +if (process.argv[2] === 'child') { + const { + fixtureKey, + mustCall, + setup, + } = require('./common.js'); + + const serverCfg = { hostKeys: [ fixtureKey('ssh_host_rsa_key').raw ] }; + + const clientKey = fixtureKey('openssh_new_rsa'); + + // Add key to the agent first + { + const { + error, status + } = spawnSync('ssh-add', [ clientKey.fullPath ], SPAWN_OPTS); + if (error || status !== 0) { + console.error('Failed to add key to agent'); + process.exit(1); + } + } + + const username = 'Agent User'; + const { server } = setup( + 'Agent authentication', + { + client: { username, agent: process.env.SSH_AUTH_SOCK }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 3: + assert(ctx.signature, 'Missing publickey signature'); + // FALLTHROUGH + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + } + ctx.accept(); + }, 3)).on('ready', mustCall(() => { + conn.end(); + })); + })); +} else { + { + const { + error, status + } = spawnSync('which', ['ssh-agent'], SPAWN_OPTS); + + if (error || status !== 0) { + console.log('No ssh-agent available, skipping agent test ...'); + process.exit(0); + } + } + + { + const { + error, status + } = spawnSync('which', ['ssh-add'], SPAWN_OPTS); + + if (error || status !== 0) { + console.log('No ssh-add available, skipping agent test ...'); + process.exit(0); + } + } + + const { + error, status + } = spawnSync('ssh-agent', + [ process.execPath, __filename, 'child' ], + { ...SPAWN_OPTS, stdio: 'inherit' }); + if (error || status !== 0) + throw new Error('Agent test failed'); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-userauth-agent.js b/reverse_engineering/node_modules/ssh2/test/test-userauth-agent.js new file mode 100644 index 0000000..a28ad0b --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-userauth-agent.js @@ -0,0 +1,170 @@ +'use strict'; + +const assert = require('assert'); + +const debug = false; + +const { + fixtureKey, + mustCall, + setup, +} = require('./common.js'); +const { + AgentProtocol, + BaseAgent, + utils: { parseKey }, +} = require('../lib/index.js'); + +const serverCfg = { hostKeys: [ fixtureKey('ssh_host_rsa_key').raw ] }; + +const clientKey = fixtureKey('openssh_new_rsa'); + +{ + let getIdentitiesCount = 0; + let signCount = 0; + class MyAgent extends BaseAgent { + getIdentities(cb) { + assert.strictEqual(++getIdentitiesCount, 1); + // Ensure that no private portion of the key is used by re-parsing the + // public version of the key + cb(null, [ parseKey(clientKey.key.getPublicSSH()) ]); + } + sign(pubKey, data, options, cb) { + assert.strictEqual(++signCount, 1); + assert.strictEqual(pubKey.getPublicPEM(), clientKey.key.getPublicPEM()); + const sig = clientKey.key.sign(data, options.hash); + cb(null, sig); + } + } + + const username = 'Agent User'; + const { server } = setup( + 'Custom agent authentication', + { + client: { username, agent: new MyAgent() }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 3: + assert(ctx.signature, 'Missing publickey signature'); + // FALLTHROUGH + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + } + ctx.accept(); + }, 3)).on('ready', mustCall(() => { + assert.strictEqual(getIdentitiesCount, 1); + assert.strictEqual(signCount, 1); + conn.end(); + })); + })); +} +{ + const client = new AgentProtocol(true); + const server = new AgentProtocol(false); + + server.on('identities', mustCall((req) => { + setImmediate(() => server.failureReply(req)); + })); + client.getIdentities(mustCall((err, keys) => { + assert(err, 'Missing expected error'); + })); + + client.pipe(server).pipe(client); +} +{ + const client = new AgentProtocol(true); + const server = new AgentProtocol(false); + + server.on('identities', mustCall((req) => { + const keys = [ clientKey.key ]; + server.getIdentitiesReply(req, keys); + })); + client.getIdentities(mustCall((err, keys) => { + assert(!err, 'Unexpected error'); + assert.strictEqual(keys.length, 1); + assert.strictEqual(keys[0].isPrivateKey(), false); + assert.strictEqual(keys[0].getPublicPEM(), clientKey.key.getPublicPEM()); + })); + + client.pipe(server).pipe(client); +} +{ + const client = new AgentProtocol(true); + const server = new AgentProtocol(false); + const buf = Buffer.from('data to sign'); + + server.on('sign', mustCall((req, pubKey, data, options) => { + assert.strictEqual(pubKey.getPublicPEM(), clientKey.key.getPublicPEM()); + assert.deepStrictEqual(data, buf); + assert.strictEqual(options.hash, undefined); + server.failureReply(req); + })); + client.sign(clientKey.key.getPublicSSH(), + buf, + mustCall((err, signature) => { + assert(err, 'Missing expected error'); + })); + + client.pipe(server).pipe(client); +} +{ + const client = new AgentProtocol(true); + const server = new AgentProtocol(false); + const buf = Buffer.from('data to sign'); + + server.on('sign', mustCall((req, pubKey, data, options) => { + assert.strictEqual(pubKey.getPublicPEM(), clientKey.key.getPublicPEM()); + assert.deepStrictEqual(data, buf); + assert.strictEqual(options.hash, undefined); + server.signReply(req, clientKey.key.sign(data)); + })); + client.sign(clientKey.key.getPublicSSH(), + buf, + mustCall((err, signature) => { + assert(!err, 'Unexpected error'); + const pubKey = parseKey(clientKey.key.getPublicSSH()); + assert.strictEqual(pubKey.verify(buf, signature), true); + })); + + client.pipe(server).pipe(client); +} +{ + // Test that outstanding requests are handled upon unexpected closure of the + // protocol stream + + const client = new AgentProtocol(true); + const server = new AgentProtocol(false); + + server.on('identities', mustCall((req) => { + server.destroy(); + })); + client.getIdentities(mustCall((err) => { + assert(err, 'Missing expected error'); + })); + + client.pipe(server).pipe(client); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test-userauth.js b/reverse_engineering/node_modules/ssh2/test/test-userauth.js new file mode 100644 index 0000000..fb2fe9e --- /dev/null +++ b/reverse_engineering/node_modules/ssh2/test/test-userauth.js @@ -0,0 +1,608 @@ +'use strict'; + +const assert = require('assert'); +const { inspect } = require('util'); + +const { + fixtureKey, + mustCall, + mustNotCall, + setup, +} = require('./common.js'); + +const serverCfg = { hostKeys: [ fixtureKey('ssh_host_rsa_key').raw ] }; + +const debug = false; + +// Keys ======================================================================== +[ + { desc: 'RSA (old OpenSSH)', + clientKey: fixtureKey('id_rsa') }, + { desc: 'RSA (new OpenSSH)', + clientKey: fixtureKey('openssh_new_rsa') }, + { desc: 'RSA (encrypted)', + clientKey: fixtureKey('id_rsa_enc', 'foobarbaz'), + passphrase: 'foobarbaz' }, + { desc: 'DSA', + clientKey: fixtureKey('id_dsa') }, + { desc: 'ECDSA', + clientKey: fixtureKey('id_ecdsa') }, + { desc: 'PPK', + clientKey: fixtureKey('id_rsa.ppk') }, +].forEach((test) => { + const { desc, clientKey, passphrase } = test; + const username = 'Key User'; + const { server } = setup( + desc, + { + client: { username, privateKey: clientKey.raw, passphrase }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 3: + assert(ctx.signature, 'Missing publickey signature'); + // FALLTHROUGH + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + break; + } + if (ctx.signature) { + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify publickey signature'); + } + ctx.accept(); + }, 3)).on('ready', mustCall(() => { + conn.end(); + })); + })); +}); + + +// Password ==================================================================== +{ + const username = 'Password User'; + const password = 'hi mom'; + const { server } = setup( + 'Password', + { + client: { username, password }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + if (++authAttempt === 1) { + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + } + assert(ctx.method === 'password', + `Wrong auth method: ${ctx.method}`); + assert(ctx.password === password, + `Wrong password: ${ctx.password}`); + ctx.accept(); + }, 2)).on('ready', mustCall(() => { + conn.end(); + })); + })); +} +{ + const username = ''; + const password = 'hi mom'; + const { server } = setup( + 'Password (empty username)', + { + client: { username, password }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + if (++authAttempt === 1) { + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + } + assert(ctx.method === 'password', + `Wrong auth method: ${ctx.method}`); + assert(ctx.password === password, + `Wrong password: ${ctx.password}`); + ctx.accept(); + }, 2)).on('ready', mustCall(() => { + conn.end(); + })); + })); +} +{ + const username = 'foo'; + const oldPassword = 'bar'; + const newPassword = 'baz'; + const changePrompt = 'Prithee changeth thy password'; + const { client, server } = setup( + 'Password (change requested)', + { + client: { username, password: oldPassword }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + if (++authAttempt === 1) { + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + } + assert(ctx.method === 'password', + `Wrong auth method: ${ctx.method}`); + assert(ctx.password === oldPassword, + `Wrong old password: ${ctx.password}`); + ctx.requestChange(changePrompt, mustCall((newPassword_) => { + assert(newPassword_ === newPassword, + `Wrong new password: ${newPassword_}`); + ctx.accept(); + })); + }, 2)).on('ready', mustCall(() => { + conn.end(); + })); + })); + + client.on('change password', mustCall((prompt, done) => { + assert(prompt === changePrompt, `Wrong password change prompt: ${prompt}`); + process.nextTick(done, newPassword); + })); +} + + +// Hostbased =================================================================== +{ + const localUsername = 'Local User Foo'; + const localHostname = 'Local Host Bar'; + const username = 'Hostbased User'; + const clientKey = fixtureKey('id_rsa'); + const { server } = setup( + 'Hostbased', + { + client: { + username, + privateKey: clientKey.raw, + localUsername, + localHostname, + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + switch (++authAttempt) { + case 1: + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 2: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + case 3: + assert(ctx.method === 'hostbased', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Wrong key algo: ${ctx.key.algo}`); + assert.deepStrictEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + assert(ctx.signature, 'Expected signature'); + assert(ctx.localHostname === localHostname, 'Wrong local hostname'); + assert(ctx.localUsername === localUsername, 'Wrong local username'); + assert(clientKey.key.verify(ctx.blob, ctx.signature) === true, + 'Could not verify hostbased signature'); + + break; + } + ctx.accept(); + }, 3)).on('ready', mustCall(() => { + conn.end(); + })); + })); +} + + +// keyboard-interactive ======================================================== +{ + const username = 'Keyboard-Interactive User'; + const request = { + name: 'SSH2 Authentication', + instructions: 'These are instructions', + prompts: [ + { prompt: 'Password: ', echo: false }, + { prompt: 'Is the cake a lie? ', echo: true }, + ], + }; + const responses = [ + 'foobarbaz', + 'yes', + ]; + const { client, server } = setup( + 'Password (empty username)', + { + client: { + username, + tryKeyboard: true, + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let authAttempt = 0; + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, + `Wrong username: ${ctx.username}`); + if (++authAttempt === 1) { + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + return ctx.reject(); + } + assert(ctx.method === 'keyboard-interactive', + `Wrong auth method: ${ctx.method}`); + ctx.prompt(request.prompts, + request.name, + request.instructions, + mustCall((responses_) => { + assert.deepStrictEqual(responses_, responses); + ctx.accept(); + })); + }, 2)).on('ready', mustCall(() => { + conn.end(); + })); + })); + + client.on('keyboard-interactive', + mustCall((name, instructions, lang, prompts, finish) => { + assert(name === request.name, `Wrong prompt name: ${name}`); + assert(instructions === request.instructions, + `Wrong prompt instructions: ${instructions}`); + assert.deepStrictEqual( + prompts, + request.prompts, + `Wrong prompts: ${inspect(prompts)}` + ); + process.nextTick(finish, responses); + })); +} + +// authHandler() tests ========================================================= +{ + const username = 'foo'; + const password = '1234'; + const clientKey = fixtureKey('id_rsa'); + const { server } = setup( + 'authHandler() (sync)', + { + client: { + username, + password, + privateKey: clientKey.raw, + + authHandler: mustCall((methodsLeft, partial, cb) => { + assert(methodsLeft === null, 'expected null methodsLeft'); + assert(partial === null, 'expected null partial'); + return 'none'; + }), + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, `Wrong username: ${ctx.username}`); + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} +{ + const username = 'foo'; + const password = '1234'; + const clientKey = fixtureKey('id_rsa'); + const { server } = setup( + 'authHandler() (async)', + { + client: { + username, + password, + privateKey: clientKey.raw, + + authHandler: mustCall((methodsLeft, partial, cb) => { + assert(methodsLeft === null, 'expected null methodsLeft'); + assert(partial === null, 'expected null partial'); + process.nextTick(mustCall(cb), 'none'); + }), + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, `Wrong username: ${ctx.username}`); + assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`); + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} +{ + const username = 'foo'; + const password = '1234'; + const clientKey = fixtureKey('id_rsa'); + const { client, server } = setup( + 'authHandler() (no methods left -- sync)', + { + client: { + username, + password, + privateKey: clientKey.raw, + + authHandler: mustCall((methodsLeft, partial, cb) => { + assert(methodsLeft === null, 'expected null methodsLeft'); + assert(partial === null, 'expected null partial'); + return false; + }), + }, + server: serverCfg, + + debug, + noForceClientReady: true, + noForceServerReady: true, + } + ); + + // Remove default client error handler added by `setup()` since we are + // expecting an error in this case + client.removeAllListeners('error'); + + client.on('error', mustCall((err) => { + assert.strictEqual(err.level, 'client-authentication'); + assert(/configured authentication methods failed/i.test(err.message), + 'Wrong error message'); + })); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustNotCall()) + .on('ready', mustNotCall()); + })); +} +{ + const username = 'foo'; + const password = '1234'; + const clientKey = fixtureKey('id_rsa'); + const { client, server } = setup( + 'authHandler() (no methods left -- async)', + { + client: { + username, + password, + privateKey: clientKey.raw, + + authHandler: mustCall((methodsLeft, partial, cb) => { + assert(methodsLeft === null, 'expected null methodsLeft'); + assert(partial === null, 'expected null partial'); + process.nextTick(mustCall(cb), false); + }), + }, + server: serverCfg, + + debug, + noForceClientReady: true, + noForceServerReady: true, + } + ); + + // Remove default client error handler added by `setup()` since we are + // expecting an error in this case + client.removeAllListeners('error'); + + client.on('error', mustCall((err) => { + assert.strictEqual(err.level, 'client-authentication'); + assert(/configured authentication methods failed/i.test(err.message), + 'Wrong error message'); + })); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustNotCall()) + .on('ready', mustNotCall()); + })); +} +{ + const username = 'foo'; + const password = '1234'; + const clientKey = fixtureKey('id_rsa'); + const events = []; + const expectedEvents = [ + 'client', 'server', 'client', 'server' + ]; + let clientCalls = 0; + const { client, server } = setup( + 'authHandler() (multi-step)', + { + client: { + username, + password, + privateKey: clientKey.raw, + + authHandler: mustCall((methodsLeft, partial, cb) => { + events.push('client'); + switch (++clientCalls) { + case 1: + assert(methodsLeft === null, 'expected null methodsLeft'); + assert(partial === null, 'expected null partial'); + return 'publickey'; + case 2: + assert.deepStrictEqual( + methodsLeft, + ['password'], + `expected 'password' method left, saw: ${methodsLeft}` + ); + assert(partial === true, 'expected partial success'); + return 'password'; + } + }, 2), + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + let attempts = 0; + conn.on('authentication', mustCall((ctx) => { + assert(++attempts === clientCalls, 'server<->client state mismatch'); + assert(ctx.username === username, + `Unexpected username: ${ctx.username}`); + events.push('server'); + switch (attempts) { + case 1: + assert(ctx.method === 'publickey', + `Wrong auth method: ${ctx.method}`); + assert(ctx.key.algo === clientKey.key.type, + `Unexpected key algo: ${ctx.key.algo}`); + assert.deepEqual(clientKey.key.getPublicSSH(), + ctx.key.data, + 'Public key mismatch'); + ctx.reject(['password'], true); + break; + case 2: + assert(ctx.method === 'password', + `Wrong auth method: ${ctx.method}`); + assert(ctx.password === password, + `Unexpected password: ${ctx.password}`); + ctx.accept(); + break; + } + }, 2)).on('ready', mustCall(() => { + conn.end(); + })); + })); + + client.on('close', mustCall(() => { + assert.deepStrictEqual(events, expectedEvents); + })); +} +{ + const username = 'foo'; + const password = '1234'; + const { server } = setup( + 'authHandler() (custom auth configuration)', + { + client: { + username: 'bar', + password: '5678', + + authHandler: mustCall((methodsLeft, partial, cb) => { + assert(methodsLeft === null, 'expected null methodsLeft'); + assert(partial === null, 'expected null partial'); + return { + type: 'password', + username, + password, + }; + }), + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, `Wrong username: ${ctx.username}`); + assert(ctx.method === 'password', `Wrong auth method: ${ctx.method}`); + assert(ctx.password === password, `Unexpected password: ${ctx.password}`); + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} +{ + const username = 'foo'; + const password = '1234'; + const { server } = setup( + 'authHandler() (simple construction with custom auth configuration)', + { + client: { + username: 'bar', + password: '5678', + + authHandler: [{ + type: 'password', + username, + password, + }], + }, + server: serverCfg, + + debug, + } + ); + + server.on('connection', mustCall((conn) => { + conn.on('authentication', mustCall((ctx) => { + assert(ctx.username === username, `Wrong username: ${ctx.username}`); + assert(ctx.method === 'password', `Wrong auth method: ${ctx.method}`); + assert(ctx.password === password, `Unexpected password: ${ctx.password}`); + ctx.accept(); + })).on('ready', mustCall(() => { + conn.end(); + })); + })); +} diff --git a/reverse_engineering/node_modules/ssh2/test/test.js b/reverse_engineering/node_modules/ssh2/test/test.js index 4a91765..d0380f2 100644 --- a/reverse_engineering/node_modules/ssh2/test/test.js +++ b/reverse_engineering/node_modules/ssh2/test/test.js @@ -1,22 +1,20 @@ -var spawn = require('child_process').spawn, - join = require('path').join; +'use strict'; -var files = require('fs').readdirSync(__dirname).filter(function(f) { - return (f.substr(0, 5) === 'test-'); - }).map(function(f) { - return join(__dirname, f); - }), - f = -1; +const { spawnSync } = require('child_process'); +const { readdirSync } = require('fs'); +const { join } = require('path'); -function next() { - if (++f < files.length) { - spawn(process.argv[0], [ files[f] ], { stdio: 'inherit' }) - .on('exit', function(code) { - if (code === 0) - process.nextTick(next); - else - process.exit(code); - }); +const files = readdirSync(__dirname).sort(); +for (const filename of files) { + if (filename.startsWith('test-')) { + const path = join(__dirname, filename); + console.log(`> Running ${filename} ...`); + const result = spawnSync(`${process.argv0} ${path}`, { + shell: true, + stdio: 'inherit', + windowsHide: true + }); + if (result.status !== 0) + process.exitCode = 1; } } -next(); diff --git a/reverse_engineering/node_modules/streamsearch/README.md b/reverse_engineering/node_modules/streamsearch/README.md deleted file mode 100644 index 6310c20..0000000 --- a/reverse_engineering/node_modules/streamsearch/README.md +++ /dev/null @@ -1,87 +0,0 @@ -Description -=========== - -streamsearch is a module for [node.js](http://nodejs.org/) that allows searching a stream using the Boyer-Moore-Horspool algorithm. - -This module is based heavily on the Streaming Boyer-Moore-Horspool C++ implementation by Hongli Lai [here](https://github.com/FooBarWidget/boyer-moore-horspool). - - -Requirements -============ - -* [node.js](http://nodejs.org/) -- v0.8.0 or newer - - -Installation -============ - - npm install streamsearch - -Example -======= - -```javascript - var StreamSearch = require('streamsearch'), - inspect = require('util').inspect; - - var needle = new Buffer([13, 10]), // CRLF - s = new StreamSearch(needle), - chunks = [ - new Buffer('foo'), - new Buffer(' bar'), - new Buffer('\r'), - new Buffer('\n'), - new Buffer('baz, hello\r'), - new Buffer('\n world.'), - new Buffer('\r\n Node.JS rules!!\r\n\r\n') - ]; - s.on('info', function(isMatch, data, start, end) { - if (data) - console.log('data: ' + inspect(data.toString('ascii', start, end))); - if (isMatch) - console.log('match!'); - }); - for (var i = 0, len = chunks.length; i < len; ++i) - s.push(chunks[i]); - - // output: - // - // data: 'foo' - // data: ' bar' - // match! - // data: 'baz, hello' - // match! - // data: ' world.' - // match! - // data: ' Node.JS rules!!' - // match! - // data: '' - // match! -``` - - -API -=== - -Events ------- - -* **info**(< _boolean_ >isMatch[, < _Buffer_ >chunk, < _integer_ >start, < _integer_ >end]) - A match _may_ or _may not_ have been made. In either case, a preceding `chunk` of data _may_ be available that did not match the needle. Data (if available) is in `chunk` between `start` (inclusive) and `end` (exclusive). - - -Properties ----------- - -* **maxMatches** - < _integer_ > - The maximum number of matches. Defaults to Infinity. - -* **matches** - < _integer_ > - The current match count. - - -Functions ---------- - -* **(constructor)**(< _mixed_ >needle) - Creates and returns a new instance for searching for a _Buffer_ or _string_ `needle`. - -* **push**(< _Buffer_ >chunk) - _integer_ - Processes `chunk`. The return value is the last processed index in `chunk` + 1. - -* **reset**() - _(void)_ - Resets internal state. Useful for when you wish to start searching a new/different stream for example. diff --git a/reverse_engineering/node_modules/streamsearch/lib/sbmh.js b/reverse_engineering/node_modules/streamsearch/lib/sbmh.js deleted file mode 100644 index dbefbc1..0000000 --- a/reverse_engineering/node_modules/streamsearch/lib/sbmh.js +++ /dev/null @@ -1,213 +0,0 @@ -/* - Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation - by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool -*/ -var EventEmitter = require('events').EventEmitter, - inherits = require('util').inherits; - -function jsmemcmp(buf1, pos1, buf2, pos2, num) { - for (var i = 0; i < num; ++i, ++pos1, ++pos2) - if (buf1[pos1] !== buf2[pos2]) - return false; - return true; -} - -function SBMH(needle) { - if (typeof needle === 'string') - needle = new Buffer(needle); - var i, j, needle_len = needle.length; - - this.maxMatches = Infinity; - this.matches = 0; - - this._occ = new Array(256); - this._lookbehind_size = 0; - this._needle = needle; - this._bufpos = 0; - - this._lookbehind = new Buffer(needle_len); - - // Initialize occurrence table. - for (j = 0; j < 256; ++j) - this._occ[j] = needle_len; - - // Populate occurrence table with analysis of the needle, - // ignoring last letter. - if (needle_len >= 1) { - for (i = 0; i < needle_len - 1; ++i) - this._occ[needle[i]] = needle_len - 1 - i; - } -} -inherits(SBMH, EventEmitter); - -SBMH.prototype.reset = function() { - this._lookbehind_size = 0; - this.matches = 0; - this._bufpos = 0; -}; - -SBMH.prototype.push = function(chunk, pos) { - var r, chlen; - if (!Buffer.isBuffer(chunk)) - chunk = new Buffer(chunk, 'binary'); - chlen = chunk.length; - this._bufpos = pos || 0; - while (r !== chlen && this.matches < this.maxMatches) - r = this._sbmh_feed(chunk); - return r; -}; - -SBMH.prototype._sbmh_feed = function(data) { - var len = data.length, needle = this._needle, needle_len = needle.length; - - // Positive: points to a position in `data` - // pos == 3 points to data[3] - // Negative: points to a position in the lookbehind buffer - // pos == -2 points to lookbehind[lookbehind_size - 2] - var pos = -this._lookbehind_size, - last_needle_char = needle[needle_len - 1], - occ = this._occ, - lookbehind = this._lookbehind; - - if (pos < 0) { - // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool - // search with character lookup code that considers both the - // lookbehind buffer and the current round's haystack data. - // - // Loop until - // there is a match. - // or until - // we've moved past the position that requires the - // lookbehind buffer. In this case we switch to the - // optimized loop. - // or until - // the character to look at lies outside the haystack. - while (pos < 0 && pos <= len - needle_len) { - var ch = this._sbmh_lookup_char(data, pos + needle_len - 1); - - if (ch === last_needle_char - && this._sbmh_memcmp(data, pos, needle_len - 1)) { - this._lookbehind_size = 0; - ++this.matches; - if (pos > -this._lookbehind_size) - this.emit('info', true, lookbehind, 0, this._lookbehind_size + pos); - else - this.emit('info', true); - - this._bufpos = pos + needle_len; - return pos + needle_len; - } else - pos += occ[ch]; - } - - // No match. - - if (pos < 0) { - // There's too few data for Boyer-Moore-Horspool to run, - // so let's use a different algorithm to skip as much as - // we can. - // Forward pos until - // the trailing part of lookbehind + data - // looks like the beginning of the needle - // or until - // pos == 0 - while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) - pos++; - } - - if (pos >= 0) { - // Discard lookbehind buffer. - this.emit('info', false, lookbehind, 0, this._lookbehind_size); - this._lookbehind_size = 0; - } else { - // Cut off part of the lookbehind buffer that has - // been processed and append the entire haystack - // into it. - var bytesToCutOff = this._lookbehind_size + pos; - - if (bytesToCutOff > 0) { - // The cut off data is guaranteed not to contain the needle. - this.emit('info', false, lookbehind, 0, bytesToCutOff); - } - - lookbehind.copy(lookbehind, 0, bytesToCutOff, - this._lookbehind_size - bytesToCutOff); - this._lookbehind_size -= bytesToCutOff; - - data.copy(lookbehind, this._lookbehind_size); - this._lookbehind_size += len; - - this._bufpos = len; - return len; - } - } - - if (pos >= 0) - pos += this._bufpos; - - // Lookbehind buffer is now empty. Perform Boyer-Moore-Horspool - // search with optimized character lookup code that only considers - // the current round's haystack data. - while (pos <= len - needle_len) { - var ch = data[pos + needle_len - 1]; - - if (ch === last_needle_char - && data[pos] === needle[0] - && jsmemcmp(needle, 0, data, pos, needle_len - 1)) { - ++this.matches; - if (pos > 0) - this.emit('info', true, data, this._bufpos, pos); - else - this.emit('info', true); - - this._bufpos = pos + needle_len; - return pos + needle_len; - } else - pos += occ[ch]; - } - - // There was no match. If there's trailing haystack data that we cannot - // match yet using the Boyer-Moore-Horspool algorithm (because the trailing - // data is less than the needle size) then match using a modified - // algorithm that starts matching from the beginning instead of the end. - // Whatever trailing data is left after running this algorithm is added to - // the lookbehind buffer. - if (pos < len) { - while (pos < len && (data[pos] !== needle[0] - || !jsmemcmp(data, pos, needle, 0, len - pos))) { - ++pos; - } - if (pos < len) { - data.copy(lookbehind, 0, pos, pos + (len - pos)); - this._lookbehind_size = len - pos; - } - } - - // Everything until pos is guaranteed not to contain needle data. - if (pos > 0) - this.emit('info', false, data, this._bufpos, pos < len ? pos : len); - - this._bufpos = len; - return len; -}; - -SBMH.prototype._sbmh_lookup_char = function(data, pos) { - if (pos < 0) - return this._lookbehind[this._lookbehind_size + pos]; - else - return data[pos]; -} - -SBMH.prototype._sbmh_memcmp = function(data, pos, len) { - var i = 0; - - while (i < len) { - if (this._sbmh_lookup_char(data, pos + i) === this._needle[i]) - ++i; - else - return false; - } - return true; -} - -module.exports = SBMH; diff --git a/reverse_engineering/node_modules/streamsearch/package.json b/reverse_engineering/node_modules/streamsearch/package.json deleted file mode 100644 index 2a4916a..0000000 --- a/reverse_engineering/node_modules/streamsearch/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ "name": "streamsearch", - "version": "0.1.2", - "author": "Brian White ", - "description": "Streaming Boyer-Moore-Horspool searching for node.js", - "main": "./lib/sbmh", - "engines": { "node" : ">=0.8.0" }, - "keywords": [ "stream", "horspool", "boyer-moore-horspool", "boyer-moore", "search" ], - "licenses": [ { "type": "MIT", "url": "http://github.com/mscdex/streamsearch/raw/master/LICENSE" } ], - "repository": { "type": "git", "url": "http://github.com/mscdex/streamsearch.git" } - -,"_resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz" -,"_integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" -,"_from": "streamsearch@0.1.2" -} \ No newline at end of file diff --git a/reverse_engineering/node_modules/tunnel-ssh/.eslintignore b/reverse_engineering/node_modules/tunnel-ssh/.eslintignore index 1616ee7..91064a5 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/.eslintignore +++ b/reverse_engineering/node_modules/tunnel-ssh/.eslintignore @@ -1,4 +1,4 @@ -node_modules/** -.idea/** -build/** -examples +node_modules/** +.idea/** +build/** +examples diff --git a/reverse_engineering/node_modules/tunnel-ssh/.travis.yml b/reverse_engineering/node_modules/tunnel-ssh/.travis.yml new file mode 100644 index 0000000..c086098 --- /dev/null +++ b/reverse_engineering/node_modules/tunnel-ssh/.travis.yml @@ -0,0 +1,4 @@ +language: node_js + +node_js: + - node diff --git a/reverse_engineering/node_modules/ssh2-streams/LICENSE b/reverse_engineering/node_modules/tunnel-ssh/LICENSE similarity index 54% rename from reverse_engineering/node_modules/ssh2-streams/LICENSE rename to reverse_engineering/node_modules/tunnel-ssh/LICENSE index 3d983a8..6bd4c38 100644 --- a/reverse_engineering/node_modules/ssh2-streams/LICENSE +++ b/reverse_engineering/node_modules/tunnel-ssh/LICENSE @@ -1,19 +1,21 @@ -Copyright 2014 Brian White. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. \ No newline at end of file +MIT License + +Copyright (c) 2018 Christoph Hagenbrock (agebrock.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/reverse_engineering/node_modules/tunnel-ssh/README.md b/reverse_engineering/node_modules/tunnel-ssh/README.md index f5df064..60f4548 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/README.md +++ b/reverse_engineering/node_modules/tunnel-ssh/README.md @@ -1,139 +1,139 @@ -Tunnel-SSH -========== - -One to connect them all ! - -![Tunnel-SSH Logo](http://i.imgur.com/I5PRnDD.jpg) - -Tunnel-ssh is based on the fantastic [ssh2](https://github.com/mscdex/ssh2) library by Brian White. -Trouble ? Please study the ssh2 configuration. - -### Latest Relese 4.1.3 - -## Release notes -* Closing sshconnections correctly thx @actionshrimp -* Improved readme -* Updated modules - -Special thanks to -@vweevers and @dickeyxxx - - -### Related projects -* [If you don't want to wrap a tunnel around your code: inject-tunnel-ssh](https://github.com/agebrock/inject-tunnel-ssh) -* [If you need it the other way around: reverse-tunnel-ssh](https://github.com/agebrock/reverse-tunnel-ssh) - -### Integration -By default tunnel-ssh will close the tunnel after a client disconnects, so your cli tools should work in the same way, they do if you connect directly. -If you need the tunnel to stay open, use the "keepAlive:true" option within -the configuration. - - -```js - - var config = { - ... - keepAlive:true - }; - - var tnl = tunnel(config, function(error, tnl){ - yourClient.connect(); - yourClient.disconnect(); - setTimeout(function(){ - // you only need to close the tunnel by yourself if you set the - // keepAlive:true option in the configuration ! - tnl.close(); - },2000); - }); - - // you can also close the tunnel from here... - setTimeout(function(){ - tnl.close(); - },2000); - -``` - - -## Understanding the configuration - -1. A local server listening for connections to forward via ssh -Description: This is where you bind your interface. -Properties: -** localHost (default is '127.0.0.1') -** localPort (default is dstPort) - - -2. The ssh configuration -Description: The host you want to use as ssh-tunnel server. -Properties: -** host -** port (22) -** username -** ... - - -3. The destination host configuration (based on the ssh host) -Imagine you just connected to The host you want to connect to. (via host:port) -now that server connects requires a target to tunnel to. -Properties: -** dstHost (localhost) -** dstPort - - -### Config example - -```js - - var config = { - username:'root', - Password:'secret', - host:sshServer, - port:22, - dstHost:destinationServer, - dstPort:27017, - localHost:'127.0.0.1', - localPort: 27000 - }; - - var tunnel = require('tunnel-ssh'); - tunnel(config, function (error, server) { - //.... - }); -``` -#### Sugar configuration - -tunnel-ssh assumes that you want to map the same port on a remote machine to your localhost using the ssh-server on the remote machine. - - -```js - - var config = { - username:'root', - dstHost:'remotehost.with.sshserver.com', - dstPort:27017, - privateKey:require(fs).readFileSync('/path/to/key'), - passphrase:'secret' - }; - -``` - -#### More configuration options -tunnel-ssh pipes the configuration direct into the ssh2 library so every config option provided by ssh2 still works. -[ssh2 configuration](https://github.com/mscdex/ssh2#client-methods) - - -#### catching errors: -```js - var tunnel = require('tunnel-ssh'); - //map port from remote 3306 to localhost 3306 - var server = tunnel({host: '172.16.0.8', dstPort: 3306}, function (error, server) { - if(error){ - //catch configuration and startup errors here. - } - }); - - // Use a listener to handle errors outside the callback - server.on('error', function(err){ - console.error('Something bad happened:', err); - }); -``` +Tunnel-SSH +========== + +One to connect them all ! + +![Tunnel-SSH Logo](http://i.imgur.com/I5PRnDD.jpg) + +Tunnel-ssh is based on the fantastic [ssh2](https://github.com/mscdex/ssh2) library by Brian White. +Trouble ? Please study the ssh2 configuration. + +### Latest Relese 4.1.3 + +## Release notes +* Closing sshconnections correctly thx @actionshrimp +* Improved readme +* Updated modules + +Special thanks to +@vweevers and @dickeyxxx + + +### Related projects +* [If you don't want to wrap a tunnel around your code: inject-tunnel-ssh](https://github.com/agebrock/inject-tunnel-ssh) +* [If you need it the other way around: reverse-tunnel-ssh](https://github.com/agebrock/reverse-tunnel-ssh) + +### Integration +By default tunnel-ssh will close the tunnel after a client disconnects, so your cli tools should work in the same way, they do if you connect directly. +If you need the tunnel to stay open, use the "keepAlive:true" option within +the configuration. + + +```js + + var config = { + ... + keepAlive:true + }; + + var tnl = tunnel(config, function(error, tnl){ + yourClient.connect(); + yourClient.disconnect(); + setTimeout(function(){ + // you only need to close the tunnel by yourself if you set the + // keepAlive:true option in the configuration ! + tnl.close(); + },2000); + }); + + // you can also close the tunnel from here... + setTimeout(function(){ + tnl.close(); + },2000); + +``` + + +## Understanding the configuration + +1. A local server listening for connections to forward via ssh +Description: This is where you bind your interface. +Properties: +** localHost (default is '127.0.0.1') +** localPort (default is dstPort) + + +2. The ssh configuration +Description: The host you want to use as ssh-tunnel server. +Properties: +** host +** port (22) +** username +** ... + + +3. The destination host configuration (based on the ssh host) +Imagine you just connected to The host you want to connect to. (via host:port) +now that server connects requires a target to tunnel to. +Properties: +** dstHost (localhost) +** dstPort + + +### Config example + +```js + + var config = { + username:'root', + password:'secret', + host:sshServer, + port:22, + dstHost:destinationServer, + dstPort:27017, + localHost:'127.0.0.1', + localPort: 27000 + }; + + var tunnel = require('tunnel-ssh'); + tunnel(config, function (error, server) { + //.... + }); +``` +#### Sugar configuration + +tunnel-ssh assumes that you want to map the same port on a remote machine to your localhost using the ssh-server on the remote machine. + + +```js + + var config = { + username:'root', + dstHost:'remotehost.with.sshserver.com', + dstPort:27017, + privateKey:require(fs).readFileSync('/path/to/key'), + passphrase:'secret' + }; + +``` + +#### More configuration options +tunnel-ssh pipes the configuration direct into the ssh2 library so every config option provided by ssh2 still works. +[ssh2 configuration](https://github.com/mscdex/ssh2#client-methods) + + +#### catching errors: +```js + var tunnel = require('tunnel-ssh'); + //map port from remote 3306 to localhost 3306 + var server = tunnel({host: '172.16.0.8', dstPort: 3306}, function (error, server) { + if(error){ + //catch configuration and startup errors here. + } + }); + + // Use a listener to handle errors outside the callback + server.on('error', function(err){ + console.error('Something bad happened:', err); + }); +``` diff --git a/reverse_engineering/node_modules/tunnel-ssh/examples/default.js b/reverse_engineering/node_modules/tunnel-ssh/examples/default.js index c54e4e3..d050211 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/examples/default.js +++ b/reverse_engineering/node_modules/tunnel-ssh/examples/default.js @@ -1,26 +1,26 @@ -var tunnel = require('../'); -var helper = require('./server'); - - -/** -make sure you can connect to your own machine with the current user without password. -Example: ssh $USER@127.0.0.1 - -Remember to add your privateKey to your ssh-agent (ssh-add) -**/ - -var config = { - host: '127.0.0.1', username: process.env.USER, dstPort: 8000, localPort: 7000 -}; - -var fakeServer = helper.createServer(config.dstPort, '127.0.0.1', function () { - tunnel(config, function () { - console.log('Tunnel open'); - helper.createClient(7000, '127.0.0.1', console.log); - helper.createClient(7000, '127.0.0.1', console.log); - }).on('error', function (e) { - console.log('error', e); - }); -}); - -fakeServer.unref(); +var tunnel = require('../'); +var helper = require('./server'); + + +/** +make sure you can connect to your own machine with the current user without password. +Example: ssh $USER@127.0.0.1 + +Remember to add your privateKey to your ssh-agent (ssh-add) +**/ + +var config = { + host: '127.0.0.1', username: process.env.USER, dstPort: 8000, localPort: 7000 +}; + +var fakeServer = helper.createServer(config.dstPort, '127.0.0.1', function () { + tunnel(config, function () { + console.log('Tunnel open'); + helper.createClient(7000, '127.0.0.1', console.log); + helper.createClient(7000, '127.0.0.1', console.log); + }).on('error', function (e) { + console.log('error', e); + }); +}); + +fakeServer.unref(); diff --git a/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive.js b/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive.js index dbc4fe7..33af4b9 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive.js +++ b/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive.js @@ -1,35 +1,35 @@ -var tunnel = require('../'); -var helper = require('./server'); - -// Keep alive example -// this example demonstrates the keepAlive option. -// keepAlive will reuse the connections -// note the "tunnelKeepAlive.close();" at the end. -// this step is required to finish execution nicely - -var configA = { - host: '127.0.0.1', username: process.env.USER, dstPort: 8000, localPort: 7000, // Use keepAlive:true to keep the tunnel open. - keepAlive: true -}; - -var fakeServer = helper.createServer(configA.dstPort, '127.0.0.1', function () { - var tunnelKeepAlive = tunnel(configA, function () { - console.log('Tunnel open'); - helper.createClient(7000, '127.0.0.1', console.log); - helper.createClient(7000, '127.0.0.1', console.log); - helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { - helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { - helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { - setTimeout(function () { - // Call tunnel.close() to shutdown the server. - console.log('TRYING TO CLOSE'); - tunnelKeepAlive.close(); - }, 2000); - }); - }); - }); - }).on('error', function (e) { - console.log('error', e); - }); -}); -fakeServer.unref(); +var tunnel = require('../'); +var helper = require('./server'); + +// Keep alive example +// this example demonstrates the keepAlive option. +// keepAlive will reuse the connections +// note the "tunnelKeepAlive.close();" at the end. +// this step is required to finish execution nicely + +var configA = { + host: '127.0.0.1', username: process.env.USER, dstPort: 8000, localPort: 7000, // Use keepAlive:true to keep the tunnel open. + keepAlive: true +}; + +var fakeServer = helper.createServer(configA.dstPort, '127.0.0.1', function () { + var tunnelKeepAlive = tunnel(configA, function () { + console.log('Tunnel open'); + helper.createClient(7000, '127.0.0.1', console.log); + helper.createClient(7000, '127.0.0.1', console.log); + helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { + helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { + helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { + setTimeout(function () { + // Call tunnel.close() to shutdown the server. + console.log('TRYING TO CLOSE'); + tunnelKeepAlive.close(); + }, 2000); + }); + }); + }); + }).on('error', function (e) { + console.log('error', e); + }); +}); +fakeServer.unref(); diff --git a/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive_error.js b/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive_error.js index 329551e..97998c1 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive_error.js +++ b/reverse_engineering/node_modules/tunnel-ssh/examples/keepAlive_error.js @@ -1,35 +1,35 @@ -var tunnel = require('../'); -var helper = require('./server'); - -// Keep alive example -// this example demonstrates the keepAlive option. -// keepAlive will reuse the connections -// note the "tunnelKeepAlive.close();" at the end. -// this step is required to finish execution nicely - -var configA = { - host: '127.0.0.1', - username: process.env.USER, - dstPort: 8000, - localPort: 7000, // Use keepAlive:true to keep the tunnel open. - keepAlive: true -}; -var tunnelKeepAlive = tunnel(configA, function () { - console.log('Tunnel open'); - helper.createClient(7000, '127.0.0.1', console.log); - helper.createClient(7000, '127.0.0.1', console.log); - helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { - helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { - helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { - setTimeout(function () { - // Call tunnel.close() to shutdown the server. - console.log('TRYING TO CLOSE'); - tunnelKeepAlive.close(); - }, 2000); - }); - }); - }); -}).on('error', function (e) { - console.log('error', e); -}); - +var tunnel = require('../'); +var helper = require('./server'); + +// Keep alive example +// this example demonstrates the keepAlive option. +// keepAlive will reuse the connections +// note the "tunnelKeepAlive.close();" at the end. +// this step is required to finish execution nicely + +var configA = { + host: '127.0.0.1', + username: process.env.USER, + dstPort: 8000, + localPort: 7000, // Use keepAlive:true to keep the tunnel open. + keepAlive: true +}; +var tunnelKeepAlive = tunnel(configA, function () { + console.log('Tunnel open'); + helper.createClient(7000, '127.0.0.1', console.log); + helper.createClient(7000, '127.0.0.1', console.log); + helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { + helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { + helper.createClient(7000, '127.0.0.1', console.log).on('close', function () { + setTimeout(function () { + // Call tunnel.close() to shutdown the server. + console.log('TRYING TO CLOSE'); + tunnelKeepAlive.close(); + }, 2000); + }); + }); + }); +}).on('error', function (e) { + console.log('error', e); +}); + diff --git a/reverse_engineering/node_modules/tunnel-ssh/examples/loginError.js b/reverse_engineering/node_modules/tunnel-ssh/examples/loginError.js deleted file mode 100644 index e5ffb41..0000000 --- a/reverse_engineering/node_modules/tunnel-ssh/examples/loginError.js +++ /dev/null @@ -1,30 +0,0 @@ -var tunnel = require('../'); -var helper = require('./server'); - - -/** -make sure you can connect to your own machine with the current user without password. -Example: ssh $USER@127.0.0.1 - -Remember to add your privateKey to your ssh-agent (ssh-add) -**/ - -var config = { - host: '127.0.0.1', username: 'foo', dstPort: 8000, localPort: 7000 -}; - -var fakeServer = helper.createServer(config.dstPort, '127.0.0.1', function () { - var srv = tunnel(config, function (server, error) { - server.sshConnection.on('error',(e) => console.log("first",e.message)) - console.log('Tunnel open', error); - helper.createClient(7000, '127.0.0.1', console.log); - helper.createClient(7000, '127.0.0.1', console.log); - }).on('error', function (e) { - console.log('error', e); - }); - -// srv.sshConnection.on('error',(e) => console.log(e.message)) - -}); - -fakeServer.unref(); diff --git a/reverse_engineering/node_modules/tunnel-ssh/examples/server/index.js b/reverse_engineering/node_modules/tunnel-ssh/examples/server/index.js index 6b44457..c3132bd 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/examples/server/index.js +++ b/reverse_engineering/node_modules/tunnel-ssh/examples/server/index.js @@ -1,36 +1,36 @@ -var net = require('net'); -var debug = require('debug')('tunnel-ssh:test-server-client'); - -function createServer(port, addr, callback) { - var handleConnection = function (socket) { - socket.on('data', function (data) { - debug('server::data', data); - }); - debug('server::write'); - socket.write('Echo server\r\n'); - }; - - return net.createServer(handleConnection).listen(port, addr, callback); -} - -function createClient(port, addr, callback) { - var client = new net.Socket(); - - client.on('error', function (e) { - console.log('errortest', e); - }); - - client.connect(port, addr, function () { - debug('client::write'); - client.write('alive !'); - setTimeout(function () { - client.end(); - debug('client::end'); - callback(null, true); - }, 300); - }); - return client; -} - -exports.createServer = createServer; -exports.createClient = createClient; +var net = require('net'); +var debug = require('debug')('tunnel-ssh:test-server-client'); + +function createServer(port, addr, callback) { + var handleConnection = function (socket) { + socket.on('data', function (data) { + debug('server::data', data); + }); + debug('server::write'); + socket.write('Echo server\r\n'); + }; + + return net.createServer(handleConnection).listen(port, addr, callback); +} + +function createClient(port, addr, callback) { + var client = new net.Socket(); + + client.on('error', function (e) { + console.log('errortest', e); + }); + + client.connect(port, addr, function () { + debug('client::write'); + client.write('alive !'); + setTimeout(function () { + client.end(); + debug('client::end'); + callback(null, true); + }, 300); + }); + return client; +} + +exports.createServer = createServer; +exports.createClient = createClient; diff --git a/reverse_engineering/node_modules/tunnel-ssh/index.js b/reverse_engineering/node_modules/tunnel-ssh/index.js index b3744e5..68f3401 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/index.js +++ b/reverse_engineering/node_modules/tunnel-ssh/index.js @@ -1,101 +1,112 @@ -var net = require('net'); -var debug = require('debug')('tunnel-ssh'); -var Connection = require('ssh2'); -var createConfig = require('./lib/config'); -var events = require('events'); -var noop = function () { -}; - -function bindSSHConnection(config, netConnection) { - var sshConnection = new Connection(); - netConnection.on('close', sshConnection.end.bind(sshConnection)); - - sshConnection.on('ready', function () { - debug('sshConnection:ready'); - netConnection.emit('sshConnection', sshConnection, netConnection); - sshConnection.forwardOut(config.srcHost, config.srcPort, config.dstHost, config.dstPort, function (err, sshStream) { - if (err) { - // Bubble up the error => netConnection => server - netConnection.emit('error', err); - debug('Destination port:', err); - return; - } - - debug('sshStream:create'); - netConnection.emit('sshStream', sshStream); - netConnection.pipe(sshStream).pipe(netConnection); - }); - }); - return sshConnection; -} - -function createServer(config) { - var server; - var connections = []; - var connectionCount = 0; - - server = net.createServer(function (netConnection) { - var sshConnection; - connectionCount++; - netConnection.on('error', server.emit.bind(server, 'error')); - netConnection.on('close', function () { - connectionCount--; - if (connectionCount === 0) { - if (!config.keepAlive) { - setTimeout(function () { - if (connectionCount === 0) { - server.close(); - } - }, 2); - } - } - }); - - server.emit('netConnection', netConnection, server); - sshConnection = bindSSHConnection(config, netConnection); - sshConnection.on('error', server.emit.bind(server, 'error')); - - netConnection.on('sshStream', function (sshStream) { - sshStream.on('error', function () { - server.close(); - }); - }); - - connections.push(sshConnection, netConnection); - sshConnection.connect(config); - }); - - server.on('close', function () { - connections.forEach(function (connection) { - connection.end(); - }); - }); - - return server; -} - -function tunnel(configArgs, callback) { - var server; - var config; - - if (!callback) { - callback = noop; - } - try { - config = createConfig(configArgs); - server = createServer(config); - - server.listen(config.localPort, config.localHost, function (error) { - callback(error, server); - }); - } catch (e) { - server = new events.EventEmitter(); - setImmediate(function () { - callback(e); - server.emit('error', e); - }); - } - return server; -} - -module.exports = tunnel; +var net = require('net'); +var debug = require('debug')('tunnel-ssh'); +var Connection = require('ssh2').Client; +var createConfig = require('./lib/config'); +var events = require('events'); +var noop = function () { +}; + +function bindSSHConnection(config, netConnection) { + var sshConnection = new Connection(); + netConnection.on('close', sshConnection.end.bind(sshConnection)); + + sshConnection.on('ready', function () { + debug('sshConnection:ready'); + netConnection.emit('sshConnection', sshConnection, netConnection); + sshConnection.forwardOut(config.srcHost, config.srcPort, config.dstHost, config.dstPort, function (err, sshStream) { + if (err) { + // Bubble up the error => netConnection => server + netConnection.emit('error', err); + debug('Destination port:', err); + return; + } + + debug('sshStream:create'); + netConnection.emit('sshStream', sshStream); + netConnection.pipe(sshStream).pipe(netConnection); + }); + }); + return sshConnection; +} + +function omit(obj, keys) { + return keys.reduce(function (copyObj, key) { + delete copyObj[key]; + return copyObj; + }, Object.assign({}, obj)); +} + +function createServer(config) { + var server; + var connections = []; + var connectionCount = 0; + + server = net.createServer(function (netConnection) { + var sshConnection; + connectionCount++; + netConnection.on('error', server.emit.bind(server, 'error')); + netConnection.on('close', function () { + connectionCount--; + if (connectionCount === 0) { + if (!config.keepAlive) { + setTimeout(function () { + if (connectionCount === 0) { + server.close(); + } + }, 2); + } + } + }); + + server.emit('netConnection', netConnection, server); + sshConnection = bindSSHConnection(config, netConnection); + sshConnection.on('error', server.emit.bind(server, 'error')); + + netConnection.on('sshStream', function (sshStream) { + sshStream.on('error', function () { + server.close(); + }); + }); + + connections.push(sshConnection, netConnection); + try { + sshConnection.connect(omit(config, ['localPort', 'localHost'])); + } catch (error) { + server.emit('error', error); + } + }); + + server.on('close', function () { + connections.forEach(function (connection) { + connection.end(); + }); + }); + + return server; +} + +function tunnel(configArgs, callback) { + var server; + var config; + + if (!callback) { + callback = noop; + } + try { + config = createConfig(configArgs); + server = createServer(config); + + server.listen(config.localPort, config.localHost, function (error) { + callback(error, server); + }); + } catch (e) { + server = new events.EventEmitter(); + setImmediate(function () { + callback(e); + server.emit('error', e); + }); + } + return server; +} + +module.exports = tunnel; diff --git a/reverse_engineering/node_modules/tunnel-ssh/lib/config.js b/reverse_engineering/node_modules/tunnel-ssh/lib/config.js index 99b1996..49f7327 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/lib/config.js +++ b/reverse_engineering/node_modules/tunnel-ssh/lib/config.js @@ -1,53 +1,53 @@ -var util = require('util'); -var defaults = require('lodash.defaults'); -var debug = require('debug')('tunnel-ssh-config'); - -var ConfigError = function (message, extra) { - Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; - this.message = message; - this.extra = extra; -}; - -util.inherits(ConfigError, Error); - -function createConfig(config) { - var env = process.env; - - defaults(config || {}, { - username: env.TUNNELSSH_USER || env.USER || env.USERNAME || 'root', - port: 22, - host: null, - srcPort: 0, - srcHost: '127.0.0.1', - dstPort: null, - dstHost: '127.0.0.1', - localHost: '127.0.0.1', - localPort: config.dstPort, - agent: process.env.SSH_AUTH_SOCK - }); - - if (!config.host) { - throw new ConfigError('host not set'); - } - - if (!config.dstPort) { - throw new ConfigError('dstPort not set'); - } - debug('ssh-config', (function () { - var hiddenValues = ['password', 'privateKey']; - - return Object.keys(config).reduce(function (obj, key) { - if (hiddenValues.indexOf(key) === -1) { - obj[key] = config[key]; - } else { - obj[key] = '***HIDDEN***'; - } - return obj; - }, {}); - })()); - - return config; -} - -module.exports = createConfig; +var util = require('util'); +var defaults = require('lodash.defaults'); +var debug = require('debug')('tunnel-ssh-config'); + +var ConfigError = function (message, extra) { + Error.captureStackTrace(this, this.constructor); + this.name = this.constructor.name; + this.message = message; + this.extra = extra; +}; + +util.inherits(ConfigError, Error); + +function createConfig(config) { + var env = process.env; + + defaults(config || {}, { + username: env.TUNNELSSH_USER || env.USER || env.USERNAME || 'root', + port: 22, + host: null, + srcPort: 0, + srcHost: '127.0.0.1', + dstPort: null, + dstHost: '127.0.0.1', + localHost: '127.0.0.1', + localPort: config.dstPort, + agent: process.env.SSH_AUTH_SOCK + }); + + if (!config.host) { + throw new ConfigError('host not set'); + } + + if (!config.dstPort) { + throw new ConfigError('dstPort not set'); + } + debug('ssh-config', (function () { + var hiddenValues = ['password', 'privateKey']; + + return Object.keys(config).reduce(function (obj, key) { + if (hiddenValues.indexOf(key) === -1) { + obj[key] = config[key]; + } else { + obj[key] = '***HIDDEN***'; + } + return obj; + }, {}); + })()); + + return config; +} + +module.exports = createConfig; diff --git a/reverse_engineering/node_modules/tunnel-ssh/package.json b/reverse_engineering/node_modules/tunnel-ssh/package.json index c693857..c970f0e 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/package.json +++ b/reverse_engineering/node_modules/tunnel-ssh/package.json @@ -1,32 +1,42 @@ { - "name": "tunnel-ssh", - "version": "4.1.4", - "description": "Easy extendable SSH tunnel", - "main": "index.js", - "scripts": { - "test": "mocha && eslint ." + "_from": "tunnel-ssh@^4.1.6", + "_id": "tunnel-ssh@4.1.6", + "_inBundle": false, + "_integrity": "sha512-y7+x+T3F3rkx2Zov5Tk9DGfeEBVAdWU3A/91E0Dk5rrZ/VFIlpV2uhhRuaISJUdyG0N+Lcp1fXZMXz+ovPt5vA==", + "_location": "/tunnel-ssh", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "tunnel-ssh@^4.1.6", + "name": "tunnel-ssh", + "escapedName": "tunnel-ssh", + "rawSpec": "^4.1.6", + "saveSpec": null, + "fetchSpec": "^4.1.6" }, - "repository": { - "type": "git", - "url": "https://github.com/agebrock/tunnel-ssh" - }, - "keywords": [ - "tunnel", - "ssh", - "mysql", - "develop", - "net" + "_requiredBy": [ + "/" ], + "_resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.6.tgz", + "_shasum": "9409e8e98d019ab6207d65807ad3851144dbc1d9", + "_spec": "tunnel-ssh@^4.1.6", + "_where": "/home/vitalii/.hackolade/plugins/PostgreSQL/reverse_engineering", "author": { "name": "Christoph Hagenbrock", "email": "christoph.hagenbrock@googlemail.com" }, - "license": "MIT", + "bugs": { + "url": "https://github.com/agebrock/tunnel-ssh/issues" + }, + "bundleDependencies": false, "dependencies": { "debug": "2.6.9", "lodash.defaults": "^4.1.0", - "ssh2": "0.5.4" + "ssh2": "1.4.0" }, + "deprecated": false, + "description": "Easy extendable SSH tunnel", "devDependencies": { "chai": "3.5.0", "eslint": "^3.2.2", @@ -44,9 +54,24 @@ 4 ] } - } - -,"_resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.4.tgz" -,"_integrity": "sha512-CjBqboGvAbM7iXSX2F95kzoI+c2J81YkrHbyyo4SWNKCzU6w5LfEvXBCHu6PPriYaNvfhMKzD8bFf5Vl14YTtg==" -,"_from": "tunnel-ssh@4.1.4" -} \ No newline at end of file + }, + "homepage": "https://github.com/agebrock/tunnel-ssh#readme", + "keywords": [ + "tunnel", + "ssh", + "mysql", + "develop", + "net" + ], + "license": "MIT", + "main": "index.js", + "name": "tunnel-ssh", + "repository": { + "type": "git", + "url": "git+https://github.com/agebrock/tunnel-ssh.git" + }, + "scripts": { + "test": "mocha && eslint ." + }, + "version": "4.1.6" +} diff --git a/reverse_engineering/node_modules/tunnel-ssh/rewrite.js b/reverse_engineering/node_modules/tunnel-ssh/rewrite.js deleted file mode 100644 index f952634..0000000 --- a/reverse_engineering/node_modules/tunnel-ssh/rewrite.js +++ /dev/null @@ -1,138 +0,0 @@ -const events = require('events'); -const sshClient = require('ssh2'); -const net = require('net'); -const debug = require('debug')('tunnel-ssh'); -const createConfig = require('./lib/config'); - -class Tunnel extends events.EventEmitter { - constructor(config) { - super(); - this.config = config; - // Expose sshClient for external event-bindings - // @TODO exclude into separate util function - this.sshClient = sshClient(); - this.sshClient.promise = new Promise((resolve, reject) => { - this.sshClient - .on('ready', () => resolve(this.sshClient)) - .on('error', error => reject(error)) - .connect(config); - }); - } - - /** - * Creates a dublex stream - * @returns {Promise.} - */ - getStream(srcHost, srcPort, dstHost, dstPort) { - // @todo implement old behavior "create a new client for every connection" - return this.sshClient.promise.then(client => { - return new Promise((resolve, reject) => { - return client.forwardOut( - srcHost, - srcPort, - dstHost, - dstPort, (error, sshConnection) => { - if (error) { - this.emit('error', error); - return reject(error); - } - return resolve(sshConnection); - }); - }); - }); - } - - /** - * Creates a tcp server as entry point for the ssh tunnel, - * every incoming tcp connection is piped to the tunnel. - * @returns {Promise.} - */ - listen(port, addr, srcHost, srcPort, dstHost, dstPort) { - let server = net.createServer(); - server.promise = new Promise((resolve, reject) => { - server.on('listening', () => resolve(server)); - server.on('error', error => reject(error)); - }); - - server.promise.catch(e => { - this.emit('error', e); - }); - - server.on('connection', tcpConnection => { - this.getStream(srcHost, srcPort, dstHost, dstPort).then(sshConnection => { - debug('sshConnection:create'); - this.emit('sshConnection', sshConnection); - if (this.config.exitOnLastConnectionEnd === true) { - tcpConnection.on('close', () => server.getConnections((error, count) => { - if (error) { - this.emit('error', error); - } - debug('ConnectionCount => ' + count); - if (count === 0) { - server.close(); - } - })); - } - tcpConnection.pipe(sshConnection).pipe(tcpConnection); - sshConnection.on('end', () => console.log('ssh-connection end')); - sshConnection.on('close', () => console.log('ssh-connection close')); - }).catch(error => this.emit('error', error)); - }); - - server.on('close', () => { - debug('server::close'); - this.sshClient.end(); - }); - - return this.sshClient.promise.then(() => { - server.listen(port, addr); - return server; - }).catch(error => this.emit('error', error)); - } -} - -function tunnel(rawConfig) { - let config = createConfig(rawConfig); - - let tnl = new Tunnel(config); - tnl.listen( - config.bindPort, - config.bindAddr, - config.srcHost, - config.srcPort, - config.dstHost, - config.dstPort - ).then(server => { - server.on('listening', function () { - console.log('listening'); - }); - }).catch(error => this.emit('error', error)); - - Promise.all(config.ports.map(port => { - return tnl.listen( - port, - config.bindAddr, - config.srcHost, - config.srcPort, - config.dstHost, - port - ); - })).then(() => console.log('done')).catch(error => console.log(error)) - - return tnl; -} -/* - var http = require('http'); - var s = http.createServer(function (req, res) { - res.setHeader('Content-Type', 'text/html'); - res.setHeader('X-Foo', 'bar'); - res.writeHead(200, {'Content-Type': 'text/plain'}); - res.write('foo'); - res.end('ok'); - }); - s.listen(7000); - s.unref(); - */ -tunnel({ - host: 'pi', user: 'pi', passphrase: '*gold12', dstPort: 8080, bindPort: 8082, ports: [8081] -}).on('error', error => console.log(error)); diff --git a/reverse_engineering/node_modules/tunnel-ssh/test/config-spec.js b/reverse_engineering/node_modules/tunnel-ssh/test/config-spec.js index 24229da..7ad297b 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/test/config-spec.js +++ b/reverse_engineering/node_modules/tunnel-ssh/test/config-spec.js @@ -1,56 +1,56 @@ -var chai = require('chai'); -var expect = chai.expect; -var createConfig = require('../lib/config'); - -describe('config', function () { - it('use dstPort as localPort', function () { - var config = { - host: 'test.host', dstPort: 8000 - }; - expect(createConfig(config).localPort).to.be.equal(8000); - }); - - it('should emit an error', function () { - var config = { - host: 'remoteHost' - }; - expect(createConfig.bind(null, config)).to.throw('dstPort not set'); - }); - - it('throws an error if host is missing', function () { - var config = { - dstPort: 8000 - }; - expect(createConfig.bind(null, config)).to.throw('host not set'); - }); -}); - -/* - // Keep alive - var configA = { - host: '127.0.0.1', - username: process.env.USER, - dstPort: 8000, - localPort: 7000, - // Use keepAlive:true to keep the tunnel open. - keepAlive: true - }; - var tunnelKeepAlive = tunnel(configA, function() { - console.log('Tunnel open'); - helper.createClient(7000, '127.0.0.1', console.log).on('close', function() { - helper.createClient(7000, '127.0.0.1', console.log).on('close', function() { - helper.createClient(7000, '127.0.0.1', console.log).on('close', function() { - setTimeout(function() { - // Call tunnel.close() to shutdown the server. - console.log('TRYING TO CLOSE'); - tunnelKeepAlive.close(); - }, 2000); - }); - }); - }); - }).on('error', function(e) { - console.log('error', e); - }); - }); - - */ +var chai = require('chai'); +var expect = chai.expect; +var createConfig = require('../lib/config'); + +describe('config', function () { + it('use dstPort as localPort', function () { + var config = { + host: 'test.host', dstPort: 8000 + }; + expect(createConfig(config).localPort).to.be.equal(8000); + }); + + it('should emit an error', function () { + var config = { + host: 'remoteHost' + }; + expect(createConfig.bind(null, config)).to.throw('dstPort not set'); + }); + + it('throws an error if host is missing', function () { + var config = { + dstPort: 8000 + }; + expect(createConfig.bind(null, config)).to.throw('host not set'); + }); +}); + +/* + // Keep alive + var configA = { + host: '127.0.0.1', + username: process.env.USER, + dstPort: 8000, + localPort: 7000, + // Use keepAlive:true to keep the tunnel open. + keepAlive: true + }; + var tunnelKeepAlive = tunnel(configA, function() { + console.log('Tunnel open'); + helper.createClient(7000, '127.0.0.1', console.log).on('close', function() { + helper.createClient(7000, '127.0.0.1', console.log).on('close', function() { + helper.createClient(7000, '127.0.0.1', console.log).on('close', function() { + setTimeout(function() { + // Call tunnel.close() to shutdown the server. + console.log('TRYING TO CLOSE'); + tunnelKeepAlive.close(); + }, 2000); + }); + }); + }); + }).on('error', function(e) { + console.log('error', e); + }); + }); + + */ diff --git a/reverse_engineering/node_modules/tunnel-ssh/test/main-spec.js b/reverse_engineering/node_modules/tunnel-ssh/test/main-spec.js index c95d2fa..4849387 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/test/main-spec.js +++ b/reverse_engineering/node_modules/tunnel-ssh/test/main-spec.js @@ -1,37 +1,37 @@ -var tunnel = require('../'); -var helper = require('./server'); -var chai = require('chai'); -var expect = chai.expect; - -describe('tunnel-ssh', function () { - it('should emit an error', function (done) { - var config = { - host: '127.0.0.1', username: process.env.USER, dstPort: 8000, localPort: 7000 - }; - - tunnel(config, function () { - helper.createClient(7000, '127.0.0.1', done); - }).on('error', function (e) { - expect(e).to.be.instanceOf(Error); - done(null); - }); - }); - - it('brokenConfig, should callback an error', function (done) { - var brokenConfig = {}; - - tunnel(brokenConfig, function (e) { - expect(e).to.be.instanceOf(Error); - done(); - }); - }); - - it('brokenConfig, should emit an error', function (done) { - var brokenConfig = {}; - - tunnel(brokenConfig).on('error', function (e) { - expect(e).to.be.instanceOf(Error); - done(null); - }); - }); -}); +var tunnel = require('../'); +var helper = require('./server'); +var chai = require('chai'); +var expect = chai.expect; + +describe('tunnel-ssh', function () { + it('should emit an error', function (done) { + var config = { + host: '127.0.0.1', username: process.env.USER, dstPort: 8000, localPort: 7000 + }; + + tunnel(config, function () { + helper.createClient(7000, '127.0.0.1', done); + }).on('error', function (e) { + expect(e).to.be.instanceOf(Error); + done(null); + }); + }); + + it('brokenConfig, should callback an error', function (done) { + var brokenConfig = {}; + + tunnel(brokenConfig, function (e) { + expect(e).to.be.instanceOf(Error); + done(); + }); + }); + + it('brokenConfig, should emit an error', function (done) { + var brokenConfig = {}; + + tunnel(brokenConfig).on('error', function (e) { + expect(e).to.be.instanceOf(Error); + done(null); + }); + }); +}); diff --git a/reverse_engineering/node_modules/tunnel-ssh/test/server/index.js b/reverse_engineering/node_modules/tunnel-ssh/test/server/index.js index 2988288..5a7e232 100644 --- a/reverse_engineering/node_modules/tunnel-ssh/test/server/index.js +++ b/reverse_engineering/node_modules/tunnel-ssh/test/server/index.js @@ -1,36 +1,36 @@ -var net = require('net'); -var debug = require('debug')('tunnel-ssh:test-server-client'); - -function createServer(port, addr, callback) { - var handleConnection = function (socket) { - socket.on('data', function (data) { - debug('server::data', data); - }); - debug('server::write'); - socket.write('Echo server\r\n'); - }; - - return net.createServer(handleConnection).listen(port, addr, callback); -} - -function createClient(port, addr, callback) { - var client = new net.Socket(); - - client.on('error', function (e) { - debug('clientError', e); - }); - - client.connect(port, addr, function () { - debug('client::write'); - client.write('alive !'); - setTimeout(function () { - client.end(); - debug('client::end'); - callback(null, true); - }, 300); - }); - return client; -} - -exports.createServer = createServer; -exports.createClient = createClient; +var net = require('net'); +var debug = require('debug')('tunnel-ssh:test-server-client'); + +function createServer(port, addr, callback) { + var handleConnection = function (socket) { + socket.on('data', function (data) { + debug('server::data', data); + }); + debug('server::write'); + socket.write('Echo server\r\n'); + }; + + return net.createServer(handleConnection).listen(port, addr, callback); +} + +function createClient(port, addr, callback) { + var client = new net.Socket(); + + client.on('error', function (e) { + debug('clientError', e); + }); + + client.connect(port, addr, function () { + debug('client::write'); + client.write('alive !'); + setTimeout(function () { + client.end(); + debug('client::end'); + callback(null, true); + }, 300); + }); + return client; +} + +exports.createServer = createServer; +exports.createClient = createClient; diff --git a/reverse_engineering/node_modules/tweetnacl/.npmignore b/reverse_engineering/node_modules/tweetnacl/.npmignore new file mode 100644 index 0000000..7d98dcb --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/.npmignore @@ -0,0 +1,4 @@ +.eslintrc +.travis.yml +bower.json +test diff --git a/reverse_engineering/node_modules/tweetnacl/AUTHORS.md b/reverse_engineering/node_modules/tweetnacl/AUTHORS.md new file mode 100644 index 0000000..6d74d40 --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/AUTHORS.md @@ -0,0 +1,28 @@ +List of TweetNaCl.js authors +============================ + + Alphabetical order by first name. + Format: Name (GitHub username or URL) + +* AndSDev (@AndSDev) +* Devi Mandiri (@devi) +* Dmitry Chestnykh (@dchest) + +List of authors of third-party public domain code from which TweetNaCl.js code was derived +========================================================================================== + +[TweetNaCl](http://tweetnacl.cr.yp.to/) +-------------------------------------- + +* Bernard van Gastel +* Daniel J. Bernstein +* Peter Schwabe +* Sjaak Smetsers +* Tanja Lange +* Wesley Janssen + + +[Poly1305-donna](https://github.com/floodyberry/poly1305-donna) +-------------------------------------------------------------- + +* Andrew Moon (@floodyberry) diff --git a/reverse_engineering/node_modules/tweetnacl/CHANGELOG.md b/reverse_engineering/node_modules/tweetnacl/CHANGELOG.md new file mode 100644 index 0000000..92a4fdc --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/CHANGELOG.md @@ -0,0 +1,221 @@ +TweetNaCl.js Changelog +====================== + + +v0.14.5 +------- + +* Fixed incomplete return types in TypeScript typings. +* Replaced COPYING.txt with LICENSE file, which now has public domain dedication + text from The Unlicense. License fields in package.json and bower.json have + been set to "Unlicense". The project was and will be in the public domain -- + this change just makes it easier for automated tools to know about this fact by + using the widely recognized and SPDX-compatible template for public domain + dedication. + + +v0.14.4 +------- + +* Added TypeScript type definitions (contributed by @AndSDev). +* Improved benchmarking code. + + +v0.14.3 +------- + +Fixed a bug in the fast version of Poly1305 and brought it back. + +Thanks to @floodyberry for promptly responding and fixing the original C code: + +> "The issue was not properly detecting if st->h was >= 2^130 - 5, coupled with +> [testing mistake] not catching the failure. The chance of the bug affecting +> anything in the real world is essentially zero luckily, but it's good to have +> it fixed." + +https://github.com/floodyberry/poly1305-donna/issues/2#issuecomment-202698577 + + +v0.14.2 +------- + +Switched Poly1305 fast version back to original (slow) version due to a bug. + + +v0.14.1 +------- + +No code changes, just tweaked packaging and added COPYING.txt. + + +v0.14.0 +------- + +* **Breaking change!** All functions from `nacl.util` have been removed. These + functions are no longer available: + + nacl.util.decodeUTF8 + nacl.util.encodeUTF8 + nacl.util.decodeBase64 + nacl.util.encodeBase64 + + If want to continue using them, you can include + package: + + + + + or + + var nacl = require('tweetnacl'); + nacl.util = require('tweetnacl-util'); + + However it is recommended to use better packages that have wider + compatibility and better performance. Functions from `nacl.util` were never + intended to be robust solution for string conversion and were included for + convenience: cryptography library is not the right place for them. + + Currently calling these functions will throw error pointing to + `tweetnacl-util-js` (in the next version this error message will be removed). + +* Improved detection of available random number generators, making it possible + to use `nacl.randomBytes` and related functions in Web Workers without + changes. + +* Changes to testing (see README). + + +v0.13.3 +------- + +No code changes. + +* Reverted license field in package.json to "Public domain". + +* Fixed typo in README. + + +v0.13.2 +------- + +* Fixed undefined variable bug in fast version of Poly1305. No worries, this + bug was *never* triggered. + +* Specified CC0 public domain dedication. + +* Updated development dependencies. + + +v0.13.1 +------- + +* Exclude `crypto` and `buffer` modules from browserify builds. + + +v0.13.0 +------- + +* Made `nacl-fast` the default version in NPM package. Now + `require("tweetnacl")` will use fast version; to get the original version, + use `require("tweetnacl/nacl.js")`. + +* Cleanup temporary array after generating random bytes. + + +v0.12.2 +------- + +* Improved performance of curve operations, making `nacl.scalarMult`, `nacl.box`, + `nacl.sign` and related functions up to 3x faster in `nacl-fast` version. + + +v0.12.1 +------- + +* Significantly improved performance of Salsa20 (~1.5x faster) and + Poly1305 (~3.5x faster) in `nacl-fast` version. + + +v0.12.0 +------- + +* Instead of using the given secret key directly, TweetNaCl.js now copies it to + a new array in `nacl.box.keyPair.fromSecretKey` and + `nacl.sign.keyPair.fromSecretKey`. + + +v0.11.2 +------- + +* Added new constant: `nacl.sign.seedLength`. + + +v0.11.1 +------- + +* Even faster hash for both short and long inputs (in `nacl-fast`). + + +v0.11.0 +------- + +* Implement `nacl.sign.keyPair.fromSeed` to enable creation of sign key pairs + deterministically from a 32-byte seed. (It behaves like + [libsodium's](http://doc.libsodium.org/public-key_cryptography/public-key_signatures.html) + `crypto_sign_seed_keypair`: the seed becomes a secret part of the secret key.) + +* Fast version now has an improved hash implementation that is 2x-5x faster. + +* Fixed benchmarks, which may have produced incorrect measurements. + + +v0.10.1 +------- + +* Exported undocumented `nacl.lowlevel.crypto_core_hsalsa20`. + + +v0.10.0 +------- + +* **Signature API breaking change!** `nacl.sign` and `nacl.sign.open` now deal + with signed messages, and new `nacl.sign.detached` and + `nacl.sign.detached.verify` are available. + + Previously, `nacl.sign` returned a signature, and `nacl.sign.open` accepted a + message and "detached" signature. This was unlike NaCl's API, which dealt with + signed messages (concatenation of signature and message). + + The new API is: + + nacl.sign(message, secretKey) -> signedMessage + nacl.sign.open(signedMessage, publicKey) -> message | null + + Since detached signatures are common, two new API functions were introduced: + + nacl.sign.detached(message, secretKey) -> signature + nacl.sign.detached.verify(message, signature, publicKey) -> true | false + + (Note that it's `verify`, not `open`, and it returns a boolean value, unlike + `open`, which returns an "unsigned" message.) + +* NPM package now comes without `test` directory to keep it small. + + +v0.9.2 +------ + +* Improved documentation. +* Fast version: increased theoretical message size limit from 2^32-1 to 2^52 + bytes in Poly1305 (and thus, secretbox and box). However this has no impact + in practice since JavaScript arrays or ArrayBuffers are limited to 32-bit + indexes, and most implementations won't allocate more than a gigabyte or so. + (Obviously, there are no tests for the correctness of implementation.) Also, + it's not recommended to use messages that large without splitting them into + smaller packets anyway. + + +v0.9.1 +------ + +* Initial release diff --git a/reverse_engineering/node_modules/tweetnacl/LICENSE b/reverse_engineering/node_modules/tweetnacl/LICENSE new file mode 100644 index 0000000..cf1ab25 --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/reverse_engineering/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md b/reverse_engineering/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..a8eb4a9 --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +# Important! + +If your contribution is not trivial (not a typo fix, etc.), we can only accept +it if you dedicate your copyright for the contribution to the public domain. +Make sure you understand what it means (see http://unlicense.org/)! If you +agree, please add yourself to AUTHORS.md file, and include the following text +to your pull request description or a comment in it: + +------------------------------------------------------------------------------ + + I dedicate any and all copyright interest in this software to the + public domain. I make this dedication for the benefit of the public at + large and to the detriment of my heirs and successors. I intend this + dedication to be an overt act of relinquishment in perpetuity of all + present and future rights to this software under copyright law. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. diff --git a/reverse_engineering/node_modules/tweetnacl/README.md b/reverse_engineering/node_modules/tweetnacl/README.md new file mode 100644 index 0000000..ffb6871 --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/README.md @@ -0,0 +1,459 @@ +TweetNaCl.js +============ + +Port of [TweetNaCl](http://tweetnacl.cr.yp.to) / [NaCl](http://nacl.cr.yp.to/) +to JavaScript for modern browsers and Node.js. Public domain. + +[![Build Status](https://travis-ci.org/dchest/tweetnacl-js.svg?branch=master) +](https://travis-ci.org/dchest/tweetnacl-js) + +Demo: + +**:warning: The library is stable and API is frozen, however it has not been +independently reviewed. If you can help reviewing it, please [contact +me](mailto:dmitry@codingrobots.com).** + +Documentation +============= + +* [Overview](#overview) +* [Installation](#installation) +* [Usage](#usage) + * [Public-key authenticated encryption (box)](#public-key-authenticated-encryption-box) + * [Secret-key authenticated encryption (secretbox)](#secret-key-authenticated-encryption-secretbox) + * [Scalar multiplication](#scalar-multiplication) + * [Signatures](#signatures) + * [Hashing](#hashing) + * [Random bytes generation](#random-bytes-generation) + * [Constant-time comparison](#constant-time-comparison) +* [System requirements](#system-requirements) +* [Development and testing](#development-and-testing) +* [Benchmarks](#benchmarks) +* [Contributors](#contributors) +* [Who uses it](#who-uses-it) + + +Overview +-------- + +The primary goal of this project is to produce a translation of TweetNaCl to +JavaScript which is as close as possible to the original C implementation, plus +a thin layer of idiomatic high-level API on top of it. + +There are two versions, you can use either of them: + +* `nacl.js` is the port of TweetNaCl with minimum differences from the + original + high-level API. + +* `nacl-fast.js` is like `nacl.js`, but with some functions replaced with + faster versions. + + +Installation +------------ + +You can install TweetNaCl.js via a package manager: + +[Bower](http://bower.io): + + $ bower install tweetnacl + +[NPM](https://www.npmjs.org/): + + $ npm install tweetnacl + +or [download source code](https://github.com/dchest/tweetnacl-js/releases). + + +Usage +----- + +All API functions accept and return bytes as `Uint8Array`s. If you need to +encode or decode strings, use functions from + or one of the more robust codec +packages. + +In Node.js v4 and later `Buffer` objects are backed by `Uint8Array`s, so you +can freely pass them to TweetNaCl.js functions as arguments. The returned +objects are still `Uint8Array`s, so if you need `Buffer`s, you'll have to +convert them manually; make sure to convert using copying: `new Buffer(array)`, +instead of sharing: `new Buffer(array.buffer)`, because some functions return +subarrays of their buffers. + + +### Public-key authenticated encryption (box) + +Implements *curve25519-xsalsa20-poly1305*. + +#### nacl.box.keyPair() + +Generates a new random key pair for box and returns it as an object with +`publicKey` and `secretKey` members: + + { + publicKey: ..., // Uint8Array with 32-byte public key + secretKey: ... // Uint8Array with 32-byte secret key + } + + +#### nacl.box.keyPair.fromSecretKey(secretKey) + +Returns a key pair for box with public key corresponding to the given secret +key. + +#### nacl.box(message, nonce, theirPublicKey, mySecretKey) + +Encrypt and authenticates message using peer's public key, our secret key, and +the given nonce, which must be unique for each distinct message for a key pair. + +Returns an encrypted and authenticated message, which is +`nacl.box.overheadLength` longer than the original message. + +#### nacl.box.open(box, nonce, theirPublicKey, mySecretKey) + +Authenticates and decrypts the given box with peer's public key, our secret +key, and the given nonce. + +Returns the original message, or `false` if authentication fails. + +#### nacl.box.before(theirPublicKey, mySecretKey) + +Returns a precomputed shared key which can be used in `nacl.box.after` and +`nacl.box.open.after`. + +#### nacl.box.after(message, nonce, sharedKey) + +Same as `nacl.box`, but uses a shared key precomputed with `nacl.box.before`. + +#### nacl.box.open.after(box, nonce, sharedKey) + +Same as `nacl.box.open`, but uses a shared key precomputed with `nacl.box.before`. + +#### nacl.box.publicKeyLength = 32 + +Length of public key in bytes. + +#### nacl.box.secretKeyLength = 32 + +Length of secret key in bytes. + +#### nacl.box.sharedKeyLength = 32 + +Length of precomputed shared key in bytes. + +#### nacl.box.nonceLength = 24 + +Length of nonce in bytes. + +#### nacl.box.overheadLength = 16 + +Length of overhead added to box compared to original message. + + +### Secret-key authenticated encryption (secretbox) + +Implements *xsalsa20-poly1305*. + +#### nacl.secretbox(message, nonce, key) + +Encrypt and authenticates message using the key and the nonce. The nonce must +be unique for each distinct message for this key. + +Returns an encrypted and authenticated message, which is +`nacl.secretbox.overheadLength` longer than the original message. + +#### nacl.secretbox.open(box, nonce, key) + +Authenticates and decrypts the given secret box using the key and the nonce. + +Returns the original message, or `false` if authentication fails. + +#### nacl.secretbox.keyLength = 32 + +Length of key in bytes. + +#### nacl.secretbox.nonceLength = 24 + +Length of nonce in bytes. + +#### nacl.secretbox.overheadLength = 16 + +Length of overhead added to secret box compared to original message. + + +### Scalar multiplication + +Implements *curve25519*. + +#### nacl.scalarMult(n, p) + +Multiplies an integer `n` by a group element `p` and returns the resulting +group element. + +#### nacl.scalarMult.base(n) + +Multiplies an integer `n` by a standard group element and returns the resulting +group element. + +#### nacl.scalarMult.scalarLength = 32 + +Length of scalar in bytes. + +#### nacl.scalarMult.groupElementLength = 32 + +Length of group element in bytes. + + +### Signatures + +Implements [ed25519](http://ed25519.cr.yp.to). + +#### nacl.sign.keyPair() + +Generates new random key pair for signing and returns it as an object with +`publicKey` and `secretKey` members: + + { + publicKey: ..., // Uint8Array with 32-byte public key + secretKey: ... // Uint8Array with 64-byte secret key + } + +#### nacl.sign.keyPair.fromSecretKey(secretKey) + +Returns a signing key pair with public key corresponding to the given +64-byte secret key. The secret key must have been generated by +`nacl.sign.keyPair` or `nacl.sign.keyPair.fromSeed`. + +#### nacl.sign.keyPair.fromSeed(seed) + +Returns a new signing key pair generated deterministically from a 32-byte seed. +The seed must contain enough entropy to be secure. This method is not +recommended for general use: instead, use `nacl.sign.keyPair` to generate a new +key pair from a random seed. + +#### nacl.sign(message, secretKey) + +Signs the message using the secret key and returns a signed message. + +#### nacl.sign.open(signedMessage, publicKey) + +Verifies the signed message and returns the message without signature. + +Returns `null` if verification failed. + +#### nacl.sign.detached(message, secretKey) + +Signs the message using the secret key and returns a signature. + +#### nacl.sign.detached.verify(message, signature, publicKey) + +Verifies the signature for the message and returns `true` if verification +succeeded or `false` if it failed. + +#### nacl.sign.publicKeyLength = 32 + +Length of signing public key in bytes. + +#### nacl.sign.secretKeyLength = 64 + +Length of signing secret key in bytes. + +#### nacl.sign.seedLength = 32 + +Length of seed for `nacl.sign.keyPair.fromSeed` in bytes. + +#### nacl.sign.signatureLength = 64 + +Length of signature in bytes. + + +### Hashing + +Implements *SHA-512*. + +#### nacl.hash(message) + +Returns SHA-512 hash of the message. + +#### nacl.hash.hashLength = 64 + +Length of hash in bytes. + + +### Random bytes generation + +#### nacl.randomBytes(length) + +Returns a `Uint8Array` of the given length containing random bytes of +cryptographic quality. + +**Implementation note** + +TweetNaCl.js uses the following methods to generate random bytes, +depending on the platform it runs on: + +* `window.crypto.getRandomValues` (WebCrypto standard) +* `window.msCrypto.getRandomValues` (Internet Explorer 11) +* `crypto.randomBytes` (Node.js) + +If the platform doesn't provide a suitable PRNG, the following functions, +which require random numbers, will throw exception: + +* `nacl.randomBytes` +* `nacl.box.keyPair` +* `nacl.sign.keyPair` + +Other functions are deterministic and will continue working. + +If a platform you are targeting doesn't implement secure random number +generator, but you somehow have a cryptographically-strong source of entropy +(not `Math.random`!), and you know what you are doing, you can plug it into +TweetNaCl.js like this: + + nacl.setPRNG(function(x, n) { + // ... copy n random bytes into x ... + }); + +Note that `nacl.setPRNG` *completely replaces* internal random byte generator +with the one provided. + + +### Constant-time comparison + +#### nacl.verify(x, y) + +Compares `x` and `y` in constant time and returns `true` if their lengths are +non-zero and equal, and their contents are equal. + +Returns `false` if either of the arguments has zero length, or arguments have +different lengths, or their contents differ. + + +System requirements +------------------- + +TweetNaCl.js supports modern browsers that have a cryptographically secure +pseudorandom number generator and typed arrays, including the latest versions +of: + +* Chrome +* Firefox +* Safari (Mac, iOS) +* Internet Explorer 11 + +Other systems: + +* Node.js + + +Development and testing +------------------------ + +Install NPM modules needed for development: + + $ npm install + +To build minified versions: + + $ npm run build + +Tests use minified version, so make sure to rebuild it every time you change +`nacl.js` or `nacl-fast.js`. + +### Testing + +To run tests in Node.js: + + $ npm run test-node + +By default all tests described here work on `nacl.min.js`. To test other +versions, set environment variable `NACL_SRC` to the file name you want to test. +For example, the following command will test fast minified version: + + $ NACL_SRC=nacl-fast.min.js npm run test-node + +To run full suite of tests in Node.js, including comparing outputs of +JavaScript port to outputs of the original C version: + + $ npm run test-node-all + +To prepare tests for browsers: + + $ npm run build-test-browser + +and then open `test/browser/test.html` (or `test/browser/test-fast.html`) to +run them. + +To run headless browser tests with `tape-run` (powered by Electron): + + $ npm run test-browser + +(If you get `Error: spawn ENOENT`, install *xvfb*: `sudo apt-get install xvfb`.) + +To run tests in both Node and Electron: + + $ npm test + +### Benchmarking + +To run benchmarks in Node.js: + + $ npm run bench + $ NACL_SRC=nacl-fast.min.js npm run bench + +To run benchmarks in a browser, open `test/benchmark/bench.html` (or +`test/benchmark/bench-fast.html`). + + +Benchmarks +---------- + +For reference, here are benchmarks from MacBook Pro (Retina, 13-inch, Mid 2014) +laptop with 2.6 GHz Intel Core i5 CPU (Intel) in Chrome 53/OS X and Xiaomi Redmi +Note 3 smartphone with 1.8 GHz Qualcomm Snapdragon 650 64-bit CPU (ARM) in +Chrome 52/Android: + +| | nacl.js Intel | nacl-fast.js Intel | nacl.js ARM | nacl-fast.js ARM | +| ------------- |:-------------:|:-------------------:|:-------------:|:-----------------:| +| salsa20 | 1.3 MB/s | 128 MB/s | 0.4 MB/s | 43 MB/s | +| poly1305 | 13 MB/s | 171 MB/s | 4 MB/s | 52 MB/s | +| hash | 4 MB/s | 34 MB/s | 0.9 MB/s | 12 MB/s | +| secretbox 1K | 1113 op/s | 57583 op/s | 334 op/s | 14227 op/s | +| box 1K | 145 op/s | 718 op/s | 37 op/s | 368 op/s | +| scalarMult | 171 op/s | 733 op/s | 56 op/s | 380 op/s | +| sign | 77 op/s | 200 op/s | 20 op/s | 61 op/s | +| sign.open | 39 op/s | 102 op/s | 11 op/s | 31 op/s | + +(You can run benchmarks on your devices by clicking on the links at the bottom +of the [home page](https://tweetnacl.js.org)). + +In short, with *nacl-fast.js* and 1024-byte messages you can expect to encrypt and +authenticate more than 57000 messages per second on a typical laptop or more than +14000 messages per second on a $170 smartphone, sign about 200 and verify 100 +messages per second on a laptop or 60 and 30 messages per second on a smartphone, +per CPU core (with Web Workers you can do these operations in parallel), +which is good enough for most applications. + + +Contributors +------------ + +See AUTHORS.md file. + + +Third-party libraries based on TweetNaCl.js +------------------------------------------- + +* [forward-secrecy](https://github.com/alax/forward-secrecy) — Axolotl ratchet implementation +* [nacl-stream](https://github.com/dchest/nacl-stream-js) - streaming encryption +* [tweetnacl-auth-js](https://github.com/dchest/tweetnacl-auth-js) — implementation of [`crypto_auth`](http://nacl.cr.yp.to/auth.html) +* [chloride](https://github.com/dominictarr/chloride) - unified API for various NaCl modules + + +Who uses it +----------- + +Some notable users of TweetNaCl.js: + +* [miniLock](http://minilock.io/) +* [Stellar](https://www.stellar.org/) diff --git a/reverse_engineering/node_modules/tweetnacl/nacl-fast.js b/reverse_engineering/node_modules/tweetnacl/nacl-fast.js new file mode 100644 index 0000000..5e4562f --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/nacl-fast.js @@ -0,0 +1,2388 @@ +(function(nacl) { +'use strict'; + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; +}; + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + +var _0 = new Uint8Array(16); +var _9 = new Uint8Array(32); _9[0] = 9; + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + +function ts64(x, i, h, l) { + x[i] = (h >> 24) & 0xff; + x[i+1] = (h >> 16) & 0xff; + x[i+2] = (h >> 8) & 0xff; + x[i+3] = h & 0xff; + x[i+4] = (l >> 24) & 0xff; + x[i+5] = (l >> 16) & 0xff; + x[i+6] = (l >> 8) & 0xff; + x[i+7] = l & 0xff; +} + +function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; +} + +function crypto_verify_16(x, xi, y, yi) { + return vn(x,xi,y,yi,16); +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); +} + +function core_salsa20(o, p, k, c) { + var j0 = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24, + j1 = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24, + j2 = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24, + j3 = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24, + j4 = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24, + j5 = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24, + j6 = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24, + j7 = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24, + j8 = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24, + j9 = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24, + j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24, + j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24, + j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24, + j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24, + j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24, + j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24; + + var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, + x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, + x15 = j15, u; + + for (var i = 0; i < 20; i += 2) { + u = x0 + x12 | 0; + x4 ^= u<<7 | u>>>(32-7); + u = x4 + x0 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x4 | 0; + x12 ^= u<<13 | u>>>(32-13); + u = x12 + x8 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x1 | 0; + x9 ^= u<<7 | u>>>(32-7); + u = x9 + x5 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x9 | 0; + x1 ^= u<<13 | u>>>(32-13); + u = x1 + x13 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x6 | 0; + x14 ^= u<<7 | u>>>(32-7); + u = x14 + x10 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x14 | 0; + x6 ^= u<<13 | u>>>(32-13); + u = x6 + x2 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x11 | 0; + x3 ^= u<<7 | u>>>(32-7); + u = x3 + x15 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x3 | 0; + x11 ^= u<<13 | u>>>(32-13); + u = x11 + x7 | 0; + x15 ^= u<<18 | u>>>(32-18); + + u = x0 + x3 | 0; + x1 ^= u<<7 | u>>>(32-7); + u = x1 + x0 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x1 | 0; + x3 ^= u<<13 | u>>>(32-13); + u = x3 + x2 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x4 | 0; + x6 ^= u<<7 | u>>>(32-7); + u = x6 + x5 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x6 | 0; + x4 ^= u<<13 | u>>>(32-13); + u = x4 + x7 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x9 | 0; + x11 ^= u<<7 | u>>>(32-7); + u = x11 + x10 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x11 | 0; + x9 ^= u<<13 | u>>>(32-13); + u = x9 + x8 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x14 | 0; + x12 ^= u<<7 | u>>>(32-7); + u = x12 + x15 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x12 | 0; + x14 ^= u<<13 | u>>>(32-13); + u = x14 + x13 | 0; + x15 ^= u<<18 | u>>>(32-18); + } + x0 = x0 + j0 | 0; + x1 = x1 + j1 | 0; + x2 = x2 + j2 | 0; + x3 = x3 + j3 | 0; + x4 = x4 + j4 | 0; + x5 = x5 + j5 | 0; + x6 = x6 + j6 | 0; + x7 = x7 + j7 | 0; + x8 = x8 + j8 | 0; + x9 = x9 + j9 | 0; + x10 = x10 + j10 | 0; + x11 = x11 + j11 | 0; + x12 = x12 + j12 | 0; + x13 = x13 + j13 | 0; + x14 = x14 + j14 | 0; + x15 = x15 + j15 | 0; + + o[ 0] = x0 >>> 0 & 0xff; + o[ 1] = x0 >>> 8 & 0xff; + o[ 2] = x0 >>> 16 & 0xff; + o[ 3] = x0 >>> 24 & 0xff; + + o[ 4] = x1 >>> 0 & 0xff; + o[ 5] = x1 >>> 8 & 0xff; + o[ 6] = x1 >>> 16 & 0xff; + o[ 7] = x1 >>> 24 & 0xff; + + o[ 8] = x2 >>> 0 & 0xff; + o[ 9] = x2 >>> 8 & 0xff; + o[10] = x2 >>> 16 & 0xff; + o[11] = x2 >>> 24 & 0xff; + + o[12] = x3 >>> 0 & 0xff; + o[13] = x3 >>> 8 & 0xff; + o[14] = x3 >>> 16 & 0xff; + o[15] = x3 >>> 24 & 0xff; + + o[16] = x4 >>> 0 & 0xff; + o[17] = x4 >>> 8 & 0xff; + o[18] = x4 >>> 16 & 0xff; + o[19] = x4 >>> 24 & 0xff; + + o[20] = x5 >>> 0 & 0xff; + o[21] = x5 >>> 8 & 0xff; + o[22] = x5 >>> 16 & 0xff; + o[23] = x5 >>> 24 & 0xff; + + o[24] = x6 >>> 0 & 0xff; + o[25] = x6 >>> 8 & 0xff; + o[26] = x6 >>> 16 & 0xff; + o[27] = x6 >>> 24 & 0xff; + + o[28] = x7 >>> 0 & 0xff; + o[29] = x7 >>> 8 & 0xff; + o[30] = x7 >>> 16 & 0xff; + o[31] = x7 >>> 24 & 0xff; + + o[32] = x8 >>> 0 & 0xff; + o[33] = x8 >>> 8 & 0xff; + o[34] = x8 >>> 16 & 0xff; + o[35] = x8 >>> 24 & 0xff; + + o[36] = x9 >>> 0 & 0xff; + o[37] = x9 >>> 8 & 0xff; + o[38] = x9 >>> 16 & 0xff; + o[39] = x9 >>> 24 & 0xff; + + o[40] = x10 >>> 0 & 0xff; + o[41] = x10 >>> 8 & 0xff; + o[42] = x10 >>> 16 & 0xff; + o[43] = x10 >>> 24 & 0xff; + + o[44] = x11 >>> 0 & 0xff; + o[45] = x11 >>> 8 & 0xff; + o[46] = x11 >>> 16 & 0xff; + o[47] = x11 >>> 24 & 0xff; + + o[48] = x12 >>> 0 & 0xff; + o[49] = x12 >>> 8 & 0xff; + o[50] = x12 >>> 16 & 0xff; + o[51] = x12 >>> 24 & 0xff; + + o[52] = x13 >>> 0 & 0xff; + o[53] = x13 >>> 8 & 0xff; + o[54] = x13 >>> 16 & 0xff; + o[55] = x13 >>> 24 & 0xff; + + o[56] = x14 >>> 0 & 0xff; + o[57] = x14 >>> 8 & 0xff; + o[58] = x14 >>> 16 & 0xff; + o[59] = x14 >>> 24 & 0xff; + + o[60] = x15 >>> 0 & 0xff; + o[61] = x15 >>> 8 & 0xff; + o[62] = x15 >>> 16 & 0xff; + o[63] = x15 >>> 24 & 0xff; +} + +function core_hsalsa20(o,p,k,c) { + var j0 = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24, + j1 = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24, + j2 = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24, + j3 = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24, + j4 = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24, + j5 = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24, + j6 = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24, + j7 = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24, + j8 = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24, + j9 = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24, + j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24, + j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24, + j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24, + j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24, + j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24, + j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24; + + var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, + x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, + x15 = j15, u; + + for (var i = 0; i < 20; i += 2) { + u = x0 + x12 | 0; + x4 ^= u<<7 | u>>>(32-7); + u = x4 + x0 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x4 | 0; + x12 ^= u<<13 | u>>>(32-13); + u = x12 + x8 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x1 | 0; + x9 ^= u<<7 | u>>>(32-7); + u = x9 + x5 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x9 | 0; + x1 ^= u<<13 | u>>>(32-13); + u = x1 + x13 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x6 | 0; + x14 ^= u<<7 | u>>>(32-7); + u = x14 + x10 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x14 | 0; + x6 ^= u<<13 | u>>>(32-13); + u = x6 + x2 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x11 | 0; + x3 ^= u<<7 | u>>>(32-7); + u = x3 + x15 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x3 | 0; + x11 ^= u<<13 | u>>>(32-13); + u = x11 + x7 | 0; + x15 ^= u<<18 | u>>>(32-18); + + u = x0 + x3 | 0; + x1 ^= u<<7 | u>>>(32-7); + u = x1 + x0 | 0; + x2 ^= u<<9 | u>>>(32-9); + u = x2 + x1 | 0; + x3 ^= u<<13 | u>>>(32-13); + u = x3 + x2 | 0; + x0 ^= u<<18 | u>>>(32-18); + + u = x5 + x4 | 0; + x6 ^= u<<7 | u>>>(32-7); + u = x6 + x5 | 0; + x7 ^= u<<9 | u>>>(32-9); + u = x7 + x6 | 0; + x4 ^= u<<13 | u>>>(32-13); + u = x4 + x7 | 0; + x5 ^= u<<18 | u>>>(32-18); + + u = x10 + x9 | 0; + x11 ^= u<<7 | u>>>(32-7); + u = x11 + x10 | 0; + x8 ^= u<<9 | u>>>(32-9); + u = x8 + x11 | 0; + x9 ^= u<<13 | u>>>(32-13); + u = x9 + x8 | 0; + x10 ^= u<<18 | u>>>(32-18); + + u = x15 + x14 | 0; + x12 ^= u<<7 | u>>>(32-7); + u = x12 + x15 | 0; + x13 ^= u<<9 | u>>>(32-9); + u = x13 + x12 | 0; + x14 ^= u<<13 | u>>>(32-13); + u = x14 + x13 | 0; + x15 ^= u<<18 | u>>>(32-18); + } + + o[ 0] = x0 >>> 0 & 0xff; + o[ 1] = x0 >>> 8 & 0xff; + o[ 2] = x0 >>> 16 & 0xff; + o[ 3] = x0 >>> 24 & 0xff; + + o[ 4] = x5 >>> 0 & 0xff; + o[ 5] = x5 >>> 8 & 0xff; + o[ 6] = x5 >>> 16 & 0xff; + o[ 7] = x5 >>> 24 & 0xff; + + o[ 8] = x10 >>> 0 & 0xff; + o[ 9] = x10 >>> 8 & 0xff; + o[10] = x10 >>> 16 & 0xff; + o[11] = x10 >>> 24 & 0xff; + + o[12] = x15 >>> 0 & 0xff; + o[13] = x15 >>> 8 & 0xff; + o[14] = x15 >>> 16 & 0xff; + o[15] = x15 >>> 24 & 0xff; + + o[16] = x6 >>> 0 & 0xff; + o[17] = x6 >>> 8 & 0xff; + o[18] = x6 >>> 16 & 0xff; + o[19] = x6 >>> 24 & 0xff; + + o[20] = x7 >>> 0 & 0xff; + o[21] = x7 >>> 8 & 0xff; + o[22] = x7 >>> 16 & 0xff; + o[23] = x7 >>> 24 & 0xff; + + o[24] = x8 >>> 0 & 0xff; + o[25] = x8 >>> 8 & 0xff; + o[26] = x8 >>> 16 & 0xff; + o[27] = x8 >>> 24 & 0xff; + + o[28] = x9 >>> 0 & 0xff; + o[29] = x9 >>> 8 & 0xff; + o[30] = x9 >>> 16 & 0xff; + o[31] = x9 >>> 24 & 0xff; +} + +function crypto_core_salsa20(out,inp,k,c) { + core_salsa20(out,inp,k,c); +} + +function crypto_core_hsalsa20(out,inp,k,c) { + core_hsalsa20(out,inp,k,c); +} + +var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]); + // "expand 32-byte k" + +function crypto_stream_salsa20_xor(c,cpos,m,mpos,b,n,k) { + var z = new Uint8Array(16), x = new Uint8Array(64); + var u, i; + for (i = 0; i < 16; i++) z[i] = 0; + for (i = 0; i < 8; i++) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < 64; i++) c[cpos+i] = m[mpos+i] ^ x[i]; + u = 1; + for (i = 8; i < 16; i++) { + u = u + (z[i] & 0xff) | 0; + z[i] = u & 0xff; + u >>>= 8; + } + b -= 64; + cpos += 64; + mpos += 64; + } + if (b > 0) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < b; i++) c[cpos+i] = m[mpos+i] ^ x[i]; + } + return 0; +} + +function crypto_stream_salsa20(c,cpos,b,n,k) { + var z = new Uint8Array(16), x = new Uint8Array(64); + var u, i; + for (i = 0; i < 16; i++) z[i] = 0; + for (i = 0; i < 8; i++) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < 64; i++) c[cpos+i] = x[i]; + u = 1; + for (i = 8; i < 16; i++) { + u = u + (z[i] & 0xff) | 0; + z[i] = u & 0xff; + u >>>= 8; + } + b -= 64; + cpos += 64; + } + if (b > 0) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < b; i++) c[cpos+i] = x[i]; + } + return 0; +} + +function crypto_stream(c,cpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + var sn = new Uint8Array(8); + for (var i = 0; i < 8; i++) sn[i] = n[i+16]; + return crypto_stream_salsa20(c,cpos,d,sn,s); +} + +function crypto_stream_xor(c,cpos,m,mpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + var sn = new Uint8Array(8); + for (var i = 0; i < 8; i++) sn[i] = n[i+16]; + return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,sn,s); +} + +/* +* Port of Andrew Moon's Poly1305-donna-16. Public domain. +* https://github.com/floodyberry/poly1305-donna +*/ + +var poly1305 = function(key) { + this.buffer = new Uint8Array(16); + this.r = new Uint16Array(10); + this.h = new Uint16Array(10); + this.pad = new Uint16Array(8); + this.leftover = 0; + this.fin = 0; + + var t0, t1, t2, t3, t4, t5, t6, t7; + + t0 = key[ 0] & 0xff | (key[ 1] & 0xff) << 8; this.r[0] = ( t0 ) & 0x1fff; + t1 = key[ 2] & 0xff | (key[ 3] & 0xff) << 8; this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff; + t2 = key[ 4] & 0xff | (key[ 5] & 0xff) << 8; this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03; + t3 = key[ 6] & 0xff | (key[ 7] & 0xff) << 8; this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff; + t4 = key[ 8] & 0xff | (key[ 9] & 0xff) << 8; this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff; + this.r[5] = ((t4 >>> 1)) & 0x1ffe; + t5 = key[10] & 0xff | (key[11] & 0xff) << 8; this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff; + t6 = key[12] & 0xff | (key[13] & 0xff) << 8; this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81; + t7 = key[14] & 0xff | (key[15] & 0xff) << 8; this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff; + this.r[9] = ((t7 >>> 5)) & 0x007f; + + this.pad[0] = key[16] & 0xff | (key[17] & 0xff) << 8; + this.pad[1] = key[18] & 0xff | (key[19] & 0xff) << 8; + this.pad[2] = key[20] & 0xff | (key[21] & 0xff) << 8; + this.pad[3] = key[22] & 0xff | (key[23] & 0xff) << 8; + this.pad[4] = key[24] & 0xff | (key[25] & 0xff) << 8; + this.pad[5] = key[26] & 0xff | (key[27] & 0xff) << 8; + this.pad[6] = key[28] & 0xff | (key[29] & 0xff) << 8; + this.pad[7] = key[30] & 0xff | (key[31] & 0xff) << 8; +}; + +poly1305.prototype.blocks = function(m, mpos, bytes) { + var hibit = this.fin ? 0 : (1 << 11); + var t0, t1, t2, t3, t4, t5, t6, t7, c; + var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9; + + var h0 = this.h[0], + h1 = this.h[1], + h2 = this.h[2], + h3 = this.h[3], + h4 = this.h[4], + h5 = this.h[5], + h6 = this.h[6], + h7 = this.h[7], + h8 = this.h[8], + h9 = this.h[9]; + + var r0 = this.r[0], + r1 = this.r[1], + r2 = this.r[2], + r3 = this.r[3], + r4 = this.r[4], + r5 = this.r[5], + r6 = this.r[6], + r7 = this.r[7], + r8 = this.r[8], + r9 = this.r[9]; + + while (bytes >= 16) { + t0 = m[mpos+ 0] & 0xff | (m[mpos+ 1] & 0xff) << 8; h0 += ( t0 ) & 0x1fff; + t1 = m[mpos+ 2] & 0xff | (m[mpos+ 3] & 0xff) << 8; h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff; + t2 = m[mpos+ 4] & 0xff | (m[mpos+ 5] & 0xff) << 8; h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff; + t3 = m[mpos+ 6] & 0xff | (m[mpos+ 7] & 0xff) << 8; h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff; + t4 = m[mpos+ 8] & 0xff | (m[mpos+ 9] & 0xff) << 8; h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff; + h5 += ((t4 >>> 1)) & 0x1fff; + t5 = m[mpos+10] & 0xff | (m[mpos+11] & 0xff) << 8; h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff; + t6 = m[mpos+12] & 0xff | (m[mpos+13] & 0xff) << 8; h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff; + t7 = m[mpos+14] & 0xff | (m[mpos+15] & 0xff) << 8; h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff; + h9 += ((t7 >>> 5)) | hibit; + + c = 0; + + d0 = c; + d0 += h0 * r0; + d0 += h1 * (5 * r9); + d0 += h2 * (5 * r8); + d0 += h3 * (5 * r7); + d0 += h4 * (5 * r6); + c = (d0 >>> 13); d0 &= 0x1fff; + d0 += h5 * (5 * r5); + d0 += h6 * (5 * r4); + d0 += h7 * (5 * r3); + d0 += h8 * (5 * r2); + d0 += h9 * (5 * r1); + c += (d0 >>> 13); d0 &= 0x1fff; + + d1 = c; + d1 += h0 * r1; + d1 += h1 * r0; + d1 += h2 * (5 * r9); + d1 += h3 * (5 * r8); + d1 += h4 * (5 * r7); + c = (d1 >>> 13); d1 &= 0x1fff; + d1 += h5 * (5 * r6); + d1 += h6 * (5 * r5); + d1 += h7 * (5 * r4); + d1 += h8 * (5 * r3); + d1 += h9 * (5 * r2); + c += (d1 >>> 13); d1 &= 0x1fff; + + d2 = c; + d2 += h0 * r2; + d2 += h1 * r1; + d2 += h2 * r0; + d2 += h3 * (5 * r9); + d2 += h4 * (5 * r8); + c = (d2 >>> 13); d2 &= 0x1fff; + d2 += h5 * (5 * r7); + d2 += h6 * (5 * r6); + d2 += h7 * (5 * r5); + d2 += h8 * (5 * r4); + d2 += h9 * (5 * r3); + c += (d2 >>> 13); d2 &= 0x1fff; + + d3 = c; + d3 += h0 * r3; + d3 += h1 * r2; + d3 += h2 * r1; + d3 += h3 * r0; + d3 += h4 * (5 * r9); + c = (d3 >>> 13); d3 &= 0x1fff; + d3 += h5 * (5 * r8); + d3 += h6 * (5 * r7); + d3 += h7 * (5 * r6); + d3 += h8 * (5 * r5); + d3 += h9 * (5 * r4); + c += (d3 >>> 13); d3 &= 0x1fff; + + d4 = c; + d4 += h0 * r4; + d4 += h1 * r3; + d4 += h2 * r2; + d4 += h3 * r1; + d4 += h4 * r0; + c = (d4 >>> 13); d4 &= 0x1fff; + d4 += h5 * (5 * r9); + d4 += h6 * (5 * r8); + d4 += h7 * (5 * r7); + d4 += h8 * (5 * r6); + d4 += h9 * (5 * r5); + c += (d4 >>> 13); d4 &= 0x1fff; + + d5 = c; + d5 += h0 * r5; + d5 += h1 * r4; + d5 += h2 * r3; + d5 += h3 * r2; + d5 += h4 * r1; + c = (d5 >>> 13); d5 &= 0x1fff; + d5 += h5 * r0; + d5 += h6 * (5 * r9); + d5 += h7 * (5 * r8); + d5 += h8 * (5 * r7); + d5 += h9 * (5 * r6); + c += (d5 >>> 13); d5 &= 0x1fff; + + d6 = c; + d6 += h0 * r6; + d6 += h1 * r5; + d6 += h2 * r4; + d6 += h3 * r3; + d6 += h4 * r2; + c = (d6 >>> 13); d6 &= 0x1fff; + d6 += h5 * r1; + d6 += h6 * r0; + d6 += h7 * (5 * r9); + d6 += h8 * (5 * r8); + d6 += h9 * (5 * r7); + c += (d6 >>> 13); d6 &= 0x1fff; + + d7 = c; + d7 += h0 * r7; + d7 += h1 * r6; + d7 += h2 * r5; + d7 += h3 * r4; + d7 += h4 * r3; + c = (d7 >>> 13); d7 &= 0x1fff; + d7 += h5 * r2; + d7 += h6 * r1; + d7 += h7 * r0; + d7 += h8 * (5 * r9); + d7 += h9 * (5 * r8); + c += (d7 >>> 13); d7 &= 0x1fff; + + d8 = c; + d8 += h0 * r8; + d8 += h1 * r7; + d8 += h2 * r6; + d8 += h3 * r5; + d8 += h4 * r4; + c = (d8 >>> 13); d8 &= 0x1fff; + d8 += h5 * r3; + d8 += h6 * r2; + d8 += h7 * r1; + d8 += h8 * r0; + d8 += h9 * (5 * r9); + c += (d8 >>> 13); d8 &= 0x1fff; + + d9 = c; + d9 += h0 * r9; + d9 += h1 * r8; + d9 += h2 * r7; + d9 += h3 * r6; + d9 += h4 * r5; + c = (d9 >>> 13); d9 &= 0x1fff; + d9 += h5 * r4; + d9 += h6 * r3; + d9 += h7 * r2; + d9 += h8 * r1; + d9 += h9 * r0; + c += (d9 >>> 13); d9 &= 0x1fff; + + c = (((c << 2) + c)) | 0; + c = (c + d0) | 0; + d0 = c & 0x1fff; + c = (c >>> 13); + d1 += c; + + h0 = d0; + h1 = d1; + h2 = d2; + h3 = d3; + h4 = d4; + h5 = d5; + h6 = d6; + h7 = d7; + h8 = d8; + h9 = d9; + + mpos += 16; + bytes -= 16; + } + this.h[0] = h0; + this.h[1] = h1; + this.h[2] = h2; + this.h[3] = h3; + this.h[4] = h4; + this.h[5] = h5; + this.h[6] = h6; + this.h[7] = h7; + this.h[8] = h8; + this.h[9] = h9; +}; + +poly1305.prototype.finish = function(mac, macpos) { + var g = new Uint16Array(10); + var c, mask, f, i; + + if (this.leftover) { + i = this.leftover; + this.buffer[i++] = 1; + for (; i < 16; i++) this.buffer[i] = 0; + this.fin = 1; + this.blocks(this.buffer, 0, 16); + } + + c = this.h[1] >>> 13; + this.h[1] &= 0x1fff; + for (i = 2; i < 10; i++) { + this.h[i] += c; + c = this.h[i] >>> 13; + this.h[i] &= 0x1fff; + } + this.h[0] += (c * 5); + c = this.h[0] >>> 13; + this.h[0] &= 0x1fff; + this.h[1] += c; + c = this.h[1] >>> 13; + this.h[1] &= 0x1fff; + this.h[2] += c; + + g[0] = this.h[0] + 5; + c = g[0] >>> 13; + g[0] &= 0x1fff; + for (i = 1; i < 10; i++) { + g[i] = this.h[i] + c; + c = g[i] >>> 13; + g[i] &= 0x1fff; + } + g[9] -= (1 << 13); + + mask = (c ^ 1) - 1; + for (i = 0; i < 10; i++) g[i] &= mask; + mask = ~mask; + for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i]; + + this.h[0] = ((this.h[0] ) | (this.h[1] << 13) ) & 0xffff; + this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10) ) & 0xffff; + this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7) ) & 0xffff; + this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4) ) & 0xffff; + this.h[4] = ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff; + this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11) ) & 0xffff; + this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8) ) & 0xffff; + this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5) ) & 0xffff; + + f = this.h[0] + this.pad[0]; + this.h[0] = f & 0xffff; + for (i = 1; i < 8; i++) { + f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0; + this.h[i] = f & 0xffff; + } + + mac[macpos+ 0] = (this.h[0] >>> 0) & 0xff; + mac[macpos+ 1] = (this.h[0] >>> 8) & 0xff; + mac[macpos+ 2] = (this.h[1] >>> 0) & 0xff; + mac[macpos+ 3] = (this.h[1] >>> 8) & 0xff; + mac[macpos+ 4] = (this.h[2] >>> 0) & 0xff; + mac[macpos+ 5] = (this.h[2] >>> 8) & 0xff; + mac[macpos+ 6] = (this.h[3] >>> 0) & 0xff; + mac[macpos+ 7] = (this.h[3] >>> 8) & 0xff; + mac[macpos+ 8] = (this.h[4] >>> 0) & 0xff; + mac[macpos+ 9] = (this.h[4] >>> 8) & 0xff; + mac[macpos+10] = (this.h[5] >>> 0) & 0xff; + mac[macpos+11] = (this.h[5] >>> 8) & 0xff; + mac[macpos+12] = (this.h[6] >>> 0) & 0xff; + mac[macpos+13] = (this.h[6] >>> 8) & 0xff; + mac[macpos+14] = (this.h[7] >>> 0) & 0xff; + mac[macpos+15] = (this.h[7] >>> 8) & 0xff; +}; + +poly1305.prototype.update = function(m, mpos, bytes) { + var i, want; + + if (this.leftover) { + want = (16 - this.leftover); + if (want > bytes) + want = bytes; + for (i = 0; i < want; i++) + this.buffer[this.leftover + i] = m[mpos+i]; + bytes -= want; + mpos += want; + this.leftover += want; + if (this.leftover < 16) + return; + this.blocks(this.buffer, 0, 16); + this.leftover = 0; + } + + if (bytes >= 16) { + want = bytes - (bytes % 16); + this.blocks(m, mpos, want); + mpos += want; + bytes -= want; + } + + if (bytes) { + for (i = 0; i < bytes; i++) + this.buffer[this.leftover + i] = m[mpos+i]; + this.leftover += bytes; + } +}; + +function crypto_onetimeauth(out, outpos, m, mpos, n, k) { + var s = new poly1305(k); + s.update(m, mpos, n); + s.finish(out, outpos); + return 0; +} + +function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) { + var x = new Uint8Array(16); + crypto_onetimeauth(x,0,m,mpos,n,k); + return crypto_verify_16(h,hpos,x,0); +} + +function crypto_secretbox(c,m,d,n,k) { + var i; + if (d < 32) return -1; + crypto_stream_xor(c,0,m,0,d,n,k); + crypto_onetimeauth(c, 16, c, 32, d - 32, c); + for (i = 0; i < 16; i++) c[i] = 0; + return 0; +} + +function crypto_secretbox_open(m,c,d,n,k) { + var i; + var x = new Uint8Array(32); + if (d < 32) return -1; + crypto_stream(x,0,32,n,k); + if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1; + crypto_stream_xor(m,0,c,0,d,n,k); + for (i = 0; i < 32; i++) m[i] = 0; + return 0; +} + +function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; +} + +function car25519(o) { + var i, v, c = 1; + for (i = 0; i < 16; i++) { + v = o[i] + c + 65535; + c = Math.floor(v / 65536); + o[i] = v - c * 65536; + } + o[0] += c-1 + 37 * (c-1); +} + +function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); +} + +function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; +} + +function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; +} + +function A(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; +} + +function Z(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; +} + +function M(o, a, b) { + var v, c, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, + t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, + t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8], + b9 = b[9], + b10 = b[10], + b11 = b[11], + b12 = b[12], + b13 = b[13], + b14 = b[14], + b15 = b[15]; + + v = a[0]; + t0 += v * b0; + t1 += v * b1; + t2 += v * b2; + t3 += v * b3; + t4 += v * b4; + t5 += v * b5; + t6 += v * b6; + t7 += v * b7; + t8 += v * b8; + t9 += v * b9; + t10 += v * b10; + t11 += v * b11; + t12 += v * b12; + t13 += v * b13; + t14 += v * b14; + t15 += v * b15; + v = a[1]; + t1 += v * b0; + t2 += v * b1; + t3 += v * b2; + t4 += v * b3; + t5 += v * b4; + t6 += v * b5; + t7 += v * b6; + t8 += v * b7; + t9 += v * b8; + t10 += v * b9; + t11 += v * b10; + t12 += v * b11; + t13 += v * b12; + t14 += v * b13; + t15 += v * b14; + t16 += v * b15; + v = a[2]; + t2 += v * b0; + t3 += v * b1; + t4 += v * b2; + t5 += v * b3; + t6 += v * b4; + t7 += v * b5; + t8 += v * b6; + t9 += v * b7; + t10 += v * b8; + t11 += v * b9; + t12 += v * b10; + t13 += v * b11; + t14 += v * b12; + t15 += v * b13; + t16 += v * b14; + t17 += v * b15; + v = a[3]; + t3 += v * b0; + t4 += v * b1; + t5 += v * b2; + t6 += v * b3; + t7 += v * b4; + t8 += v * b5; + t9 += v * b6; + t10 += v * b7; + t11 += v * b8; + t12 += v * b9; + t13 += v * b10; + t14 += v * b11; + t15 += v * b12; + t16 += v * b13; + t17 += v * b14; + t18 += v * b15; + v = a[4]; + t4 += v * b0; + t5 += v * b1; + t6 += v * b2; + t7 += v * b3; + t8 += v * b4; + t9 += v * b5; + t10 += v * b6; + t11 += v * b7; + t12 += v * b8; + t13 += v * b9; + t14 += v * b10; + t15 += v * b11; + t16 += v * b12; + t17 += v * b13; + t18 += v * b14; + t19 += v * b15; + v = a[5]; + t5 += v * b0; + t6 += v * b1; + t7 += v * b2; + t8 += v * b3; + t9 += v * b4; + t10 += v * b5; + t11 += v * b6; + t12 += v * b7; + t13 += v * b8; + t14 += v * b9; + t15 += v * b10; + t16 += v * b11; + t17 += v * b12; + t18 += v * b13; + t19 += v * b14; + t20 += v * b15; + v = a[6]; + t6 += v * b0; + t7 += v * b1; + t8 += v * b2; + t9 += v * b3; + t10 += v * b4; + t11 += v * b5; + t12 += v * b6; + t13 += v * b7; + t14 += v * b8; + t15 += v * b9; + t16 += v * b10; + t17 += v * b11; + t18 += v * b12; + t19 += v * b13; + t20 += v * b14; + t21 += v * b15; + v = a[7]; + t7 += v * b0; + t8 += v * b1; + t9 += v * b2; + t10 += v * b3; + t11 += v * b4; + t12 += v * b5; + t13 += v * b6; + t14 += v * b7; + t15 += v * b8; + t16 += v * b9; + t17 += v * b10; + t18 += v * b11; + t19 += v * b12; + t20 += v * b13; + t21 += v * b14; + t22 += v * b15; + v = a[8]; + t8 += v * b0; + t9 += v * b1; + t10 += v * b2; + t11 += v * b3; + t12 += v * b4; + t13 += v * b5; + t14 += v * b6; + t15 += v * b7; + t16 += v * b8; + t17 += v * b9; + t18 += v * b10; + t19 += v * b11; + t20 += v * b12; + t21 += v * b13; + t22 += v * b14; + t23 += v * b15; + v = a[9]; + t9 += v * b0; + t10 += v * b1; + t11 += v * b2; + t12 += v * b3; + t13 += v * b4; + t14 += v * b5; + t15 += v * b6; + t16 += v * b7; + t17 += v * b8; + t18 += v * b9; + t19 += v * b10; + t20 += v * b11; + t21 += v * b12; + t22 += v * b13; + t23 += v * b14; + t24 += v * b15; + v = a[10]; + t10 += v * b0; + t11 += v * b1; + t12 += v * b2; + t13 += v * b3; + t14 += v * b4; + t15 += v * b5; + t16 += v * b6; + t17 += v * b7; + t18 += v * b8; + t19 += v * b9; + t20 += v * b10; + t21 += v * b11; + t22 += v * b12; + t23 += v * b13; + t24 += v * b14; + t25 += v * b15; + v = a[11]; + t11 += v * b0; + t12 += v * b1; + t13 += v * b2; + t14 += v * b3; + t15 += v * b4; + t16 += v * b5; + t17 += v * b6; + t18 += v * b7; + t19 += v * b8; + t20 += v * b9; + t21 += v * b10; + t22 += v * b11; + t23 += v * b12; + t24 += v * b13; + t25 += v * b14; + t26 += v * b15; + v = a[12]; + t12 += v * b0; + t13 += v * b1; + t14 += v * b2; + t15 += v * b3; + t16 += v * b4; + t17 += v * b5; + t18 += v * b6; + t19 += v * b7; + t20 += v * b8; + t21 += v * b9; + t22 += v * b10; + t23 += v * b11; + t24 += v * b12; + t25 += v * b13; + t26 += v * b14; + t27 += v * b15; + v = a[13]; + t13 += v * b0; + t14 += v * b1; + t15 += v * b2; + t16 += v * b3; + t17 += v * b4; + t18 += v * b5; + t19 += v * b6; + t20 += v * b7; + t21 += v * b8; + t22 += v * b9; + t23 += v * b10; + t24 += v * b11; + t25 += v * b12; + t26 += v * b13; + t27 += v * b14; + t28 += v * b15; + v = a[14]; + t14 += v * b0; + t15 += v * b1; + t16 += v * b2; + t17 += v * b3; + t18 += v * b4; + t19 += v * b5; + t20 += v * b6; + t21 += v * b7; + t22 += v * b8; + t23 += v * b9; + t24 += v * b10; + t25 += v * b11; + t26 += v * b12; + t27 += v * b13; + t28 += v * b14; + t29 += v * b15; + v = a[15]; + t15 += v * b0; + t16 += v * b1; + t17 += v * b2; + t18 += v * b3; + t19 += v * b4; + t20 += v * b5; + t21 += v * b6; + t22 += v * b7; + t23 += v * b8; + t24 += v * b9; + t25 += v * b10; + t26 += v * b11; + t27 += v * b12; + t28 += v * b13; + t29 += v * b14; + t30 += v * b15; + + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function crypto_box_beforenm(k, y, x) { + var s = new Uint8Array(32); + crypto_scalarmult(s, x, y); + return crypto_core_hsalsa20(k, _0, s, sigma); +} + +var crypto_box_afternm = crypto_secretbox; +var crypto_box_open_afternm = crypto_secretbox_open; + +function crypto_box(c, m, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_afternm(c, m, d, n, k); +} + +function crypto_box_open(m, c, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_open_afternm(m, c, d, n, k); +} + +var K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +]; + +function crypto_hashblocks_hl(hh, hl, m, n) { + var wh = new Int32Array(16), wl = new Int32Array(16), + bh0, bh1, bh2, bh3, bh4, bh5, bh6, bh7, + bl0, bl1, bl2, bl3, bl4, bl5, bl6, bl7, + th, tl, i, j, h, l, a, b, c, d; + + var ah0 = hh[0], + ah1 = hh[1], + ah2 = hh[2], + ah3 = hh[3], + ah4 = hh[4], + ah5 = hh[5], + ah6 = hh[6], + ah7 = hh[7], + + al0 = hl[0], + al1 = hl[1], + al2 = hl[2], + al3 = hl[3], + al4 = hl[4], + al5 = hl[5], + al6 = hl[6], + al7 = hl[7]; + + var pos = 0; + while (n >= 128) { + for (i = 0; i < 16; i++) { + j = 8 * i + pos; + wh[i] = (m[j+0] << 24) | (m[j+1] << 16) | (m[j+2] << 8) | m[j+3]; + wl[i] = (m[j+4] << 24) | (m[j+5] << 16) | (m[j+6] << 8) | m[j+7]; + } + for (i = 0; i < 80; i++) { + bh0 = ah0; + bh1 = ah1; + bh2 = ah2; + bh3 = ah3; + bh4 = ah4; + bh5 = ah5; + bh6 = ah6; + bh7 = ah7; + + bl0 = al0; + bl1 = al1; + bl2 = al2; + bl3 = al3; + bl4 = al4; + bl5 = al5; + bl6 = al6; + bl7 = al7; + + // add + h = ah7; + l = al7; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + // Sigma1 + h = ((ah4 >>> 14) | (al4 << (32-14))) ^ ((ah4 >>> 18) | (al4 << (32-18))) ^ ((al4 >>> (41-32)) | (ah4 << (32-(41-32)))); + l = ((al4 >>> 14) | (ah4 << (32-14))) ^ ((al4 >>> 18) | (ah4 << (32-18))) ^ ((ah4 >>> (41-32)) | (al4 << (32-(41-32)))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // Ch + h = (ah4 & ah5) ^ (~ah4 & ah6); + l = (al4 & al5) ^ (~al4 & al6); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // K + h = K[i*2]; + l = K[i*2+1]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // w + h = wh[i%16]; + l = wl[i%16]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + th = c & 0xffff | d << 16; + tl = a & 0xffff | b << 16; + + // add + h = th; + l = tl; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + // Sigma0 + h = ((ah0 >>> 28) | (al0 << (32-28))) ^ ((al0 >>> (34-32)) | (ah0 << (32-(34-32)))) ^ ((al0 >>> (39-32)) | (ah0 << (32-(39-32)))); + l = ((al0 >>> 28) | (ah0 << (32-28))) ^ ((ah0 >>> (34-32)) | (al0 << (32-(34-32)))) ^ ((ah0 >>> (39-32)) | (al0 << (32-(39-32)))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // Maj + h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2); + l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + bh7 = (c & 0xffff) | (d << 16); + bl7 = (a & 0xffff) | (b << 16); + + // add + h = bh3; + l = bl3; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = th; + l = tl; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + bh3 = (c & 0xffff) | (d << 16); + bl3 = (a & 0xffff) | (b << 16); + + ah1 = bh0; + ah2 = bh1; + ah3 = bh2; + ah4 = bh3; + ah5 = bh4; + ah6 = bh5; + ah7 = bh6; + ah0 = bh7; + + al1 = bl0; + al2 = bl1; + al3 = bl2; + al4 = bl3; + al5 = bl4; + al6 = bl5; + al7 = bl6; + al0 = bl7; + + if (i%16 === 15) { + for (j = 0; j < 16; j++) { + // add + h = wh[j]; + l = wl[j]; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = wh[(j+9)%16]; + l = wl[(j+9)%16]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // sigma0 + th = wh[(j+1)%16]; + tl = wl[(j+1)%16]; + h = ((th >>> 1) | (tl << (32-1))) ^ ((th >>> 8) | (tl << (32-8))) ^ (th >>> 7); + l = ((tl >>> 1) | (th << (32-1))) ^ ((tl >>> 8) | (th << (32-8))) ^ ((tl >>> 7) | (th << (32-7))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + // sigma1 + th = wh[(j+14)%16]; + tl = wl[(j+14)%16]; + h = ((th >>> 19) | (tl << (32-19))) ^ ((tl >>> (61-32)) | (th << (32-(61-32)))) ^ (th >>> 6); + l = ((tl >>> 19) | (th << (32-19))) ^ ((th >>> (61-32)) | (tl << (32-(61-32)))) ^ ((tl >>> 6) | (th << (32-6))); + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + wh[j] = (c & 0xffff) | (d << 16); + wl[j] = (a & 0xffff) | (b << 16); + } + } + } + + // add + h = ah0; + l = al0; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[0]; + l = hl[0]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[0] = ah0 = (c & 0xffff) | (d << 16); + hl[0] = al0 = (a & 0xffff) | (b << 16); + + h = ah1; + l = al1; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[1]; + l = hl[1]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[1] = ah1 = (c & 0xffff) | (d << 16); + hl[1] = al1 = (a & 0xffff) | (b << 16); + + h = ah2; + l = al2; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[2]; + l = hl[2]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[2] = ah2 = (c & 0xffff) | (d << 16); + hl[2] = al2 = (a & 0xffff) | (b << 16); + + h = ah3; + l = al3; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[3]; + l = hl[3]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[3] = ah3 = (c & 0xffff) | (d << 16); + hl[3] = al3 = (a & 0xffff) | (b << 16); + + h = ah4; + l = al4; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[4]; + l = hl[4]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[4] = ah4 = (c & 0xffff) | (d << 16); + hl[4] = al4 = (a & 0xffff) | (b << 16); + + h = ah5; + l = al5; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[5]; + l = hl[5]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[5] = ah5 = (c & 0xffff) | (d << 16); + hl[5] = al5 = (a & 0xffff) | (b << 16); + + h = ah6; + l = al6; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[6]; + l = hl[6]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[6] = ah6 = (c & 0xffff) | (d << 16); + hl[6] = al6 = (a & 0xffff) | (b << 16); + + h = ah7; + l = al7; + + a = l & 0xffff; b = l >>> 16; + c = h & 0xffff; d = h >>> 16; + + h = hh[7]; + l = hl[7]; + + a += l & 0xffff; b += l >>> 16; + c += h & 0xffff; d += h >>> 16; + + b += a >>> 16; + c += b >>> 16; + d += c >>> 16; + + hh[7] = ah7 = (c & 0xffff) | (d << 16); + hl[7] = al7 = (a & 0xffff) | (b << 16); + + pos += 128; + n -= 128; + } + + return n; +} + +function crypto_hash(out, m, n) { + var hh = new Int32Array(8), + hl = new Int32Array(8), + x = new Uint8Array(256), + i, b = n; + + hh[0] = 0x6a09e667; + hh[1] = 0xbb67ae85; + hh[2] = 0x3c6ef372; + hh[3] = 0xa54ff53a; + hh[4] = 0x510e527f; + hh[5] = 0x9b05688c; + hh[6] = 0x1f83d9ab; + hh[7] = 0x5be0cd19; + + hl[0] = 0xf3bcc908; + hl[1] = 0x84caa73b; + hl[2] = 0xfe94f82b; + hl[3] = 0x5f1d36f1; + hl[4] = 0xade682d1; + hl[5] = 0x2b3e6c1f; + hl[6] = 0xfb41bd6b; + hl[7] = 0x137e2179; + + crypto_hashblocks_hl(hh, hl, m, n); + n %= 128; + + for (i = 0; i < n; i++) x[i] = m[b-n+i]; + x[n] = 128; + + n = 256-128*(n<112?1:0); + x[n-9] = 0; + ts64(x, n-8, (b / 0x20000000) | 0, b << 3); + crypto_hashblocks_hl(hh, hl, x, n); + + for (i = 0; i < 8; i++) ts64(out, 8*i, hh[i], hl[i]); + + return 0; +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64); + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm.subarray(32), n+32); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + crypto_hash(h, sm, n + 64); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i, mlen; + var t = new Uint8Array(32), h = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + mlen = -1; + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + crypto_hash(h, m, n); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + mlen = n; + return mlen; +} + +var crypto_secretbox_KEYBYTES = 32, + crypto_secretbox_NONCEBYTES = 24, + crypto_secretbox_ZEROBYTES = 32, + crypto_secretbox_BOXZEROBYTES = 16, + crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_box_BEFORENMBYTES = 32, + crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, + crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, + crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32, + crypto_hash_BYTES = 64; + +nacl.lowlevel = { + crypto_core_hsalsa20: crypto_core_hsalsa20, + crypto_stream_xor: crypto_stream_xor, + crypto_stream: crypto_stream, + crypto_stream_salsa20_xor: crypto_stream_salsa20_xor, + crypto_stream_salsa20: crypto_stream_salsa20, + crypto_onetimeauth: crypto_onetimeauth, + crypto_onetimeauth_verify: crypto_onetimeauth_verify, + crypto_verify_16: crypto_verify_16, + crypto_verify_32: crypto_verify_32, + crypto_secretbox: crypto_secretbox, + crypto_secretbox_open: crypto_secretbox_open, + crypto_scalarmult: crypto_scalarmult, + crypto_scalarmult_base: crypto_scalarmult_base, + crypto_box_beforenm: crypto_box_beforenm, + crypto_box_afternm: crypto_box_afternm, + crypto_box: crypto_box, + crypto_box_open: crypto_box_open, + crypto_box_keypair: crypto_box_keypair, + crypto_hash: crypto_hash, + crypto_sign: crypto_sign, + crypto_sign_keypair: crypto_sign_keypair, + crypto_sign_open: crypto_sign_open, + + crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES, + crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES, + crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES, + crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES, + crypto_scalarmult_BYTES: crypto_scalarmult_BYTES, + crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES, + crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES, + crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES, + crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES, + crypto_box_NONCEBYTES: crypto_box_NONCEBYTES, + crypto_box_ZEROBYTES: crypto_box_ZEROBYTES, + crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES, + crypto_sign_BYTES: crypto_sign_BYTES, + crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, + crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, + crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, + crypto_hash_BYTES: crypto_hash_BYTES +}; + +/* High-level API */ + +function checkLengths(k, n) { + if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size'); + if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size'); +} + +function checkBoxLengths(pk, sk) { + if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size'); + if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); +} + +function checkArrayTypes() { + var t, i; + for (i = 0; i < arguments.length; i++) { + if ((t = Object.prototype.toString.call(arguments[i])) !== '[object Uint8Array]') + throw new TypeError('unexpected type ' + t + ', use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +// TODO: Completely remove this in v0.15. +if (!nacl.util) { + nacl.util = {}; + nacl.util.decodeUTF8 = nacl.util.encodeUTF8 = nacl.util.encodeBase64 = nacl.util.decodeBase64 = function() { + throw new Error('nacl.util moved into separate package: https://github.com/dchest/tweetnacl-util-js'); + }; +} + +nacl.randomBytes = function(n) { + var b = new Uint8Array(n); + randombytes(b, n); + return b; +}; + +nacl.secretbox = function(msg, nonce, key) { + checkArrayTypes(msg, nonce, key); + checkLengths(key, nonce); + var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); + var c = new Uint8Array(m.length); + for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; + crypto_secretbox(c, m, m.length, nonce, key); + return c.subarray(crypto_secretbox_BOXZEROBYTES); +}; + +nacl.secretbox.open = function(box, nonce, key) { + checkArrayTypes(box, nonce, key); + checkLengths(key, nonce); + var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); + var m = new Uint8Array(c.length); + for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; + if (c.length < 32) return false; + if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return false; + return m.subarray(crypto_secretbox_ZEROBYTES); +}; + +nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES; +nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES; +nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES; + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.scalarMult.base = function(n) { + checkArrayTypes(n); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult_base(q, n); + return q; +}; + +nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; +nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES; + +nacl.box = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox(msg, nonce, k); +}; + +nacl.box.before = function(publicKey, secretKey) { + checkArrayTypes(publicKey, secretKey); + checkBoxLengths(publicKey, secretKey); + var k = new Uint8Array(crypto_box_BEFORENMBYTES); + crypto_box_beforenm(k, publicKey, secretKey); + return k; +}; + +nacl.box.after = nacl.secretbox; + +nacl.box.open = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox.open(msg, nonce, k); +}; + +nacl.box.open.after = nacl.secretbox.open; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES; +nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES; +nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES; +nacl.box.nonceLength = crypto_box_NONCEBYTES; +nacl.box.overheadLength = nacl.secretbox.overheadLength; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.open = function(signedMsg, publicKey) { + if (arguments.length !== 2) + throw new Error('nacl.sign.open accepts 2 arguments; did you mean to use nacl.sign.detached.verify?'); + checkArrayTypes(signedMsg, publicKey); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var tmp = new Uint8Array(signedMsg.length); + var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey); + if (mlen < 0) return null; + var m = new Uint8Array(mlen); + for (var i = 0; i < m.length; i++) m[i] = tmp[i]; + return m; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES; +nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES; +nacl.sign.seedLength = crypto_sign_SEEDBYTES; +nacl.sign.signatureLength = crypto_sign_BYTES; + +nacl.hash = function(msg) { + checkArrayTypes(msg); + var h = new Uint8Array(crypto_hash_BYTES); + crypto_hash(h, msg, msg.length); + return h; +}; + +nacl.hash.hashLength = crypto_hash_BYTES; + +nacl.verify = function(x, y) { + checkArrayTypes(x, y); + // Zero length arguments are considered not equal. + if (x.length === 0 || y.length === 0) return false; + if (x.length !== y.length) return false; + return (vn(x, 0, y, 0, x.length) === 0) ? true : false; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof require !== 'undefined') { + // Node.js. + crypto = require('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); diff --git a/reverse_engineering/node_modules/tweetnacl/nacl-fast.min.js b/reverse_engineering/node_modules/tweetnacl/nacl-fast.min.js new file mode 100644 index 0000000..8bc47da --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/nacl-fast.min.js @@ -0,0 +1,2 @@ +!function(r){"use strict";function t(r,t,n,e){r[t]=n>>24&255,r[t+1]=n>>16&255,r[t+2]=n>>8&255,r[t+3]=255&n,r[t+4]=e>>24&255,r[t+5]=e>>16&255,r[t+6]=e>>8&255,r[t+7]=255&e}function n(r,t,n,e,o){var i,h=0;for(i=0;i>>8)-1}function e(r,t,e,o){return n(r,t,e,o,16)}function o(r,t,e,o){return n(r,t,e,o,32)}function i(r,t,n,e){for(var o,i=255&e[0]|(255&e[1])<<8|(255&e[2])<<16|(255&e[3])<<24,h=255&n[0]|(255&n[1])<<8|(255&n[2])<<16|(255&n[3])<<24,a=255&n[4]|(255&n[5])<<8|(255&n[6])<<16|(255&n[7])<<24,f=255&n[8]|(255&n[9])<<8|(255&n[10])<<16|(255&n[11])<<24,s=255&n[12]|(255&n[13])<<8|(255&n[14])<<16|(255&n[15])<<24,c=255&e[4]|(255&e[5])<<8|(255&e[6])<<16|(255&e[7])<<24,u=255&t[0]|(255&t[1])<<8|(255&t[2])<<16|(255&t[3])<<24,y=255&t[4]|(255&t[5])<<8|(255&t[6])<<16|(255&t[7])<<24,l=255&t[8]|(255&t[9])<<8|(255&t[10])<<16|(255&t[11])<<24,w=255&t[12]|(255&t[13])<<8|(255&t[14])<<16|(255&t[15])<<24,p=255&e[8]|(255&e[9])<<8|(255&e[10])<<16|(255&e[11])<<24,v=255&n[16]|(255&n[17])<<8|(255&n[18])<<16|(255&n[19])<<24,b=255&n[20]|(255&n[21])<<8|(255&n[22])<<16|(255&n[23])<<24,g=255&n[24]|(255&n[25])<<8|(255&n[26])<<16|(255&n[27])<<24,_=255&n[28]|(255&n[29])<<8|(255&n[30])<<16|(255&n[31])<<24,A=255&e[12]|(255&e[13])<<8|(255&e[14])<<16|(255&e[15])<<24,d=i,U=h,E=a,x=f,M=s,m=c,B=u,S=y,K=l,T=w,Y=p,k=v,L=b,z=g,R=_,P=A,O=0;O<20;O+=2)o=d+L|0,M^=o<<7|o>>>25,o=M+d|0,K^=o<<9|o>>>23,o=K+M|0,L^=o<<13|o>>>19,o=L+K|0,d^=o<<18|o>>>14,o=m+U|0,T^=o<<7|o>>>25,o=T+m|0,z^=o<<9|o>>>23,o=z+T|0,U^=o<<13|o>>>19,o=U+z|0,m^=o<<18|o>>>14,o=Y+B|0,R^=o<<7|o>>>25,o=R+Y|0,E^=o<<9|o>>>23,o=E+R|0,B^=o<<13|o>>>19,o=B+E|0,Y^=o<<18|o>>>14,o=P+k|0,x^=o<<7|o>>>25,o=x+P|0,S^=o<<9|o>>>23,o=S+x|0,k^=o<<13|o>>>19,o=k+S|0,P^=o<<18|o>>>14,o=d+x|0,U^=o<<7|o>>>25,o=U+d|0,E^=o<<9|o>>>23,o=E+U|0,x^=o<<13|o>>>19,o=x+E|0,d^=o<<18|o>>>14,o=m+M|0,B^=o<<7|o>>>25,o=B+m|0,S^=o<<9|o>>>23,o=S+B|0,M^=o<<13|o>>>19,o=M+S|0,m^=o<<18|o>>>14,o=Y+T|0,k^=o<<7|o>>>25,o=k+Y|0,K^=o<<9|o>>>23,o=K+k|0,T^=o<<13|o>>>19,o=T+K|0,Y^=o<<18|o>>>14,o=P+R|0,L^=o<<7|o>>>25,o=L+P|0,z^=o<<9|o>>>23,o=z+L|0,R^=o<<13|o>>>19,o=R+z|0,P^=o<<18|o>>>14;d=d+i|0,U=U+h|0,E=E+a|0,x=x+f|0,M=M+s|0,m=m+c|0,B=B+u|0,S=S+y|0,K=K+l|0,T=T+w|0,Y=Y+p|0,k=k+v|0,L=L+b|0,z=z+g|0,R=R+_|0,P=P+A|0,r[0]=d>>>0&255,r[1]=d>>>8&255,r[2]=d>>>16&255,r[3]=d>>>24&255,r[4]=U>>>0&255,r[5]=U>>>8&255,r[6]=U>>>16&255,r[7]=U>>>24&255,r[8]=E>>>0&255,r[9]=E>>>8&255,r[10]=E>>>16&255,r[11]=E>>>24&255,r[12]=x>>>0&255,r[13]=x>>>8&255,r[14]=x>>>16&255,r[15]=x>>>24&255,r[16]=M>>>0&255,r[17]=M>>>8&255,r[18]=M>>>16&255,r[19]=M>>>24&255,r[20]=m>>>0&255,r[21]=m>>>8&255,r[22]=m>>>16&255,r[23]=m>>>24&255,r[24]=B>>>0&255,r[25]=B>>>8&255,r[26]=B>>>16&255,r[27]=B>>>24&255,r[28]=S>>>0&255,r[29]=S>>>8&255,r[30]=S>>>16&255,r[31]=S>>>24&255,r[32]=K>>>0&255,r[33]=K>>>8&255,r[34]=K>>>16&255,r[35]=K>>>24&255,r[36]=T>>>0&255,r[37]=T>>>8&255,r[38]=T>>>16&255,r[39]=T>>>24&255,r[40]=Y>>>0&255,r[41]=Y>>>8&255,r[42]=Y>>>16&255,r[43]=Y>>>24&255,r[44]=k>>>0&255,r[45]=k>>>8&255,r[46]=k>>>16&255,r[47]=k>>>24&255,r[48]=L>>>0&255,r[49]=L>>>8&255,r[50]=L>>>16&255,r[51]=L>>>24&255,r[52]=z>>>0&255,r[53]=z>>>8&255,r[54]=z>>>16&255,r[55]=z>>>24&255,r[56]=R>>>0&255,r[57]=R>>>8&255,r[58]=R>>>16&255,r[59]=R>>>24&255,r[60]=P>>>0&255,r[61]=P>>>8&255,r[62]=P>>>16&255,r[63]=P>>>24&255}function h(r,t,n,e){for(var o,i=255&e[0]|(255&e[1])<<8|(255&e[2])<<16|(255&e[3])<<24,h=255&n[0]|(255&n[1])<<8|(255&n[2])<<16|(255&n[3])<<24,a=255&n[4]|(255&n[5])<<8|(255&n[6])<<16|(255&n[7])<<24,f=255&n[8]|(255&n[9])<<8|(255&n[10])<<16|(255&n[11])<<24,s=255&n[12]|(255&n[13])<<8|(255&n[14])<<16|(255&n[15])<<24,c=255&e[4]|(255&e[5])<<8|(255&e[6])<<16|(255&e[7])<<24,u=255&t[0]|(255&t[1])<<8|(255&t[2])<<16|(255&t[3])<<24,y=255&t[4]|(255&t[5])<<8|(255&t[6])<<16|(255&t[7])<<24,l=255&t[8]|(255&t[9])<<8|(255&t[10])<<16|(255&t[11])<<24,w=255&t[12]|(255&t[13])<<8|(255&t[14])<<16|(255&t[15])<<24,p=255&e[8]|(255&e[9])<<8|(255&e[10])<<16|(255&e[11])<<24,v=255&n[16]|(255&n[17])<<8|(255&n[18])<<16|(255&n[19])<<24,b=255&n[20]|(255&n[21])<<8|(255&n[22])<<16|(255&n[23])<<24,g=255&n[24]|(255&n[25])<<8|(255&n[26])<<16|(255&n[27])<<24,_=255&n[28]|(255&n[29])<<8|(255&n[30])<<16|(255&n[31])<<24,A=255&e[12]|(255&e[13])<<8|(255&e[14])<<16|(255&e[15])<<24,d=i,U=h,E=a,x=f,M=s,m=c,B=u,S=y,K=l,T=w,Y=p,k=v,L=b,z=g,R=_,P=A,O=0;O<20;O+=2)o=d+L|0,M^=o<<7|o>>>25,o=M+d|0,K^=o<<9|o>>>23,o=K+M|0,L^=o<<13|o>>>19,o=L+K|0,d^=o<<18|o>>>14,o=m+U|0,T^=o<<7|o>>>25,o=T+m|0,z^=o<<9|o>>>23,o=z+T|0,U^=o<<13|o>>>19,o=U+z|0,m^=o<<18|o>>>14,o=Y+B|0,R^=o<<7|o>>>25,o=R+Y|0,E^=o<<9|o>>>23,o=E+R|0,B^=o<<13|o>>>19,o=B+E|0,Y^=o<<18|o>>>14,o=P+k|0,x^=o<<7|o>>>25,o=x+P|0,S^=o<<9|o>>>23,o=S+x|0,k^=o<<13|o>>>19,o=k+S|0,P^=o<<18|o>>>14,o=d+x|0,U^=o<<7|o>>>25,o=U+d|0,E^=o<<9|o>>>23,o=E+U|0,x^=o<<13|o>>>19,o=x+E|0,d^=o<<18|o>>>14,o=m+M|0,B^=o<<7|o>>>25,o=B+m|0,S^=o<<9|o>>>23,o=S+B|0,M^=o<<13|o>>>19,o=M+S|0,m^=o<<18|o>>>14,o=Y+T|0,k^=o<<7|o>>>25,o=k+Y|0,K^=o<<9|o>>>23,o=K+k|0,T^=o<<13|o>>>19,o=T+K|0,Y^=o<<18|o>>>14,o=P+R|0,L^=o<<7|o>>>25,o=L+P|0,z^=o<<9|o>>>23,o=z+L|0,R^=o<<13|o>>>19,o=R+z|0,P^=o<<18|o>>>14;r[0]=d>>>0&255,r[1]=d>>>8&255,r[2]=d>>>16&255,r[3]=d>>>24&255,r[4]=m>>>0&255,r[5]=m>>>8&255,r[6]=m>>>16&255,r[7]=m>>>24&255,r[8]=Y>>>0&255,r[9]=Y>>>8&255,r[10]=Y>>>16&255,r[11]=Y>>>24&255,r[12]=P>>>0&255,r[13]=P>>>8&255,r[14]=P>>>16&255,r[15]=P>>>24&255,r[16]=B>>>0&255,r[17]=B>>>8&255,r[18]=B>>>16&255,r[19]=B>>>24&255,r[20]=S>>>0&255,r[21]=S>>>8&255,r[22]=S>>>16&255,r[23]=S>>>24&255,r[24]=K>>>0&255,r[25]=K>>>8&255,r[26]=K>>>16&255,r[27]=K>>>24&255,r[28]=T>>>0&255,r[29]=T>>>8&255,r[30]=T>>>16&255,r[31]=T>>>24&255}function a(r,t,n,e){i(r,t,n,e)}function f(r,t,n,e){h(r,t,n,e)}function s(r,t,n,e,o,i,h){var f,s,c=new Uint8Array(16),u=new Uint8Array(64);for(s=0;s<16;s++)c[s]=0;for(s=0;s<8;s++)c[s]=i[s];for(;o>=64;){for(a(u,c,h,ur),s=0;s<64;s++)r[t+s]=n[e+s]^u[s];for(f=1,s=8;s<16;s++)f=f+(255&c[s])|0,c[s]=255&f,f>>>=8;o-=64,t+=64,e+=64}if(o>0)for(a(u,c,h,ur),s=0;s=64;){for(a(s,f,o,ur),h=0;h<64;h++)r[t+h]=s[h];for(i=1,h=8;h<16;h++)i=i+(255&f[h])|0,f[h]=255&i,i>>>=8;n-=64,t+=64}if(n>0)for(a(s,f,o,ur),h=0;h>16&1),i[n-1]&=65535;i[15]=h[15]-32767-(i[14]>>16&1),o=i[15]>>16&1,i[14]&=65535,_(h,i,1-o)}for(n=0;n<16;n++)r[2*n]=255&h[n],r[2*n+1]=h[n]>>8}function d(r,t){var n=new Uint8Array(32),e=new Uint8Array(32);return A(n,r),A(e,t),o(n,0,e,0)}function U(r){var t=new Uint8Array(32);return A(t,r),1&t[0]}function E(r,t){var n;for(n=0;n<16;n++)r[n]=t[2*n]+(t[2*n+1]<<8);r[15]&=32767}function x(r,t,n){for(var e=0;e<16;e++)r[e]=t[e]+n[e]}function M(r,t,n){for(var e=0;e<16;e++)r[e]=t[e]-n[e]}function m(r,t,n){var e,o,i=0,h=0,a=0,f=0,s=0,c=0,u=0,y=0,l=0,w=0,p=0,v=0,b=0,g=0,_=0,A=0,d=0,U=0,E=0,x=0,M=0,m=0,B=0,S=0,K=0,T=0,Y=0,k=0,L=0,z=0,R=0,P=n[0],O=n[1],N=n[2],C=n[3],F=n[4],I=n[5],G=n[6],Z=n[7],j=n[8],q=n[9],V=n[10],X=n[11],D=n[12],H=n[13],J=n[14],Q=n[15];e=t[0],i+=e*P,h+=e*O,a+=e*N,f+=e*C,s+=e*F,c+=e*I,u+=e*G,y+=e*Z,l+=e*j,w+=e*q,p+=e*V,v+=e*X,b+=e*D,g+=e*H,_+=e*J,A+=e*Q,e=t[1],h+=e*P,a+=e*O,f+=e*N,s+=e*C,c+=e*F,u+=e*I,y+=e*G,l+=e*Z,w+=e*j,p+=e*q,v+=e*V,b+=e*X,g+=e*D,_+=e*H,A+=e*J,d+=e*Q,e=t[2],a+=e*P,f+=e*O,s+=e*N,c+=e*C,u+=e*F,y+=e*I,l+=e*G,w+=e*Z,p+=e*j,v+=e*q,b+=e*V,g+=e*X,_+=e*D,A+=e*H,d+=e*J,U+=e*Q,e=t[3],f+=e*P,s+=e*O,c+=e*N,u+=e*C,y+=e*F,l+=e*I,w+=e*G,p+=e*Z,v+=e*j,b+=e*q,g+=e*V,_+=e*X,A+=e*D,d+=e*H,U+=e*J,E+=e*Q,e=t[4],s+=e*P,c+=e*O,u+=e*N,y+=e*C,l+=e*F,w+=e*I,p+=e*G,v+=e*Z,b+=e*j,g+=e*q,_+=e*V,A+=e*X,d+=e*D,U+=e*H,E+=e*J,x+=e*Q,e=t[5],c+=e*P,u+=e*O,y+=e*N,l+=e*C,w+=e*F,p+=e*I,v+=e*G,b+=e*Z,g+=e*j,_+=e*q,A+=e*V,d+=e*X,U+=e*D,E+=e*H,x+=e*J,M+=e*Q,e=t[6],u+=e*P,y+=e*O,l+=e*N,w+=e*C,p+=e*F,v+=e*I,b+=e*G,g+=e*Z,_+=e*j,A+=e*q,d+=e*V,U+=e*X,E+=e*D,x+=e*H,M+=e*J,m+=e*Q,e=t[7],y+=e*P,l+=e*O,w+=e*N,p+=e*C,v+=e*F,b+=e*I,g+=e*G,_+=e*Z,A+=e*j,d+=e*q,U+=e*V,E+=e*X,x+=e*D,M+=e*H,m+=e*J,B+=e*Q,e=t[8],l+=e*P,w+=e*O,p+=e*N,v+=e*C,b+=e*F,g+=e*I,_+=e*G,A+=e*Z,d+=e*j,U+=e*q,E+=e*V,x+=e*X,M+=e*D,m+=e*H,B+=e*J,S+=e*Q,e=t[9],w+=e*P,p+=e*O,v+=e*N,b+=e*C,g+=e*F,_+=e*I,A+=e*G,d+=e*Z,U+=e*j,E+=e*q,x+=e*V,M+=e*X,m+=e*D,B+=e*H,S+=e*J,K+=e*Q,e=t[10],p+=e*P,v+=e*O,b+=e*N,g+=e*C,_+=e*F,A+=e*I,d+=e*G,U+=e*Z,E+=e*j,x+=e*q,M+=e*V,m+=e*X,B+=e*D,S+=e*H,K+=e*J,T+=e*Q,e=t[11],v+=e*P,b+=e*O,g+=e*N,_+=e*C,A+=e*F,d+=e*I,U+=e*G,E+=e*Z,x+=e*j,M+=e*q,m+=e*V,B+=e*X;S+=e*D;K+=e*H,T+=e*J,Y+=e*Q,e=t[12],b+=e*P,g+=e*O,_+=e*N,A+=e*C,d+=e*F,U+=e*I,E+=e*G,x+=e*Z,M+=e*j,m+=e*q,B+=e*V,S+=e*X,K+=e*D,T+=e*H,Y+=e*J,k+=e*Q,e=t[13],g+=e*P,_+=e*O,A+=e*N,d+=e*C,U+=e*F,E+=e*I,x+=e*G,M+=e*Z,m+=e*j,B+=e*q,S+=e*V,K+=e*X,T+=e*D,Y+=e*H,k+=e*J,L+=e*Q,e=t[14],_+=e*P,A+=e*O,d+=e*N,U+=e*C,E+=e*F,x+=e*I,M+=e*G,m+=e*Z,B+=e*j,S+=e*q,K+=e*V,T+=e*X,Y+=e*D,k+=e*H,L+=e*J,z+=e*Q,e=t[15],A+=e*P,d+=e*O,U+=e*N,E+=e*C,x+=e*F,M+=e*I,m+=e*G,B+=e*Z,S+=e*j,K+=e*q,T+=e*V,Y+=e*X,k+=e*D,L+=e*H,z+=e*J,R+=e*Q,i+=38*d,h+=38*U,a+=38*E,f+=38*x,s+=38*M,c+=38*m,u+=38*B,y+=38*S,l+=38*K,w+=38*T,p+=38*Y,v+=38*k,b+=38*L,g+=38*z,_+=38*R,o=1,e=i+o+65535,o=Math.floor(e/65536),i=e-65536*o,e=h+o+65535,o=Math.floor(e/65536),h=e-65536*o,e=a+o+65535,o=Math.floor(e/65536),a=e-65536*o,e=f+o+65535,o=Math.floor(e/65536),f=e-65536*o,e=s+o+65535,o=Math.floor(e/65536),s=e-65536*o,e=c+o+65535,o=Math.floor(e/65536),c=e-65536*o,e=u+o+65535,o=Math.floor(e/65536),u=e-65536*o,e=y+o+65535,o=Math.floor(e/65536),y=e-65536*o,e=l+o+65535,o=Math.floor(e/65536),l=e-65536*o,e=w+o+65535,o=Math.floor(e/65536),w=e-65536*o,e=p+o+65535,o=Math.floor(e/65536),p=e-65536*o,e=v+o+65535,o=Math.floor(e/65536),v=e-65536*o,e=b+o+65535,o=Math.floor(e/65536),b=e-65536*o,e=g+o+65535,o=Math.floor(e/65536),g=e-65536*o,e=_+o+65535,o=Math.floor(e/65536),_=e-65536*o,e=A+o+65535,o=Math.floor(e/65536),A=e-65536*o,i+=o-1+37*(o-1),o=1,e=i+o+65535,o=Math.floor(e/65536),i=e-65536*o,e=h+o+65535,o=Math.floor(e/65536),h=e-65536*o,e=a+o+65535,o=Math.floor(e/65536),a=e-65536*o,e=f+o+65535,o=Math.floor(e/65536),f=e-65536*o,e=s+o+65535,o=Math.floor(e/65536),s=e-65536*o,e=c+o+65535,o=Math.floor(e/65536),c=e-65536*o,e=u+o+65535,o=Math.floor(e/65536),u=e-65536*o,e=y+o+65535,o=Math.floor(e/65536),y=e-65536*o,e=l+o+65535,o=Math.floor(e/65536),l=e-65536*o,e=w+o+65535,o=Math.floor(e/65536),w=e-65536*o,e=p+o+65535,o=Math.floor(e/65536),p=e-65536*o,e=v+o+65535,o=Math.floor(e/65536),v=e-65536*o,e=b+o+65535,o=Math.floor(e/65536),b=e-65536*o,e=g+o+65535,o=Math.floor(e/65536),g=e-65536*o,e=_+o+65535,o=Math.floor(e/65536),_=e-65536*o,e=A+o+65535,o=Math.floor(e/65536),A=e-65536*o,i+=o-1+37*(o-1),r[0]=i,r[1]=h,r[2]=a,r[3]=f,r[4]=s,r[5]=c,r[6]=u,r[7]=y,r[8]=l,r[9]=w,r[10]=p,r[11]=v,r[12]=b,r[13]=g;r[14]=_;r[15]=A}function B(r,t){m(r,t,t)}function S(r,t){var n,e=$();for(n=0;n<16;n++)e[n]=t[n];for(n=253;n>=0;n--)B(e,e),2!==n&&4!==n&&m(e,e,t);for(n=0;n<16;n++)r[n]=e[n]}function K(r,t){var n,e=$();for(n=0;n<16;n++)e[n]=t[n];for(n=250;n>=0;n--)B(e,e),1!==n&&m(e,e,t);for(n=0;n<16;n++)r[n]=e[n]}function T(r,t,n){var e,o,i=new Uint8Array(32),h=new Float64Array(80),a=$(),f=$(),s=$(),c=$(),u=$(),y=$();for(o=0;o<31;o++)i[o]=t[o];for(i[31]=127&t[31]|64,i[0]&=248,E(h,n),o=0;o<16;o++)f[o]=h[o],c[o]=a[o]=s[o]=0;for(a[0]=c[0]=1,o=254;o>=0;--o)e=i[o>>>3]>>>(7&o)&1,_(a,f,e),_(s,c,e),x(u,a,s),M(a,a,s),x(s,f,c),M(f,f,c),B(c,u),B(y,a),m(a,s,a),m(s,f,u),x(u,a,s),M(a,a,s),B(f,a),M(s,c,y),m(a,s,ir),x(a,a,c),m(s,s,a),m(a,c,y),m(c,f,h),B(f,u),_(a,f,e),_(s,c,e);for(o=0;o<16;o++)h[o+16]=a[o],h[o+32]=s[o],h[o+48]=f[o],h[o+64]=c[o];var l=h.subarray(32),w=h.subarray(16);return S(l,l),m(w,w,l),A(r,w),0}function Y(r,t){return T(r,t,nr)}function k(r,t){return rr(t,32),Y(r,t)}function L(r,t,n){var e=new Uint8Array(32);return T(e,n,t),f(r,tr,e,ur)}function z(r,t,n,e,o,i){var h=new Uint8Array(32);return L(h,o,i),lr(r,t,n,e,h)}function R(r,t,n,e,o,i){var h=new Uint8Array(32);return L(h,o,i),wr(r,t,n,e,h)}function P(r,t,n,e){for(var o,i,h,a,f,s,c,u,y,l,w,p,v,b,g,_,A,d,U,E,x,M,m,B,S,K,T=new Int32Array(16),Y=new Int32Array(16),k=r[0],L=r[1],z=r[2],R=r[3],P=r[4],O=r[5],N=r[6],C=r[7],F=t[0],I=t[1],G=t[2],Z=t[3],j=t[4],q=t[5],V=t[6],X=t[7],D=0;e>=128;){for(U=0;U<16;U++)E=8*U+D,T[U]=n[E+0]<<24|n[E+1]<<16|n[E+2]<<8|n[E+3],Y[U]=n[E+4]<<24|n[E+5]<<16|n[E+6]<<8|n[E+7];for(U=0;U<80;U++)if(o=k,i=L,h=z,a=R,f=P,s=O,c=N,u=C,y=F,l=I,w=G,p=Z,v=j,b=q,g=V,_=X,x=C,M=X,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=(P>>>14|j<<18)^(P>>>18|j<<14)^(j>>>9|P<<23),M=(j>>>14|P<<18)^(j>>>18|P<<14)^(P>>>9|j<<23),m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,x=P&O^~P&N,M=j&q^~j&V,m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,x=pr[2*U],M=pr[2*U+1],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,x=T[U%16],M=Y[U%16],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,A=65535&S|K<<16,d=65535&m|B<<16,x=A,M=d,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=(k>>>28|F<<4)^(F>>>2|k<<30)^(F>>>7|k<<25),M=(F>>>28|k<<4)^(k>>>2|F<<30)^(k>>>7|F<<25),m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,x=k&L^k&z^L&z,M=F&I^F&G^I&G,m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,u=65535&S|K<<16,_=65535&m|B<<16,x=a,M=p,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=A,M=d,m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,a=65535&S|K<<16,p=65535&m|B<<16,L=o,z=i,R=h,P=a,O=f,N=s,C=c,k=u,I=y,G=l,Z=w,j=p,q=v,V=b,X=g,F=_,U%16===15)for(E=0;E<16;E++)x=T[E],M=Y[E],m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=T[(E+9)%16],M=Y[(E+9)%16],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,A=T[(E+1)%16],d=Y[(E+1)%16],x=(A>>>1|d<<31)^(A>>>8|d<<24)^A>>>7,M=(d>>>1|A<<31)^(d>>>8|A<<24)^(d>>>7|A<<25),m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,A=T[(E+14)%16],d=Y[(E+14)%16],x=(A>>>19|d<<13)^(d>>>29|A<<3)^A>>>6,M=(d>>>19|A<<13)^(A>>>29|d<<3)^(d>>>6|A<<26),m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,T[E]=65535&S|K<<16,Y[E]=65535&m|B<<16;x=k,M=F,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[0],M=t[0],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[0]=k=65535&S|K<<16,t[0]=F=65535&m|B<<16,x=L,M=I,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[1],M=t[1],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[1]=L=65535&S|K<<16,t[1]=I=65535&m|B<<16,x=z,M=G,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[2],M=t[2],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[2]=z=65535&S|K<<16,t[2]=G=65535&m|B<<16,x=R,M=Z,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[3],M=t[3],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[3]=R=65535&S|K<<16,t[3]=Z=65535&m|B<<16,x=P,M=j,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[4],M=t[4],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[4]=P=65535&S|K<<16,t[4]=j=65535&m|B<<16,x=O,M=q,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[5],M=t[5],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[5]=O=65535&S|K<<16,t[5]=q=65535&m|B<<16,x=N,M=V,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[6],M=t[6],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[6]=N=65535&S|K<<16,t[6]=V=65535&m|B<<16,x=C,M=X,m=65535&M,B=M>>>16,S=65535&x,K=x>>>16,x=r[7],M=t[7],m+=65535&M,B+=M>>>16,S+=65535&x,K+=x>>>16,B+=m>>>16,S+=B>>>16,K+=S>>>16,r[7]=C=65535&S|K<<16,t[7]=X=65535&m|B<<16,D+=128,e-=128}return e}function O(r,n,e){var o,i=new Int32Array(8),h=new Int32Array(8),a=new Uint8Array(256),f=e;for(i[0]=1779033703,i[1]=3144134277,i[2]=1013904242,i[3]=2773480762,i[4]=1359893119,i[5]=2600822924,i[6]=528734635,i[7]=1541459225,h[0]=4089235720,h[1]=2227873595,h[2]=4271175723,h[3]=1595750129,h[4]=2917565137,h[5]=725511199,h[6]=4215389547,h[7]=327033209,P(i,h,n,e),e%=128,o=0;o=0;--o)e=n[o/8|0]>>(7&o)&1,C(r,t,e),N(t,r),N(r,r),C(r,t,e)}function G(r,t){var n=[$(),$(),$(),$()];b(n[0],fr),b(n[1],sr),b(n[2],or),m(n[3],fr,sr),I(r,n,t)}function Z(r,t,n){var e,o=new Uint8Array(64),i=[$(),$(),$(),$()];for(n||rr(t,32),O(o,t,32),o[0]&=248,o[31]&=127,o[31]|=64,G(i,o),F(r,i),e=0;e<32;e++)t[e+32]=r[e];return 0}function j(r,t){var n,e,o,i;for(e=63;e>=32;--e){for(n=0,o=e-32,i=e-12;o>8,t[o]-=256*n;t[o]+=n,t[e]=0}for(n=0,o=0;o<32;o++)t[o]+=n-(t[31]>>4)*vr[o],n=t[o]>>8,t[o]&=255;for(o=0;o<32;o++)t[o]-=n*vr[o];for(e=0;e<32;e++)t[e+1]+=t[e]>>8,r[e]=255&t[e]}function q(r){var t,n=new Float64Array(64);for(t=0;t<64;t++)n[t]=r[t];for(t=0;t<64;t++)r[t]=0;j(r,n)}function V(r,t,n,e){var o,i,h=new Uint8Array(64),a=new Uint8Array(64),f=new Uint8Array(64),s=new Float64Array(64),c=[$(),$(),$(),$()];O(h,e,32),h[0]&=248,h[31]&=127,h[31]|=64;var u=n+64;for(o=0;o>7&&M(r[0],er,r[0]),m(r[3],r[0],r[1]),0)}function D(r,t,n,e){var i,h,a=new Uint8Array(32),f=new Uint8Array(64),s=[$(),$(),$(),$()],c=[$(),$(),$(),$()];if(h=-1,n<64)return-1;if(X(c,e))return-1;for(i=0;i>>13|n<<3),e=255&r[4]|(255&r[5])<<8,this.r[2]=7939&(n>>>10|e<<6),o=255&r[6]|(255&r[7])<<8,this.r[3]=8191&(e>>>7|o<<9),i=255&r[8]|(255&r[9])<<8,this.r[4]=255&(o>>>4|i<<12),this.r[5]=i>>>1&8190,h=255&r[10]|(255&r[11])<<8,this.r[6]=8191&(i>>>14|h<<2),a=255&r[12]|(255&r[13])<<8,this.r[7]=8065&(h>>>11|a<<5),f=255&r[14]|(255&r[15])<<8,this.r[8]=8191&(a>>>8|f<<8),this.r[9]=f>>>5&127,this.pad[0]=255&r[16]|(255&r[17])<<8,this.pad[1]=255&r[18]|(255&r[19])<<8,this.pad[2]=255&r[20]|(255&r[21])<<8,this.pad[3]=255&r[22]|(255&r[23])<<8,this.pad[4]=255&r[24]|(255&r[25])<<8,this.pad[5]=255&r[26]|(255&r[27])<<8,this.pad[6]=255&r[28]|(255&r[29])<<8,this.pad[7]=255&r[30]|(255&r[31])<<8};yr.prototype.blocks=function(r,t,n){for(var e,o,i,h,a,f,s,c,u,y,l,w,p,v,b,g,_,A,d,U=this.fin?0:2048,E=this.h[0],x=this.h[1],M=this.h[2],m=this.h[3],B=this.h[4],S=this.h[5],K=this.h[6],T=this.h[7],Y=this.h[8],k=this.h[9],L=this.r[0],z=this.r[1],R=this.r[2],P=this.r[3],O=this.r[4],N=this.r[5],C=this.r[6],F=this.r[7],I=this.r[8],G=this.r[9];n>=16;)e=255&r[t+0]|(255&r[t+1])<<8,E+=8191&e,o=255&r[t+2]|(255&r[t+3])<<8,x+=8191&(e>>>13|o<<3),i=255&r[t+4]|(255&r[t+5])<<8,M+=8191&(o>>>10|i<<6),h=255&r[t+6]|(255&r[t+7])<<8,m+=8191&(i>>>7|h<<9),a=255&r[t+8]|(255&r[t+9])<<8,B+=8191&(h>>>4|a<<12),S+=a>>>1&8191,f=255&r[t+10]|(255&r[t+11])<<8,K+=8191&(a>>>14|f<<2),s=255&r[t+12]|(255&r[t+13])<<8,T+=8191&(f>>>11|s<<5),c=255&r[t+14]|(255&r[t+15])<<8,Y+=8191&(s>>>8|c<<8),k+=c>>>5|U,u=0,y=u,y+=E*L,y+=x*(5*G),y+=M*(5*I),y+=m*(5*F),y+=B*(5*C),u=y>>>13,y&=8191,y+=S*(5*N),y+=K*(5*O),y+=T*(5*P),y+=Y*(5*R),y+=k*(5*z),u+=y>>>13,y&=8191,l=u,l+=E*z,l+=x*L,l+=M*(5*G),l+=m*(5*I),l+=B*(5*F),u=l>>>13,l&=8191,l+=S*(5*C),l+=K*(5*N),l+=T*(5*O),l+=Y*(5*P),l+=k*(5*R),u+=l>>>13,l&=8191,w=u,w+=E*R,w+=x*z,w+=M*L,w+=m*(5*G),w+=B*(5*I),u=w>>>13,w&=8191,w+=S*(5*F),w+=K*(5*C),w+=T*(5*N),w+=Y*(5*O),w+=k*(5*P),u+=w>>>13,w&=8191,p=u,p+=E*P,p+=x*R,p+=M*z,p+=m*L,p+=B*(5*G),u=p>>>13,p&=8191,p+=S*(5*I),p+=K*(5*F),p+=T*(5*C),p+=Y*(5*N),p+=k*(5*O),u+=p>>>13,p&=8191,v=u,v+=E*O,v+=x*P,v+=M*R,v+=m*z,v+=B*L,u=v>>>13,v&=8191,v+=S*(5*G),v+=K*(5*I),v+=T*(5*F),v+=Y*(5*C),v+=k*(5*N),u+=v>>>13,v&=8191,b=u,b+=E*N,b+=x*O,b+=M*P,b+=m*R,b+=B*z,u=b>>>13,b&=8191,b+=S*L,b+=K*(5*G),b+=T*(5*I),b+=Y*(5*F),b+=k*(5*C),u+=b>>>13,b&=8191,g=u,g+=E*C,g+=x*N,g+=M*O,g+=m*P,g+=B*R,u=g>>>13,g&=8191,g+=S*z,g+=K*L,g+=T*(5*G),g+=Y*(5*I),g+=k*(5*F),u+=g>>>13,g&=8191,_=u,_+=E*F,_+=x*C,_+=M*N,_+=m*O,_+=B*P,u=_>>>13,_&=8191,_+=S*R,_+=K*z,_+=T*L,_+=Y*(5*G),_+=k*(5*I),u+=_>>>13,_&=8191,A=u,A+=E*I,A+=x*F,A+=M*C,A+=m*N,A+=B*O,u=A>>>13,A&=8191,A+=S*P,A+=K*R,A+=T*z,A+=Y*L,A+=k*(5*G),u+=A>>>13,A&=8191,d=u,d+=E*G,d+=x*I,d+=M*F,d+=m*C,d+=B*N,u=d>>>13,d&=8191,d+=S*O,d+=K*P,d+=T*R,d+=Y*z,d+=k*L,u+=d>>>13,d&=8191,u=(u<<2)+u|0,u=u+y|0,y=8191&u,u>>>=13,l+=u,E=y,x=l,M=w,m=p,B=v,S=b,K=g,T=_,Y=A,k=d,t+=16,n-=16;this.h[0]=E,this.h[1]=x,this.h[2]=M,this.h[3]=m,this.h[4]=B,this.h[5]=S,this.h[6]=K,this.h[7]=T,this.h[8]=Y,this.h[9]=k},yr.prototype.finish=function(r,t){var n,e,o,i,h=new Uint16Array(10);if(this.leftover){for(i=this.leftover,this.buffer[i++]=1;i<16;i++)this.buffer[i]=0;this.fin=1,this.blocks(this.buffer,0,16)}for(n=this.h[1]>>>13,this.h[1]&=8191,i=2;i<10;i++)this.h[i]+=n,n=this.h[i]>>>13,this.h[i]&=8191;for(this.h[0]+=5*n,n=this.h[0]>>>13,this.h[0]&=8191,this.h[1]+=n,n=this.h[1]>>>13,this.h[1]&=8191,this.h[2]+=n,h[0]=this.h[0]+5,n=h[0]>>>13,h[0]&=8191,i=1;i<10;i++)h[i]=this.h[i]+n,n=h[i]>>>13,h[i]&=8191;for(h[9]-=8192,e=(1^n)-1,i=0;i<10;i++)h[i]&=e;for(e=~e,i=0;i<10;i++)this.h[i]=this.h[i]&e|h[i];for(this.h[0]=65535&(this.h[0]|this.h[1]<<13),this.h[1]=65535&(this.h[1]>>>3|this.h[2]<<10),this.h[2]=65535&(this.h[2]>>>6|this.h[3]<<7),this.h[3]=65535&(this.h[3]>>>9|this.h[4]<<4),this.h[4]=65535&(this.h[4]>>>12|this.h[5]<<1|this.h[6]<<14),this.h[5]=65535&(this.h[6]>>>2|this.h[7]<<11),this.h[6]=65535&(this.h[7]>>>5|this.h[8]<<8),this.h[7]=65535&(this.h[8]>>>8|this.h[9]<<5),o=this.h[0]+this.pad[0],this.h[0]=65535&o,i=1;i<8;i++)o=(this.h[i]+this.pad[i]|0)+(o>>>16)|0,this.h[i]=65535&o;r[t+0]=this.h[0]>>>0&255,r[t+1]=this.h[0]>>>8&255,r[t+2]=this.h[1]>>>0&255,r[t+3]=this.h[1]>>>8&255,r[t+4]=this.h[2]>>>0&255,r[t+5]=this.h[2]>>>8&255,r[t+6]=this.h[3]>>>0&255,r[t+7]=this.h[3]>>>8&255,r[t+8]=this.h[4]>>>0&255,r[t+9]=this.h[4]>>>8&255,r[t+10]=this.h[5]>>>0&255,r[t+11]=this.h[5]>>>8&255,r[t+12]=this.h[6]>>>0&255,r[t+13]=this.h[6]>>>8&255,r[t+14]=this.h[7]>>>0&255,r[t+15]=this.h[7]>>>8&255},yr.prototype.update=function(r,t,n){var e,o;if(this.leftover){for(o=16-this.leftover,o>n&&(o=n),e=0;e=16&&(o=n-n%16,this.blocks(r,t,o),t+=o,n-=o),n){for(e=0;e=0},r.sign.keyPair=function(){var r=new Uint8Array(Tr),t=new Uint8Array(Yr);return Z(r,t),{publicKey:r,secretKey:t}},r.sign.keyPair.fromSecretKey=function(r){if(Q(r),r.length!==Yr)throw new Error("bad secret key size");for(var t=new Uint8Array(Tr),n=0;n void): void; +} diff --git a/reverse_engineering/node_modules/tweetnacl/nacl.js b/reverse_engineering/node_modules/tweetnacl/nacl.js new file mode 100644 index 0000000..f72dd78 --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/nacl.js @@ -0,0 +1,1175 @@ +(function(nacl) { +'use strict'; + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var u64 = function(h, l) { this.hi = h|0 >>> 0; this.lo = l|0 >>> 0; }; +var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; +}; + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + +var _0 = new Uint8Array(16); +var _9 = new Uint8Array(32); _9[0] = 9; + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + +function L32(x, c) { return (x << c) | (x >>> (32 - c)); } + +function ld32(x, i) { + var u = x[i+3] & 0xff; + u = (u<<8)|(x[i+2] & 0xff); + u = (u<<8)|(x[i+1] & 0xff); + return (u<<8)|(x[i+0] & 0xff); +} + +function dl64(x, i) { + var h = (x[i] << 24) | (x[i+1] << 16) | (x[i+2] << 8) | x[i+3]; + var l = (x[i+4] << 24) | (x[i+5] << 16) | (x[i+6] << 8) | x[i+7]; + return new u64(h, l); +} + +function st32(x, j, u) { + var i; + for (i = 0; i < 4; i++) { x[j+i] = u & 255; u >>>= 8; } +} + +function ts64(x, i, u) { + x[i] = (u.hi >> 24) & 0xff; + x[i+1] = (u.hi >> 16) & 0xff; + x[i+2] = (u.hi >> 8) & 0xff; + x[i+3] = u.hi & 0xff; + x[i+4] = (u.lo >> 24) & 0xff; + x[i+5] = (u.lo >> 16) & 0xff; + x[i+6] = (u.lo >> 8) & 0xff; + x[i+7] = u.lo & 0xff; +} + +function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; +} + +function crypto_verify_16(x, xi, y, yi) { + return vn(x,xi,y,yi,16); +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); +} + +function core(out,inp,k,c,h) { + var w = new Uint32Array(16), x = new Uint32Array(16), + y = new Uint32Array(16), t = new Uint32Array(4); + var i, j, m; + + for (i = 0; i < 4; i++) { + x[5*i] = ld32(c, 4*i); + x[1+i] = ld32(k, 4*i); + x[6+i] = ld32(inp, 4*i); + x[11+i] = ld32(k, 16+4*i); + } + + for (i = 0; i < 16; i++) y[i] = x[i]; + + for (i = 0; i < 20; i++) { + for (j = 0; j < 4; j++) { + for (m = 0; m < 4; m++) t[m] = x[(5*j+4*m)%16]; + t[1] ^= L32((t[0]+t[3])|0, 7); + t[2] ^= L32((t[1]+t[0])|0, 9); + t[3] ^= L32((t[2]+t[1])|0,13); + t[0] ^= L32((t[3]+t[2])|0,18); + for (m = 0; m < 4; m++) w[4*j+(j+m)%4] = t[m]; + } + for (m = 0; m < 16; m++) x[m] = w[m]; + } + + if (h) { + for (i = 0; i < 16; i++) x[i] = (x[i] + y[i]) | 0; + for (i = 0; i < 4; i++) { + x[5*i] = (x[5*i] - ld32(c, 4*i)) | 0; + x[6+i] = (x[6+i] - ld32(inp, 4*i)) | 0; + } + for (i = 0; i < 4; i++) { + st32(out,4*i,x[5*i]); + st32(out,16+4*i,x[6+i]); + } + } else { + for (i = 0; i < 16; i++) st32(out, 4 * i, (x[i] + y[i]) | 0); + } +} + +function crypto_core_salsa20(out,inp,k,c) { + core(out,inp,k,c,false); + return 0; +} + +function crypto_core_hsalsa20(out,inp,k,c) { + core(out,inp,k,c,true); + return 0; +} + +var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]); + // "expand 32-byte k" + +function crypto_stream_salsa20_xor(c,cpos,m,mpos,b,n,k) { + var z = new Uint8Array(16), x = new Uint8Array(64); + var u, i; + if (!b) return 0; + for (i = 0; i < 16; i++) z[i] = 0; + for (i = 0; i < 8; i++) z[i] = n[i]; + while (b >= 64) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < 64; i++) c[cpos+i] = (m?m[mpos+i]:0) ^ x[i]; + u = 1; + for (i = 8; i < 16; i++) { + u = u + (z[i] & 0xff) | 0; + z[i] = u & 0xff; + u >>>= 8; + } + b -= 64; + cpos += 64; + if (m) mpos += 64; + } + if (b > 0) { + crypto_core_salsa20(x,z,k,sigma); + for (i = 0; i < b; i++) c[cpos+i] = (m?m[mpos+i]:0) ^ x[i]; + } + return 0; +} + +function crypto_stream_salsa20(c,cpos,d,n,k) { + return crypto_stream_salsa20_xor(c,cpos,null,0,d,n,k); +} + +function crypto_stream(c,cpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20(c,cpos,d,n.subarray(16),s); +} + +function crypto_stream_xor(c,cpos,m,mpos,d,n,k) { + var s = new Uint8Array(32); + crypto_core_hsalsa20(s,n,k,sigma); + return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,n.subarray(16),s); +} + +function add1305(h, c) { + var j, u = 0; + for (j = 0; j < 17; j++) { + u = (u + ((h[j] + c[j]) | 0)) | 0; + h[j] = u & 255; + u >>>= 8; + } +} + +var minusp = new Uint32Array([ + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252 +]); + +function crypto_onetimeauth(out, outpos, m, mpos, n, k) { + var s, i, j, u; + var x = new Uint32Array(17), r = new Uint32Array(17), + h = new Uint32Array(17), c = new Uint32Array(17), + g = new Uint32Array(17); + for (j = 0; j < 17; j++) r[j]=h[j]=0; + for (j = 0; j < 16; j++) r[j]=k[j]; + r[3]&=15; + r[4]&=252; + r[7]&=15; + r[8]&=252; + r[11]&=15; + r[12]&=252; + r[15]&=15; + + while (n > 0) { + for (j = 0; j < 17; j++) c[j] = 0; + for (j = 0; (j < 16) && (j < n); ++j) c[j] = m[mpos+j]; + c[j] = 1; + mpos += j; n -= j; + add1305(h,c); + for (i = 0; i < 17; i++) { + x[i] = 0; + for (j = 0; j < 17; j++) x[i] = (x[i] + (h[j] * ((j <= i) ? r[i - j] : ((320 * r[i + 17 - j])|0))) | 0) | 0; + } + for (i = 0; i < 17; i++) h[i] = x[i]; + u = 0; + for (j = 0; j < 16; j++) { + u = (u + h[j]) | 0; + h[j] = u & 255; + u >>>= 8; + } + u = (u + h[16]) | 0; h[16] = u & 3; + u = (5 * (u >>> 2)) | 0; + for (j = 0; j < 16; j++) { + u = (u + h[j]) | 0; + h[j] = u & 255; + u >>>= 8; + } + u = (u + h[16]) | 0; h[16] = u; + } + + for (j = 0; j < 17; j++) g[j] = h[j]; + add1305(h,minusp); + s = (-(h[16] >>> 7) | 0); + for (j = 0; j < 17; j++) h[j] ^= s & (g[j] ^ h[j]); + + for (j = 0; j < 16; j++) c[j] = k[j + 16]; + c[16] = 0; + add1305(h,c); + for (j = 0; j < 16; j++) out[outpos+j] = h[j]; + return 0; +} + +function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) { + var x = new Uint8Array(16); + crypto_onetimeauth(x,0,m,mpos,n,k); + return crypto_verify_16(h,hpos,x,0); +} + +function crypto_secretbox(c,m,d,n,k) { + var i; + if (d < 32) return -1; + crypto_stream_xor(c,0,m,0,d,n,k); + crypto_onetimeauth(c, 16, c, 32, d - 32, c); + for (i = 0; i < 16; i++) c[i] = 0; + return 0; +} + +function crypto_secretbox_open(m,c,d,n,k) { + var i; + var x = new Uint8Array(32); + if (d < 32) return -1; + crypto_stream(x,0,32,n,k); + if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1; + crypto_stream_xor(m,0,c,0,d,n,k); + for (i = 0; i < 32; i++) m[i] = 0; + return 0; +} + +function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; +} + +function car25519(o) { + var c; + var i; + for (i = 0; i < 16; i++) { + o[i] += 65536; + c = Math.floor(o[i] / 65536); + o[(i+1)*(i<15?1:0)] += c - 1 + 37 * (c-1) * (i===15?1:0); + o[i] -= (c * 65536); + } +} + +function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); +} + +function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; +} + +function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; +} + +function A(o, a, b) { + var i; + for (i = 0; i < 16; i++) o[i] = (a[i] + b[i])|0; +} + +function Z(o, a, b) { + var i; + for (i = 0; i < 16; i++) o[i] = (a[i] - b[i])|0; +} + +function M(o, a, b) { + var i, j, t = new Float64Array(31); + for (i = 0; i < 31; i++) t[i] = 0; + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + t[i+j] += a[i] * b[j]; + } + } + for (i = 0; i < 15; i++) { + t[i] += 38 * t[i+16]; + } + for (i = 0; i < 16; i++) o[i] = t[i]; + car25519(o); + car25519(o); +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function crypto_box_beforenm(k, y, x) { + var s = new Uint8Array(32); + crypto_scalarmult(s, x, y); + return crypto_core_hsalsa20(k, _0, s, sigma); +} + +var crypto_box_afternm = crypto_secretbox; +var crypto_box_open_afternm = crypto_secretbox_open; + +function crypto_box(c, m, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_afternm(c, m, d, n, k); +} + +function crypto_box_open(m, c, d, n, y, x) { + var k = new Uint8Array(32); + crypto_box_beforenm(k, y, x); + return crypto_box_open_afternm(m, c, d, n, k); +} + +function add64() { + var a = 0, b = 0, c = 0, d = 0, m16 = 65535, l, h, i; + for (i = 0; i < arguments.length; i++) { + l = arguments[i].lo; + h = arguments[i].hi; + a += (l & m16); b += (l >>> 16); + c += (h & m16); d += (h >>> 16); + } + + b += (a >>> 16); + c += (b >>> 16); + d += (c >>> 16); + + return new u64((c & m16) | (d << 16), (a & m16) | (b << 16)); +} + +function shr64(x, c) { + return new u64((x.hi >>> c), (x.lo >>> c) | (x.hi << (32 - c))); +} + +function xor64() { + var l = 0, h = 0, i; + for (i = 0; i < arguments.length; i++) { + l ^= arguments[i].lo; + h ^= arguments[i].hi; + } + return new u64(h, l); +} + +function R(x, c) { + var h, l, c1 = 32 - c; + if (c < 32) { + h = (x.hi >>> c) | (x.lo << c1); + l = (x.lo >>> c) | (x.hi << c1); + } else if (c < 64) { + h = (x.lo >>> c) | (x.hi << c1); + l = (x.hi >>> c) | (x.lo << c1); + } + return new u64(h, l); +} + +function Ch(x, y, z) { + var h = (x.hi & y.hi) ^ (~x.hi & z.hi), + l = (x.lo & y.lo) ^ (~x.lo & z.lo); + return new u64(h, l); +} + +function Maj(x, y, z) { + var h = (x.hi & y.hi) ^ (x.hi & z.hi) ^ (y.hi & z.hi), + l = (x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo); + return new u64(h, l); +} + +function Sigma0(x) { return xor64(R(x,28), R(x,34), R(x,39)); } +function Sigma1(x) { return xor64(R(x,14), R(x,18), R(x,41)); } +function sigma0(x) { return xor64(R(x, 1), R(x, 8), shr64(x,7)); } +function sigma1(x) { return xor64(R(x,19), R(x,61), shr64(x,6)); } + +var K = [ + new u64(0x428a2f98, 0xd728ae22), new u64(0x71374491, 0x23ef65cd), + new u64(0xb5c0fbcf, 0xec4d3b2f), new u64(0xe9b5dba5, 0x8189dbbc), + new u64(0x3956c25b, 0xf348b538), new u64(0x59f111f1, 0xb605d019), + new u64(0x923f82a4, 0xaf194f9b), new u64(0xab1c5ed5, 0xda6d8118), + new u64(0xd807aa98, 0xa3030242), new u64(0x12835b01, 0x45706fbe), + new u64(0x243185be, 0x4ee4b28c), new u64(0x550c7dc3, 0xd5ffb4e2), + new u64(0x72be5d74, 0xf27b896f), new u64(0x80deb1fe, 0x3b1696b1), + new u64(0x9bdc06a7, 0x25c71235), new u64(0xc19bf174, 0xcf692694), + new u64(0xe49b69c1, 0x9ef14ad2), new u64(0xefbe4786, 0x384f25e3), + new u64(0x0fc19dc6, 0x8b8cd5b5), new u64(0x240ca1cc, 0x77ac9c65), + new u64(0x2de92c6f, 0x592b0275), new u64(0x4a7484aa, 0x6ea6e483), + new u64(0x5cb0a9dc, 0xbd41fbd4), new u64(0x76f988da, 0x831153b5), + new u64(0x983e5152, 0xee66dfab), new u64(0xa831c66d, 0x2db43210), + new u64(0xb00327c8, 0x98fb213f), new u64(0xbf597fc7, 0xbeef0ee4), + new u64(0xc6e00bf3, 0x3da88fc2), new u64(0xd5a79147, 0x930aa725), + new u64(0x06ca6351, 0xe003826f), new u64(0x14292967, 0x0a0e6e70), + new u64(0x27b70a85, 0x46d22ffc), new u64(0x2e1b2138, 0x5c26c926), + new u64(0x4d2c6dfc, 0x5ac42aed), new u64(0x53380d13, 0x9d95b3df), + new u64(0x650a7354, 0x8baf63de), new u64(0x766a0abb, 0x3c77b2a8), + new u64(0x81c2c92e, 0x47edaee6), new u64(0x92722c85, 0x1482353b), + new u64(0xa2bfe8a1, 0x4cf10364), new u64(0xa81a664b, 0xbc423001), + new u64(0xc24b8b70, 0xd0f89791), new u64(0xc76c51a3, 0x0654be30), + new u64(0xd192e819, 0xd6ef5218), new u64(0xd6990624, 0x5565a910), + new u64(0xf40e3585, 0x5771202a), new u64(0x106aa070, 0x32bbd1b8), + new u64(0x19a4c116, 0xb8d2d0c8), new u64(0x1e376c08, 0x5141ab53), + new u64(0x2748774c, 0xdf8eeb99), new u64(0x34b0bcb5, 0xe19b48a8), + new u64(0x391c0cb3, 0xc5c95a63), new u64(0x4ed8aa4a, 0xe3418acb), + new u64(0x5b9cca4f, 0x7763e373), new u64(0x682e6ff3, 0xd6b2b8a3), + new u64(0x748f82ee, 0x5defb2fc), new u64(0x78a5636f, 0x43172f60), + new u64(0x84c87814, 0xa1f0ab72), new u64(0x8cc70208, 0x1a6439ec), + new u64(0x90befffa, 0x23631e28), new u64(0xa4506ceb, 0xde82bde9), + new u64(0xbef9a3f7, 0xb2c67915), new u64(0xc67178f2, 0xe372532b), + new u64(0xca273ece, 0xea26619c), new u64(0xd186b8c7, 0x21c0c207), + new u64(0xeada7dd6, 0xcde0eb1e), new u64(0xf57d4f7f, 0xee6ed178), + new u64(0x06f067aa, 0x72176fba), new u64(0x0a637dc5, 0xa2c898a6), + new u64(0x113f9804, 0xbef90dae), new u64(0x1b710b35, 0x131c471b), + new u64(0x28db77f5, 0x23047d84), new u64(0x32caab7b, 0x40c72493), + new u64(0x3c9ebe0a, 0x15c9bebc), new u64(0x431d67c4, 0x9c100d4c), + new u64(0x4cc5d4be, 0xcb3e42b6), new u64(0x597f299c, 0xfc657e2a), + new u64(0x5fcb6fab, 0x3ad6faec), new u64(0x6c44198c, 0x4a475817) +]; + +function crypto_hashblocks(x, m, n) { + var z = [], b = [], a = [], w = [], t, i, j; + + for (i = 0; i < 8; i++) z[i] = a[i] = dl64(x, 8*i); + + var pos = 0; + while (n >= 128) { + for (i = 0; i < 16; i++) w[i] = dl64(m, 8*i+pos); + for (i = 0; i < 80; i++) { + for (j = 0; j < 8; j++) b[j] = a[j]; + t = add64(a[7], Sigma1(a[4]), Ch(a[4], a[5], a[6]), K[i], w[i%16]); + b[7] = add64(t, Sigma0(a[0]), Maj(a[0], a[1], a[2])); + b[3] = add64(b[3], t); + for (j = 0; j < 8; j++) a[(j+1)%8] = b[j]; + if (i%16 === 15) { + for (j = 0; j < 16; j++) { + w[j] = add64(w[j], w[(j+9)%16], sigma0(w[(j+1)%16]), sigma1(w[(j+14)%16])); + } + } + } + + for (i = 0; i < 8; i++) { + a[i] = add64(a[i], z[i]); + z[i] = a[i]; + } + + pos += 128; + n -= 128; + } + + for (i = 0; i < 8; i++) ts64(x, 8*i, z[i]); + return n; +} + +var iv = new Uint8Array([ + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +]); + +function crypto_hash(out, m, n) { + var h = new Uint8Array(64), x = new Uint8Array(256); + var i, b = n; + + for (i = 0; i < 64; i++) h[i] = iv[i]; + + crypto_hashblocks(h, m, n); + n %= 128; + + for (i = 0; i < 256; i++) x[i] = 0; + for (i = 0; i < n; i++) x[i] = m[b-n+i]; + x[n] = 128; + + n = 256-128*(n<112?1:0); + x[n-9] = 0; + ts64(x, n-8, new u64((b / 0x20000000) | 0, b << 3)); + crypto_hashblocks(h, x, n); + + for (i = 0; i < 64; i++) out[i] = h[i]; + + return 0; +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64); + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + crypto_hash(r, sm.subarray(32), n+32); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + crypto_hash(h, sm, n + 64); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i, mlen; + var t = new Uint8Array(32), h = new Uint8Array(64); + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + mlen = -1; + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + crypto_hash(h, m, n); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + mlen = n; + return mlen; +} + +var crypto_secretbox_KEYBYTES = 32, + crypto_secretbox_NONCEBYTES = 24, + crypto_secretbox_ZEROBYTES = 32, + crypto_secretbox_BOXZEROBYTES = 16, + crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_box_BEFORENMBYTES = 32, + crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, + crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, + crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32, + crypto_hash_BYTES = 64; + +nacl.lowlevel = { + crypto_core_hsalsa20: crypto_core_hsalsa20, + crypto_stream_xor: crypto_stream_xor, + crypto_stream: crypto_stream, + crypto_stream_salsa20_xor: crypto_stream_salsa20_xor, + crypto_stream_salsa20: crypto_stream_salsa20, + crypto_onetimeauth: crypto_onetimeauth, + crypto_onetimeauth_verify: crypto_onetimeauth_verify, + crypto_verify_16: crypto_verify_16, + crypto_verify_32: crypto_verify_32, + crypto_secretbox: crypto_secretbox, + crypto_secretbox_open: crypto_secretbox_open, + crypto_scalarmult: crypto_scalarmult, + crypto_scalarmult_base: crypto_scalarmult_base, + crypto_box_beforenm: crypto_box_beforenm, + crypto_box_afternm: crypto_box_afternm, + crypto_box: crypto_box, + crypto_box_open: crypto_box_open, + crypto_box_keypair: crypto_box_keypair, + crypto_hash: crypto_hash, + crypto_sign: crypto_sign, + crypto_sign_keypair: crypto_sign_keypair, + crypto_sign_open: crypto_sign_open, + + crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES, + crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES, + crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES, + crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES, + crypto_scalarmult_BYTES: crypto_scalarmult_BYTES, + crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES, + crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES, + crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES, + crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES, + crypto_box_NONCEBYTES: crypto_box_NONCEBYTES, + crypto_box_ZEROBYTES: crypto_box_ZEROBYTES, + crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES, + crypto_sign_BYTES: crypto_sign_BYTES, + crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, + crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, + crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, + crypto_hash_BYTES: crypto_hash_BYTES +}; + +/* High-level API */ + +function checkLengths(k, n) { + if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size'); + if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size'); +} + +function checkBoxLengths(pk, sk) { + if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size'); + if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); +} + +function checkArrayTypes() { + var t, i; + for (i = 0; i < arguments.length; i++) { + if ((t = Object.prototype.toString.call(arguments[i])) !== '[object Uint8Array]') + throw new TypeError('unexpected type ' + t + ', use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +// TODO: Completely remove this in v0.15. +if (!nacl.util) { + nacl.util = {}; + nacl.util.decodeUTF8 = nacl.util.encodeUTF8 = nacl.util.encodeBase64 = nacl.util.decodeBase64 = function() { + throw new Error('nacl.util moved into separate package: https://github.com/dchest/tweetnacl-util-js'); + }; +} + +nacl.randomBytes = function(n) { + var b = new Uint8Array(n); + randombytes(b, n); + return b; +}; + +nacl.secretbox = function(msg, nonce, key) { + checkArrayTypes(msg, nonce, key); + checkLengths(key, nonce); + var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); + var c = new Uint8Array(m.length); + for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; + crypto_secretbox(c, m, m.length, nonce, key); + return c.subarray(crypto_secretbox_BOXZEROBYTES); +}; + +nacl.secretbox.open = function(box, nonce, key) { + checkArrayTypes(box, nonce, key); + checkLengths(key, nonce); + var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); + var m = new Uint8Array(c.length); + for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; + if (c.length < 32) return false; + if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return false; + return m.subarray(crypto_secretbox_ZEROBYTES); +}; + +nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES; +nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES; +nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES; + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.scalarMult.base = function(n) { + checkArrayTypes(n); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult_base(q, n); + return q; +}; + +nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES; +nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES; + +nacl.box = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox(msg, nonce, k); +}; + +nacl.box.before = function(publicKey, secretKey) { + checkArrayTypes(publicKey, secretKey); + checkBoxLengths(publicKey, secretKey); + var k = new Uint8Array(crypto_box_BEFORENMBYTES); + crypto_box_beforenm(k, publicKey, secretKey); + return k; +}; + +nacl.box.after = nacl.secretbox; + +nacl.box.open = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey); + return nacl.secretbox.open(msg, nonce, k); +}; + +nacl.box.open.after = nacl.secretbox.open; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES; +nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES; +nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES; +nacl.box.nonceLength = crypto_box_NONCEBYTES; +nacl.box.overheadLength = nacl.secretbox.overheadLength; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.open = function(signedMsg, publicKey) { + if (arguments.length !== 2) + throw new Error('nacl.sign.open accepts 2 arguments; did you mean to use nacl.sign.detached.verify?'); + checkArrayTypes(signedMsg, publicKey); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var tmp = new Uint8Array(signedMsg.length); + var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey); + if (mlen < 0) return null; + var m = new Uint8Array(mlen); + for (var i = 0; i < m.length; i++) m[i] = tmp[i]; + return m; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES; +nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES; +nacl.sign.seedLength = crypto_sign_SEEDBYTES; +nacl.sign.signatureLength = crypto_sign_BYTES; + +nacl.hash = function(msg) { + checkArrayTypes(msg); + var h = new Uint8Array(crypto_hash_BYTES); + crypto_hash(h, msg, msg.length); + return h; +}; + +nacl.hash.hashLength = crypto_hash_BYTES; + +nacl.verify = function(x, y) { + checkArrayTypes(x, y); + // Zero length arguments are considered not equal. + if (x.length === 0 || y.length === 0) return false; + if (x.length !== y.length) return false; + return (vn(x, 0, y, 0, x.length) === 0) ? true : false; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof require !== 'undefined') { + // Node.js. + crypto = require('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); diff --git a/reverse_engineering/node_modules/tweetnacl/nacl.min.js b/reverse_engineering/node_modules/tweetnacl/nacl.min.js new file mode 100644 index 0000000..4484974 --- /dev/null +++ b/reverse_engineering/node_modules/tweetnacl/nacl.min.js @@ -0,0 +1 @@ +!function(r){"use strict";function n(r,n){return r<>>32-n}function e(r,n){var e=255&r[n+3];return e=e<<8|255&r[n+2],e=e<<8|255&r[n+1],e<<8|255&r[n+0]}function t(r,n){var e=r[n]<<24|r[n+1]<<16|r[n+2]<<8|r[n+3],t=r[n+4]<<24|r[n+5]<<16|r[n+6]<<8|r[n+7];return new sr(e,t)}function o(r,n,e){var t;for(t=0;t<4;t++)r[n+t]=255&e,e>>>=8}function i(r,n,e){r[n]=e.hi>>24&255,r[n+1]=e.hi>>16&255,r[n+2]=e.hi>>8&255,r[n+3]=255&e.hi,r[n+4]=e.lo>>24&255,r[n+5]=e.lo>>16&255,r[n+6]=e.lo>>8&255,r[n+7]=255&e.lo}function a(r,n,e,t,o){var i,a=0;for(i=0;i>>8)-1}function f(r,n,e,t){return a(r,n,e,t,16)}function u(r,n,e,t){return a(r,n,e,t,32)}function c(r,t,i,a,f){var u,c,w,y=new Uint32Array(16),l=new Uint32Array(16),s=new Uint32Array(16),h=new Uint32Array(4);for(u=0;u<4;u++)l[5*u]=e(a,4*u),l[1+u]=e(i,4*u),l[6+u]=e(t,4*u),l[11+u]=e(i,16+4*u);for(u=0;u<16;u++)s[u]=l[u];for(u=0;u<20;u++){for(c=0;c<4;c++){for(w=0;w<4;w++)h[w]=l[(5*c+4*w)%16];for(h[1]^=n(h[0]+h[3]|0,7),h[2]^=n(h[1]+h[0]|0,9),h[3]^=n(h[2]+h[1]|0,13),h[0]^=n(h[3]+h[2]|0,18),w=0;w<4;w++)y[4*c+(c+w)%4]=h[w]}for(w=0;w<16;w++)l[w]=y[w]}if(f){for(u=0;u<16;u++)l[u]=l[u]+s[u]|0;for(u=0;u<4;u++)l[5*u]=l[5*u]-e(a,4*u)|0,l[6+u]=l[6+u]-e(t,4*u)|0;for(u=0;u<4;u++)o(r,4*u,l[5*u]),o(r,16+4*u,l[6+u])}else for(u=0;u<16;u++)o(r,4*u,l[u]+s[u]|0)}function w(r,n,e,t){return c(r,n,e,t,!1),0}function y(r,n,e,t){return c(r,n,e,t,!0),0}function l(r,n,e,t,o,i,a){var f,u,c=new Uint8Array(16),y=new Uint8Array(64);if(!o)return 0;for(u=0;u<16;u++)c[u]=0;for(u=0;u<8;u++)c[u]=i[u];for(;o>=64;){for(w(y,c,a,Br),u=0;u<64;u++)r[n+u]=(e?e[t+u]:0)^y[u];for(f=1,u=8;u<16;u++)f=f+(255&c[u])|0,c[u]=255&f,f>>>=8;o-=64,n+=64,e&&(t+=64)}if(o>0)for(w(y,c,a,Br),u=0;u>>=8}function b(r,n,e,t,o,i){var a,f,u,c,w=new Uint32Array(17),y=new Uint32Array(17),l=new Uint32Array(17),s=new Uint32Array(17),h=new Uint32Array(17);for(u=0;u<17;u++)y[u]=l[u]=0;for(u=0;u<16;u++)y[u]=i[u];for(y[3]&=15,y[4]&=252,y[7]&=15,y[8]&=252,y[11]&=15,y[12]&=252,y[15]&=15;o>0;){for(u=0;u<17;u++)s[u]=0;for(u=0;u<16&&u>>=8;for(c=c+l[16]|0,l[16]=3&c,c=5*(c>>>2)|0,u=0;u<16;u++)c=c+l[u]|0,l[u]=255&c,c>>>=8;c=c+l[16]|0,l[16]=c}for(u=0;u<17;u++)h[u]=l[u];for(v(l,Sr),a=0|-(l[16]>>>7),u=0;u<17;u++)l[u]^=a&(h[u]^l[u]);for(u=0;u<16;u++)s[u]=i[u+16];for(s[16]=0,v(l,s),u=0;u<16;u++)r[n+u]=l[u];return 0}function p(r,n,e,t,o,i){var a=new Uint8Array(16);return b(a,0,e,t,o,i),f(r,n,a,0)}function _(r,n,e,t,o){var i;if(e<32)return-1;for(g(r,0,n,0,e,t,o),b(r,16,r,32,e-32,r),i=0;i<16;i++)r[i]=0;return 0}function A(r,n,e,t,o){var i,a=new Uint8Array(32);if(e<32)return-1;if(h(a,0,32,t,o),0!==p(n,16,n,32,e-32,a))return-1;for(g(r,0,n,0,e,t,o),i=0;i<32;i++)r[i]=0;return 0}function U(r,n){var e;for(e=0;e<16;e++)r[e]=0|n[e]}function E(r){var n,e;for(e=0;e<16;e++)r[e]+=65536,n=Math.floor(r[e]/65536),r[(e+1)*(e<15?1:0)]+=n-1+37*(n-1)*(15===e?1:0),r[e]-=65536*n}function d(r,n,e){for(var t,o=~(e-1),i=0;i<16;i++)t=o&(r[i]^n[i]),r[i]^=t,n[i]^=t}function x(r,n){var e,t,o,i=hr(),a=hr();for(e=0;e<16;e++)a[e]=n[e];for(E(a),E(a),E(a),t=0;t<2;t++){for(i[0]=a[0]-65517,e=1;e<15;e++)i[e]=a[e]-65535-(i[e-1]>>16&1),i[e-1]&=65535;i[15]=a[15]-32767-(i[14]>>16&1),o=i[15]>>16&1,i[14]&=65535,d(a,i,1-o)}for(e=0;e<16;e++)r[2*e]=255&a[e],r[2*e+1]=a[e]>>8}function m(r,n){var e=new Uint8Array(32),t=new Uint8Array(32);return x(e,r),x(t,n),u(e,0,t,0)}function B(r){var n=new Uint8Array(32);return x(n,r),1&n[0]}function S(r,n){var e;for(e=0;e<16;e++)r[e]=n[2*e]+(n[2*e+1]<<8);r[15]&=32767}function K(r,n,e){var t;for(t=0;t<16;t++)r[t]=n[t]+e[t]|0}function T(r,n,e){var t;for(t=0;t<16;t++)r[t]=n[t]-e[t]|0}function Y(r,n,e){var t,o,i=new Float64Array(31);for(t=0;t<31;t++)i[t]=0;for(t=0;t<16;t++)for(o=0;o<16;o++)i[t+o]+=n[t]*e[o];for(t=0;t<15;t++)i[t]+=38*i[t+16];for(t=0;t<16;t++)r[t]=i[t];E(r),E(r)}function L(r,n){Y(r,n,n)}function k(r,n){var e,t=hr();for(e=0;e<16;e++)t[e]=n[e];for(e=253;e>=0;e--)L(t,t),2!==e&&4!==e&&Y(t,t,n);for(e=0;e<16;e++)r[e]=t[e]}function z(r,n){var e,t=hr();for(e=0;e<16;e++)t[e]=n[e];for(e=250;e>=0;e--)L(t,t),1!==e&&Y(t,t,n);for(e=0;e<16;e++)r[e]=t[e]}function R(r,n,e){var t,o,i=new Uint8Array(32),a=new Float64Array(80),f=hr(),u=hr(),c=hr(),w=hr(),y=hr(),l=hr();for(o=0;o<31;o++)i[o]=n[o];for(i[31]=127&n[31]|64,i[0]&=248,S(a,e),o=0;o<16;o++)u[o]=a[o],w[o]=f[o]=c[o]=0;for(f[0]=w[0]=1,o=254;o>=0;--o)t=i[o>>>3]>>>(7&o)&1,d(f,u,t),d(c,w,t),K(y,f,c),T(f,f,c),K(c,u,w),T(u,u,w),L(w,y),L(l,f),Y(f,c,f),Y(c,u,y),K(y,f,c),T(f,f,c),L(u,f),T(c,w,l),Y(f,c,Ar),K(f,f,w),Y(c,c,f),Y(f,w,l),Y(w,u,a),L(u,y),d(f,u,t),d(c,w,t);for(o=0;o<16;o++)a[o+16]=f[o],a[o+32]=c[o],a[o+48]=u[o],a[o+64]=w[o];var s=a.subarray(32),h=a.subarray(16);return k(s,s),Y(h,h,s),x(r,h),0}function P(r,n){return R(r,n,br)}function O(r,n){return gr(n,32),P(r,n)}function F(r,n,e){var t=new Uint8Array(32);return R(t,e,n),y(r,vr,t,Br)}function N(r,n,e,t,o,i){var a=new Uint8Array(32);return F(a,o,i),Kr(r,n,e,t,a)}function C(r,n,e,t,o,i){var a=new Uint8Array(32);return F(a,o,i),Tr(r,n,e,t,a)}function M(){var r,n,e,t=0,o=0,i=0,a=0,f=65535;for(e=0;e>>16,i+=n&f,a+=n>>>16;return o+=t>>>16,i+=o>>>16,a+=i>>>16,new sr(i&f|a<<16,t&f|o<<16)}function G(r,n){return new sr(r.hi>>>n,r.lo>>>n|r.hi<<32-n)}function Z(){var r,n=0,e=0;for(r=0;r>>n|r.lo<>>n|r.hi<>>n|r.hi<>>n|r.lo<=128;){for(a=0;a<16;a++)y[a]=t(n,8*a+l);for(a=0;a<80;a++){for(f=0;f<8;f++)c[f]=w[f];for(o=M(w[7],X(w[4]),q(w[4],w[5],w[6]),Yr[a],y[a%16]),c[7]=M(o,V(w[0]),I(w[0],w[1],w[2])),c[3]=M(c[3],o),f=0;f<8;f++)w[(f+1)%8]=c[f];if(a%16===15)for(f=0;f<16;f++)y[f]=M(y[f],y[(f+9)%16],D(y[(f+1)%16]),H(y[(f+14)%16]))}for(a=0;a<8;a++)w[a]=M(w[a],u[a]),u[a]=w[a];l+=128,e-=128}for(a=0;a<8;a++)i(r,8*a,u[a]);return e}function Q(r,n,e){var t,o=new Uint8Array(64),a=new Uint8Array(256),f=e;for(t=0;t<64;t++)o[t]=Lr[t];for(J(o,n,e),e%=128,t=0;t<256;t++)a[t]=0;for(t=0;t=0;--o)t=e[o/8|0]>>(7&o)&1,$(r,n,t),W(n,r),W(r,r),$(r,n,t)}function er(r,n){var e=[hr(),hr(),hr(),hr()];U(e[0],dr),U(e[1],xr),U(e[2],_r),Y(e[3],dr,xr),nr(r,e,n)}function tr(r,n,e){var t,o=new Uint8Array(64),i=[hr(),hr(),hr(),hr()];for(e||gr(n,32),Q(o,n,32),o[0]&=248,o[31]&=127,o[31]|=64,er(i,o),rr(r,i),t=0;t<32;t++)n[t+32]=r[t];return 0}function or(r,n){var e,t,o,i;for(t=63;t>=32;--t){for(e=0,o=t-32,i=t-12;o>8,n[o]-=256*e;n[o]+=e,n[t]=0}for(e=0,o=0;o<32;o++)n[o]+=e-(n[31]>>4)*kr[o],e=n[o]>>8,n[o]&=255;for(o=0;o<32;o++)n[o]-=e*kr[o];for(t=0;t<32;t++)n[t+1]+=n[t]>>8,r[t]=255&n[t]}function ir(r){var n,e=new Float64Array(64);for(n=0;n<64;n++)e[n]=r[n];for(n=0;n<64;n++)r[n]=0;or(r,e)}function ar(r,n,e,t){var o,i,a=new Uint8Array(64),f=new Uint8Array(64),u=new Uint8Array(64),c=new Float64Array(64),w=[hr(),hr(),hr(),hr()];Q(a,t,32),a[0]&=248,a[31]&=127,a[31]|=64;var y=e+64;for(o=0;o>7&&T(r[0],pr,r[0]),Y(r[3],r[0],r[1]),0)}function ur(r,n,e,t){var o,i,a=new Uint8Array(32),f=new Uint8Array(64),c=[hr(),hr(),hr(),hr()],w=[hr(),hr(),hr(),hr()];if(i=-1,e<64)return-1;if(fr(w,t))return-1;for(o=0;o=0},r.sign.keyPair=function(){var r=new Uint8Array(Vr),n=new Uint8Array(Xr);return tr(r,n),{publicKey:r,secretKey:n}},r.sign.keyPair.fromSecretKey=function(r){if(yr(r),r.length!==Xr)throw new Error("bad secret key size");for(var n=new Uint8Array(Vr),e=0;e/dev/null && browserify test/browser/init.js test/*.quick.js | uglifyjs -c -m -o test/browser/_bundle-quick.js 2>/dev/null", + "lint": "eslint nacl.js nacl-fast.js test/*.js test/benchmark/*.js", + "test": "npm run test-node-all && npm run test-browser", + "test-browser": "NACL_SRC=${NACL_SRC:='nacl.min.js'} && npm run build-test-browser && cat $NACL_SRC test/browser/_bundle.js | tape-run | faucet", + "test-node": "tape test/*.js | faucet", + "test-node-all": "make -C test/c && tape test/*.js test/c/*.js | faucet" + }, + "types": "nacl.d.ts", + "version": "0.14.5" +} diff --git a/reverse_engineering/package-lock.json b/reverse_engineering/package-lock.json index 37da0eb..fa9a449 100644 --- a/reverse_engineering/package-lock.json +++ b/reverse_engineering/package-lock.json @@ -12,11 +12,28 @@ "safer-buffer": "~2.1.0" } }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, + "cpu-features": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.2.tgz", + "integrity": "sha512-/2yieBqvMcRj8McNzkycjW2v3OIUOibBfd2dLEJ0nWts8NobAxwiyw9phVNS6oDL8x8tz9F7uNVFEVpJncQpeA==", + "optional": true, + "requires": { + "nan": "^2.14.1" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -40,6 +57,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "optional": true + }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -142,11 +165,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, "split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", @@ -156,28 +174,16 @@ } }, "ssh2": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-0.5.4.tgz", - "integrity": "sha1-G/a2soyW6u8mf01sRqWiUXpZnic=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.4.0.tgz", + "integrity": "sha512-XvXwcXKvS452DyQvCa6Ct+chpucwc/UyxgliYz+rWXJ3jDHdtBb9xgmxJdMmnIn5bpgGAEV3KaEsH98ZGPHqwg==", "requires": { - "ssh2-streams": "~0.1.15" + "asn1": "^0.2.4", + "bcrypt-pbkdf": "^1.0.2", + "cpu-features": "0.0.2", + "nan": "^2.15.0" } }, - "ssh2-streams": { - "version": "0.1.20", - "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.1.20.tgz", - "integrity": "sha1-URGNFUVV31Rp7h9n4M8efoosDjo=", - "requires": { - "asn1": "~0.2.0", - "semver": "^5.1.0", - "streamsearch": "~0.1.2" - } - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -187,15 +193,20 @@ } }, "tunnel-ssh": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.4.tgz", - "integrity": "sha512-CjBqboGvAbM7iXSX2F95kzoI+c2J81YkrHbyyo4SWNKCzU6w5LfEvXBCHu6PPriYaNvfhMKzD8bFf5Vl14YTtg==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/tunnel-ssh/-/tunnel-ssh-4.1.6.tgz", + "integrity": "sha512-y7+x+T3F3rkx2Zov5Tk9DGfeEBVAdWU3A/91E0Dk5rrZ/VFIlpV2uhhRuaISJUdyG0N+Lcp1fXZMXz+ovPt5vA==", "requires": { "debug": "2.6.9", "lodash.defaults": "^4.1.0", - "ssh2": "0.5.4" + "ssh2": "1.4.0" } }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/reverse_engineering/package.json b/reverse_engineering/package.json index 5787c42..69069a2 100644 --- a/reverse_engineering/package.json +++ b/reverse_engineering/package.json @@ -5,7 +5,7 @@ "author": "Hackolade", "dependencies": { "pg": "^8.7.1", - "tunnel-ssh": "^4.1.4" + "tunnel-ssh": "^4.1.6" }, "installed": true }