annotate .svn/pristine/60/60a7eaf3b71f4ea5a952f91807abdd540583522f.svn-base @ 1628:9c5f8e24dadc live tip

Quieten this cron script
author Chris Cannam
date Tue, 25 Aug 2020 11:38:49 +0100
parents cbb26bc654de
children
rev   line source
Chris@909 1 # $Id: pdu.rb 126 2006-05-31 15:55:16Z blackhedd $
Chris@909 2 #
Chris@909 3 # LDAP PDU support classes
Chris@909 4 #
Chris@909 5 #
Chris@909 6 #----------------------------------------------------------------------------
Chris@909 7 #
Chris@909 8 # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
Chris@909 9 #
Chris@909 10 # Gmail: garbagecat10
Chris@909 11 #
Chris@909 12 # This program is free software; you can redistribute it and/or modify
Chris@909 13 # it under the terms of the GNU General Public License as published by
Chris@909 14 # the Free Software Foundation; either version 2 of the License, or
Chris@909 15 # (at your option) any later version.
Chris@909 16 #
Chris@909 17 # This program is distributed in the hope that it will be useful,
Chris@909 18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@909 19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@909 20 # GNU General Public License for more details.
Chris@909 21 #
Chris@909 22 # You should have received a copy of the GNU General Public License
Chris@909 23 # along with this program; if not, write to the Free Software
Chris@909 24 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Chris@909 25 #
Chris@909 26 #---------------------------------------------------------------------------
Chris@909 27 #
Chris@909 28
Chris@909 29
Chris@909 30
Chris@909 31 module Net
Chris@909 32
Chris@909 33
Chris@909 34 class LdapPduError < Exception; end
Chris@909 35
Chris@909 36
Chris@909 37 class LdapPdu
Chris@909 38
Chris@909 39 BindResult = 1
Chris@909 40 SearchReturnedData = 4
Chris@909 41 SearchResult = 5
Chris@909 42 ModifyResponse = 7
Chris@909 43 AddResponse = 9
Chris@909 44 DeleteResponse = 11
Chris@909 45 ModifyRDNResponse = 13
Chris@909 46 SearchResultReferral = 19
Chris@909 47
Chris@909 48 attr_reader :msg_id, :app_tag
Chris@909 49 attr_reader :search_dn, :search_attributes, :search_entry
Chris@909 50 attr_reader :search_referrals
Chris@909 51
Chris@909 52 #
Chris@909 53 # initialize
Chris@909 54 # An LDAP PDU always looks like a BerSequence with
Chris@909 55 # at least two elements: an integer (message-id number), and
Chris@909 56 # an application-specific sequence.
Chris@909 57 # Some LDAPv3 packets also include an optional
Chris@909 58 # third element, which is a sequence of "controls"
Chris@909 59 # (See RFC 2251, section 4.1.12).
Chris@909 60 # The application-specific tag in the sequence tells
Chris@909 61 # us what kind of packet it is, and each kind has its
Chris@909 62 # own format, defined in RFC-1777.
Chris@909 63 # Observe that many clients (such as ldapsearch)
Chris@909 64 # do not necessarily enforce the expected application
Chris@909 65 # tags on received protocol packets. This implementation
Chris@909 66 # does interpret the RFC strictly in this regard, and
Chris@909 67 # it remains to be seen whether there are servers out
Chris@909 68 # there that will not work well with our approach.
Chris@909 69 #
Chris@909 70 # Added a controls-processor to SearchResult.
Chris@909 71 # Didn't add it everywhere because it just _feels_
Chris@909 72 # like it will need to be refactored.
Chris@909 73 #
Chris@909 74 def initialize ber_object
Chris@909 75 begin
Chris@909 76 @msg_id = ber_object[0].to_i
Chris@909 77 @app_tag = ber_object[1].ber_identifier - 0x60
Chris@909 78 rescue
Chris@909 79 # any error becomes a data-format error
Chris@909 80 raise LdapPduError.new( "ldap-pdu format error" )
Chris@909 81 end
Chris@909 82
Chris@909 83 case @app_tag
Chris@909 84 when BindResult
Chris@909 85 parse_ldap_result ber_object[1]
Chris@909 86 when SearchReturnedData
Chris@909 87 parse_search_return ber_object[1]
Chris@909 88 when SearchResultReferral
Chris@909 89 parse_search_referral ber_object[1]
Chris@909 90 when SearchResult
Chris@909 91 parse_ldap_result ber_object[1]
Chris@909 92 parse_controls(ber_object[2]) if ber_object[2]
Chris@909 93 when ModifyResponse
Chris@909 94 parse_ldap_result ber_object[1]
Chris@909 95 when AddResponse
Chris@909 96 parse_ldap_result ber_object[1]
Chris@909 97 when DeleteResponse
Chris@909 98 parse_ldap_result ber_object[1]
Chris@909 99 when ModifyRDNResponse
Chris@909 100 parse_ldap_result ber_object[1]
Chris@909 101 else
Chris@909 102 raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" )
Chris@909 103 end
Chris@909 104 end
Chris@909 105
Chris@909 106 #
Chris@909 107 # result_code
Chris@909 108 # This returns an LDAP result code taken from the PDU,
Chris@909 109 # but it will be nil if there wasn't a result code.
Chris@909 110 # That can easily happen depending on the type of packet.
Chris@909 111 #
Chris@909 112 def result_code code = :resultCode
Chris@909 113 @ldap_result and @ldap_result[code]
Chris@909 114 end
Chris@909 115
Chris@909 116 # Return RFC-2251 Controls if any.
Chris@909 117 # Messy. Does this functionality belong somewhere else?
Chris@909 118 def result_controls
Chris@909 119 @ldap_controls || []
Chris@909 120 end
Chris@909 121
Chris@909 122
Chris@909 123 #
Chris@909 124 # parse_ldap_result
Chris@909 125 #
Chris@909 126 def parse_ldap_result sequence
Chris@909 127 sequence.length >= 3 or raise LdapPduError
Chris@909 128 @ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]}
Chris@909 129 end
Chris@909 130 private :parse_ldap_result
Chris@909 131
Chris@909 132 #
Chris@909 133 # parse_search_return
Chris@909 134 # Definition from RFC 1777 (we're handling application-4 here)
Chris@909 135 #
Chris@909 136 # Search Response ::=
Chris@909 137 # CHOICE {
Chris@909 138 # entry [APPLICATION 4] SEQUENCE {
Chris@909 139 # objectName LDAPDN,
Chris@909 140 # attributes SEQUENCE OF SEQUENCE {
Chris@909 141 # AttributeType,
Chris@909 142 # SET OF AttributeValue
Chris@909 143 # }
Chris@909 144 # },
Chris@909 145 # resultCode [APPLICATION 5] LDAPResult
Chris@909 146 # }
Chris@909 147 #
Chris@909 148 # We concoct a search response that is a hash of the returned attribute values.
Chris@909 149 # NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES.
Chris@909 150 # This is to make them more predictable for user programs, but it
Chris@909 151 # may not be a good idea. Maybe this should be configurable.
Chris@909 152 # ALTERNATE IMPLEMENTATION: In addition to @search_dn and @search_attributes,
Chris@909 153 # we also return @search_entry, which is an LDAP::Entry object.
Chris@909 154 # If that works out well, then we'll remove the first two.
Chris@909 155 #
Chris@909 156 # Provisionally removed obsolete search_attributes and search_dn, 04May06.
Chris@909 157 #
Chris@909 158 def parse_search_return sequence
Chris@909 159 sequence.length >= 2 or raise LdapPduError
Chris@909 160 @search_entry = LDAP::Entry.new( sequence[0] )
Chris@909 161 #@search_dn = sequence[0]
Chris@909 162 #@search_attributes = {}
Chris@909 163 sequence[1].each {|seq|
Chris@909 164 @search_entry[seq[0]] = seq[1]
Chris@909 165 #@search_attributes[seq[0].downcase.intern] = seq[1]
Chris@909 166 }
Chris@909 167 end
Chris@909 168
Chris@909 169 #
Chris@909 170 # A search referral is a sequence of one or more LDAP URIs.
Chris@909 171 # Any number of search-referral replies can be returned by the server, interspersed
Chris@909 172 # with normal replies in any order.
Chris@909 173 # Until I can think of a better way to do this, we'll return the referrals as an array.
Chris@909 174 # It'll be up to higher-level handlers to expose something reasonable to the client.
Chris@909 175 def parse_search_referral uris
Chris@909 176 @search_referrals = uris
Chris@909 177 end
Chris@909 178
Chris@909 179
Chris@909 180 # Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting
Chris@909 181 # of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL
Chris@909 182 # Octet String. If only two fields are given, the second one may be
Chris@909 183 # either criticality or data, since criticality has a default value.
Chris@909 184 # Someday we may want to come back here and add support for some of
Chris@909 185 # more-widely used controls. RFC-2696 is a good example.
Chris@909 186 #
Chris@909 187 def parse_controls sequence
Chris@909 188 @ldap_controls = sequence.map do |control|
Chris@909 189 o = OpenStruct.new
Chris@909 190 o.oid,o.criticality,o.value = control[0],control[1],control[2]
Chris@909 191 if o.criticality and o.criticality.is_a?(String)
Chris@909 192 o.value = o.criticality
Chris@909 193 o.criticality = false
Chris@909 194 end
Chris@909 195 o
Chris@909 196 end
Chris@909 197 end
Chris@909 198 private :parse_controls
Chris@909 199
Chris@909 200
Chris@909 201 end
Chris@909 202
Chris@909 203
Chris@909 204 end # module Net
Chris@909 205