active_directory 1.1.1

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