Giter Site home page Giter Site logo

pylibssh2's Introduction

=========
pylibssh2
=========

:libssh2: Python module
:Copyright: Keyphrene, Wallix
:License: LGPL
:Homepage: http://github.com/wallix/pylibssh2

pylibssh2 1.0.2
================

1.0.0 release, may 2010
1.0.1 release, july 2011
1.0.2 release, apr 2012
1.0.3 release, july 2012

What
----

pylibssh2 is a python binding for libssh2 library, it was forked and rewrote
from scratch using old org.keyphrene (http://sourceforge.net/projects/orgkeyphrene/)
bindings.

Sofian Brabez wrote this extension at Wallix (http://wallix.com) to provide an easy
way to manage SSH2 connection through libssh2 library in python.

This is a C extension module to provide a high level python API. libssh2 API is
fairy well respected and export into a python API.

Packaging and API is documented with epydoc format. 

Requirements
------------

    - python 2.6+ <http://www.python.org>
      (older version before 2.5 aren't supported and not recommended)
    - libssh2 1.2.1+ <http://www.libssh2.org>
      (older version after 0.18 can works too)

Linux Debian/Ubuntu::

    sudo aptitude install python2.6 python2.6-dev libssh2-1 libssh2-1-dev

FreeBSD::

    sudo make -C /usr/ports/lang/python install clean
    sudo make -C /usr/ports/security/libssh2/ install clean

License
-------

Old parts from Keyphrene.org are licensied against GNU Lesser GPL (LGPL) and all
new and rewritten parts from Wallix.com are licensied against LGPL License too.

Portability
-----------

This is developed and tested mostly on Linux, though it should support others posix
systesm.

Bugs & Support
---------------

Bug tracker is available at

    http://github.com/wallix/pylibssh2/issues

Get the source code
    
    git clone http://github.com/wallix/pylibssh2.git

Browse the source code at

    http://github.com/wallix/pylibssh2.git

Download tarballs at

    http://pypi.python.org/packages/source/p/pylibssh2/
    

Example
-------

These following examples are located in examples/ directory.

:scp_upload.py:
    dummy version of scp upload file transfer.

:sftp_listdir.py:
    this example show how to list remote directories through
    SFTP protocol.

:ssh_exec.py:
    this example show how to execute a SSH remote command execution.

:ssh.py:
    this example demonstrate how implement a partial ssh client to get a remote
    shell.

:ssh_x11.py:
    this example demonstrate how implement a X11 forwarding client.

Documentation
-------------

API documentation can be generated with epydoc <http://epydoc.sourceforge.net/> 
with following command line::

    epydoc --no-private -n pylibssh2 -o doc libssh2

    or

    make doc

Install
-------

See the INSTALL file for installation instructions.

Don't hesitate to reports bugs and submit patches, or just mail author.

pylibssh2's People

Contributors

aaloksood avatar kvechera avatar morian avatar octplane avatar ohe avatar pykoder avatar sbz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pylibssh2's Issues

SSH Error: SSH startup: Unable to exchange encryption keys

Hi!
i got that error with old mikrotik

> system routerboard print
       routerboard: yes
             model: "SXT 5HnD"
     serial-number: "292901552E3D"
  current-firmware: "2.32"
  upgrade-firmware: "2.32"

the code is

class SSHIOStream(IOStream):
    SSH_KEY_PREFIX = os.path.join("var", "etc", "ssh")

    def __init__(self, sock, cli, *args, **kwargs):
        super(SSHIOStream, self).__init__(sock, *args, **kwargs)
        self.cli = cli
        self.script = self.cli.script
        self.logger = cli.logger
        self.session = libssh2.Session()
        self.channel = None

    @tornado.gen.coroutine
    def startup(self):
        """
        SSH session startup
        """
        user = self.script.credentials["user"]
        self.logger.debug("Startup ssh session")
        try:
            self.session.set_trace(libssh2.LIBSSH2_TRACE_SOCKET | libssh2.LIBSSH2_TRACE_TRANS)
            self.session.session_method_pref(20,"diffie-hellman-group1-sha1")
            self.session.startup(self.socket)
            host_hash = self.session.hostkey_hash(2)  # SHA1
            self.logger.debug("Connected. Host fingerprint is %s",
                              host_hash.encode("hex"))
            auth_methods = self.session.userauth_list(user).split(",")
            self.logger.debug("Supported authentication methods: %s",
                              ", ".join(auth_methods))
            # Try to authenticate
            authenticated = False
            for method in auth_methods:
                ah = getattr(self, "auth_%s" % method, None)
                if ah:
                    authenticated |= ah()
                    if authenticated:
                        break
            if authenticated:
                self.logger.debug("User is authenticated")
            else:
                self.logger.error("Failed to authenticate user '%s'", user)
                raise self.cli.CLIError("Failed to log in")
            self.logger.debug("Open channel")
            self.channel = self.session.open_session()
            self.channel.pty("xterm")
            self.channel.shell()
            self.channel.setblocking(0)
        except _libssh2.Error, why:
            raise self.cli.CLIError("SSH Error: %s" % why)

i got error on

self.session.startup(self.socket)

because mikrotik wants old style packet. so in console i got
Protocol error: expected packet type 30, got 34

i am using python 2.7 and libssh2 from master branch and Debian 8.4

# dpkg -l | grep libssh2
ii  libssh2-1:amd64                1.4.3-4.1+deb8u1            amd64        SSH2 client-side library
ii  libssh2-1-dev:amd64            1.4.3-4.1+deb8u1            amd64        SSH2 client-side library (development headers)

userauth_agent problem

When i try to use userauth_agent method:

Error: Authentification by public key failed: No authorized key found in ssh-agent! (failed closing the agent socket)
<Greenlet at 0xd37910: runcmd('115.238.73.226')> failed with Error

But:
in the securecrt ssh forwarding is ok

Code:

    ret = self.session.userauth_agent('root')
    while ret == self.LIBSSH2_ERROR_EAGAIN:
        _wait_select(self.session, self.sock)
        ret = self.session.userauth_agent('root')

Thank you for your share!

Compilation error on Mac os X

Hello,

I've used this lib on my Ubuntu -- all worked good, but I can't install on my new mac. There are compilation errors while installing.

  • I sue Python 2.6.7
  • Mac OS X 10.8.3

Error:

clang -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -DMAJOR_VERSION=2 -DMINOR_VERSION=0 -DPATCH_VERSION=2 -I/opt/local/include/ -I/System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 -c src/listener.c -o build/temp.macosx-10.8-intel-2.6/src/listener.o clang: warning: argument unused during compilation: '-mno-fused-madd' clang -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -DMAJOR_VERSION=2 -DMINOR_VERSION=0 -DPATCH_VERSION=2 -I/opt/local/include/ -I/System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 -c src/pylibssh2.c -o build/temp.macosx-10.8-intel-2.6/src/pylibssh2.o clang: warning: argument unused during compilation: '-mno-fused-madd' src/pylibssh2.c:229:15: error: no member named 'st_atim' in 'struct stat' attr->st_atim.tv_sec + attr->st_mtim.tv_nsec * 0.000000001)); ~~~~ ^ src/pylibssh2.c:229:38: error: no member named 'st_mtim' in 'struct stat' attr->st_atim.tv_sec + attr->st_mtim.tv_nsec * 0.000000001)); ~~~~ ^ src/pylibssh2.c:231:15: error: no member named 'st_mtim' in 'struct stat' attr->st_mtim.tv_sec + attr->st_mtim.tv_nsec * 0.000000001)); ~~~~ ^ src/pylibssh2.c:231:38: error: no member named 'st_mtim' in 'struct stat' attr->st_mtim.tv_sec + attr->st_mtim.tv_nsec * 0.000000001)); ~~~~ ^ 4 errors generated. error: command 'clang' failed with exit status 1

Fingerprint string created from non-zero-terminated string

Fingerprint string at the Python side contains random bytes.
Patch below.

From 5700e11605f800cd7b257c8d7903178a260fe2c2 Mon Sep 17 00:00:00 2001
From: Marcin Szewczyk <[email protected]>
Date: Tue, 28 Jun 2011 22:16:47 +0200
Subject: [PATCH 2/2] Truncate hash to an appropriate length.

---
 src/session.c |   20 +++++++++++++++++++-
 1 files changed, 19 insertions(+), 1 deletions(-)

diff --git a/src/session.c b/src/session.c
index 81913b5..ccb6977 100644
--- a/src/session.c
+++ b/src/session.c
@@ -205,6 +205,8 @@ PYLIBSSH2_Session_hostkey_hash(PYLIBSSH2_SESSION *self, PyObject *args)
 {
     int hashtype = LIBSSH2_HOSTKEY_HASH_MD5;
     const char *hash;
+    char buff[20+1];
+    size_t len;

     if (!PyArg_ParseTuple(args, "|i:hostkey_hash", &hashtype)) {
         return NULL;
@@ -219,7 +221,21 @@ PYLIBSSH2_Session_hostkey_hash(PYLIBSSH2_SESSION *self, PyObject *args)
         return Py_None;
     }

-    return PyString_FromString(hash);
+    switch(hashtype) {
+        case LIBSSH2_HOSTKEY_HASH_MD5:
+            len = 16;
+            break;
+        case LIBSSH2_HOSTKEY_HASH_SHA1:
+            len = 20;
+            break;
+        default:
+            len = 0;
+    }
+
+    memcpy(buff, hash, len);
+    buff[len] = '\0';
+
+    return PyString_FromString(buff);
 }
 /* }}} */

@@ -915,3 +931,5 @@ init_libssh2_Session(PyObject *dict)

     return 1;
 }
+
+/* vim: set sw=4: */
-- 
1.7.5.4

No return value where it is declared there should be one

Patch below...

From edd1a5a1aa904491cdd80d301c083e70a7e05cee Mon Sep 17 00:00:00 2001
From: Marcin Szewczyk <[email protected]>
Date: Tue, 28 Jun 2011 22:13:39 +0200
Subject: [PATCH 1/2] Return values as declared. Added _session in
 session_methods.

---
 libssh2/session.py |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libssh2/session.py b/libssh2/session.py
index afed5e3..2b85dc5 100644
--- a/libssh2/session.py
+++ b/libssh2/session.py
@@ -62,7 +62,7 @@ class Session(object):
         @return: 0 on success or negative on failure
         @rtype: int
         """
-        self._session.close(reason)
+        return self._session.close(reason)

     def direct_tcpip(self, host, port, shost, sport):
         """
@@ -183,7 +183,7 @@ class Session(object):
         @return: 0 on success or negative on failure
         @rtype: int
         """
-        self._session.session_methods(method_type, pref)
+        return self._session.session_methods(method_type, pref)

     def session_methods(self):
         """
@@ -193,7 +193,7 @@ class Session(object):
         @return: dictionnary with actual method negociated
         @rtype: dict
         """
-        return self.session_methods()
+        return self._session.session_methods()

     def set_banner(self, banner=_libssh2.DEFAULT_BANNER):
         """
@@ -206,7 +206,7 @@ class Session(object):
         @return: 0 on success or negative on failure
         @rtype: int
         """
-        self._session.set_banner(banner)
+        return self._session.set_banner(banner)

     def sftp_init(self):
         """
@@ -227,7 +227,7 @@ class Session(object):
         @return: 0 on success or negative on failure
         @rtype: int
         """
-        self._session.startup(sock)
+        return self._session.startup(sock)

     def userauth_authenticated(self):
         """
@@ -249,7 +249,7 @@ class Session(object):
         methods
         @rtype: str
         """
-        self._session.userauth_list(username)
+        return self._session.userauth_list(username)

     def userauth_password(self, username, password):
         """
@@ -263,7 +263,7 @@ class Session(object):
         @return: 0 on success or negative on failure
         @rtype: int
         """
-        self._session.userauth_password(username, password)
+        return self._session.userauth_password(username, password)

     def userauth_publickey_fromfile(
             self, username, publickey, privatekey, passphrase
-- 
1.7.5.4

userauth_publickey_fromfile not implemented?

When I use, per the documentation:

session.userauth_publickey_fromfile(
"stephane", os.path.expanduser('/.ssh/id_rsa.pub'), os.path.expanduser('/.ssh/id_rsa'), "secretphrase")

I get:

Traceback (most recent call last):
File "test.py", line 12, in
"stephane", os.path.expanduser('/.ssh/id_rsa.pub'), os.path.expanduser('/.ssh/id_rsa'), "secretphrase")
File "/usr/lib/pymodules/python2.6/libssh2/session.py", line 287, in userauth_publickey_fromfile
raise NotImplementedError()
NotImplementedError

Debian "squeeze" (the stable version) :
Python libssh2 1.0.0

Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2

Accessing Session object from sftp handle

I am building non-blocking sftp support for pylibssh2.

It works just fine except for one thing. When I do a sftp.open or sftp.opendir in non blocking mode, I have to call libssh2_session_last_error to see if this was a EGAIN or some genuine error.

I was not able to access session object from the sftp object in the sftp handle.

I have however worked around this problem by keeping pointer to session object in sftp handle.
Now on my local, sftp works beautifully in non blocking mode.

This is what the code for opendir looks like:

    Py_BEGIN_ALLOW_THREADS
    handle = libssh2_sftp_opendir(self->sftp, path);
    Py_END_ALLOW_THREADS

    if (handle == NULL) {
      if (libssh2_session_last_error(self->session, NULL, NULL, 0) ==
      LIBSSH2_ERROR_EAGAIN){
    return Py_BuildValue("");
      }
      else{
        /* CLEAN: PYLIBSSH2_SFTPHANDLE_CANT_OPENDIR_MSG */
        PyErr_SetString(PYLIBSSH2_Error, "Unable to open sftp directory.");
        return NULL;
      }
    }

Before I send in a merge request, I wanted to make sure if this approach is okay, or if there are other (better) ways to do this.

_libssh2.Error: Unable to close the channel.

Traceback (most recent call last):
  File "test.py", line 94, in <module>
    libssh2_upload()
  File "test.py", line 92, in libssh2_upload
    chan.close()
  File "/usr/local/lib/python2.6/dist-packages/pylibssh2-1.0.1-py2.6-linux-x86_64.egg/libssh2/channel.py", line 53, in close
    return self._channel.close()
_libssh2.Error: Unable to close the channel.

Code being used;

def libssh2_upload():
    import libssh2
    import tempfile
    import os
    import socket

    host = "xxx"
    user = "xxx"
    file_to_send = "/tmp/lol"

    fd, fpath = tempfile.mkstemp()
    fh = os.fdopen(fd, 'w')
    fh.write(key)
    fh.close()

    fd2, fpath2 = tempfile.mkstemp()
    fh2 = os.fdopen(fd2, 'w')
    fh2.write(pubkey)
    fh2.close()

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host, 22))
    sock.setblocking(1)

    session = libssh2.Session()
    session.set_banner()
    session.startup(sock)
    session.userauth_publickey_fromfile(user, fpath2, fpath, "")

    fsize = os.path.getsize(file_to_send)
    chan = session.scp_send(file_to_send, 0700, fsize)

    sf = open(file_to_send, 'rb')
    while True:
        c = sf.read(512)
        if not c:
            break
        chan.write(c)
    chan.close()

libssh2_upload()

Also, the file is corrupt on the other side (md5 mismatch) and the size is very different.

Any ideas?

Thanks

port forwarding

I tried to implement local and remote port forwarding (ssh -L and -R option), using the direct_tcpip and forward_listen channel objects, but I did not succeed. If someone could post a hint or even a code example and add it to the examples section, I would be very grateful. Thank you!

scp examples update

Since I had some trouble getting scp working, I'd thought I'd better share my examples.
In the regular examples there is only a scp_update, which doesn't work, not on OpenBSD at least, and getting a scp_download working was even a bit more awkward. (it now looks so simple though, but I didn't want to use sftp at first...)
Because no EOF is set when downloading, I had to keep an eye on filesize. In the C examples of the libssh2 package, that is the way it is done anyhow.
One would expect that after reading the last block of a file the next read would return "", which could be used to detect the eof. But it doesn't. It just hangs somewhere in a waiting loop, and I couldn't determine how to prevent that.

channel.close() will close the channel, but might generate an error. This is caused by a bug in channel.c line 46, which schould be: if (rc && rc != LIBSSH2_ERROR_EAGAIN)
To upload a file I've rewritten the send routine in the scp_upload.py example as follows. Reading and writing blocks instead of lines.

import os
...
def send(self, remote_path, mode=0644):
    file_size = os.path.getsize(remote_path)
    channel = self.session.scp_send(remote_path, mode, file_size)
    f=open(remote_path, "rb")
    send = 0
    while True:
        data = f.read(1024)
        channel.write(data)
        send = send + len(data)
        if  send >= file_size: 
            break
    f.close()
    channel.close()

To download a file I used the same scp_upload.py example with putting in a receive routine, reading blocks over the channel.
The last block get an extra 0 - eof byte, increasing the filesize, so I strip that (checking if it really is a 0, which can probably be omitted)
The only problem now is to determine the filesize. In C, it comes with the scp_recv call, but pylibssh2 puts a NULL in the fileinfo field :-(. So it has to be done with sftp:

import os
def _prepare_sock(self):
...
    self.sftp = self.session._session.sftp_init()
    ...
def receive(self, remote_path, mode=0644):
    file_size = self.sftp.get_stat(remote_path)[0]
    channel = self.session.scp_recv(remote_path)
    f=open(remote_path, "wb")
    got = 0
    while True:
        data = channel.read(1024)
        got = got + len(data)
        if got > file_size:
            if (data[-1:]=="\0"): # probably not needed
                f.write(data[:-1])
            break
        else:
            f.write(data)
    f.close()
    channel.close()
    os.chmod(remote_path,mode)
...
...
myscp.receive(sys.argv[4])

It would be nice if the regular examples can be updated with these.
Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.