sys-admin 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +16 -0
- data/MANIFEST +15 -14
- data/README +54 -38
- data/examples/groups.rb +3 -3
- data/examples/users.rb +21 -3
- data/{lib/sys/unix.c → ext/admin.c} +50 -60
- data/ext/admin.h +428 -0
- data/{extconf.rb → ext/extconf.rb} +4 -8
- data/test/tc_admin.rb +1 -1
- data/test/tc_unix.rb +5 -5
- data/test/{tc_win32.rb → tc_windows.rb} +68 -4
- metadata +9 -7
- data/lib/sys/unix.h +0 -411
- data/lib/sys/win32.orig +0 -403
data/lib/sys/win32.orig
DELETED
@@ -1,403 +0,0 @@
|
|
1
|
-
require "win32ole"
|
2
|
-
require "Win32API"
|
3
|
-
require "socket"
|
4
|
-
|
5
|
-
module Sys
|
6
|
-
class AdminError < StandardError; end
|
7
|
-
|
8
|
-
class Group
|
9
|
-
attr_accessor :caption, :description, :domain, :install_date
|
10
|
-
attr_accessor :name, :sid, :status, :gid
|
11
|
-
attr_writer :local
|
12
|
-
def initialize
|
13
|
-
yield self if block_given?
|
14
|
-
end
|
15
|
-
|
16
|
-
def local?
|
17
|
-
@local
|
18
|
-
end
|
19
|
-
|
20
|
-
def sid_type
|
21
|
-
@sid_type
|
22
|
-
end
|
23
|
-
|
24
|
-
def sid_type=(stype)
|
25
|
-
case stype
|
26
|
-
when 1
|
27
|
-
@sid_type = "user"
|
28
|
-
when 2
|
29
|
-
@sid_type = "group"
|
30
|
-
when 3
|
31
|
-
@sid_type = "domain"
|
32
|
-
when 4
|
33
|
-
@sid_type = "alias"
|
34
|
-
when 5
|
35
|
-
@sid_type = "well_known_group"
|
36
|
-
when 6
|
37
|
-
@sid_type = "deleted_account"
|
38
|
-
when 7
|
39
|
-
@sid_type = "invalid"
|
40
|
-
when 8
|
41
|
-
@sid_type = "unknown"
|
42
|
-
when 9
|
43
|
-
@sid_type = "computer"
|
44
|
-
else
|
45
|
-
@sid_type = "unknown"
|
46
|
-
end
|
47
|
-
@sid_type
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
class User
|
52
|
-
|
53
|
-
attr_accessor :caption, :description, :domain, :password
|
54
|
-
attr_accessor :full_name, :install_date, :name, :sid, :status
|
55
|
-
attr_writer :disabled, :local, :lockout, :password_changeable
|
56
|
-
attr_writer :password_expires, :password_required
|
57
|
-
attr_reader :account_type
|
58
|
-
|
59
|
-
def initialize
|
60
|
-
yield self if block_given?
|
61
|
-
end
|
62
|
-
|
63
|
-
def account_type=(type)
|
64
|
-
case type
|
65
|
-
when 256
|
66
|
-
@account_type = "duplicate"
|
67
|
-
when 512
|
68
|
-
@account_type = "normal"
|
69
|
-
when 2048
|
70
|
-
@account_type = "interdomain_trust"
|
71
|
-
when 4096
|
72
|
-
@account_type = "workstation_trust"
|
73
|
-
when 8192
|
74
|
-
@account_type = "server_trust"
|
75
|
-
else
|
76
|
-
@account_type = "unknown"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def sid_type
|
81
|
-
@sid_type
|
82
|
-
end
|
83
|
-
|
84
|
-
def sid_type=(stype)
|
85
|
-
case stype
|
86
|
-
when 1
|
87
|
-
@sid_type = "user"
|
88
|
-
when 2
|
89
|
-
@sid_type = "group"
|
90
|
-
when 3
|
91
|
-
@sid_type = "domain"
|
92
|
-
when 4
|
93
|
-
@sid_type = "alias"
|
94
|
-
when 5
|
95
|
-
@sid_type = "well_known_group"
|
96
|
-
when 6
|
97
|
-
@sid_type = "deleted_account"
|
98
|
-
when 7
|
99
|
-
@sid_type = "invalid"
|
100
|
-
when 8
|
101
|
-
@sid_type = "unknown"
|
102
|
-
when 9
|
103
|
-
@sid_type = "computer"
|
104
|
-
else
|
105
|
-
@sid_type = "unknown"
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def disabled?
|
110
|
-
@disabled
|
111
|
-
end
|
112
|
-
|
113
|
-
def local?
|
114
|
-
@local
|
115
|
-
end
|
116
|
-
|
117
|
-
def lockout?
|
118
|
-
@lockout
|
119
|
-
end
|
120
|
-
|
121
|
-
def password_changeable?
|
122
|
-
@password_changeable
|
123
|
-
end
|
124
|
-
|
125
|
-
def password_expires?
|
126
|
-
@password_expires
|
127
|
-
end
|
128
|
-
|
129
|
-
def password_required?
|
130
|
-
@password_required
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
class Admin
|
135
|
-
VERSION = "1.3.1"
|
136
|
-
|
137
|
-
# Deletes +userid+ from the given +host+, or the local host if no host
|
138
|
-
# is specified.
|
139
|
-
#
|
140
|
-
def self.delete_user(userid=nil, host=Socket.gethostname)
|
141
|
-
begin
|
142
|
-
adsi = WIN32OLE.connect("WinNT://#{host},Computer")
|
143
|
-
rescue WIN32OLERuntimeError => err
|
144
|
-
raise AdminError, err
|
145
|
-
end
|
146
|
-
|
147
|
-
begin
|
148
|
-
adsi.delete("user", userid)
|
149
|
-
rescue WIN32OLERuntimeError => err
|
150
|
-
raise AdminError, err
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# Returns the user name (only) of the current login.
|
155
|
-
#
|
156
|
-
def self.get_login
|
157
|
-
getlogin = Win32API.new("advapi32","GetUserName",['P','P'],'L')
|
158
|
-
buffer = "\0" * 256;
|
159
|
-
nsize = [256].pack("L")
|
160
|
-
getlogin.call(buffer,nsize)
|
161
|
-
len = nsize.unpack("L")[0]
|
162
|
-
username = buffer[0 ... len].chop
|
163
|
-
username
|
164
|
-
end
|
165
|
-
|
166
|
-
# Returns a User object based on either +name+ or +uid+.
|
167
|
-
#
|
168
|
-
# call-seq:
|
169
|
-
# get_user(name, host=localhost)
|
170
|
-
# get_user(uid, host=localhost, local=true)
|
171
|
-
#
|
172
|
-
# You may specify a +host+ from which information is retrieved. The
|
173
|
-
# default is the local machine. You may also specify whether to
|
174
|
-
# retrieve a local or global account. The default is local.
|
175
|
-
#
|
176
|
-
def self.get_user(uid, host=Socket.gethostname, local=true)
|
177
|
-
host = Socket.gethostname if host.nil?
|
178
|
-
cs = "winmgmts:{impersonationLevel=impersonate}!"
|
179
|
-
cs << "//#{host}/root/cimv2"
|
180
|
-
|
181
|
-
begin
|
182
|
-
wmi = WIN32OLE.connect(cs)
|
183
|
-
rescue WIN32OLERuntimeError => e
|
184
|
-
raise AdminError, e
|
185
|
-
end
|
186
|
-
|
187
|
-
query = "select * from win32_useraccount"
|
188
|
-
query << " where localaccount = true" if local
|
189
|
-
|
190
|
-
if uid.kind_of?(Fixnum)
|
191
|
-
if local
|
192
|
-
query << " and sid like '%-#{uid}'"
|
193
|
-
else
|
194
|
-
query << " where sid like '%-#{uid}'"
|
195
|
-
end
|
196
|
-
else
|
197
|
-
if local
|
198
|
-
query << " and name = '#{uid}'"
|
199
|
-
else
|
200
|
-
query << " where name = '#{uid}'"
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
wmi.execquery(query).each{ |user|
|
205
|
-
# Because our 'like' query isn't fulproof, let's parse
|
206
|
-
# the SID again to make sure
|
207
|
-
if uid.kind_of?(Fixnum)
|
208
|
-
if user.sid.split("-").last.to_i != uid
|
209
|
-
next
|
210
|
-
end
|
211
|
-
end
|
212
|
-
usr = User.new do |u|
|
213
|
-
u.account_type = user.accounttype
|
214
|
-
u.caption = user.caption
|
215
|
-
u.description = user.description
|
216
|
-
u.disabled = user.disabled
|
217
|
-
u.domain = user.domain
|
218
|
-
u.full_name = user.fullname
|
219
|
-
u.install_date = user.installdate
|
220
|
-
u.local = user.localaccount
|
221
|
-
u.lockout = user.lockout
|
222
|
-
u.name = user.name
|
223
|
-
u.password_changeable = user.passwordchangeable
|
224
|
-
u.password_expires = user.passwordexpires
|
225
|
-
u.password_required = user.passwordrequired
|
226
|
-
u.sid = user.sid
|
227
|
-
u.sid_type = user.sidtype
|
228
|
-
u.status = user.status
|
229
|
-
end
|
230
|
-
return usr
|
231
|
-
}
|
232
|
-
end
|
233
|
-
|
234
|
-
# In block form, yields a User object for each user on the system. In
|
235
|
-
# non-block form, returns an Array of User objects.
|
236
|
-
#
|
237
|
-
# call-seq:
|
238
|
-
# users(host=localhost, local=true)
|
239
|
-
# users(host=localhost, local=true){ |user| ... }
|
240
|
-
#
|
241
|
-
# You may specify a host from which information is retrieved. The
|
242
|
-
# default is the local machine. You can retrieve either a global or
|
243
|
-
# group, depending on the value of the +local+ argument.
|
244
|
-
#
|
245
|
-
def self.users(host=Socket.gethostname, local=true)
|
246
|
-
host = Socket.gethostname if host.nil?
|
247
|
-
cs = "winmgmts:{impersonationLevel=impersonate}!"
|
248
|
-
cs << "//#{host}/root/cimv2"
|
249
|
-
|
250
|
-
begin
|
251
|
-
wmi = WIN32OLE.connect(cs)
|
252
|
-
rescue WIN32OLERuntimeError => e
|
253
|
-
raise AdminError, e
|
254
|
-
end
|
255
|
-
|
256
|
-
query = "select * from win32_useraccount"
|
257
|
-
query << " where localaccount = true" if local
|
258
|
-
array = []
|
259
|
-
|
260
|
-
wmi.execquery(query).each{ |user|
|
261
|
-
usr = User.new do |u|
|
262
|
-
u.account_type = user.accounttype
|
263
|
-
u.caption = user.caption
|
264
|
-
u.description = user.description
|
265
|
-
u.disabled = user.disabled
|
266
|
-
u.domain = user.domain
|
267
|
-
u.full_name = user.fullname
|
268
|
-
u.install_date = user.installdate
|
269
|
-
u.local = user.localaccount
|
270
|
-
u.lockout = user.lockout
|
271
|
-
u.name = user.name
|
272
|
-
u.password_changeable = user.passwordchangeable
|
273
|
-
u.password_expires = user.passwordexpires
|
274
|
-
u.password_required = user.passwordrequired
|
275
|
-
u.sid = user.sid
|
276
|
-
u.sid_type = user.sidtype
|
277
|
-
u.status = user.status
|
278
|
-
end
|
279
|
-
|
280
|
-
if block_given?
|
281
|
-
yield usr
|
282
|
-
else
|
283
|
-
array.push(usr)
|
284
|
-
end
|
285
|
-
}
|
286
|
-
return array unless block_given?
|
287
|
-
end
|
288
|
-
|
289
|
-
# Returns a Group object based on either +name+ or +uid+.
|
290
|
-
#
|
291
|
-
# call-seq:
|
292
|
-
# get_group(name, host=localhost, local=true)
|
293
|
-
# get_group(gid, host=localhost, local=true)
|
294
|
-
#
|
295
|
-
# You may specify a host from which information is retrieved.
|
296
|
-
# The default is the local machine. You can retrieve either a global or
|
297
|
-
# local group, depending on the value of the +local+ argument.
|
298
|
-
#
|
299
|
-
def self.get_group(grp, host=Socket.gethostname, local=true)
|
300
|
-
host = Socket.gethostname if host.nil?
|
301
|
-
cs = "winmgmts:{impersonationLevel=impersonate}!"
|
302
|
-
cs << "//#{host}/root/cimv2"
|
303
|
-
gid = nil
|
304
|
-
|
305
|
-
begin
|
306
|
-
wmi = WIN32OLE.connect(cs)
|
307
|
-
rescue WIN32OLERuntimeError => e
|
308
|
-
raise AdminError, e
|
309
|
-
end
|
310
|
-
|
311
|
-
query = "select * from win32_group"
|
312
|
-
query << " where localaccount = true" if local
|
313
|
-
|
314
|
-
if grp.kind_of?(Fixnum)
|
315
|
-
if local
|
316
|
-
query << " and sid like '%-#{grp}'"
|
317
|
-
else
|
318
|
-
query << " where sid like '%-#{grp}'"
|
319
|
-
end
|
320
|
-
else
|
321
|
-
if local
|
322
|
-
query << " and name = '#{grp}'"
|
323
|
-
else
|
324
|
-
query << " where name = '#{grp}'"
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
wmi.execquery(query).each{ |group|
|
329
|
-
gid = group.sid.split("-").last.to_i
|
330
|
-
|
331
|
-
# Because our 'like' query isn't fulproof, let's parse
|
332
|
-
# the SID again to make sure
|
333
|
-
if grp.kind_of?(Fixnum)
|
334
|
-
next if grp != gid
|
335
|
-
end
|
336
|
-
|
337
|
-
grp = Group.new do |g|
|
338
|
-
g.caption = group.caption
|
339
|
-
g.description = group.description
|
340
|
-
g.domain = group.domain
|
341
|
-
g.gid = gid
|
342
|
-
g.install_date = group.installdate
|
343
|
-
g.local = group.localaccount
|
344
|
-
g.name = group.name
|
345
|
-
g.sid = group.sid
|
346
|
-
g.sid_type = group.sidtype
|
347
|
-
g.status = group.status
|
348
|
-
end
|
349
|
-
return grp
|
350
|
-
}
|
351
|
-
# If we're here, it means it wasn't found.
|
352
|
-
raise AdminError, "no group found for '#{grp}'"
|
353
|
-
end
|
354
|
-
|
355
|
-
# In block form, yields a Group object for each user on the system. In
|
356
|
-
# non-block form, returns an Array of Group objects.
|
357
|
-
#
|
358
|
-
# call-seq:
|
359
|
-
# groups(host=localhost, local=true)
|
360
|
-
# groups(host=localhost, local=true){ |group| ... }
|
361
|
-
#
|
362
|
-
# You may specify a host from which information is retrieved.
|
363
|
-
# The default is the local machine. You can retrieve either a global or
|
364
|
-
# local group, depending on the value of the +local+ argument.
|
365
|
-
#
|
366
|
-
def self.groups(host=Socket.gethostname, local=true)
|
367
|
-
host = Socket.gethostname if host.nil?
|
368
|
-
cs = "winmgmts:{impersonationLevel=impersonate}!"
|
369
|
-
cs << "//#{host}/root/cimv2"
|
370
|
-
|
371
|
-
begin
|
372
|
-
wmi = WIN32OLE.connect(cs)
|
373
|
-
rescue WIN32OLERuntimeError => e
|
374
|
-
raise AdminError, e
|
375
|
-
end
|
376
|
-
|
377
|
-
query = "select * from win32_group"
|
378
|
-
query << " where localaccount = true" if local
|
379
|
-
|
380
|
-
array = []
|
381
|
-
wmi.execquery(query).each{ |group|
|
382
|
-
grp = Group.new do |g|
|
383
|
-
g.caption = group.caption
|
384
|
-
g.description = group.description
|
385
|
-
g.domain = group.domain
|
386
|
-
g.gid = group.sid.split("-").last.to_i
|
387
|
-
g.install_date = group.installdate
|
388
|
-
g.local = group.localaccount
|
389
|
-
g.name = group.name
|
390
|
-
g.sid = group.sid
|
391
|
-
g.sid_type = group.sidtype
|
392
|
-
g.status = group.status
|
393
|
-
end
|
394
|
-
if block_given?
|
395
|
-
yield grp
|
396
|
-
else
|
397
|
-
array.push(grp)
|
398
|
-
end
|
399
|
-
}
|
400
|
-
return array unless block_given?
|
401
|
-
end
|
402
|
-
end
|
403
|
-
end
|