Skip to content

Commit

Permalink
Merge b076c10 into e941d56
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianDeiss committed Aug 25, 2014
2 parents e941d56 + b076c10 commit 3cae3a2
Show file tree
Hide file tree
Showing 29 changed files with 2,379 additions and 52 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -5,6 +5,7 @@ dist/
paramiko.egg-info/
test.log
docs/
demos/*.log
!sites/docs
_build
.coverage
18 changes: 18 additions & 0 deletions README
Expand Up @@ -72,6 +72,24 @@ Bugs & Support
Please file bug reports at https://github.com/paramiko/paramiko/. There is currently no mailing list but we plan to create a new one ASAP.


Kerberos Support
----------------

If you want paramiko to do kerberos authentication or key exchange using GSS-API or SSPI, you
need the following python packages:

- pyasn1 0.1.7 or better
- python-gssapi 0.6.1 or better (Unix)
- pywin32 2.1.8 or better (Windows)

So you have to install pyasn1 and python-gssapi on Unix or pywin32 on Windows.
To enable GSS-API / SSPI authentication or key exchange see the demos or paramiko docs.
Note: If you use Microsoft SSPI for kerberos authentication and credential
delegation in paramiko, make sure that the target host is trusted for
delegation in the active directory configuration. For details see:
http://technet.microsoft.com/en-us/library/cc738491%28v=ws.10%29.aspx


Demo
----

Expand Down
37 changes: 35 additions & 2 deletions demos/demo_server.py
Expand Up @@ -66,9 +66,39 @@ def check_auth_publickey(self, username, key):
if (username == 'robey') and (key == self.good_pub_key):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED

def check_auth_gssapi_with_mic(self, username,
gss_authenticated=paramiko.AUTH_FAILED,
cc_file=None):
"""
@note: We are just checking in L{AuthHandler} that the given user is
a valid krb5 principal!
We don't check if the krb5 principal is allowed to log in on
the server, because there is no way to do that in python. So
if you develop your own SSH server with paramiko for a certain
platform like Linux, you should call C{krb5_kuserok()} in your
local kerberos library to make sure that the krb5_principal has
an account on the server and is allowed to log in as a user.
@see: U{krb5_kuserok() man page <http://www.unix.com/man-page/all/3/krb5_kuserok/>}
"""
if gss_authenticated == paramiko.AUTH_SUCCESSFUL:
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED

def check_auth_gssapi_keyex(self, username,
gss_authenticated=paramiko.AUTH_FAILED,
cc_file=None):
if gss_authenticated == paramiko.AUTH_SUCCESSFUL:
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED

def enable_auth_gssapi(self):
UseGSSAPI = True
GSSAPICleanupCredentials = False
return UseGSSAPI

def get_allowed_auths(self, username):
return 'password,publickey'
return 'gssapi-keyex,gssapi-with-mic,password,publickey'

def check_channel_shell_request(self, channel):
self.event.set()
Expand All @@ -79,6 +109,8 @@ def check_channel_pty_request(self, channel, term, width, height, pixelwidth,
return True


DoGSSAPIKeyExchange = True

# now connect
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Expand All @@ -101,7 +133,8 @@ def check_channel_pty_request(self, channel, term, width, height, pixelwidth,
print('Got a connection!')

try:
t = paramiko.Transport(client)
t = paramiko.Transport(client, gss_kex=DoGSSAPIKeyExchange)
t.set_gss_host(socket.getfqdn(""))
try:
t.load_server_moduli()
except:
Expand Down
19 changes: 14 additions & 5 deletions demos/demo_sftp.py 100755 → 100644
Expand Up @@ -34,6 +34,11 @@
# setup logging
paramiko.util.log_to_file('demo_sftp.log')

# Paramiko client configuration
UseGSSAPI = True # enable GSS-API / SSPI authentication
DoGSSAPIKeyExchange = True
Port = 22

# get hostname
username = ''
if len(sys.argv) > 1:
Expand All @@ -45,10 +50,10 @@
if len(hostname) == 0:
print('*** Hostname required.')
sys.exit(1)
port = 22

if hostname.find(':') >= 0:
hostname, portstr = hostname.split(':')
port = int(portstr)
Port = int(portstr)


# get username
Expand All @@ -57,7 +62,10 @@
username = input('Username [%s]: ' % default_username)
if len(username) == 0:
username = default_username
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
if not UseGSSAPI:
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
else:
password = None


# get host key, if we know one
Expand All @@ -81,8 +89,9 @@

# now, connect and use paramiko Transport to negotiate SSH2 across the connection
try:
t = paramiko.Transport((hostname, port))
t.connect(username=username, password=password, hostkey=hostkey)
t = paramiko.Transport((hostname, Port))
t.connect(hostkey, username, password, gss_host=socket.getfqdn(hostname),
gss_auth=UseGSSAPI, gss_kex=DoGSSAPIKeyExchange)
sftp = paramiko.SFTPClient.from_transport(t)

# dirlist on remote host
Expand Down
24 changes: 20 additions & 4 deletions demos/demo_simple.py
Expand Up @@ -36,6 +36,10 @@

# setup logging
paramiko.util.log_to_file('demo_simple.log')
# Paramiko client configuration
UseGSSAPI = True # enable GSS-API / SSPI authentication
DoGSSAPIKeyExchange = True
Port = 22

# get hostname
username = ''
Expand All @@ -48,10 +52,10 @@
if len(hostname) == 0:
print('*** Hostname required.')
sys.exit(1)
port = 22

if hostname.find(':') >= 0:
hostname, portstr = hostname.split(':')
port = int(portstr)
Port = int(portstr)


# get username
Expand All @@ -60,7 +64,8 @@
username = input('Username [%s]: ' % default_username)
if len(username) == 0:
username = default_username
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
if not UseGSSAPI or (not UseGSSAPI and not DoGSSAPIKeyExchange):
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))


# now, connect and use paramiko Client to negotiate SSH2 across the connection
Expand All @@ -69,7 +74,18 @@
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
print('*** Connecting...')
client.connect(hostname, port, username, password)
if not UseGSSAPI or (not UseGSSAPI and not DoGSSAPIKeyExchange):
client.connect(hostname, Port, username, password)
else:
# SSPI works only with the FQDN of the target host
hostname = socket.getfqdn(hostname)
try:
client.connect(hostname, Port, username, gss_auth=UseGSSAPI,
gss_kex=DoGSSAPIKeyExchange)
except Exception:
password = getpass.getpass('Password for %s@%s: ' % (username, hostname))
client.connect(hostname, Port, username, password)

chan = client.invoke_shell()
print(repr(client.get_transport()))
print('*** Here we go!\n')
Expand Down
1 change: 1 addition & 0 deletions paramiko/__init__.py
Expand Up @@ -31,6 +31,7 @@
from paramiko.transport import SecurityOptions, Transport
from paramiko.client import SSHClient, MissingHostKeyPolicy, AutoAddPolicy, RejectPolicy, WarningPolicy
from paramiko.auth_handler import AuthHandler
from paramiko.ssh_gss import GSSAuth, GSS_AUTH_AVAILABLE
from paramiko.channel import Channel, ChannelFile
from paramiko.ssh_exception import SSHException, PasswordRequiredException, \
BadAuthenticationType, ChannelException, BadHostKeyException, \
Expand Down
1 change: 1 addition & 0 deletions paramiko/agent.py
Expand Up @@ -43,6 +43,7 @@
SSH2_AGENT_SIGN_RESPONSE = 14



class AgentSSH(object):
def __init__(self):
self._conn = None
Expand Down

0 comments on commit 3cae3a2

Please sign in to comment.