win32-security 0.3.1 → 0.3.2
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGES +63 -57
- data/MANIFEST +11 -9
- data/README +53 -53
- data/Rakefile +58 -61
- data/certs/djberg96_pub.pem +21 -0
- data/lib/win32-security.rb +1 -0
- data/lib/win32/security.rb +91 -91
- data/lib/win32/security/ace.rb +75 -75
- data/lib/win32/security/acl.rb +224 -224
- data/lib/win32/security/sid.rb +394 -394
- data/lib/win32/security/windows/constants.rb +184 -184
- data/lib/win32/security/windows/functions.rb +116 -116
- data/lib/win32/security/windows/structs.rb +94 -94
- data/test/test_ace.rb +48 -48
- data/test/test_acl.rb +101 -101
- data/test/test_security.rb +23 -23
- data/test/test_sid.rb +142 -142
- data/win32-security.gemspec +28 -27
- metadata +48 -18
- metadata.gz.sig +0 -0
data/lib/win32/security/ace.rb
CHANGED
@@ -1,75 +1,75 @@
|
|
1
|
-
# The Win32 module serves as a namespace only.
|
2
|
-
module Win32
|
3
|
-
|
4
|
-
# The Security class serves as a toplevel class namespace.
|
5
|
-
class Security
|
6
|
-
|
7
|
-
# The ACE class encapsulates an Access Control Entry, an element within
|
8
|
-
# an Access Control List.
|
9
|
-
class ACE
|
10
|
-
# The version of the Win32::Security::ACE class.
|
11
|
-
VERSION = '0.1.0'
|
12
|
-
|
13
|
-
# The ACE type, e.g. ACCESS_ALLOWED, ACCESS_DENIED, etc. This is an integer.
|
14
|
-
attr_accessor :ace_type
|
15
|
-
|
16
|
-
# Standard access rights, e.g. GENERIC_READ, GENERIC_WRITE, etc.
|
17
|
-
# This is an integer.
|
18
|
-
attr_accessor :access_mask
|
19
|
-
|
20
|
-
# Bit flags associated with the ACE, e.g. OBJECT_INHERIT_ACE, etc.
|
21
|
-
# This is an integer.
|
22
|
-
attr_reader :flags
|
23
|
-
|
24
|
-
# Creates and returns an ACE object.
|
25
|
-
#
|
26
|
-
def initialize(access_mask, ace_type, flags)
|
27
|
-
@access_mask = access_mask
|
28
|
-
@ace_type = ace_type
|
29
|
-
@flags = flags
|
30
|
-
yield self if block_given?
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns the type of ace as a string, e.g. "ACCESS_ALLOWED_TYPE_ACE".
|
34
|
-
#
|
35
|
-
def ace_type_string
|
36
|
-
case @ace_type
|
37
|
-
when 0x0
|
38
|
-
'ACCESS_ALLOWED_ACE_TYPE'
|
39
|
-
when 0x1
|
40
|
-
'ACCESS_DENIED_ACE_TYPE'
|
41
|
-
when 0x2
|
42
|
-
'SYSTEM_AUDIT_ACE_TYPE'
|
43
|
-
when 0x3
|
44
|
-
'SYSTEM_ALARM_ACE_TYPE'
|
45
|
-
when 0x4
|
46
|
-
'ACCESS_ALLOWED_COMPOUND_ACE_TYPE'
|
47
|
-
when 0x5
|
48
|
-
'ACCESS_ALLOWED_OBJECT_ACE_TYPE'
|
49
|
-
when 0x6
|
50
|
-
'ACCESS_DENIED_OBJECT_ACE_TYPE'
|
51
|
-
when 0x7
|
52
|
-
'SYSTEM_AUDIT_OBJECT_ACE_TYPE'
|
53
|
-
when 0x8
|
54
|
-
'SYSTEM_ALARM_OBJECT_ACE_TYPE'
|
55
|
-
when 0x9
|
56
|
-
'ACCESS_ALLOWED_CALLBACK_ACE_TYPE'
|
57
|
-
when 0xA
|
58
|
-
'ACCESS_DENIED_CALLBACK_ACE_TYPE'
|
59
|
-
when 0xB
|
60
|
-
'ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE'
|
61
|
-
when 0xC
|
62
|
-
'ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE'
|
63
|
-
when 0xD
|
64
|
-
'SYSTEM_AUDIT_CALLBACK_ACE_TYPE'
|
65
|
-
when 0xE
|
66
|
-
'SYSTEM_ALARM_CALLBACK_ACE_TYPE'
|
67
|
-
when 0xF
|
68
|
-
'SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE'
|
69
|
-
when 0x10
|
70
|
-
'SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE'
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
1
|
+
# The Win32 module serves as a namespace only.
|
2
|
+
module Win32
|
3
|
+
|
4
|
+
# The Security class serves as a toplevel class namespace.
|
5
|
+
class Security
|
6
|
+
|
7
|
+
# The ACE class encapsulates an Access Control Entry, an element within
|
8
|
+
# an Access Control List.
|
9
|
+
class ACE
|
10
|
+
# The version of the Win32::Security::ACE class.
|
11
|
+
VERSION = '0.1.0'
|
12
|
+
|
13
|
+
# The ACE type, e.g. ACCESS_ALLOWED, ACCESS_DENIED, etc. This is an integer.
|
14
|
+
attr_accessor :ace_type
|
15
|
+
|
16
|
+
# Standard access rights, e.g. GENERIC_READ, GENERIC_WRITE, etc.
|
17
|
+
# This is an integer.
|
18
|
+
attr_accessor :access_mask
|
19
|
+
|
20
|
+
# Bit flags associated with the ACE, e.g. OBJECT_INHERIT_ACE, etc.
|
21
|
+
# This is an integer.
|
22
|
+
attr_reader :flags
|
23
|
+
|
24
|
+
# Creates and returns an ACE object.
|
25
|
+
#
|
26
|
+
def initialize(access_mask, ace_type, flags)
|
27
|
+
@access_mask = access_mask
|
28
|
+
@ace_type = ace_type
|
29
|
+
@flags = flags
|
30
|
+
yield self if block_given?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the type of ace as a string, e.g. "ACCESS_ALLOWED_TYPE_ACE".
|
34
|
+
#
|
35
|
+
def ace_type_string
|
36
|
+
case @ace_type
|
37
|
+
when 0x0
|
38
|
+
'ACCESS_ALLOWED_ACE_TYPE'
|
39
|
+
when 0x1
|
40
|
+
'ACCESS_DENIED_ACE_TYPE'
|
41
|
+
when 0x2
|
42
|
+
'SYSTEM_AUDIT_ACE_TYPE'
|
43
|
+
when 0x3
|
44
|
+
'SYSTEM_ALARM_ACE_TYPE'
|
45
|
+
when 0x4
|
46
|
+
'ACCESS_ALLOWED_COMPOUND_ACE_TYPE'
|
47
|
+
when 0x5
|
48
|
+
'ACCESS_ALLOWED_OBJECT_ACE_TYPE'
|
49
|
+
when 0x6
|
50
|
+
'ACCESS_DENIED_OBJECT_ACE_TYPE'
|
51
|
+
when 0x7
|
52
|
+
'SYSTEM_AUDIT_OBJECT_ACE_TYPE'
|
53
|
+
when 0x8
|
54
|
+
'SYSTEM_ALARM_OBJECT_ACE_TYPE'
|
55
|
+
when 0x9
|
56
|
+
'ACCESS_ALLOWED_CALLBACK_ACE_TYPE'
|
57
|
+
when 0xA
|
58
|
+
'ACCESS_DENIED_CALLBACK_ACE_TYPE'
|
59
|
+
when 0xB
|
60
|
+
'ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE'
|
61
|
+
when 0xC
|
62
|
+
'ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE'
|
63
|
+
when 0xD
|
64
|
+
'SYSTEM_AUDIT_CALLBACK_ACE_TYPE'
|
65
|
+
when 0xE
|
66
|
+
'SYSTEM_ALARM_CALLBACK_ACE_TYPE'
|
67
|
+
when 0xF
|
68
|
+
'SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE'
|
69
|
+
when 0x10
|
70
|
+
'SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/win32/security/acl.rb
CHANGED
@@ -1,224 +1,224 @@
|
|
1
|
-
# The Win32 module serves as a namespace only.
|
2
|
-
module Win32
|
3
|
-
|
4
|
-
# The Security class serves as a toplevel class namespace.
|
5
|
-
class Security
|
6
|
-
|
7
|
-
# The ACL class encapsulates an Access Control List.
|
8
|
-
class ACL
|
9
|
-
include Windows::Security::Constants
|
10
|
-
include Windows::Security::Functions
|
11
|
-
include Windows::Security::Structs
|
12
|
-
extend Windows::Security::Functions
|
13
|
-
|
14
|
-
# The version of the Win32::Security::ACL class.
|
15
|
-
VERSION = '0.2.0'
|
16
|
-
|
17
|
-
# The underlying ACL structure.
|
18
|
-
attr_reader :acl
|
19
|
-
|
20
|
-
# The revision level.
|
21
|
-
attr_reader :revision
|
22
|
-
|
23
|
-
# Creates and returns a new Win32::Security::ACL object. This object
|
24
|
-
# encapsulates an ACL structure, including a binary representation of
|
25
|
-
# the ACL itself, and the revision information.
|
26
|
-
#
|
27
|
-
def initialize(size = 1024, revision = ACL_REVISION)
|
28
|
-
acl = ACL_STRUCT.new
|
29
|
-
|
30
|
-
unless InitializeAcl(acl, size, revision)
|
31
|
-
raise SystemCallError.new("InitializeAcl", FFI.errno)
|
32
|
-
end
|
33
|
-
|
34
|
-
@acl = acl
|
35
|
-
@revision = revision
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns the number of ACE's in the ACL object.
|
39
|
-
#
|
40
|
-
def ace_count
|
41
|
-
info = ACL_SIZE_INFORMATION.new
|
42
|
-
|
43
|
-
unless GetAclInformation(@acl, info, info.size, AclSizeInformation)
|
44
|
-
raise SystemCallError.new("GetAclInformation", FFI.errno)
|
45
|
-
end
|
46
|
-
|
47
|
-
info[:AceCount]
|
48
|
-
end
|
49
|
-
|
50
|
-
# Returns a two element array that consists of the bytes in use and
|
51
|
-
# bytes free for the ACL.
|
52
|
-
#
|
53
|
-
def byte_info
|
54
|
-
info = ACL_SIZE_INFORMATION.new
|
55
|
-
|
56
|
-
unless GetAclInformation(@acl, info, info.size, AclSizeInformation)
|
57
|
-
raise SystemCallError.new("GetAclInformation", FFI.errno)
|
58
|
-
end
|
59
|
-
|
60
|
-
[info[:AclBytesInUse], info[:AclBytesFree]]
|
61
|
-
end
|
62
|
-
|
63
|
-
# Adds an access allowed ACE to the given +sid+, which can be a
|
64
|
-
# Win32::Security::SID object or a plain user or group name. If no
|
65
|
-
# sid is provided then the owner of the current process is used.
|
66
|
-
#
|
67
|
-
# The +mask+ is a bitwise OR'd value of access rights.
|
68
|
-
#
|
69
|
-
# The +flags+ argument can be anyone of the following constants.
|
70
|
-
#
|
71
|
-
# * OBJECT_INHERIT_ACE
|
72
|
-
# * CONTAINER_INHERIT_ACE
|
73
|
-
# * NO_PROPAGATE_INHERIT_ACE
|
74
|
-
# * INHERIT_ONLY_ACE
|
75
|
-
# * INHERITED_ACE
|
76
|
-
#
|
77
|
-
# Example:
|
78
|
-
#
|
79
|
-
# acl = Win32::Security::ACL.new
|
80
|
-
# acl.add_access_allowed_ace('some_user', GENERIC_READ | GENERIC_WRITE)
|
81
|
-
#
|
82
|
-
def add_access_allowed_ace(sid=nil, mask=0, flags=nil)
|
83
|
-
if sid.is_a?(Win32::Security::SID)
|
84
|
-
sid = sid.sid
|
85
|
-
else
|
86
|
-
sid = Win32::Security::SID.new(sid).sid
|
87
|
-
end
|
88
|
-
|
89
|
-
if flags
|
90
|
-
unless AddAccessAllowedAceEx(@acl, @revision, flags, mask, sid)
|
91
|
-
raise SystemCallError.new("AddAccessAllowedAceEx", FFI.errno)
|
92
|
-
end
|
93
|
-
else
|
94
|
-
unless AddAccessAllowedAce(@acl, @revision, mask, sid)
|
95
|
-
raise SystemCallError.new("AddAccessAllowedAce", FFI.errno)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
sid
|
100
|
-
end
|
101
|
-
|
102
|
-
# Adds an access denied ACE to the given +sid+, which can be a
|
103
|
-
# Win32::Security::SID object ora plain user or group name. If
|
104
|
-
# no sid is provided then the owner of the current process is used.
|
105
|
-
#
|
106
|
-
# The +mask+ is the bitwise OR'd value of access rights.
|
107
|
-
#
|
108
|
-
# The +flags+ argument can be any one of the following constants:
|
109
|
-
#
|
110
|
-
# * OBJECT_INHERIT_ACE
|
111
|
-
# * CONTAINER_INHERIT_ACE
|
112
|
-
# * NO_PROPAGATE_INHERIT_ACE
|
113
|
-
# * INHERIT_ONLY_ACE
|
114
|
-
# * INHERITED_ACE
|
115
|
-
#
|
116
|
-
def add_access_denied_ace(sid=nil, mask=0, flags=nil)
|
117
|
-
if sid.is_a?(Win32::Security::SID)
|
118
|
-
sid = sid.sid
|
119
|
-
else
|
120
|
-
sid = Win32::Security::SID.new(sid).sid
|
121
|
-
end
|
122
|
-
|
123
|
-
if flags
|
124
|
-
unless AddAccessDeniedAceEx(@acl, @revision, flags, mask, sid)
|
125
|
-
raise SystemCallError.new("AddAccessDeniedAceEx", FFI.errno)
|
126
|
-
end
|
127
|
-
else
|
128
|
-
unless AddAccessDeniedAce(@acl, @revision, mask, sid)
|
129
|
-
raise SystemCallError.new("AddAccessDeniedAce", FFI.errno)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# Adds an ACE to the ACL object with the given +revision+ at +index+
|
135
|
-
# or the end of the chain if no index is specified.
|
136
|
-
#
|
137
|
-
# Returns the index if successful.
|
138
|
-
#--
|
139
|
-
# This won't work until we implement the ACE class.
|
140
|
-
#
|
141
|
-
def add_ace(ace, index=MAXDWORD)
|
142
|
-
unless AddAce(@acl, @revision, index, ace, ace.length)
|
143
|
-
raise SystemCallError.new("AddAce", FFI.errno)
|
144
|
-
end
|
145
|
-
|
146
|
-
index
|
147
|
-
end
|
148
|
-
|
149
|
-
# Deletes an ACE from the ACL object at +index+, or from the end of
|
150
|
-
# the chain if no index is specified.
|
151
|
-
#
|
152
|
-
# Returns the index if successful.
|
153
|
-
#
|
154
|
-
def delete_ace(index=MAXDWORD)
|
155
|
-
unless DeleteAce(@acl, index)
|
156
|
-
raise SystemCallError.new("DeleteAce", FFI.errno)
|
157
|
-
end
|
158
|
-
|
159
|
-
index
|
160
|
-
end
|
161
|
-
|
162
|
-
# Finds and returns an ACE object for the ACL at the given
|
163
|
-
# +index+. If no index is provided, then it returns an ACE object
|
164
|
-
# that corresponds to the first free byte of the ACL.
|
165
|
-
#
|
166
|
-
# If +raw+ is true, it will return an ACCESS_GENERIC_ACE struct,
|
167
|
-
# an FFI object that you can then access directly.
|
168
|
-
#
|
169
|
-
def find_ace(index = nil, raw = false)
|
170
|
-
result = nil
|
171
|
-
|
172
|
-
FFI::MemoryPointer.new(:pointer) do |pptr|
|
173
|
-
if index.nil?
|
174
|
-
unless FindFirstFreeAce(@acl, pptr)
|
175
|
-
raise SystemCallError.new("FindFirstFreeAce", FFI.errno)
|
176
|
-
end
|
177
|
-
else
|
178
|
-
unless GetAce(@acl, index, pptr)
|
179
|
-
raise SystemCallError.new("GetAce", FFI.errno)
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
# There's no way to know what type of ACE it is at this point as far
|
184
|
-
# as I know, so we use a generic struct and use the AceType to figure
|
185
|
-
# it out later, or the users can.
|
186
|
-
ace = ACCESS_GENERIC_ACE.new(pptr.read_pointer)
|
187
|
-
|
188
|
-
if raw
|
189
|
-
result = ace
|
190
|
-
else
|
191
|
-
result = ACE.new(ace[:Mask], ace[:Header][:AceType], ace[:Header][:AceFlags])
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
result
|
196
|
-
end
|
197
|
-
|
198
|
-
# Sets the revision information level, where the +revision_level+
|
199
|
-
# can be ACL_REVISION1, ACL_REVISION2, ACL_REVISION3 or ACL_REVISION4.
|
200
|
-
#
|
201
|
-
# Returns the revision level if successful.
|
202
|
-
#
|
203
|
-
def revision=(revision_level)
|
204
|
-
FFI::MemoryPointer.new(:ulong) do |buf|
|
205
|
-
buf.write_ulong(revision_level)
|
206
|
-
|
207
|
-
unless SetAclInformation(@acl, buf, buf.size, AclRevisionInformation)
|
208
|
-
raise SystemCallError.new("SetAclInformation", FFI.errno)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
@revision = revision_level
|
213
|
-
|
214
|
-
revision_level
|
215
|
-
end
|
216
|
-
|
217
|
-
# Returns whether or not the ACL is a valid ACL.
|
218
|
-
#
|
219
|
-
def valid?
|
220
|
-
IsValidAcl(@acl)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
1
|
+
# The Win32 module serves as a namespace only.
|
2
|
+
module Win32
|
3
|
+
|
4
|
+
# The Security class serves as a toplevel class namespace.
|
5
|
+
class Security
|
6
|
+
|
7
|
+
# The ACL class encapsulates an Access Control List.
|
8
|
+
class ACL
|
9
|
+
include Windows::Security::Constants
|
10
|
+
include Windows::Security::Functions
|
11
|
+
include Windows::Security::Structs
|
12
|
+
extend Windows::Security::Functions
|
13
|
+
|
14
|
+
# The version of the Win32::Security::ACL class.
|
15
|
+
VERSION = '0.2.0'
|
16
|
+
|
17
|
+
# The underlying ACL structure.
|
18
|
+
attr_reader :acl
|
19
|
+
|
20
|
+
# The revision level.
|
21
|
+
attr_reader :revision
|
22
|
+
|
23
|
+
# Creates and returns a new Win32::Security::ACL object. This object
|
24
|
+
# encapsulates an ACL structure, including a binary representation of
|
25
|
+
# the ACL itself, and the revision information.
|
26
|
+
#
|
27
|
+
def initialize(size = 1024, revision = ACL_REVISION)
|
28
|
+
acl = ACL_STRUCT.new
|
29
|
+
|
30
|
+
unless InitializeAcl(acl, size, revision)
|
31
|
+
raise SystemCallError.new("InitializeAcl", FFI.errno)
|
32
|
+
end
|
33
|
+
|
34
|
+
@acl = acl
|
35
|
+
@revision = revision
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the number of ACE's in the ACL object.
|
39
|
+
#
|
40
|
+
def ace_count
|
41
|
+
info = ACL_SIZE_INFORMATION.new
|
42
|
+
|
43
|
+
unless GetAclInformation(@acl, info, info.size, AclSizeInformation)
|
44
|
+
raise SystemCallError.new("GetAclInformation", FFI.errno)
|
45
|
+
end
|
46
|
+
|
47
|
+
info[:AceCount]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a two element array that consists of the bytes in use and
|
51
|
+
# bytes free for the ACL.
|
52
|
+
#
|
53
|
+
def byte_info
|
54
|
+
info = ACL_SIZE_INFORMATION.new
|
55
|
+
|
56
|
+
unless GetAclInformation(@acl, info, info.size, AclSizeInformation)
|
57
|
+
raise SystemCallError.new("GetAclInformation", FFI.errno)
|
58
|
+
end
|
59
|
+
|
60
|
+
[info[:AclBytesInUse], info[:AclBytesFree]]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Adds an access allowed ACE to the given +sid+, which can be a
|
64
|
+
# Win32::Security::SID object or a plain user or group name. If no
|
65
|
+
# sid is provided then the owner of the current process is used.
|
66
|
+
#
|
67
|
+
# The +mask+ is a bitwise OR'd value of access rights.
|
68
|
+
#
|
69
|
+
# The +flags+ argument can be anyone of the following constants.
|
70
|
+
#
|
71
|
+
# * OBJECT_INHERIT_ACE
|
72
|
+
# * CONTAINER_INHERIT_ACE
|
73
|
+
# * NO_PROPAGATE_INHERIT_ACE
|
74
|
+
# * INHERIT_ONLY_ACE
|
75
|
+
# * INHERITED_ACE
|
76
|
+
#
|
77
|
+
# Example:
|
78
|
+
#
|
79
|
+
# acl = Win32::Security::ACL.new
|
80
|
+
# acl.add_access_allowed_ace('some_user', GENERIC_READ | GENERIC_WRITE)
|
81
|
+
#
|
82
|
+
def add_access_allowed_ace(sid=nil, mask=0, flags=nil)
|
83
|
+
if sid.is_a?(Win32::Security::SID)
|
84
|
+
sid = sid.sid
|
85
|
+
else
|
86
|
+
sid = Win32::Security::SID.new(sid).sid
|
87
|
+
end
|
88
|
+
|
89
|
+
if flags
|
90
|
+
unless AddAccessAllowedAceEx(@acl, @revision, flags, mask, sid)
|
91
|
+
raise SystemCallError.new("AddAccessAllowedAceEx", FFI.errno)
|
92
|
+
end
|
93
|
+
else
|
94
|
+
unless AddAccessAllowedAce(@acl, @revision, mask, sid)
|
95
|
+
raise SystemCallError.new("AddAccessAllowedAce", FFI.errno)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
sid
|
100
|
+
end
|
101
|
+
|
102
|
+
# Adds an access denied ACE to the given +sid+, which can be a
|
103
|
+
# Win32::Security::SID object ora plain user or group name. If
|
104
|
+
# no sid is provided then the owner of the current process is used.
|
105
|
+
#
|
106
|
+
# The +mask+ is the bitwise OR'd value of access rights.
|
107
|
+
#
|
108
|
+
# The +flags+ argument can be any one of the following constants:
|
109
|
+
#
|
110
|
+
# * OBJECT_INHERIT_ACE
|
111
|
+
# * CONTAINER_INHERIT_ACE
|
112
|
+
# * NO_PROPAGATE_INHERIT_ACE
|
113
|
+
# * INHERIT_ONLY_ACE
|
114
|
+
# * INHERITED_ACE
|
115
|
+
#
|
116
|
+
def add_access_denied_ace(sid=nil, mask=0, flags=nil)
|
117
|
+
if sid.is_a?(Win32::Security::SID)
|
118
|
+
sid = sid.sid
|
119
|
+
else
|
120
|
+
sid = Win32::Security::SID.new(sid).sid
|
121
|
+
end
|
122
|
+
|
123
|
+
if flags
|
124
|
+
unless AddAccessDeniedAceEx(@acl, @revision, flags, mask, sid)
|
125
|
+
raise SystemCallError.new("AddAccessDeniedAceEx", FFI.errno)
|
126
|
+
end
|
127
|
+
else
|
128
|
+
unless AddAccessDeniedAce(@acl, @revision, mask, sid)
|
129
|
+
raise SystemCallError.new("AddAccessDeniedAce", FFI.errno)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Adds an ACE to the ACL object with the given +revision+ at +index+
|
135
|
+
# or the end of the chain if no index is specified.
|
136
|
+
#
|
137
|
+
# Returns the index if successful.
|
138
|
+
#--
|
139
|
+
# This won't work until we implement the ACE class.
|
140
|
+
#
|
141
|
+
def add_ace(ace, index=MAXDWORD)
|
142
|
+
unless AddAce(@acl, @revision, index, ace, ace.length)
|
143
|
+
raise SystemCallError.new("AddAce", FFI.errno)
|
144
|
+
end
|
145
|
+
|
146
|
+
index
|
147
|
+
end
|
148
|
+
|
149
|
+
# Deletes an ACE from the ACL object at +index+, or from the end of
|
150
|
+
# the chain if no index is specified.
|
151
|
+
#
|
152
|
+
# Returns the index if successful.
|
153
|
+
#
|
154
|
+
def delete_ace(index=MAXDWORD)
|
155
|
+
unless DeleteAce(@acl, index)
|
156
|
+
raise SystemCallError.new("DeleteAce", FFI.errno)
|
157
|
+
end
|
158
|
+
|
159
|
+
index
|
160
|
+
end
|
161
|
+
|
162
|
+
# Finds and returns an ACE object for the ACL at the given
|
163
|
+
# +index+. If no index is provided, then it returns an ACE object
|
164
|
+
# that corresponds to the first free byte of the ACL.
|
165
|
+
#
|
166
|
+
# If +raw+ is true, it will return an ACCESS_GENERIC_ACE struct,
|
167
|
+
# an FFI object that you can then access directly.
|
168
|
+
#
|
169
|
+
def find_ace(index = nil, raw = false)
|
170
|
+
result = nil
|
171
|
+
|
172
|
+
FFI::MemoryPointer.new(:pointer) do |pptr|
|
173
|
+
if index.nil?
|
174
|
+
unless FindFirstFreeAce(@acl, pptr)
|
175
|
+
raise SystemCallError.new("FindFirstFreeAce", FFI.errno)
|
176
|
+
end
|
177
|
+
else
|
178
|
+
unless GetAce(@acl, index, pptr)
|
179
|
+
raise SystemCallError.new("GetAce", FFI.errno)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# There's no way to know what type of ACE it is at this point as far
|
184
|
+
# as I know, so we use a generic struct and use the AceType to figure
|
185
|
+
# it out later, or the users can.
|
186
|
+
ace = ACCESS_GENERIC_ACE.new(pptr.read_pointer)
|
187
|
+
|
188
|
+
if raw
|
189
|
+
result = ace
|
190
|
+
else
|
191
|
+
result = ACE.new(ace[:Mask], ace[:Header][:AceType], ace[:Header][:AceFlags])
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
result
|
196
|
+
end
|
197
|
+
|
198
|
+
# Sets the revision information level, where the +revision_level+
|
199
|
+
# can be ACL_REVISION1, ACL_REVISION2, ACL_REVISION3 or ACL_REVISION4.
|
200
|
+
#
|
201
|
+
# Returns the revision level if successful.
|
202
|
+
#
|
203
|
+
def revision=(revision_level)
|
204
|
+
FFI::MemoryPointer.new(:ulong) do |buf|
|
205
|
+
buf.write_ulong(revision_level)
|
206
|
+
|
207
|
+
unless SetAclInformation(@acl, buf, buf.size, AclRevisionInformation)
|
208
|
+
raise SystemCallError.new("SetAclInformation", FFI.errno)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
@revision = revision_level
|
213
|
+
|
214
|
+
revision_level
|
215
|
+
end
|
216
|
+
|
217
|
+
# Returns whether or not the ACL is a valid ACL.
|
218
|
+
#
|
219
|
+
def valid?
|
220
|
+
IsValidAcl(@acl)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|