bsb_active_directory 8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,114 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ #
23
+ # The ActiveDirectory::Container class represents a more malleable way
24
+ # of dealing with LDAP Distinguished Names (dn), like
25
+ # "cn=UserName,ou=Users,dc=example,dc=org".
26
+ #
27
+ # The following two representations of the above dn are identical:
28
+ #
29
+ # dn = "cn=UserName,ou=Users,dc=example,dc=org"
30
+ # dn = ActiveDirectory::Container.dc('org').dc('example').ou('Users').cn('UserName').to_s
31
+ #
32
+ class Container
33
+ attr_reader :type
34
+ attr_reader :name
35
+ attr_reader :parent
36
+
37
+ def initialize(type, name, node = nil) #:nodoc:
38
+ @type = type
39
+ @name = name
40
+ @node = node
41
+ end
42
+
43
+ #
44
+ # Creates a starting OU (Organizational Unit) dn part.
45
+ #
46
+ # # ou_part = "ou=OrganizationalUnit"
47
+ # ou_part = ActiveDirectory::Container.ou('OrganizationalUnit').to_s
48
+ #
49
+ def self.ou(name)
50
+ new(:ou, name, nil)
51
+ end
52
+
53
+ #
54
+ # Creates a starting DC (Domain Component) dn part.
55
+ #
56
+ # # dc_part = "dc=net"
57
+ # dc_part = ActiveDirectory::Container.dc('net').to_s
58
+ #
59
+ def self.dc(name)
60
+ new(:dc, name, nil)
61
+ end
62
+
63
+ #
64
+ # Creates a starting CN (Canonical Name) dn part.
65
+ #
66
+ # # cn_part = "cn=CanonicalName"
67
+ # cn_part = ActiveDirectory::Container.cn('CanonicalName').to_s
68
+ #
69
+ def self.cn(name)
70
+ new(:cn, name, nil)
71
+ end
72
+
73
+ #
74
+ # Appends an OU (Organizational Unit) dn part to another Container.
75
+ #
76
+ # # ou = "ou=InfoTech,dc=net"
77
+ # ou = ActiveDirectory::Container.dc("net").ou("InfoTech").to_s
78
+ #
79
+ def ou(name)
80
+ self.class.new(:ou, name, self)
81
+ end
82
+
83
+ #
84
+ # Appends a DC (Domain Component) dn part to another Container.
85
+ #
86
+ # # base = "dc=example,dc=net"
87
+ # base = ActiveDirectory::Container.dc("net").dc("example").to_s
88
+ #
89
+ def dc(name)
90
+ self.class.new(:dc, name, self)
91
+ end
92
+
93
+ #
94
+ # Appends a CN (Canonical Name) dn part to another Container.
95
+ #
96
+ # # user = "cn=UID,ou=Users"
97
+ # user = ActiveDirectory::Container.ou("Users").cn("UID")
98
+ #
99
+ def cn(name)
100
+ self.class.new(:cn, name, self)
101
+ end
102
+
103
+ #
104
+ # Converts the Container object to its String representation.
105
+ #
106
+ def to_s
107
+ @node ? "#{@type}=#{name},#{@node}" : "#{@type}=#{name}"
108
+ end
109
+
110
+ def ==(other) #:nodoc:
111
+ to_s.casecmp(other.to_s.downcase).zero?
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,39 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class Binary
24
+ #
25
+ # Encodes a hex string into a GUID
26
+ #
27
+ def self.encode(hex_string)
28
+ [hex_string].pack('H*')
29
+ end
30
+
31
+ #
32
+ # Decodes a binary GUID as a hex string
33
+ #
34
+ def self.decode(guid)
35
+ guid.unpack('H*').first.to_s
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class Date
24
+ #
25
+ # Converts a time object into an ISO8601 format compatable with Active Directory
26
+ #
27
+ def self.encode(local_time)
28
+ local_time.strftime('%Y%m%d%H%M%S.0Z')
29
+ end
30
+
31
+ #
32
+ # Decodes an Active Directory date when stored as ISO8601
33
+ #
34
+ def self.decode(remote_time)
35
+ Time.parse(remote_time)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,40 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class DnArray
24
+ #
25
+ # Encodes an array of objects into a list of dns
26
+ #
27
+ def self.encode(obj_array)
28
+ obj_array.collect(&:dn)
29
+ end
30
+
31
+ #
32
+ # Decodes a list of DNs into the objects that they are
33
+ #
34
+ def self.decode(dn_array)
35
+ # How to do user or group?
36
+ Base.find(:all, distinguishedname: dn_array)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class GroupDnArray
24
+ #
25
+ # Encodes an array of objects into a list of dns
26
+ #
27
+ def self.encode(obj_array)
28
+ obj_array.collect(&:dn)
29
+ end
30
+
31
+ #
32
+ # Decodes a list of DNs into the objects that they are
33
+ #
34
+ def self.decode(dn_array)
35
+ # How to do user or group?
36
+ Group.find(:all, distinguishedname: dn_array)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class MemberDnArray
24
+ #
25
+ # Encodes an array of objects into a list of dns
26
+ #
27
+ def self.encode(obj_array)
28
+ obj_array.collect(&:dn)
29
+ end
30
+
31
+ #
32
+ # Decodes a list of DNs into the objects that they are
33
+ #
34
+ def self.decode(dn_array)
35
+ # Ensures that the objects are cast correctly
36
+ users = User.find(:all, distinguishedname: dn_array)
37
+ groups = Group.find(:all, distinguishedname: dn_array)
38
+
39
+ arr = []
40
+ arr << users unless users.nil?
41
+ arr << groups unless groups.nil?
42
+
43
+ arr.flatten
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,41 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class Password
24
+ #
25
+ # Encodes an unencrypted password into an encrypted password
26
+ # that the Active Directory server will understand.
27
+ #
28
+ def self.encode(password)
29
+ ("\"#{password}\"".split(//).collect { |c| "#{c}\000" }).join
30
+ end
31
+
32
+ #
33
+ # Always returns nil, since you can't decrypt the User's encrypted
34
+ # password.
35
+ #
36
+ def self.decode(_hashed)
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class Timestamp
24
+ AD_DIVISOR = 10_000_000 #:nodoc:
25
+ AD_OFFSET = 11_644_473_600 #:nodoc:
26
+
27
+ #
28
+ # Encodes a local Time object (or the number of seconds since January
29
+ # 1, 1970) into a timestamp that the Active Directory server can
30
+ # understand (number of 100 nanosecond time units since January 1, 1600)
31
+ #
32
+ def self.encode(local_time)
33
+ (local_time.to_i + AD_OFFSET) * AD_DIVISOR
34
+ end
35
+
36
+ #
37
+ # Decodes an Active Directory timestamp (the number of 100 nanosecond time
38
+ # units since January 1, 1600) into a Ruby Time object.
39
+ #
40
+ def self.decode(remote_time)
41
+ Time.at((remote_time.to_i / AD_DIVISOR) - AD_OFFSET)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module FieldType
23
+ class UserDnArray
24
+ #
25
+ # Encodes an array of objects into a list of dns
26
+ #
27
+ def self.encode(obj_array)
28
+ obj_array.collect(&:dn)
29
+ end
30
+
31
+ #
32
+ # Decodes a list of DNs into the objects that they are
33
+ #
34
+ def self.decode(dn_array)
35
+ # How to do user or group?
36
+ User.find(:all, distinguishedname: dn_array)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,160 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ require 'bsb_active_directory/attributes'
22
+
23
+ module ActiveDirectory
24
+ class Group < Base
25
+ include Member
26
+
27
+ def self.filter # :nodoc:
28
+ Net::LDAP::Filter.eq(:objectClass, 'group')
29
+ end
30
+
31
+ def self.required_attributes # :nodoc:
32
+ { objectClass: %w[top group] }
33
+ end
34
+
35
+ def reload # :nodoc:
36
+ @member_users_non_r = nil
37
+ @member_users_r = nil
38
+ @member_groups_non_r = nil
39
+ @member_groups_r = nil
40
+ @groups = nil
41
+ super
42
+ end
43
+
44
+ #
45
+ # Returns true if the passed User or Group object belongs to
46
+ # this group. For performance reasons, the check is handled
47
+ # by the User or Group object passed.
48
+ #
49
+ def has_member?(user)
50
+ user.member_of?(self)
51
+ end
52
+
53
+ def self.create_security_group(ou, name, type)
54
+ type_mask = GroupType::SECURITY_ENABLED
55
+ case type
56
+ when :local
57
+ type_mask |= GroupType::RESSOURCE_GROUP
58
+ when :global
59
+ type_mask |= GroupType::ACCOUNT_GROUP
60
+ when :universal
61
+ type_mask |= GroupType::UNIVERSAL_GROUP
62
+ else
63
+ raise "Unknown type specified : #{type}"
64
+ end
65
+ dn = 'CN=' + name + ',' + ou
66
+ attributes = {
67
+ objectClass: %w[top group],
68
+ sAMAccountName: name,
69
+ objectCategory: 'CN=Group,CN=Schema,CN=Configuration,DC=afssa,DC=fr',
70
+ groupType: type_mask.to_s
71
+ }
72
+ @@ldap.add(dn: dn, attributes: attributes)
73
+ from_dn(dn)
74
+ end
75
+
76
+ #
77
+ # Add the passed User or Group object to this Group. Returns true if
78
+ # the User or Group is already a member of the group, or if the operation
79
+ # to add them succeeds.
80
+ #
81
+ def add(new_member)
82
+ return false unless new_member.is_a?(User) || new_member.is_a?(Group)
83
+ if @@ldap.modify(dn: distinguishedName, operations: [
84
+ [:add, :member, new_member.distinguishedName]
85
+ ])
86
+ return true
87
+ else
88
+ return has_member?(new_member)
89
+ end
90
+ end
91
+
92
+ #
93
+ # Remove a User or Group from this Group. Returns true if the User or
94
+ # Group does not belong to this Group, or if the oepration to remove them
95
+ # succeeds.
96
+ #
97
+ def remove(member)
98
+ return false unless member.is_a?(User) || member.is_a?(Group)
99
+ if @@ldap.modify(dn: distinguishedName, operations: [
100
+ [:delete, :member, member.distinguishedName]
101
+ ])
102
+ return true
103
+ else
104
+ return !has_member?(member)
105
+ end
106
+ end
107
+
108
+ def has_members?
109
+ return @entry.member.nil? || @entry.member.empty? ? false : true
110
+ rescue NoMethodError
111
+ return false
112
+ end
113
+
114
+ #
115
+ # Returns an array of all User objects that belong to this group.
116
+ #
117
+ # If the recursive argument is passed as false, then only Users who
118
+ # belong explicitly to this Group are returned.
119
+ #
120
+ # If the recursive argument is passed as true, then all Users who
121
+ # belong to this Group, or any of its subgroups, are returned.
122
+ #
123
+ def member_users(recursive = false)
124
+ @member_users = User.find(:all, distinguishedname: @entry[:member]).delete_if(&:nil?)
125
+ if recursive
126
+ member_groups.each do |group|
127
+ @member_users.concat(group.member_users(true))
128
+ end
129
+ end
130
+ @member_users
131
+ end
132
+
133
+ #
134
+ # Returns an array of all Group objects that belong to this group.
135
+ #
136
+ # If the recursive argument is passed as false, then only Groups that
137
+ # belong explicitly to this Group are returned.
138
+ #
139
+ # If the recursive argument is passed as true, then all Groups that
140
+ # belong to this Group, or any of its subgroups, are returned.
141
+ #
142
+ def member_groups(recursive = false)
143
+ @member_groups ||= Group.find(:all, distinguishedname: @entry[:member]).delete_if(&:nil?)
144
+ if recursive
145
+ member_groups.each do |group|
146
+ @member_groups.concat(group.member_groups(true))
147
+ end
148
+ end
149
+ @member_groups
150
+ end
151
+
152
+ #
153
+ # Returns an array of Group objects that this Group belongs to.
154
+ #
155
+ def groups
156
+ return [] if memberOf.nil?
157
+ @groups ||= Group.find(:all, distinguishedname: @entry.memberOf).delete_if(&:nil?)
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,53 @@
1
+ #-- license
2
+ #
3
+ # Based on original code by Justin Mecham and James Hunt
4
+ # at http://rubyforge.org/projects/activedirectory
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+ #++ license
20
+
21
+ module ActiveDirectory
22
+ module Member
23
+ #
24
+ # Returns true if this member (User or Group) is a member of
25
+ # the passed Group object.
26
+ #
27
+ def member_of?(usergroup)
28
+ group_dns = memberOf
29
+ return false if group_dns.nil? || group_dns.empty?
30
+ # group_dns = [group_dns] unless group_dns.is_a?(Array)
31
+ group_dns.map(&:dn).include?(usergroup.dn)
32
+ end
33
+
34
+ #
35
+ # Add the member to the passed Group object. Returns true if this object
36
+ # is already a member of the Group, or if the operation to add it succeeded.
37
+ #
38
+ def join(group)
39
+ return false unless group.is_a?(Group)
40
+ group.add(self)
41
+ end
42
+
43
+ #
44
+ # Remove the member from the passed Group object. Returns true if this
45
+ # object is not a member of the Group, or if the operation to remove it
46
+ # succeeded.
47
+ #
48
+ def unjoin(group)
49
+ return false unless group.is_a?(Group)
50
+ group.remove(self)
51
+ end
52
+ end
53
+ end