我想从LDAP查询中检索base64编码的objectSid到Active Directory数据库,并将它们转换为标准的SID表示。你能给我一个Python代码片段吗?
答案 0 :(得分:9)
这应该可以解决问题:
import struct
def convert(binary):
version = struct.unpack('B', binary[0])[0]
# I do not know how to treat version != 1 (it does not exist yet)
assert version == 1, version
length = struct.unpack('B', binary[1])[0]
authority = struct.unpack('>Q', '\x00\x00' + binary[2:8])[0]
string = 'S-%d-%d' % (version, authority)
binary = binary[8:]
assert len(binary) == 4 * length
for i in xrange(length):
value = struct.unpack('<L', binary[4*i:4*(i+1)])[0]
string += '-%d' % value
return string
参考文献:http://blogs.msdn.com/b/oldnewthing/archive/2004/03/15/89753.aspx和http://codeimpossible.com/2008/04/07/Converting-a-Security-Identifier-from-binary-to-string/。
答案 1 :(得分:2)
答案 2 :(得分:1)
这是@Giovanni Mascellani的答案,适用于Python 3.x:
import struct
def convert(binary):
version = struct.unpack('B', binary[0:1])[0]
# I do not know how to treat version != 1 (it does not exist yet)
assert version == 1, version
length = struct.unpack('B', binary[1:2])[0]
authority = struct.unpack(b'>Q', b'\x00\x00' + binary[2:8])[0]
string = 'S-%d-%d' % (version, authority)
binary = binary[8:]
assert len(binary) == 4 * length
for i in range(length):
value = struct.unpack('<L', binary[4*i:4*(i+1)])[0]
string += '-%d' % value
return string
答案 3 :(得分:1)
如果您使用的是 Linux 并安装了 Samba:
from samba.dcerpc import security
from samba.ndr import ndr_unpack
def convert(binary_sid):
return str(ndr_unpack(security.dom_sid, binary_sid))
其中 binary_sid
是 sid 的二进制表示。
答案 4 :(得分:0)
格式为S-1-5-21-2562418665-3218585558-1813906818-1576
的SID具有以下十六进制原始格式:010500000000000515000000e967bb98d6b7d7bf82051e6c28060000
,可以按以下方式分解:
S
:这意味着这只是一个objectSid 01
:(1)据我所知,修订版ans始终为1 05
:下级机构的数量,或者您可以简单地说破折号减去2 000000000005
:( 5)大端字节15000000
:( 21)小字节序e967bb98
:( 2562418665)小字节序d6b7d7bf
:( 3218585558)小字节序82051e6c
:( 1813906818)小字节序28060000
:( 1576)小字节序小字节序应以相反的顺序读取。这就是表示二进制数据的方式,最低有效字节首先存储在哪里。 因此,Big Endian是最高有效字节首先存储的顺序。 Here是一篇很好的文章,解释了字节顺序。
This是有关objecSid结构的简短介绍,而this是一篇不错的博客文章。
根据这些信息,让我们尝试读取一个SID,该SID是从LDAP查询中以二进制形式返回的。 binascii
库可用于Python 2和Python 3:
from binascii import b2a_hex
def sid_to_str(sid):
try:
# Python 3
if str is not bytes:
# revision
revision = int(sid[0])
# count of sub authorities
sub_authorities = int(sid[1])
# big endian
identifier_authority = int.from_bytes(sid[2:8], byteorder='big')
# If true then it is represented in hex
if identifier_authority >= 2 ** 32:
identifier_authority = hex(identifier_authority)
# loop over the count of small endians
sub_authority = '-' + '-'.join([str(int.from_bytes(sid[8 + (i * 4): 12 + (i * 4)], byteorder='little')) for i in range(sub_authorities)])
# Python 2
else:
revision = int(b2a_hex(sid[0]))
sub_authorities = int(b2a_hex(sid[1]))
identifier_authority = int(b2a_hex(sid[2:8]), 16)
if identifier_authority >= 2 ** 32:
identifier_authority = hex(identifier_authority)
sub_authority = '-' + '-'.join([str(int(b2a_hex(sid[11 + (i * 4): 7 + (i * 4): -1]), 16)) for i in range(sub_authorities)])
objectSid = 'S-' + str(revision) + '-' + str(identifier_authority) + sub_authority
return objectSid
except Exception:
pass
return sid
sid = b'\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xe9\x67\xbb\x98\xd6\xb7\xd7\xbf\x82\x05\x1e\x6c\x28\x06\x00\x00'
print(sid_to_str(sid)) # S-1-5-21-2562418665-3218585558-1813906818-1576