activesambaldap 0.0.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.
- data/NEWS.en +9 -0
- data/NEWS.ja +10 -0
- data/README.en +310 -0
- data/README.ja +307 -0
- data/Rakefile +95 -0
- data/bin/asl-groupadd +70 -0
- data/bin/asl-groupdel +58 -0
- data/bin/asl-groupmod +133 -0
- data/bin/asl-groupshow +31 -0
- data/bin/asl-passwd +99 -0
- data/bin/asl-populate +96 -0
- data/bin/asl-purge +24 -0
- data/bin/asl-samba-computeradd +94 -0
- data/bin/asl-samba-groupadd +55 -0
- data/bin/asl-samba-groupdel +53 -0
- data/bin/asl-samba-groupmod +98 -0
- data/bin/asl-samba-useradd +98 -0
- data/bin/asl-samba-userdel +47 -0
- data/bin/asl-samba-usermod +92 -0
- data/bin/asl-useradd +263 -0
- data/bin/asl-userdel +75 -0
- data/bin/asl-usermod +335 -0
- data/bin/asl-usershow +31 -0
- data/lib/active_samba_ldap/account.rb +199 -0
- data/lib/active_samba_ldap/base.rb +126 -0
- data/lib/active_samba_ldap/command.rb +94 -0
- data/lib/active_samba_ldap/computer.rb +13 -0
- data/lib/active_samba_ldap/computer_account.rb +34 -0
- data/lib/active_samba_ldap/configuration.rb +322 -0
- data/lib/active_samba_ldap/dc.rb +17 -0
- data/lib/active_samba_ldap/entry.rb +80 -0
- data/lib/active_samba_ldap/group.rb +182 -0
- data/lib/active_samba_ldap/idmap.rb +17 -0
- data/lib/active_samba_ldap/ou.rb +18 -0
- data/lib/active_samba_ldap/populate.rb +254 -0
- data/lib/active_samba_ldap/samba_account.rb +200 -0
- data/lib/active_samba_ldap/samba_computer.rb +20 -0
- data/lib/active_samba_ldap/samba_group.rb +126 -0
- data/lib/active_samba_ldap/samba_user.rb +39 -0
- data/lib/active_samba_ldap/unix_id_pool.rb +41 -0
- data/lib/active_samba_ldap/user.rb +14 -0
- data/lib/active_samba_ldap/user_account.rb +30 -0
- data/lib/active_samba_ldap/version.rb +3 -0
- data/lib/active_samba_ldap.rb +29 -0
- data/lib/samba/encrypt.rb +86 -0
- data/misc/rd2html.rb +42 -0
- data/rails/plugin/active_samba_ldap/README +30 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/scaffold_asl_generator.rb +28 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/computer.rb +3 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/dc.rb +3 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/group.rb +3 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/idmap.rb +3 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/ldap.yml +24 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/ou.rb +3 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/samba_controller.rb +12 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/samba_helper.rb +2 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/samba_index.rhtml +17 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/samba_populate.rhtml +15 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/samba_purge.rhtml +10 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/unix_id_pool.rb +3 -0
- data/rails/plugin/active_samba_ldap/generators/scaffold_asl/templates/user.rb +3 -0
- data/rails/plugin/active_samba_ldap/init.rb +6 -0
- data/test/asl-test-utils.rb +276 -0
- data/test/command.rb +64 -0
- data/test/config.yaml.sample +17 -0
- data/test/run-test.rb +18 -0
- data/test/test-unit-ext/always-show-result.rb +28 -0
- data/test/test-unit-ext/priority.rb +159 -0
- data/test/test-unit-ext.rb +2 -0
- data/test/test_asl_groupadd.rb +69 -0
- data/test/test_asl_groupdel.rb +88 -0
- data/test/test_asl_groupmod.rb +256 -0
- data/test/test_asl_groupshow.rb +21 -0
- data/test/test_asl_passwd.rb +125 -0
- data/test/test_asl_populate.rb +92 -0
- data/test/test_asl_purge.rb +21 -0
- data/test/test_asl_useradd.rb +710 -0
- data/test/test_asl_userdel.rb +73 -0
- data/test/test_asl_usermod.rb +541 -0
- data/test/test_asl_usershow.rb +27 -0
- data/test/test_group.rb +21 -0
- data/test/test_password.rb +51 -0
- data/test/test_samba_encrypt.rb +36 -0
- data/test/test_user_home_directory.rb +43 -0
- metadata +177 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'English'
|
2
|
+
|
3
|
+
require 'active_samba_ldap/entry'
|
4
|
+
|
5
|
+
module ActiveSambaLdap
|
6
|
+
class Group < Base
|
7
|
+
include Reloadable::Subclasses
|
8
|
+
|
9
|
+
include Entry
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def ldap_mapping(options={})
|
13
|
+
options = default_options.merge(options)
|
14
|
+
super(extract_ldap_mapping_options(options))
|
15
|
+
init_associations(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def find_by_name_or_gid_number(key)
|
19
|
+
group = nil
|
20
|
+
begin
|
21
|
+
gid_number = Integer(key)
|
22
|
+
group = find_by_gid_number(gid_number)
|
23
|
+
raise GidNumberDoesNotExist.new(gid_number) if group.nil?
|
24
|
+
rescue ArgumentError
|
25
|
+
raise GroupDoesNotExist.new(key) unless exists?(key)
|
26
|
+
group = find(key)
|
27
|
+
end
|
28
|
+
group
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_by_gid_number(number)
|
32
|
+
attribute = "gidNumber"
|
33
|
+
value = Integer(number).to_s
|
34
|
+
find(:first, :filter => "(#{attribute}=#{value})")
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def default_options
|
39
|
+
{
|
40
|
+
:dn_attribute => "cn",
|
41
|
+
:prefix => configuration[:groups_suffix],
|
42
|
+
:classes => default_classes,
|
43
|
+
|
44
|
+
:members_wrap => "memberUid",
|
45
|
+
:users_class => default_user_class,
|
46
|
+
:computers_class => default_computer_class,
|
47
|
+
|
48
|
+
:primary_members_foreign_key => "gidNumber",
|
49
|
+
:primary_members_primary_key => "gidNumber",
|
50
|
+
:primary_users_class => default_user_class,
|
51
|
+
:primary_computers_class => default_computer_class,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_classes
|
56
|
+
["top", "posixGroup"]
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_user_class
|
60
|
+
"User"
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_computer_class
|
64
|
+
"Computer"
|
65
|
+
end
|
66
|
+
|
67
|
+
def init_associations(options)
|
68
|
+
association_options = {}
|
69
|
+
options.each do |key, value|
|
70
|
+
case key.to_s
|
71
|
+
when /^((?:primary_)?(?:(?:user|computer|member)s))_/
|
72
|
+
association_options[$1] ||= {}
|
73
|
+
association_options[$1][$POSTMATCH.to_sym] = value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
members_opts = association_options["members"] || {}
|
78
|
+
user_members_opts = association_options["users"] || {}
|
79
|
+
computer_members_opts = association_options["computers"] || {}
|
80
|
+
has_many :users, members_opts.merge(user_members_opts)
|
81
|
+
has_many :computers, members_opts.merge(computer_members_opts)
|
82
|
+
|
83
|
+
primary_members_opts = association_options["primary_members"] || {}
|
84
|
+
primary_user_members_opts =
|
85
|
+
association_options["primary_users"] || {}
|
86
|
+
primary_computer_members_opts =
|
87
|
+
association_options["primary_computers"] || {}
|
88
|
+
has_many :primary_users,
|
89
|
+
primary_members_opts.merge(primary_user_members_opts)
|
90
|
+
has_many :primary_computers,
|
91
|
+
primary_members_opts.merge(primary_computer_members_opts)
|
92
|
+
end
|
93
|
+
|
94
|
+
def prepare_create_options(group, options)
|
95
|
+
prepare_create_options_for_number(:gid_number, group, options)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def fill_default_values(options={})
|
100
|
+
gid_number = options[:gid_number]
|
101
|
+
change_gid_number(gid_number) if gid_number
|
102
|
+
self.description ||= options[:description] || cn
|
103
|
+
end
|
104
|
+
|
105
|
+
def members
|
106
|
+
users.to_ary + computers.to_ary
|
107
|
+
end
|
108
|
+
|
109
|
+
def reload_members
|
110
|
+
users.reload
|
111
|
+
computers.reload
|
112
|
+
end
|
113
|
+
|
114
|
+
def primary_members
|
115
|
+
primary_users.to_ary + primary_computers.to_ary
|
116
|
+
end
|
117
|
+
|
118
|
+
def reload_primary_members
|
119
|
+
primary_users.reload
|
120
|
+
primary_computers.reload
|
121
|
+
end
|
122
|
+
|
123
|
+
def change_gid_number(gid, allow_non_unique=false)
|
124
|
+
check_unique_gid_number(gid) unless allow_non_unique
|
125
|
+
self.gid_number = gid.to_s
|
126
|
+
end
|
127
|
+
|
128
|
+
def destroy(options={})
|
129
|
+
if options[:remove_members]
|
130
|
+
if options[:force_change_primary_members]
|
131
|
+
change_primary_members(options)
|
132
|
+
end
|
133
|
+
reload_primary_members
|
134
|
+
unless primary_members.empty?
|
135
|
+
not_destroyed_members = primary_members.collect {|x| x.uid}
|
136
|
+
raise PrimaryGroupCanNotBeDestroyed.new(cn, not_destroyed_members)
|
137
|
+
end
|
138
|
+
self.users = []
|
139
|
+
self.computers = []
|
140
|
+
end
|
141
|
+
super()
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
def ensure_uid(member_or_uid)
|
146
|
+
if member_or_uid.is_a?(String)
|
147
|
+
member_or_uid
|
148
|
+
else
|
149
|
+
member_or_uid.uid
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def check_unique_gid_number(gid_number)
|
154
|
+
ActiveSambaLdap::Base.restart_nscd do
|
155
|
+
if self.class.find_by_gid_number(Integer(gid_number))
|
156
|
+
raise GidNumberAlreadyExists.new(gid_number)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def change_primary_members(options={})
|
162
|
+
name = cn
|
163
|
+
|
164
|
+
pr_members = primary_members
|
165
|
+
cannot_removed_members = []
|
166
|
+
pr_members.each do |member|
|
167
|
+
if (member.groups.collect {|group| group.cn} - [name]).empty?
|
168
|
+
cannot_removed_members << member.uid
|
169
|
+
end
|
170
|
+
end
|
171
|
+
unless cannot_removed_members.empty?
|
172
|
+
raise CanNotChangePrimaryGroup.new(name, cannot_removed_members)
|
173
|
+
end
|
174
|
+
|
175
|
+
pr_members.each do |member|
|
176
|
+
new_group = member.groups.find {|gr| gr.cn != name}
|
177
|
+
member.primary_group = new_group
|
178
|
+
member.save!
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveSambaLdap
|
2
|
+
class Idmap < Base
|
3
|
+
include Reloadable::Subclasses
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def ldap_mapping(options={})
|
7
|
+
default_options = {
|
8
|
+
:dn_attribute => "sambaSID",
|
9
|
+
:prefix => configuration[:idmap_suffix],
|
10
|
+
:classes => ["top", "sambaIdmapEntry"],
|
11
|
+
}
|
12
|
+
options = default_options.merge(options)
|
13
|
+
super options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ActiveSambaLdap
|
2
|
+
class Ou < Base
|
3
|
+
include Reloadable::Subclasses
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def ldap_mapping(options={})
|
7
|
+
default_options = {
|
8
|
+
:dn_attribute => "ou",
|
9
|
+
:prefix => "",
|
10
|
+
:classes => ["top", "organizationalUnit"],
|
11
|
+
:scope => :sub,
|
12
|
+
}
|
13
|
+
options = default_options.merge(options)
|
14
|
+
super(options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
module ActiveSambaLdap
|
2
|
+
module Populate
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def populate(options={})
|
9
|
+
Private.new(self, options).populate
|
10
|
+
end
|
11
|
+
|
12
|
+
def purge(options={})
|
13
|
+
self.delete_all(nil, {:scope => :sub}.merge(options))
|
14
|
+
end
|
15
|
+
|
16
|
+
class Private
|
17
|
+
def initialize(base, options)
|
18
|
+
@base = base
|
19
|
+
@options = options.dup
|
20
|
+
end
|
21
|
+
|
22
|
+
def populate
|
23
|
+
init_classes
|
24
|
+
init_options
|
25
|
+
|
26
|
+
entries = []
|
27
|
+
entries.concat(ensure_base)
|
28
|
+
entries.concat(ensure_group_base)
|
29
|
+
entries.concat(ensure_user_base)
|
30
|
+
entries.concat(ensure_computer_base)
|
31
|
+
entries.concat(ensure_idmap_base)
|
32
|
+
entries.concat(make_groups)
|
33
|
+
entries.concat(make_users)
|
34
|
+
entries.concat(make_pool)
|
35
|
+
|
36
|
+
[entries, @options]
|
37
|
+
end
|
38
|
+
|
39
|
+
def init_classes
|
40
|
+
@options[:user_class] = user_class = Class.new(SambaUser)
|
41
|
+
@options[:group_class] = group_class = Class.new(SambaGroup)
|
42
|
+
@options[:computer_class] = computer_class = Class.new(SambaComputer)
|
43
|
+
@options[:idmap_class] = idmap_class = Class.new(Idmap)
|
44
|
+
@options[:unix_id_pool_class] = id_pool_class = Class.new(UnixIdPool)
|
45
|
+
|
46
|
+
user_class.ldap_mapping
|
47
|
+
group_class.ldap_mapping
|
48
|
+
computer_class.ldap_mapping
|
49
|
+
idmap_class.ldap_mapping
|
50
|
+
id_pool_class.ldap_mapping
|
51
|
+
|
52
|
+
user_class.set_associated_class(:primary_group, group_class)
|
53
|
+
computer_class.set_associated_class(:primary_group, group_class)
|
54
|
+
user_class.set_associated_class(:groups, group_class)
|
55
|
+
computer_class.set_associated_class(:groups, group_class)
|
56
|
+
|
57
|
+
group_class.set_associated_class(:users, user_class)
|
58
|
+
group_class.set_associated_class(:computers, computer_class)
|
59
|
+
group_class.set_associated_class(:primary_users, user_class)
|
60
|
+
group_class.set_associated_class(:primary_computers, computer_class)
|
61
|
+
end
|
62
|
+
|
63
|
+
def user_class
|
64
|
+
@options[:user_class]
|
65
|
+
end
|
66
|
+
|
67
|
+
def group_class
|
68
|
+
@options[:group_class]
|
69
|
+
end
|
70
|
+
|
71
|
+
def computer_class
|
72
|
+
@options[:computer_class]
|
73
|
+
end
|
74
|
+
|
75
|
+
def idmap_class
|
76
|
+
@options[:idmap_class]
|
77
|
+
end
|
78
|
+
|
79
|
+
def init_options
|
80
|
+
config = @base.configuration
|
81
|
+
@options[:start_uid] ||= Integer(config[:start_uid])
|
82
|
+
@options[:start_gid] ||= Integer(config[:start_gid])
|
83
|
+
@options[:administrator] ||= user_class::DOMAIN_ADMIN_NAME
|
84
|
+
@options[:administrator_uid] ||=
|
85
|
+
user_class.rid2uid(user_class::DOMAIN_ADMIN_RID)
|
86
|
+
@options[:administrator_gid] ||=
|
87
|
+
group_class.rid2gid(group_class::DOMAIN_ADMINS_RID)
|
88
|
+
@options[:guest] ||= user_class::DOMAIN_GUEST_NAME
|
89
|
+
@options[:guest_uid] ||=
|
90
|
+
user_class.rid2uid(user_class::DOMAIN_GUEST_RID)
|
91
|
+
@options[:guest_gid] ||=
|
92
|
+
group_class.rid2gid(group_class::DOMAIN_GUESTS_RID)
|
93
|
+
@options[:default_user_gid] ||= config[:default_user_gid]
|
94
|
+
@options[:default_computer_gid] ||= config[:default_computer_gid]
|
95
|
+
end
|
96
|
+
|
97
|
+
def ensure_container_base(dn, target_name, klass, ignore_base=false)
|
98
|
+
entries = []
|
99
|
+
suffixes = []
|
100
|
+
dn.split(/,/).reverse_each do |suffix|
|
101
|
+
name, value = suffix.split(/=/, 2)
|
102
|
+
next unless name == target_name
|
103
|
+
container_class = Class.new(klass)
|
104
|
+
prefix = suffixes.reverse.join(",")
|
105
|
+
suffixes << suffix
|
106
|
+
if ignore_base
|
107
|
+
container_class.ldap_mapping :prefix => "", :scope => :base
|
108
|
+
container_class.base = prefix
|
109
|
+
else
|
110
|
+
container_class.ldap_mapping :prefix => prefix, :scope => :base
|
111
|
+
end
|
112
|
+
next if container_class.exists?(value, :prefix => suffix)
|
113
|
+
container = container_class.new(value)
|
114
|
+
yield(container) if block_given?
|
115
|
+
container.save!
|
116
|
+
entries << container
|
117
|
+
end
|
118
|
+
entries
|
119
|
+
end
|
120
|
+
|
121
|
+
def ensure_base
|
122
|
+
ensure_container_base(@base.base, "dc", Dc, true) do |dc|
|
123
|
+
dc.o = dc.dc
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def ensure_ou_base(dn)
|
128
|
+
ensure_container_base(dn, "ou", Ou)
|
129
|
+
end
|
130
|
+
|
131
|
+
def ensure_user_base
|
132
|
+
ensure_ou_base(user_class.prefix)
|
133
|
+
end
|
134
|
+
|
135
|
+
def ensure_group_base
|
136
|
+
ensure_ou_base(group_class.prefix)
|
137
|
+
end
|
138
|
+
|
139
|
+
def ensure_computer_base
|
140
|
+
ensure_ou_base(computer_class.prefix)
|
141
|
+
end
|
142
|
+
|
143
|
+
def ensure_idmap_base
|
144
|
+
ensure_ou_base(idmap_class.prefix)
|
145
|
+
end
|
146
|
+
|
147
|
+
def make_user(user_class, name, uid, group)
|
148
|
+
if user_class.exists?(name)
|
149
|
+
user = user_class.find(name)
|
150
|
+
group = nil
|
151
|
+
else
|
152
|
+
user = user_class.new(name)
|
153
|
+
user.fill_default_values(:uid_number => uid, :group => group)
|
154
|
+
user.save!
|
155
|
+
group.users << user
|
156
|
+
end
|
157
|
+
[user, group]
|
158
|
+
end
|
159
|
+
|
160
|
+
def make_users
|
161
|
+
user_class = @options[:user_class]
|
162
|
+
group_class = @options[:group_class]
|
163
|
+
entries = []
|
164
|
+
[
|
165
|
+
[@options[:administrator], @options[:administrator_uid],
|
166
|
+
@options[:administrator_gid]],
|
167
|
+
[@options[:guest], @options[:guest_uid], @options[:guest_gid]],
|
168
|
+
].each do |name, uid, gid|
|
169
|
+
user, group = make_user(user_class, name, uid,
|
170
|
+
group_class.find_by_gid_number(gid))
|
171
|
+
entries << user
|
172
|
+
if group
|
173
|
+
old_group = entries.find do |entry|
|
174
|
+
entry.is_a?(group_class) and entry.cn == group.cn
|
175
|
+
end
|
176
|
+
index = entries.index(old_group)
|
177
|
+
if index
|
178
|
+
entries[index] = group
|
179
|
+
else
|
180
|
+
entries << group
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
entries
|
185
|
+
end
|
186
|
+
|
187
|
+
def make_group(group_class, name, gid, description=nil, type=nil)
|
188
|
+
if group_class.exists?(name)
|
189
|
+
group = group_class.find(name)
|
190
|
+
else
|
191
|
+
group = group_class.new(name)
|
192
|
+
group.change_type(type || "domain")
|
193
|
+
group.display_name = name
|
194
|
+
group.description = name || description
|
195
|
+
group.change_gid_number(gid)
|
196
|
+
|
197
|
+
group.save!
|
198
|
+
end
|
199
|
+
group
|
200
|
+
end
|
201
|
+
|
202
|
+
def make_groups
|
203
|
+
entries = []
|
204
|
+
[
|
205
|
+
["Domain Admins", @options[:administrator_gid],
|
206
|
+
"Netbios Domain Administrators"],
|
207
|
+
["Domain Users", @options[:default_user_gid],
|
208
|
+
"Netbios Domain Users"],
|
209
|
+
["Domain Guests", @options[:guest_gid],
|
210
|
+
"Netbios Domain Guest Users"],
|
211
|
+
["Domain Computers", @options[:default_computer_gid],
|
212
|
+
"Netbios Domain Computers"],
|
213
|
+
["Administrators", nil, nil, "builtin",
|
214
|
+
group_class::LOCAL_ADMINS_RID],
|
215
|
+
["Users", nil, nil, "builtin", group_class::LOCAL_USERS_RID],
|
216
|
+
["Guests", nil, nil, "builtin", group_class::LOCAL_GUESTS_RID],
|
217
|
+
["Power Users", nil, nil, "builtin",
|
218
|
+
group_class::LOCAL_POWER_USERS_RID],
|
219
|
+
["Account Operators", nil, nil, "builtin",
|
220
|
+
group_class::LOCAL_ACCOUNT_OPERATORS_RID],
|
221
|
+
["System Operators", nil, nil, "builtin",
|
222
|
+
group_class::LOCAL_SYSTEM_OPERATORS_RID],
|
223
|
+
["Print Operators", nil, nil, "builtin",
|
224
|
+
group_class::LOCAL_PRINT_OPERATORS_RID],
|
225
|
+
["Backup Operators", nil, nil, "builtin",
|
226
|
+
group_class::LOCAL_BACKUP_OPERATORS_RID],
|
227
|
+
["Replicators", nil, nil, "builtin",
|
228
|
+
group_class::LOCAL_REPLICATORS_RID],
|
229
|
+
].each do |name, gid, description, type, rid|
|
230
|
+
gid ||= group_class.rid2gid(rid)
|
231
|
+
entries << make_group(group_class, name, gid, description, type)
|
232
|
+
end
|
233
|
+
entries
|
234
|
+
end
|
235
|
+
|
236
|
+
def make_pool
|
237
|
+
config = @base.configuration
|
238
|
+
klass = @options[:unix_id_pool_class]
|
239
|
+
name = config[:samba_domain]
|
240
|
+
if klass.exists?(name)
|
241
|
+
pool = klass.find(name)
|
242
|
+
else
|
243
|
+
pool = klass.new(name)
|
244
|
+
pool.samba_sid = config[:sid]
|
245
|
+
pool.uid_number = @options[:start_uid]
|
246
|
+
pool.gid_number = @options[:start_gid]
|
247
|
+
pool.save!
|
248
|
+
end
|
249
|
+
[pool]
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
module ActiveSambaLdap
|
2
|
+
module SambaAccount
|
3
|
+
def self.included(base)
|
4
|
+
super
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
# from source/include/rpc_misc.c in Samba
|
9
|
+
DOMAIN_ADMIN_RID = 0x000001F4
|
10
|
+
DOMAIN_GUEST_RID = 0x000001F5
|
11
|
+
|
12
|
+
# from source/rpc_server/srv_util.c in Samba
|
13
|
+
DOMAIN_ADMIN_NAME = "Administrator"
|
14
|
+
DOMAIN_GUEST_NAME = "Guest"
|
15
|
+
|
16
|
+
WELL_KNOWN_RIDS = []
|
17
|
+
WELL_KNOWN_NAMES = []
|
18
|
+
constants.each do |name|
|
19
|
+
case name
|
20
|
+
when /_RID$/
|
21
|
+
WELL_KNOWN_RIDS << const_get(name)
|
22
|
+
when /_NAME$/
|
23
|
+
WELL_KNOWN_NAMES << const_get(name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
FAR_FUTURE_TIME = Time.parse("2050/01/01").to_i.to_s
|
28
|
+
ACCOUNT_FLAGS_RE = /\A\[([NDHTUMWSLXI ]+)\]\z/
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
def uid2rid(uid)
|
32
|
+
uid = Integer(uid)
|
33
|
+
if WELL_KNOWN_RIDS.include?(uid)
|
34
|
+
uid
|
35
|
+
else
|
36
|
+
2 * uid + 1000
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def rid2uid(rid)
|
41
|
+
rid = Integer(rid)
|
42
|
+
if WELL_KNOWN_RIDS.include?(rid)
|
43
|
+
rid
|
44
|
+
else
|
45
|
+
(Integer(rid) - 1000) / 2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_rid
|
50
|
+
uid2rid(start_uid)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def default_classes
|
55
|
+
super + ["sambaSamAccount"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def primary_group_options(options)
|
59
|
+
super.merge(:extend => PrimaryGroupProxy)
|
60
|
+
end
|
61
|
+
|
62
|
+
module PrimaryGroupProxy
|
63
|
+
def replace(entry)
|
64
|
+
super
|
65
|
+
if @target
|
66
|
+
if @target.samba_sid.to_s.empty?
|
67
|
+
raise GroupDoesNotHaveSambaSID.new(@target.gid_number)
|
68
|
+
end
|
69
|
+
@owner.samba_primary_group_sid = @target.samba_sid
|
70
|
+
else
|
71
|
+
@owner.samba_primary_group_sid = nil
|
72
|
+
end
|
73
|
+
entry
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def fill_default_values(options={})
|
79
|
+
super
|
80
|
+
|
81
|
+
self.samba_logon_time ||= "0"
|
82
|
+
self.samba_logoff_time ||= FAR_FUTURE_TIME
|
83
|
+
self.samba_kickoff_time ||= nil
|
84
|
+
|
85
|
+
password = options[:password]
|
86
|
+
change_samba_password(password) if password
|
87
|
+
self.samba_lm_password ||= "XXX"
|
88
|
+
self.samba_nt_password ||= "XXX"
|
89
|
+
self.samba_pwd_last_set ||= "0"
|
90
|
+
|
91
|
+
account_flags_is_not_set = samba_acct_flags.nil?
|
92
|
+
self.samba_acct_flags ||= default_account_flags
|
93
|
+
|
94
|
+
can_change_password = options[:can_change_password]
|
95
|
+
if can_change_password
|
96
|
+
self.enable_password_change
|
97
|
+
elsif account_flags_is_not_set or can_change_password == false
|
98
|
+
self.disable_password_change
|
99
|
+
end
|
100
|
+
|
101
|
+
must_change_password = options[:must_change_password]
|
102
|
+
if must_change_password
|
103
|
+
self.enable_forcing_password_change
|
104
|
+
elsif account_flags_is_not_set or must_change_password == false
|
105
|
+
self.disable_forcing_password_change
|
106
|
+
end
|
107
|
+
|
108
|
+
enable_account = options[:enable]
|
109
|
+
if enable_account
|
110
|
+
self.enable
|
111
|
+
elsif account_flags_is_not_set or enable_account == false
|
112
|
+
self.disable
|
113
|
+
end
|
114
|
+
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
def change_uid_number(uid, allow_non_unique=false)
|
119
|
+
super
|
120
|
+
rid = self.class.uid2rid(uid_number.to_s)
|
121
|
+
change_sid(rid, allow_non_unique)
|
122
|
+
end
|
123
|
+
|
124
|
+
def change_uid_number_by_rid(rid, allow_non_unique=false)
|
125
|
+
change_uid_number(self.class.rid2uid(rid), allow_non_unique)
|
126
|
+
end
|
127
|
+
|
128
|
+
def change_sid(rid, allow_non_unique=false)
|
129
|
+
sid = "#{self.class.configuration[:sid]}-#{rid}"
|
130
|
+
# check_unique_sid_number(sid) unless allow_non_unique
|
131
|
+
self.samba_sid = sid
|
132
|
+
end
|
133
|
+
|
134
|
+
def rid
|
135
|
+
Integer(samba_sid.split(/-/).last)
|
136
|
+
end
|
137
|
+
|
138
|
+
def change_samba_password(password)
|
139
|
+
self.samba_lm_password = Samba::Encrypt.lm_hash(password)
|
140
|
+
self.samba_nt_password = Samba::Encrypt.ntlm_hash(password)
|
141
|
+
self.samba_pwd_last_set = Time.now.to_i.to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
def enable_password_change
|
145
|
+
self.samba_pwd_can_change = "0"
|
146
|
+
end
|
147
|
+
|
148
|
+
def disable_password_change
|
149
|
+
self.samba_pwd_can_change = FAR_FUTURE_TIME
|
150
|
+
end
|
151
|
+
|
152
|
+
def can_change_password?
|
153
|
+
samba_pwd_can_change.nil? or
|
154
|
+
Time.at(samba_pwd_can_change.to_i) <= Time.now
|
155
|
+
end
|
156
|
+
|
157
|
+
def enable_forcing_password_change
|
158
|
+
self.samba_pwd_must_change = "0"
|
159
|
+
if /X/ =~ samba_acct_flags.to_s
|
160
|
+
self.samba_acct_flags = samba_acct_flags.sub(/X/, '')
|
161
|
+
end
|
162
|
+
if samba_pwd_last_set.to_i.zero?
|
163
|
+
self.samba_pwd_last_set = FAR_FUTURE_TIME
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def disable_forcing_password_change
|
168
|
+
self.samba_pwd_must_change = FAR_FUTURE_TIME
|
169
|
+
end
|
170
|
+
|
171
|
+
def must_change_password?
|
172
|
+
!(/X/ =~ samba_acct_flags.to_s or
|
173
|
+
samba_pwd_must_change.nil? or
|
174
|
+
Time.at(samba_pwd_must_change.to_i) > Time.now)
|
175
|
+
end
|
176
|
+
|
177
|
+
def enable
|
178
|
+
if /D/ =~ samba_acct_flags.to_s
|
179
|
+
self.samba_acct_flags = samba_acct_flags.gsub(/D/, '')
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def disable
|
184
|
+
flags = ""
|
185
|
+
if ACCOUNT_FLAGS_RE =~ samba_acct_flags.to_s
|
186
|
+
flags = $1
|
187
|
+
return if /D/ =~ flags
|
188
|
+
end
|
189
|
+
self.samba_acct_flags = "[D#{flags}]"
|
190
|
+
end
|
191
|
+
|
192
|
+
def enabled?
|
193
|
+
!disabled?
|
194
|
+
end
|
195
|
+
|
196
|
+
def disabled?
|
197
|
+
(/D/ =~ samba_acct_flags.to_s) ? true : false
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_samba_ldap/account'
|
2
|
+
require 'active_samba_ldap/user_account'
|
3
|
+
require 'active_samba_ldap/samba_account'
|
4
|
+
|
5
|
+
module ActiveSambaLdap
|
6
|
+
class SambaComputer < Base
|
7
|
+
include Reloadable::Subclasses
|
8
|
+
|
9
|
+
include Entry
|
10
|
+
|
11
|
+
include Account
|
12
|
+
include ComputerAccount
|
13
|
+
include SambaAccount
|
14
|
+
|
15
|
+
private
|
16
|
+
def default_account_flags
|
17
|
+
"[W]"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|