sys-admin 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,411 @@
1
+ #include <limits.h>
2
+ #include <stdlib.h>
3
+ #include <stdio.h>
4
+ #include <unistd.h>
5
+ #include <pwd.h>
6
+ #include <grp.h>
7
+ #include <fcntl.h>
8
+ #include <errno.h>
9
+ #include <string.h>
10
+
11
+ #define SYS_ADMIN_VERSION "1.3.1"
12
+
13
+ #ifdef HAVE_LASTLOG_H
14
+ #include <lastlog.h>
15
+ #else
16
+ #include <utmp.h>
17
+ #endif
18
+
19
+ #ifndef _POSIX_LOGIN_NAME_MAX
20
+ #define _POSIX_LOGIN_NAME_MAX 9
21
+ #endif
22
+
23
+ #ifdef _SC_GETPW_R_SIZE_MAX
24
+ #define USER_BUF_SIZE (sysconf(_SC_GETPW_R_SIZE_MAX))
25
+ #else
26
+ #define USER_BUF_SIZE 1024
27
+ #endif
28
+
29
+ #ifdef _SC_GETGR_R_SIZE_MAX
30
+ #define GROUP_BUF_SIZE (sysconf(_SC_GETGR_R_SIZE_MAX))
31
+ #else
32
+ #define GROUP_BUF_SIZE 7296
33
+ #endif
34
+
35
+ #ifndef _PATH_LASTLOG
36
+ #define _PATH_LASTLOG "/var/adm/lastlog"
37
+ #endif
38
+
39
+ /* Function prototypes */
40
+ static VALUE get_user(struct passwd* p);
41
+ static VALUE get_group(struct group* g);
42
+ int get_lastlog_info(const char* n, VALUE rbVal);
43
+
44
+ VALUE cUser, cGroup, cAdminError;
45
+
46
+ /*
47
+ * :no-doc:
48
+ *
49
+ * Helper function that returns a User object based on user ID.
50
+ */
51
+ static VALUE get_user_by_num(VALUE rbUID){
52
+ VALUE rbUser;
53
+ uid_t uid = NUM2INT(rbUID);
54
+
55
+ #ifdef HAVE_GETPWUID_R
56
+ char buf[USER_BUF_SIZE];
57
+ struct passwd pwd;
58
+ struct passwd* pwdbuf;
59
+
60
+ if(getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwdbuf) != 0)
61
+ rb_raise(cAdminError, "%s", strerror(errno));
62
+
63
+ if(!pwdbuf)
64
+ rb_raise(cAdminError, "no user found for %i:", uid);
65
+
66
+ rbUser = get_user(pwdbuf);
67
+ #elif HAVE_GETPWUID
68
+ struct passwd* pwd;
69
+ if( (pwd = getpwuid(uid)) == NULL)
70
+ rb_raise(cAdminError, "no user found for: %i", uid);
71
+
72
+ rbUser = get_user(pwd);
73
+ #else
74
+ rb_raise(rb_eNotImpError, "getting user by user ID not supported");
75
+ #endif
76
+
77
+ return rbUser;
78
+ }
79
+
80
+ /*
81
+ * :no-doc:
82
+ *
83
+ * Helper function that returns a User object based on name.
84
+ */
85
+ static VALUE get_user_by_name(VALUE rbName){
86
+ VALUE rbUser;
87
+ SafeStringValue(rbName);
88
+
89
+ #ifdef HAVE_GETPWNAM_R
90
+ char buf[USER_BUF_SIZE];
91
+ struct passwd pwd;
92
+ struct passwd* pwdbuf;
93
+
94
+ if(getpwnam_r(RSTRING(rbName)->ptr, &pwd, buf, sizeof(buf), &pwdbuf) != 0)
95
+ rb_raise(cAdminError, "%s", strerror(errno));
96
+
97
+ if(!pwdbuf)
98
+ rb_raise(cAdminError, "no user found for %s", StringValuePtr(rbName));
99
+
100
+ rbUser = get_user(pwdbuf);
101
+ #elif HAVE_GETPWNAM
102
+ struct passwd* pwd;
103
+ if( (pwd = getpwnam(RSTRING(rbName)->ptr)) == NULL)
104
+ rb_raise(cAdminError, "no user found for %s", StringValuePtr(rbName));
105
+
106
+ rbUser = get_user(pwd);
107
+ #else
108
+ rb_raise(rb_eNotImpError, "getting user by name not supported");
109
+ #endif
110
+
111
+ return rbUser;
112
+ }
113
+
114
+ /*
115
+ * :no-doc:
116
+ *
117
+ * Helper function that returns a Group object based on group ID.
118
+ */
119
+ static VALUE get_group_by_num(VALUE rbGID){
120
+ VALUE rbGroup;
121
+ gid_t gid = NUM2INT(rbGID);
122
+
123
+ #ifdef HAVE_GETGRGID_R
124
+ char buf[GROUP_BUF_SIZE];
125
+ struct group grp;
126
+ struct group* grpbuf;
127
+
128
+ if(getgrgid_r(gid, &grp, buf, sizeof(buf), &grpbuf) != 0)
129
+ rb_raise(cAdminError, "%s", strerror(errno));
130
+
131
+ if(!grpbuf)
132
+ rb_raise(cAdminError, "no group found for group ID: %i", gid);
133
+
134
+ rbGroup = get_group(grpbuf);
135
+ #elif HAVE_GETGRGID
136
+ struct group* grp;
137
+ if( (grp = getgrgid(gid)) == NULL)
138
+ rb_raise(cAdminError, "no group found for group ID: %i", gid);
139
+
140
+ rbGroup = get_group(grp);
141
+ #else
142
+ rb_raise(rb_eNotImpError, "getting group by group ID not supported");
143
+ #endif
144
+
145
+ return rbGroup;
146
+ }
147
+
148
+ /*
149
+ * :no-doc:
150
+ *
151
+ * Helper function that returns a Group object based on group name.
152
+ */
153
+ static VALUE get_group_by_name(VALUE rbName){
154
+ VALUE rbGroup = Qnil;
155
+ SafeStringValue(rbName);
156
+ #ifdef HAVE_GETGRNAM_R
157
+ char buf[GROUP_BUF_SIZE];
158
+ struct group grp;
159
+ struct group* grpbuf;
160
+
161
+ if(getgrnam_r(RSTRING(rbName)->ptr, &grp, buf, sizeof(buf), &grpbuf) != 0)
162
+ rb_raise(cAdminError, "%s", strerror(errno));
163
+
164
+ if(!grpbuf)
165
+ rb_raise(cAdminError, "no group found for: %s", StringValuePtr(rbName));
166
+
167
+ rbGroup = get_group(grpbuf);
168
+ #elif HAVE_GETGRNAM
169
+ struct group* grp
170
+ if((grp = getgrnam(RSTRING(rbName)->ptr)) == NULL)
171
+ rb_raise(cAdminError, "no group found for: %s", StringValuePtr(rbName));
172
+
173
+ rbGroup = get_group(grp);
174
+ #else
175
+ rb_raise(rb_eNotImpError,"get_group is not supported on this platform");
176
+ #endif
177
+
178
+ return rbGroup;
179
+ }
180
+
181
+ /*
182
+ * :no-doc:
183
+ *
184
+ * Helper function that turns a struct passwd into a User object.
185
+ */
186
+ static VALUE get_user(struct passwd* p){
187
+ VALUE rbUser = rb_funcall(cUser,rb_intern("new"),0,0);
188
+
189
+ rb_iv_set(rbUser, "@name", rb_str_new2(p->pw_name));
190
+ rb_iv_set(rbUser, "@uid", INT2FIX(p->pw_uid));
191
+ rb_iv_set(rbUser, "@gid", INT2FIX(p->pw_gid));
192
+ rb_iv_set(rbUser, "@dir", rb_str_new2(p->pw_dir));
193
+ rb_iv_set(rbUser, "@shell", rb_str_new2(p->pw_shell));
194
+
195
+ #ifdef HAVE_ST_PW_PASSWD
196
+ rb_iv_set(rbUser, "@passwd", rb_str_new2(p->pw_passwd));
197
+ #endif
198
+
199
+ #ifdef HAVE_ST_PW_AGE
200
+ rb_iv_set(rbUser, "@age", INT2FIX(p->pw_age));
201
+ #endif
202
+
203
+ #ifdef HAVE_ST_PW_COMMENT
204
+ rb_iv_set(rbUser, "@comment", rb_str_new2(p->pw_comment));
205
+ #endif
206
+
207
+ #ifdef HAVE_ST_PW_GECOS
208
+ rb_iv_set(rbUser, "@gecos", rb_str_new2(p->pw_gecos));
209
+ #endif
210
+
211
+ #ifdef HAVE_ST_PW_QUOTA
212
+ rb_iv_set(rbUser, "@quota", INT2FIX(p->pw_quota));
213
+ #endif
214
+
215
+ #ifdef HAVE_ST_PW_CLASS
216
+ rb_iv_set(rbUser, "@class", rb_str_new2(p->pw_class));
217
+ #endif
218
+
219
+ #ifdef HAVE_ST_PW_EXPIRE
220
+ rb_iv_set(rbUser, "@expire", INT2FIX(p->pw_expire));
221
+ #endif
222
+
223
+ /* Get the lastlog info for the given user */
224
+ get_lastlog_info(p->pw_name, rbUser);
225
+
226
+ return rbUser;
227
+ }
228
+
229
+ /*
230
+ * :no-doc:
231
+ *
232
+ * Helper function that turns a User object into a struct passwd.
233
+ */
234
+ void get_user_from_value(VALUE rbUser, struct passwd* pwd){
235
+
236
+ VALUE rbName = rb_iv_get(rbUser, "@name");
237
+ VALUE rbUID = rb_iv_get(rbUser, "@uid");
238
+ VALUE rbGID = rb_iv_get(rbUser, "@gid");
239
+ VALUE rbDir = rb_iv_get(rbUser, "@dir");
240
+ VALUE rbShell = rb_iv_get(rbUser, "@shell");
241
+
242
+ if(NIL_P(rbName))
243
+ rb_raise(cAdminError, "user name cannot be nil");
244
+
245
+ if(!NIL_P(rbUID))
246
+ pwd->pw_uid = NUM2INT(rbUID);
247
+
248
+ if(!NIL_P(rbGID))
249
+ pwd->pw_gid = NUM2INT(rbGID);
250
+
251
+ if(!NIL_P(rbDir)){
252
+ SafeStringValue(rbDir);
253
+ pwd->pw_dir = StringValuePtr(rbDir);
254
+ }
255
+
256
+ if(!NIL_P(rbShell)){
257
+ SafeStringValue(rbShell);
258
+ pwd->pw_shell = StringValuePtr(rbShell);
259
+ }
260
+
261
+ #ifdef HAVE_ST_PW_PASSWD
262
+ VALUE rbPasswd = rb_iv_get(rbUser, "@passwd");
263
+ if(!NIL_P(rbPasswd)){
264
+ SafeStringValue(rbPasswd);
265
+ pwd->pw_passwd = StringValuePtr(rbPasswd);
266
+ }
267
+ #endif
268
+
269
+ #ifdef HAVE_ST_PW_AGE
270
+ VALUE rbAge = rb_iv_get(rbUser, "@age");
271
+ if(!NIL_P(rbAge))
272
+ pwd->pw_age = (char*)NUM2INT(rbAge);
273
+ #endif
274
+
275
+ #ifdef HAVE_ST_PW_COMMENT
276
+ VALUE rbComment = rb_iv_get(rbUser, "@comment");
277
+ if(!NIL_P(rbComment)){
278
+ SafeStringValue(rbComment);
279
+ pwd->pw_comment = StringValuePtr(rbComment);
280
+ }
281
+ #endif
282
+
283
+ #ifdef HAVE_ST_PW_GECOS
284
+ VALUE rbGecos = rb_iv_get(rbUser, "@gecos");
285
+ if(!NIL_P(rbGecos)){
286
+ SafeStringValue(rbGecos);
287
+ pwd->pw_gecos = StringValuePtr(rbGecos);
288
+ }
289
+ #endif
290
+
291
+ #ifdef HAVE_ST_PW_QUOTA
292
+ VALUE rbQuota = rb_iv_get(rbUser, "@quota");
293
+ if(!NIL_P(rbQuota))
294
+ pwd->pw_quota = NUM2INT(rbQuota);
295
+ #endif
296
+
297
+ #ifdef HAVE_ST_PW_CLASS
298
+ VALUE rbClass = rb_iv_get(rbUser, "@class");
299
+ if(!NIL_P(rbClass)){
300
+ SafeStringValue(rbClass);
301
+ pwd->pw_class = StringValuePtr(rbClass);
302
+ }
303
+ #endif
304
+
305
+ #ifdef HAVE_ST_PW_EXPIRE
306
+ VALUE rbExpire = rb_iv_get(rbUser, "@expire");
307
+ if(!NIL_P(rbExpire))
308
+ pwd->pw_expire = NUM2INT(rbExpire);
309
+ #endif
310
+
311
+ }
312
+
313
+ /*
314
+ * :no-doc:
315
+ *
316
+ * Helper function that turns a struct grp into a Group object.
317
+ */
318
+ static VALUE get_group(struct group* g){
319
+ VALUE rbGroup = rb_funcall(cGroup,rb_intern("new"),0,0);
320
+ VALUE rbArray = rb_ary_new();
321
+
322
+ /* Return the members as an Array of Strings */
323
+ while(*g->gr_mem){
324
+ rb_ary_push(rbArray, rb_str_new2(*g->gr_mem));
325
+ g->gr_mem++;
326
+ }
327
+
328
+ rb_iv_set(rbGroup, "@name", rb_str_new2(g->gr_name));
329
+ rb_iv_set(rbGroup, "@gid", INT2FIX(g->gr_gid));
330
+ rb_iv_set(rbGroup, "@members", rbArray);
331
+ #ifdef HAVE_ST_GR_PASSWD
332
+ rb_iv_set(rbGroup, "@passwd", rb_str_new2(g->gr_passwd));
333
+ #endif
334
+
335
+ return rbGroup;
336
+ }
337
+
338
+ /*
339
+ * :no-doc:
340
+ *
341
+ * Helper function that turns a Group object into a struct group.
342
+ */
343
+ void get_group_from_value(VALUE rbGroup, struct group* grp){
344
+ char** members = malloc(sizeof(char*));
345
+ VALUE rbName = rb_iv_get(rbGroup, "@name");
346
+ VALUE rbGID = rb_iv_get(rbGroup, "@gid");
347
+ VALUE rbMem = rb_iv_get(rbGroup, "@members");
348
+ VALUE rbPasswd = rb_iv_get(rbGroup, "@passwd");
349
+ int i = 0;
350
+
351
+ if(NIL_P(rbName))
352
+ rb_raise(cAdminError, "group name must be set");
353
+
354
+ SafeStringValue(rbName);
355
+ grp->gr_name = StringValuePtr(rbName);
356
+
357
+ if(!NIL_P(rbGID))
358
+ grp->gr_gid = NUM2INT(rbGID);
359
+
360
+ if(!NIL_P(rbMem)){
361
+ VALUE rbVal;
362
+ while((rbVal = rb_ary_shift(rbMem)) != Qnil){
363
+ members[i] = StringValuePtr(rbVal);
364
+ i++;
365
+ }
366
+ members[i] = '\0';
367
+ grp->gr_mem = members;
368
+ }
369
+
370
+ #ifdef HAVE_ST_GR_PASSWD
371
+ if(!NIL_P(rbPasswd)){
372
+ SafeStringValue(rbPasswd);
373
+ grp->gr_passwd = StringValuePtr(rbPasswd);
374
+ }
375
+ #endif
376
+
377
+ free(members);
378
+ }
379
+
380
+ /*
381
+ * :no-doc:
382
+ *
383
+ * Helper function that gets lastlog information for the User object.
384
+ */
385
+ int get_lastlog_info(const char* name, VALUE rbUser){
386
+ int fd;
387
+ struct lastlog log;
388
+ struct passwd* pwd;
389
+ int ll_size = sizeof(struct lastlog);
390
+
391
+ /* The lastlog information is not necessarily readable by all users, so
392
+ * ignore open() errors if they occur.
393
+ */
394
+ if((fd = open(_PATH_LASTLOG, O_RDONLY)) == -1)
395
+ return -1;
396
+
397
+ if((pwd = getpwnam(name)) == NULL)
398
+ rb_sys_fail(0);
399
+
400
+ pread(fd, &log, ll_size, pwd->pw_uid * ll_size);
401
+ close(fd);
402
+
403
+ #ifdef HAVE_ST_LL_TIME
404
+ if(log.ll_time != 0)
405
+ rb_iv_set(rbUser, "@login_time", rb_time_new(log.ll_time, 0));
406
+ #endif
407
+ rb_iv_set(rbUser, "@login_device", rb_str_new2(log.ll_line));
408
+ rb_iv_set(rbUser, "@login_host", rb_str_new2(log.ll_host));
409
+
410
+ return 0;
411
+ }
@@ -0,0 +1,403 @@
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