Skip to content

Commit

Permalink
[project @ Arch-1:[email protected]%secsh--dev--1.0--patch-17]
Browse files Browse the repository at this point in the history
lots more documentation, and added Transport.connect()
renamed demo_host_key to demo_rsa_key.  moved changelog to a separate file,
and indicated that future changelog entries should be fetched from tla.
tried to clean up "__all__" in a way that makes epydoc still work.

added lots more documentation, and renamed many methods and vars to hide
them as private non-exported API.

Transport's ModulusPack is now a static member, so it only has to be loaded
once, and can then be used by any future Transport object.

added Transport.connect(), which tries to wrap all the SSH2 negotiation and
authentication into one method.  you should be able to create a Transport,
call connect(), and then create channels.
  • Loading branch information
Robey Pointer committed Dec 30, 2003
1 parent 36d6d95 commit 48c7d88
Show file tree
Hide file tree
Showing 19 changed files with 989 additions and 460 deletions.
42 changes: 42 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

2003-08-24:
* implemented the other hashes: all 4 from the draft are working now
* added 'aes128-cbc' and '3des-cbc' cipher support
* fixed channel eof/close semantics
2003-09-12: version "aerodactyl"
* implemented group-exchange kex ("kex-gex")
* implemented RSA/DSA private key auth
2003-09-13:
* fixed inflate_long and deflate_long to handle negatives, even though
they're never used in the current ssh protocol
2003-09-14:
* fixed session_id handling: re-keying works now
* added the ability for a Channel to have a fileno() for select/poll
purposes, although this will cause worse window performance if the
client app isn't careful
2003-09-16: version "bulbasaur"
* fixed pipe (fileno) method to be nonblocking and it seems to work now
* fixed silly bug that caused large blocks to be truncated
2003-10-08:
* patch to fix Channel.invoke_subsystem and add Channel.exec_command
[vaclav dvorak]
* patch to add Channel.sendall [vaclav dvorak]
* patch to add Channel.shutdown [vaclav dvorak]
* patch to add Channel.makefile and a ChannelFile class which emulates
a python file object [vaclav dvorak]
2003-10-26:
* thread creation no longer happens during construction -- use the new
method "start_client(event)" to get things rolling
* re-keying now takes place after 1GB of data or 1 billion packets
(these limits can be easily changed per-session if needed)
2003-11-06:
* added a demo server and host key
2003-11-09:
* lots of changes to server mode
* ChannelFile supports universal newline mode; fixed readline
* fixed a bug with parsing the remote banner
2003-11-10: version "charmander"
* renamed SSHException -> SecshException
* cleaned up server mode and the demo server

*** for all subsequent changes, please see 'tla changelog'.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# releases:
# aerodactyl (13sep03)
# bulbasaur
# bulbasaur (18sep03)
# charmander (10nov03)

RELEASE=charmander

release:
python ./setup.py sdist --formats=zip

docs:
epydoc -o docs/ paramiko

# places where the version number is stored:
#
# setup.py
# secsh.py
# __init__.py
# README
13 changes: 0 additions & 13 deletions NOTES
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,6 @@ SSHOutputStream --> ssh2 chan --> ssh2 transport --> SOS [no thread]

exported API...

from BaseTransport:
start_client
start_server
add_server_key
get_server_key
close
get_remote_server_key
* is_active
open_session
open_channel
renegotiate_keys
check_channel_request

from Transport:
* is_authenticated
auth_key
Expand Down
43 changes: 0 additions & 43 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -130,49 +130,6 @@ are still running (and you'll have to kill -9 from another shell window).
[fixme: add info about server mode]


*** CHANGELOG

2003-08-24:
* implemented the other hashes: all 4 from the draft are working now
* added 'aes128-cbc' and '3des-cbc' cipher support
* fixed channel eof/close semantics
2003-09-12: version "aerodactyl"
* implemented group-exchange kex ("kex-gex")
* implemented RSA/DSA private key auth
2003-09-13:
* fixed inflate_long and deflate_long to handle negatives, even though
they're never used in the current ssh protocol
2003-09-14:
* fixed session_id handling: re-keying works now
* added the ability for a Channel to have a fileno() for select/poll
purposes, although this will cause worse window performance if the
client app isn't careful
2003-09-16: version "bulbasaur"
* fixed pipe (fileno) method to be nonblocking and it seems to work now
* fixed silly bug that caused large blocks to be truncated
2003-10-08:
* patch to fix Channel.invoke_subsystem and add Channel.exec_command
[vaclav dvorak]
* patch to add Channel.sendall [vaclav dvorak]
* patch to add Channel.shutdown [vaclav dvorak]
* patch to add Channel.makefile and a ChannelFile class which emulates
a python file object [vaclav dvorak]
2003-10-26:
* thread creation no longer happens during construction -- use the new
method "start_client(event)" to get things rolling
* re-keying now takes place after 1GB of data or 1 billion packets
(these limits can be easily changed per-session if needed)
2003-11-06:
* added a demo server and host key
2003-11-09:
* lots of changes to server mode
* ChannelFile supports universal newline mode; fixed readline
* fixed a bug with parsing the remote banner
2003-11-10: version "charmander"
* renamed SSHException -> SecshException
* cleaned up server mode and the demo server


*** MISSING LINKS

* ctr forms of ciphers are missing (blowfish-ctr, aes128-ctr, aes256-ctr)
Expand Down
1 change: 0 additions & 1 deletion demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def load_host_keys():
try:
event = threading.Event()
t = paramiko.Transport(sock)
t.ultra_debug = 0
t.start_client(event)
# print repr(t)
event.wait(15)
Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion demo_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
l.addHandler(lh)

#host_key = paramiko.RSAKey()
#host_key.read_private_key_file('demo_host_key')
#host_key.read_private_key_file('demo_rsa_key')

host_key = paramiko.DSSKey()
host_key.read_private_key_file('demo_dss_key')

print 'Read key: ' + paramiko.hexify(host_key.get_fingerprint())


Expand Down
136 changes: 136 additions & 0 deletions demo_simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/python

import sys, os, base64, getpass, socket, logging, traceback, termios, tty, select
import paramiko


##### utility functions

def load_host_keys():
filename = os.environ['HOME'] + '/.ssh/known_hosts'
keys = {}
try:
f = open(filename, 'r')
except Exception, e:
print '*** Unable to open host keys file (%s)' % filename
return
for line in f:
keylist = line.split(' ')
if len(keylist) != 3:
continue
hostlist, keytype, key = keylist
hosts = hostlist.split(',')
for host in hosts:
if not keys.has_key(host):
keys[host] = {}
keys[host][keytype] = base64.decodestring(key)
f.close()
return keys


# setup logging
l = logging.getLogger("paramiko")
l.setLevel(logging.DEBUG)
if len(l.handlers) == 0:
f = open('demo.log', 'w')
lh = logging.StreamHandler(f)
lh.setFormatter(logging.Formatter('%(levelname)-.3s [%(asctime)s] %(name)s: %(message)s', '%Y%m%d:%H%M%S'))
l.addHandler(lh)

# get hostname
username = ''
if len(sys.argv) > 1:
hostname = sys.argv[1]
if hostname.find('@') >= 0:
username, hostname = hostname.split('@')
else:
hostname = raw_input('Hostname: ')
if len(hostname) == 0:
print '*** Hostname required.'
sys.exit(1)
port = 22
if hostname.find(':') >= 0:
hostname, portstr = hostname.split(':')
port = int(portstr)


# get username
if username == '':
default_username = getpass.getuser()
username = raw_input('Username [%s]: ' % default_username)
if len(username) == 0:
username = default_username
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))


# get host key, if we know one
hostkeytype = None
hostkey = None
hkeys = load_host_keys()
if hkeys.has_key(hostname):
hostkeytype = hkeys[hostname].keys()[0]
hostkey = hkeys[hostname][hostkeytype]
print 'Using host key of type %s' % hostkeytype


# now connect
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((hostname, port))
except Exception, e:
print '*** Connect failed: ' + str(e)
traceback.print_exc()
sys.exit(1)


# finally, use paramiko Transport to negotiate SSH2 across the connection
try:
t = paramiko.Transport(sock)
t.connect(username=username, password=password, hostkeytype=hostkeytype, hostkey=hostkey)
chan = t.open_session()
chan.get_pty()
chan.invoke_shell()
print '*** Here we go!'
print

try:
oldtty = termios.tcgetattr(sys.stdin)
tty.setraw(sys.stdin.fileno())
tty.setcbreak(sys.stdin.fileno())
chan.settimeout(0.0)

while 1:
r, w, e = select.select([chan, sys.stdin], [], [])
if chan in r:
try:
x = chan.recv(1024)
if len(x) == 0:
print '\r\n*** EOF\r\n',
break
sys.stdout.write(x)
sys.stdout.flush()
except socket.timeout:
pass
if sys.stdin in r:
# FIXME: reading 1 byte at a time is incredibly dumb.
x = sys.stdin.read(1)
if len(x) == 0:
print
print '*** Bye.\r\n',
break
chan.send(x)

finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)

chan.close()
t.close()

except Exception, e:
print '*** Caught exception: ' + str(e.__class__) + ': ' + str(e)
traceback.print_exc()
try:
t.close()
except:
pass
sys.exit(1)
24 changes: 0 additions & 24 deletions paramiko.py

This file was deleted.

37 changes: 31 additions & 6 deletions paramiko/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,35 @@
__credits__ = "Huzzah!"


from auth_transport import Transport
from channel import Channel
from rsakey import RSAKey
from dsskey import DSSKey
from util import hexify
import ssh_exception, transport, auth_transport, channel, rsakey, dsskey, util

#__all__ = [ 'Transport', 'Channel', 'RSAKey', 'DSSKey', 'hexify' ]
class SSHException (ssh_exception.SSHException):
pass

class Transport (auth_transport.Transport):
"""
An SSH Transport attaches to a stream (usually a socket), negotiates an
encrypted session, authenticates, and then creates stream tunnels, called
L{Channel}s, across the session. Multiple channels can be multiplexed
across a single session (and often are, in the case of port forwardings).
"""
pass

class Channel (channel.Channel):
"""
A secure tunnel across an SSH L{Transport}. A Channel is meant to behave
like a socket, and has an API that should be indistinguishable from the
python socket API.
"""
pass

class RSAKey (rsakey.RSAKey):
pass

class DSSKey (dsskey.DSSKey):
pass


__all__ = [ 'Transport', 'Channel', 'RSAKey', 'DSSKey', 'transport',
'auth_transport', 'channel', 'rsakey', 'ddskey', 'util',
'SSHException' ]
Loading

0 comments on commit 48c7d88

Please sign in to comment.