Class: Net::LDAP::AuthAdapter::Sasl

Inherits:
Net::LDAP::AuthAdapter show all
Defined in:
lib/net/ldap/auth_adapter/sasl.rb

Constant Summary collapse

MAX_SASL_CHALLENGES =
10

Instance Method Summary collapse

Methods inherited from Net::LDAP::AuthAdapter

[], #initialize, register

Constructor Details

This class inherits a constructor from Net::LDAP::AuthAdapter

Instance Method Details

#bind(auth) ⇒ Object

– 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. ++


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/net/ldap/auth_adapter/sasl.rb', line 30

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 do
    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) > MAX_SASL_CHALLENGES)

    cred = chall.call(pdu.result_server_sasl_creds)
  end

  raise Net::LDAP::SASLChallengeOverflowError, "why are we here?"
end