Skip to content

Commit

Permalink
[project @ Arch-1:[email protected]%secsh--dev--1.0--patch-16]
Browse files Browse the repository at this point in the history
hook up server-side kex-gex; add more documentation
group-exchange kex should work now on the server side.  it will only be
advertised if a "moduli" file has been loaded (see the -gasp- docs) so we
don't spend hours (literally. hours.) computing primes.  some of the logic
was previously wrong, too, since it had never been tested.

fixed repr() string for Transport/BaseTransport.  moved is_authenticated to
Transport where it belongs.

added lots of documentation (but still only about 10% documented).  lots of
methods were made private finally.
  • Loading branch information
Robey Pointer committed Dec 28, 2003
1 parent eb4c279 commit 36d6d95
Show file tree
Hide file tree
Showing 11 changed files with 507 additions and 275 deletions.
4 changes: 2 additions & 2 deletions NOTES
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ from BaseTransport:
get_server_key
close
get_remote_server_key
is_active
is_authenticated
* is_active
open_session
open_channel
renegotiate_keys
check_channel_request

from Transport:
* is_authenticated
auth_key
auth_password
get_allowed_auths
Expand Down
2 changes: 1 addition & 1 deletion demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def load_host_keys():
t.ultra_debug = 0
t.start_client(event)
# print repr(t)
event.wait(10)
event.wait(15)
if not t.is_active():
print '*** SSH negotiation failed.'
sys.exit(1)
Expand Down
8 changes: 7 additions & 1 deletion demo_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ def check_shell_request(self):
try:
event = threading.Event()
t = ServerTransport(client)
try:
t.load_server_moduli()
except:
print '(Failed to load moduli -- gex will be unsupported.)'
raise
t.add_server_key(host_key)
t.ultra_debug = 0
t.start_server(event)
Expand All @@ -81,10 +86,11 @@ def check_shell_request(self):
# print repr(t)

# wait for auth
chan = t.accept(10)
chan = t.accept(20)
if chan is None:
print '*** No channel.'
sys.exit(1)
print 'Authenticated!'
chan.event.wait(10)
if not chan.event.isSet():
print '*** Client never asked for a shell.'
Expand Down
2 changes: 1 addition & 1 deletion paramiko/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
from dsskey import DSSKey
from util import hexify

__all__ = [ 'Transport', 'Channel', 'RSAKey', 'DSSKey', 'hexify' ]
#__all__ = [ 'Transport', 'Channel', 'RSAKey', 'DSSKey', 'hexify' ]
80 changes: 54 additions & 26 deletions paramiko/auth_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,45 @@ class Transport(BaseTransport):

def __init__(self, sock):
BaseTransport.__init__(self, sock)
self.authenticated = False
self.auth_event = None
# for server mode:
self.auth_username = None
self.auth_fail_count = 0
self.auth_complete = 0

def request_auth(self):
def __repr__(self):
if not self.active:
return '<paramiko.Transport (unconnected)>'
out = '<paramiko.Transport'
if self.local_cipher != '':
out += ' (cipher %s)' % self.local_cipher
if self.authenticated:
if len(self.channels) == 1:
out += ' (active; 1 open channel)'
else:
out += ' (active; %d open channels)' % len(self.channels)
elif self.initial_kex_done:
out += ' (connected; awaiting auth)'
else:
out += ' (connecting)'
out += '>'
return out

def is_authenticated(self):
"""
Return true if this session is active and authenticated.
@return: True if the session is still open and has been authenticated successfully;
False if authentication failed and/or the session is closed.
"""
return self.authenticated and self.active

def _request_auth(self):
m = Message()
m.add_byte(chr(MSG_SERVICE_REQUEST))
m.add_string('ssh-userauth')
self.send_message(m)
self._send_message(m)

def auth_key(self, username, key, event):
if (not self.active) or (not self.initial_kex_done):
Expand All @@ -41,7 +69,7 @@ def auth_key(self, username, key, event):
self.auth_method = 'publickey'
self.username = username
self.private_key = key
self.request_auth()
self._request_auth()
finally:
self.lock.release()

Expand All @@ -56,7 +84,7 @@ def auth_password(self, username, password, event):
self.auth_method = 'password'
self.username = username
self.password = password
self.request_auth()
self._request_auth()
finally:
self.lock.release()

Expand All @@ -66,7 +94,7 @@ def disconnect_service_not_available(self):
m.add_int(DISCONNECT_SERVICE_NOT_AVAILABLE)
m.add_string('Service not available')
m.add_string('en')
self.send_message(m)
self._send_message(m)
self.close()

def disconnect_no_more_auth(self):
Expand All @@ -75,7 +103,7 @@ def disconnect_no_more_auth(self):
m.add_int(DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE)
m.add_string('No more auth methods available')
m.add_string('en')
self.send_message(m)
self._send_message(m)
self.close()

def parse_service_request(self, m):
Expand All @@ -85,15 +113,15 @@ def parse_service_request(self, m):
m = Message()
m.add_byte(chr(MSG_SERVICE_ACCEPT))
m.add_string(service)
self.send_message(m)
self._send_message(m)
return
# dunno this one
self.disconnect_service_not_available()

def parse_service_accept(self, m):
service = m.get_string()
if service == 'ssh-userauth':
self.log(DEBUG, 'userauth is OK')
self._log(DEBUG, 'userauth is OK')
m = Message()
m.add_byte(chr(MSG_USERAUTH_REQUEST))
m.add_string(self.username)
Expand All @@ -109,9 +137,9 @@ def parse_service_accept(self, m):
m.add_string(self.private_key.sign_ssh_session(self.randpool, self.H, self.username))
else:
raise SSHException('Unknown auth method "%s"' % self.auth_method)
self.send_message(m)
self._send_message(m)
else:
self.log(DEBUG, 'Service request "%s" accepted (?)' % service)
self._log(DEBUG, 'Service request "%s" accepted (?)' % service)

def get_allowed_auths(self, username):
"override me!"
Expand All @@ -136,20 +164,20 @@ def parse_userauth_request(self, m):
m.add_byte(chr(MSG_USERAUTH_FAILURE))
m.add_string('none')
m.add_boolean(0)
self.send_message(m)
self._send_message(m)
return
if self.auth_complete:
# ignore
return
username = m.get_string()
service = m.get_string()
method = m.get_string()
self.log(DEBUG, 'Auth request (type=%s) service=%s, username=%s' % (method, service, username))
self._log(DEBUG, 'Auth request (type=%s) service=%s, username=%s' % (method, service, username))
if service != 'ssh-connection':
self.disconnect_service_not_available()
return
if (self.auth_username is not None) and (self.auth_username != username):
self.log(DEBUG, 'Auth rejected because the client attempted to change username in mid-flight')
self._log(DEBUG, 'Auth rejected because the client attempted to change username in mid-flight')
self.disconnect_no_more_auth()
return
if method == 'none':
Expand All @@ -160,7 +188,7 @@ def parse_userauth_request(self, m):
if changereq:
# always treated as failure, since we don't support changing passwords, but collect
# the list of valid auth types from the callback anyway
self.log(DEBUG, 'Auth request to change passwords (rejected)')
self._log(DEBUG, 'Auth request to change passwords (rejected)')
newpassword = m.get_string().decode('UTF-8')
result = self.AUTH_FAILED
else:
Expand All @@ -173,50 +201,50 @@ def parse_userauth_request(self, m):
# okay, send result
m = Message()
if result == self.AUTH_SUCCESSFUL:
self.log(DEBUG, 'Auth granted.')
self._log(DEBUG, 'Auth granted.')
m.add_byte(chr(MSG_USERAUTH_SUCCESS))
self.auth_complete = 1
else:
self.log(DEBUG, 'Auth rejected.')
self._log(DEBUG, 'Auth rejected.')
m.add_byte(chr(MSG_USERAUTH_FAILURE))
m.add_string(self.get_allowed_auths(username))
if result == self.AUTH_PARTIALLY_SUCCESSFUL:
m.add_boolean(1)
else:
m.add_boolean(0)
self.auth_fail_count += 1
self.send_message(m)
self._send_message(m)
if self.auth_fail_count >= 10:
self.disconnect_no_more_auth()

def parse_userauth_success(self, m):
self.log(INFO, 'Authentication successful!')
self.authenticated = 1
self._log(INFO, 'Authentication successful!')
self.authenticated = True
if self.auth_event != None:
self.auth_event.set()

def parse_userauth_failure(self, m):
authlist = m.get_list()
partial = m.get_boolean()
if partial:
self.log(INFO, 'Authentication continues...')
self.log(DEBUG, 'Methods: ' + str(partial))
self._log(INFO, 'Authentication continues...')
self._log(DEBUG, 'Methods: ' + str(partial))
# FIXME - do something
pass
self.log(INFO, 'Authentication failed.')
self.authenticated = 0
self._log(INFO, 'Authentication failed.')
self.authenticated = False
self.close()
if self.auth_event != None:
self.auth_event.set()

def parse_userauth_banner(self, m):
banner = m.get_string()
lang = m.get_string()
self.log(INFO, 'Auth banner: ' + banner)
self._log(INFO, 'Auth banner: ' + banner)
# who cares.

handler_table = BaseTransport.handler_table.copy()
handler_table.update({
_handler_table = BaseTransport._handler_table.copy()
_handler_table.update({
MSG_SERVICE_REQUEST: parse_service_request,
MSG_SERVICE_ACCEPT: parse_service_accept,
MSG_USERAUTH_REQUEST: parse_userauth_request,
Expand Down
Loading

0 comments on commit 36d6d95

Please sign in to comment.