sys-admin 1.4.3-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,330 @@
1
+ = Description
2
+ A unified, cross-platform replacement for the Etc module that allows you to
3
+ get information about users and groups.
4
+
5
+ = Synopsis
6
+ require 'sys/admin'
7
+ include Sys
8
+
9
+ Admin.get_login # -> 'djberge'
10
+ Admin.get_user('djberge') # -> Admin::User object
11
+ Admin.get_group(501) # -> Admin::Group object
12
+
13
+ # Iterate over all users
14
+ Admin.users do |usr|
15
+ p usr
16
+ end
17
+
18
+ # Iterate over all groups
19
+ Admin.groups do |grp|
20
+ p grp
21
+ end
22
+
23
+ = Constants
24
+ == Sys::Admin
25
+ VERSION
26
+ The version of this package, returned as a String.
27
+
28
+ == Sys::Admin::User
29
+ TEMP_DUPLICATE
30
+ An account for users whose primary account is in another domain.
31
+
32
+ NORMAL
33
+ Default account type that represents a typical user.
34
+
35
+ INTERDOMAIN_TRUST
36
+ A permit to trust account for a domain that trusts other domains.
37
+
38
+ WORKSTATION_TRUST
39
+ An account for a Windows NT/2000 workstation or server that is a member
40
+ member of this domain.
41
+
42
+ SERVER_TRUST
43
+ A computer account for a backup domain controller that is a member of this
44
+ domain.
45
+
46
+ = Class Methods
47
+ == Sys::Admin
48
+ Admin.add_global_group(group, domain)
49
+ Adds the global +group+ on +domain+.
50
+
51
+ Admin.add_global_user(user, domain)
52
+ Adds the global +user+ on +domain+.
53
+
54
+ Admin.add_local_group(group, host=localhost)
55
+ Adds the local +group+ on +host+, or the localhost if no host is specified.
56
+
57
+ Admin.add_local_user(user, host=localhost)
58
+ Adds the local +user+ on +host+, or the localhost if no host is specified.
59
+
60
+ Admin.config_global_group(user, option, domain)
61
+ Configures +group+ on +domain+ using +options+. There are too many options
62
+ to list here.
63
+
64
+ See http://tinyurl.com/cjkzl for a list of valid options.
65
+
66
+ Admin.config_local_group(user, option, host=localhost)
67
+ Configures +group+ on +host+ using +options+. There are too many options
68
+ to list here.
69
+
70
+ See http://tinyurl.com/cjkzl for a list of valid options.
71
+
72
+ Admin.config_global_user(user, option, domain)
73
+ Configures +user+ on +domain+ using +options+. There are too many options
74
+ to list here.
75
+
76
+ See http://tinyurl.com/3hjv9 for a list of valid options.
77
+
78
+ Admin.config_local_user(user, options, host=localhost)
79
+ Configures the local +user+ on +host+ using +options+. If no host is
80
+ specified, the default is localhost.
81
+
82
+ See http://tinyurl.com/3hjv9 for a list of valid options.
83
+
84
+ Admin.delete_global_group(group, domain)
85
+ Deletes the global +group+ from +domain+.
86
+
87
+ Admin.delete_global_user(user, domain)
88
+ Deletes the global +user+ from +domain+.
89
+
90
+ Admin.delete_local_group(group, host=localhost)
91
+ Deletes the local +group+ from +host+, or localhost if no host is specified.
92
+
93
+ Admin.delete_local_user(user, host=localhost)
94
+ Deletes the local +user+ from +host+, or localhost if no host is specified.
95
+
96
+ Admin.get_group(name, host=localhost, local=true)
97
+ Admin.get_group(gid, host=localhost, local=true)
98
+ Returns a Group object for the given name or gid. Raises an Admin::Error
99
+ if a group cannot be found for that name or GID.
100
+
101
+ You may specify a host from which information is retrieved.
102
+ The default is the local machine. You can retrieve either a global or
103
+ local group, depending on the value of the +local+ argument.
104
+
105
+ Admin.get_login
106
+ Returns the user name of the current login.
107
+
108
+ Admin.get_user(name, host=localhost, local=true)
109
+ Admin.get_user(uid, host=localhost, local=true)
110
+ Returns a User object for the given name or uid. Raises an Admin::Error if
111
+ a user cannot be found for that name or user ID.
112
+
113
+ You may specify a +host+ from which information is retrieved. The
114
+ default is the local machine. You may also specify whether to
115
+ retrieve a local or global account. The default is local.
116
+
117
+ Admin.groups(host=localhost, local=true)
118
+ Admin.groups(host=localhost, local=true){ |grp| ... }
119
+ In block form, yields a Group object for each group on the system. In
120
+ non-block form, returns an Array of Group objects.
121
+
122
+ You may specify a +host+ from which information is retrieved. The default
123
+ is the local machine. You can retrieve either a global or local groups,
124
+ depending on the value of the +local+ argument. The default is local.
125
+
126
+ Admin.users(host=localhost, local=true)
127
+ Admin.users(host=localhost, local=true){ |grp| ... }
128
+ In block form, yields a User object for each group on the system. In
129
+ non-block form, returns an Array of User objects.
130
+
131
+ You may specify a +host+ from which information is retrieved. The default
132
+ is the local machine. You can retrieve either a global or local users,
133
+ depending on the value of the +local+ argument. The default is local.
134
+
135
+ == Sys::Admin::Group
136
+ Group.new
137
+ Group.new{ |grp| ... }
138
+ Creates and returns a Group object, which encapsulates the information
139
+ typically found within an /etc/group entry, i.e. a struct group. If a
140
+ block is provided, yields the object back to the block.
141
+
142
+ == Sys::Admin::User
143
+ User.new
144
+ User.new{ |usr| ... }
145
+ Creates and returns a User object, which encapsulates the information
146
+ typically found within an /etc/passwd entry, i.e. a struct passwd. If a
147
+ block is provided, yields the object back to the block.
148
+
149
+ = Instance Methods
150
+ == Sys::Admin::Group
151
+ Group#caption
152
+ Short description of the group.
153
+
154
+ Group#caption=
155
+ Sets the caption for the group. Use only when creating a new group.
156
+
157
+ Group#description
158
+ Description of the group.
159
+
160
+ Group#description=
161
+ Sets the description of the group. Use only when creating a new group.
162
+
163
+ Group#domain
164
+ The name of the Windows domain to which the group account belongs.
165
+
166
+ Group#domain=
167
+ Sets the name of the Windows domain to which the group account belongs.
168
+ Use only when creating a new group.
169
+
170
+ Group#install_date
171
+ The date the group was added.
172
+
173
+ Group#gid
174
+ The group id.
175
+
176
+ Group#local?
177
+ Returns whether or not the group is local (vs global).
178
+
179
+ Group#local=
180
+ Sets whether or not the group is local (vs global).
181
+
182
+ Group#name
183
+ The name of the Windows group account on the given domain.
184
+
185
+ Group#name=
186
+ Sets the name of the Windows group account on the given domain.
187
+ Use only when creating a new group.
188
+
189
+ Group#sid
190
+ The security identifer for the group.
191
+
192
+ Group#sid=
193
+ Sets the security identifer for the group.
194
+
195
+ Group#sid_type
196
+ The type of security identifier as a stringified value.
197
+
198
+ Group#sid_type=
199
+ Sets the type of security identifier as a stringified value. Use only when
200
+ creating a new group.
201
+
202
+ See the +constants+ section for a list of valid sid types.
203
+
204
+ Group#status
205
+ Current status for the group, such as "ok", "error", etc.
206
+
207
+ Group#status=
208
+ Sets the status for the group.
209
+
210
+ == Sys::Admin::User
211
+ User#account_type
212
+ Returns the account type as a human readable string.
213
+
214
+ User#account_type=
215
+ Sets the account type. See the +constants+ section for a list of valid
216
+ values you can set this to.
217
+
218
+ User#caption
219
+ Domain and username of the account.
220
+
221
+ User#caption=
222
+ Sets the domain and username of the account.
223
+
224
+ User#description
225
+ Description of the account.
226
+
227
+ User#description=
228
+ Sets the description of the account.
229
+
230
+ User#disabled?
231
+ Returns whether or not the account is disabled.
232
+
233
+ User#disabled=
234
+ Sets whether or not the account is disabled.
235
+
236
+ User#domain
237
+ Name of the Windows domain to which a user account belongs.
238
+
239
+ User#domain=
240
+ Sets the name of the Windows domain to which a user account belongs.
241
+
242
+ User#full_name
243
+ Full name of a local user.
244
+
245
+ User#full_name=
246
+ Sets the full name of a local user.
247
+
248
+ User#install_date
249
+ Date the user account was created.
250
+
251
+ User#local?
252
+ Returns whether or not the account is defined on the local computer.
253
+
254
+ User#local=
255
+ Sets whether or not the account is defined on the local computer.
256
+
257
+ User#lockout?
258
+ Returns whether or not the account is locked out of the OS.
259
+
260
+ User#lockout=
261
+ Sets whether or not the account is locked out of the OS.
262
+
263
+ User#name
264
+ Name of the Windows user account on the domain that the User#domain
265
+ property specifies.
266
+
267
+ User#name=
268
+ Sets the name of the Windows user account on the domain that the User#domain
269
+ property specifies.
270
+
271
+ User#password
272
+ The user's password.
273
+
274
+ User#password=
275
+ Sets the user's password.
276
+
277
+ User#password_changeable?
278
+ Returns whether or not the password for the account can be changed.
279
+
280
+ User#password_changeable=
281
+ Sets whether or not the password for the account can be changed.
282
+
283
+ User#password_expires?
284
+ Returns whether or not the password for the account expires.
285
+
286
+ User#password_expires=
287
+ Sets whether or not the password for the account expires.
288
+
289
+ User#password_required?
290
+ Returns whether or not a password is required for the account.
291
+
292
+ User#password_required=
293
+ Sets whether or not a password is required for the account.
294
+
295
+ User#sid
296
+ The user's security identifier.
297
+
298
+ User#sid=
299
+ Sets the user's security identifier.
300
+
301
+ User#status
302
+ Current status for the user, such as "ok", "error", etc.
303
+
304
+ == Notes
305
+ Not all platforms support all of the User members. The only ones that are
306
+ supported on all platforms are name, uid, gid, dir and shell. The rest
307
+ will simply return nil if they aren't supported.
308
+
309
+ == Known Bugs
310
+ None that I am aware of. Please log any bugs you find on the project
311
+ website at http://www.rubyforge.org/projects/sysutils.
312
+
313
+ == License
314
+ Ruby's
315
+
316
+ == Copyright
317
+ Copyright 2002-2007, Daniel J. Berger
318
+
319
+ All Rights Reserved. This module is free software. It may be used,
320
+ redistributed and/or modified under the same terms as Ruby itself.
321
+
322
+ == Warranty
323
+ This package is provided "as is" and without any express or
324
+ implied warranties, including, without limitation, the implied
325
+ warranties of merchantability and fitness for a particular purpose.
326
+
327
+ == Author
328
+ Daniel J. Berger
329
+ djberg96 at nospam at gmail dot com
330
+ imperator on IRC (Freenode)
@@ -0,0 +1,39 @@
1
+ ###########################################################################
2
+ # groups.rb
3
+ #
4
+ # Sample script to demonstrate some of the various group methods. Alter
5
+ # as you see fit.
6
+ ###########################################################################
7
+ base = File.basename(Dir.pwd)
8
+
9
+ if base == "examples" || base =~ /sys-admin.*/
10
+ require "ftools"
11
+ Dir.chdir("..") if base == "examples"
12
+ Dir.mkdir("sys") unless File.exists?("sys")
13
+ if RUBY_PLATFORM.match("mswin")
14
+ File.copy("lib/sys/admin.rb", "sys/admin.rb")
15
+ else
16
+ File.copy("admin.so","sys") if File.exists?("admin.so")
17
+ end
18
+ $LOAD_PATH.unshift(Dir.pwd)
19
+ end
20
+
21
+ require "pp"
22
+ require "sys/admin"
23
+ include Sys
24
+
25
+ if PLATFORM.match("mswin")
26
+ pp Admin.get_group("guests")
27
+ pp Admin.get_group(513)
28
+ else
29
+ pp Admin.get_group("adm")
30
+ pp Admin.get_group(7)
31
+ end
32
+
33
+ Admin.groups{ |g|
34
+ pp g
35
+ puts
36
+ }
37
+
38
+ # This should raise an error
39
+ Admin.get_group("fofofofof")
@@ -0,0 +1,53 @@
1
+ ###########################################################################
2
+ # users.rb
3
+ #
4
+ # Sample script to demonstrate some of the various user methods. Alter
5
+ # as you see fit.
6
+ ###########################################################################
7
+ base = File.basename(Dir.pwd)
8
+
9
+ if base == "examples" || base =~ /sys-admin.*/
10
+ require "ftools"
11
+ Dir.chdir("..") if base == "examples"
12
+ Dir.mkdir("sys") unless File.exists?("sys")
13
+ if RUBY_PLATFORM.match("mswin")
14
+ File.copy("lib/sys/admin.rb", "sys/admin.rb")
15
+ else
16
+ File.copy("admin.so","sys") if File.exists?("admin.so")
17
+ end
18
+ $LOAD_PATH.unshift(Dir.pwd)
19
+ end
20
+
21
+ require "pp"
22
+ require "sys/admin"
23
+ include Sys
24
+
25
+ user = User.new do |u|
26
+ u.name = "Foo"
27
+ u.description = "Test account"
28
+ u.password = "changeme"
29
+ #u.lockout = false
30
+ u.disabled = true
31
+ #u.password_required = true
32
+ end
33
+
34
+ Admin.delete_user(u.name) rescue nil
35
+ Admin.add_user(user)
36
+
37
+ #pp Admin.get_user("Foo")
38
+
39
+ #Admin.delete_user("Foo")
40
+
41
+ =begin
42
+ user = Admin.get_login
43
+
44
+ puts "User: #{user}"
45
+
46
+ Admin.users{ |u|
47
+ pp u
48
+ puts
49
+ }
50
+
51
+ pp Admin.get_user(user)
52
+ pp Admin.get_user(501)
53
+ =end
@@ -0,0 +1,713 @@
1
+ require "win32ole"
2
+ require "Win32API"
3
+ require "socket"
4
+
5
+ module Sys
6
+ class Group
7
+ # Short description of the object.
8
+ attr_accessor :caption
9
+
10
+ # Description of the group.
11
+ attr_accessor :description
12
+
13
+ # Name of the Windows domain to which the group account belongs.
14
+ attr_accessor :domain
15
+
16
+ # Date the group was added.
17
+ attr_accessor :install_date
18
+
19
+ # Name of the Windows group account on the Group#domain specified.
20
+ attr_accessor :name
21
+
22
+ # Security identifier for this group.
23
+ attr_accessor :sid
24
+
25
+ # Current status for the group, such as "ok", "error", etc.
26
+ attr_accessor :status
27
+
28
+ # The group ID.
29
+ attr_accessor :gid
30
+
31
+ # Sets whether or not the group is local (as opposed to global).
32
+ attr_writer :local
33
+
34
+ # Creates and returns a new Group object. This class encapsulates
35
+ # the information for a group account, whether it be global or local.
36
+ #
37
+ # Yields +self+ if a block is given.
38
+ #
39
+ def initialize
40
+ yield self if block_given?
41
+ end
42
+
43
+ # Returns whether or not the group is a local group.
44
+ #
45
+ def local?
46
+ @local
47
+ end
48
+
49
+ # Returns the type of SID (Security Identifier) as a stringified value.
50
+ #
51
+ def sid_type
52
+ @sid_type
53
+ end
54
+
55
+ # Sets the SID (Security Identifier) type to +stype+, which can be
56
+ # one of the following constant values:
57
+ #
58
+ # * Admin::SidTypeUser
59
+ # * Admin::SidTypeGroup
60
+ # * Admin::SidTypeDomain
61
+ # * Admin::SidTypeAlias
62
+ # * Admin::SidTypeWellKnownGroup
63
+ # * Admin::SidTypeDeletedAccount
64
+ # * Admin::SidTypeInvalid
65
+ # * Admin::SidTypeUnknown
66
+ # * Admin::SidTypeComputer
67
+ #
68
+ def sid_type=(stype)
69
+ if stype.kind_of?(String)
70
+ @sid_type = stype.downcase
71
+ else
72
+ case stype
73
+ when Admin::SidTypeUser
74
+ @sid_type = "user"
75
+ when Admin::SidTypeGroup
76
+ @sid_type = "group"
77
+ when Admin::SidTypeDomain
78
+ @sid_type = "domain"
79
+ when Admin::SidTypeAlias
80
+ @sid_type = "alias"
81
+ when Admin::SidTypeWellKnownGroup
82
+ @sid_type = "well_known_group"
83
+ when Admin::SidTypeDeletedAccount
84
+ @sid_type = "deleted_account"
85
+ when Admin::SidTypeInvalid
86
+ @sid_type = "invalid"
87
+ when Admin::SidTypeUnknown
88
+ @sid_type = "unknown"
89
+ when Admin::SidTypeComputer
90
+ @sid_type = "computer"
91
+ else
92
+ @sid_type = "unknown"
93
+ end
94
+ end
95
+ @sid_type
96
+ end
97
+ end
98
+
99
+ class User
100
+ # An account for users whose primary account is in another domain.
101
+ TEMP_DUPLICATE = 0x0100
102
+
103
+ # Default account type that represents a typical user.
104
+ NORMAL = 0x0200
105
+
106
+ # A permit to trust account for a domain that trusts other domains.
107
+ INTERDOMAIN_TRUST = 0x0800
108
+
109
+ # An account for a Windows NT/2000 workstation or server that is a
110
+ # member of this domain.
111
+ WORKSTATION_TRUST = 0x1000
112
+
113
+ # A computer account for a backup domain controller that is a member
114
+ # of this domain.
115
+ SERVER_TRUST = 0x2000
116
+
117
+ # Domain and username of the account.
118
+ attr_accessor :caption
119
+
120
+ # Description of the account.
121
+ attr_accessor :description
122
+
123
+ # Name of the Windows domain to which a user account belongs.
124
+ attr_accessor :domain
125
+
126
+ # The user's password.
127
+ attr_accessor :password
128
+
129
+ # Full name of a local user.
130
+ attr_accessor :full_name
131
+
132
+ # Date the user account was created.
133
+ attr_accessor :install_date
134
+
135
+ # Name of the Windows user account on the domain that the User#domain
136
+ # property specifies.
137
+ attr_accessor :name
138
+
139
+ # The user's security identifier.
140
+ attr_accessor :sid
141
+
142
+ # Current status for the user, such as "ok", "error", etc.
143
+ attr_accessor :status
144
+
145
+ # Used to set whether or not the account is disabled.
146
+ attr_writer :disabled
147
+
148
+ # Sets whether or not the account is defined on the local computer.
149
+ attr_writer :local
150
+
151
+ # Sets whether or not the account is locked out of the OS.
152
+ attr_writer :lockout
153
+
154
+ # Sets whether or not the password for the account can be changed.
155
+ attr_writer :password_changeable
156
+
157
+ # Sets whether or not the password for the account expires.
158
+ attr_writer :password_expires
159
+
160
+ # Sets whether or not a password is required for the account.
161
+ attr_writer :password_required
162
+
163
+ # Returns the account type as a human readable string.
164
+ attr_reader :account_type
165
+
166
+ # Creates an returns a new User object. A User object encapsulates a
167
+ # user account on the operating system.
168
+ #
169
+ # Yields +self+ if a block is provided.
170
+ #
171
+ def initialize
172
+ yield self if block_given?
173
+ end
174
+
175
+ # Sets the account type for the account. Possible values are:
176
+ #
177
+ # * User::TEMP_DUPLICATE
178
+ # * User::NORMAL
179
+ # * User::INTERDOMAIN_TRUST
180
+ # * User::WORKSTATION_TRUST
181
+ # * User::SERVER_TRUST
182
+ #
183
+ def account_type=(type)
184
+ case type
185
+ when TEMP_DUPLICATE
186
+ @account_type = "duplicate"
187
+ when NORMAL
188
+ @account_type = "normal"
189
+ when INTERDOMAIN_TRUST
190
+ @account_type = "interdomain_trust"
191
+ when WORKSTATION_TRUST
192
+ @account_type = "workstation_trust"
193
+ when SERVER_TRUST
194
+ @account_type = "server_trust"
195
+ else
196
+ @account_type = "unknown"
197
+ end
198
+ end
199
+
200
+ # Returns the SID type as a human readable string.
201
+ #
202
+ def sid_type
203
+ @sid_type
204
+ end
205
+
206
+ # Sets the SID (Security Identifier) type to +stype+, which can be
207
+ # one of the following constant values:
208
+ #
209
+ # * Admin::SidTypeUser
210
+ # * Admin::SidTypeGroup
211
+ # * Admin::SidTypeDomain
212
+ # * Admin::SidTypeAlias
213
+ # * Admin::SidTypeWellKnownGroup
214
+ # * Admin::SidTypeDeletedAccount
215
+ # * Admin::SidTypeInvalid
216
+ # * Admin::SidTypeUnknown
217
+ # * Admin::SidTypeComputer
218
+ #
219
+ def sid_type=(stype)
220
+ case stype
221
+ when Admin::SidTypeUser
222
+ @sid_type = "user"
223
+ when Admin::SidTypeGroup
224
+ @sid_type = "group"
225
+ when Admin::SidTypeDomain
226
+ @sid_type = "domain"
227
+ when Admin::SidTypeAlias
228
+ @sid_type = "alias"
229
+ when Admin::SidTypeWellKnownGroup
230
+ @sid_type = "well_known_group"
231
+ when Admin::SidTypeDeletedAccount
232
+ @sid_type = "deleted_account"
233
+ when Admin::SidTypeInvalid
234
+ @sid_type = "invalid"
235
+ when Admin::SidTypeUnknown
236
+ @sid_type = "unknown"
237
+ when Admin::SidTypeComputer
238
+ @sid_type = "computer"
239
+ else
240
+ @sid_type = "unknown"
241
+ end
242
+ end
243
+
244
+ # Returns whether or not the account is disabled.
245
+ #
246
+ def disabled?
247
+ @disabled
248
+ end
249
+
250
+ # Returns whether or not the account is local.
251
+ #
252
+ def local?
253
+ @local
254
+ end
255
+
256
+ # Returns whether or not the account is locked out.
257
+ #
258
+ def lockout?
259
+ @lockout
260
+ end
261
+
262
+ # Returns whether or not the password for the account is changeable.
263
+ #
264
+ def password_changeable?
265
+ @password_changeable
266
+ end
267
+
268
+ # Returns whether or not the password for the account is changeable.
269
+ #
270
+ def password_expires?
271
+ @password_expires
272
+ end
273
+
274
+ # Returns whether or not the a password is required for the account.
275
+ #
276
+ def password_required?
277
+ @password_required
278
+ end
279
+ end
280
+
281
+ class Admin
282
+ VERSION = '1.4.3'
283
+
284
+ # This is the error raised in the majority of cases if anything goes wrong
285
+ # with any of the Sys::Admin methods.
286
+ #
287
+ class Error < StandardError; end
288
+
289
+
290
+ SidTypeUser = 1
291
+ SidTypeGroup = 2
292
+ SidTypeDomain = 3
293
+ SidTypeAlias = 4
294
+ SidTypeWellKnownGroup = 5
295
+ SidTypeDeletedAccount = 6
296
+ SidTypeInvalid = 7
297
+ SidTypeUnknown = 8
298
+ SidTypeComputer = 9
299
+
300
+ # Used by the get_login method
301
+ GetUserName = Win32API.new('advapi32', 'GetUserName', 'PP', 'L') # :nodoc:
302
+
303
+ # Configures the global +user+ on +domain+ using options.
304
+ #
305
+ # See http://tinyurl.com/3hjv9 for a list of valid options.
306
+ #
307
+ def self.config_global_user(user, options, domain)
308
+ begin
309
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{user},user")
310
+ options.each{ |option, value|
311
+ adsi.put(option.to_s, value)
312
+ }
313
+ adsi.setinfo
314
+ rescue WIN32OLERuntimeError => err
315
+ raise Error, err
316
+ end
317
+ end
318
+
319
+ # Configures the local +user+ on +host+ using +options+. If no host
320
+ # is specified, the default is localhost.
321
+ #
322
+ # See http://tinyurl.com/3hjv9 for a list of valid options.
323
+ #
324
+ def self.config_local_user(user, options, host=Socket.gethostname)
325
+ begin
326
+ adsi = WIN32OLE.connect("WinNT://#{host}/#{user},user")
327
+ options.each{ |option, value|
328
+ adsi.put(option.to_s, value)
329
+ }
330
+ adsi.setinfo
331
+ rescue WIN32OLERuntimeError => err
332
+ raise Error, err
333
+ end
334
+ end
335
+
336
+ # Adds the global +user+ on +domain+
337
+ #
338
+ def self.add_global_user(user, domain)
339
+ begin
340
+ adsi = WIN32OLE.connect("WinNT://#{host},Computer")
341
+ user = adsi.create("user", user)
342
+ user.setinfo
343
+ rescue WIN32OLERuntimeError => err
344
+ raise Error, err
345
+ end
346
+ end
347
+
348
+ # Adds the local +user+ on +host+, or the localhost if none is specified.
349
+ #
350
+ def self.add_local_user(user, host=Socket.gethostname)
351
+ begin
352
+ adsi = WIN32OLE.connect("WinNT://#{host},Computer")
353
+ user = adsi.create("user", user)
354
+ user.setinfo
355
+ rescue WIN32OLERuntimeError => err
356
+ raise Error, err
357
+ end
358
+ end
359
+
360
+ # Deletes the local +user+ from +host+, or localhost if no host specified.
361
+ #
362
+ def self.delete_local_user(user, host=Socket.gethostname)
363
+ begin
364
+ adsi = WIN32OLE.connect("WinNT://#{host},Computer")
365
+ adsi.delete("user", user)
366
+ rescue WIN32OLERuntimeError => err
367
+ raise Error, err
368
+ end
369
+ end
370
+
371
+ # Deletes the global +user+ from +domain+.
372
+ #
373
+ def self.delete_global_user(user, domain)
374
+ begin
375
+ adsi = WIN32OLE.connect("WinNT://#{domain}")
376
+ adsi.delete("user", user)
377
+ rescue WIN32OLERuntimeError => err
378
+ raise Error, err
379
+ end
380
+ end
381
+
382
+ # Configures the global +group+ on +domain+ using +options+.
383
+ #
384
+ # See http://tinyurl.com/cjkzl for a list of valid options.
385
+ #
386
+ def self.config_global_group(group, options, domain)
387
+ begin
388
+ adsi = WIN32OLE.connect("WinNT://#{domain}/#{group},group")
389
+ options.each{ |option, value|
390
+ adsi.put(option.to_s, value)
391
+ }
392
+ adsi.setinfo
393
+ rescue WIN32OLERuntimeError => err
394
+ raise Error, err
395
+ end
396
+ end
397
+
398
+ # Configures the local +group+ on +host+ using +options+. If no host
399
+ # is specified, the default is localhost.
400
+ #
401
+ # See http://tinyurl.com/cjkzl for a list of valid options.
402
+ #
403
+ def self.config_local_group(group, options, host=Socket.gethostname)
404
+ begin
405
+ adsi = WIN32OLE.connect("WinNT://#{host}/#{group},group")
406
+ options.each{ |option, value|
407
+ adsi.put(option.to_s, value)
408
+ }
409
+ adsi.setinfo
410
+ rescue WIN32OLERuntimeError => err
411
+ raise Error, err
412
+ end
413
+ end
414
+
415
+ # Add global +group+ to +domain+.
416
+ #
417
+ def self.add_global_group(group, domain)
418
+ begin
419
+ adsi = WIN32OLE.connect("WinNT://#{domain},Computer")
420
+ obj = adsi.create("group", group)
421
+ obj.setinfo
422
+ rescue WIN32OLERuntimeError => err
423
+ raise Error, err
424
+ end
425
+ end
426
+
427
+ # Add local +group+ to +host+, or the localhost if no host is specified.
428
+ #
429
+ def self.add_local_group(group, host=Socket.gethostname)
430
+ begin
431
+ adsi = WIN32OLE.connect("WinNT://#{host},Computer")
432
+ obj = adsi.create("group", group)
433
+ obj.setinfo
434
+ rescue WIN32OLERuntimeError => err
435
+ raise Error, err
436
+ end
437
+ end
438
+
439
+ # Delete the global +group+ from +domain+.
440
+ #
441
+ def self.delete_global_group(groupid, domain)
442
+ begin
443
+ adsi = WIN32OLE.connect("WinNT://#{domain},Computer")
444
+ obj = adsi.delete("group", groupid)
445
+ rescue WIN32OLERuntimeError => err
446
+ raise Error, err
447
+ end
448
+ end
449
+
450
+ # Delete the local +group+ from +host+, or localhost if no host specified.
451
+ #
452
+ def self.delete_local_group(groupid, host=Socket.gethostname)
453
+ begin
454
+ adsi = WIN32OLE.connect("WinNT://#{host},Computer")
455
+ obj = adsi.delete("group", groupid)
456
+ rescue WIN32OLERuntimeError => err
457
+ raise Error, err
458
+ end
459
+ end
460
+
461
+ # Returns the user name (only) of the current login.
462
+ #
463
+ def self.get_login
464
+ buffer = 0.chr * 256
465
+ nsize = [buffer.size].pack("L")
466
+
467
+ if GetUserName.call(buffer, nsize) == 0
468
+ raise Error, 'GetUserName() call failed in get_login'
469
+ end
470
+
471
+ length = nsize.unpack("L")[0]
472
+ username = buffer[0 ... length].chop
473
+ username
474
+ end
475
+
476
+ # Returns a User object based on either +name+ or +uid+.
477
+ #
478
+ # call-seq:
479
+ # get_user(name, host=localhost)
480
+ # get_user(uid, host=localhost, local=true)
481
+ #
482
+ # You may specify a +host+ from which information is retrieved. The
483
+ # default is the local machine. You may also specify whether to
484
+ # retrieve a local or global account. The default is local.
485
+ #
486
+ def self.get_user(uid, host=Socket.gethostname, local=true)
487
+ host = Socket.gethostname if host.nil?
488
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
489
+ cs << "//#{host}/root/cimv2"
490
+
491
+ begin
492
+ wmi = WIN32OLE.connect(cs)
493
+ rescue WIN32OLERuntimeError => e
494
+ raise Error, e
495
+ end
496
+
497
+ query = "select * from win32_useraccount"
498
+ query << " where localaccount = true" if local
499
+
500
+ if uid.kind_of?(Fixnum)
501
+ if local
502
+ query << " and sid like '%-#{uid}'"
503
+ else
504
+ query << " where sid like '%-#{uid}'"
505
+ end
506
+ else
507
+ if local
508
+ query << " and name = '#{uid}'"
509
+ else
510
+ query << " where name = '#{uid}'"
511
+ end
512
+ end
513
+
514
+ wmi.execquery(query).each{ |user|
515
+ # Because our 'like' query isn't fulproof, let's parse
516
+ # the SID again to make sure
517
+ if uid.kind_of?(Fixnum)
518
+ if user.sid.split("-").last.to_i != uid
519
+ next
520
+ end
521
+ end
522
+ usr = User.new do |u|
523
+ u.account_type = user.accounttype
524
+ u.caption = user.caption
525
+ u.description = user.description
526
+ u.disabled = user.disabled
527
+ u.domain = user.domain
528
+ u.full_name = user.fullname
529
+ u.install_date = user.installdate
530
+ u.local = user.localaccount
531
+ u.lockout = user.lockout
532
+ u.name = user.name
533
+ u.password_changeable = user.passwordchangeable
534
+ u.password_expires = user.passwordexpires
535
+ u.password_required = user.passwordrequired
536
+ u.sid = user.sid
537
+ u.sid_type = user.sidtype
538
+ u.status = user.status
539
+ end
540
+ return usr
541
+ }
542
+ end
543
+
544
+ # In block form, yields a User object for each user on the system. In
545
+ # non-block form, returns an Array of User objects.
546
+ #
547
+ # call-seq:
548
+ # users(host=localhost, local=true)
549
+ # users(host=localhost, local=true){ |user| ... }
550
+ #
551
+ # You may specify a host from which information is retrieved. The
552
+ # default is the local machine. You can retrieve either a global or
553
+ # local group, depending on the value of the +local+ argument.
554
+ #
555
+ def self.users(host=Socket.gethostname, local=true)
556
+ host = Socket.gethostname if host.nil?
557
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
558
+ cs << "//#{host}/root/cimv2"
559
+
560
+ begin
561
+ wmi = WIN32OLE.connect(cs)
562
+ rescue WIN32OLERuntimeError => e
563
+ raise Error, e
564
+ end
565
+
566
+ query = "select * from win32_useraccount"
567
+ query << " where localaccount = true" if local
568
+ array = []
569
+
570
+ wmi.execquery(query).each{ |user|
571
+ usr = User.new do |u|
572
+ u.account_type = user.accounttype
573
+ u.caption = user.caption
574
+ u.description = user.description
575
+ u.disabled = user.disabled
576
+ u.domain = user.domain
577
+ u.full_name = user.fullname
578
+ u.install_date = user.installdate
579
+ u.local = user.localaccount
580
+ u.lockout = user.lockout
581
+ u.name = user.name
582
+ u.password_changeable = user.passwordchangeable
583
+ u.password_expires = user.passwordexpires
584
+ u.password_required = user.passwordrequired
585
+ u.sid = user.sid
586
+ u.sid_type = user.sidtype
587
+ u.status = user.status
588
+ end
589
+
590
+ if block_given?
591
+ yield usr
592
+ else
593
+ array.push(usr)
594
+ end
595
+ }
596
+ return array unless block_given?
597
+ end
598
+
599
+ # Returns a Group object based on either +name+ or +uid+.
600
+ #
601
+ # call-seq:
602
+ # get_group(name, host=localhost, local=true)
603
+ # get_group(gid, host=localhost, local=true)
604
+ #
605
+ # You may specify a host from which information is retrieved.
606
+ # The default is the local machine. You can retrieve either a global or
607
+ # local group, depending on the value of the +local+ argument.
608
+ #
609
+ def self.get_group(grp, host=Socket.gethostname, local=true)
610
+ host = Socket.gethostname if host.nil?
611
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
612
+ cs << "//#{host}/root/cimv2"
613
+ gid = nil
614
+
615
+ begin
616
+ wmi = WIN32OLE.connect(cs)
617
+ rescue WIN32OLERuntimeError => e
618
+ raise Error, e
619
+ end
620
+
621
+ query = "select * from win32_group"
622
+ query << " where localaccount = true" if local
623
+
624
+ if grp.kind_of?(Fixnum)
625
+ if local
626
+ query << " and sid like '%-#{grp}'"
627
+ else
628
+ query << " where sid like '%-#{grp}'"
629
+ end
630
+ else
631
+ if local
632
+ query << " and name = '#{grp}'"
633
+ else
634
+ query << " where name = '#{grp}'"
635
+ end
636
+ end
637
+
638
+ wmi.execquery(query).each{ |group|
639
+ gid = group.sid.split("-").last.to_i
640
+
641
+ # Because our 'like' query isn't fulproof, let's parse
642
+ # the SID again to make sure
643
+ if grp.kind_of?(Fixnum)
644
+ next if grp != gid
645
+ end
646
+
647
+ grp = Group.new do |g|
648
+ g.caption = group.caption
649
+ g.description = group.description
650
+ g.domain = group.domain
651
+ g.gid = gid
652
+ g.install_date = group.installdate
653
+ g.local = group.localaccount
654
+ g.name = group.name
655
+ g.sid = group.sid
656
+ g.sid_type = group.sidtype
657
+ g.status = group.status
658
+ end
659
+ return grp
660
+ }
661
+ # If we're here, it means it wasn't found.
662
+ raise Error, "no group found for '#{grp}'"
663
+ end
664
+
665
+ # In block form, yields a Group object for each user on the system. In
666
+ # non-block form, returns an Array of Group objects.
667
+ #
668
+ # call-seq:
669
+ # groups(host=localhost, local=true)
670
+ # groups(host=localhost, local=true){ |group| ... }
671
+ #
672
+ # You may specify a host from which information is retrieved.
673
+ # The default is the local machine. You can retrieve either a global or
674
+ # local group, depending on the value of the +local+ argument.
675
+ #
676
+ def self.groups(host=Socket.gethostname, local=true)
677
+ host = Socket.gethostname if host.nil?
678
+ cs = "winmgmts:{impersonationLevel=impersonate}!"
679
+ cs << "//#{host}/root/cimv2"
680
+
681
+ begin
682
+ wmi = WIN32OLE.connect(cs)
683
+ rescue WIN32OLERuntimeError => e
684
+ raise Error, e
685
+ end
686
+
687
+ query = "select * from win32_group"
688
+ query << " where localaccount = true" if local
689
+
690
+ array = []
691
+ wmi.execquery(query).each{ |group|
692
+ grp = Group.new do |g|
693
+ g.caption = group.caption
694
+ g.description = group.description
695
+ g.domain = group.domain
696
+ g.gid = group.sid.split("-").last.to_i
697
+ g.install_date = group.installdate
698
+ g.local = group.localaccount
699
+ g.name = group.name
700
+ g.sid = group.sid
701
+ g.sid_type = group.sidtype
702
+ g.status = group.status
703
+ end
704
+ if block_given?
705
+ yield grp
706
+ else
707
+ array.push(grp)
708
+ end
709
+ }
710
+ return array unless block_given?
711
+ end
712
+ end
713
+ end