File: ssh

package info (click to toggle)
plinth 19.1%2Bdeb10u2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 28,292 kB
  • sloc: python: 22,066; xml: 12,007; sh: 568; javascript: 406; pascal: 74; makefile: 49; php: 11
file content (120 lines) | stat: -rwxr-xr-x 3,583 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/python3
#
# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

"""
Configuration helper for SSH server.
"""

import argparse
import os
import pwd
import shutil
import stat
import subprocess
import sys

from plinth import action_utils


def parse_arguments():
    """Return parsed command line arguments as dictionary."""
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')

    subparsers.add_parser('setup', help='Setup SSH server')

    get_keys = subparsers.add_parser('get-keys',
                                     help='Get SSH authorized keys')
    get_keys.add_argument('--username')

    set_keys = subparsers.add_parser('set-keys',
                                     help='Set SSH authorized keys')
    set_keys.add_argument('--username')
    set_keys.add_argument('--keys')

    subparsers.required = True
    return parser.parse_args()


def subcommand_setup(arguments):
    """Setup Open SSH server.

    Regenerates deleted SSH keys. This is necessary when FreedomBox image is
    being used. During the image building process the SSH keys are removed and
    start OpenSSH server fails without the keys.

    If the keys already exist, do nothing. This is necessary when a user
    installs FreedomBox using an apt package. SSH keys exist and running
    reconfigure on the openssh-server package does not regenerate them.

    """
    action_utils.dpkg_reconfigure('openssh-server', {})


def get_user_homedir(username):
    """Return the home dir of a user by looking up in password database."""
    try:
        return pwd.getpwnam(username).pw_dir
    except KeyError as exception:
        print('Username not found')
        sys.exit(1)


def subcommand_get_keys(arguments):
    """Get SSH authorized keys."""
    user = arguments.username

    path = os.path.join(get_user_homedir(user), '.ssh', 'authorized_keys')
    try:
        with open(path, 'r') as file_handle:
            print(file_handle.read())
    except FileNotFoundError:
        pass


def subcommand_set_keys(arguments):
    """Set SSH authorized keys."""
    user = arguments.username

    ssh_folder = os.path.join(get_user_homedir(user), '.ssh')
    key_file_path = os.path.join(ssh_folder, 'authorized_keys')

    subprocess.check_call(['mkhomedir_helper', user])

    if not os.path.exists(ssh_folder):
        os.makedirs(ssh_folder)
        shutil.chown(ssh_folder, user, 'users')

    with open(key_file_path, 'w') as file_handle:
        file_handle.write(arguments.keys)

    shutil.chown(key_file_path, user, 'users')
    os.chmod(key_file_path, stat.S_IRUSR | stat.S_IWUSR)


def main():
    """Parse arguments and perform all duties."""
    arguments = parse_arguments()

    subcommand = arguments.subcommand.replace('-', '_')
    subcommand_method = globals()['subcommand_' + subcommand]
    subcommand_method(arguments)


if __name__ == '__main__':
    main()