win32-security 0.1.4 → 0.2.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 +4 -0
- data/MANIFEST +8 -8
- data/README +1 -1
- data/Rakefile +9 -5
- data/lib/win32/security.rb +76 -33
- data/lib/win32/security/acl.rb +32 -31
- data/lib/win32/security/sid.rb +97 -118
- data/lib/win32/security/windows/constants.rb +121 -0
- data/lib/win32/security/windows/functions.rb +97 -0
- data/lib/win32/security/windows/structs.rb +67 -0
- data/test/test_acl.rb +82 -57
- data/test/test_security.rb +9 -24
- data/test/test_sid.rb +5 -9
- data/win32-security.gemspec +4 -4
- metadata +11 -8
data/CHANGES
CHANGED
data/MANIFEST
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
* CHANGES
|
2
|
-
* MANIFEST
|
3
|
-
* README
|
4
|
-
* Rakefile
|
5
|
-
* win32-security.gemspec
|
6
|
-
* lib/win32/security.rb
|
7
|
-
* lib/win32/security/sid.rb
|
8
|
-
* test/test_security.rb
|
1
|
+
* CHANGES
|
2
|
+
* MANIFEST
|
3
|
+
* README
|
4
|
+
* Rakefile
|
5
|
+
* win32-security.gemspec
|
6
|
+
* lib/win32/security.rb
|
7
|
+
* lib/win32/security/sid.rb
|
8
|
+
* test/test_security.rb
|
9
9
|
* test/test_sid.rb
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'rake'
|
2
|
+
require 'rake/clean'
|
2
3
|
require 'rake/testtask'
|
3
4
|
require 'rbconfig'
|
4
5
|
|
5
|
-
|
6
|
-
desc "Remove any .gem files in the project"
|
7
|
-
task :clean do
|
8
|
-
Dir['*.gem'].each{ |f| File.delete(f) }
|
9
|
-
end
|
6
|
+
CLEAN.include('**/*.gem', '**/*.rbc')
|
10
7
|
|
8
|
+
namespace :gem do
|
11
9
|
desc "Create the win32-security gem"
|
12
10
|
task :create => [:clean] do
|
13
11
|
spec = eval(IO.read('win32-security.gemspec'))
|
@@ -29,6 +27,12 @@ namespace :test do
|
|
29
27
|
t.test_files = Dir['test/test_security.rb']
|
30
28
|
end
|
31
29
|
|
30
|
+
Rake::TestTask.new(:acl) do |t|
|
31
|
+
t.verbose = true
|
32
|
+
t.warning = true
|
33
|
+
t.test_files = Dir['test/test_acl.rb']
|
34
|
+
end
|
35
|
+
|
32
36
|
Rake::TestTask.new(:sid) do |t|
|
33
37
|
t.verbose = true
|
34
38
|
t.warning = true
|
data/lib/win32/security.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# This file allows users to require all security related classes from
|
2
2
|
# a single file, instead of having to require individual files.
|
3
3
|
|
4
|
-
require 'windows
|
5
|
-
require '
|
6
|
-
require 'windows
|
7
|
-
require 'windows/error'
|
4
|
+
require File.join(File.dirname(__FILE__), 'security', 'windows', 'constants')
|
5
|
+
require File.join(File.dirname(__FILE__), 'security', 'windows', 'structs')
|
6
|
+
require File.join(File.dirname(__FILE__), 'security', 'windows', 'functions')
|
8
7
|
|
9
8
|
# The Win32 module serves as a namespace only.
|
10
9
|
module Win32
|
@@ -15,53 +14,97 @@ module Win32
|
|
15
14
|
# Base error class for all Win32::Security errors.
|
16
15
|
class Error < StandardError; end
|
17
16
|
|
18
|
-
include Windows::Security
|
19
|
-
|
20
|
-
|
21
|
-
extend Windows::Security
|
22
|
-
extend Windows::Handle
|
23
|
-
extend Windows::Error
|
17
|
+
include Windows::Security::Functions
|
18
|
+
include Windows::Security::Constants
|
19
|
+
include Windows::Security::Structs
|
20
|
+
extend Windows::Security::Functions
|
24
21
|
|
25
22
|
# The version of the win32-security library
|
26
|
-
VERSION = '0.
|
23
|
+
VERSION = '0.2.0'
|
24
|
+
|
25
|
+
# Used by OpenProcessToken
|
26
|
+
TOKEN_QUERY = 8
|
27
27
|
|
28
28
|
# Returns whether or not the owner of the current process is running
|
29
29
|
# with elevated security privileges.
|
30
30
|
#
|
31
|
-
#
|
31
|
+
# On Windows XP an earlier this method is actually just checking to
|
32
|
+
# see if the caller's process is a member of the local Administrator's
|
33
|
+
# group.
|
32
34
|
#
|
33
35
|
def self.elevated_security?
|
34
|
-
|
36
|
+
if windows_version < 6
|
37
|
+
sid_ptr = FFI::MemoryPointer.new(:pointer)
|
38
|
+
nt_auth_ptr = FFI::MemoryPointer.new(SID_IDENTIFIER_AUTHORITY,1)
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
nt_auth = SID_IDENTIFIER_AUTHORITY.new(nt_auth_ptr)
|
41
|
+
nt_auth[:Value].to_ptr.put_bytes(0, 0.chr*5 + 5.chr)
|
42
|
+
|
43
|
+
bool = AllocateAndInitializeSid(
|
44
|
+
nt_auth_ptr,
|
45
|
+
2,
|
46
|
+
SECURITY_BUILTIN_DOMAIN_RID,
|
47
|
+
DOMAIN_ALIAS_RID_ADMINS,
|
48
|
+
0, 0, 0, 0, 0, 0,
|
49
|
+
sid_ptr
|
50
|
+
)
|
51
|
+
unless bool
|
52
|
+
raise SystemCallError.new("AllocateAndInitializeSid", FFI.errno)
|
53
|
+
end
|
39
54
|
|
40
|
-
|
41
|
-
token = token.unpack('V')[0]
|
55
|
+
pbool = FFI::MemoryPointer.new(:long)
|
42
56
|
|
43
|
-
|
44
|
-
|
57
|
+
unless CheckTokenMembership(0, sid_ptr.read_pointer, pbool)
|
58
|
+
raise SystemCallError.new("CheckTokenMembership", FFI.errno)
|
59
|
+
end
|
45
60
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
61
|
+
pbool.read_long != 0
|
62
|
+
else
|
63
|
+
token = FFI::MemoryPointer.new(:ulong)
|
64
|
+
|
65
|
+
unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, token)
|
66
|
+
raise SystemCallError.new("OpenProcessToken", FFI.errno)
|
67
|
+
end
|
68
|
+
|
69
|
+
begin
|
70
|
+
token = token.read_ulong
|
71
|
+
|
72
|
+
# Since the TokenElevation struct only has 1 member, we use a pointer.
|
73
|
+
te = FFI::MemoryPointer.new(:ulong)
|
74
|
+
rl = FFI::MemoryPointer.new(:ulong)
|
75
|
+
|
76
|
+
bool = GetTokenInformation(
|
77
|
+
token,
|
78
|
+
:TokenElevation,
|
79
|
+
te,
|
80
|
+
te.size,
|
81
|
+
rl
|
82
|
+
)
|
83
|
+
|
84
|
+
raise SystemCallError.new("GetTokenInformation", FFI.errno) unless bool
|
85
|
+
ensure
|
86
|
+
CloseHandle(token)
|
87
|
+
end
|
88
|
+
|
89
|
+
te.read_ulong != 0
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def self.windows_version
|
96
|
+
ver = OSVERSIONINFO.new
|
97
|
+
ver[:dwOSVersionInfoSize] = ver.size
|
53
98
|
|
54
|
-
|
55
|
-
|
56
|
-
CloseHandle(token)
|
99
|
+
unless GetVersionExA(ver)
|
100
|
+
raise SystemCallError.new("GetVersionEx", FFI.errno)
|
57
101
|
end
|
58
102
|
|
59
|
-
|
60
|
-
te.unpack('L')[0] != 0
|
103
|
+
ver[:dwMajorVersion]
|
61
104
|
end
|
62
105
|
end
|
63
106
|
end
|
64
107
|
|
65
108
|
require 'win32/security/sid'
|
66
|
-
|
109
|
+
require 'win32/security/acl'
|
67
110
|
#require 'win32/security/ace'
|
data/lib/win32/security/acl.rb
CHANGED
@@ -1,25 +1,24 @@
|
|
1
|
-
require 'windows
|
2
|
-
require 'windows
|
3
|
-
require 'windows
|
4
|
-
require 'windows/msvcrt/buffer'
|
1
|
+
require File.join(File.dirname(__FILE__), 'windows', 'constants')
|
2
|
+
require File.join(File.dirname(__FILE__), 'windows', 'structs')
|
3
|
+
require File.join(File.dirname(__FILE__), 'windows', 'functions')
|
5
4
|
|
6
5
|
# The Win32 module serves as a namespace only.
|
7
6
|
module Win32
|
8
|
-
|
7
|
+
|
9
8
|
# The Security class serves as a toplevel class namespace.
|
10
9
|
class Security
|
11
|
-
|
10
|
+
|
12
11
|
# The ACL class encapsulates an Access Control List.
|
13
12
|
class ACL
|
14
|
-
include Windows::
|
15
|
-
include Windows::Security
|
16
|
-
include Windows::
|
17
|
-
|
18
|
-
|
13
|
+
include Windows::Security::Constants
|
14
|
+
include Windows::Security::Functions
|
15
|
+
include Windows::Security::Structs
|
16
|
+
extend Windows::Security::Functions
|
17
|
+
|
19
18
|
# The version of the Win32::Security::ACL class.
|
20
|
-
VERSION = '0.
|
19
|
+
VERSION = '0.2.0'
|
21
20
|
|
22
|
-
# The
|
21
|
+
# The underlying ACL structure.
|
23
22
|
attr_reader :acl
|
24
23
|
|
25
24
|
# The revision level.
|
@@ -30,10 +29,10 @@ module Win32
|
|
30
29
|
# the ACL itself, and the revision information.
|
31
30
|
#
|
32
31
|
def initialize(revision = ACL_REVISION)
|
33
|
-
acl =
|
32
|
+
acl = ACL_STRUCT.new
|
34
33
|
|
35
34
|
unless InitializeAcl(acl, acl.size, revision)
|
36
|
-
raise
|
35
|
+
raise SystemCallError.new("InitializeAcl", FFI.errno)
|
37
36
|
end
|
38
37
|
|
39
38
|
@acl = acl
|
@@ -43,21 +42,22 @@ module Win32
|
|
43
42
|
# Returns the number of ACE's in the ACL object.
|
44
43
|
#
|
45
44
|
def ace_count
|
46
|
-
|
45
|
+
info = ACL_SIZE_INFORMATION.new
|
47
46
|
|
48
|
-
unless GetAclInformation(@acl,
|
49
|
-
raise
|
47
|
+
unless GetAclInformation(@acl, info, info.size, AclSizeInformation)
|
48
|
+
raise SystemCallError.new("GetAclInformation", FFI.errno)
|
50
49
|
end
|
51
50
|
|
52
|
-
|
51
|
+
info[:AceCount]
|
53
52
|
end
|
54
53
|
|
55
54
|
# Adds an access allowed ACE to the given +sid+. The +mask+ is a
|
56
55
|
# bitwise OR'd value of access rights.
|
57
56
|
#
|
57
|
+
# TODO: Move this into the SID class?
|
58
58
|
def add_access_allowed_ace(sid, mask=0)
|
59
59
|
unless AddAccessAllowedAce(@acl, @revision, mask, sid)
|
60
|
-
raise
|
60
|
+
raise SystemCallError.new("AddAccessAllowedAce", FFI.errno)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -65,7 +65,7 @@ module Win32
|
|
65
65
|
#
|
66
66
|
def add_access_denied_ace(sid, mask=0)
|
67
67
|
unless AddAccessDeniedAce(@acl, @revision, mask, sid)
|
68
|
-
raise
|
68
|
+
raise SystemCallError.new("AddAccessDeniedAce", FFI.errno)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -79,7 +79,7 @@ module Win32
|
|
79
79
|
#
|
80
80
|
def add_ace(ace, index=MAXDWORD)
|
81
81
|
unless AddAce(@acl, @revision, index, ace, ace.length)
|
82
|
-
raise
|
82
|
+
raise SystemCallError.new("AddAce", FFI.errno)
|
83
83
|
end
|
84
84
|
|
85
85
|
index
|
@@ -95,7 +95,7 @@ module Win32
|
|
95
95
|
#
|
96
96
|
def delete_ace(index=MAXDWORD)
|
97
97
|
unless DeleteAce(@ace, index)
|
98
|
-
raise
|
98
|
+
raise SystemCallError.new("DeleteAce", FFI.errno)
|
99
99
|
end
|
100
100
|
|
101
101
|
index
|
@@ -106,19 +106,19 @@ module Win32
|
|
106
106
|
# first free byte of the ACL is returned.
|
107
107
|
#
|
108
108
|
def find_ace(index = nil)
|
109
|
-
|
109
|
+
pptr = FFI::MemoryPointer.new(:pointer)
|
110
110
|
|
111
111
|
if index.nil?
|
112
|
-
unless FindFirstFreeAce(@acl,
|
113
|
-
raise
|
112
|
+
unless FindFirstFreeAce(@acl, pptr)
|
113
|
+
raise SystemCallError.new("DeleteAce", FFI.errno)
|
114
114
|
end
|
115
115
|
else
|
116
|
-
unless GetAce(@acl, index,
|
117
|
-
raise
|
116
|
+
unless GetAce(@acl, index, pptr)
|
117
|
+
raise SystemCallError.new("GetAce", FFI.errno)
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
|
-
|
121
|
+
pptr.read_pointer.address
|
122
122
|
end
|
123
123
|
|
124
124
|
# Sets the revision information level, where the +revision_level+
|
@@ -127,10 +127,11 @@ module Win32
|
|
127
127
|
# Returns the revision level if successful.
|
128
128
|
#
|
129
129
|
def revision=(revision_level)
|
130
|
-
buf =
|
130
|
+
buf = FFI::MemoryPointer.new(:ulong)
|
131
|
+
buf.write_ulong(revision_level)
|
131
132
|
|
132
133
|
unless SetAclInformation(@acl, buf, buf.size, AclRevisionInformation)
|
133
|
-
raise
|
134
|
+
raise SystemCallError.new("SetAclInformation", FFI.errno)
|
134
135
|
end
|
135
136
|
|
136
137
|
@revision = revision_level
|
data/lib/win32/security/sid.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
require 'windows
|
2
|
-
require 'windows
|
3
|
-
require 'windows
|
4
|
-
require 'windows/error'
|
5
|
-
require 'windows/msvcrt/string'
|
6
|
-
require 'windows/msvcrt/buffer'
|
1
|
+
require File.join(File.dirname(__FILE__), 'windows', 'constants')
|
2
|
+
require File.join(File.dirname(__FILE__), 'windows', 'functions')
|
3
|
+
require File.join(File.dirname(__FILE__), 'windows', 'structs')
|
7
4
|
require 'socket'
|
8
5
|
|
9
6
|
# The Win32 module serves as a namespace only.
|
@@ -14,23 +11,13 @@ module Win32
|
|
14
11
|
|
15
12
|
# The SID class encapsulates a Security Identifier.
|
16
13
|
class SID
|
17
|
-
include Windows::Security
|
18
|
-
include Windows::
|
19
|
-
include Windows::
|
20
|
-
|
21
|
-
include Windows::Thread
|
22
|
-
include Windows::Process
|
23
|
-
|
24
|
-
extend Windows::Security
|
25
|
-
extend Windows::Error
|
26
|
-
extend Windows::MSVCRT::String
|
27
|
-
extend Windows::MSVCRT::Buffer
|
28
|
-
|
29
|
-
# Error class typically raised if any of the SID methods fail
|
30
|
-
class Error < StandardError; end
|
14
|
+
include Windows::Security::Constants
|
15
|
+
include Windows::Security::Functions
|
16
|
+
include Windows::Security::Structs
|
17
|
+
extend Windows::Security::Functions
|
31
18
|
|
32
19
|
# The version of the Win32::Security::SID class.
|
33
|
-
VERSION = '0.
|
20
|
+
VERSION = '0.2.0'
|
34
21
|
|
35
22
|
# Some constant SID's for your convenience, in string format.
|
36
23
|
# See http://support.microsoft.com/kb/243330 for details.
|
@@ -91,40 +78,25 @@ module Win32
|
|
91
78
|
# Converts a binary SID to a string in S-R-I-S-S... format.
|
92
79
|
#
|
93
80
|
def self.sid_to_string(sid)
|
94
|
-
|
95
|
-
sid_buf = 0.chr * 80
|
96
|
-
sid_ptr = 0.chr * 4
|
81
|
+
string_sid = FFI::MemoryPointer.new(:pointer)
|
97
82
|
|
98
|
-
unless ConvertSidToStringSid(
|
99
|
-
raise
|
83
|
+
unless ConvertSidToStringSid(sid, string_sid)
|
84
|
+
raise SystemCallError.new("ConvertSidToStringSid", FFI.errno)
|
100
85
|
end
|
101
86
|
|
102
|
-
|
103
|
-
sid_buf.strip
|
87
|
+
string_sid.read_pointer.read_string
|
104
88
|
end
|
105
89
|
|
106
90
|
# Converts a string in S-R-I-S-S... format back to a binary SID.
|
107
91
|
#
|
108
92
|
def self.string_to_sid(string)
|
109
|
-
|
110
|
-
sid_ptr = 0.chr * 4
|
93
|
+
sid = FFI::MemoryPointer.new(:pointer)
|
111
94
|
|
112
|
-
unless ConvertStringSidToSid(
|
113
|
-
raise
|
95
|
+
unless ConvertStringSidToSid(string, sid)
|
96
|
+
raise SystemCallError.new("ConvertStringSidToSid", FFI.errno)
|
114
97
|
end
|
115
98
|
|
116
|
-
|
117
|
-
raise Error, get_last_error
|
118
|
-
end
|
119
|
-
|
120
|
-
sid_len = GetLengthSid(sid_ptr.unpack('L')[0])
|
121
|
-
sid_buf = 0.chr * sid_len
|
122
|
-
|
123
|
-
unless CopySid(sid_len, [sid_buf].pack('p*').unpack('L')[0], sid_ptr.unpack('L')[0])
|
124
|
-
raise Error, get_last_error
|
125
|
-
end
|
126
|
-
|
127
|
-
sid_buf
|
99
|
+
sid.read_pointer.read_string
|
128
100
|
end
|
129
101
|
|
130
102
|
# Creates a new SID with +authority+ and up to 8 +subauthorities+,
|
@@ -149,24 +121,25 @@ module Win32
|
|
149
121
|
#
|
150
122
|
def self.create(authority, *sub_authorities)
|
151
123
|
if sub_authorities.length > 8
|
152
|
-
|
124
|
+
raise ArgumentError, "maximum of 8 subauthorities allowed"
|
153
125
|
end
|
154
126
|
|
155
|
-
|
127
|
+
size = GetSidLengthRequired(sub_authorities.length)
|
128
|
+
sid = FFI::MemoryPointer.new(:uchar, size)
|
156
129
|
|
157
|
-
auth =
|
130
|
+
auth = SID_IDENTIFIER_AUTHORITY.new
|
131
|
+
auth[:Value][5] = authority
|
158
132
|
|
159
133
|
unless InitializeSid(sid, auth, sub_authorities.length)
|
160
|
-
|
134
|
+
raise SystemCallError.new("InitializeSid", FFI.errno)
|
161
135
|
end
|
162
136
|
|
163
137
|
sub_authorities.each_index do |i|
|
164
|
-
|
165
|
-
|
166
|
-
memcpy(auth_ptr, value, 4)
|
138
|
+
ptr = GetSidSubAuthority(sid, i)
|
139
|
+
ptr.write_ulong(sub_authorities[i])
|
167
140
|
end
|
168
141
|
|
169
|
-
new(sid)
|
142
|
+
new(sid.read_string(size)) # Pass a binary string
|
170
143
|
end
|
171
144
|
|
172
145
|
# Creates and returns a new Win32::Security::SID object, based on
|
@@ -198,45 +171,41 @@ module Win32
|
|
198
171
|
#
|
199
172
|
def initialize(account=nil, host=Socket.gethostname)
|
200
173
|
if account.nil?
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
174
|
+
begin
|
175
|
+
ptoken = FFI::MemoryPointer.new(:ulong)
|
176
|
+
|
177
|
+
# Try the thread token first, default to the process token.
|
178
|
+
bool = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, true, ptoken)
|
179
|
+
|
180
|
+
if !bool && FFI.errno != ERROR_NO_TOKEN
|
181
|
+
raise SystemCallError.new("OpenThreadToken", FFI.errno)
|
210
182
|
else
|
211
|
-
|
183
|
+
ptoken = FFI::MemoryPointer.new(:ulong)
|
184
|
+
unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, ptoken)
|
185
|
+
raise SystemCallError.new("OpenProcessToken", FFI.errno)
|
186
|
+
end
|
212
187
|
end
|
213
|
-
end
|
214
188
|
|
215
|
-
|
216
|
-
|
217
|
-
|
189
|
+
token = ptoken.read_ulong
|
190
|
+
pinfo = FFI::MemoryPointer.new(:pointer)
|
191
|
+
plength = FFI::MemoryPointer.new(:ulong)
|
218
192
|
|
219
|
-
|
220
|
-
|
221
|
-
TokenOwner,
|
222
|
-
token_info,
|
223
|
-
token_info.size,
|
224
|
-
cbti
|
225
|
-
)
|
193
|
+
# First pass, just get the size needed (1 is TokenOwner)
|
194
|
+
GetTokenInformation(token, 1, pinfo, pinfo.size, plength)
|
226
195
|
|
227
|
-
|
228
|
-
|
229
|
-
end
|
230
|
-
end
|
196
|
+
pinfo = FFI::MemoryPointer.new(plength.read_ulong)
|
197
|
+
plength = FFI::MemoryPointer.new(:ulong)
|
231
198
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
domain_buf = 0.chr * 80
|
237
|
-
domain_cch = [domain_buf.size].pack('L')
|
199
|
+
# Second pass, actual call (1 is TokenOwner)
|
200
|
+
unless GetTokenInformation(token, 1, pinfo, pinfo.size, plength)
|
201
|
+
raise SystemCallError.new("GetTokenInformation", FFI.errno)
|
202
|
+
end
|
238
203
|
|
239
|
-
|
204
|
+
token_info = pinfo.read_pointer
|
205
|
+
ensure
|
206
|
+
CloseHandle(token) if token
|
207
|
+
end
|
208
|
+
end
|
240
209
|
|
241
210
|
if account
|
242
211
|
ordinal_val = account[0]
|
@@ -245,61 +214,74 @@ module Win32
|
|
245
214
|
ordinal_val = nil
|
246
215
|
end
|
247
216
|
|
217
|
+
sid = FFI::MemoryPointer.new(:uchar, 260)
|
218
|
+
sid_size = FFI::MemoryPointer.new(:ulong)
|
219
|
+
sid_size.write_ulong(sid.size)
|
220
|
+
|
221
|
+
domain = FFI::MemoryPointer.new(:uchar, 260)
|
222
|
+
domain_size = FFI::MemoryPointer.new(:ulong)
|
223
|
+
domain_size.write_ulong(domain.size)
|
224
|
+
|
225
|
+
use_ptr = FFI::MemoryPointer.new(:ulong)
|
226
|
+
|
248
227
|
if ordinal_val.nil?
|
249
228
|
bool = LookupAccountSid(
|
250
229
|
nil,
|
251
|
-
token_info
|
230
|
+
token_info,
|
252
231
|
sid,
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
232
|
+
sid_size,
|
233
|
+
domain,
|
234
|
+
domain_size,
|
235
|
+
use_ptr
|
257
236
|
)
|
237
|
+
unless bool
|
238
|
+
raise SystemCallError.new("LookupAccountSid", FFI.errno)
|
239
|
+
end
|
258
240
|
elsif ordinal_val < 10 # Assume it's a binary SID.
|
241
|
+
account_ptr = FFI::MemoryPointer.from_string(account)
|
259
242
|
bool = LookupAccountSid(
|
260
243
|
host,
|
261
|
-
|
244
|
+
account_ptr,
|
262
245
|
sid,
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
246
|
+
sid_size,
|
247
|
+
domain,
|
248
|
+
domain_size,
|
249
|
+
use_ptr
|
267
250
|
)
|
251
|
+
unless bool
|
252
|
+
raise SystemCallError.new("LookupAccountSid", FFI.errno)
|
253
|
+
end
|
268
254
|
else
|
269
255
|
bool = LookupAccountName(
|
270
256
|
host,
|
271
257
|
account,
|
272
258
|
sid,
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
259
|
+
sid_size,
|
260
|
+
domain,
|
261
|
+
domain_size,
|
262
|
+
use_ptr,
|
277
263
|
)
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
raise Error, get_last_error
|
264
|
+
unless bool
|
265
|
+
raise SystemCallError.new("LookupAccountName", FFI.errno)
|
266
|
+
end
|
282
267
|
end
|
283
268
|
|
284
269
|
# The arguments are flipped depending on which path we took
|
285
270
|
if ordinal_val.nil?
|
286
|
-
|
287
|
-
|
288
|
-
memcpy(buf, ptr, token_info.size)
|
289
|
-
@sid = buf.strip
|
290
|
-
@account = sid.strip
|
271
|
+
@sid = token_info.read_string
|
272
|
+
@account = sid.read_string(sid.size).strip
|
291
273
|
elsif ordinal_val < 10
|
292
274
|
@sid = account
|
293
|
-
@account = sid.strip
|
275
|
+
@account = sid.read_string(sid.size).strip
|
294
276
|
else
|
295
|
-
@sid = sid.strip
|
277
|
+
@sid = sid.read_string(sid.size).strip
|
296
278
|
@account = account
|
297
279
|
end
|
298
280
|
|
299
281
|
@host = host
|
300
|
-
@domain =
|
282
|
+
@domain = domain.read_string
|
301
283
|
|
302
|
-
@account_type = get_account_type(
|
284
|
+
@account_type = get_account_type(use_ptr.read_ulong)
|
303
285
|
end
|
304
286
|
|
305
287
|
# Synonym for SID.new.
|
@@ -312,16 +294,13 @@ module Win32
|
|
312
294
|
# storage or transmission.
|
313
295
|
#
|
314
296
|
def to_s
|
315
|
-
|
316
|
-
sid_buf = 0.chr * 80
|
317
|
-
sid_ptr = 0.chr * 4
|
297
|
+
ptr = FFI::MemoryPointer.new(:pointer)
|
318
298
|
|
319
|
-
unless ConvertSidToStringSid(
|
320
|
-
raise
|
299
|
+
unless ConvertSidToStringSid(@sid, ptr)
|
300
|
+
raise SystemCallError.new("ConvertSidToStringSid", FFI.errno)
|
321
301
|
end
|
322
302
|
|
323
|
-
|
324
|
-
sid_buf.strip
|
303
|
+
ptr.read_pointer.read_string
|
325
304
|
end
|
326
305
|
|
327
306
|
alias to_str to_s
|