Skip to content

Commit a16e558

Browse files
committed
Release 0.1.0
0 parents  commit a16e558

16 files changed

+1389
-0
lines changed

COPYING

Lines changed: 676 additions & 0 deletions
Large diffs are not rendered by default.

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include README COPYING NEWS sftp-server.py gen-server-keys.py authconfig.ini.example pysftpd.ini.example

NEWS

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
====
2+
NEWS
3+
====
4+
5+
Highlights of what's new in each release:
6+
7+
8+
Releases
9+
~~~~~~~~
10+
11+
v0.1.0 2008-03-02
12+
-----------------
13+
* Initial release.
14+

README

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
***********
2+
* PySFTPd *
3+
***********
4+
5+
Author: Dwayne C. Litzenberger <[email protected]>
6+
Homepage: http://www.dlitz.net/software/pysftpd/
7+
8+
PySFTPd is an SFTP server implementation that builds upon Robey Pointer's
9+
paramiko <http://www.lag.net/paramiko/> secure shell library.
10+
11+
Note: At this time, PySFTPd supports only read-only operation, though you can
12+
extend it to support read-write operations if you wish.
13+
14+
15+
Copyright:
16+
~~~~~~~~~~
17+
Copyright (C) 2007-2008 Dwayne C. Litzenberger <[email protected]>
18+
19+
PySFTPd is free software: you can redistribute it and/or modify it under the
20+
terms of the GNU General Public License as published by the Free Software
21+
Foundation, either version 3 of the License, or (at your option) any later
22+
version.
23+
24+
PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
25+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
26+
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
27+
28+
You should have received a copy of the GNU General Public License along with
29+
this program. If not, see <http://www.gnu.org/licenses/>.
30+
31+
32+
Revision History:
33+
~~~~~~~~~~~~~~~~~
34+
See the file NEWS for details.
35+
36+
37+
Quick Start:
38+
~~~~~~~~~~~~
39+
1. Unpack the source distribution.
40+
41+
2. Generate SSH server keys "server_rsa_key" and "server_dss_key"
42+
43+
./gen-server-keys.py
44+
45+
3. Copy pysftpd.ini.example to pysftpd.ini and edit it to suit your needs.
46+
47+
4. Copy authconfig.ini.example to authconfig.ini and edit it to suit your
48+
needs.
49+
50+
5. Read the usage info for PySFTPd
51+
52+
./sftp-server.py --help
53+
54+
5. Start PySFTPd
55+
56+
./sftp-server.py -c pysftpd.ini
57+

authconfig.ini.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[anonymous]
2+
anonymous = true
3+
root_path = /var/ftpd
4+
5+
[dwon]
6+
password = $1$XXXXXXXX$oqV205xSKMnljqNTxnZaP.
7+
root_path = /
8+
authorized_keys_file = /home/dwon/.ssh/authorized_keys

gen-server-keys.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/python -tt
2+
# -*- coding: ascii -*-
3+
# Copyright (c) 2007, 2008 Dwayne C. Litzenberger <[email protected]>
4+
#
5+
# This file is part of PySFTPd.
6+
#
7+
# PySFTPd is free software: you can redistribute it and/or modify it under the
8+
# terms of the GNU General Public License as published by the Free Software
9+
# Foundation, either version 3 of the License, or (at your option) any later
10+
# version.
11+
#
12+
# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
13+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
import sys
20+
import os
21+
import paramiko
22+
23+
rsa_bits = 3072
24+
dss_bits = 1024
25+
26+
rsa_key_filename = "server_rsa_key"
27+
dss_key_filename = "server_dss_key"
28+
29+
def show_progress(s):
30+
sys.stdout.write("... " + s)
31+
sys.stdout.flush()
32+
33+
def main():
34+
status = 0
35+
36+
if os.path.exists(rsa_key_filename):
37+
print >>sys.stderr, "%s already exists. Not generating RSA host key." % (rsa_key_filename,)
38+
status = 2
39+
elif os.path.exists(rsa_key_filename + ".pub"):
40+
print >>sys.stderr, "%s already exists. Not generating RSA host key." % (rsa_key_filename + ".pub",)
41+
status = 2
42+
else:
43+
print "Generating %d-bit RSA host key..." % (rsa_bits,)
44+
rsa_key = paramiko.RSAKey.generate(bits=rsa_bits, progress_func=show_progress)
45+
print "... Writing %s" % (rsa_key_filename,)
46+
rsa_key.write_private_key_file(rsa_key_filename)
47+
print "... Writing %s" % (rsa_key_filename + ".pub",)
48+
open(rsa_key_filename + ".pub", "w").write("%s %s\n" % (rsa_key.get_name(), rsa_key.get_base64()))
49+
del rsa_key
50+
print "... done!"
51+
52+
if os.path.exists(dss_key_filename):
53+
print >>sys.stderr, "%s already exists. Not generating DSS host key." % (dss_key_filename,)
54+
status = 2
55+
elif os.path.exists(dss_key_filename + ".pub"):
56+
print >>sys.stderr, "%s already exists. Not generating DSS host key." % (dss_key_filename + ".pub",)
57+
status = 2
58+
else:
59+
print "Generating %d-bit RSA host key..." % (dss_bits,)
60+
dss_key = paramiko.DSSKey.generate(bits=dss_bits, progress_func=show_progress)
61+
print "... Writing %s" % (dss_key_filename,)
62+
dss_key.write_private_key_file(dss_key_filename)
63+
print "... Writing %s" % (dss_key_filename + ".pub",)
64+
open(dss_key_filename + ".pub", "w").write("%s %s\n" % (dss_key.get_name(), dss_key.get_base64()))
65+
del dss_key
66+
print "... done!"
67+
68+
sys.exit(status)
69+
70+
if __name__ == '__main__':
71+
main()
72+
73+
# vim:set ts=4 sw=4 sts=4 expandtab:

pysftpd.ini.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[pysftpd]
2+
auth_config = ./authconfig.ini
3+
host_key.0 = ./server_rsa_key
4+
host_key.1 = ./server_dss_key
5+
listen_host =
6+
listen_port = 54321

setup.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/python -tt
2+
# -*- coding: ascii -*-
3+
# Copyright (c) 2008 Dwayne C. Litzenberger <[email protected]>
4+
#
5+
# This file is part of PySFTPd.
6+
#
7+
# PySFTPd is free software: you can redistribute it and/or modify it under the
8+
# terms of the GNU General Public License as published by the Free Software
9+
# Foundation, either version 3 of the License, or (at your option) any later
10+
# version.
11+
#
12+
# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
13+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
from distutils.core import setup
20+
21+
setup(
22+
name='PySFTPd',
23+
version='0.1.0', # don't forget to update download_url and "Development Status" below
24+
download_url='https://secure.dlitz.net/pub/dlitz/python/pysftpd/PySFTPd-0.1.0.tar.gz',
25+
requires=['paramiko (>=1.7.2)'],
26+
description='SFTP daemon',
27+
long_description="PySFTPd is an SFTP server implementation that builds upon the paramiko secure shell library.",
28+
author='Dwayne C. Litzenberger',
29+
author_email='[email protected]',
30+
url='http://www.dlitz.net/software/pysftpd/',
31+
packages=['sftpd'],
32+
license='GNU General Public License (GPL) >= 3',
33+
classifiers=[
34+
'Development Status :: 3 - Alpha',
35+
'Intended Audience :: Developers',
36+
'Intended Audience :: System Administrators',
37+
'Topic :: Internet',
38+
'Topic :: Security :: Cryptography',
39+
'License :: OSI Approved :: GNU General Public License (GPL)',
40+
'Operating System :: POSIX :: Linux',
41+
],
42+
)
43+
44+
# vim:set ts=4 sw=4 sts=4 expandtab:

sftp-server.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/python -tt
2+
# -*- coding: ascii -*-
3+
# Copyright (c) 2007, 2008 Dwayne C. Litzenberger <[email protected]>
4+
#
5+
# This file is part of PySFTPd.
6+
#
7+
# PySFTPd is free software: you can redistribute it and/or modify it under the
8+
# terms of the GNU General Public License as published by the Free Software
9+
# Foundation, either version 3 of the License, or (at your option) any later
10+
# version.
11+
#
12+
# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
13+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
import optparse
20+
import sys
21+
import os
22+
import logging
23+
import pwd
24+
import grp
25+
import paramiko
26+
from sftpd.CLI import CLI
27+
28+
if __name__ == '__main__':
29+
CLI().main()
30+
31+
# vim:set ts=4 sw=4 sts=4 expandtab:

sftpd/Authorization.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/python -tt
2+
# -*- coding: ascii -*-
3+
# Copyright (c) 2007, 2008 Dwayne C. Litzenberger <[email protected]>
4+
#
5+
# This file is part of PySFTPd.
6+
#
7+
# PySFTPd is free software: you can redistribute it and/or modify it under the
8+
# terms of the GNU General Public License as published by the Free Software
9+
# Foundation, either version 3 of the License, or (at your option) any later
10+
# version.
11+
#
12+
# PySFTPd is distributed in the hope that it will be useful, but WITHOUT ANY
13+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
import paramiko
20+
import crypt
21+
22+
class Authorization(paramiko.ServerInterface):
23+
24+
users = None
25+
26+
def __init__(self, users, setAuthUserFunc):
27+
self.users = users
28+
self._setAuthUser = setAuthUserFunc
29+
30+
def get_allowed_auths(self, username):
31+
return "publickey,password"
32+
33+
def check_auth_none(self, username):
34+
if username == 'anonymous' and username in self.users and self.users[username].anonymous:
35+
self._setAuthUser(self.users[username])
36+
return paramiko.AUTH_SUCCESSFUL
37+
else:
38+
return paramiko.AUTH_FAILED
39+
40+
def check_auth_password(self, username, password):
41+
if username == 'anonymous' and username in self.users and self.users[username].anonymous:
42+
# 'anonymous' user may use any password
43+
pass
44+
elif username in self.users:
45+
pwhash = self.users[username].password_hash
46+
if crypt.crypt(password, pwhash) != pwhash:
47+
return paramiko.AUTH_FAILED
48+
else:
49+
return paramiko.AUTH_FAILED
50+
self._setAuthUser(self.users[username])
51+
return paramiko.AUTH_SUCCESSFUL
52+
53+
def check_auth_publickey(self, username, key):
54+
if username == 'anonymous' and username in self.users and self.users[username].anonymous:
55+
# 'anonymous' user may use any public key
56+
pass
57+
elif username in self.users:
58+
if key not in self.users[username].authorized_keys:
59+
return paramiko.AUTH_FAILED
60+
else:
61+
return paramiko.AUTH_FAILED
62+
self._setAuthUser(self.users[username])
63+
return paramiko.AUTH_SUCCESSFUL
64+
65+
def check_channel_request(self, kind, chanid):
66+
if kind == 'session':
67+
return paramiko.OPEN_SUCCEEDED
68+
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
69+
70+
# vim:set ts=4 sw=4 sts=4 expandtab:

0 commit comments

Comments
 (0)