summaryrefslogtreecommitdiff
path: root/bin/ldap2chroot-accounts
diff options
context:
space:
mode:
authorPeter Palfrader <peter@palfrader.org>2006-10-18 11:33:32 +0000
committerweasel <weasel@bc3d92e2-beff-0310-a7cd-cc87d7ac0ede>2006-10-18 11:33:32 +0000
commitc88bc35f1c88d9fbbba6706a4abaad24a1868c98 (patch)
tree487c31421b2f92e6e76bcf946500187b6b014e91 /bin/ldap2chroot-accounts
Add hosting ldap
git-svn-id: svn+ssh://asteria.noreply.org/svn/weaselutils/trunk@190 bc3d92e2-beff-0310-a7cd-cc87d7ac0ede
Diffstat (limited to 'bin/ldap2chroot-accounts')
-rwxr-xr-xbin/ldap2chroot-accounts139
1 files changed, 139 insertions, 0 deletions
diff --git a/bin/ldap2chroot-accounts b/bin/ldap2chroot-accounts
new file mode 100755
index 0000000..2cdadab
--- /dev/null
+++ b/bin/ldap2chroot-accounts
@@ -0,0 +1,139 @@
+#!/usr/bin/ruby
+
+#
+# Copyright (c) 2004 Peter Palfrader <peter@palfrader.org>
+#
+# All rights reserved.
+#
+
+require "ldap"
+require "getoptlong"
+require "myldap"
+require "yaml"
+
+
+
+def fatal(reason)
+ STDERR.puts reason
+ exit 1;
+end
+
+# read mtab
+#
+# /dev/sda11 /aux xfs rw 0 0
+# /chroot-accounts/MasterChroot/bin /chroot-accounts/weasel.weasel/bin none rw,bind 0 0
+#
+def getmounts()
+ mounts = Hash.new
+
+ IO.foreach('/etc/mtab') { |line|
+ (device, mountpoint, fstype, option, dummy1, dummy2) = line.split
+ next unless mountpoint.index(@spool)
+
+ fatal("Unexpected option or fstype in "+line) if (!(option =~ /bind/) || (fstype != 'none'))
+
+ # check mountpoint in detail
+ components = mountpoint.gsub(/^\//, '').split('/');
+ fatal("Weird mountpoint (not 3 components) in "+line) unless (components.size == 3)
+ fatal("1st componend of mountpoint is not sane in "+line) unless ('/' + components[0] == @spool)
+ fatal("2nd componend of mountpoint is not sane in "+line) unless (components[1] =~ /^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+$/)
+ fatal("3rd componend of mountpoint is not sane in "+line) unless (["bin", "usr", "lib", components[1]].include?(components[2]))
+
+ mounts[components[1]] = Hash.new unless mounts[components[1]]
+ mounts[components[1]][components[2]] = device
+ }
+ mounts
+end
+
+@config = YAML::load( File.open( '/etc/noreply/config' ) )
+
+masterName = @config['module']['ftp']['masterName']
+@spool = (@config['module']['ftp']['chrootBaseDir']).gsub('//', '/')
+@spool.chop! if @spool =~ /\/$/
+@master = @spool + '/' + masterName + '/'
+
+ldap = MyLDAP.new(@config, "ldap2chroot-accounts")
+accounts = Hash.new
+ldap.conn.search2(@config['basedn'], LDAP::LDAP_SCOPE_SUBTREE,
+ '(&(objectclass=tnFTPuser)(tnHost='+@config['thishost']+'))').each{ |e|
+ accounts[ e['uid'][0] ] = e
+}
+
+mounts = getmounts
+
+# create all account directories
+accounts.each_key{ |homedir|
+ dir = @spool + '/' + homedir
+ Dir.mkdir(dir) unless File.exists?(dir)
+}
+
+existingdirs = Dir.entries( @spool ).delete_if { |e| ((e =~ /^\./) != nil) }
+existingdirs.delete( masterName )
+# Iterate over all existing directories
+# checking up on mounts, and update them if necessary
+existingdirs.each { |homedir|
+ basedir = @spool + '/' + homedir
+ if accounts[homedir]
+ # Check bin, usr, and lib mounts
+ # also, the user's datadir is in a directory with the same name as her account
+ subdirs = %w(bin usr lib)
+ subdirs << homedir
+ subdirs.each { |subdir|
+ supposedLocation = subdir == homedir ? accounts[homedir]['tnFTPDataDirectory'][0] : @master + subdir
+ mountpoint = basedir + '/' + subdir
+
+ # umount if it's mounted in the wrong place
+ if mounts[homedir] && mounts[homedir][subdir]
+ if mounts[homedir][subdir] != supposedLocation
+ STDERR.puts("warn: Directory "+mountpoint+" is bind mounted to the wrong place: "+mounts[homedir][subdir]+". Should be "+supposedLocation+" remounting.")
+ system("umount " + mountpoint) or fatal("umount for "+mountpoint+" failed");
+ mounts[homedir].delete(subdir)
+ end
+ end
+
+ # mount if it's not mounted
+ if !(mounts[homedir] && mounts[homedir][subdir])
+ Dir.mkdir(mountpoint) unless File.exists?(mountpoint)
+ system("mount -o bind "+ supposedLocation + " " + mountpoint) or fatal("mount for "+mountpoint+" failed");
+ end
+ }
+ # create etc
+ etcdir = basedir + '/etc'
+ Dir.mkdir(etcdir, 0111) unless File.exists?(etcdir)
+ uid = accounts[homedir]['uid'][0]
+ uidNumber = accounts[homedir]['uidNumber'][0]
+ gidNumber = accounts[homedir]['gidNumber'][0]
+ passwd = "root:x:0:0:root::\n" + "%s:x:%d:%d:::\n"%[uid, uidNumber, gidNumber]
+ group = "root:x:0:\n" + "%s:x:%s:\n"%[uid, gidNumber]
+ File.open(etcdir+'/passwd', File::CREAT|File::TRUNC|File::RDWR, 0444).write(passwd)
+ File.open(etcdir+'/group', File::CREAT|File::TRUNC|File::RDWR, 0444).write(group)
+
+ # create .ssh
+ sshdir = basedir + '/.ssh'
+ Dir.mkdir(sshdir, 0111) unless File.exists?(sshdir)
+ authkeys = '';
+ accounts[homedir]['tnSSHKey'] and accounts[homedir]['tnSSHKey'].each{ |key|
+ key.gsub!('\n', '')
+ authkeys << "no-port-forwarding,no-X11-forwarding,no-agent-forwarding "+key+"\n"
+ }
+ File.open(sshdir+'/authorized_keys', File::CREAT|File::TRUNC|File::RDWR, 0444).write(authkeys)
+ else
+ # clean up old stuff
+ mounts[homedir] and mounts[homedir].each_key{ |subdir|
+ mountpoint = basedir + '/' + subdir
+ system("umount " + mountpoint) or fatal("umount for "+mountpoint+" failed");
+ Dir.rmdir(mountpoint)
+ }
+ { 'etc' => ['passwd', 'group'], '.ssh' => ['authorized_keys'], homedir => [] }.each{ |dir, files|
+ dir = basedir + '/' + dir
+ if File.exists?(dir)
+ files.each { |f|
+ file = dir + '/' + f
+ File.unlink(file) if File.exists?(file)
+ }
+ Dir.rmdir(dir)
+ end
+ }
+ Dir.rmdir(basedir)
+ end
+}