Permalink
Browse files

Release 0.1.0

  • Loading branch information...
dlitz committed Mar 3, 2008
0 parents commit a16e558b113a844f72b13e6aaf74f630522d1974
Showing with 1,389 additions and 0 deletions.
  1. +676 −0 COPYING
  2. +1 −0 MANIFEST.in
  3. +14 −0 NEWS
  4. +57 −0 README
  5. +8 −0 authconfig.ini.example
  6. +73 −0 gen-server-keys.py
  7. +6 −0 pysftpd.ini.example
  8. +44 −0 setup.py
  9. +31 −0 sftp-server.py
  10. +70 −0 sftpd/Authorization.py
  11. +91 −0 sftpd/CLI.py
  12. +104 −0 sftpd/Configuration.py
  13. +89 −0 sftpd/SFTPServer.py
  14. +73 −0 sftpd/SFTPServerInterface.py
  15. +29 −0 sftpd/__init__.py
  16. +23 −0 sftpd/errors.py
676 COPYING

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1 @@
+include README COPYING NEWS sftp-server.py gen-server-keys.py authconfig.ini.example pysftpd.ini.example
14 NEWS
@@ -0,0 +1,14 @@
+====
+NEWS
+====
+
+Highlights of what's new in each release:
+
+
+Releases
+~~~~~~~~
+
+v0.1.0 2008-03-02
+-----------------
+ * Initial release.
+
57 README
@@ -0,0 +1,57 @@
+***********
+* PySFTPd *
+***********
+
+Author: Dwayne C. Litzenberger <dlitz@dlitz.net>
+Homepage: http://www.dlitz.net/software/pysftpd/
+
+PySFTPd is an SFTP server implementation that builds upon Robey Pointer's
+paramiko <http://www.lag.net/paramiko/> secure shell library.
+
+Note: At this time, PySFTPd supports only read-only operation, though you can
+extend it to support read-write operations if you wish.
+
+
+Copyright:
+~~~~~~~~~~
+Copyright (C) 2007-2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+
+PySFTPd is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+Revision History:
+~~~~~~~~~~~~~~~~~
+See the file NEWS for details.
+
+
+Quick Start:
+~~~~~~~~~~~~
+1. Unpack the source distribution.
+
+2. Generate SSH server keys "server_rsa_key" and "server_dss_key"
+
+ ./gen-server-keys.py
+
+3. Copy pysftpd.ini.example to pysftpd.ini and edit it to suit your needs.
+
+4. Copy authconfig.ini.example to authconfig.ini and edit it to suit your
+ needs.
+
+5. Read the usage info for PySFTPd
+
+ ./sftp-server.py --help
+
+5. Start PySFTPd
+
+ ./sftp-server.py -c pysftpd.ini
+
@@ -0,0 +1,8 @@
+[anonymous]
+anonymous = true
+root_path = /var/ftpd
+
+[dwon]
+password = $1$XXXXXXXX$oqV205xSKMnljqNTxnZaP.
+root_path = /
+authorized_keys_file = /home/dwon/.ssh/authorized_keys
@@ -0,0 +1,73 @@
+#!/usr/bin/python -tt
+# -*- coding: ascii -*-
+# Copyright (c) 2007, 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# This file is part of PySFTPd.
+#
+# PySFTPd is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import sys
+import os
+import paramiko
+
+rsa_bits = 3072
+dss_bits = 1024
+
+rsa_key_filename = "server_rsa_key"
+dss_key_filename = "server_dss_key"
+
+def show_progress(s):
+ sys.stdout.write("... " + s)
+ sys.stdout.flush()
+
+def main():
+ status = 0
+
+ if os.path.exists(rsa_key_filename):
+ print >>sys.stderr, "%s already exists. Not generating RSA host key." % (rsa_key_filename,)
+ status = 2
+ elif os.path.exists(rsa_key_filename + ".pub"):
+ print >>sys.stderr, "%s already exists. Not generating RSA host key." % (rsa_key_filename + ".pub",)
+ status = 2
+ else:
+ print "Generating %d-bit RSA host key..." % (rsa_bits,)
+ rsa_key = paramiko.RSAKey.generate(bits=rsa_bits, progress_func=show_progress)
+ print "... Writing %s" % (rsa_key_filename,)
+ rsa_key.write_private_key_file(rsa_key_filename)
+ print "... Writing %s" % (rsa_key_filename + ".pub",)
+ open(rsa_key_filename + ".pub", "w").write("%s %s\n" % (rsa_key.get_name(), rsa_key.get_base64()))
+ del rsa_key
+ print "... done!"
+
+ if os.path.exists(dss_key_filename):
+ print >>sys.stderr, "%s already exists. Not generating DSS host key." % (dss_key_filename,)
+ status = 2
+ elif os.path.exists(dss_key_filename + ".pub"):
+ print >>sys.stderr, "%s already exists. Not generating DSS host key." % (dss_key_filename + ".pub",)
+ status = 2
+ else:
+ print "Generating %d-bit RSA host key..." % (dss_bits,)
+ dss_key = paramiko.DSSKey.generate(bits=dss_bits, progress_func=show_progress)
+ print "... Writing %s" % (dss_key_filename,)
+ dss_key.write_private_key_file(dss_key_filename)
+ print "... Writing %s" % (dss_key_filename + ".pub",)
+ open(dss_key_filename + ".pub", "w").write("%s %s\n" % (dss_key.get_name(), dss_key.get_base64()))
+ del dss_key
+ print "... done!"
+
+ sys.exit(status)
+
+if __name__ == '__main__':
+ main()
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
@@ -0,0 +1,6 @@
+[pysftpd]
+auth_config = ./authconfig.ini
+host_key.0 = ./server_rsa_key
+host_key.1 = ./server_dss_key
+listen_host =
+listen_port = 54321
@@ -0,0 +1,44 @@
+#!/usr/bin/python -tt
+# -*- coding: ascii -*-
+# Copyright (c) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# This file is part of PySFTPd.
+#
+# PySFTPd is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from distutils.core import setup
+
+setup(
+ name='PySFTPd',
+ version='0.1.0', # don't forget to update download_url and "Development Status" below
+ download_url='https://secure.dlitz.net/pub/dlitz/python/pysftpd/PySFTPd-0.1.0.tar.gz',
+ requires=['paramiko (>=1.7.2)'],
+ description='SFTP daemon',
+ long_description="PySFTPd is an SFTP server implementation that builds upon the paramiko secure shell library.",
+ author='Dwayne C. Litzenberger',
+ author_email='dlitz@dlitz.net',
+ url='http://www.dlitz.net/software/pysftpd/',
+ packages=['sftpd'],
+ license='GNU General Public License (GPL) >= 3',
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'Topic :: Internet',
+ 'Topic :: Security :: Cryptography',
+ 'License :: OSI Approved :: GNU General Public License (GPL)',
+ 'Operating System :: POSIX :: Linux',
+ ],
+)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
@@ -0,0 +1,31 @@
+#!/usr/bin/python -tt
+# -*- coding: ascii -*-
+# Copyright (c) 2007, 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# This file is part of PySFTPd.
+#
+# PySFTPd is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import optparse
+import sys
+import os
+import logging
+import pwd
+import grp
+import paramiko
+from sftpd.CLI import CLI
+
+if __name__ == '__main__':
+ CLI().main()
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
@@ -0,0 +1,70 @@
+#!/usr/bin/python -tt
+# -*- coding: ascii -*-
+# Copyright (c) 2007, 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# This file is part of PySFTPd.
+#
+# PySFTPd is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import paramiko
+import crypt
+
+class Authorization(paramiko.ServerInterface):
+
+ users = None
+
+ def __init__(self, users, setAuthUserFunc):
+ self.users = users
+ self._setAuthUser = setAuthUserFunc
+
+ def get_allowed_auths(self, username):
+ return "publickey,password"
+
+ def check_auth_none(self, username):
+ if username == 'anonymous' and username in self.users and self.users[username].anonymous:
+ self._setAuthUser(self.users[username])
+ return paramiko.AUTH_SUCCESSFUL
+ else:
+ return paramiko.AUTH_FAILED
+
+ def check_auth_password(self, username, password):
+ if username == 'anonymous' and username in self.users and self.users[username].anonymous:
+ # 'anonymous' user may use any password
+ pass
+ elif username in self.users:
+ pwhash = self.users[username].password_hash
+ if crypt.crypt(password, pwhash) != pwhash:
+ return paramiko.AUTH_FAILED
+ else:
+ return paramiko.AUTH_FAILED
+ self._setAuthUser(self.users[username])
+ return paramiko.AUTH_SUCCESSFUL
+
+ def check_auth_publickey(self, username, key):
+ if username == 'anonymous' and username in self.users and self.users[username].anonymous:
+ # 'anonymous' user may use any public key
+ pass
+ elif username in self.users:
+ if key not in self.users[username].authorized_keys:
+ return paramiko.AUTH_FAILED
+ else:
+ return paramiko.AUTH_FAILED
+ self._setAuthUser(self.users[username])
+ return paramiko.AUTH_SUCCESSFUL
+
+ def check_channel_request(self, kind, chanid):
+ if kind == 'session':
+ return paramiko.OPEN_SUCCEEDED
+ return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
Oops, something went wrong.

0 comments on commit a16e558

Please sign in to comment.