shellinabox : now modified to auto-connect if no password is defined
[slapos.git] / slapos / recipe / shellinabox.py
1 ##############################################################################
2 #
3 # Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
4 #
5 # WARNING: This program as such is intended to be used by professional
6 # programmers who take the whole responsibility of assessing all potential
7 # consequences resulting from its eventual inadequacies and bugs
8 # End users who are looking for a ready-to-use solution with commercial
9 # guarantees and support are strongly adviced to contract a Free Software
10 # Service Company
11 #
12 # This program is Free Software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; either version 3
15 # of the License, or (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #
26 ##############################################################################
27 from getpass import getpass
28 import pwd
29 import grp
30 import os
31 import shlex
32
33 from slapos.recipe.librecipe import GenericBaseRecipe
34
35 def login_shell(args):
36 password = args['password']
37
38 if (password != ''):
39 entered_password = getpass()
40 else:
41 entered_password = ''
42
43 if entered_password != password:
44 return 1
45 else:
46 commandline = shlex.split(args['shell'])
47 path = commandline[0]
48 os.execv(path, commandline)
49
50 def shellinabox(args):
51 certificate_dir = args['certificate_dir']
52 certificate_path = os.path.join(certificate_dir, 'certificate.pem')
53 with open(certificate_path, 'w') as certificate_file:
54 with open(args['ssl_key'], 'r') as key_file:
55 # XXX: Dirty hack in order to make shellinabox work
56 print >> certificate_file, key_file.read().replace(' PRIVATE ',
57 ' RSA PRIVATE ')
58 with open(args['ssl_certificate']) as public_key_file:
59 print >> certificate_file, public_key_file.read()
60
61 user = pwd.getpwuid(os.getuid()).pw_name
62 group = grp.getgrgid(os.getgid()).gr_name
63 service = '/:%(user)s:%(group)s:%(directory)s:%(command)s' % {
64 'user': group,
65 'group': user,
66 'directory': args['directory'],
67 'command': args['login_shell'],
68 }
69
70 command_line = [
71 args['shellinabox'],
72 '-d',
73 '-c', certificate_dir,
74 '-s', service,
75 '--ipv6', args['ipv6'],
76 '-p', args['port'],
77 ]
78
79 # XXX: By default shellinbox drop privileges
80 # switching to nobody:nogroup user.
81 # This force root.
82 if group == 'root':
83 command_line.extend(['-g', group])
84 if user == 'root':
85 command_line.extend(['-u', group])
86
87 os.execv(command_line[0], command_line)
88
89
90 class Recipe(GenericBaseRecipe):
91
92 def install(self):
93 path_list = []
94
95 login_shell = self.createPythonScript(
96 self.options['login-shell'],
97 '%s.login_shell' % __name__,
98 {
99 'password': self.options['password'],
100 'shell': self.options['shell']
101 }
102 )
103 path_list.append(login_shell)
104
105 wrapper = self.createPythonScript(
106 self.options['wrapper'],
107 '%s.shellinabox' % __name__,
108 dict(
109 certificate_dir=self.options['certificate-directory'],
110 ssl_key=self.options['key-file'],
111 ssl_certificate=self.options['cert-file'],
112 shellinabox=self.options['shellinabox-binary'],
113 directory=self.options['directory'],
114 ipv6=self.options['ipv6'],
115 port=self.options['port'],
116 login_shell=login_shell,
117 )
118 )
119 path_list.append(wrapper)
120
121 return [wrapper]