-
Notifications
You must be signed in to change notification settings - Fork 252
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #226 from satoryu/define_auth_adapters
Define auth adapters
- Loading branch information
Showing
7 changed files
with
182 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
module Net | ||
class LDAP | ||
class AuthAdapter | ||
def self.register(names, adapter) | ||
names = Array(names) | ||
@adapters ||= {} | ||
names.each do |name| | ||
@adapters[name] = adapter | ||
end | ||
end | ||
|
||
def self.[](name) | ||
a = @adapters[name] | ||
if a.nil? | ||
raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{name})" | ||
end | ||
return a | ||
end | ||
|
||
def initialize(conn) | ||
@connection = conn | ||
end | ||
|
||
def bind | ||
raise "bind method must be overwritten" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
require 'net/ldap/auth_adapter' | ||
require 'net/ldap/auth_adapter/sasl' | ||
|
||
module Net | ||
class LDAP | ||
module AuthAdapers | ||
#-- | ||
# PROVISIONAL, only for testing SASL implementations. DON'T USE THIS YET. | ||
# Uses Kohei Kajimoto's Ruby/NTLM. We have to find a clean way to | ||
# integrate it without introducing an external dependency. | ||
# | ||
# This authentication method is accessed by calling #bind with a :method | ||
# parameter of :gss_spnego. It requires :username and :password | ||
# attributes, just like the :simple authentication method. It performs a | ||
# GSS-SPNEGO authentication with the server, which is presumed to be a | ||
# Microsoft Active Directory. | ||
#++ | ||
class GSS_SPNEGO < Net::LDAP::AuthAdapter | ||
def bind(auth) | ||
require 'ntlm' | ||
|
||
user, psw = [auth[:username] || auth[:dn], auth[:password]] | ||
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) | ||
|
||
nego = proc { |challenge| | ||
t2_msg = NTLM::Message.parse(challenge) | ||
t3_msg = t2_msg.response({ :user => user, :password => psw }, | ||
{ :ntlmv2 => true }) | ||
t3_msg.serialize | ||
} | ||
|
||
Net::LDAP::AuthAdapter::Sasl.new(@connection). | ||
bind(:method => :sasl, :mechanism => "GSS-SPNEGO", | ||
:initial_credential => NTLM::Message::Type1.new.serialize, | ||
:challenge_response => nego) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
require 'net/ldap/auth_adapter' | ||
|
||
module Net | ||
class LDAP | ||
class AuthAdapter | ||
class Sasl < Net::LDAP::AuthAdapter | ||
#-- | ||
# Required parameters: :mechanism, :initial_credential and | ||
# :challenge_response | ||
# | ||
# Mechanism is a string value that will be passed in the SASL-packet's | ||
# "mechanism" field. | ||
# | ||
# Initial credential is most likely a string. It's passed in the initial | ||
# BindRequest that goes to the server. In some protocols, it may be empty. | ||
# | ||
# Challenge-response is a Ruby proc that takes a single parameter and | ||
# returns an object that will typically be a string. The | ||
# challenge-response block is called when the server returns a | ||
# BindResponse with a result code of 14 (saslBindInProgress). The | ||
# challenge-response block receives a parameter containing the data | ||
# returned by the server in the saslServerCreds field of the LDAP | ||
# BindResponse packet. The challenge-response block may be called multiple | ||
# times during the course of a SASL authentication, and each time it must | ||
# return a value that will be passed back to the server as the credential | ||
# data in the next BindRequest packet. | ||
#++ | ||
def bind(auth) | ||
mech, cred, chall = auth[:mechanism], auth[:initial_credential], | ||
auth[:challenge_response] | ||
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (mech && cred && chall) | ||
|
||
message_id = @connection.next_msgid | ||
|
||
n = 0 | ||
loop { | ||
sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) | ||
request = [ | ||
Net::LDAP::Connection::LdapVersion.to_ber, "".to_ber, sasl | ||
].to_ber_appsequence(Net::LDAP::PDU::BindRequest) | ||
|
||
@connection.send(:write, request, nil, message_id) | ||
pdu = @connection.queued_read(message_id) | ||
|
||
if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult | ||
raise Net::LDAP::NoBindResultError, "no bind result" | ||
end | ||
|
||
return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress | ||
raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) | ||
|
||
cred = chall.call(pdu.result_server_sasl_creds) | ||
} | ||
|
||
raise Net::LDAP::SASLChallengeOverflowError, "why are we here?" | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
require 'net/ldap/auth_adapter' | ||
|
||
module Net | ||
class LDAP | ||
class AuthAdapter | ||
class Simple < AuthAdapter | ||
def bind(auth) | ||
user, psw = if auth[:method] == :simple | ||
[auth[:username] || auth[:dn], auth[:password]] | ||
else | ||
["", ""] | ||
end | ||
|
||
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw) | ||
|
||
message_id = @connection.next_msgid | ||
request = [ | ||
Net::LDAP::Connection::LdapVersion.to_ber, user.to_ber, | ||
psw.to_ber_contextspecific(0) | ||
].to_ber_appsequence(Net::LDAP::PDU::BindRequest) | ||
|
||
@connection.send(:write, request, nil, message_id) | ||
pdu = @connection.queued_read(message_id) | ||
|
||
if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult | ||
raise Net::LDAP::NoBindResultError, "no bind result" | ||
end | ||
|
||
pdu | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
require 'test_helper' | ||
|
||
class TestAuthAdapter < Test::Unit::TestCase | ||
def test_undefined_auth_adapter | ||
flexmock(TCPSocket).should_receive(:new).ordered.with('ldap.example.com', 379).once.and_return(nil) | ||
conn = Net::LDAP::Connection.new(host: 'ldap.example.com', port: 379) | ||
assert_raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (foo)" do | ||
conn.bind(method: :foo) | ||
end | ||
end | ||
end |