|
100 | 100 | expect(ftp_scanner.errors[:ftp_timeout]).to be_empty |
101 | 101 | end |
102 | 102 | end |
| 103 | + end |
103 | 104 |
|
104 | | - |
| 105 | + describe '#banner' do |
| 106 | + it 'is a public method' do |
| 107 | + expect(described_class.public_method_defined?(:banner)).to be true |
| 108 | + end |
105 | 109 | end |
106 | 110 |
|
107 | 111 | context '#attempt_login' do |
| 112 | + let(:mock_socket) { double('socket') } |
| 113 | + |
108 | 114 | before(:example) do |
109 | 115 | ftp_scanner.host = '127.0.0.1' |
110 | 116 | ftp_scanner.port = 21 |
|
114 | 120 | ftp_scanner.cred_details = detail_group |
115 | 121 | end |
116 | 122 |
|
| 123 | + context 'when the connection fails' do |
117 | 124 |
|
118 | | - context 'when it fails' do |
119 | | - |
120 | | - it 'returns Metasploit::Model::Login::Status::UNABLE_TO_CONNECT for a Rex::ConnectionError' do |
| 125 | + it 'returns UNABLE_TO_CONNECT for a Rex::ConnectionError' do |
121 | 126 | expect(Rex::Socket::Tcp).to receive(:create) { raise Rex::ConnectionError } |
122 | 127 | expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
123 | 128 | end |
124 | 129 |
|
125 | | - it 'returns Metasploit::Model::Login::Status::UNABLE_TO_CONNECT for a Rex::AddressInUse' do |
| 130 | + it 'returns UNABLE_TO_CONNECT for a Rex::AddressInUse' do |
126 | 131 | expect(Rex::Socket::Tcp).to receive(:create) { raise Rex::AddressInUse } |
127 | 132 | expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
128 | 133 | end |
129 | 134 |
|
130 | | - it 'returns :connection_disconnect for a ::EOFError' do |
| 135 | + it 'returns UNABLE_TO_CONNECT for a ::EOFError' do |
131 | 136 | expect(Rex::Socket::Tcp).to receive(:create) { raise ::EOFError } |
132 | 137 | expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
133 | 138 | end |
134 | 139 |
|
135 | | - it 'returns :connection_disconnect for a ::Timeout::Error' do |
| 140 | + it 'returns UNABLE_TO_CONNECT for a ::Timeout::Error' do |
136 | 141 | expect(Rex::Socket::Tcp).to receive(:create) { raise ::Timeout::Error } |
137 | 142 | expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
138 | 143 | end |
139 | 144 |
|
| 145 | + it 'returns UNABLE_TO_CONNECT for a Errno::ECONNRESET' do |
| 146 | + expect(Rex::Socket::Tcp).to receive(:create) { raise Errno::ECONNRESET } |
| 147 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
| 148 | + end |
| 149 | + |
| 150 | + it 'returns UNABLE_TO_CONNECT for a Rex::ConnectionTimeout' do |
| 151 | + expect(Rex::Socket::Tcp).to receive(:create) { raise Rex::ConnectionTimeout } |
| 152 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
| 153 | + end |
| 154 | + |
| 155 | + it 'sets proof to the exception message' do |
| 156 | + expect(Rex::Socket::Tcp).to receive(:create) { raise ::Timeout::Error, 'connection timed out' } |
| 157 | + expect(ftp_scanner.attempt_login(pub_pri).proof).to eq 'connection timed out' |
| 158 | + end |
| 159 | + |
140 | 160 | end |
141 | 161 |
|
142 | | - context 'when it succeeds' do |
| 162 | + context 'when the connection succeeds' do |
| 163 | + before(:example) do |
| 164 | + allow(ftp_scanner).to receive(:connect).and_return(mock_socket) |
| 165 | + allow(ftp_scanner).to receive(:disconnect) |
| 166 | + end |
| 167 | + |
| 168 | + context 'and the login fails' do |
| 169 | + |
| 170 | + it 'returns UNABLE_TO_CONNECT when send_user returns nil' do |
| 171 | + allow(ftp_scanner).to receive(:send_user).and_return(nil) |
| 172 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
| 173 | + end |
| 174 | + |
| 175 | + it 'sets proof to the expected string when the response is nil' do |
| 176 | + allow(ftp_scanner).to receive(:send_user).and_return(nil) |
| 177 | + expect(ftp_scanner.attempt_login(pub_pri).proof).to eq 'No response to login command' |
| 178 | + end |
| 179 | + |
| 180 | + it 'returns INCORRECT when send_user returns a non-2xx non-331 response' do |
| 181 | + allow(ftp_scanner).to receive(:send_user).and_return("530 Login incorrect\r\n") |
| 182 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::INCORRECT |
| 183 | + end |
143 | 184 |
|
| 185 | + it 'sets proof to the stripped server response when INCORRECT' do |
| 186 | + allow(ftp_scanner).to receive(:send_user).and_return("530 Login incorrect\r\n") |
| 187 | + expect(ftp_scanner.attempt_login(pub_pri).proof).to eq '530 Login incorrect' |
| 188 | + end |
144 | 189 |
|
| 190 | + it 'does not call send_pass when send_user response does not match 331 or 2xx' do |
| 191 | + allow(ftp_scanner).to receive(:send_user).and_return("530 Login incorrect\r\n") |
| 192 | + expect(ftp_scanner).not_to receive(:send_pass) |
| 193 | + ftp_scanner.attempt_login(pub_pri) |
| 194 | + end |
| 195 | + |
| 196 | + it 'returns INCORRECT when send_pass returns a non-2xx response' do |
| 197 | + allow(ftp_scanner).to receive(:send_user).and_return("331 Password required\r\n") |
| 198 | + allow(ftp_scanner).to receive(:send_pass).and_return("530 Login incorrect\r\n") |
| 199 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::INCORRECT |
| 200 | + end |
| 201 | + |
| 202 | + it 'returns INCORRECT when send_user returns 2xx and send_pass returns a non-2xx response' do |
| 203 | + allow(ftp_scanner).to receive(:send_user).and_return("230 Login successful\r\n") |
| 204 | + allow(ftp_scanner).to receive(:send_pass).and_return("530 Login incorrect\r\n") |
| 205 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::INCORRECT |
| 206 | + end |
| 207 | + |
| 208 | + it 'returns UNABLE_TO_CONNECT when send_pass returns nil' do |
| 209 | + allow(ftp_scanner).to receive(:send_user).and_return("331 Password required\r\n") |
| 210 | + allow(ftp_scanner).to receive(:send_pass).and_return(nil) |
| 211 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
| 212 | + end |
| 213 | + |
| 214 | + end |
| 215 | + |
| 216 | + context 'and the login succeeds' do |
| 217 | + |
| 218 | + it 'returns SUCCESSFUL when send_user returns 331 and send_pass returns 2xx' do |
| 219 | + allow(ftp_scanner).to receive(:send_user).and_return("331 Password required\r\n") |
| 220 | + allow(ftp_scanner).to receive(:send_pass).and_return("230 Login successful\r\n") |
| 221 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::SUCCESSFUL |
| 222 | + end |
| 223 | + |
| 224 | + it 'returns SUCCESSFUL when send_user returns 2xx and send_pass returns 2xx' do |
| 225 | + allow(ftp_scanner).to receive(:send_user).and_return("230 Login successful\r\n") |
| 226 | + allow(ftp_scanner).to receive(:send_pass).and_return("230 Already logged in\r\n") |
| 227 | + expect(ftp_scanner.attempt_login(pub_pri).status).to eq Metasploit::Model::Login::Status::SUCCESSFUL |
| 228 | + end |
| 229 | + |
| 230 | + it 'sets proof to the stripped server response' do |
| 231 | + allow(ftp_scanner).to receive(:send_user).and_return("331 Password required\r\n") |
| 232 | + allow(ftp_scanner).to receive(:send_pass).and_return("230 Login successful\r\n") |
| 233 | + expect(ftp_scanner.attempt_login(pub_pri).proof).to eq "230 Login successful" |
| 234 | + end |
| 235 | + |
| 236 | + end |
| 237 | + |
| 238 | + context 'result metadata' do |
| 239 | + before(:example) do |
| 240 | + allow(ftp_scanner).to receive(:send_user).and_return("331 Password required\r\n") |
| 241 | + allow(ftp_scanner).to receive(:send_pass).and_return("230 Login successful\r\n") |
| 242 | + end |
| 243 | + |
| 244 | + it 'sets result.host to the scanner host' do |
| 245 | + expect(ftp_scanner.attempt_login(pub_pri).host).to eq '127.0.0.1' |
| 246 | + end |
| 247 | + |
| 248 | + it 'sets result.port to the scanner port' do |
| 249 | + expect(ftp_scanner.attempt_login(pub_pri).port).to eq 21 |
| 250 | + end |
| 251 | + |
| 252 | + it 'sets result.protocol to tcp' do |
| 253 | + expect(ftp_scanner.attempt_login(pub_pri).protocol).to eq 'tcp' |
| 254 | + end |
| 255 | + |
| 256 | + it 'sets result.service_name to ftp' do |
| 257 | + expect(ftp_scanner.attempt_login(pub_pri).service_name).to eq 'ftp' |
| 258 | + end |
| 259 | + |
| 260 | + end |
145 | 261 | end |
146 | 262 | end |
147 | 263 |
|
|
0 commit comments