From 1a27513a55cfe02c93232a9e41358ce14c95a278 Mon Sep 17 00:00:00 2001 From: a7b81a9086 <> Date: Fri, 11 Jun 2021 15:01:17 +0200 Subject: [PATCH 1/4] Add support for ldapwhoami (RFC4532) --- lib/net/ldap.rb | 19 +++++++++++++++++++ lib/net/ldap/connection.rb | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index bf9dcc83..0f325c9f 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -306,6 +306,7 @@ class Net::LDAP 3 => :string, # SearchFilter-extensible 4 => :string, # SearchFilter-extensible 7 => :string, # serverSaslCreds + 11 => :string, # responseValue } constructed = { 0 => :array, # RFC-2251 Control and Filter-AND @@ -341,6 +342,7 @@ class Net::LDAP StartTlsOid = '1.3.6.1.4.1.1466.20037' PasswdModifyOid = '1.3.6.1.4.1.4203.1.11.1' + WhoamiOid = '1.3.6.1.4.1.4203.1.11.3' # https://tools.ietf.org/html/rfc4511#section-4.1.9 # https://tools.ietf.org/html/rfc4511#appendix-A @@ -1200,6 +1202,23 @@ def delete_tree(args) end end + # Return the authorization identity of the client that issues the + # ldapwhoami request. The method does not support any arguments. + # + # Returns True or False to indicate whether the request was successfull. + # The result is available in the extended status information when calling + # #get_operation_result. + # + # ldap.ldapwhoami + # puts ldap.get_operation_result.extended_response + def ldapwhoami(args = {}) + instrument "ldapwhoami.net_ldap", args do |payload| + @result = use_connection(args, &:ldapwhoami) + @result.success? + end + end + alias_method :whoami, :ldapwhoami + # This method is experimental and subject to change. Return the rootDSE # record from the LDAP server as a Net::LDAP::Entry, or an empty Entry if # the server doesn't return the record. diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index f51b7b7e..b73791a1 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -693,6 +693,22 @@ def delete(args) pdu end + def ldapwhoami + ext_seq = [Net::LDAP::WhoamiOid.to_ber_contextspecific(0)] + request = ext_seq.to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) + + message_id = next_msgid + + write(request, nil, message_id) + pdu = queued_read(message_id) + + if !pdu || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse + raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" + end + + pdu + end + # Internal: Returns a Socket like object used internally to communicate with # LDAP server. # From 0e38c4a6226bae54f3eecff4850d56dee70a8a5b Mon Sep 17 00:00:00 2001 From: a7b81a9086 <> Date: Sun, 13 Jun 2021 12:48:27 +0200 Subject: [PATCH 2/4] Do not break Net::LDAP#modify_password --- lib/net/ldap.rb | 1 - lib/net/ldap/connection.rb | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index 0f325c9f..e92b372d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -306,7 +306,6 @@ class Net::LDAP 3 => :string, # SearchFilter-extensible 4 => :string, # SearchFilter-extensible 7 => :string, # serverSaslCreds - 11 => :string, # responseValue } constructed = { 0 => :array, # RFC-2251 Control and Filter-AND diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index b73791a1..ce62c14b 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -694,6 +694,7 @@ def delete(args) end def ldapwhoami + Net::LDAP::AsnSyntax[139] = :string ext_seq = [Net::LDAP::WhoamiOid.to_ber_contextspecific(0)] request = ext_seq.to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) @@ -706,6 +707,7 @@ def ldapwhoami raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" end + Net::LDAP::AsnSyntax[139] = nil pdu end From 1d38606dbee091177d8eac475b854261d4a94ceb Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 23 Feb 2024 15:50:57 -0500 Subject: [PATCH 3/4] Return the extended response data --- lib/net/ldap.rb | 4 ++-- lib/net/ldap/connection.rb | 2 -- lib/net/ldap/pdu.rb | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index e92b372d..7d758e96 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -325,7 +325,7 @@ class Net::LDAP universal = { constructed: { - 107 => :array, #ExtendedResponse (PasswdModifyResponseValue) + 107 => :string, # ExtendedResponse }, } @@ -1213,7 +1213,7 @@ def delete_tree(args) def ldapwhoami(args = {}) instrument "ldapwhoami.net_ldap", args do |payload| @result = use_connection(args, &:ldapwhoami) - @result.success? + @result.success? ? @result.extended_response : nil end end alias_method :whoami, :ldapwhoami diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index ce62c14b..b73791a1 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -694,7 +694,6 @@ def delete(args) end def ldapwhoami - Net::LDAP::AsnSyntax[139] = :string ext_seq = [Net::LDAP::WhoamiOid.to_ber_contextspecific(0)] request = ext_seq.to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) @@ -707,7 +706,6 @@ def ldapwhoami raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid" end - Net::LDAP::AsnSyntax[139] = nil pdu end diff --git a/lib/net/ldap/pdu.rb b/lib/net/ldap/pdu.rb index 564a23cc..d29db032 100644 --- a/lib/net/ldap/pdu.rb +++ b/lib/net/ldap/pdu.rb @@ -194,13 +194,13 @@ def parse_ldap_result(sequence) # requestValue [1] OCTET STRING OPTIONAL } def parse_extended_response(sequence) - sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP result length." + sequence.length.between?(3, 5) or raise Net::LDAP::PDU::Error, "Invalid LDAP result length." @ldap_result = { :resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2], } - @extended_response = sequence[3] + @extended_response = sequence.last end private :parse_extended_response From d5e82fa3f940172cb729877809987f578e666413 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 23 Feb 2024 15:57:41 -0500 Subject: [PATCH 4/4] Add test for connection.ldapwhoami --- test/test_ldap_connection.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 74de115c..96ae7ea4 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -540,4 +540,15 @@ def test_search_with_controls # ensure no unread assert unread.empty?, "should not have any leftover unread messages" end + + def test_ldapwhoami + ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, '', '', 0, 'dn:uid=zerosteiner,ou=users,dc=example,dc=org']) + ber.ber_identifier = Net::LDAP::PDU::ExtendedResponse + response = [1, ber] + + @tcp_socket.should_receive(:read_ber).and_return(response) + + result = @connection.ldapwhoami + assert result.extended_response == 'dn:uid=zerosteiner,ou=users,dc=example,dc=org' + end end