banner functionality #58

Closed
wants to merge 1 commit into
from

Projects

None yet

7 participants

@Jhoanor
Contributor
Jhoanor commented Dec 16, 2011

I would like to be able to obtain the banner supplied by a server to which my python script connects using paramiko.
This is to be able to supply reasons for not be able to connect at a certain moment, (can be handy for legal issues as well)
The following changes are in line wich the get_username method.
Tested and works. :-)
I have not updated documentation in the pull request but this line can be added I suppose in the class Transport documentation on http://www.lag.net/paramiko/docs/ :
string get_banner(self)
Return the banner supplied by the remote server.

@ebwolf
ebwolf commented Jan 29, 2013

I was just adding a similar patch to my version of paramiko. It sure would be nice to get this pulled into the trunk.

I are using paramiko in test automation. We need to be able to parse the banner to decide how to authenticate the SSH session. Right now I am replacing the log handler and watching for "auth banner:" in log.info.

Tested in 1.09.0... Sure would be nice!

@lndbrg
Contributor
lndbrg commented Jan 21, 2014

Yes, I'll agree, this should be merged.

@bitprophet bitprophet added a commit that referenced this pull request Feb 11, 2014
@bitprophet bitprophet Changelog re #58 c73616b
@bitprophet
Member

This is in now, thanks!

@bitprophet bitprophet closed this Feb 11, 2014
@ying-wang-

Can anyone give an example of how to use get_banner? I need the banner to calculate the password. Thanks!

@rustyscottweber

(This was a wrong statement.. the real issue is that the banner isn't retrieved for keyboard interactive logon)
Currently there doesn't seem to be a way to get a banner without logging in which is kind of a lame requirement and not at all what I think people were hoping for.. How can one calculate the password if he needs the password to get the banner?
The get banner method should have been a static method that takes in a host name and a port and returns the banner.

@ying-wang-

We use the date and time from the banner to calculate the password. Here is the codelet that works for my situation.

import paramiko

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(ip,username='username',password='anything') # login with invalid password
except:
loginbanner = client._transport.get_banner()
if not loginbanner:
raise IOError('SSH server banner is NOT available')
else:
loginbanner = loginbanner.split()
pwd = calculate_pwd(loginbanner)
client.connect(ip,username='username',password=pwd) # login with calculated password

@rustyscottweber

that method will return None for most servers because the banner is held on the auth_handler which will get systematically overwritten for backup authentication methods. The most common method being keyboard-interactive. If password authentication is not allowed, the auth handler which got the banner correctly and is storing it will be overwritten which means that the default will be populated on the new auth handler. Unless the remote sshd's policy for password authentication, different from keyboard-interactive, is on attempting to get the banner won't work..

@ying-wang-

My codelet has been working so far.

@rustyscottweber

Most likely because your sshd allows password authentication which means paramiko doesn't have to fail over to keyboard interactive or any other type of authentication.

@rustyscottweber

I've been debugging through code and it looks like the _parse_userauth_banner method is never called while dealing with keyboard-interactive which is the true root of the problem. The current work around is to set the policy for the server in the sshd.conf
PasswordAuthentication yes
For people like me where that isn't an option.. I'm working toward a solution.

@rustyscottweber

Here is a much more sure fire way to get the banner of a server.. I suggest that we put this into a static function for paramiko...

        banner = None
        try:
            t = paramiko.Transport((hostname, port))
            t.connect()
            t.auth_none('parmiko_banner_retrieval_service')
        except:
            banner = t.get_banner()
@ying-wang-

Thanks. I'll replace my code with it.

@jossef
jossef commented Jun 9, 2016
# !/usr/bin/python

import paramiko


def grab_banner(ip_address, port):
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(ip_address, port=port, username='username', password='bad-password-on-purpose')
    except:
        return client._transport.get_banner()


if __name__ == '__main__':
    print grab_banner('192.168.1.26', 22)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment