从objectSid转换为SID表示的Python代码

从objectSid转换为SID表示的Python代码,python,active-directory,Python,Active Directory,我想从LDAP查询检索base64编码的objectSid到Active Directory数据库,并将其转换为标准SID表示形式。你能给我一个这样做的Python代码片段吗?这应该可以做到: 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)

我想从LDAP查询检索base64编码的objectSid到Active Directory数据库,并将其转换为标准SID表示形式。你能给我一个这样做的Python代码片段吗?

这应该可以做到:

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
导入结构
def转换(二进制):
version=struct.unpack('B',二进制[0])[0]
#我不知道如何对待版本!=1(它还不存在)
断言版本==1,版本
长度=结构解包('B',二进制[1])[0]
authority=struct.unpack('>Q','\x00\x00'+二进制[2:8])[0]
字符串='S-%d-%d'(版本、权限)
二进制=二进制[8:]
断言长度(二进制)==4*长度
对于X范围内的i(长度):

value=struct.unpack(“使用或参见ldap3中的实现


这是@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
导入结构
def转换(二进制):
version=struct.unpack('B',二进制[0:1])[0]
#我不知道如何处理版本!=1(它还不存在)
断言版本==1,版本
长度=结构解包('B',二进制[1:2])[0]
authority=struct.unpack(b'>Q',b'\x00\x00'+二进制[2:8])[0]
字符串='S-%d-%d'(版本、权限)
二进制=二进制[8:]
断言长度(二进制)==4*长度
对于范围内的i(长度):

value=struct.unpack(“S-1-5-21-2562418665-3218585558-1813906818-1576格式的SID
具有以下十六进制原始格式:
010500000000000515000E967BB98D6B7D7BF82051E6C28060000
,可以分解如下:

  • S
    :这意味着这是一个objectSid
  • 01
    :(1)是修订版吗?据我所知,ans始终是1
  • 05
    :分支机构的计数,或者您可以简单地说,破折号计数减去2
  • 000000000005
    :(5)大端
  • 15000000
    :(21)小尾端
  • e967bb98
    :(2562418665)小尾端
  • d6b7d7bf
    :(3218585558)小尾端
  • 82051e6c
    :(1813906818)小尾端
  • 28060000
    :(1576)小尾端
应以相反的顺序读取Small-endian。这就是二进制数据的表示方式,其中最低有效字节首先存储。 因此,Big-endian是最高有效字节首先存储的顺序。这是一篇解释字节顺序的好文章

这是一篇关于ObjeCId结构的简要介绍,也是一篇不错的博客文章

根据这些信息,让我们尝试读取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


如果您使用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\u sid
是sid的二进制表示形式。

我在源代码中找不到它,但是否有一个格式化程序可以做相反的事情?(将格式化字符串转换为原始二进制)@kakigadol
来自win32security import ConvertStringSidToSid
问题是,在我的例子中,我运行的是一台linux服务器,它无法安装PyWin32。最后我发现了这段代码,我复制了它的一些功能:我想如果安装Samba,这也可以在Windows上运行,当然也可以在MacOS上运行。
from samba.dcerpc import security
from samba.ndr import ndr_unpack

def convert(binary_sid):
    return str(ndr_unpack(security.dom_sid, binary_sid))