You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.2 KiB
123 lines
3.2 KiB
require 'ldap/server/connection'
|
|
require 'ldap/server/operation'
|
|
require 'openssl'
|
|
require 'logger'
|
|
|
|
module LDAP
|
|
class Server
|
|
|
|
attr_accessor :root_dse
|
|
|
|
DEFAULT_OPT = {
|
|
:port=>389,
|
|
:nodelay=>true,
|
|
}
|
|
|
|
# Create a new server. Options include all those to tcpserver/preforkserver
|
|
# plus:
|
|
# either
|
|
# :router=>Router - request router instance
|
|
# or
|
|
# :operation_class=>Class - set Operation handler class
|
|
# :operation_args=>[...] - args to Operation.new
|
|
#
|
|
# :ssl_key_file=>pem, :ssl_cert_file=>pem - enable SSL
|
|
# :ssl_ca_path=>directory - verify peer certificates
|
|
# :schema=>Schema - Schema object
|
|
# :namingContexts=>[dn, ...] - base DN(s) we answer
|
|
#
|
|
# Specifying a :router always overrides :operation_class
|
|
|
|
attr_reader :logger
|
|
|
|
def initialize(opt = DEFAULT_OPT)
|
|
@opt = opt
|
|
@opt[:server] = self
|
|
if @opt[:router]
|
|
@opt.delete(:operation_class)
|
|
@opt.delete(:operation_args)
|
|
else
|
|
@opt[:operation_class] ||= LDAP::Server::Operation
|
|
@opt[:operation_args] ||= []
|
|
end
|
|
unless @opt[:logger]
|
|
@opt[:logger] ||= Logger.new($stderr)
|
|
@opt[:logger].level = Logger::INFO
|
|
end
|
|
@logger = @opt[:logger]
|
|
LDAP::Server.ssl_prepare(@opt)
|
|
@schema = opt[:schema] # may be nil
|
|
@root_dse = Hash.new { |h,k| h[k] = [] }.merge({
|
|
'objectClass' => ['top','openLDAProotDSE','extensibleObject'],
|
|
'supportedLDAPVersion' => ['3'],
|
|
#'altServer' =>
|
|
#'supportedExtension' =>
|
|
#'supportedControl' =>
|
|
#'supportedSASLMechanisms' =>
|
|
})
|
|
@root_dse['subschemaSubentry'] = [@schema.subschema_dn] if @schema
|
|
@root_dse['namingContexts'] = opt[:namingContexts] if opt[:namingContexts]
|
|
end
|
|
|
|
# create opt[:ssl_ctx] from the other ssl options
|
|
|
|
def self.ssl_prepare(opt) # :nodoc:
|
|
if opt[:ssl_key_file] and opt[:ssl_cert_file]
|
|
ctx = OpenSSL::SSL::SSLContext.new
|
|
ctx.key = OpenSSL::PKey::RSA.new(File::read(opt[:ssl_key_file]))
|
|
ctx.cert = OpenSSL::X509::Certificate.new(File::read(opt[:ssl_cert_file]))
|
|
if opt[:ssl_dhparams]
|
|
ctx.tmp_dh_callback = proc { |*args|
|
|
OpenSSL::PKey::DH.new(
|
|
File.read(opt[:ssl_dhparams])
|
|
)
|
|
}
|
|
end
|
|
if opt[:ssl_ca_path]
|
|
ctx.ca_path = opt[:ssl_ca_path]
|
|
ctx.verify_mode = opt[:ssl_verify_mode] ||
|
|
OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
|
elsif opt[:ssl_verify_mode] != 0
|
|
$stderr.puts "Warning: No ssl_ca_path, peer certificate won't be verified"
|
|
end
|
|
opt[:ssl_ctx] = ctx
|
|
end
|
|
end
|
|
|
|
def run_tcpserver
|
|
require 'ldap/server/tcpserver'
|
|
|
|
opt = @opt
|
|
@thread = LDAP::Server.tcpserver(@opt) do
|
|
LDAP::Server::Connection::new(self,opt).handle_requests
|
|
end
|
|
end
|
|
|
|
def run_prefork
|
|
require 'ldap/server/preforkserver'
|
|
|
|
opt = @opt
|
|
@thread = LDAP::Server.preforkserver(@opt) do
|
|
LDAP::Server::Connection::new(self,opt).handle_requests
|
|
end
|
|
end
|
|
|
|
def join
|
|
begin
|
|
@thread.join
|
|
rescue Interrupt
|
|
@logger.info "Exiting..."
|
|
end
|
|
end
|
|
|
|
def stop
|
|
@thread.raise Interrupt, "" # <= temporary fix for 1.8.6
|
|
begin
|
|
@thread.join
|
|
rescue Interrupt
|
|
# nop
|
|
end
|
|
end
|
|
|
|
end # class Server
|
|
end # module LDAP
|