Path: blob/master/spec/lib/rex/proto/postgresql/client_spec.rb
24821 views
# -*- coding: binary -*-12require 'spec_helper'3require 'postgres/postgres-pr/connection'45RSpec.describe Msf::Db::PostgresPR::Connection do6let(:host) { '127.0.0.1' }7let(:port) { 1234 }8let(:info) { "#{host}:#{port}" }9let(:db_name) { 'my_db_name' }10let(:socket) { double(Rex::Socket, peerhost: host, peerport: port) }11let(:message) { Msf::Db::PostgresPR::ReadyForQuery.new('') }1213before do14allow(socket).to receive(:<<)15allow(socket).to receive(:write)16allow(socket).to receive(:read).and_return('S')17allow(socket).to receive(:extend)18allow(socket).to receive(:initsock_with_ssl_version)19allow(Msf::Db::PostgresPR::Message).to receive(:read).and_return(message)20allow(Rex::Socket).to receive(:create_param).and_return(socket)21end2223subject do24described_class.new(db_name, 'username', 'password', "tcp://#{host}:#{port}")25end2627it_behaves_like 'session compatible SQL client'2829describe 'SSL connection' do30let(:ssl_request_message) { instance_double(Msf::Db::PostgresPR::SSLRequest) }31let(:ssl_opts) { { ssl_version: 'TLS1.2', ssl_verify_mode: 'peer', ssl_cipher: 'AES256' } }3233before do34allow(Msf::Db::PostgresPR::SSLRequest).to receive(:new).with(80877103).and_return(ssl_request_message)35allow(ssl_request_message).to receive(:dump).and_return('ssl_request_data')36end3738context 'when SSL is enabled and server supports SSL' do39it 'successfully establishes SSL connection' do40allow(socket).to receive(:read).with(1).and_return('S')4142expect(socket).to receive(:write).with('ssl_request_data')43expect(socket).to receive(:extend).with(Rex::Socket::SslTcp)44expect(socket).to receive(:initsock_with_ssl_version)4546client = described_class.new(db_name, 'username', 'password', "tcp://#{host}:#{port}", nil, true, ssl_opts)47expect(client).to be_a(Msf::Db::PostgresPR::Connection)48end49end5051context 'when SSL is enabled but server does not support SSL' do52it 'raises an error when server responds with N' do53allow(socket).to receive(:read).with(1).and_return('N')5455expect(socket).to receive(:write).with('ssl_request_data')56expect(socket).not_to receive(:extend)5758expect {59described_class.new(db_name, 'username', 'password', "tcp://#{host}:#{port}", nil, true, ssl_opts)60}.to raise_error("SSL connection requested but server at #{host}:#{port} does not support SSL")61end62end6364context 'when SSL is enabled but server responds unexpectedly' do65it 'raises an error for unexpected SSL response' do66allow(socket).to receive(:read).with(1).and_return('X')6768expect(socket).to receive(:write).with('ssl_request_data')69expect(socket).not_to receive(:extend)7071expect {72described_class.new(db_name, 'username', 'password', "tcp://#{host}:#{port}", nil, true, ssl_opts)73}.to raise_error('Unexpected response to SSLRequest: "X"')74end75end7677context 'when SSL is disabled' do78it 'does not attempt SSL handshake' do79expect(socket).not_to receive(:write).with('ssl_request_data')80expect(socket).not_to receive(:extend).with(Rex::Socket::SslTcp)8182client = described_class.new(db_name, 'username', 'password', "tcp://#{host}:#{port}", nil, false, ssl_opts)83expect(client).to be_a(Msf::Db::PostgresPR::Connection)84end85end86end8788describe '#map_compile_os_to_platform' do89[90{ info: 'linux', expected: Msf::Platform::Linux.realname },91{ info: 'linux2.6', expected: Msf::Platform::Linux.realname },92{ info: 'debian-linux-gnu', expected: Msf::Platform::Linux.realname },93{ info: 'win', expected: Msf::Platform::Windows.realname },94{ info: 'windows', expected: Msf::Platform::Windows.realname },95{ info: 'darwin', expected: Msf::Platform::OSX.realname },96{ info: 'osx', expected: Msf::Platform::OSX.realname },97{ info: 'macos', expected: Msf::Platform::OSX.realname },98{ info: 'solaris', expected: Msf::Platform::Solaris.realname },99{ info: 'aix', expected: Msf::Platform::AIX.realname },100{ info: 'hpux', expected: Msf::Platform::HPUX.realname },101{ info: 'irix', expected: Msf::Platform::Irix.realname },102].each do |test|103it "correctly identifies '#{test[:info]}' as '#{test[:expected]}'" do104expect(subject.map_compile_os_to_platform(test[:info])).to eq(test[:expected])105end106end107end108109describe '#map_compile_arch_to_architecture' do110[111{ info: 'x86_64', expected: ARCH_X86_64 },112{ info: 'x86_x64', expected: ARCH_X86_64 },113{ info: 'x64', expected: ARCH_X86_64 },114{ info: '64', expected: ARCH_X86_64 },115{ info: 'x86', expected: ARCH_X86 },116{ info: '86', expected: ARCH_X86 },117{ info: 'i686', expected: ARCH_X86 },118{ info: 'arm64', expected: ARCH_AARCH64 },119{ info: 'arm', expected: ARCH_ARMLE },120{ info: 'sparc', expected: ARCH_SPARC },121{ info: 'sparc64', expected: ARCH_SPARC64 },122{ info: 'ppc', expected: ARCH_PPC },123{ info: 'mips', expected: ARCH_MIPS },124].each do |test|125it "correctly identifies '#{test[:info]}' as '#{test[:expected]}'" do126expect(subject.map_compile_arch_to_architecture(test[:info])).to eq(test[:expected])127end128end129end130131describe '#detect_platform_and_arch' do132[133{ version: 'PostgreSQL 9.4.26 on x86_64-pc-linux-gnu (Debian 9.4.26-1.pgdg90+1), compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit', expected: { arch: 'x86_64', platform: 'Linux' } },134{ version: 'PostgreSQL 14.11 (Debian 14.11-1.pgdg120+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit', expected: { arch: 'x86_64', platform: 'Linux' } },135{ version: 'PostgreSQL 14.11 (Homebrew) on x86_64-apple-darwin22.6.0, compiled by Apple clang version 15.0.0 (clang-1500.1.0.2.5), 64-bit', expected: { arch: 'x86_64', platform: 'OSX' } },136{137version: 'PostgreSQL 14.11 (Homebrew) <arch>-<platform>, compiled by <platform> clang version 15.0.0 (clang-1500.1.0.2.5), <arch>',138expected: {139arch: 'postgresql 14.11 (homebrew) <arch>-<platform>, compiled by <platform> clang version 15.0.0 (clang-1500.1.0.2.5), <arch>',140platform: 'postgresql 14.11 (homebrew) <arch>-<platform>, compiled by <platform> clang version 15.0.0 (clang-1500.1.0.2.5), <arch>'141}142}143].each do |test|144context "when the database is version #{test[:version]}" do145it "returns #{test[:expected]}" do146mock_query_result = instance_double Msf::Db::PostgresPR::Connection::Result, rows: [[test[:version]]]147allow(subject).to receive(:query).with('select version()').and_return(mock_query_result)148149expect(subject.detect_platform_and_arch).to eq test[:expected]150end151end152end153end154end155156157