summaryrefslogtreecommitdiffstats
path: root/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap')
-rw-r--r--vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/dataset.rb108
-rw-r--r--vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/entry.rb165
-rw-r--r--vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/filter.rb387
-rw-r--r--vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/pdu.rb205
-rw-r--r--vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/psw.rb64
5 files changed, 929 insertions, 0 deletions
diff --git a/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/dataset.rb b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/dataset.rb
new file mode 100644
index 000000000..1480a8f84
--- /dev/null
+++ b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/dataset.rb
@@ -0,0 +1,108 @@
+# $Id: dataset.rb 78 2006-04-26 02:57:34Z blackhedd $
+#
+#
+#----------------------------------------------------------------------------
+#
+# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
+#
+# Gmail: garbagecat10
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+#---------------------------------------------------------------------------
+#
+#
+
+
+
+
+module Net
+class LDAP
+
+class Dataset < Hash
+
+ attr_reader :comments
+
+
+ def Dataset::read_ldif io
+ ds = Dataset.new
+
+ line = io.gets && chomp
+ dn = nil
+
+ while line
+ io.gets and chomp
+ if $_ =~ /^[\s]+/
+ line << " " << $'
+ else
+ nextline = $_
+
+ if line =~ /^\#/
+ ds.comments << line
+ elsif line =~ /^dn:[\s]*/i
+ dn = $'
+ ds[dn] = Hash.new {|k,v| k[v] = []}
+ elsif line.length == 0
+ dn = nil
+ elsif line =~ /^([^:]+):([\:]?)[\s]*/
+ # $1 is the attribute name
+ # $2 is a colon iff the attr-value is base-64 encoded
+ # $' is the attr-value
+ # Avoid the Base64 class because not all Ruby versions have it.
+ attrvalue = ($2 == ":") ? $'.unpack('m').shift : $'
+ ds[dn][$1.downcase.intern] << attrvalue
+ end
+
+ line = nextline
+ end
+ end
+
+ ds
+ end
+
+
+ def initialize
+ @comments = []
+ end
+
+
+ def to_ldif
+ ary = []
+ ary += (@comments || [])
+
+ keys.sort.each {|dn|
+ ary << "dn: #{dn}"
+
+ self[dn].keys.map {|sym| sym.to_s}.sort.each {|attr|
+ self[dn][attr.intern].each {|val|
+ ary << "#{attr}: #{val}"
+ }
+ }
+
+ ary << ""
+ }
+
+ block_given? and ary.each {|line| yield line}
+
+ ary
+ end
+
+
+end # Dataset
+
+end # LDAP
+end # Net
+
+
diff --git a/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/entry.rb b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/entry.rb
new file mode 100644
index 000000000..8978545ee
--- /dev/null
+++ b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/entry.rb
@@ -0,0 +1,165 @@
+# $Id: entry.rb 123 2006-05-18 03:52:38Z blackhedd $
+#
+# LDAP Entry (search-result) support classes
+#
+#
+#----------------------------------------------------------------------------
+#
+# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
+#
+# Gmail: garbagecat10
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+#---------------------------------------------------------------------------
+#
+
+
+
+
+module Net
+class LDAP
+
+
+ # Objects of this class represent individual entries in an LDAP
+ # directory. User code generally does not instantiate this class.
+ # Net::LDAP#search provides objects of this class to user code,
+ # either as block parameters or as return values.
+ #
+ # In LDAP-land, an "entry" is a collection of attributes that are
+ # uniquely and globally identified by a DN ("Distinguished Name").
+ # Attributes are identified by short, descriptive words or phrases.
+ # Although a directory is
+ # free to implement any attribute name, most of them follow rigorous
+ # standards so that the range of commonly-encountered attribute
+ # names is not large.
+ #
+ # An attribute name is case-insensitive. Most directories also
+ # restrict the range of characters allowed in attribute names.
+ # To simplify handling attribute names, Net::LDAP::Entry
+ # internally converts them to a standard format. Therefore, the
+ # methods which take attribute names can take Strings or Symbols,
+ # and work correctly regardless of case or capitalization.
+ #
+ # An attribute consists of zero or more data items called
+ # <i>values.</i> An entry is the combination of a unique DN, a set of attribute
+ # names, and a (possibly-empty) array of values for each attribute.
+ #
+ # Class Net::LDAP::Entry provides convenience methods for dealing
+ # with LDAP entries.
+ # In addition to the methods documented below, you may access individual
+ # attributes of an entry simply by giving the attribute name as
+ # the name of a method call. For example:
+ # ldap.search( ... ) do |entry|
+ # puts "Common name: #{entry.cn}"
+ # puts "Email addresses:"
+ # entry.mail.each {|ma| puts ma}
+ # end
+ # If you use this technique to access an attribute that is not present
+ # in a particular Entry object, a NoMethodError exception will be raised.
+ #
+ #--
+ # Ugly problem to fix someday: We key off the internal hash with
+ # a canonical form of the attribute name: convert to a string,
+ # downcase, then take the symbol. Unfortunately we do this in
+ # at least three places. Should do it in ONE place.
+ class Entry
+
+ # This constructor is not generally called by user code.
+ def initialize dn = nil # :nodoc:
+ @myhash = Hash.new {|k,v| k[v] = [] }
+ @myhash[:dn] = [dn]
+ end
+
+
+ def []= name, value # :nodoc:
+ sym = name.to_s.downcase.intern
+ @myhash[sym] = value
+ end
+
+
+ #--
+ # We have to deal with this one as we do with []=
+ # because this one and not the other one gets called
+ # in formulations like entry["CN"] << cn.
+ #
+ def [] name # :nodoc:
+ name = name.to_s.downcase.intern unless name.is_a?(Symbol)
+ @myhash[name]
+ end
+
+ # Returns the dn of the Entry as a String.
+ def dn
+ self[:dn][0]
+ end
+
+ # Returns an array of the attribute names present in the Entry.
+ def attribute_names
+ @myhash.keys
+ end
+
+ # Accesses each of the attributes present in the Entry.
+ # Calls a user-supplied block with each attribute in turn,
+ # passing two arguments to the block: a Symbol giving
+ # the name of the attribute, and a (possibly empty)
+ # Array of data values.
+ #
+ def each
+ if block_given?
+ attribute_names.each {|a|
+ attr_name,values = a,self[a]
+ yield attr_name, values
+ }
+ end
+ end
+
+ alias_method :each_attribute, :each
+
+
+ #--
+ # Convenience method to convert unknown method names
+ # to attribute references. Of course the method name
+ # comes to us as a symbol, so let's save a little time
+ # and not bother with the to_s.downcase two-step.
+ # Of course that means that a method name like mAIL
+ # won't work, but we shouldn't be encouraging that
+ # kind of bad behavior in the first place.
+ # Maybe we should thow something if the caller sends
+ # arguments or a block...
+ #
+ def method_missing *args, &block # :nodoc:
+ s = args[0].to_s.downcase.intern
+ if attribute_names.include?(s)
+ self[s]
+ elsif s.to_s[-1] == 61 and s.to_s.length > 1
+ value = args[1] or raise RuntimeError.new( "unable to set value" )
+ value = [value] unless value.is_a?(Array)
+ name = s.to_s[0..-2].intern
+ self[name] = value
+ else
+ raise NoMethodError.new( "undefined method '#{s}'" )
+ end
+ end
+
+ def write
+ end
+
+ end # class Entry
+
+
+end # class LDAP
+end # module Net
+
+
diff --git a/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/filter.rb b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/filter.rb
new file mode 100644
index 000000000..38944a710
--- /dev/null
+++ b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/filter.rb
@@ -0,0 +1,387 @@
+# $Id: filter.rb 151 2006-08-15 08:34:53Z blackhedd $
+#
+#
+#----------------------------------------------------------------------------
+#
+# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
+#
+# Gmail: garbagecat10
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+#---------------------------------------------------------------------------
+#
+#
+
+
+module Net
+class LDAP
+
+
+# Class Net::LDAP::Filter is used to constrain
+# LDAP searches. An object of this class is
+# passed to Net::LDAP#search in the parameter :filter.
+#
+# Net::LDAP::Filter supports the complete set of search filters
+# available in LDAP, including conjunction, disjunction and negation
+# (AND, OR, and NOT). This class supplants the (infamous) RFC-2254
+# standard notation for specifying LDAP search filters.
+#
+# Here's how to code the familiar "objectclass is present" filter:
+# f = Net::LDAP::Filter.pres( "objectclass" )
+# The object returned by this code can be passed directly to
+# the <tt>:filter</tt> parameter of Net::LDAP#search.
+#
+# See the individual class and instance methods below for more examples.
+#
+class Filter
+
+ def initialize op, a, b
+ @op = op
+ @left = a
+ @right = b
+ end
+
+ # #eq creates a filter object indicating that the value of
+ # a paticular attribute must be either <i>present</i> or must
+ # match a particular string.
+ #
+ # To specify that an attribute is "present" means that only
+ # directory entries which contain a value for the particular
+ # attribute will be selected by the filter. This is useful
+ # in case of optional attributes such as <tt>mail.</tt>
+ # Presence is indicated by giving the value "*" in the second
+ # parameter to #eq. This example selects only entries that have
+ # one or more values for <tt>sAMAccountName:</tt>
+ # f = Net::LDAP::Filter.eq( "sAMAccountName", "*" )
+ #
+ # To match a particular range of values, pass a string as the
+ # second parameter to #eq. The string may contain one or more
+ # "*" characters as wildcards: these match zero or more occurrences
+ # of any character. Full regular-expressions are <i>not</i> supported
+ # due to limitations in the underlying LDAP protocol.
+ # This example selects any entry with a <tt>mail</tt> value containing
+ # the substring "anderson":
+ # f = Net::LDAP::Filter.eq( "mail", "*anderson*" )
+ #--
+ # Removed gt and lt. They ain't in the standard!
+ #
+ def Filter::eq attribute, value; Filter.new :eq, attribute, value; end
+ def Filter::ne attribute, value; Filter.new :ne, attribute, value; end
+ #def Filter::gt attribute, value; Filter.new :gt, attribute, value; end
+ #def Filter::lt attribute, value; Filter.new :lt, attribute, value; end
+ def Filter::ge attribute, value; Filter.new :ge, attribute, value; end
+ def Filter::le attribute, value; Filter.new :le, attribute, value; end
+
+ # #pres( attribute ) is a synonym for #eq( attribute, "*" )
+ #
+ def Filter::pres attribute; Filter.eq attribute, "*"; end
+
+ # operator & ("AND") is used to conjoin two or more filters.
+ # This expression will select only entries that have an <tt>objectclass</tt>
+ # attribute AND have a <tt>mail</tt> attribute that begins with "George":
+ # f = Net::LDAP::Filter.pres( "objectclass" ) & Net::LDAP::Filter.eq( "mail", "George*" )
+ #
+ def & filter; Filter.new :and, self, filter; end
+
+ # operator | ("OR") is used to disjoin two or more filters.
+ # This expression will select entries that have either an <tt>objectclass</tt>
+ # attribute OR a <tt>mail</tt> attribute that begins with "George":
+ # f = Net::LDAP::Filter.pres( "objectclass" ) | Net::LDAP::Filter.eq( "mail", "George*" )
+ #
+ def | filter; Filter.new :or, self, filter; end
+
+
+ #
+ # operator ~ ("NOT") is used to negate a filter.
+ # This expression will select only entries that <i>do not</i> have an <tt>objectclass</tt>
+ # attribute:
+ # f = ~ Net::LDAP::Filter.pres( "objectclass" )
+ #
+ #--
+ # This operator can't be !, evidently. Try it.
+ # Removed GT and LT. They're not in the RFC.
+ def ~@; Filter.new :not, self, nil; end
+
+
+ def to_s
+ case @op
+ when :ne
+ "(!(#{@left}=#{@right}))"
+ when :eq
+ "(#{@left}=#{@right})"
+ #when :gt
+ # "#{@left}>#{@right}"
+ #when :lt
+ # "#{@left}<#{@right}"
+ when :ge
+ "#{@left}>=#{@right}"
+ when :le
+ "#{@left}<=#{@right}"
+ when :and
+ "(&(#{@left})(#{@right}))"
+ when :or
+ "(|(#{@left})(#{@right}))"
+ when :not
+ "(!(#{@left}))"
+ else
+ raise "invalid or unsupported operator in LDAP Filter"
+ end
+ end
+
+
+ #--
+ # to_ber
+ # Filter ::=
+ # CHOICE {
+ # and [0] SET OF Filter,
+ # or [1] SET OF Filter,
+ # not [2] Filter,
+ # equalityMatch [3] AttributeValueAssertion,
+ # substrings [4] SubstringFilter,
+ # greaterOrEqual [5] AttributeValueAssertion,
+ # lessOrEqual [6] AttributeValueAssertion,
+ # present [7] AttributeType,
+ # approxMatch [8] AttributeValueAssertion
+ # }
+ #
+ # SubstringFilter
+ # SEQUENCE {
+ # type AttributeType,
+ # SEQUENCE OF CHOICE {
+ # initial [0] LDAPString,
+ # any [1] LDAPString,
+ # final [2] LDAPString
+ # }
+ # }
+ #
+ # Parsing substrings is a little tricky.
+ # We use the split method to break a string into substrings
+ # delimited by the * (star) character. But we also need
+ # to know whether there is a star at the head and tail
+ # of the string. A Ruby particularity comes into play here:
+ # if you split on * and the first character of the string is
+ # a star, then split will return an array whose first element
+ # is an _empty_ string. But if the _last_ character of the
+ # string is star, then split will return an array that does
+ # _not_ add an empty string at the end. So we have to deal
+ # with all that specifically.
+ #
+ def to_ber
+ case @op
+ when :eq
+ if @right == "*" # present
+ @left.to_s.to_ber_contextspecific 7
+ elsif @right =~ /[\*]/ #substring
+ ary = @right.split( /[\*]+/ )
+ final_star = @right =~ /[\*]$/
+ initial_star = ary.first == "" and ary.shift
+
+ seq = []
+ unless initial_star
+ seq << ary.shift.to_ber_contextspecific(0)
+ end
+ n_any_strings = ary.length - (final_star ? 0 : 1)
+ #p n_any_strings
+ n_any_strings.times {
+ seq << ary.shift.to_ber_contextspecific(1)
+ }
+ unless final_star
+ seq << ary.shift.to_ber_contextspecific(2)
+ end
+ [@left.to_s.to_ber, seq.to_ber].to_ber_contextspecific 4
+ else #equality
+ [@left.to_s.to_ber, @right.to_ber].to_ber_contextspecific 3
+ end
+ when :ge
+ [@left.to_s.to_ber, @right.to_ber].to_ber_contextspecific 5
+ when :le
+ [@left.to_s.to_ber, @right.to_ber].to_ber_contextspecific 6
+ when :and
+ ary = [@left.coalesce(:and), @right.coalesce(:and)].flatten
+ ary.map {|a| a.to_ber}.to_ber_contextspecific( 0 )
+ when :or
+ ary = [@left.coalesce(:or), @right.coalesce(:or)].flatten
+ ary.map {|a| a.to_ber}.to_ber_contextspecific( 1 )
+ when :not
+ [@left.to_ber].to_ber_contextspecific 2
+ else
+ # ERROR, we'll return objectclass=* to keep things from blowing up,
+ # but that ain't a good answer and we need to kick out an error of some kind.
+ raise "unimplemented search filter"
+ end
+ end
+
+ #--
+ # coalesce
+ # This is a private helper method for dealing with chains of ANDs and ORs
+ # that are longer than two. If BOTH of our branches are of the specified
+ # type of joining operator, then return both of them as an array (calling
+ # coalesce recursively). If they're not, then return an array consisting
+ # only of self.
+ #
+ def coalesce operator
+ if @op == operator
+ [@left.coalesce( operator ), @right.coalesce( operator )]
+ else
+ [self]
+ end
+ end
+
+
+
+ #--
+ # We get a Ruby object which comes from parsing an RFC-1777 "Filter"
+ # object. Convert it to a Net::LDAP::Filter.
+ # TODO, we're hardcoding the RFC-1777 BER-encodings of the various
+ # filter types. Could pull them out into a constant.
+ #
+ def Filter::parse_ldap_filter obj
+ case obj.ber_identifier
+ when 0x87 # present. context-specific primitive 7.
+ Filter.eq( obj.to_s, "*" )
+ when 0xa3 # equalityMatch. context-specific constructed 3.
+ Filter.eq( obj[0], obj[1] )
+ else
+ raise LdapError.new( "unknown ldap search-filter type: #{obj.ber_identifier}" )
+ end
+ end
+
+
+ #--
+ # We got a hash of attribute values.
+ # Do we match the attributes?
+ # Return T/F, and call match recursively as necessary.
+ def match entry
+ case @op
+ when :eq
+ if @right == "*"
+ l = entry[@left] and l.length > 0
+ else
+ l = entry[@left] and l = l.to_a and l.index(@right)
+ end
+ else
+ raise LdapError.new( "unknown filter type in match: #{@op}" )
+ end
+ end
+
+ # Converts an LDAP filter-string (in the prefix syntax specified in RFC-2254)
+ # to a Net::LDAP::Filter.
+ def self.construct ldap_filter_string
+ FilterParser.new(ldap_filter_string).filter
+ end
+
+ # Synonym for #construct.
+ # to a Net::LDAP::Filter.
+ def self.from_rfc2254 ldap_filter_string
+ construct ldap_filter_string
+ end
+
+end # class Net::LDAP::Filter
+
+
+
+class FilterParser #:nodoc:
+
+ attr_reader :filter
+
+ def initialize str
+ require 'strscan'
+ @filter = parse( StringScanner.new( str )) or raise Net::LDAP::LdapError.new( "invalid filter syntax" )
+ end
+
+ def parse scanner
+ parse_filter_branch(scanner) or parse_paren_expression(scanner)
+ end
+
+ def parse_paren_expression scanner
+ if scanner.scan /\s*\(\s*/
+ b = if scanner.scan /\s*\&\s*/
+ a = nil
+ branches = []
+ while br = parse_paren_expression(scanner)
+ branches << br
+ end
+ if branches.length >= 2
+ a = branches.shift
+ while branches.length > 0
+ a = a & branches.shift
+ end
+ a
+ end
+ elsif scanner.scan /\s*\|\s*/
+ # TODO: DRY!
+ a = nil
+ branches = []
+ while br = parse_paren_expression(scanner)
+ branches << br
+ end
+ if branches.length >= 2
+ a = branches.shift
+ while branches.length > 0
+ a = a | branches.shift
+ end
+ a
+ end
+ elsif scanner.scan /\s*\!\s*/
+ br = parse_paren_expression(scanner)
+ if br
+ ~ br
+ end
+ else
+ parse_filter_branch( scanner )
+ end
+
+ if b and scanner.scan( /\s*\)\s*/ )
+ b
+ end
+ end
+ end
+
+ # Added a greatly-augmented filter contributed by Andre Nathan
+ # for detecting special characters in values. (15Aug06)
+ def parse_filter_branch scanner
+ scanner.scan /\s*/
+ if token = scanner.scan( /[\w\-_]+/ )
+ scanner.scan /\s*/
+ if op = scanner.scan( /\=|\<\=|\<|\>\=|\>|\!\=/ )
+ scanner.scan /\s*/
+ #if value = scanner.scan( /[\w\*\.]+/ ) (ORG)
+ if value = scanner.scan( /[\w\*\.\+\-@=#\$%&!]+/ )
+ case op
+ when "="
+ Filter.eq( token, value )
+ when "!="
+ Filter.ne( token, value )
+ when "<"
+ Filter.lt( token, value )
+ when "<="
+ Filter.le( token, value )
+ when ">"
+ Filter.gt( token, value )
+ when ">="
+ Filter.ge( token, value )
+ end
+ end
+ end
+ end
+ end
+
+end # class Net::LDAP::FilterParser
+
+end # class Net::LDAP
+end # module Net
+
+
diff --git a/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/pdu.rb b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/pdu.rb
new file mode 100644
index 000000000..dbc0d6f10
--- /dev/null
+++ b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/pdu.rb
@@ -0,0 +1,205 @@
+# $Id: pdu.rb 126 2006-05-31 15:55:16Z blackhedd $
+#
+# LDAP PDU support classes
+#
+#
+#----------------------------------------------------------------------------
+#
+# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
+#
+# Gmail: garbagecat10
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+#---------------------------------------------------------------------------
+#
+
+
+
+module Net
+
+
+class LdapPduError < Exception; end
+
+
+class LdapPdu
+
+ BindResult = 1
+ SearchReturnedData = 4
+ SearchResult = 5
+ ModifyResponse = 7
+ AddResponse = 9
+ DeleteResponse = 11
+ ModifyRDNResponse = 13
+ SearchResultReferral = 19
+
+ attr_reader :msg_id, :app_tag
+ attr_reader :search_dn, :search_attributes, :search_entry
+ attr_reader :search_referrals
+
+ #
+ # initialize
+ # An LDAP PDU always looks like a BerSequence with
+ # at least two elements: an integer (message-id number), and
+ # an application-specific sequence.
+ # Some LDAPv3 packets also include an optional
+ # third element, which is a sequence of "controls"
+ # (See RFC 2251, section 4.1.12).
+ # The application-specific tag in the sequence tells
+ # us what kind of packet it is, and each kind has its
+ # own format, defined in RFC-1777.
+ # Observe that many clients (such as ldapsearch)
+ # do not necessarily enforce the expected application
+ # tags on received protocol packets. This implementation
+ # does interpret the RFC strictly in this regard, and
+ # it remains to be seen whether there are servers out
+ # there that will not work well with our approach.
+ #
+ # Added a controls-processor to SearchResult.
+ # Didn't add it everywhere because it just _feels_
+ # like it will need to be refactored.
+ #
+ def initialize ber_object
+ begin
+ @msg_id = ber_object[0].to_i
+ @app_tag = ber_object[1].ber_identifier - 0x60
+ rescue
+ # any error becomes a data-format error
+ raise LdapPduError.new( "ldap-pdu format error" )
+ end
+
+ case @app_tag
+ when BindResult
+ parse_ldap_result ber_object[1]
+ when SearchReturnedData
+ parse_search_return ber_object[1]
+ when SearchResultReferral
+ parse_search_referral ber_object[1]
+ when SearchResult
+ parse_ldap_result ber_object[1]
+ parse_controls(ber_object[2]) if ber_object[2]
+ when ModifyResponse
+ parse_ldap_result ber_object[1]
+ when AddResponse
+ parse_ldap_result ber_object[1]
+ when DeleteResponse
+ parse_ldap_result ber_object[1]
+ when ModifyRDNResponse
+ parse_ldap_result ber_object[1]
+ else
+ raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" )
+ end
+ end
+
+ #
+ # result_code
+ # This returns an LDAP result code taken from the PDU,
+ # but it will be nil if there wasn't a result code.
+ # That can easily happen depending on the type of packet.
+ #
+ def result_code code = :resultCode
+ @ldap_result and @ldap_result[code]
+ end
+
+ # Return RFC-2251 Controls if any.
+ # Messy. Does this functionality belong somewhere else?
+ def result_controls
+ @ldap_controls || []
+ end
+
+
+ #
+ # parse_ldap_result
+ #
+ def parse_ldap_result sequence
+ sequence.length >= 3 or raise LdapPduError
+ @ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]}
+ end
+ private :parse_ldap_result
+
+ #
+ # parse_search_return
+ # Definition from RFC 1777 (we're handling application-4 here)
+ #
+ # Search Response ::=
+ # CHOICE {
+ # entry [APPLICATION 4] SEQUENCE {
+ # objectName LDAPDN,
+ # attributes SEQUENCE OF SEQUENCE {
+ # AttributeType,
+ # SET OF AttributeValue
+ # }
+ # },
+ # resultCode [APPLICATION 5] LDAPResult
+ # }
+ #
+ # We concoct a search response that is a hash of the returned attribute values.
+ # NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES.
+ # This is to make them more predictable for user programs, but it
+ # may not be a good idea. Maybe this should be configurable.
+ # ALTERNATE IMPLEMENTATION: In addition to @search_dn and @search_attributes,
+ # we also return @search_entry, which is an LDAP::Entry object.
+ # If that works out well, then we'll remove the first two.
+ #
+ # Provisionally removed obsolete search_attributes and search_dn, 04May06.
+ #
+ def parse_search_return sequence
+ sequence.length >= 2 or raise LdapPduError
+ @search_entry = LDAP::Entry.new( sequence[0] )
+ #@search_dn = sequence[0]
+ #@search_attributes = {}
+ sequence[1].each {|seq|
+ @search_entry[seq[0]] = seq[1]
+ #@search_attributes[seq[0].downcase.intern] = seq[1]
+ }
+ end
+
+ #
+ # A search referral is a sequence of one or more LDAP URIs.
+ # Any number of search-referral replies can be returned by the server, interspersed
+ # with normal replies in any order.
+ # Until I can think of a better way to do this, we'll return the referrals as an array.
+ # It'll be up to higher-level handlers to expose something reasonable to the client.
+ def parse_search_referral uris
+ @search_referrals = uris
+ end
+
+
+ # Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting
+ # of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL
+ # Octet String. If only two fields are given, the second one may be
+ # either criticality or data, since criticality has a default value.
+ # Someday we may want to come back here and add support for some of
+ # more-widely used controls. RFC-2696 is a good example.
+ #
+ def parse_controls sequence
+ @ldap_controls = sequence.map do |control|
+ o = OpenStruct.new
+ o.oid,o.criticality,o.value = control[0],control[1],control[2]
+ if o.criticality and o.criticality.is_a?(String)
+ o.value = o.criticality
+ o.criticality = false
+ end
+ o
+ end
+ end
+ private :parse_controls
+
+
+end
+
+
+end # module Net
+
diff --git a/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/psw.rb b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/psw.rb
new file mode 100644
index 000000000..89d1ffdf2
--- /dev/null
+++ b/vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/psw.rb
@@ -0,0 +1,64 @@
+# $Id: psw.rb 73 2006-04-24 21:59:35Z blackhedd $
+#
+#
+#----------------------------------------------------------------------------
+#
+# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
+#
+# Gmail: garbagecat10
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+#---------------------------------------------------------------------------
+#
+#
+
+
+module Net
+class LDAP
+
+
+class Password
+ class << self
+
+ # Generate a password-hash suitable for inclusion in an LDAP attribute.
+ # Pass a hash type (currently supported: :md5 and :sha) and a plaintext
+ # password. This function will return a hashed representation.
+ # STUB: This is here to fulfill the requirements of an RFC, which one?
+ # TODO, gotta do salted-sha and (maybe) salted-md5.
+ # Should we provide sha1 as a synonym for sha1? I vote no because then
+ # should you also provide ssha1 for symmetry?
+ def generate( type, str )
+ case type
+ when :md5
+ require 'md5'
+ "{MD5}#{ [MD5.new( str.to_s ).digest].pack("m").chomp }"
+ when :sha
+ require 'sha1'
+ "{SHA}#{ [SHA1.new( str.to_s ).digest].pack("m").chomp }"
+ # when ssha
+ else
+ raise Net::LDAP::LdapError.new( "unsupported password-hash type (#{type})" )
+ end
+ end
+
+ end
+end
+
+
+end # class LDAP
+end # module Net
+
+