~ubuntu-branches/ubuntu/trusty/puppet/trusty

« back to all changes in this revision

Viewing changes to lib/puppet/util/adsi.rb

  • Committer: Package Import Robot
  • Author(s): Stig Sandbeck Mathisen
  • Date: 2011-10-22 14:08:22 UTC
  • mfrom: (1.1.25) (3.1.32 sid)
  • Revision ID: package-import@ubuntu.com-20111022140822-odxde5lohc45yhuz
Tags: 2.7.6-1
* New upstream release (CVE-2011-3872)
* Remove cherry-picked "groupadd_aix_warning" patch
* Install all new manpages

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
module Puppet::Util::ADSI
 
2
  class << self
 
3
    def connectable?(uri)
 
4
      begin
 
5
        !! connect(uri)
 
6
      rescue
 
7
        false
 
8
      end
 
9
    end
 
10
 
 
11
    def connect(uri)
 
12
      begin
 
13
        WIN32OLE.connect(uri)
 
14
      rescue Exception => e
 
15
        raise Puppet::Error.new( "ADSI connection error: #{e}" )
 
16
      end
 
17
    end
 
18
 
 
19
    def create(name, resource_type)
 
20
      Puppet::Util::ADSI.connect(computer_uri).Create(resource_type, name)
 
21
    end
 
22
 
 
23
    def delete(name, resource_type)
 
24
      Puppet::Util::ADSI.connect(computer_uri).Delete(resource_type, name)
 
25
    end
 
26
 
 
27
    def computer_name
 
28
      unless @computer_name
 
29
        buf = " " * 128
 
30
        Win32API.new('kernel32', 'GetComputerName', ['P','P'], 'I').call(buf, buf.length.to_s)
 
31
        @computer_name = buf.unpack("A*")
 
32
      end
 
33
      @computer_name
 
34
    end
 
35
 
 
36
    def computer_uri
 
37
      "WinNT://#{computer_name}"
 
38
    end
 
39
 
 
40
    def wmi_resource_uri( host = '.' )
 
41
      "winmgmts:{impersonationLevel=impersonate}!//#{host}/root/cimv2"
 
42
    end
 
43
 
 
44
    def uri(resource_name, resource_type)
 
45
      "#{computer_uri}/#{resource_name},#{resource_type}"
 
46
    end
 
47
 
 
48
    def execquery(query)
 
49
      connect(wmi_resource_uri).execquery(query)
 
50
    end
 
51
 
 
52
    def sid_for_account(name)
 
53
      sid = nil
 
54
 
 
55
      execquery(
 
56
        "SELECT Sid from Win32_Account
 
57
         WHERE Name = '#{name}' AND LocalAccount = true"
 
58
      ).each {|u| sid ||= u.Sid}
 
59
 
 
60
      sid
 
61
    end
 
62
  end
 
63
 
 
64
  class User
 
65
    extend Enumerable
 
66
 
 
67
    attr_accessor :native_user
 
68
    attr_reader :name
 
69
    def initialize(name, native_user = nil)
 
70
      @name = name
 
71
      @native_user = native_user
 
72
    end
 
73
 
 
74
    def native_user
 
75
      @native_user ||= Puppet::Util::ADSI.connect(uri)
 
76
    end
 
77
 
 
78
    def self.uri(name)
 
79
      Puppet::Util::ADSI.uri(name, 'user')
 
80
    end
 
81
 
 
82
    def uri
 
83
      self.class.uri(name)
 
84
    end
 
85
 
 
86
    def self.logon(name, password)
 
87
      fLOGON32_LOGON_NETWORK = 3
 
88
      fLOGON32_PROVIDER_DEFAULT = 0
 
89
 
 
90
      logon_user = Win32API.new("advapi32", "LogonUser", ['P', 'P', 'P', 'L', 'L', 'P'], 'L')
 
91
      close_handle = Win32API.new("kernel32", "CloseHandle", ['P'], 'V')
 
92
 
 
93
      token = ' ' * 4
 
94
      if logon_user.call(name, "", password, fLOGON32_LOGON_NETWORK, fLOGON32_PROVIDER_DEFAULT, token) != 0
 
95
        close_handle.call(token.unpack('L')[0])
 
96
        true
 
97
      else
 
98
        false
 
99
      end
 
100
    end
 
101
 
 
102
    def [](attribute)
 
103
      native_user.Get(attribute)
 
104
    end
 
105
 
 
106
    def []=(attribute, value)
 
107
      native_user.Put(attribute, value)
 
108
    end
 
109
 
 
110
    def commit
 
111
      begin
 
112
        native_user.SetInfo unless native_user.nil?
 
113
      rescue Exception => e
 
114
        raise Puppet::Error.new( "User update failed: #{e}" )
 
115
      end
 
116
      self
 
117
    end
 
118
 
 
119
    def password_is?(password)
 
120
      self.class.logon(name, password)
 
121
    end
 
122
 
 
123
    def add_flag(flag_name, value)
 
124
      flag = native_user.Get(flag_name) rescue 0
 
125
 
 
126
      native_user.Put(flag_name, flag | value)
 
127
 
 
128
      commit
 
129
    end
 
130
 
 
131
    def password=(password)
 
132
      native_user.SetPassword(password)
 
133
      commit
 
134
      fADS_UF_DONT_EXPIRE_PASSWD = 0x10000
 
135
      add_flag("UserFlags", fADS_UF_DONT_EXPIRE_PASSWD)
 
136
    end
 
137
 
 
138
    def groups
 
139
      # WIN32OLE objects aren't enumerable, so no map
 
140
      groups = []
 
141
      native_user.Groups.each {|g| groups << g.Name}
 
142
      groups
 
143
    end
 
144
 
 
145
    def add_to_groups(*group_names)
 
146
      group_names.each do |group_name|
 
147
        Puppet::Util::ADSI::Group.new(group_name).add_member(@name)
 
148
      end
 
149
    end
 
150
    alias add_to_group add_to_groups
 
151
 
 
152
    def remove_from_groups(*group_names)
 
153
      group_names.each do |group_name|
 
154
        Puppet::Util::ADSI::Group.new(group_name).remove_member(@name)
 
155
      end
 
156
    end
 
157
    alias remove_from_group remove_from_groups
 
158
 
 
159
    def set_groups(desired_groups, minimum = true)
 
160
      return if desired_groups.nil? or desired_groups.empty?
 
161
 
 
162
      desired_groups = desired_groups.split(',').map(&:strip)
 
163
 
 
164
      current_groups = self.groups
 
165
 
 
166
      # First we add the user to all the groups it should be in but isn't
 
167
      groups_to_add = desired_groups - current_groups
 
168
      add_to_groups(*groups_to_add)
 
169
 
 
170
      # Then we remove the user from all groups it is in but shouldn't be, if
 
171
      # that's been requested
 
172
      groups_to_remove = current_groups - desired_groups
 
173
      remove_from_groups(*groups_to_remove) unless minimum
 
174
    end
 
175
 
 
176
    def self.create(name)
 
177
      new(name, Puppet::Util::ADSI.create(name, 'user'))
 
178
    end
 
179
 
 
180
    def self.exists?(name)
 
181
      Puppet::Util::ADSI::connectable?(User.uri(name))
 
182
    end
 
183
 
 
184
    def self.delete(name)
 
185
      Puppet::Util::ADSI.delete(name, 'user')
 
186
    end
 
187
 
 
188
    def self.each(&block)
 
189
      wql = Puppet::Util::ADSI.execquery("select * from win32_useraccount")
 
190
 
 
191
      users = []
 
192
      wql.each do |u|
 
193
        users << new(u.name, u)
 
194
      end
 
195
 
 
196
      users.each(&block)
 
197
    end
 
198
  end
 
199
 
 
200
  class Group
 
201
    extend Enumerable
 
202
 
 
203
    attr_accessor :native_group
 
204
    attr_reader :name
 
205
    def initialize(name, native_group = nil)
 
206
      @name = name
 
207
      @native_group = native_group
 
208
    end
 
209
 
 
210
    def uri
 
211
      self.class.uri(name)
 
212
    end
 
213
 
 
214
    def self.uri(name)
 
215
      Puppet::Util::ADSI.uri(name, 'group')
 
216
    end
 
217
 
 
218
    def native_group
 
219
      @native_group ||= Puppet::Util::ADSI.connect(uri)
 
220
    end
 
221
 
 
222
    def commit
 
223
      begin
 
224
        native_group.SetInfo unless native_group.nil?
 
225
      rescue Exception => e
 
226
        raise Puppet::Error.new( "Group update failed: #{e}" )
 
227
      end
 
228
      self
 
229
    end
 
230
 
 
231
    def add_members(*names)
 
232
      names.each do |name|
 
233
        native_group.Add(Puppet::Util::ADSI::User.uri(name))
 
234
      end
 
235
    end
 
236
    alias add_member add_members
 
237
 
 
238
    def remove_members(*names)
 
239
      names.each do |name|
 
240
        native_group.Remove(Puppet::Util::ADSI::User.uri(name))
 
241
      end
 
242
    end
 
243
    alias remove_member remove_members
 
244
 
 
245
    def members
 
246
      # WIN32OLE objects aren't enumerable, so no map
 
247
      members = []
 
248
      native_group.Members.each {|m| members << m.Name}
 
249
      members
 
250
    end
 
251
 
 
252
    def set_members(desired_members)
 
253
      return if desired_members.nil? or desired_members.empty?
 
254
 
 
255
      current_members = self.members
 
256
 
 
257
      # First we add all missing members
 
258
      members_to_add = desired_members - current_members
 
259
      add_members(*members_to_add)
 
260
 
 
261
      # Then we remove all extra members
 
262
      members_to_remove = current_members - desired_members
 
263
      remove_members(*members_to_remove)
 
264
    end
 
265
 
 
266
    def self.create(name)
 
267
      new(name, Puppet::Util::ADSI.create(name, 'group'))
 
268
    end
 
269
 
 
270
    def self.exists?(name)
 
271
      Puppet::Util::ADSI.connectable?(Group.uri(name))
 
272
    end
 
273
 
 
274
    def self.delete(name)
 
275
      Puppet::Util::ADSI.delete(name, 'group')
 
276
    end
 
277
 
 
278
    def self.each(&block)
 
279
      wql = Puppet::Util::ADSI.execquery( "select * from win32_group" )
 
280
 
 
281
      groups = []
 
282
      wql.each do |g|
 
283
        groups << new(g.name, g)
 
284
      end
 
285
 
 
286
      groups.each(&block)
 
287
    end
 
288
  end
 
289
end