Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace optparse to argparse, paramiko to ssh. and add option daemonize. #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@ Examples
Debug level: WARNING, INFO, DEBUG [default: INFO]
-k FILE, --keyfile=FILE
Path to private key, for example /tmp/test_rsa.key
-d, --daemon To launch sftpserver as a daemon. How to kill: kill `cat /tmp/mydaemon.pid`

$ sftpserver -k /tmp/test_rsa.key -l DEBUG


Connecting with a Python client to our server:

>>> import paramiko
>>> import ssh
>>> pkey = paramiko.RSAKey.from_private_key_file('/tmp/test_rsa.key')
>>> transport = paramiko.Transport(('localhost', 3373))
>>> transport = ssh.Transport(('localhost', 3373))
>>> transport.connect(username='admin', password='admin', pkey=pkey)
>>> sftp = paramiko.SFTPClient.from_transport(transport)
>>> sftp = ssh.SFTPClient.from_transport(transport)
>>> sftp.listdir('.')
['loop.py', 'stub_sftp.py']
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ def read(*rel_names):
setup(
name='sftpserver',
version='0.2',
url='http://github.com/rspivak/sftpserver',
url='http://github.com/kk6/sftpserver',
license='MIT',
description='sftpserver - a simple single-threaded sftp server',
author='Ruslan Spivak',
author_email='[email protected]',
packages=find_packages('src'),
package_dir={'': 'src'},
install_requires=['distribute', 'paramiko'],
install_requires=['distribute', 'ssh', 'python-daemon'],
zip_safe=False,
entry_points="""\
[console_scripts]
Expand Down
56 changes: 37 additions & 19 deletions src/sftpserver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@

import time
import socket
import optparse
import argparse
import sys
import textwrap

import paramiko
import ssh
from daemon import DaemonContext
from lockfile.pidlockfile import PIDLockFile

from sftpserver.stub_sftp import StubServer, StubSFTPServer

Expand All @@ -39,8 +41,8 @@


def start_server(host, port, keyfile, level):
paramiko_level = getattr(paramiko.common, level)
paramiko.common.logging.basicConfig(level=paramiko_level)
ssh_level = getattr(ssh.common, level)
ssh.common.logging.basicConfig(level=ssh_level)

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
Expand All @@ -50,11 +52,11 @@ def start_server(host, port, keyfile, level):
while True:
conn, addr = server_socket.accept()

host_key = paramiko.RSAKey.from_private_key_file(keyfile)
transport = paramiko.Transport(conn)
host_key = ssh.RSAKey.from_private_key_file(keyfile)
transport = ssh.Transport(conn)
transport.add_server_key(host_key)
transport.set_subsystem_handler(
'sftp', paramiko.SFTPServer, StubSFTPServer)
'sftp', ssh.SFTPServer, StubSFTPServer)

server = StubServer()
transport.start_server(server=server)
Expand All @@ -69,30 +71,46 @@ def main():
usage: sftpserver [options]
-k/--keyfile should be specified
"""
parser = optparse.OptionParser(usage=textwrap.dedent(usage))
parser.add_option(
parser = argparse.ArgumentParser(usage=textwrap.dedent(usage))
parser.add_argument(
'--host', dest='host', default=HOST,
help='listen on HOST [default: %default]')
parser.add_option(
'-p', '--port', dest='port', type='int', default=PORT,
help='listen on PORT [default: %default]'
help='listen on HOST [default: %(default)s]')
parser.add_argument(
'-p', '--port', dest='port', type=int, default=PORT,
help='listen on PORT [default: %(default)s]'
)
parser.add_option(
parser.add_argument(
'-l', '--level', dest='level', default='INFO',
help='Debug level: WARNING, INFO, DEBUG [default: %default]'
help='Debug level: WARNING, INFO, DEBUG [default: %(default)s]'
)
parser.add_option(
parser.add_argument(
'-k', '--keyfile', dest='keyfile', metavar='FILE',
help='Path to private key, for example /tmp/test_rsa.key'
)
parser.add_argument(
'-d', '--daemon', action='store_true', dest='daemon',
default=False,
help=('To launch sftpserver as a daemon.'
'How to kill: kill `cat /tmp/mydaemon.pid`')
)

options, args = parser.parse_args()
args = parser.parse_args()

if options.keyfile is None:
if args.keyfile is None:
parser.print_help()
sys.exit(-1)

start_server(options.host, options.port, options.keyfile, options.level)
if args.daemon:
dc = DaemonContext(
pidfile=PIDLockFile('/tmp/mydaemon.pid'),
stderr=open('fake_err_console.txt', 'w+')
)
with dc:
start_server(args.host, args.port, args.keyfile,
args.level)
else:
start_server(args.host, args.port, args.keyfile,
args.level)


if __name__ == '__main__':
Expand Down
4 changes: 2 additions & 2 deletions src/sftpserver/stub_sftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"""

import os
from paramiko import ServerInterface, SFTPServerInterface, SFTPServer, SFTPAttributes, \
from ssh import ServerInterface, SFTPServerInterface, SFTPServer, SFTPAttributes, \
SFTPHandle, SFTP_OK, AUTH_SUCCESSFUL, OPEN_SUCCEEDED


Expand Down Expand Up @@ -55,7 +55,7 @@ class StubSFTPServer (SFTPServerInterface):
# assume current folder is a fine root
# (the tests always create and eventualy delete a subfolder, so there shouldn't be any mess)
ROOT = os.getcwd()

def _realpath(self, path):
return self.ROOT + self.canonicalize(path)

Expand Down