~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to bin/ivle-buildjail

  • Committer: William Grant
  • Date: 2010-02-23 08:08:27 UTC
  • Revision ID: grantw@unimelb.edu.au-20100223080827-wklsx122pcw79wi7
Reject off-site non-GET requests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
import optparse
20
20
import os
 
21
import stat
21
22
import sys
22
23
import shutil
23
24
 
24
 
import ivle.conf
25
25
import ivle.config
26
26
import ivle.jailbuilder.debian
27
27
 
 
28
class UnsafeJail(Exception):
 
29
    pass
 
30
 
28
31
usage = """usage: %prog [options]
29
32
(requires root)
30
33
Builds or updates the base IVLE jail."""
31
34
 
 
35
# Requires root
 
36
if os.getuid() != 0:
 
37
    print >> sys.stderr, "This script requires root privileges to run"
 
38
    sys.exit(1)
 
39
 
32
40
conf = ivle.config.Config()
33
 
build_path = ivle.conf.jail_system_build
 
41
build_path = conf['paths']['jails']['template_build']
34
42
 
35
43
# Parse arguments
36
44
parser = optparse.OptionParser(usage)
43
51
    help='''Apply any package updates in the jail.''')
44
52
parser.add_option("-m", "--mirror",
45
53
    action="store", dest="apt_mirror",
46
 
    help="Sets the apt mirror used when recreating the jail.")
 
54
    help="Sets the apt mirror.", default=conf['jail']['mirror'])
 
55
parser.add_option("--python-site-packages",
 
56
    action="store", dest="python_site_packages",
 
57
    help="Path to Python site packages directory inside the jail.",
 
58
    default=None)
47
59
(options, args) = parser.parse_args(sys.argv)
48
60
 
49
61
if os.geteuid() != 0:
54
66
    print >> sys.stderr, "No jail exists -- please rerun with -r."
55
67
    sys.exit(1)
56
68
 
 
69
if (options.python_site_packages is not None and
 
70
    options.python_site_packages[:1] not in (os.path.sep, os.path.altsep)):
 
71
    print >> sys.stderr, "python-site-packages must be an absolute path."
 
72
    sys.exit(1)
 
73
 
57
74
if options.recreate:
 
75
    options.upgrade = True
 
76
 
58
77
    # Create the jail and its subdirectories
59
78
    # Note: Other subdirs will be made by copying files
60
79
    if options.apt_mirror is not None:
64
83
    ivle.jailbuilder.debian.debootstrap_create_jail(conf['jail']['suite'],
65
84
              build_path, mirror=options.apt_mirror)
66
85
 
 
86
    ivle.jailbuilder.debian.apt_update_cache(build_path)
 
87
    # Minimal required packages
 
88
    ivle.jailbuilder.debian.apt_install(build_path,
 
89
            ['python2.5', 'python-cjson', 'python-svn', 'python-configobj'])
 
90
 
 
91
    ivle.jailbuilder.debian.apt_clean(build_path)
 
92
 
 
93
if options.upgrade:
 
94
    # Run apt-get update, apt-get upgrade and apt-get clean.
 
95
    ivle.jailbuilder.debian.mangle_sources_list(build_path, clobber=True)
 
96
    ivle.jailbuilder.debian.mangle_sources_list(build_path, lines=[
 
97
            'deb %s %s%s %s' % (options.apt_mirror, conf['jail']['suite'],
 
98
                                pocket, ' '.join(['main', 'universe']))
 
99
            for pocket in ('', '-updates', '-security')])
 
100
 
67
101
    # Add any extra site apt sources.
68
102
    if conf['jail']['extra_sources']:
69
103
        ivle.jailbuilder.debian.mangle_sources_list(build_path,
75
109
                                            conf['jail']['extra_keys'])
76
110
 
77
111
    ivle.jailbuilder.debian.apt_update_cache(build_path)
78
 
    ivle.jailbuilder.debian.apt_install(build_path,
79
 
                        ['python2.5', 'python-cjson', 'python-svn'])
 
112
    ivle.jailbuilder.debian.apt_upgrade(build_path)
80
113
 
81
114
    # Install any extra site packages.
82
115
    if conf['jail']['extra_packages']:
85
118
 
86
119
    ivle.jailbuilder.debian.apt_clean(build_path)
87
120
 
88
 
if options.upgrade:
89
 
    # Run apt-get update, apt-get upgrade and apt-get clean.
90
 
    ivle.jailbuilder.debian.apt_update_cache(build_path)
91
 
    ivle.jailbuilder.debian.apt_upgrade(build_path)
92
 
    ivle.jailbuilder.debian.apt_clean(build_path)
93
 
 
94
 
# Copy all console and operating system files into the jail
95
 
services_path = os.path.join(ivle.conf.share_path, 'services')
96
 
jail_services_path = os.path.join(build_path, services_path[1:])
97
 
if os.path.exists(jail_services_path):
98
 
    shutil.rmtree(jail_services_path)
99
 
shutil.copytree(services_path, jail_services_path)
100
 
 
101
 
# Also copy the IVLE lib directory into the jail
102
 
# This is necessary for running certain services
103
 
ivle_site_packages = os.path.join(ivle.conf.python_site_packages, 'ivle')
104
 
jail_site_packages = os.path.join(build_path, ivle_site_packages[1:])
105
 
if os.path.exists(jail_site_packages):
106
 
    shutil.rmtree(jail_site_packages)
107
 
shutil.copytree(ivle_site_packages, jail_site_packages)
108
 
 
109
 
# IMPORTANT: ivle/conf/conf.py contains details which could compromise security
110
 
# if left in the jail (such as the DB password). We delete it now! It would be
111
 
# shadowed by the per-user conf.py anyway, but it's best to be safe.
112
 
os.unlink(os.path.join(jail_site_packages, 'conf/conf.py'))
113
 
# XXX: Shouldn't copy the compiled files at all, but compile them in the jail!
114
 
os.unlink(os.path.join(jail_site_packages, 'conf/conf.pyc'))
115
 
 
 
121
    # Configure locales to allow en_US.UTF-8 (which IVLE uses)
 
122
    ivle.jailbuilder.debian._execute_in_chroot(build_path,
 
123
        ['locale-gen', 'en_US.UTF-8'])
 
124
 
 
125
if conf['jail']['devmode']:
 
126
    # Copy all console and operating system files into the jail
 
127
    services_path = os.path.join(conf['paths']['share'], 'services')
 
128
    jail_services_path = os.path.join(build_path, services_path[1:])
 
129
    if os.path.exists(jail_services_path):
 
130
        shutil.rmtree(jail_services_path)
 
131
    shutil.copytree(services_path, jail_services_path)
 
132
 
 
133
    # Also copy the IVLE lib directory into the jail
 
134
    # This is necessary for running certain services
 
135
 
 
136
    # ivle_site_packages is the IVLE install location outside the jail
 
137
    ivle_site_packages = os.path.dirname(ivle.__file__)
 
138
 
 
139
    if options.python_site_packages is None:
 
140
        # Get the site packages from the IVLE install location *OUTSIDE* the
 
141
        # jail. Warning! This only works if you have the same Python site
 
142
        # packages directory inside and out (ie. same Python version).
 
143
        # If not, you should use --python-site-packages.
 
144
        jail_site_packages = os.path.join(build_path, ivle_site_packages[1:])
 
145
    else:
 
146
        # User-specified site packages
 
147
        jail_site_packages = os.path.join(build_path,
 
148
                                options.python_site_packages[1:], "ivle")
 
149
    if os.path.exists(jail_site_packages):
 
150
        shutil.rmtree(jail_site_packages)
 
151
    shutil.copytree(ivle_site_packages, jail_site_packages)
 
152
 
 
153
    # And finally copy in /etc/hosts, /etc/resolv.conf and /etc/hostname,
 
154
    # so name resolution is less unlikely to work.
 
155
    shutil.copy(
 
156
        '/etc/resolv.conf', os.path.join(build_path, 'etc/resolv.conf'))
 
157
    shutil.copy('/etc/hosts', os.path.join(build_path, 'etc/hosts'))
 
158
    shutil.copy('/etc/hostname', os.path.join(build_path, 'etc/hostname'))
 
159
 
 
160
# Make /tmp and /var/lock un-world-writable. /tmp will be mounted over,
 
161
# and /var/{lock,tmp} should die.
 
162
for path in ('tmp', 'var/lock', 'var/tmp'):
 
163
    path = os.path.join(build_path, path)
 
164
    os.chmod(path, os.stat(path).st_mode & ~stat.S_IWOTH)
 
165
 
 
166
# Verify that nothing in the jail is world-writable.
 
167
# We don't want students to write into places that others can see.
 
168
try:
 
169
    for path, dirs, files in os.walk(build_path):
 
170
        for dname in dirs:
 
171
            d = os.path.join(path, dname)
 
172
            if os.path.islink(d):
 
173
                continue
 
174
            if os.stat(d).st_mode & stat.S_IWOTH:
 
175
                raise UnsafeJail(d)
 
176
 
 
177
        for fname in files:
 
178
            f = os.path.join(path, fname)
 
179
            if os.path.islink(f):
 
180
                continue
 
181
            if os.stat(f).st_mode & stat.S_IWOTH:
 
182
                if (os.path.dirname(f) == os.path.join(build_path, 'dev') and
 
183
                    os.path.basename(f) in ('ptmx', 'null', 'tty', 'full', 'zero',
 
184
                                            'random', 'urandom')
 
185
                    ):
 
186
                    continue
 
187
                raise UnsafeJail(f)
 
188
except UnsafeJail, e:
 
189
    print >> sys.stderr,"""Error: Jail contains world writable path: '%s'.
 
190
This is a security vulnerability as jail template contents are shared between 
 
191
users. Please either make this path world unwriteable or remove it from the 
 
192
jail."""%str(e)
 
193
    sys.exit(1)
 
194
 
 
195
# Copy jail template build to actual jail template
 
196
template_path = conf['paths']['jails']['template']
116
197
if os.spawnvp(os.P_WAIT, 'rsync', ['rsync', '-a', '--delete',
117
 
              build_path + '/', ivle.conf.jail_system]) != 0:
 
198
              build_path + '/', template_path]) != 0:
118
199
    print >> sys.stderr, "Jail copying failed."
119
200
    sys.exit(1)
120
201
 
 
202
# Now mangle things a bit, so we can bind-mount the user bits in.
 
203
# /etc/passwd and /etc/ivle/ivle.conf need to be symlinks to somewhere in /home
 
204
 
 
205
os.rename(os.path.join(template_path, 'etc/passwd'),
 
206
          os.path.join(template_path, 'home/.passwd')
 
207
          )
 
208
os.symlink('../home/.passwd', os.path.join(template_path, 'etc/passwd'))
 
209
 
 
210
os.makedirs(os.path.join(template_path, "etc/ivle"))
 
211
os.symlink('../../home/.ivle.conf',
 
212
           os.path.join(template_path, "etc/ivle/ivle.conf"))