103
99
os.rename(ivle.conf.svn_conf + ".new", ivle.conf.svn_conf)
104
100
chown_to_webserver(ivle.conf.svn_conf)
106
def rebuild_svn_group_config():
102
def rebuild_svn_group_config(store):
107
103
"""Build the complete SVN configuration file for groups
110
groups = conn.get_all('project_group',
111
['groupid', 'groupnm', 'projectsetid'])
112
105
f = open(ivle.conf.svn_group_conf + ".new", "w")
113
106
f.write("# IVLE SVN Group Repositories Configuration\n")
114
107
f.write("# Auto-generated on %s\n" % time.asctime())
117
projectsetid = g['projectsetid']
118
offeringinfo = conn.get_offering_info(projectsetid)
119
subj_short_name = offeringinfo['subj_short_name']
120
year = offeringinfo['year']
121
semester = offeringinfo['semester']
122
reponame = "_".join([subj_short_name, year, semester, g['groupnm']])
109
for group in store.find(ProjectGroup):
110
offering = group.project_set.offering
111
reponame = "_".join([offering.subject.short_name,
112
offering.semester.year,
113
offering.semester.semester,
123
115
f.write("[%s:/]\n"%reponame)
124
users = conn.get_projectgroup_members(g['groupid'])
126
f.write("%s = rw\n"%u['login'])
116
for user in group.members:
117
f.write("%s = rw\n" % user.login)
129
120
os.rename(ivle.conf.svn_group_conf + ".new", ivle.conf.svn_group_conf)
196
186
Chowns the user's directory within the jail to the given UID.
198
Note: This takes separate username and uid arguments. The UID need not
199
*necessarily* correspond to a Unix username at all, if all you are
200
planning to do is setuid to it. This allows the caller the freedom of
201
deciding the binding between username and uid, if any.
203
188
force: If false, exception if jail already exists for this user.
204
189
If true (default), overwrites it, but preserves home directory.
206
svn_pass: If provided this will be a string, the randomly-generated
207
Subversion password for this user (if you happen to already have it).
208
If not provided, it will be read from the database.
210
191
# MUST run as root or some of this may fail
211
192
if os.getuid() != 0:
212
193
raise Exception("Must run make_jail as root")
214
195
# tempdir is for putting backup homes in
215
tempdir = os.path.join(ivle.conf.jail_base, '__temp__')
196
tempdir = os.path.join(ivle.conf.jail_src_base, '__temp__')
216
197
if not os.path.exists(tempdir):
217
198
os.makedirs(tempdir)
218
199
elif not os.path.isdir(tempdir):
219
200
os.unlink(tempdir)
220
201
os.mkdir(tempdir)
221
userdir = os.path.join(ivle.conf.jail_src_base, username)
202
userdir = os.path.join(ivle.conf.jail_src_base, user.login)
222
203
homedir = os.path.join(userdir, 'home')
223
userhomedir = os.path.join(homedir, username) # Return value
204
userhomedir = os.path.join(homedir, user.login) # Return value
225
206
if os.path.exists(userdir):
232
213
warnings.simplefilter('ignore')
233
214
homebackup = os.tempnam(tempdir)
234
215
warnings.resetwarnings()
235
# Note: shutil.move does not behave like "mv" - it does not put a file
236
# into a directory if it already exists, just fails. Therefore it is
237
# not susceptible to tmpnam symlink attack.
216
# Back up the /home directory, delete the entire jail, recreate the
217
# jail directory tree, then copy the /home back
218
# NOTE that shutil.move changed in Python 2.6, it now moves a
219
# directory INTO the target (like `mv`), which it didn't use to do.
220
# This code works regardless.
238
221
shutil.move(homedir, homebackup)
239
222
shutil.rmtree(userdir)
241
224
shutil.move(homebackup, homedir)
242
225
# Change the ownership of all the files to the right unixid
243
226
logging.debug("chown %s's home directory files to uid %d"
245
os.chown(userhomedir, uid, uid)
246
for root, dirs, files in os.walk(userhomedir):
247
for fsobj in dirs + files:
248
os.chown(os.path.join(root, fsobj), uid, uid)
227
%(user.login, user.unixid))
228
os.spawnvp(os.P_WAIT, 'chown', ['chown', '-R', '%d:%d' % (user.unixid,
229
user.unixid), userhomedir])
250
231
# No user jail exists
251
232
# Set up the user's home directory
252
233
os.makedirs(userhomedir)
253
234
# Chown (and set the GID to the same as the UID).
254
os.chown(userhomedir, uid, uid)
235
os.chown(userhomedir, user.unixid, user.unixid)
255
236
# Chmod to rwxr-xr-x (755)
256
237
os.chmod(userhomedir, 0755)
258
# There are 2 special files which need to be generated specific to this
259
# user: ${python_site_packages}/lib/conf/conf.py and /etc/passwd.
260
# "__" username "__" users are exempt (special)
261
if not (username.startswith("__") and username.endswith("__")):
262
make_conf_py(username, userdir, ivle.conf.jail_system, svn_pass)
263
make_etc_passwd(username, userdir, ivle.conf.jail_system, uid)
239
make_ivle_conf(user.login, userdir, user.svn_pass)
240
make_etc_passwd(user.login, userdir, ivle.conf.jail_system, user.unixid)
265
242
return userhomedir
267
def make_conf_py(username, user_jail_dir, staging_dir, svn_pass=None):
244
def make_ivle_conf(username, user_jail_dir, svn_pass):
269
246
Creates (overwriting any existing file, and creating directories) a
270
file ${python_site_packages}/ivle/conf/conf.py in a given user's jail.
247
file /etc/ivle/ivle.conf in a given user's jail.
271
248
username: Username.
272
249
user_jail_dir: User's jail dir, ie. ivle.conf.jail_base + username
273
staging_dir: The dir with the staging copy of the jail. (With the
274
template conf.py file).
275
svn_pass: As with make_jail. User's SVN password, but if not supplied,
276
will look up in the DB.
250
svn_pass: User's SVN password.
278
template_conf_path = os.path.join(staging_dir,
279
ivle.conf.python_site_packages[1:], "ivle/conf/conf.py")
280
conf_path = os.path.join(user_jail_dir,
281
ivle.conf.python_site_packages[1:], "ivle/conf/conf.py")
252
conf_path = os.path.join(user_jail_dir, "etc/ivle/ivle.conf")
282
253
os.makedirs(os.path.dirname(conf_path))
284
# If svn_pass isn't supplied, grab it from the DB
286
dbconn = ivle.db.DB()
287
svn_pass = dbconn.get_user(username).svn_pass
290
# Read the contents of the template conf file
292
template_conf_file = open(template_conf_path, "r")
293
template_conf_data = template_conf_file.read()
294
template_conf_file.close()
296
# Couldn't open template conf.py for some reason
297
# Just treat it as empty file
298
template_conf_data = ("# Warning: Problem building config script.\n"
299
"# Could not find template conf.py file.\n")
301
conf_file = open(conf_path, "w")
302
conf_file.write(template_conf_data)
303
conf_file.write("\n# The login name for the owner of the jail\n")
304
conf_file.write("login = %s\n" % repr(username))
305
conf_file.write("\n")
306
conf_file.write("# The subversion-only password for the owner of "
308
conf_file.write("svn_pass = %s\n" % repr(svn_pass))
255
# In the "in-jail" version of conf, we don't need MOST of the details
256
# (it would be a security risk to have them here).
257
# So we just write root_dir.
258
conf_obj = ivle.config.Config(blank=True)
259
conf_obj.filename = conf_path
260
conf_obj['urls']['root'] = ivle.conf.root_dir
261
conf_obj['urls']['public_host'] = ivle.conf.public_host
262
conf_obj['urls']['svn_addr'] = ivle.conf.svn_addr
263
conf_obj['user_info']['login'] = username
264
conf_obj['user_info']['svn_pass'] = svn_pass
311
267
# Make this file world-readable
312
268
# (chmod 644 conf_path)
329
285
% (username, unixid, unixid, username))
330
286
passwd_file.close()
332
def make_user_db(throw_on_error = True, **kwargs):
333
"""Creates a user's entry in the database, filling in all the fields.
334
All arguments must be keyword args. They are the fields in the table.
335
However, instead of supplying a "passhash", you must supply a
336
"password" argument, which will be hashed internally.
337
Also do not supply a state. All users are created in the "no_agreement"
339
Also pulls the user's subjects using the configured subject pulldown
340
module, and adds enrolments to the DB.
341
Throws an exception if the user already exists.
343
dbconn = ivle.db.DB()
344
dbconn.create_user(**kwargs)
347
if kwargs['password']:
348
if os.path.exists(ivle.conf.svn_auth_local):
352
res = os.system("htpasswd -%smb %s %s %s" % (create,
353
ivle.conf.svn_auth_local,
356
if res != 0 and throw_on_error:
357
raise Exception("Unable to create local-auth for %s" % kwargs['login'])
359
# Make sure the file is owned by the web server
361
chown_to_webserver(ivle.conf.svn_auth_local)
363
# Pulldown subjects and add enrolments
364
ivle.pulldown_subj.enrol_user(kwargs['login'])
366
288
def mount_jail(login):
367
289
# This is where we'll mount to...
368
290
destdir = os.path.join(ivle.conf.jail_base, login)