#!/usr/bin/env ruby $:.unshift('lib') $debug = true require 'ldap/server' $logger = Logger.new($stderr) # We subclass the Operation class, overriding the methods to do what we need class HashOperation < LDAP::Server::Operation def initialize(connection, messageID, hash) super(connection, messageID) @hash = hash # an object reference to our directory data end # ici, c'est bizarre # systèmatiquement appelé (SEARCH ou AUTH) # du coup, je retourne super si pas de dn => SEARCH normal sans authentication # sinon ça passe aussi !!! def do_bind(protocolOp, controls) # :nodoc: dn = protocolOp.value[1].value dn = nil if dn == '' return super if dn.nil? version = protocolOp.value[0].value authentication = protocolOp.value[2] password = authentication.value $logger.info("AUTHENTICATION ..version=#{version}, dn=#{dn}") super end # def simple_bind(version, dn, password) # super.simple_bind(version, dn, password) # $logger.info("SIMPLE BIND...version=#{version}, dn=#{dn}") # # raise LDAP::ResultError::ProtocolError, 'version 3 only' if version != 3 # raise LDAP::ResultError::InvalidCredentials, 'Invalid credentials' if password.nil? || password == '' # # $logger.info('authentication SUCCESS') # end # def search(basedn, scope, deref, filter) $logger.info("SEARCHING...basedn=#{basedn}, scope=#{scope}, deref=#{deref}, filter=#{filter}") basedn = basedn.downcase result = nil case scope when LDAP::Server::BaseObject # client asked for single object by DN obj = @hash[basedn] raise LDAP::ResultError::NoSuchObject unless obj result = send_SearchResultEntry(basedn, obj) if LDAP::Server::Filter.run(filter, obj) when LDAP::Server::WholeSubtree @hash.each do |dn, av| next unless dn.index(basedn, -basedn.length) # under basedn? next unless LDAP::Server::Filter.run(filter, av) # attribute filter? result = send_SearchResultEntry(dn, av) end else raise LDAP::ResultError::UnwillingToPerform, 'OneLevel not implemented' end $logger.info "result=#{result}" result end end # This is the shared object which carries our actual directory entries. # It's just a hash of {dn=>entry}, where each entry is {attr=>[val,val,...]} directory = {} require 'yaml' File.open('examples/ldapdb.yaml') { |f| directory = YAML.load(f.read) } $logger.info("DIRECTORY=#{directory}") # Listen for incoming LDAP connections. For each one, create a Connection # object, which will invoke a HashOperation object for each request. s = LDAP::Server.new( port: 1389, nodelay: true, listen: 10, operation_class: HashOperation, operation_args: [directory] ) $logger.info('server2 RUNNING...') s.run_tcpserver s.join