Feature #1060 » net-ldap-0.2.2_r5657.patch
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testldif.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: testldif.rb 61 2006-04-18 20:55:55Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | ||
| 5 | ||
| 6 | $:.unshift "lib" | |
| 7 | ||
| 8 | require 'test/unit' | |
| 9 | ||
| 10 | require 'net/ldap' | |
| 11 | require 'net/ldif' | |
| 12 | ||
| 13 | require 'sha1' | |
| 14 | require 'base64' | |
| 15 | ||
| 16 | class TestLdif < Test::Unit::TestCase | |
| 17 | ||
| 18 | TestLdifFilename = "tests/testdata.ldif" | |
| 19 | ||
| 20 | def test_empty_ldif | |
| 21 | ds = Net::LDAP::Dataset::read_ldif( StringIO.new ) | |
| 22 | assert_equal( true, ds.empty? ) | |
| 23 | end | |
| 24 | ||
| 25 | def test_ldif_with_comments | |
| 26 | str = ["# Hello from LDIF-land", "# This is an unterminated comment"] | |
| 27 | io = StringIO.new( str[0] + "\r\n" + str[1] ) | |
| 28 | ds = Net::LDAP::Dataset::read_ldif( io ) | |
| 29 | assert_equal( str, ds.comments ) | |
| 30 | end | |
| 31 | ||
| 32 | def test_ldif_with_password | |
| 33 | psw = "goldbricks" | |
| 34 |     hashed_psw = "{SHA}" + Base64::encode64( SHA1.new(psw).digest ).chomp | |
| 35 | ||
| 36 | ldif_encoded = Base64::encode64( hashed_psw ).chomp | |
| 37 |     ds = Net::LDAP::Dataset::read_ldif( StringIO.new( "dn: Goldbrick\r\nuserPassword:: #{ldif_encoded}\r\n\r\n" )) | |
| 38 | recovered_psw = ds["Goldbrick"][:userpassword].shift | |
| 39 | assert_equal( hashed_psw, recovered_psw ) | |
| 40 | end | |
| 41 | ||
| 42 | def test_ldif_with_continuation_lines | |
| 43 | ds = Net::LDAP::Dataset::read_ldif( StringIO.new( "dn: abcdefg\r\n hijklmn\r\n\r\n" )) | |
| 44 | assert_equal( true, ds.has_key?( "abcdefg hijklmn" )) | |
| 45 | end | |
| 46 | ||
| 47 | # TODO, INADEQUATE. We need some more tests | |
| 48 | # to verify the content. | |
| 49 | def test_ldif | |
| 50 |     File.open( TestLdifFilename, "r" ) {|f| | |
| 51 | ds = Net::LDAP::Dataset::read_ldif( f ) | |
| 52 | assert_equal( 13, ds.length ) | |
| 53 | } | |
| 54 | end | |
| 55 | ||
| 56 | # TODO, need some tests. | |
| 57 | # Must test folded lines and base64-encoded lines as well as normal ones. | |
| 58 | def test_to_ldif | |
| 59 |     File.open( TestLdifFilename, "r" ) {|f| | |
| 60 | ds = Net::LDAP::Dataset::read_ldif( f ) | |
| 61 | ds.to_ldif | |
| 62 | assert_equal( true, false ) # REMOVE WHEN WE HAVE SOME TESTS HERE. | |
| 63 | } | |
| 64 | end | |
| 65 | ||
| 66 | ||
| 67 | end | |
| 68 | ||
| 69 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testldap.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: testldap.rb 65 2006-04-23 01:17:49Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | ||
| 5 | ||
| 6 | $:.unshift "lib" | |
| 7 | ||
| 8 | require 'test/unit' | |
| 9 | ||
| 10 | require 'net/ldap' | |
| 11 | require 'stringio' | |
| 12 | ||
| 13 | ||
| 14 | class TestLdapClient < Test::Unit::TestCase | |
| 15 | ||
| 16 | # TODO: these tests crash and burn if the associated | |
| 17 | # LDAP testserver isn't up and running. | |
| 18 | # We rely on being able to read a file with test data | |
| 19 | # in LDIF format. | |
| 20 | # TODO, WARNING: for the moment, this data is in a file | |
| 21 | # whose name and location are HARDCODED into the | |
| 22 | # instance method load_test_data. | |
| 23 | ||
| 24 | def setup | |
| 25 | @host = "127.0.0.1" | |
| 26 | @port = 3890 | |
| 27 |     @auth = { | |
| 28 | :method => :simple, | |
| 29 | :username => "cn=bigshot,dc=bayshorenetworks,dc=com", | |
| 30 | :password => "opensesame" | |
| 31 | } | |
| 32 | ||
| 33 | @ldif = load_test_data | |
| 34 | end | |
| 35 | ||
| 36 | ||
| 37 | ||
| 38 | # Get some test data which will be used to validate | |
| 39 | # the responses from the test LDAP server we will | |
| 40 | # connect to. | |
| 41 | # TODO, Bogus: we are HARDCODING the location of the file for now. | |
| 42 | # | |
| 43 | def load_test_data | |
| 44 | ary = File.readlines( "tests/testdata.ldif" ) | |
| 45 |     hash = {} | |
| 46 | while line = ary.shift and line.chomp! | |
| 47 | if line =~ /^dn:[\s]*/i | |
| 48 | dn = $' | |
| 49 |         hash[dn] = {} | |
| 50 | while attr = ary.shift and attr.chomp! and attr =~ /^([\w]+)[\s]*:[\s]*/ | |
| 51 | hash[dn][$1.downcase.intern] ||= [] | |
| 52 | hash[dn][$1.downcase.intern] << $' | |
| 53 | end | |
| 54 | end | |
| 55 | end | |
| 56 | hash | |
| 57 | end | |
| 58 | ||
| 59 | ||
| 60 | ||
| 61 | # Binding tests. | |
| 62 | # Need tests for all kinds of network failures and incorrect auth. | |
| 63 | # TODO: Implement a class-level timeout for operations like bind. | |
| 64 | # Search has a timeout defined at the protocol level, other ops do not. | |
| 65 | # TODO, use constants for the LDAP result codes, rather than hardcoding them. | |
| 66 | def test_bind | |
| 67 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth | |
| 68 | assert_equal( true, ldap.bind ) | |
| 69 | assert_equal( 0, ldap.get_operation_result.code ) | |
| 70 | assert_equal( "Success", ldap.get_operation_result.message ) | |
| 71 | ||
| 72 |     bad_username = @auth.merge( {:username => "cn=badguy,dc=imposters,dc=com"} ) | |
| 73 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => bad_username | |
| 74 | assert_equal( false, ldap.bind ) | |
| 75 | assert_equal( 48, ldap.get_operation_result.code ) | |
| 76 | assert_equal( "Inappropriate Authentication", ldap.get_operation_result.message ) | |
| 77 | ||
| 78 |     bad_password = @auth.merge( {:password => "cornhusk"} ) | |
| 79 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => bad_password | |
| 80 | assert_equal( false, ldap.bind ) | |
| 81 | assert_equal( 49, ldap.get_operation_result.code ) | |
| 82 | assert_equal( "Invalid Credentials", ldap.get_operation_result.message ) | |
| 83 | end | |
| 84 | ||
| 85 | ||
| 86 | ||
| 87 | def test_search | |
| 88 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth | |
| 89 | ||
| 90 |     search = {:base => "dc=smalldomain,dc=com"} | |
| 91 | assert_equal( false, ldap.search( search )) | |
| 92 | assert_equal( 32, ldap.get_operation_result.code ) | |
| 93 |  | |
| 94 |     search = {:base => "dc=bayshorenetworks,dc=com"} | |
| 95 | assert_equal( true, ldap.search( search )) | |
| 96 | assert_equal( 0, ldap.get_operation_result.code ) | |
| 97 |  | |
| 98 |     ldap.search( search ) {|res| | |
| 99 | assert_equal( res, @ldif ) | |
| 100 | } | |
| 101 | end | |
| 102 |  | |
| 103 | ||
| 104 | ||
| 105 | ||
| 106 | # This is a helper routine for test_search_attributes. | |
| 107 | def internal_test_search_attributes attrs_to_search | |
| 108 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth | |
| 109 | assert( ldap.bind ) | |
| 110 | ||
| 111 |     search = { | |
| 112 | :base => "dc=bayshorenetworks,dc=com", | |
| 113 | :attributes => attrs_to_search | |
| 114 | } | |
| 115 | ||
| 116 | ldif = @ldif | |
| 117 |     ldif.each {|dn,entry| | |
| 118 |       entry.delete_if {|attr,value| | |
| 119 | ! attrs_to_search.include?(attr) | |
| 120 | } | |
| 121 | } | |
| 122 |  | |
| 123 | assert_equal( true, ldap.search( search )) | |
| 124 |     ldap.search( search ) {|res| | |
| 125 | res_keys = res.keys.sort | |
| 126 | ldif_keys = ldif.keys.sort | |
| 127 | assert( res_keys, ldif_keys ) | |
| 128 |       res.keys.each {|rk| | |
| 129 | assert( res[rk], ldif[rk] ) | |
| 130 | } | |
| 131 | } | |
| 132 | end | |
| 133 | ||
| 134 | ||
| 135 | def test_search_attributes | |
| 136 | internal_test_search_attributes [:mail] | |
| 137 | internal_test_search_attributes [:cn] | |
| 138 | internal_test_search_attributes [:ou] | |
| 139 | internal_test_search_attributes [:hasaccessprivilege] | |
| 140 | internal_test_search_attributes ["mail"] | |
| 141 | internal_test_search_attributes ["cn"] | |
| 142 | internal_test_search_attributes ["ou"] | |
| 143 | internal_test_search_attributes ["hasaccessrole"] | |
| 144 | ||
| 145 | internal_test_search_attributes [:mail, :cn, :ou, :hasaccessrole] | |
| 146 | internal_test_search_attributes [:mail, "cn", :ou, "hasaccessrole"] | |
| 147 | end | |
| 148 | ||
| 149 | ||
| 150 | def test_search_filters | |
| 151 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth | |
| 152 |     search = { | |
| 153 | :base => "dc=bayshorenetworks,dc=com", | |
| 154 | :filter => Net::LDAP::Filter.eq( "sn", "Fosse" ) | |
| 155 | } | |
| 156 | ||
| 157 |     ldap.search( search ) {|res| | |
| 158 | p res | |
| 159 | } | |
| 160 | end | |
| 161 | ||
| 162 | ||
| 163 | ||
| 164 | def test_open | |
| 165 | ldap = Net::LDAP.new :host => @host, :port => @port, :auth => @auth | |
| 166 |     ldap.open {|ldap| | |
| 167 |       10.times { | |
| 168 | rc = ldap.search( :base => "dc=bayshorenetworks,dc=com" ) | |
| 169 | assert_equal( true, rc ) | |
| 170 | } | |
| 171 | } | |
| 172 | end | |
| 173 | ||
| 174 | ||
| 175 | def test_ldap_open | |
| 176 |     Net::LDAP.open( :host => @host, :port => @port, :auth => @auth ) {|ldap| | |
| 177 |       10.times { | |
| 178 | rc = ldap.search( :base => "dc=bayshorenetworks,dc=com" ) | |
| 179 | assert_equal( true, rc ) | |
| 180 | } | |
| 181 | } | |
| 182 | end | |
| 183 | ||
| 184 | ||
| 185 | ||
| 186 | ||
| 187 | ||
| 188 | end | |
| 189 | ||
| 190 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testem.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: testem.rb 121 2006-05-15 18:36:24Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | ||
| 5 | require 'test/unit' | |
| 6 | require 'tests/testber' | |
| 7 | require 'tests/testldif' | |
| 8 | require 'tests/testldap' | |
| 9 | require 'tests/testpsw' | |
| 10 | require 'tests/testfilter' | |
| 11 | ||
| 12 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testdata.ldif (working copy) | ||
|---|---|---|
| 1 | # $Id: testdata.ldif 50 2006-04-17 17:57:33Z blackhedd $ | |
| 2 | # | |
| 3 | # This is test-data for an LDAP server in LDIF format. | |
| 4 | # | |
| 5 | dn: dc=bayshorenetworks,dc=com | |
| 6 | objectClass: dcObject | |
| 7 | objectClass: organization | |
| 8 | o: Bayshore Networks LLC | |
| 9 | dc: bayshorenetworks | |
| 10 | ||
| 11 | dn: cn=Manager,dc=bayshorenetworks,dc=com | |
| 12 | objectClass: organizationalrole | |
| 13 | cn: Manager | |
| 14 | ||
| 15 | dn: ou=people,dc=bayshorenetworks,dc=com | |
| 16 | objectClass: organizationalunit | |
| 17 | ou: people | |
| 18 | ||
| 19 | dn: ou=privileges,dc=bayshorenetworks,dc=com | |
| 20 | objectClass: organizationalunit | |
| 21 | ou: privileges | |
| 22 | ||
| 23 | dn: ou=roles,dc=bayshorenetworks,dc=com | |
| 24 | objectClass: organizationalunit | |
| 25 | ou: roles | |
| 26 | ||
| 27 | dn: ou=office,dc=bayshorenetworks,dc=com | |
| 28 | objectClass: organizationalunit | |
| 29 | ou: office | |
| 30 | ||
| 31 | dn: mail=nogoodnik@steamheat.net,ou=people,dc=bayshorenetworks,dc=com | |
| 32 | cn: Bob Fosse | |
| 33 | mail: nogoodnik@steamheat.net | |
| 34 | sn: Fosse | |
| 35 | ou: people | |
| 36 | objectClass: top | |
| 37 | objectClass: inetorgperson | |
| 38 | objectClass: authorizedperson | |
| 39 | hasAccessRole: uniqueIdentifier=engineer,ou=roles | |
| 40 | hasAccessRole: uniqueIdentifier=ldapadmin,ou=roles | |
| 41 | hasAccessRole: uniqueIdentifier=ldapsuperadmin,ou=roles | |
| 42 | hasAccessRole: uniqueIdentifier=ogilvy_elephant_user,ou=roles | |
| 43 | hasAccessRole: uniqueIdentifier=ogilvy_eagle_user,ou=roles | |
| 44 | hasAccessRole: uniqueIdentifier=greenplug_user,ou=roles | |
| 45 | hasAccessRole: uniqueIdentifier=brandplace_logging_user,ou=roles | |
| 46 | hasAccessRole: uniqueIdentifier=brandplace_report_user,ou=roles | |
| 47 | hasAccessRole: uniqueIdentifier=workorder_user,ou=roles | |
| 48 | hasAccessRole: uniqueIdentifier=bayshore_eagle_user,ou=roles | |
| 49 | hasAccessRole: uniqueIdentifier=bayshore_eagle_superuser,ou=roles | |
| 50 | hasAccessRole: uniqueIdentifier=kledaras_user,ou=roles | |
| 51 | ||
| 52 | dn: mail=elephant@steamheat.net,ou=people,dc=bayshorenetworks,dc=com | |
| 53 | cn: Gwen Verdon | |
| 54 | mail: elephant@steamheat.net | |
| 55 | sn: Verdon | |
| 56 | ou: people | |
| 57 | objectClass: top | |
| 58 | objectClass: inetorgperson | |
| 59 | objectClass: authorizedperson | |
| 60 | hasAccessRole: uniqueIdentifier=brandplace_report_user,ou=roles | |
| 61 | hasAccessRole: uniqueIdentifier=engineer,ou=roles | |
| 62 | hasAccessRole: uniqueIdentifier=ogilvy_elephant_user,ou=roles | |
| 63 | hasAccessRole: uniqueIdentifier=ldapsuperadmin,ou=roles | |
| 64 | hasAccessRole: uniqueIdentifier=ldapadmin,ou=roles | |
| 65 | ||
| 66 | dn: uniqueIdentifier=engineering,ou=privileges,dc=bayshorenetworks,dc=com | |
| 67 | uniqueIdentifier: engineering | |
| 68 | ou: privileges | |
| 69 | objectClass: accessPrivilege | |
| 70 | ||
| 71 | dn: uniqueIdentifier=engineer,ou=roles,dc=bayshorenetworks,dc=com | |
| 72 | uniqueIdentifier: engineer | |
| 73 | ou: roles | |
| 74 | objectClass: accessRole | |
| 75 | hasAccessPrivilege: uniqueIdentifier=engineering,ou=privileges | |
| 76 | ||
| 77 | dn: uniqueIdentifier=ldapadmin,ou=roles,dc=bayshorenetworks,dc=com | |
| 78 | uniqueIdentifier: ldapadmin | |
| 79 | ou: roles | |
| 80 | objectClass: accessRole | |
| 81 | ||
| 82 | dn: uniqueIdentifier=ldapsuperadmin,ou=roles,dc=bayshorenetworks,dc=com | |
| 83 | uniqueIdentifier: ldapsuperadmin | |
| 84 | ou: roles | |
| 85 | objectClass: accessRole | |
| 86 | ||
| 87 | dn: mail=catperson@steamheat.net,ou=people,dc=bayshorenetworks,dc=com | |
| 88 | cn: Sid Sorokin | |
| 89 | mail: catperson@steamheat.net | |
| 90 | sn: Sorokin | |
| 91 | ou: people | |
| 92 | objectClass: top | |
| 93 | objectClass: inetorgperson | |
| 94 | objectClass: authorizedperson | |
| 95 | hasAccessRole: uniqueIdentifier=engineer,ou=roles | |
| 96 | hasAccessRole: uniqueIdentifier=ogilvy_elephant_user,ou=roles | |
| 97 | hasAccessRole: uniqueIdentifier=ldapsuperadmin,ou=roles | |
| 98 | hasAccessRole: uniqueIdentifier=ogilvy_eagle_user,ou=roles | |
| 99 | hasAccessRole: uniqueIdentifier=greenplug_user,ou=roles | |
| 100 | hasAccessRole: uniqueIdentifier=workorder_user,ou=roles | |
| 101 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testfilter.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: testfilter.rb 122 2006-05-15 20:03:56Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | ||
| 5 | require 'test/unit' | |
| 6 | ||
| 7 | $:.unshift "lib" | |
| 8 | ||
| 9 | require 'net/ldap' | |
| 10 | ||
| 11 | ||
| 12 | class TestFilter < Test::Unit::TestCase | |
| 13 | ||
| 14 | def setup | |
| 15 | end | |
| 16 | ||
| 17 | ||
| 18 | def teardown | |
| 19 | end | |
| 20 | ||
| 21 | def test_rfc_2254 | |
| 22 | p Net::LDAP::Filter.from_rfc2254( " ( uid=george* ) " ) | |
| 23 | p Net::LDAP::Filter.from_rfc2254( "uid!=george*" ) | |
| 24 | p Net::LDAP::Filter.from_rfc2254( "uid<george*" ) | |
| 25 | p Net::LDAP::Filter.from_rfc2254( "uid <= george*" ) | |
| 26 | p Net::LDAP::Filter.from_rfc2254( "uid>george*" ) | |
| 27 | p Net::LDAP::Filter.from_rfc2254( "uid>=george*" ) | |
| 28 | p Net::LDAP::Filter.from_rfc2254( "uid!=george*" ) | |
| 29 | ||
| 30 | p Net::LDAP::Filter.from_rfc2254( "(& (uid!=george* ) (mail=*))" ) | |
| 31 | p Net::LDAP::Filter.from_rfc2254( "(| (uid!=george* ) (mail=*))" ) | |
| 32 | p Net::LDAP::Filter.from_rfc2254( "(! (mail=*))" ) | |
| 33 | end | |
| 34 | ||
| 35 | ||
| 36 | end | |
| 37 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testber.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: testber.rb 57 2006-04-18 00:18:48Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | ||
| 5 | ||
| 6 | $:.unshift "lib" | |
| 7 | ||
| 8 | require 'net/ldap' | |
| 9 | require 'stringio' | |
| 10 | ||
| 11 | ||
| 12 | class TestBer < Test::Unit::TestCase | |
| 13 | ||
| 14 | def setup | |
| 15 | end | |
| 16 | ||
| 17 | # TODO: Add some much bigger numbers | |
| 18 | # 5000000000 is a Bignum, which hits different code. | |
| 19 | def test_ber_integers | |
| 20 | assert_equal( "\002\001\005", 5.to_ber ) | |
| 21 | assert_equal( "\002\002\203t", 500.to_ber ) | |
| 22 | assert_equal( "\002\003\203\206P", 50000.to_ber ) | |
| 23 | assert_equal( "\002\005\222\320\227\344\000", 5000000000.to_ber ) | |
| 24 | end | |
| 25 | ||
| 26 | def test_ber_parsing | |
| 27 | assert_equal( 6, "\002\001\006".read_ber( Net::LDAP::AsnSyntax )) | |
| 28 | assert_equal( "testing", "\004\007testing".read_ber( Net::LDAP::AsnSyntax )) | |
| 29 | end | |
| 30 | ||
| 31 | ||
| 32 | def test_ber_parser_on_ldap_bind_request | |
| 33 | s = StringIO.new "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus" | |
| 34 | assert_equal( [1, [3, "Administrator", "ad_is_bogus"]], s.read_ber( Net::LDAP::AsnSyntax )) | |
| 35 | end | |
| 36 | ||
| 37 | ||
| 38 | ||
| 39 | ||
| 40 | end | |
| 41 | ||
| 42 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/tests/testpsw.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: testpsw.rb 72 2006-04-24 21:58:14Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | ||
| 5 | ||
| 6 | $:.unshift "lib" | |
| 7 | ||
| 8 | require 'net/ldap' | |
| 9 | require 'stringio' | |
| 10 | ||
| 11 | ||
| 12 | class TestPassword < Test::Unit::TestCase | |
| 13 | ||
| 14 | def setup | |
| 15 | end | |
| 16 | ||
| 17 | ||
| 18 | def test_psw | |
| 19 |     assert_equal( "{MD5}xq8jwrcfibi0sZdZYNkSng==", Net::LDAP::Password.generate( :md5, "cashflow" )) | |
| 20 |     assert_equal( "{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", Net::LDAP::Password.generate( :sha, "cashflow" )) | |
| 21 | end | |
| 22 | ||
| 23 | ||
| 24 | ||
| 25 | ||
| 26 | end | |
| 27 | ||
| 28 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/LICENCE (working copy) | ||
|---|---|---|
| 1 | Net::LDAP is copyrighted free software by Francis Cianfrocca | |
| 2 | <garbagecat10@gmail.com>. You can redistribute it and/or modify it under either | |
| 3 | the terms of the GPL (see the file COPYING), or the conditions below: | |
| 4 | ||
| 5 | 1. You may make and give away verbatim copies of the source form of the | |
| 6 | software without restriction, provided that you duplicate all of the | |
| 7 | original copyright notices and associated disclaimers. | |
| 8 | ||
| 9 | 2. You may modify your copy of the software in any way, provided that you do | |
| 10 | at least ONE of the following: | |
| 11 | ||
| 12 | a) place your modifications in the Public Domain or otherwise make them | |
| 13 | Freely Available, such as by posting said modifications to Usenet or | |
| 14 | an equivalent medium, or by allowing the author to include your | |
| 15 | modifications in the software. | |
| 16 | ||
| 17 | b) use the modified software only within your corporation or | |
| 18 | organization. | |
| 19 | ||
| 20 | c) rename any non-standard executables so the names do not conflict with | |
| 21 | standard executables, which must also be provided. | |
| 22 | ||
| 23 | d) make other distribution arrangements with the author. | |
| 24 | ||
| 25 | 3. You may distribute the software in object code or executable form, | |
| 26 | provided that you do at least ONE of the following: | |
| 27 | ||
| 28 | a) distribute the executables and library files of the software, together | |
| 29 | with instructions (in the manual page or equivalent) on where to get | |
| 30 | the original distribution. | |
| 31 | ||
| 32 | b) accompany the distribution with the machine-readable source of the | |
| 33 | software. | |
| 34 | ||
| 35 | c) give non-standard executables non-standard names, with instructions on | |
| 36 | where to get the original software distribution. | |
| 37 | ||
| 38 | d) make other distribution arrangements with the author. | |
| 39 | ||
| 40 | 4. You may modify and include the part of the software into any other | |
| 41 | software (possibly commercial). But some files in the distribution are | |
| 42 | not written by the author, so that they are not under this terms. | |
| 43 | ||
| 44 | They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some | |
| 45 | files under the ./missing directory. See each file for the copying | |
| 46 | condition. | |
| 47 | ||
| 48 | 5. The scripts and library files supplied as input to or produced as output | |
| 49 | from the software do not automatically fall under the copyright of the | |
| 50 | software, but belong to whomever generated them, and may be sold | |
| 51 | commercially, and may be aggregated with this software. | |
| 52 | ||
| 53 | 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED | |
| 54 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | |
| 55 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
| vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/entry.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: entry.rb 123 2006-05-18 03:52:38Z blackhedd $ | |
| 2 | # | |
| 3 | # LDAP Entry (search-result) support classes | |
| 4 | # | |
| 5 | # | |
| 6 | #---------------------------------------------------------------------------- | |
| 7 | # | |
| 8 | # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. | |
| 9 | # | |
| 10 | # Gmail: garbagecat10 | |
| 11 | # | |
| 12 | # This program is free software; you can redistribute it and/or modify | |
| 13 | # it under the terms of the GNU General Public License as published by | |
| 14 | # the Free Software Foundation; either version 2 of the License, or | |
| 15 | # (at your option) any later version. | |
| 16 | # | |
| 17 | # This program is distributed in the hope that it will be useful, | |
| 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | # GNU General Public License for more details. | |
| 21 | # | |
| 22 | # You should have received a copy of the GNU General Public License | |
| 23 | # along with this program; if not, write to the Free Software | |
| 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 25 | # | |
| 26 | #--------------------------------------------------------------------------- | |
| 27 | # | |
| 28 | ||
| 29 | ||
| 30 | ||
| 31 | ||
| 32 | module Net | |
| 33 | class LDAP | |
| 34 | ||
| 35 | ||
| 36 | # Objects of this class represent individual entries in an LDAP | |
| 37 | # directory. User code generally does not instantiate this class. | |
| 38 | # Net::LDAP#search provides objects of this class to user code, | |
| 39 | # either as block parameters or as return values. | |
| 40 | # | |
| 41 | # In LDAP-land, an "entry" is a collection of attributes that are | |
| 42 |   # uniquely and globally identified by a DN ("Distinguished Name"). | |
| 43 | # Attributes are identified by short, descriptive words or phrases. | |
| 44 | # Although a directory is | |
| 45 | # free to implement any attribute name, most of them follow rigorous | |
| 46 | # standards so that the range of commonly-encountered attribute | |
| 47 | # names is not large. | |
| 48 | # | |
| 49 | # An attribute name is case-insensitive. Most directories also | |
| 50 | # restrict the range of characters allowed in attribute names. | |
| 51 | # To simplify handling attribute names, Net::LDAP::Entry | |
| 52 | # internally converts them to a standard format. Therefore, the | |
| 53 | # methods which take attribute names can take Strings or Symbols, | |
| 54 | # and work correctly regardless of case or capitalization. | |
| 55 | # | |
| 56 | # An attribute consists of zero or more data items called | |
| 57 | # <i>values.</i> An entry is the combination of a unique DN, a set of attribute | |
| 58 | # names, and a (possibly-empty) array of values for each attribute. | |
| 59 | # | |
| 60 | # Class Net::LDAP::Entry provides convenience methods for dealing | |
| 61 | # with LDAP entries. | |
| 62 | # In addition to the methods documented below, you may access individual | |
| 63 | # attributes of an entry simply by giving the attribute name as | |
| 64 | # the name of a method call. For example: | |
| 65 | # ldap.search( ... ) do |entry| | |
| 66 |   #    puts "Common name: #{entry.cn}" | |
| 67 | # puts "Email addresses:" | |
| 68 |   #      entry.mail.each {|ma| puts ma} | |
| 69 | # end | |
| 70 | # If you use this technique to access an attribute that is not present | |
| 71 | # in a particular Entry object, a NoMethodError exception will be raised. | |
| 72 | # | |
| 73 | #-- | |
| 74 | # Ugly problem to fix someday: We key off the internal hash with | |
| 75 | # a canonical form of the attribute name: convert to a string, | |
| 76 | # downcase, then take the symbol. Unfortunately we do this in | |
| 77 | # at least three places. Should do it in ONE place. | |
| 78 | class Entry | |
| 79 | ||
| 80 | # This constructor is not generally called by user code. | |
| 81 | def initialize dn = nil # :nodoc: | |
| 82 |       @myhash = Hash.new {|k,v| k[v] = [] } | |
| 83 | @myhash[:dn] = [dn] | |
| 84 | end | |
| 85 | ||
| 86 | ||
| 87 | def []= name, value # :nodoc: | |
| 88 | sym = name.to_s.downcase.intern | |
| 89 | @myhash[sym] = value | |
| 90 | end | |
| 91 | ||
| 92 | ||
| 93 | #-- | |
| 94 | # We have to deal with this one as we do with []= | |
| 95 | # because this one and not the other one gets called | |
| 96 | # in formulations like entry["CN"] << cn. | |
| 97 | # | |
| 98 | def [] name # :nodoc: | |
| 99 | name = name.to_s.downcase.intern unless name.is_a?(Symbol) | |
| 100 | @myhash[name] | |
| 101 | end | |
| 102 | ||
| 103 | # Returns the dn of the Entry as a String. | |
| 104 | def dn | |
| 105 | self[:dn][0] | |
| 106 | end | |
| 107 | ||
| 108 | # Returns an array of the attribute names present in the Entry. | |
| 109 | def attribute_names | |
| 110 | @myhash.keys | |
| 111 | end | |
| 112 | ||
| 113 | # Accesses each of the attributes present in the Entry. | |
| 114 | # Calls a user-supplied block with each attribute in turn, | |
| 115 | # passing two arguments to the block: a Symbol giving | |
| 116 | # the name of the attribute, and a (possibly empty) | |
| 117 | # Array of data values. | |
| 118 | # | |
| 119 | def each | |
| 120 | if block_given? | |
| 121 |         attribute_names.each {|a| | |
| 122 | attr_name,values = a,self[a] | |
| 123 | yield attr_name, values | |
| 124 | } | |
| 125 | end | |
| 126 | end | |
| 127 | ||
| 128 | alias_method :each_attribute, :each | |
| 129 | ||
| 130 | ||
| 131 | #-- | |
| 132 | # Convenience method to convert unknown method names | |
| 133 | # to attribute references. Of course the method name | |
| 134 | # comes to us as a symbol, so let's save a little time | |
| 135 | # and not bother with the to_s.downcase two-step. | |
| 136 | # Of course that means that a method name like mAIL | |
| 137 | # won't work, but we shouldn't be encouraging that | |
| 138 | # kind of bad behavior in the first place. | |
| 139 | # Maybe we should thow something if the caller sends | |
| 140 | # arguments or a block... | |
| 141 | # | |
| 142 | def method_missing *args, &block # :nodoc: | |
| 143 | s = args[0].to_s.downcase.intern | |
| 144 | if attribute_names.include?(s) | |
| 145 | self[s] | |
| 146 | elsif s.to_s[-1] == 61 and s.to_s.length > 1 | |
| 147 | value = args[1] or raise RuntimeError.new( "unable to set value" ) | |
| 148 | value = [value] unless value.is_a?(Array) | |
| 149 | name = s.to_s[0..-2].intern | |
| 150 | self[name] = value | |
| 151 | else | |
| 152 |         raise NoMethodError.new( "undefined method '#{s}'" ) | |
| 153 | end | |
| 154 | end | |
| 155 | ||
| 156 | def write | |
| 157 | end | |
| 158 | ||
| 159 | end # class Entry | |
| 160 | ||
| 161 | ||
| 162 | end # class LDAP | |
| 163 | end # module Net | |
| 164 | ||
| 165 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/dataset.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: dataset.rb 78 2006-04-26 02:57:34Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | #---------------------------------------------------------------------------- | |
| 5 | # | |
| 6 | # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. | |
| 7 | # | |
| 8 | # Gmail: garbagecat10 | |
| 9 | # | |
| 10 | # This program is free software; you can redistribute it and/or modify | |
| 11 | # it under the terms of the GNU General Public License as published by | |
| 12 | # the Free Software Foundation; either version 2 of the License, or | |
| 13 | # (at your option) any later version. | |
| 14 | # | |
| 15 | # This program is distributed in the hope that it will be useful, | |
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | # GNU General Public License for more details. | |
| 19 | # | |
| 20 | # You should have received a copy of the GNU General Public License | |
| 21 | # along with this program; if not, write to the Free Software | |
| 22 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 23 | # | |
| 24 | #--------------------------------------------------------------------------- | |
| 25 | # | |
| 26 | # | |
| 27 | ||
| 28 | ||
| 29 | ||
| 30 | ||
| 31 | module Net | |
| 32 | class LDAP | |
| 33 | ||
| 34 | class Dataset < Hash | |
| 35 | ||
| 36 | attr_reader :comments | |
| 37 | ||
| 38 | ||
| 39 | def Dataset::read_ldif io | |
| 40 | ds = Dataset.new | |
| 41 | ||
| 42 | line = io.gets && chomp | |
| 43 | dn = nil | |
| 44 | ||
| 45 | while line | |
| 46 | io.gets and chomp | |
| 47 | if $_ =~ /^[\s]+/ | |
| 48 | line << " " << $' | |
| 49 | else | |
| 50 | nextline = $_ | |
| 51 | ||
| 52 | if line =~ /^\#/ | |
| 53 | ds.comments << line | |
| 54 | elsif line =~ /^dn:[\s]*/i | |
| 55 | dn = $' | |
| 56 |           ds[dn] = Hash.new {|k,v| k[v] = []} | |
| 57 | elsif line.length == 0 | |
| 58 | dn = nil | |
| 59 | elsif line =~ /^([^:]+):([\:]?)[\s]*/ | |
| 60 | # $1 is the attribute name | |
| 61 | # $2 is a colon iff the attr-value is base-64 encoded | |
| 62 | # $' is the attr-value | |
| 63 | # Avoid the Base64 class because not all Ruby versions have it. | |
| 64 |           attrvalue = ($2 == ":") ? $'.unpack('m').shift : $' | |
| 65 | ds[dn][$1.downcase.intern] << attrvalue | |
| 66 | end | |
| 67 | ||
| 68 | line = nextline | |
| 69 | end | |
| 70 | end | |
| 71 |  | |
| 72 | ds | |
| 73 | end | |
| 74 | ||
| 75 | ||
| 76 | def initialize | |
| 77 | @comments = [] | |
| 78 | end | |
| 79 | ||
| 80 | ||
| 81 | def to_ldif | |
| 82 | ary = [] | |
| 83 | ary += (@comments || []) | |
| 84 | ||
| 85 |     keys.sort.each {|dn| | |
| 86 |       ary << "dn: #{dn}" | |
| 87 | ||
| 88 |       self[dn].keys.map {|sym| sym.to_s}.sort.each {|attr| | |
| 89 |         self[dn][attr.intern].each {|val| | |
| 90 |           ary << "#{attr}: #{val}" | |
| 91 | } | |
| 92 | } | |
| 93 | ||
| 94 | ary << "" | |
| 95 | } | |
| 96 | ||
| 97 |     block_given? and ary.each {|line| yield line} | |
| 98 | ||
| 99 | ary | |
| 100 | end | |
| 101 | ||
| 102 | ||
| 103 | end # Dataset | |
| 104 | ||
| 105 | end # LDAP | |
| 106 | end # Net | |
| 107 | ||
| 108 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/filter.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: filter.rb 151 2006-08-15 08:34:53Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | #---------------------------------------------------------------------------- | |
| 5 | # | |
| 6 | # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. | |
| 7 | # | |
| 8 | # Gmail: garbagecat10 | |
| 9 | # | |
| 10 | # This program is free software; you can redistribute it and/or modify | |
| 11 | # it under the terms of the GNU General Public License as published by | |
| 12 | # the Free Software Foundation; either version 2 of the License, or | |
| 13 | # (at your option) any later version. | |
| 14 | # | |
| 15 | # This program is distributed in the hope that it will be useful, | |
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | # GNU General Public License for more details. | |
| 19 | # | |
| 20 | # You should have received a copy of the GNU General Public License | |
| 21 | # along with this program; if not, write to the Free Software | |
| 22 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 23 | # | |
| 24 | #--------------------------------------------------------------------------- | |
| 25 | # | |
| 26 | # | |
| 27 | ||
| 28 | ||
| 29 | module Net | |
| 30 | class LDAP | |
| 31 | ||
| 32 | ||
| 33 | # Class Net::LDAP::Filter is used to constrain | |
| 34 | # LDAP searches. An object of this class is | |
| 35 | # passed to Net::LDAP#search in the parameter :filter. | |
| 36 | # | |
| 37 | # Net::LDAP::Filter supports the complete set of search filters | |
| 38 | # available in LDAP, including conjunction, disjunction and negation | |
| 39 | # (AND, OR, and NOT). This class supplants the (infamous) RFC-2254 | |
| 40 | # standard notation for specifying LDAP search filters. | |
| 41 | # | |
| 42 | # Here's how to code the familiar "objectclass is present" filter: | |
| 43 | # f = Net::LDAP::Filter.pres( "objectclass" ) | |
| 44 | # The object returned by this code can be passed directly to | |
| 45 | # the <tt>:filter</tt> parameter of Net::LDAP#search. | |
| 46 | # | |
| 47 | # See the individual class and instance methods below for more examples. | |
| 48 | # | |
| 49 | class Filter | |
| 50 | ||
| 51 | def initialize op, a, b | |
| 52 | @op = op | |
| 53 | @left = a | |
| 54 | @right = b | |
| 55 | end | |
| 56 | ||
| 57 | # #eq creates a filter object indicating that the value of | |
| 58 | # a paticular attribute must be either <i>present</i> or must | |
| 59 | # match a particular string. | |
| 60 | # | |
| 61 | # To specify that an attribute is "present" means that only | |
| 62 | # directory entries which contain a value for the particular | |
| 63 | # attribute will be selected by the filter. This is useful | |
| 64 | # in case of optional attributes such as <tt>mail.</tt> | |
| 65 | # Presence is indicated by giving the value "*" in the second | |
| 66 | # parameter to #eq. This example selects only entries that have | |
| 67 | # one or more values for <tt>sAMAccountName:</tt> | |
| 68 | # f = Net::LDAP::Filter.eq( "sAMAccountName", "*" ) | |
| 69 | # | |
| 70 | # To match a particular range of values, pass a string as the | |
| 71 | # second parameter to #eq. The string may contain one or more | |
| 72 | # "*" characters as wildcards: these match zero or more occurrences | |
| 73 | # of any character. Full regular-expressions are <i>not</i> supported | |
| 74 | # due to limitations in the underlying LDAP protocol. | |
| 75 | # This example selects any entry with a <tt>mail</tt> value containing | |
| 76 | # the substring "anderson": | |
| 77 | # f = Net::LDAP::Filter.eq( "mail", "*anderson*" ) | |
| 78 | #-- | |
| 79 | # Removed gt and lt. They ain't in the standard! | |
| 80 | # | |
| 81 | def Filter::eq attribute, value; Filter.new :eq, attribute, value; end | |
| 82 | def Filter::ne attribute, value; Filter.new :ne, attribute, value; end | |
| 83 | #def Filter::gt attribute, value; Filter.new :gt, attribute, value; end | |
| 84 | #def Filter::lt attribute, value; Filter.new :lt, attribute, value; end | |
| 85 | def Filter::ge attribute, value; Filter.new :ge, attribute, value; end | |
| 86 | def Filter::le attribute, value; Filter.new :le, attribute, value; end | |
| 87 | ||
| 88 | # #pres( attribute ) is a synonym for #eq( attribute, "*" ) | |
| 89 | # | |
| 90 | def Filter::pres attribute; Filter.eq attribute, "*"; end | |
| 91 | ||
| 92 |   # operator & ("AND") is used to conjoin two or more filters. | |
| 93 | # This expression will select only entries that have an <tt>objectclass</tt> | |
| 94 | # attribute AND have a <tt>mail</tt> attribute that begins with "George": | |
| 95 | # f = Net::LDAP::Filter.pres( "objectclass" ) & Net::LDAP::Filter.eq( "mail", "George*" ) | |
| 96 | # | |
| 97 | def & filter; Filter.new :and, self, filter; end | |
| 98 | ||
| 99 |   # operator | ("OR") is used to disjoin two or more filters. | |
| 100 | # This expression will select entries that have either an <tt>objectclass</tt> | |
| 101 | # attribute OR a <tt>mail</tt> attribute that begins with "George": | |
| 102 | # f = Net::LDAP::Filter.pres( "objectclass" ) | Net::LDAP::Filter.eq( "mail", "George*" ) | |
| 103 | # | |
| 104 | def | filter; Filter.new :or, self, filter; end | |
| 105 | ||
| 106 | ||
| 107 | # | |
| 108 |   # operator ~ ("NOT") is used to negate a filter. | |
| 109 | # This expression will select only entries that <i>do not</i> have an <tt>objectclass</tt> | |
| 110 | # attribute: | |
| 111 | # f = ~ Net::LDAP::Filter.pres( "objectclass" ) | |
| 112 | # | |
| 113 | #-- | |
| 114 | # This operator can't be !, evidently. Try it. | |
| 115 | # Removed GT and LT. They're not in the RFC. | |
| 116 | def ~@; Filter.new :not, self, nil; end | |
| 117 | ||
| 118 | ||
| 119 | def to_s | |
| 120 | case @op | |
| 121 | when :ne | |
| 122 |       "(!(#{@left}=#{@right}))" | |
| 123 | when :eq | |
| 124 |       "(#{@left}=#{@right})" | |
| 125 | #when :gt | |
| 126 |      # "#{@left}>#{@right}" | |
| 127 | #when :lt | |
| 128 |      # "#{@left}<#{@right}" | |
| 129 | when :ge | |
| 130 |       "#{@left}>=#{@right}" | |
| 131 | when :le | |
| 132 |       "#{@left}<=#{@right}" | |
| 133 | when :and | |
| 134 |       "(&(#{@left})(#{@right}))" | |
| 135 | when :or | |
| 136 |       "(|(#{@left})(#{@right}))" | |
| 137 | when :not | |
| 138 |       "(!(#{@left}))" | |
| 139 | else | |
| 140 | raise "invalid or unsupported operator in LDAP Filter" | |
| 141 | end | |
| 142 | end | |
| 143 | ||
| 144 | ||
| 145 | #-- | |
| 146 | # to_ber | |
| 147 | # Filter ::= | |
| 148 |   #     CHOICE { | |
| 149 | # and [0] SET OF Filter, | |
| 150 | # or [1] SET OF Filter, | |
| 151 | # not [2] Filter, | |
| 152 | # equalityMatch [3] AttributeValueAssertion, | |
| 153 | # substrings [4] SubstringFilter, | |
| 154 | # greaterOrEqual [5] AttributeValueAssertion, | |
| 155 | # lessOrEqual [6] AttributeValueAssertion, | |
| 156 | # present [7] AttributeType, | |
| 157 | # approxMatch [8] AttributeValueAssertion | |
| 158 | # } | |
| 159 | # | |
| 160 | # SubstringFilter | |
| 161 |   #     SEQUENCE { | |
| 162 | # type AttributeType, | |
| 163 |   #         SEQUENCE OF CHOICE { | |
| 164 | # initial [0] LDAPString, | |
| 165 | # any [1] LDAPString, | |
| 166 | # final [2] LDAPString | |
| 167 | # } | |
| 168 | # } | |
| 169 | # | |
| 170 | # Parsing substrings is a little tricky. | |
| 171 | # We use the split method to break a string into substrings | |
| 172 | # delimited by the * (star) character. But we also need | |
| 173 | # to know whether there is a star at the head and tail | |
| 174 | # of the string. A Ruby particularity comes into play here: | |
| 175 | # if you split on * and the first character of the string is | |
| 176 | # a star, then split will return an array whose first element | |
| 177 | # is an _empty_ string. But if the _last_ character of the | |
| 178 | # string is star, then split will return an array that does | |
| 179 | # _not_ add an empty string at the end. So we have to deal | |
| 180 | # with all that specifically. | |
| 181 | # | |
| 182 | def to_ber | |
| 183 | case @op | |
| 184 | when :eq | |
| 185 | if @right == "*" # present | |
| 186 | @left.to_s.to_ber_contextspecific 7 | |
| 187 | elsif @right =~ /[\*]/ #substring | |
| 188 | ary = @right.split( /[\*]+/ ) | |
| 189 | final_star = @right =~ /[\*]$/ | |
| 190 | initial_star = ary.first == "" and ary.shift | |
| 191 | ||
| 192 | seq = [] | |
| 193 | unless initial_star | |
| 194 | seq << ary.shift.to_ber_contextspecific(0) | |
| 195 | end | |
| 196 | n_any_strings = ary.length - (final_star ? 0 : 1) | |
| 197 | #p n_any_strings | |
| 198 |         n_any_strings.times { | |
| 199 | seq << ary.shift.to_ber_contextspecific(1) | |
| 200 | } | |
| 201 | unless final_star | |
| 202 | seq << ary.shift.to_ber_contextspecific(2) | |
| 203 | end | |
| 204 | [@left.to_s.to_ber, seq.to_ber].to_ber_contextspecific 4 | |
| 205 | else #equality | |
| 206 | [@left.to_s.to_ber, @right.to_ber].to_ber_contextspecific 3 | |
| 207 | end | |
| 208 | when :ge | |
| 209 | [@left.to_s.to_ber, @right.to_ber].to_ber_contextspecific 5 | |
| 210 | when :le | |
| 211 | [@left.to_s.to_ber, @right.to_ber].to_ber_contextspecific 6 | |
| 212 | when :and | |
| 213 | ary = [@left.coalesce(:and), @right.coalesce(:and)].flatten | |
| 214 |       ary.map {|a| a.to_ber}.to_ber_contextspecific( 0 ) | |
| 215 | when :or | |
| 216 | ary = [@left.coalesce(:or), @right.coalesce(:or)].flatten | |
| 217 |       ary.map {|a| a.to_ber}.to_ber_contextspecific( 1 ) | |
| 218 | when :not | |
| 219 | [@left.to_ber].to_ber_contextspecific 2 | |
| 220 | else | |
| 221 | # ERROR, we'll return objectclass=* to keep things from blowing up, | |
| 222 | # but that ain't a good answer and we need to kick out an error of some kind. | |
| 223 | raise "unimplemented search filter" | |
| 224 | end | |
| 225 | end | |
| 226 | ||
| 227 | #-- | |
| 228 | # coalesce | |
| 229 | # This is a private helper method for dealing with chains of ANDs and ORs | |
| 230 | # that are longer than two. If BOTH of our branches are of the specified | |
| 231 | # type of joining operator, then return both of them as an array (calling | |
| 232 | # coalesce recursively). If they're not, then return an array consisting | |
| 233 | # only of self. | |
| 234 | # | |
| 235 | def coalesce operator | |
| 236 | if @op == operator | |
| 237 | [@left.coalesce( operator ), @right.coalesce( operator )] | |
| 238 | else | |
| 239 | [self] | |
| 240 | end | |
| 241 | end | |
| 242 | ||
| 243 | ||
| 244 | ||
| 245 | #-- | |
| 246 | # We get a Ruby object which comes from parsing an RFC-1777 "Filter" | |
| 247 | # object. Convert it to a Net::LDAP::Filter. | |
| 248 | # TODO, we're hardcoding the RFC-1777 BER-encodings of the various | |
| 249 | # filter types. Could pull them out into a constant. | |
| 250 | # | |
| 251 | def Filter::parse_ldap_filter obj | |
| 252 | case obj.ber_identifier | |
| 253 | when 0x87 # present. context-specific primitive 7. | |
| 254 | Filter.eq( obj.to_s, "*" ) | |
| 255 | when 0xa3 # equalityMatch. context-specific constructed 3. | |
| 256 | Filter.eq( obj[0], obj[1] ) | |
| 257 | else | |
| 258 |       raise LdapError.new( "unknown ldap search-filter type: #{obj.ber_identifier}" ) | |
| 259 | end | |
| 260 | end | |
| 261 | ||
| 262 | ||
| 263 | #-- | |
| 264 | # We got a hash of attribute values. | |
| 265 | # Do we match the attributes? | |
| 266 | # Return T/F, and call match recursively as necessary. | |
| 267 | def match entry | |
| 268 | case @op | |
| 269 | when :eq | |
| 270 | if @right == "*" | |
| 271 | l = entry[@left] and l.length > 0 | |
| 272 | else | |
| 273 | l = entry[@left] and l = l.to_a and l.index(@right) | |
| 274 | end | |
| 275 | else | |
| 276 |       raise LdapError.new( "unknown filter type in match: #{@op}" ) | |
| 277 | end | |
| 278 | end | |
| 279 | ||
| 280 | # Converts an LDAP filter-string (in the prefix syntax specified in RFC-2254) | |
| 281 | # to a Net::LDAP::Filter. | |
| 282 | def self.construct ldap_filter_string | |
| 283 | FilterParser.new(ldap_filter_string).filter | |
| 284 | end | |
| 285 | ||
| 286 | # Synonym for #construct. | |
| 287 | # to a Net::LDAP::Filter. | |
| 288 | def self.from_rfc2254 ldap_filter_string | |
| 289 | construct ldap_filter_string | |
| 290 | end | |
| 291 | ||
| 292 | end # class Net::LDAP::Filter | |
| 293 | ||
| 294 | ||
| 295 | ||
| 296 | class FilterParser #:nodoc: | |
| 297 | ||
| 298 | attr_reader :filter | |
| 299 | ||
| 300 | def initialize str | |
| 301 | require 'strscan' | |
| 302 | @filter = parse( StringScanner.new( str )) or raise Net::LDAP::LdapError.new( "invalid filter syntax" ) | |
| 303 | end | |
| 304 | ||
| 305 | def parse scanner | |
| 306 | parse_filter_branch(scanner) or parse_paren_expression(scanner) | |
| 307 | end | |
| 308 | ||
| 309 | def parse_paren_expression scanner | |
| 310 | if scanner.scan(/\s*\(\s*/) | |
| 311 | b = if scanner.scan(/\s*\&\s*/) | |
| 312 | a = nil | |
| 313 | branches = [] | |
| 314 | while br = parse_paren_expression(scanner) | |
| 315 | branches << br | |
| 316 | end | |
| 317 | if branches.length >= 2 | |
| 318 | a = branches.shift | |
| 319 | while branches.length > 0 | |
| 320 | a = a & branches.shift | |
| 321 | end | |
| 322 | a | |
| 323 | end | |
| 324 | elsif scanner.scan(/\s*\|\s*/) | |
| 325 | # TODO: DRY! | |
| 326 | a = nil | |
| 327 | branches = [] | |
| 328 | while br = parse_paren_expression(scanner) | |
| 329 | branches << br | |
| 330 | end | |
| 331 | if branches.length >= 2 | |
| 332 | a = branches.shift | |
| 333 | while branches.length > 0 | |
| 334 | a = a | branches.shift | |
| 335 | end | |
| 336 | a | |
| 337 | end | |
| 338 | elsif scanner.scan(/\s*\!\s*/) | |
| 339 | br = parse_paren_expression(scanner) | |
| 340 | if br | |
| 341 | ~ br | |
| 342 | end | |
| 343 | else | |
| 344 | parse_filter_branch( scanner ) | |
| 345 | end | |
| 346 | ||
| 347 | if b and scanner.scan( /\s*\)\s*/ ) | |
| 348 | b | |
| 349 | end | |
| 350 | end | |
| 351 | end | |
| 352 | ||
| 353 | # Added a greatly-augmented filter contributed by Andre Nathan | |
| 354 | # for detecting special characters in values. (15Aug06) | |
| 355 | def parse_filter_branch scanner | |
| 356 | scanner.scan(/\s*/) | |
| 357 | if token = scanner.scan( /[\w\-_]+/ ) | |
| 358 | scanner.scan(/\s*/) | |
| 359 | if op = scanner.scan( /\=|\<\=|\<|\>\=|\>|\!\=/ ) | |
| 360 | scanner.scan(/\s*/) | |
| 361 | #if value = scanner.scan( /[\w\*\.]+/ ) (ORG) | |
| 362 | if value = scanner.scan( /[\w\*\.\+\-@=#\$%&!]+/ ) | |
| 363 | case op | |
| 364 | when "=" | |
| 365 | Filter.eq( token, value ) | |
| 366 | when "!=" | |
| 367 | Filter.ne( token, value ) | |
| 368 | when "<" | |
| 369 | Filter.lt( token, value ) | |
| 370 | when "<=" | |
| 371 | Filter.le( token, value ) | |
| 372 | when ">" | |
| 373 | Filter.gt( token, value ) | |
| 374 | when ">=" | |
| 375 | Filter.ge( token, value ) | |
| 376 | end | |
| 377 | end | |
| 378 | end | |
| 379 | end | |
| 380 | end | |
| 381 | ||
| 382 | end # class Net::LDAP::FilterParser | |
| 383 | ||
| 384 | end # class Net::LDAP | |
| 385 | end # module Net | |
| 386 | ||
| 387 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/pdu.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: pdu.rb 126 2006-05-31 15:55:16Z blackhedd $ | |
| 2 | # | |
| 3 | # LDAP PDU support classes | |
| 4 | # | |
| 5 | # | |
| 6 | #---------------------------------------------------------------------------- | |
| 7 | # | |
| 8 | # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. | |
| 9 | # | |
| 10 | # Gmail: garbagecat10 | |
| 11 | # | |
| 12 | # This program is free software; you can redistribute it and/or modify | |
| 13 | # it under the terms of the GNU General Public License as published by | |
| 14 | # the Free Software Foundation; either version 2 of the License, or | |
| 15 | # (at your option) any later version. | |
| 16 | # | |
| 17 | # This program is distributed in the hope that it will be useful, | |
| 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | # GNU General Public License for more details. | |
| 21 | # | |
| 22 | # You should have received a copy of the GNU General Public License | |
| 23 | # along with this program; if not, write to the Free Software | |
| 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 25 | # | |
| 26 | #--------------------------------------------------------------------------- | |
| 27 | # | |
| 28 | ||
| 29 | ||
| 30 | ||
| 31 | module Net | |
| 32 | ||
| 33 | ||
| 34 | class LdapPduError < Exception; end | |
| 35 | ||
| 36 | ||
| 37 | class LdapPdu | |
| 38 | ||
| 39 | BindResult = 1 | |
| 40 | SearchReturnedData = 4 | |
| 41 | SearchResult = 5 | |
| 42 | ModifyResponse = 7 | |
| 43 | AddResponse = 9 | |
| 44 | DeleteResponse = 11 | |
| 45 | ModifyRDNResponse = 13 | |
| 46 | SearchResultReferral = 19 | |
| 47 | ||
| 48 | attr_reader :msg_id, :app_tag | |
| 49 | attr_reader :search_dn, :search_attributes, :search_entry | |
| 50 | attr_reader :search_referrals | |
| 51 | ||
| 52 | # | |
| 53 | # initialize | |
| 54 | # An LDAP PDU always looks like a BerSequence with | |
| 55 | # at least two elements: an integer (message-id number), and | |
| 56 | # an application-specific sequence. | |
| 57 | # Some LDAPv3 packets also include an optional | |
| 58 | # third element, which is a sequence of "controls" | |
| 59 | # (See RFC 2251, section 4.1.12). | |
| 60 | # The application-specific tag in the sequence tells | |
| 61 | # us what kind of packet it is, and each kind has its | |
| 62 | # own format, defined in RFC-1777. | |
| 63 | # Observe that many clients (such as ldapsearch) | |
| 64 | # do not necessarily enforce the expected application | |
| 65 | # tags on received protocol packets. This implementation | |
| 66 | # does interpret the RFC strictly in this regard, and | |
| 67 | # it remains to be seen whether there are servers out | |
| 68 | # there that will not work well with our approach. | |
| 69 | # | |
| 70 | # Added a controls-processor to SearchResult. | |
| 71 | # Didn't add it everywhere because it just _feels_ | |
| 72 | # like it will need to be refactored. | |
| 73 | # | |
| 74 | def initialize ber_object | |
| 75 | begin | |
| 76 | @msg_id = ber_object[0].to_i | |
| 77 | @app_tag = ber_object[1].ber_identifier - 0x60 | |
| 78 | rescue | |
| 79 | # any error becomes a data-format error | |
| 80 | raise LdapPduError.new( "ldap-pdu format error" ) | |
| 81 | end | |
| 82 | ||
| 83 | case @app_tag | |
| 84 | when BindResult | |
| 85 | parse_ldap_result ber_object[1] | |
| 86 | when SearchReturnedData | |
| 87 | parse_search_return ber_object[1] | |
| 88 | when SearchResultReferral | |
| 89 | parse_search_referral ber_object[1] | |
| 90 | when SearchResult | |
| 91 | parse_ldap_result ber_object[1] | |
| 92 | parse_controls(ber_object[2]) if ber_object[2] | |
| 93 | when ModifyResponse | |
| 94 | parse_ldap_result ber_object[1] | |
| 95 | when AddResponse | |
| 96 | parse_ldap_result ber_object[1] | |
| 97 | when DeleteResponse | |
| 98 | parse_ldap_result ber_object[1] | |
| 99 | when ModifyRDNResponse | |
| 100 | parse_ldap_result ber_object[1] | |
| 101 | else | |
| 102 |       raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" ) | |
| 103 | end | |
| 104 | end | |
| 105 | ||
| 106 | # | |
| 107 | # result_code | |
| 108 | # This returns an LDAP result code taken from the PDU, | |
| 109 | # but it will be nil if there wasn't a result code. | |
| 110 | # That can easily happen depending on the type of packet. | |
| 111 | # | |
| 112 | def result_code code = :resultCode | |
| 113 | @ldap_result and @ldap_result[code] | |
| 114 | end | |
| 115 | ||
| 116 | # Return RFC-2251 Controls if any. | |
| 117 | # Messy. Does this functionality belong somewhere else? | |
| 118 | def result_controls | |
| 119 | @ldap_controls || [] | |
| 120 | end | |
| 121 | ||
| 122 | ||
| 123 | # | |
| 124 | # parse_ldap_result | |
| 125 | # | |
| 126 | def parse_ldap_result sequence | |
| 127 | sequence.length >= 3 or raise LdapPduError | |
| 128 |     @ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]} | |
| 129 | end | |
| 130 | private :parse_ldap_result | |
| 131 | ||
| 132 | # | |
| 133 | # parse_search_return | |
| 134 | # Definition from RFC 1777 (we're handling application-4 here) | |
| 135 | # | |
| 136 | # Search Response ::= | |
| 137 |   #    CHOICE { | |
| 138 |   #         entry          [APPLICATION 4] SEQUENCE { | |
| 139 | # objectName LDAPDN, | |
| 140 |   #                             attributes     SEQUENCE OF SEQUENCE { | |
| 141 | # AttributeType, | |
| 142 | # SET OF AttributeValue | |
| 143 | # } | |
| 144 | # }, | |
| 145 | # resultCode [APPLICATION 5] LDAPResult | |
| 146 | # } | |
| 147 | # | |
| 148 | # We concoct a search response that is a hash of the returned attribute values. | |
| 149 | # NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES. | |
| 150 | # This is to make them more predictable for user programs, but it | |
| 151 | # may not be a good idea. Maybe this should be configurable. | |
| 152 | # ALTERNATE IMPLEMENTATION: In addition to @search_dn and @search_attributes, | |
| 153 | # we also return @search_entry, which is an LDAP::Entry object. | |
| 154 | # If that works out well, then we'll remove the first two. | |
| 155 | # | |
| 156 | # Provisionally removed obsolete search_attributes and search_dn, 04May06. | |
| 157 | # | |
| 158 | def parse_search_return sequence | |
| 159 | sequence.length >= 2 or raise LdapPduError | |
| 160 | @search_entry = LDAP::Entry.new( sequence[0] ) | |
| 161 | #@search_dn = sequence[0] | |
| 162 |     #@search_attributes = {} | |
| 163 |     sequence[1].each {|seq| | |
| 164 | @search_entry[seq[0]] = seq[1] | |
| 165 | #@search_attributes[seq[0].downcase.intern] = seq[1] | |
| 166 | } | |
| 167 | end | |
| 168 | ||
| 169 | # | |
| 170 | # A search referral is a sequence of one or more LDAP URIs. | |
| 171 | # Any number of search-referral replies can be returned by the server, interspersed | |
| 172 | # with normal replies in any order. | |
| 173 | # Until I can think of a better way to do this, we'll return the referrals as an array. | |
| 174 | # It'll be up to higher-level handlers to expose something reasonable to the client. | |
| 175 | def parse_search_referral uris | |
| 176 | @search_referrals = uris | |
| 177 | end | |
| 178 | ||
| 179 | ||
| 180 | # Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting | |
| 181 | # of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL | |
| 182 | # Octet String. If only two fields are given, the second one may be | |
| 183 | # either criticality or data, since criticality has a default value. | |
| 184 | # Someday we may want to come back here and add support for some of | |
| 185 | # more-widely used controls. RFC-2696 is a good example. | |
| 186 | # | |
| 187 | def parse_controls sequence | |
| 188 | @ldap_controls = sequence.map do |control| | |
| 189 | o = OpenStruct.new | |
| 190 | o.oid,o.criticality,o.value = control[0],control[1],control[2] | |
| 191 | if o.criticality and o.criticality.is_a?(String) | |
| 192 | o.value = o.criticality | |
| 193 | o.criticality = false | |
| 194 | end | |
| 195 | o | |
| 196 | end | |
| 197 | end | |
| 198 | private :parse_controls | |
| 199 | ||
| 200 | ||
| 201 | end | |
| 202 | ||
| 203 | ||
| 204 | end # module Net | |
| 205 | ||
| vendor/plugins/ruby-net-ldap-0.0.4/lib/net/ldap/psw.rb (working copy) | ||
|---|---|---|
| 1 | # $Id: psw.rb 73 2006-04-24 21:59:35Z blackhedd $ | |
| 2 | # | |
| 3 | # | |
| 4 | #---------------------------------------------------------------------------- | |
| 5 | # | |
| 6 | # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. | |
| 7 | # | |
| 8 | # Gmail: garbagecat10 | |
| 9 | # | |
| 10 | # This program is free software; you can redistribute it and/or modify | |
| 11 | # it under the terms of the GNU General Public License as published by | |
| 12 | # the Free Software Foundation; either version 2 of the License, or | |
| 13 | # (at your option) any later version. | |
| 14 | # | |
| 15 | # This program is distributed in the hope that it will be useful, | |
| 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | # GNU General Public License for more details. | |
| 19 | # | |
| 20 | # You should have received a copy of the GNU General Public License | |
| 21 | # along with this program; if not, write to the Free Software | |
| 22 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 23 | # | |
| 24 | #--------------------------------------------------------------------------- | |
| 25 | # | |
| 26 | # | |
| 27 | ||
| 28 | ||
| 29 | module Net | |
| 30 | class LDAP | |
| 31 | ||
| 32 | ||
| 33 | class Password | |
| 34 | class << self | |
| 35 | ||
| 36 | # Generate a password-hash suitable for inclusion in an LDAP attribute. | |
| 37 | # Pass a hash type (currently supported: :md5 and :sha) and a plaintext | |
- « Previous
- 1
- 2
- 3
- 4
- Next »