#!/usr/bin/ruby # # Copyright (c) 2004 Peter Palfrader # # All rights reserved. # require "ldap" require "yaml" @config = YAML::load( File.open( '/etc/noreply/config' ) ) VALIDATION_REGEX = { 'uid' => /^[Wa-z.-]+$/, 'cn' => /^[Wa-z-]+$/, 'uidNumber' => /^[1-9][0-9]+$/, 'gidNumber' => /^[1-9][0-9]+$/, 'gecos' => /^[a-zA-Z0-9,. -]+$/, 'homeDirectory' => /^\/[a-zA-Z0-9.\/-]+$/, 'loginShell' => /^\/[a-zA-Z0-9\/-]+$/ } 5.times{ begin @conn = LDAP::Conn.new(@config['ldapserver'], @config['ldapport'] ) break if @conn rescue LDAP::ResultError sleep 3 end }; unless @conn.bind(@config['credentials']['ldap2passwd']['binddn'], @config['credentials']['ldap2passwd']['bindpw']) throw @conn.perror("bind") end def passwd_line(entry) l = {} %w(uid uidNumber gidNumber gecos homeDirectory loginShell).each{ |key| next if ['gecos', 'loginShell'].include?(key) and not entry[key] throw "key #{key} missing in #{entry['dn']}" unless entry[key] throw "no validation regex for #{key}" unless VALIDATION_REGEX[key] l[key] = entry[key].to_s throw "value for #{key} (#{l[key]}) in #{entry['dn']} fails validation regex #{VALIDATION_REGEX[key]}" unless l[key] =~ VALIDATION_REGEX[key] }; l['gecos'] = '' unless l['gecos'] l['loginShell'] = '/bin/false' unless l['loginShell'] sprintf "%s:x:%s:%s:%s:%s:%s\n", l['uid'], l['uidNumber'], l['gidNumber'], l['gecos'], l['homeDirectory'], l['loginShell'] end def group_line(entry) l = {} %w(cn gidNumber).each{ |key| throw "key #{key} missing in #{entry['dn']}" unless entry[key] throw "no validation regex for #{key}" unless VALIDATION_REGEX[key] l[key] = entry[key].to_s throw "value for #{key} (#{l[key]}) in #{entry['dn']} fails validation regex #{VALIDATION_REGEX[key]}" unless l[key] =~ VALIDATION_REGEX[key] }; members = [] if entry['memberUid'] entry['memberUid'].each{ |member| throw "empty member value in group #{entry['dn']}" unless member m = member.to_s throw "member of group #{entry['dn']} fails UID validiation test" unless m =~ VALIDATION_REGEX['uid'] members << m } end sprintf "%s:x:%s:%s\n", l['cn'], l['gidNumber'], members.join(',') end passwd_lines = [] passwd = @conn.search2(@config['basedn'], LDAP::LDAP_SCOPE_SUBTREE, '(objectClass=posixAccount)') passwd.each{ |line| passwd_lines << passwd_line(line) } group_lines = [] group = @conn.search2(@config['basedn'], LDAP::LDAP_SCOPE_SUBTREE, '(objectClass=posixGroup)') group.each{ |line| group_lines << group_line(line) } unless File.exists?('passwd') && (File.read('passwd') == passwd_lines.join()) f = File.new('passwd', 'w') f.print passwd_lines.join end unless File.exists?('group') && (File.read('group') == group_lines.join()) f = File.new('group', 'w') f.print group_lines.join end