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

时间:2015-10-17 15:38:36

标签: python active-directory

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

5 个答案:

答案 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.aspxhttp://codeimpossible.com/2008/04/07/Converting-a-Security-Identifier-from-binary-to-string/

答案 1 :(得分:2)

使用或查看ldap3中的实现 ldap-doc
source

  

ldap3.protocol.formatters.formatters.format_sid

答案 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