sys-admin 1.5.4-x86-mingw32 → 1.5.5-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,11 @@
1
+ == 1.5.5 - 5-Jul-2011
2
+ * Modified lastlog handling, and ignore getpwent_r and getgrent_r, on AIX.
3
+ Thanks go to Rick Ohnemus for the spot and patches.
4
+ * Explicitly set spec.cpu on Windows to 'universal' in the gem creation task.
5
+ * Fixed a bug in the User.get_login and User.get_group methods where the query
6
+ being generated was incorrect if no options were passed. Thanks go to
7
+ Matthew Brown for the spot.
8
+
1
9
  == 1.5.4 - 7-Oct-2010
2
10
  * Prefer the getlastlogx() function over lastlog() where supported.
3
11
 
data/Rakefile CHANGED
@@ -2,21 +2,19 @@ require 'rake'
2
2
  require 'rake/clean'
3
3
  require 'rake/testtask'
4
4
  require 'rbconfig'
5
+ include Config
5
6
 
6
- WINDOWS = Config::CONFIG['host_os'] =~ /msdos|mswin|win32|mingw|cygwin/i
7
+ WINDOWS = CONFIG['host_os'] =~ /msdos|mswin|win32|mingw|cygwin|windows/i
7
8
 
8
- desc "Clean the build files for the sys-admin source for UNIX systems"
9
- task :clean do
10
- Dir['*.gem'].each{ |f| File.delete(f) } # Remove any .gem files
11
- unless WINDOWS
12
- Dir.chdir('ext') do
13
- rm_rf('conftest.dSYM') if File.exists?('conftest.dSYM') # OS X
14
- build_file = 'admin.' + Config::CONFIG['DLEXT']
15
- sh 'make distclean' if File.exists?(build_file)
16
- File.delete("sys/#{build_file}") if File.exists?("sys/#{build_file}")
17
- end
18
- end
19
- end
9
+ CLEAN.include(
10
+ '**/*.gem', # Gem files
11
+ '**/*.rbc', # Rubinius
12
+ '**/*.o', # C object file
13
+ '**/*.log', # Ruby extension build log
14
+ '**/Makefile', # C Makefile
15
+ '**/conftest.dSYM', # OS X build directory
16
+ "**/*.#{CONFIG['DLEXT']}" # C shared object
17
+ )
20
18
 
21
19
  desc "Build the sys-admin library on UNIX systems (but don't install it)"
22
20
  task :build => [:clean] do
@@ -37,6 +35,7 @@ namespace :gem do
37
35
 
38
36
  if WINDOWS
39
37
  spec.platform = Gem::Platform::CURRENT
38
+ spec.platform.cpu = 'universal'
40
39
  spec.files = spec.files.reject{ |f| f.include?('ext') }
41
40
  spec.add_dependency('win32-security', '>= 0.1.2')
42
41
  else
data/lib/sys/admin.rb CHANGED
@@ -4,977 +4,985 @@ require 'win32/registry'
4
4
  require 'socket'
5
5
 
6
6
  module Sys
7
- class Group
8
- # Short description of the object.
9
- attr_accessor :caption
10
-
11
- # Description of the group.
12
- attr_accessor :description
13
-
14
- # Name of the Windows domain to which the group account belongs.
15
- attr_accessor :domain
16
-
17
- # Date the group was added.
18
- attr_accessor :install_date
19
-
20
- # Name of the Windows group account on the Group#domain specified.
21
- attr_accessor :name
22
-
23
- # Security identifier for this group.
24
- attr_accessor :sid
25
-
26
- # Current status for the group, such as "ok", "error", etc.
27
- attr_accessor :status
28
-
29
- # The group ID.
30
- attr_accessor :gid
31
-
32
- # Sets whether or not the group is local (as opposed to global).
33
- attr_writer :local
34
-
35
- # An array of members for that group. May contain SID's.
36
- attr_accessor :members
37
-
38
- # Creates and returns a new Group object. This class encapsulates
39
- # the information for a group account, whether it be global or local.
40
- #
41
- # Yields +self+ if a block is given.
42
- #
43
- def initialize
44
- yield self if block_given?
45
- end
7
+ class Group
8
+ # Short description of the object.
9
+ attr_accessor :caption
10
+
11
+ # Description of the group.
12
+ attr_accessor :description
13
+
14
+ # Name of the Windows domain to which the group account belongs.
15
+ attr_accessor :domain
16
+
17
+ # Date the group was added.
18
+ attr_accessor :install_date
19
+
20
+ # Name of the Windows group account on the Group#domain specified.
21
+ attr_accessor :name
22
+
23
+ # Security identifier for this group.
24
+ attr_accessor :sid
25
+
26
+ # Current status for the group, such as "ok", "error", etc.
27
+ attr_accessor :status
28
+
29
+ # The group ID.
30
+ attr_accessor :gid
31
+
32
+ # Sets whether or not the group is local (as opposed to global).
33
+ attr_writer :local
34
+
35
+ # An array of members for that group. May contain SID's.
36
+ attr_accessor :members
37
+
38
+ # Creates and returns a new Group object. This class encapsulates
39
+ # the information for a group account, whether it be global or local.
40
+ #
41
+ # Yields +self+ if a block is given.
42
+ #
43
+ def initialize
44
+ yield self if block_given?
45
+ end
46
+
47
+ # Returns whether or not the group is a local group.
48
+ #
49
+ def local?
50
+ @local
51
+ end
52
+
53
+ # Returns the type of SID (Security Identifier) as a stringified value.
54
+ #
55
+ def sid_type
56
+ @sid_type
57
+ end
46
58
 
47
- # Returns whether or not the group is a local group.
48
- #
49
- def local?
50
- @local
51
- end
52
-
53
- # Returns the type of SID (Security Identifier) as a stringified value.
54
- #
55
- def sid_type
56
- @sid_type
57
- end
58
-
59
- # Sets the SID (Security Identifier) type to +stype+, which can be
60
- # one of the following constant values:
61
- #
62
- # * Admin::SidTypeUser
63
- # * Admin::SidTypeGroup
64
- # * Admin::SidTypeDomain
65
- # * Admin::SidTypeAlias
66
- # * Admin::SidTypeWellKnownGroup
67
- # * Admin::SidTypeDeletedAccount
68
- # * Admin::SidTypeInvalid
69
- # * Admin::SidTypeUnknown
70
- # * Admin::SidTypeComputer
71
- #
72
- def sid_type=(stype)
73
- if stype.kind_of?(String)
74
- @sid_type = stype.downcase
75
- else
76
- case stype
77
- when Admin::SidTypeUser
78
- @sid_type = "user"
79
- when Admin::SidTypeGroup
80
- @sid_type = "group"
81
- when Admin::SidTypeDomain
82
- @sid_type = "domain"
83
- when Admin::SidTypeAlias
84
- @sid_type = "alias"
85
- when Admin::SidTypeWellKnownGroup
86
- @sid_type = "well_known_group"
87
- when Admin::SidTypeDeletedAccount
88
- @sid_type = "deleted_account"
89
- when Admin::SidTypeInvalid
90
- @sid_type = "invalid"
91
- when Admin::SidTypeUnknown
92
- @sid_type = "unknown"
93
- when Admin::SidTypeComputer
94
- @sid_type = "computer"
95
- else
96
- @sid_type = "unknown"
97
- end
59
+ # Sets the SID (Security Identifier) type to +stype+, which can be
60
+ # one of the following constant values:
61
+ #
62
+ # * Admin::SidTypeUser
63
+ # * Admin::SidTypeGroup
64
+ # * Admin::SidTypeDomain
65
+ # * Admin::SidTypeAlias
66
+ # * Admin::SidTypeWellKnownGroup
67
+ # * Admin::SidTypeDeletedAccount
68
+ # * Admin::SidTypeInvalid
69
+ # * Admin::SidTypeUnknown
70
+ # * Admin::SidTypeComputer
71
+ #
72
+ def sid_type=(stype)
73
+ if stype.kind_of?(String)
74
+ @sid_type = stype.downcase
75
+ else
76
+ case stype
77
+ when Admin::SidTypeUser
78
+ @sid_type = "user"
79
+ when Admin::SidTypeGroup
80
+ @sid_type = "group"
81
+ when Admin::SidTypeDomain
82
+ @sid_type = "domain"
83
+ when Admin::SidTypeAlias
84
+ @sid_type = "alias"
85
+ when Admin::SidTypeWellKnownGroup
86
+ @sid_type = "well_known_group"
87
+ when Admin::SidTypeDeletedAccount
88
+ @sid_type = "deleted_account"
89
+ when Admin::SidTypeInvalid
90
+ @sid_type = "invalid"
91
+ when Admin::SidTypeUnknown
92
+ @sid_type = "unknown"
93
+ when Admin::SidTypeComputer
94
+ @sid_type = "computer"
95
+ else
96
+ @sid_type = "unknown"
98
97
  end
99
- @sid_type
100
- end
101
- end
98
+ end
99
+ @sid_type
100
+ end
101
+ end
102
102
 
103
- class User
104
- # An account for users whose primary account is in another domain.
105
- TEMP_DUPLICATE = 0x0100
106
-
107
- # Default account type that represents a typical user.
108
- NORMAL = 0x0200
109
-
110
- # A permit to trust account for a domain that trusts other domains.
111
- INTERDOMAIN_TRUST = 0x0800
103
+ class User
104
+ # An account for users whose primary account is in another domain.
105
+ TEMP_DUPLICATE = 0x0100
106
+
107
+ # Default account type that represents a typical user.
108
+ NORMAL = 0x0200
109
+
110
+ # A permit to trust account for a domain that trusts other domains.
111
+ INTERDOMAIN_TRUST = 0x0800
112
+
113
+ # An account for a Windows NT/2000 workstation or server that is a
114
+ # member of this domain.
115
+ WORKSTATION_TRUST = 0x1000
116
+
117
+ # A computer account for a backup domain controller that is a member
118
+ # of this domain.
119
+ SERVER_TRUST = 0x2000
120
+
121
+ # Domain and username of the account.
122
+ attr_accessor :caption
123
+
124
+ # Description of the account.
125
+ attr_accessor :description
126
+
127
+ # Name of the Windows domain to which a user account belongs.
128
+ attr_accessor :domain
129
+
130
+ # The user's password.
131
+ attr_accessor :password
132
+
133
+ # Full name of a local user.
134
+ attr_accessor :full_name
135
+
136
+ # An array of groups to which the user belongs.
137
+ attr_accessor :groups
138
+
139
+ # Date the user account was created.
140
+ attr_accessor :install_date
141
+
142
+ # Name of the Windows user account on the domain that the User#domain
143
+ # property specifies.
144
+ attr_accessor :name
145
+
146
+ # The user's security identifier.
147
+ attr_accessor :sid
148
+
149
+ # Current status for the user, such as "ok", "error", etc.
150
+ attr_accessor :status
151
+
152
+ # The user's id (RID).
153
+ attr_accessor :uid
154
+
155
+ # The user's home directory
156
+ attr_accessor :dir
157
+
158
+ # Used to set whether or not the account is disabled.
159
+ attr_writer :disabled
160
+
161
+ # Sets whether or not the account is defined on the local computer.
162
+ attr_writer :local
163
+
164
+ # Sets whether or not the account is locked out of the OS.
165
+ attr_writer :lockout
166
+
167
+ # Sets whether or not the password for the account can be changed.
168
+ attr_writer :password_changeable
169
+
170
+ # Sets whether or not the password for the account expires.
171
+ attr_writer :password_expires
172
+
173
+ # Sets whether or not a password is required for the account.
174
+ attr_writer :password_required
175
+
176
+ # Returns the account type as a human readable string.
177
+ attr_reader :account_type
112
178
 
113
- # An account for a Windows NT/2000 workstation or server that is a
114
- # member of this domain.
115
- WORKSTATION_TRUST = 0x1000
179
+ # Creates an returns a new User object. A User object encapsulates a
180
+ # user account on the operating system.
181
+ #
182
+ # Yields +self+ if a block is provided.
183
+ #
184
+ def initialize
185
+ yield self if block_given?
186
+ end
116
187
 
117
- # A computer account for a backup domain controller that is a member
118
- # of this domain.
119
- SERVER_TRUST = 0x2000
120
-
121
- # Domain and username of the account.
122
- attr_accessor :caption
123
-
124
- # Description of the account.
125
- attr_accessor :description
126
-
127
- # Name of the Windows domain to which a user account belongs.
128
- attr_accessor :domain
129
-
130
- # The user's password.
131
- attr_accessor :password
132
-
133
- # Full name of a local user.
134
- attr_accessor :full_name
135
-
136
- # An array of groups to which the user belongs.
137
- attr_accessor :groups
138
-
139
- # Date the user account was created.
140
- attr_accessor :install_date
141
-
142
- # Name of the Windows user account on the domain that the User#domain
143
- # property specifies.
144
- attr_accessor :name
145
-
146
- # The user's security identifier.
147
- attr_accessor :sid
148
-
149
- # Current status for the user, such as "ok", "error", etc.
150
- attr_accessor :status
151
-
152
- # The user's id (RID).
153
- attr_accessor :uid
154
-
155
- # The user's home directory
156
- attr_accessor :dir
157
-
158
- # Used to set whether or not the account is disabled.
159
- attr_writer :disabled
160
-
161
- # Sets whether or not the account is defined on the local computer.
162
- attr_writer :local
163
-
164
- # Sets whether or not the account is locked out of the OS.
165
- attr_writer :lockout
166
-
167
- # Sets whether or not the password for the account can be changed.
168
- attr_writer :password_changeable
169
-
170
- # Sets whether or not the password for the account expires.
171
- attr_writer :password_expires
172
-
173
- # Sets whether or not a password is required for the account.
174
- attr_writer :password_required
175
-
176
- # Returns the account type as a human readable string.
177
- attr_reader :account_type
178
-
179
- # Creates an returns a new User object. A User object encapsulates a
180
- # user account on the operating system.
181
- #
182
- # Yields +self+ if a block is provided.
183
- #
184
- def initialize
185
- yield self if block_given?
186
- end
187
-
188
- # Sets the account type for the account. Possible values are:
189
- #
190
- # * User::TEMP_DUPLICATE
191
- # * User::NORMAL
192
- # * User::INTERDOMAIN_TRUST
193
- # * User::WORKSTATION_TRUST
194
- # * User::SERVER_TRUST
195
- #
196
- def account_type=(type)
197
- case type
198
- when TEMP_DUPLICATE
199
- @account_type = 'duplicate'
200
- when NORMAL
201
- @account_type = 'normal'
202
- when INTERDOMAIN_TRUST
203
- @account_type = 'interdomain_trust'
204
- when WORKSTATION_TRUST
205
- @account_type = 'workstation_trust'
206
- when SERVER_TRUST
207
- @account_type = 'server_trust'
208
- else
209
- @account_type = 'unknown'
210
- end
188
+ # Sets the account type for the account. Possible values are:
189
+ #
190
+ # * User::TEMP_DUPLICATE
191
+ # * User::NORMAL
192
+ # * User::INTERDOMAIN_TRUST
193
+ # * User::WORKSTATION_TRUST
194
+ # * User::SERVER_TRUST
195
+ #
196
+ def account_type=(type)
197
+ case type
198
+ when TEMP_DUPLICATE
199
+ @account_type = 'duplicate'
200
+ when NORMAL
201
+ @account_type = 'normal'
202
+ when INTERDOMAIN_TRUST
203
+ @account_type = 'interdomain_trust'
204
+ when WORKSTATION_TRUST
205
+ @account_type = 'workstation_trust'
206
+ when SERVER_TRUST
207
+ @account_type = 'server_trust'
208
+ else
209
+ @account_type = 'unknown'
211
210
  end
211
+ end
212
212
 
213
- # Returns the SID type as a human readable string.
214
- #
215
- def sid_type
216
- @sid_type
217
- end
213
+ # Returns the SID type as a human readable string.
214
+ #
215
+ def sid_type
216
+ @sid_type
217
+ end
218
218
 
219
- # Sets the SID (Security Identifier) type to +stype+, which can be
220
- # one of the following constant values:
221
- #
222
- # * Admin::SidTypeUser
223
- # * Admin::SidTypeGroup
224
- # * Admin::SidTypeDomain
225
- # * Admin::SidTypeAlias
226
- # * Admin::SidTypeWellKnownGroup
227
- # * Admin::SidTypeDeletedAccount
228
- # * Admin::SidTypeInvalid
229
- # * Admin::SidTypeUnknown
230
- # * Admin::SidTypeComputer
231
- #
232
- def sid_type=(stype)
233
- case stype
234
- when Admin::SidTypeUser
235
- @sid_type = 'user'
236
- when Admin::SidTypeGroup
237
- @sid_type = 'group'
238
- when Admin::SidTypeDomain
239
- @sid_type = 'domain'
240
- when Admin::SidTypeAlias
241
- @sid_type = 'alias'
242
- when Admin::SidTypeWellKnownGroup
243
- @sid_type = 'well_known_group'
244
- when Admin::SidTypeDeletedAccount
245
- @sid_type = 'deleted_account'
246
- when Admin::SidTypeInvalid
247
- @sid_type = 'invalid'
248
- when Admin::SidTypeUnknown
249
- @sid_type = 'unknown'
250
- when Admin::SidTypeComputer
251
- @sid_type = 'computer'
252
- else
253
- @sid_type = 'unknown'
254
- end
255
- end
256
-
257
- # Returns whether or not the account is disabled.
258
- #
259
- def disabled?
260
- @disabled
219
+ # Sets the SID (Security Identifier) type to +stype+, which can be
220
+ # one of the following constant values:
221
+ #
222
+ # * Admin::SidTypeUser
223
+ # * Admin::SidTypeGroup
224
+ # * Admin::SidTypeDomain
225
+ # * Admin::SidTypeAlias
226
+ # * Admin::SidTypeWellKnownGroup
227
+ # * Admin::SidTypeDeletedAccount
228
+ # * Admin::SidTypeInvalid
229
+ # * Admin::SidTypeUnknown
230
+ # * Admin::SidTypeComputer
231
+ #
232
+ def sid_type=(stype)
233
+ case stype
234
+ when Admin::SidTypeUser
235
+ @sid_type = 'user'
236
+ when Admin::SidTypeGroup
237
+ @sid_type = 'group'
238
+ when Admin::SidTypeDomain
239
+ @sid_type = 'domain'
240
+ when Admin::SidTypeAlias
241
+ @sid_type = 'alias'
242
+ when Admin::SidTypeWellKnownGroup
243
+ @sid_type = 'well_known_group'
244
+ when Admin::SidTypeDeletedAccount
245
+ @sid_type = 'deleted_account'
246
+ when Admin::SidTypeInvalid
247
+ @sid_type = 'invalid'
248
+ when Admin::SidTypeUnknown
249
+ @sid_type = 'unknown'
250
+ when Admin::SidTypeComputer
251
+ @sid_type = 'computer'
252
+ else
253
+ @sid_type = 'unknown'
261
254
  end
255
+ end
262
256
 
263
- # Returns whether or not the account is local.
264
- #
265
- def local?
266
- @local
267
- end
268
-
269
- # Returns whether or not the account is locked out.
270
- #
271
- def lockout?
272
- @lockout
273
- end
257
+ # Returns whether or not the account is disabled.
258
+ #
259
+ def disabled?
260
+ @disabled
261
+ end
262
+
263
+ # Returns whether or not the account is local.
264
+ #
265
+ def local?
266
+ @local
267
+ end
268
+
269
+ # Returns whether or not the account is locked out.
270
+ #
271
+ def lockout?
272
+ @lockout
273
+ end
274
274
 
275
- # Returns whether or not the password for the account is changeable.
276
- #
277
- def password_changeable?
278
- @password_changeable
279
- end
280
-
281
- # Returns whether or not the password for the account is changeable.
282
- #
283
- def password_expires?
284
- @password_expires
275
+ # Returns whether or not the password for the account is changeable.
276
+ #
277
+ def password_changeable?
278
+ @password_changeable
279
+ end
280
+
281
+ # Returns whether or not the password for the account is changeable.
282
+ #
283
+ def password_expires?
284
+ @password_expires
285
+ end
286
+
287
+ # Returns whether or not the a password is required for the account.
288
+ #
289
+ def password_required?
290
+ @password_required
291
+ end
292
+ end
293
+
294
+ class Admin
295
+ # The version of the sys-admin library
296
+ VERSION = '1.5.5'
297
+
298
+ # This is the error raised in the majority of cases if anything goes wrong
299
+ # with any of the Sys::Admin methods.
300
+ #
301
+ class Error < StandardError; end
302
+
303
+ SidTypeUser = 1
304
+ SidTypeGroup = 2
305
+ SidTypeDomain = 3
306
+ SidTypeAlias = 4
307
+ SidTypeWellKnownGroup = 5
308
+ SidTypeDeletedAccount = 6
309
+ SidTypeInvalid = 7
310
+ SidTypeUnknown = 8
311
+ SidTypeComputer = 9
312
+
313
+ private
314
+
315
+ HKEY = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"
316
+
317
+ # Retrieves the user's home directory. For local accounts query the
318
+ # registry. For domain accounts use ADSI and use the HomeDirectory.
319
+ #
320
+ def self.get_home_dir(user, local = false, domain = nil)
321
+ if local
322
+ sec = Win32::Security::SID.open(user)
323
+ key = HKEY + sec.to_s
324
+ dir = nil
325
+
326
+ begin
327
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |reg|
328
+ dir = reg['ProfileImagePath']
329
+ end
330
+ rescue Win32::Registry::Error
331
+ # Not every local user has a home directory
332
+ end
333
+ else
334
+ domain ||= Socket.gethostname
335
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{user},user")
336
+ dir = adsi.get('HomeDirectory')
285
337
  end
338
+
339
+ dir
340
+ end
341
+
342
+ # A private method that lower cases all keys, and converts them
343
+ # all to symbols.
344
+ #
345
+ def self.munge_options(opts)
346
+ rhash = {}
347
+
348
+ opts.each{ |k, v|
349
+ k = k.to_s.downcase.to_sym
350
+ rhash[k] = v
351
+ }
352
+
353
+ rhash
354
+ end
355
+
356
+ # An internal, private method for getting a list of groups for
357
+ # a particular user.
358
+ #
359
+ def self.get_groups(domain, user)
360
+ array = []
361
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{user}")
362
+ adsi.groups.each{ |g| array << g.name }
363
+ array
364
+ end
365
+
366
+ # An internal, private method for getting a list of members for
367
+ # any particular group.
368
+ #
369
+ def self.get_members(domain, group)
370
+ array = []
371
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{group}")
372
+ adsi.members.each{ |g| array << g.name }
373
+ array
374
+ end
286
375
 
287
- # Returns whether or not the a password is required for the account.
288
- #
289
- def password_required?
290
- @password_required
291
- end
292
- end
293
-
294
- class Admin
295
- # The version of the sys-admin library
296
- VERSION = '1.5.4'
297
-
298
- # This is the error raised in the majority of cases if anything goes wrong
299
- # with any of the Sys::Admin methods.
300
- #
301
- class Error < StandardError; end
302
-
303
- SidTypeUser = 1
304
- SidTypeGroup = 2
305
- SidTypeDomain = 3
306
- SidTypeAlias = 4
307
- SidTypeWellKnownGroup = 5
308
- SidTypeDeletedAccount = 6
309
- SidTypeInvalid = 7
310
- SidTypeUnknown = 8
311
- SidTypeComputer = 9
312
-
313
- private
314
-
315
- HKEY = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"
316
-
317
- # Retrieves the user's home directory. For local accounts query the
318
- # registry. For domain accounts use ADSI and use the HomeDirectory.
319
- #
320
- def self.get_home_dir(user, local = false, domain = nil)
321
- if local
322
- sec = Win32::Security::SID.open(user)
323
- key = HKEY + sec.to_s
324
- dir = nil
325
-
326
- begin
327
- Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |reg|
328
- dir = reg['ProfileImagePath']
329
- end
330
- rescue Win32::Registry::Error
331
- # Not every local user has a home directory
332
- end
333
- else
334
- domain ||= Socket.gethostname
335
- adsi = WIN32OLE.connect("WinNT://#{domain}/#{user},user")
336
- dir = adsi.get('HomeDirectory')
337
- end
338
-
339
- dir
376
+ # Used by the get_login method
377
+ GetUserName = Win32::API.new('GetUserName', 'PP', 'L', 'advapi32') # :nodoc:
378
+
379
+ public
380
+
381
+ # Creates the given +user+. If no domain option is specified,
382
+ # then it defaults to your local host, i.e. a local account is
383
+ # created.
384
+ #
385
+ # Any options provided are treated as IADsUser interface methods
386
+ # and are called before SetInfo is finally called.
387
+ #
388
+ # Examples:
389
+ #
390
+ # # Create a local user with no options
391
+ # Sys::Admin.add_user(:name => 'asmith')
392
+ #
393
+ # # Create a local user with options
394
+ # Sys::Admin.add_user(
395
+ # :name => 'asmith',
396
+ # :description => 'Really cool guy',
397
+ # :password => 'abc123'
398
+ # )
399
+ #
400
+ # # Create a user on a specific domain
401
+ # Sys::Admin.add_user(
402
+ # :name => 'asmith',
403
+ # :domain => 'XX',
404
+ # :fullname => 'Al Smith'
405
+ # )
406
+ #--
407
+ # Most options are passed to the 'put' method. However, we handle the
408
+ # password specially since it's a separate method, and some environments
409
+ # require that it be set up front.
410
+ #
411
+ def self.add_user(options = {})
412
+ options = munge_options(options)
413
+
414
+ name = options.delete(:name) or raise ArgumentError, 'No user given'
415
+ domain = options[:domain]
416
+
417
+ if domain.nil?
418
+ domain = Socket.gethostname
419
+ moniker = "WinNT://#{domain},Computer"
420
+ else
421
+ moniker = "WinNT://#{domain}"
340
422
  end
341
423
 
342
- # A private method that lower cases all keys, and converts them
343
- # all to symbols.
344
- #
345
- def self.munge_options(opts)
346
- rhash = {}
347
-
348
- opts.each{ |k, v|
349
- k = k.to_s.downcase.to_sym
350
- rhash[k] = v
351
- }
352
-
353
- rhash
424
+ begin
425
+ adsi = WIN32OLE.connect(moniker)
426
+ user = adsi.create('user', name)
427
+ options.each{ |option, value|
428
+ if option.to_s == 'password'
429
+ user.setpassword(value)
430
+ else
431
+ user.put(option.to_s, value)
432
+ end
433
+ }
434
+ user.setinfo
435
+ rescue WIN32OLERuntimeError => err
436
+ raise Error, err
354
437
  end
355
-
356
- # An internal, private method for getting a list of groups for
357
- # a particular user.
358
- #
359
- def self.get_groups(domain, user)
360
- array = []
361
- adsi = WIN32OLE.connect("WinNT://#{domain}/#{user}")
362
- adsi.groups.each{ |g| array << g.name }
363
- array
438
+ end
439
+
440
+ # Configures the +user+ using +options+. If no domain option is
441
+ # specified then your local host is used, i.e. you are configuring
442
+ # a local user account.
443
+ #
444
+ # See http://tinyurl.com/3hjv9 for a list of valid options.
445
+ #
446
+ # In the case of a password change, pass a two element array as the
447
+ # old value and new value.
448
+ #
449
+ # Examples:
450
+ #
451
+ # # Configure a local user
452
+ # Sys::Admin.configure_user(
453
+ # :name => 'djberge',
454
+ # :description => 'Awesome'
455
+ # )
456
+ #
457
+ # # Change the password
458
+ # Sys::Admin.configure_user(
459
+ # :name => 'asmith',
460
+ # :password => [old_pass, new_pass]
461
+ # )
462
+ #
463
+ # # Configure a user on a specific domain
464
+ # Sys::Admin.configure_user(
465
+ # :name => 'jsmrz',
466
+ # :domain => 'XX',
467
+ # :firstname => 'Jo'
468
+ # )
469
+ #
470
+ def self.configure_user(options = {})
471
+ options = munge_options(options)
472
+
473
+ name = options.delete(:name) or raise ArgumentError, 'No name given'
474
+ domain = options[:domain] || Socket.gethostname
475
+
476
+ begin
477
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{name},user")
478
+ options.each{ |option, value|
479
+ if option.to_s == 'password'
480
+ adsi.changepassword(value[0], value[1])
481
+ else
482
+ adsi.put(option.to_s, value)
483
+ end
484
+ }
485
+ adsi.setinfo
486
+ rescue WIN32OLERuntimeError => err
487
+ raise Error, err
364
488
  end
365
-
366
- # An internal, private method for getting a list of members for
367
- # any particular group.
368
- #
369
- def self.get_members(domain, group)
370
- array = []
371
- adsi = WIN32OLE.connect("WinNT://#{domain}/#{group}")
372
- adsi.members.each{ |g| array << g.name }
373
- array
489
+ end
490
+
491
+ # Deletes the given +user+ on +domain+. If no domain is specified,
492
+ # then it defaults to your local host, i.e. a local account is
493
+ # deleted.
494
+ #
495
+ def self.delete_user(user, domain = nil)
496
+ if domain.nil?
497
+ domain = Socket.gethostname
498
+ moniker = "WinNT://#{domain},Computer"
499
+ else
500
+ moniker = "WinNT://#{domain}"
374
501
  end
375
-
376
- # Used by the get_login method
377
- GetUserName = Win32::API.new('GetUserName', 'PP', 'L', 'advapi32') # :nodoc:
378
-
379
- public
380
-
381
- # Creates the given +user+. If no domain option is specified,
382
- # then it defaults to your local host, i.e. a local account is
383
- # created.
384
- #
385
- # Any options provided are treated as IADsUser interface methods
386
- # and are called before SetInfo is finally called.
387
- #
388
- # Examples:
389
- #
390
- # # Create a local user with no options
391
- # Sys::Admin.add_user(:name => 'asmith')
392
- #
393
- # # Create a local user with options
394
- # Sys::Admin.add_user(
395
- # :name => 'asmith',
396
- # :description => 'Really cool guy',
397
- # :password => 'abc123'
398
- # )
399
- #
400
- # # Create a user on a specific domain
401
- # Sys::Admin.add_user(
402
- # :name => 'asmith',
403
- # :domain => 'XX',
404
- # :fullname => 'Al Smith'
405
- # )
406
- #--
407
- # Most options are passed to the 'put' method. However, we handle the
408
- # password specially since it's a separate method, and some environments
409
- # require that it be set up front.
410
- #
411
- def self.add_user(options = {})
412
- options = munge_options(options)
413
-
414
- name = options.delete(:name) or raise ArgumentError, 'No user given'
415
- domain = options[:domain]
416
-
417
- if domain.nil?
418
- domain = Socket.gethostname
419
- moniker = "WinNT://#{domain},Computer"
420
- else
421
- moniker = "WinNT://#{domain}"
422
- end
423
502
 
424
- begin
425
- adsi = WIN32OLE.connect(moniker)
426
- user = adsi.create('user', name)
427
- options.each{ |option, value|
428
- if option.to_s == 'password'
429
- user.setpassword(value)
430
- else
431
- user.put(option.to_s, value)
432
- end
433
- }
434
- user.setinfo
435
- rescue WIN32OLERuntimeError => err
436
- raise Error, err
437
- end
503
+ begin
504
+ adsi = WIN32OLE.connect(moniker)
505
+ adsi.delete('user', user)
506
+ rescue WIN32OLERuntimeError => err
507
+ raise Error, err
438
508
  end
439
-
440
- # Configures the +user+ using +options+. If no domain option is
441
- # specified then your local host is used, i.e. you are configuring
442
- # a local user account.
443
- #
444
- # See http://tinyurl.com/3hjv9 for a list of valid options.
445
- #
446
- # In the case of a password change, pass a two element array as the
447
- # old value and new value.
448
- #
449
- # Examples:
450
- #
451
- # # Configure a local user
452
- # Sys::Admin.configure_user(
453
- # :name => 'djberge',
454
- # :description => 'Awesome'
455
- # )
456
- #
457
- # # Change the password
458
- # Sys::Admin.configure_user(
459
- # :name => 'asmith',
460
- # :password => [old_pass, new_pass]
461
- # )
462
- #
463
- # # Configure a user on a specific domain
464
- # Sys::Admin.configure_user(
465
- # :name => 'jsmrz',
466
- # :domain => 'XX',
467
- # :firstname => 'Jo'
468
- # )
469
- #
470
- def self.configure_user(options = {})
471
- options = munge_options(options)
472
-
473
- name = options.delete(:name) or raise ArgumentError, 'No name given'
474
- domain = options[:domain] || Socket.gethostname
475
-
476
- begin
477
- adsi = WIN32OLE.connect("WinNT://#{domain}/#{name},user")
478
- options.each{ |option, value|
479
- if option.to_s == 'password'
480
- adsi.changepassword(value[0], value[1])
481
- else
482
- adsi.put(option.to_s, value)
483
- end
484
- }
485
- adsi.setinfo
486
- rescue WIN32OLERuntimeError => err
487
- raise Error, err
488
- end
509
+ end
510
+
511
+ # Create a new +group+ using +options+. If no domain option is specified
512
+ # then a local group is created instead.
513
+ #
514
+ # Examples:
515
+ #
516
+ # # Create a local group with no options
517
+ # Sys::Admin.add_group(:name => 'Dudes')
518
+ #
519
+ # # Create a local group with options
520
+ # Sys::Admin.add_group(:name => 'Dudes', :description => 'Boys')
521
+ #
522
+ # # Create a group on a specific domain
523
+ # Sys::Admin.add_group(
524
+ # :name => 'Ladies',
525
+ # :domain => 'XYZ',
526
+ # :description => 'Girls'
527
+ # )
528
+ #
529
+ def self.add_group(options = {})
530
+ options = munge_options(options)
531
+
532
+ group = options.delete(:name) or raise ArgumentError, 'No name given'
533
+ domain = options[:domain]
534
+
535
+ if domain.nil?
536
+ domain = Socket.gethostname
537
+ moniker = "WinNT://#{domain},Computer"
538
+ else
539
+ moniker = "WinNT://#{domain}"
489
540
  end
490
541
 
491
- # Deletes the given +user+ on +domain+. If no domain is specified,
492
- # then it defaults to your local host, i.e. a local account is
493
- # deleted.
494
- #
495
- def self.delete_user(user, domain = nil)
496
- if domain.nil?
497
- domain = Socket.gethostname
498
- moniker = "WinNT://#{domain},Computer"
499
- else
500
- moniker = "WinNT://#{domain}"
501
- end
502
-
503
- begin
504
- adsi = WIN32OLE.connect(moniker)
505
- adsi.delete('user', user)
506
- rescue WIN32OLERuntimeError => err
507
- raise Error, err
508
- end
542
+ begin
543
+ adsi = WIN32OLE.connect(moniker)
544
+ group = adsi.create('group', group)
545
+ group.setinfo
546
+ configure_group(options) unless options.empty?
547
+ rescue WIN32OLERuntimeError => err
548
+ raise Error, err
509
549
  end
510
-
511
- # Create a new +group+ using +options+. If no domain option is specified
512
- # then a local group is created instead.
513
- #
514
- # Examples:
515
- #
516
- # # Create a local group with no options
517
- # Sys::Admin.add_group(:name => 'Dudes')
518
- #
519
- # # Create a local group with options
520
- # Sys::Admin.add_group(:name => 'Dudes', :description => 'Boys')
521
- #
522
- # # Create a group on a specific domain
523
- # Sys::Admin.add_group(
524
- # :name => 'Ladies',
525
- # :domain => 'XYZ',
526
- # :description => 'Girls'
527
- # )
528
- #
529
- def self.add_group(options = {})
530
- options = munge_options(options)
531
-
532
- group = options.delete(:name) or raise ArgumentError, 'No name given'
533
- domain = options[:domain]
534
-
535
- if domain.nil?
536
- domain = Socket.gethostname
537
- moniker = "WinNT://#{domain},Computer"
538
- else
539
- moniker = "WinNT://#{domain}"
540
- end
541
-
542
- begin
543
- adsi = WIN32OLE.connect(moniker)
544
- group = adsi.create('group', group)
545
- group.setinfo
546
- configure_group(options) unless options.empty?
547
- rescue WIN32OLERuntimeError => err
548
- raise Error, err
549
- end
550
+ end
551
+
552
+ # Configures the +group+ using +options+. If no domain option is
553
+ # specified then your local host is used, i.e. you are configuring
554
+ # a local group.
555
+ #
556
+ # See http://tinyurl.com/cjkzl for a list of valid options.
557
+ #
558
+ # Examples:
559
+ #
560
+ # # Configure a local group.
561
+ # Sys::Admin.configure_group(:name => 'Abba', :description => 'Swedish')
562
+ #
563
+ # # Configure a group on a specific domain.
564
+ # Sys::Admin.configure_group(
565
+ # :name => 'Web Team',
566
+ # :domain => 'Foo',
567
+ # :description => 'Web programming cowboys'
568
+ # )
569
+ #
570
+ def self.configure_group(options = {})
571
+ options = munge_options(options)
572
+
573
+ group = options.delete(:name) or raise ArgumentError, 'No name given'
574
+ domain = options[:domain] || Socket.gethostname
575
+
576
+ begin
577
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{group},group")
578
+ options.each{ |option, value| adsi.put(option.to_s, value) }
579
+ adsi.setinfo
580
+ rescue WIN32OLERuntimeError => err
581
+ raise Error, err
550
582
  end
551
-
552
- # Configures the +group+ using +options+. If no domain option is
553
- # specified then your local host is used, i.e. you are configuring
554
- # a local group.
555
- #
556
- # See http://tinyurl.com/cjkzl for a list of valid options.
557
- #
558
- # Examples:
559
- #
560
- # # Configure a local group.
561
- # Sys::Admin.configure_group(:name => 'Abba', :description => 'Swedish')
562
- #
563
- # # Configure a group on a specific domain.
564
- # Sys::Admin.configure_group(
565
- # :name => 'Web Team',
566
- # :domain => 'Foo',
567
- # :description => 'Web programming cowboys'
568
- # )
569
- #
570
- def self.configure_group(options = {})
571
- options = munge_options(options)
572
-
573
- group = options.delete(:name) or raise ArgumentError, 'No name given'
574
- domain = options[:domain] || Socket.gethostname
575
-
576
- begin
577
- adsi = WIN32OLE.connect("WinNT://#{domain}/#{group},group")
578
- options.each{ |option, value| adsi.put(option.to_s, value) }
579
- adsi.setinfo
580
- rescue WIN32OLERuntimeError => err
581
- raise Error, err
582
- end
583
+ end
584
+
585
+ # Delete the +group+ from +domain+. If no domain is specified, then
586
+ # you are deleting a local group.
587
+ #
588
+ def self.delete_group(group, domain = nil)
589
+ if domain.nil?
590
+ domain = Socket.gethostname
591
+ moniker = "WinNT://#{domain},Computer"
592
+ else
593
+ moniker = "WinNT://#{domain}"
583
594
  end
584
595
 
585
- # Delete the +group+ from +domain+. If no domain is specified, then
586
- # you are deleting a local group.
587
- #
588
- def self.delete_group(group, domain = nil)
589
- if domain.nil?
590
- domain = Socket.gethostname
591
- moniker = "WinNT://#{domain},Computer"
592
- else
593
- moniker = "WinNT://#{domain}"
594
- end
595
-
596
- begin
597
- adsi = WIN32OLE.connect(moniker)
598
- obj = adsi.delete('group', group)
599
- rescue WIN32OLERuntimeError => err
600
- raise Error, err
601
- end
596
+ begin
597
+ adsi = WIN32OLE.connect(moniker)
598
+ obj = adsi.delete('group', group)
599
+ rescue WIN32OLERuntimeError => err
600
+ raise Error, err
602
601
  end
602
+ end
603
603
 
604
- # Returns the user name (only) of the current login.
605
- #
606
- def self.get_login
607
- buffer = 0.chr * 256
608
- nsize = [buffer.size].pack("L")
609
-
610
- if GetUserName.call(buffer, nsize) == 0
611
- raise Error, 'GetUserName() call failed in get_login'
612
- end
613
-
614
- length = nsize.unpack('L')[0]
615
- username = buffer[0 ... length].chop
616
- username
604
+ # Returns the user name (only) of the current login.
605
+ #
606
+ def self.get_login
607
+ buffer = 0.chr * 256
608
+ nsize = [buffer.size].pack("L")
609
+
610
+ if GetUserName.call(buffer, nsize) == 0
611
+ raise Error, 'GetUserName() call failed in get_login'
617
612
  end
618
613
 
619
- # Returns a User object based on either +name+ or +uid+.
620
- #
621
- # call-seq:
622
- # Sys::Admin.get_user(name, options = {})
623
- # Sys::Admin.get_user(uid, options = {})
624
- #
625
- # Looks for +usr+ information based on the options you specify, where
626
- # the +usr+ argument can be either a user name or a RID.
627
- #
628
- # If a 'host' option is specified, information is retrieved from that
629
- # host. Otherwise, the local host is used.
630
- #
631
- # All other options are converted to WQL statements against the
632
- # Win32_UserAccount WMI object. See http://tinyurl.com/by9nvn for a
633
- # list of possible options.
634
- #
635
- # Examples:
636
- #
637
- # # Get a user by name
638
- # Admin.get_user('djberge')
639
- #
640
- # # Get a user by uid
641
- # Admin.get_user(100)
642
- #
643
- # # Get a user on a specific domain
644
- # Admin.get_user('djberge', :domain => 'TEST')
645
- #--
646
- # The reason for keeping the +usr+ variable as a separate argument
647
- # instead of rolling it into the options hash was to keep a unified
648
- # API between the Windows and UNIX versions.
649
- #
650
- def self.get_user(usr, options = {})
651
- options = munge_options(options)
652
-
653
- host = options.delete(:host) || Socket.gethostname
654
- cs = "winmgmts:{impersonationLevel=impersonate}!"
655
- cs << "//#{host}/root/cimv2"
656
-
657
- begin
658
- wmi = WIN32OLE.connect(cs)
659
- rescue WIN32OLERuntimeError => err
660
- raise Error, err
661
- end
662
-
663
- query = "select * from win32_useraccount"
664
-
665
- i = 0
666
-
667
- options.each{ |opt, val|
668
- if i == 0
669
- query << " where #{opt} = '#{val}'"
670
- i += 1
671
- else
672
- query << " and #{opt} = '#{val}'"
673
- end
674
- }
675
-
676
- if usr.kind_of?(Fixnum)
677
- query << " and sid like '%-#{usr}'"
678
- else
679
- query << " and name = '#{usr}'"
680
- end
681
-
682
- domain = options[:domain] || host
683
-
684
- wmi.execquery(query).each{ |user|
685
- uid = user.sid.split('-').last.to_i
686
-
687
- # Because our 'like' query isn't fulproof, let's parse
688
- # the SID again to make sure
689
- if usr.kind_of?(Fixnum)
690
- next if usr != uid
691
- end
692
-
693
- user_object = User.new do |u|
694
- u.account_type = user.accounttype
695
- u.caption = user.caption
696
- u.description = user.description
697
- u.disabled = user.disabled
698
- u.domain = user.domain
699
- u.full_name = user.fullname
700
- u.install_date = user.installdate
701
- u.local = user.localaccount
702
- u.lockout = user.lockout
703
- u.name = user.name
704
- u.password_changeable = user.passwordchangeable
705
- u.password_expires = user.passwordexpires
706
- u.password_required = user.passwordrequired
707
- u.sid = user.sid
708
- u.sid_type = user.sidtype
709
- u.status = user.status
710
- u.uid = uid
711
- u.groups = get_groups(domain, user.name)
712
- u.dir = get_home_dir(user.name, options[:localaccount], domain)
713
- end
714
-
715
- return user_object
716
- }
717
-
718
- # If we're here, it means it wasn't found.
719
- raise Error, "no user found for '#{usr}'"
614
+ length = nsize.unpack('L')[0]
615
+ username = buffer[0 ... length].chop
616
+ username
617
+ end
618
+
619
+ # Returns a User object based on either +name+ or +uid+.
620
+ #
621
+ # call-seq:
622
+ # Sys::Admin.get_user(name, options = {})
623
+ # Sys::Admin.get_user(uid, options = {})
624
+ #
625
+ # Looks for +usr+ information based on the options you specify, where
626
+ # the +usr+ argument can be either a user name or a RID.
627
+ #
628
+ # If a 'host' option is specified, information is retrieved from that
629
+ # host. Otherwise, the local host is used.
630
+ #
631
+ # All other options are converted to WQL statements against the
632
+ # Win32_UserAccount WMI object. See http://tinyurl.com/by9nvn for a
633
+ # list of possible options.
634
+ #
635
+ # Examples:
636
+ #
637
+ # # Get a user by name
638
+ # Admin.get_user('djberge')
639
+ #
640
+ # # Get a user by uid
641
+ # Admin.get_user(100)
642
+ #
643
+ # # Get a user on a specific domain
644
+ # Admin.get_user('djberge', :domain => 'TEST')
645
+ #--
646
+ # The reason for keeping the +usr+ variable as a separate argument
647
+ # instead of rolling it into the options hash was to keep a unified
648
+ # API between the Windows and UNIX versions.
649
+ #
650
+ def self.get_user(usr, options = {})
651
+ options = munge_options(options)
652
+
653
+ host = options.delete(:host) || Socket.gethostname
654
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
655
+ cs << "//#{host}/root/cimv2"
656
+
657
+ begin
658
+ wmi = WIN32OLE.connect(cs)
659
+ rescue WIN32OLERuntimeError => err
660
+ raise Error, err
661
+ end
662
+
663
+ query = "select * from win32_useraccount"
664
+
665
+ i = 0
666
+
667
+ options.each{ |opt, val|
668
+ if i == 0
669
+ query << " where #{opt} = '#{val}'"
670
+ i += 1
671
+ else
672
+ query << " and #{opt} = '#{val}'"
673
+ end
674
+ }
675
+
676
+ if usr.kind_of?(Fixnum)
677
+ query << " and sid like '%-#{usr}'"
678
+ else
679
+ if i > 0
680
+ query << " and name = '#{usr}'"
681
+ else
682
+ query << " where name = '#{usr}'"
683
+ end
720
684
  end
685
+
686
+ domain = options[:domain] || host
687
+
688
+ wmi.execquery(query).each{ |user|
689
+ uid = user.sid.split('-').last.to_i
690
+
691
+ # Because our 'like' query isn't fulproof, let's parse
692
+ # the SID again to make sure
693
+ if usr.kind_of?(Fixnum)
694
+ next if usr != uid
695
+ end
696
+
697
+ user_object = User.new do |u|
698
+ u.account_type = user.accounttype
699
+ u.caption = user.caption
700
+ u.description = user.description
701
+ u.disabled = user.disabled
702
+ u.domain = user.domain
703
+ u.full_name = user.fullname
704
+ u.install_date = user.installdate
705
+ u.local = user.localaccount
706
+ u.lockout = user.lockout
707
+ u.name = user.name
708
+ u.password_changeable = user.passwordchangeable
709
+ u.password_expires = user.passwordexpires
710
+ u.password_required = user.passwordrequired
711
+ u.sid = user.sid
712
+ u.sid_type = user.sidtype
713
+ u.status = user.status
714
+ u.uid = uid
715
+ u.groups = get_groups(domain, user.name)
716
+ u.dir = get_home_dir(user.name, options[:localaccount], domain)
717
+ end
718
+
719
+ return user_object
720
+ }
721
+
722
+ # If we're here, it means it wasn't found.
723
+ raise Error, "no user found for '#{usr}'"
724
+ end
721
725
 
722
- # In block form, yields a User object for each user on the system. In
723
- # non-block form, returns an Array of User objects.
724
- #
725
- # call-seq:
726
- # Sys::Admin.users(options = {})
727
- # Sys::Admin.users(options = {}){ |user| ... }
728
- #
729
- # You may specify a host from which information is retrieved. The
730
- # default is the local host.
731
- #
732
- # All other arguments are passed as WQL query parameters against
733
- # the Win32_UserAccont WMI object.
734
- #
735
- # Examples:
736
- #
737
- # # Get all local account users
738
- # Sys::Admin.users(:localaccount => true)
739
- #
740
- # # Get all user accounts on a specific domain
741
- # Sys::Admin.users(:domain => 'FOO')
742
- #
743
- # # Get a single user from a domain
744
- # Sys::Admin.users(:name => 'djberge', :domain => 'FOO')
745
- #
746
- def self.users(options = {})
747
- options = munge_options(options)
748
-
749
- host = options.delete(:host) || Socket.gethostname
750
- cs = "winmgmts:{impersonationLevel=impersonate}!"
751
- cs << "//#{host}/root/cimv2"
752
-
753
- begin
754
- wmi = WIN32OLE.connect(cs)
755
- rescue WIN32OLERuntimeError => e
756
- raise Error, e
757
- end
758
-
759
- query = "select * from win32_useraccount"
760
-
761
- i = 0
762
-
763
- options.each{ |opt, val|
764
- if i == 0
765
- query << " where #{opt} = '#{val}'"
766
- i += 1
767
- else
768
- query << " and #{opt} = '#{val}'"
769
- end
770
- }
771
-
772
- array = []
773
- domain = options[:domain] || host
774
-
775
- wmi.execquery(query).each{ |user|
776
- uid = user.sid.split('-').last.to_i
777
-
778
- usr = User.new do |u|
779
- u.account_type = user.accounttype
780
- u.caption = user.caption
781
- u.description = user.description
782
- u.disabled = user.disabled
783
- u.domain = user.domain
784
- u.full_name = user.fullname
785
- u.install_date = user.installdate
786
- u.local = user.localaccount
787
- u.lockout = user.lockout
788
- u.name = user.name
789
- u.password_changeable = user.passwordchangeable
790
- u.password_expires = user.passwordexpires
791
- u.password_required = user.passwordrequired
792
- u.sid = user.sid
793
- u.sid_type = user.sidtype
794
- u.status = user.status
795
- u.groups = get_groups(domain, user.name)
796
- u.uid = uid
797
- u.dir = get_home_dir(user.name, options[:localaccount], host)
798
- end
799
-
800
- if block_given?
801
- yield usr
802
- else
803
- array.push(usr)
804
- end
805
- }
806
-
807
- return array unless block_given?
726
+ # In block form, yields a User object for each user on the system. In
727
+ # non-block form, returns an Array of User objects.
728
+ #
729
+ # call-seq:
730
+ # Sys::Admin.users(options = {})
731
+ # Sys::Admin.users(options = {}){ |user| ... }
732
+ #
733
+ # You may specify a host from which information is retrieved. The
734
+ # default is the local host.
735
+ #
736
+ # All other arguments are passed as WQL query parameters against
737
+ # the Win32_UserAccont WMI object.
738
+ #
739
+ # Examples:
740
+ #
741
+ # # Get all local account users
742
+ # Sys::Admin.users(:localaccount => true)
743
+ #
744
+ # # Get all user accounts on a specific domain
745
+ # Sys::Admin.users(:domain => 'FOO')
746
+ #
747
+ # # Get a single user from a domain
748
+ # Sys::Admin.users(:name => 'djberge', :domain => 'FOO')
749
+ #
750
+ def self.users(options = {})
751
+ options = munge_options(options)
752
+
753
+ host = options.delete(:host) || Socket.gethostname
754
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
755
+ cs << "//#{host}/root/cimv2"
756
+
757
+ begin
758
+ wmi = WIN32OLE.connect(cs)
759
+ rescue WIN32OLERuntimeError => e
760
+ raise Error, e
808
761
  end
762
+
763
+ query = "select * from win32_useraccount"
764
+
765
+ i = 0
766
+
767
+ options.each{ |opt, val|
768
+ if i == 0
769
+ query << " where #{opt} = '#{val}'"
770
+ i += 1
771
+ else
772
+ query << " and #{opt} = '#{val}'"
773
+ end
774
+ }
775
+
776
+ array = []
777
+ domain = options[:domain] || host
778
+
779
+ wmi.execquery(query).each{ |user|
780
+ uid = user.sid.split('-').last.to_i
781
+
782
+ usr = User.new do |u|
783
+ u.account_type = user.accounttype
784
+ u.caption = user.caption
785
+ u.description = user.description
786
+ u.disabled = user.disabled
787
+ u.domain = user.domain
788
+ u.full_name = user.fullname
789
+ u.install_date = user.installdate
790
+ u.local = user.localaccount
791
+ u.lockout = user.lockout
792
+ u.name = user.name
793
+ u.password_changeable = user.passwordchangeable
794
+ u.password_expires = user.passwordexpires
795
+ u.password_required = user.passwordrequired
796
+ u.sid = user.sid
797
+ u.sid_type = user.sidtype
798
+ u.status = user.status
799
+ u.groups = get_groups(domain, user.name)
800
+ u.uid = uid
801
+ u.dir = get_home_dir(user.name, options[:localaccount], host)
802
+ end
803
+
804
+ if block_given?
805
+ yield usr
806
+ else
807
+ array.push(usr)
808
+ end
809
+ }
810
+
811
+ return array unless block_given?
812
+ end
809
813
 
810
- # Returns a Group object based on either +name+ or +gid+.
811
- #
812
- # call-seq:
813
- # Sys::Admin.get_group(name, options = {})
814
- # Sys::Admin.get_group(gid, options = {})
815
- #
816
- # If a numeric value is sent as the first parameter, it is treated
817
- # as a RID and is checked against the SID for a match.
818
- #
819
- # You may specify a host as an option from which information is
820
- # retrieved. The default is the local host.
821
- #
822
- # All other options are passed as WQL parameters to the Win32_Group
823
- # WMI object. See http://tinyurl.com/bngc8s for a list of possible
824
- # options.
825
- #
826
- # Examples:
827
- #
828
- # # Find a group by name
829
- # Sys::Admin.get_group('Web Team')
830
- #
831
- # # Find a group by id
832
- # Sys::Admin.get_group(31667)
833
- #
834
- # # Find a group on a specific domain
835
- # Sys::Admin.get_group('Web Team', :domain => 'FOO')
836
- #
837
- def self.get_group(grp, options = {})
838
- options = munge_options(options)
839
-
840
- host = options.delete(:host) || Socket.gethostname
841
- cs = "winmgmts:{impersonationLevel=impersonate}!"
842
- cs << "//#{host}/root/cimv2"
843
-
844
- begin
845
- wmi = WIN32OLE.connect(cs)
846
- rescue WIN32OLERuntimeError => err
847
- raise Error, err
848
- end
849
-
850
- query = "select * from win32_group"
851
-
852
- i = 0
853
-
854
- options.each{ |opt, val|
855
- if i == 0
856
- query << " where #{opt} = '#{val}'"
857
- i += 1
858
- else
859
- query << " and #{opt} = '#{val}'"
860
- end
861
- }
862
-
863
- if grp.kind_of?(Fixnum)
864
- query << " and sid like '%-#{grp}'"
865
- else
866
- query << " and name = '#{grp}'"
867
- end
868
-
869
- domain = options[:domain] || host
870
-
871
- wmi.execquery(query).each{ |group|
872
- gid = group.sid.split("-").last.to_i
873
-
874
- # Because our 'like' query isn't fulproof, let's parse
875
- # the SID again to make sure
876
- if grp.kind_of?(Fixnum)
877
- next if grp != gid
878
- end
879
-
880
- group_object = Group.new do |g|
881
- g.caption = group.caption
882
- g.description = group.description
883
- g.domain = group.domain
884
- g.gid = gid
885
- g.install_date = group.installdate
886
- g.local = group.localaccount
887
- g.name = group.name
888
- g.sid = group.sid
889
- g.sid_type = group.sidtype
890
- g.status = group.status
891
- g.members = get_members(domain, group.name)
892
- end
893
-
894
- return group_object
895
- }
896
-
897
- # If we're here, it means it wasn't found.
898
- raise Error, "no group found for '#{grp}'"
814
+ # Returns a Group object based on either +name+ or +gid+.
815
+ #
816
+ # call-seq:
817
+ # Sys::Admin.get_group(name, options = {})
818
+ # Sys::Admin.get_group(gid, options = {})
819
+ #
820
+ # If a numeric value is sent as the first parameter, it is treated
821
+ # as a RID and is checked against the SID for a match.
822
+ #
823
+ # You may specify a host as an option from which information is
824
+ # retrieved. The default is the local host.
825
+ #
826
+ # All other options are passed as WQL parameters to the Win32_Group
827
+ # WMI object. See http://tinyurl.com/bngc8s for a list of possible
828
+ # options.
829
+ #
830
+ # Examples:
831
+ #
832
+ # # Find a group by name
833
+ # Sys::Admin.get_group('Web Team')
834
+ #
835
+ # # Find a group by id
836
+ # Sys::Admin.get_group(31667)
837
+ #
838
+ # # Find a group on a specific domain
839
+ # Sys::Admin.get_group('Web Team', :domain => 'FOO')
840
+ #
841
+ def self.get_group(grp, options = {})
842
+ options = munge_options(options)
843
+
844
+ host = options.delete(:host) || Socket.gethostname
845
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
846
+ cs << "//#{host}/root/cimv2"
847
+
848
+ begin
849
+ wmi = WIN32OLE.connect(cs)
850
+ rescue WIN32OLERuntimeError => err
851
+ raise Error, err
852
+ end
853
+
854
+ query = "select * from win32_group"
855
+
856
+ i = 0
857
+
858
+ options.each{ |opt, val|
859
+ if i == 0
860
+ query << " where #{opt} = '#{val}'"
861
+ i += 1
862
+ else
863
+ query << " and #{opt} = '#{val}'"
864
+ end
865
+ }
866
+
867
+ if grp.kind_of?(Fixnum)
868
+ query << " and sid like '%-#{grp}'"
869
+ else
870
+ if i > 0
871
+ query << " and name = '#{grp}'"
872
+ else
873
+ query << " where name = '#{grp}'"
874
+ end
899
875
  end
876
+
877
+ domain = options[:domain] || host
878
+
879
+ wmi.execquery(query).each{ |group|
880
+ gid = group.sid.split("-").last.to_i
881
+
882
+ # Because our 'like' query isn't fulproof, let's parse
883
+ # the SID again to make sure
884
+ if grp.kind_of?(Fixnum)
885
+ next if grp != gid
886
+ end
887
+
888
+ group_object = Group.new do |g|
889
+ g.caption = group.caption
890
+ g.description = group.description
891
+ g.domain = group.domain
892
+ g.gid = gid
893
+ g.install_date = group.installdate
894
+ g.local = group.localaccount
895
+ g.name = group.name
896
+ g.sid = group.sid
897
+ g.sid_type = group.sidtype
898
+ g.status = group.status
899
+ g.members = get_members(domain, group.name)
900
+ end
901
+
902
+ return group_object
903
+ }
904
+
905
+ # If we're here, it means it wasn't found.
906
+ raise Error, "no group found for '#{grp}'"
907
+ end
900
908
 
901
- # In block form, yields a Group object for each user on the system. In
902
- # non-block form, returns an Array of Group objects.
903
- #
904
- # call-seq:
905
- # groups(options = {})
906
- # groups(options = {}){ |group| ... }
907
- #
908
- # You may specify a host option from which information is retrieved.
909
- # The default is the local host.
910
- #
911
- # All other options are passed as WQL parameters to the Win32_Group
912
- # WMI object. See http://tinyurl.com/bngc8s for a list of possible
913
- # options.
914
- #
915
- # Examples:
916
- #
917
- # # Get local group information
918
- # Sys::Admin.groups(:localaccount => true)
919
- #
920
- # # Get all groups on a specific domain
921
- # Sys::Admin.groups(:domain => 'FOO')
922
- #
923
- # # Get a specific group on a domain
924
- # Sys::Admin.groups(:name => 'Some Group', :domain => 'FOO')
925
- #
926
- def self.groups(options = {})
927
- options = munge_options(options)
928
-
929
- host = options.delete(:host) || Socket.gethostname
930
- cs = "winmgmts:{impersonationLevel=impersonate}!"
931
- cs << "//#{host}/root/cimv2"
932
-
933
- begin
934
- wmi = WIN32OLE.connect(cs)
935
- rescue WIN32OLERuntimeError => err
936
- raise Error, err
937
- end
938
-
939
- query = "select * from win32_group"
940
-
941
- i = 0
942
-
943
- options.each{ |opt, val|
944
- if i == 0
945
- query << " where #{opt} = '#{val}'"
946
- i += 1
947
- else
948
- query << " and #{opt} = '#{val}'"
949
- end
950
- }
951
-
952
- array = []
953
- domain = options[:domain] || host
954
-
955
- wmi.execquery(query).each{ |group|
956
- grp = Group.new do |g|
957
- g.caption = group.caption
958
- g.description = group.description
959
- g.domain = group.domain
960
- g.gid = group.sid.split("-").last.to_i
961
- g.install_date = group.installdate
962
- g.local = group.localaccount
963
- g.name = group.name
964
- g.sid = group.sid
965
- g.sid_type = group.sidtype
966
- g.status = group.status
967
- g.members = get_members(domain, group.name)
968
- end
969
-
970
- if block_given?
971
- yield grp
972
- else
973
- array.push(grp)
974
- end
975
- }
976
-
977
- return array unless block_given?
909
+ # In block form, yields a Group object for each user on the system. In
910
+ # non-block form, returns an Array of Group objects.
911
+ #
912
+ # call-seq:
913
+ # groups(options = {})
914
+ # groups(options = {}){ |group| ... }
915
+ #
916
+ # You may specify a host option from which information is retrieved.
917
+ # The default is the local host.
918
+ #
919
+ # All other options are passed as WQL parameters to the Win32_Group
920
+ # WMI object. See http://tinyurl.com/bngc8s for a list of possible
921
+ # options.
922
+ #
923
+ # Examples:
924
+ #
925
+ # # Get local group information
926
+ # Sys::Admin.groups(:localaccount => true)
927
+ #
928
+ # # Get all groups on a specific domain
929
+ # Sys::Admin.groups(:domain => 'FOO')
930
+ #
931
+ # # Get a specific group on a domain
932
+ # Sys::Admin.groups(:name => 'Some Group', :domain => 'FOO')
933
+ #
934
+ def self.groups(options = {})
935
+ options = munge_options(options)
936
+
937
+ host = options.delete(:host) || Socket.gethostname
938
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
939
+ cs << "//#{host}/root/cimv2"
940
+
941
+ begin
942
+ wmi = WIN32OLE.connect(cs)
943
+ rescue WIN32OLERuntimeError => err
944
+ raise Error, err
978
945
  end
979
- end
946
+
947
+ query = "select * from win32_group"
948
+
949
+ i = 0
950
+
951
+ options.each{ |opt, val|
952
+ if i == 0
953
+ query << " where #{opt} = '#{val}'"
954
+ i += 1
955
+ else
956
+ query << " and #{opt} = '#{val}'"
957
+ end
958
+ }
959
+
960
+ array = []
961
+ domain = options[:domain] || host
962
+
963
+ wmi.execquery(query).each{ |group|
964
+ grp = Group.new do |g|
965
+ g.caption = group.caption
966
+ g.description = group.description
967
+ g.domain = group.domain
968
+ g.gid = group.sid.split("-").last.to_i
969
+ g.install_date = group.installdate
970
+ g.local = group.localaccount
971
+ g.name = group.name
972
+ g.sid = group.sid
973
+ g.sid_type = group.sidtype
974
+ g.status = group.status
975
+ g.members = get_members(domain, group.name)
976
+ end
977
+
978
+ if block_given?
979
+ yield grp
980
+ else
981
+ array.push(grp)
982
+ end
983
+ }
984
+
985
+ return array unless block_given?
986
+ end
987
+ end
980
988
  end