通过在 linux 上使用 python 从 smb 共享获取文件的所有者

Getting owner of file from smb share, by using python on linux

我需要找出我正在编写的脚本谁是 smb 共享中文件的真正所有者(当然在我的服务器上使用 mount -t cifs 安装并使用 net use 通过windows 台机器)。

事实证明,在 linux 服务器上使用 python 查找此信息是一项真正的挑战。

我尝试使用很多 smb 库(例如 smbprotocol、smbclient 等),但没有任何效果。
我发现 windows 的解决方案很少,它们都使用 pywin32 或其他 windows 特定包。
而且我还设法从 bash 使用 smbcalcs 做到了,但不能干净利落地使用 subprocess.popen('smbcacls')..

知道如何解决吗?

令人难以置信的是,这不是一项微不足道的任务,不幸的是,答案并不像我希望的那样简单..

如果将来有人会遇到同样的问题,我会post回答这个问题,但希望有人会post早点找到更好的解决方案

为了找到我使用的所有者 this library with its examples:

from smb.SMBConnection import SMBConnection

conn = SMBConnection(username='<username>', password='<password>', domain=<domain>', my_name='<some pc name>', remote_name='<server name>')
conn.connect('<server name>')

sec_att = conn.getSecurity('<share name>', r'\some\file\path')
owner_sid = sec_att.owner

问题是 pysmb 包只会给你所有者的 SID 而不是他的名字。
为了得到他的名字,你需要(重新post输入代码):

from ldap3 import Server, Connection, ALL
from ldap3.utils.conv import escape_bytes

s = Server('my_server', get_info=ALL)
c = Connection(s, 'my_user', 'my_password')
c.bind()

binary_sid = b'....'  # your sid must be in binary format

c.search('my_base', '(objectsid=' + escape_bytes(binary_sid) + ')', attributes=['objectsid', 'samaccountname'])
print(c.entries)

但当然没有什么是容易的,我花了几个小时才找到一种方法将字符串 SID 转换为二进制 SID python,and in the end this solved it:

# posting the needed functions and omitting the class part
def byte(strsid):
    '''
    Convert a SID into bytes
        strdsid - SID to convert into bytes
    '''
    sid = str.split(strsid, '-')
    ret = bytearray()
    sid.remove('S')
    for i in range(len(sid)):
        sid[i] = int(sid[i])
    sid.insert(1, len(sid)-2)
    ret += longToByte(sid[0], size=1)
    ret += longToByte(sid[1], size=1)
    ret += longToByte(sid[2], False, 6)
    for i in range(3, len(sid)):
        ret += cls.longToByte(sid[i])
    return ret

def byteToLong(byte, little_endian=True):
    '''
    Convert bytes into a Python integer
        byte - bytes to convert
        little_endian - True (default) or False for little or big endian
    '''
    if len(byte) > 8:
        raise Exception('Bytes too long. Needs to be <= 8 or 64bit')
    else:
        if little_endian:
            a = byte.ljust(8, b'\x00')
            return struct.unpack('<q', a)[0]
        else:
            a = byte.rjust(8, b'\x00')
            return struct.unpack('>q', a)[0]  

...最后您有了完整的解决方案!享受:(