无法连接到 Windows 共享

Posted

技术标签:

【中文标题】无法连接到 Windows 共享【英文标题】:Unable to connect to windows shares 【发布时间】:2013-09-16 17:44:44 【问题描述】:

我正在使用 pysmb library 查询 SMB/CIFS 网络共享上的共享/目录结构。

def ListShares(Server, Username=None, Password=None, Domain=None):
    Ip = socket.gethostbyname(Server)
    conn = SMBConnection(Username,
                         Password,
                         'MyApp',
                         Server,
                         Domain,
                         use_ntlm_v2=True,
                         sign_options=SMBConnection.SIGN_WHEN_SUPPORTED,
                         is_direct_tcp=True)
    assert conn.connect(Ip)

    Response = conn.listShares(timeout=30)

    return ['Name': x.name,
             'Type': x.type,
             'IsTemporary': x.isTemporary,
             'Comments': x.comments for x in Response if not x.isSpecial]

当连接到运行 samba 的 linux 机器时,我可以正常连接并且一切正常。当我尝试连接到 Win7/SBS2008/Server2008 共享时,出现错误。

如果is_direct_tcp=True,我得到Invalid protocol header for Direct TCP session message

File ".../MyApp/Managers/SmbHelper.py", line 38, in ListShares assert conn.connect(Ip) 
File "/opt/pyenv/lib/python3.3/site-packages/smb/SMBConnection.py", line 111, in connect self._pollForNetBiosPacket(timeout) 
File "/opt/pyenv/lib/python3.3/site-packages/smb/SMBConnection.py", line 504, in _pollForNetBIOSPacket self.feedData(data) 
File "/opt/pyenv/lib/python3.3/site-packages/nmb/base.py", line 49, in feedData length = self.data_nmb.decode(self.data_buf, offset) 
File "/opt/pyenv/lib/python3.3/site-packages/nmb/nmb_structs.py", line 60, in decode raise NMBError("Invalid protocol header for Direct TCP session message") 

如果is_direct_tcp=False,我会得到NotConnectedError

File ".../MyApp/Managers/SmbHelper.py", line 38, in ListShares assert conn.connect(Ip) 
File "/opt/pyenv/lib/python3.3/lib/site-packages/smb/SMBConnection.py", line 111, in connect self._pollForNetBIOSPacket(timeout) 
File "/opt/pyenv/lib/python3.3/lib/site-packages/smb/SMBConnection.py", line 466, in _pollForNetBIOSPacket raise NotConnectedError 

我碰到了一堵砖墙。我怎样才能找出究竟是什么错误并解决它?

进一步诊断...

smbclient -L linux.domain.local   -U MyUsername -W domain //Works
smbclient -L linux.domain.local   -U MyUsername@domain    //Doesn't work (Auth failed)
smbclient -L windows.domain.local -U MyUsername -W domain //Doesn't work (Auth failed)
smbclient -L windows.domain.local -U MyUsername@domain    //Works

smbclient -L [either].domain.local -U MyUsername@domain -W domain //Works, despite redundancy

因此,Linux 似乎从 -W 参数中获取域,Windows 从 Username@Domain 语法中获取域,并且两者都提供使得 smbclient 调用成功到任一服务器。不幸的是,即使我使用@Domain 语法,在 pysmb 中连接到 Windows 也不会成功

解决方案

有3个问题...首先,当use_direct_tcp = True时,port需要是445。当它是False 时,端口应该是139。使用 Python3 中的模块时也存在错误(字节编码不正确)。最后,它与服务器的通信方式存在问题(至少在连接到 Windows 机器而不是 linux samba 服务器时)。

该模块的作者 Michael Teo 开发了一个修复程序,我们已经对其进行了测试和工作。他计划很快更新软件包。

【问题讨论】:

【参考方案1】:

我不确定这对你的情况是否有帮助,但它对我有用:

    SmbConnection 的第三个参数应该是(我认为)client_machine_name,所以我把从socket.gethostname() 得到的东西传递给那里。

    我没有使用sign_optionsis_direct_tcp 我只是保留默认值。

这对我来说适用于 samba 和 windows 共享(有时我只需要传递不同的端口号)。

这是我使用的代码:

class Smb(object):
    def __init__(self, username, password, server, share, port=139):
        # split username if it contains a domain (domain\username)
        domain, username = username.split('\\') if username.count('\\') == 1 else ('', username)
        # setup data
        self.domain    = str(domain)
        self.username  = str(username)
        self.password  = str(password)
        self.client    = socket.gethostname()
        self.server    = str(server)
        self.server_ip = socket.gethostbyname(server)
        self.share     = str(share)
        self.port      = port
        self.conn      = None
        self.connected = False
        # SMB.SMBConnection logs too much
        smb_logger = logging.getLogger('SMB.SMBConnection')
        smb_logger.setLevel(logging.WARNING)

    def connect(self):
        try:
            self.conn = SMBConnection(self.username, self.password,
                                      self.client, self.server,
                                      use_ntlm_v2=True, domain=self.domain)
            self.connected = self.conn.connect(self.server_ip, self.port)
            logger.info('Connected to %s' % self.server)
            return self.connected
        except Exception, e:
            logger.error('Connect failed. Reason: %s', e)
            return False

并将其用作:

smb = Smb('domain\\user', 'password', 'server', 'share_name')

【讨论】:

谢谢,让我试试看会发生什么...嗯,这让我回到了NotConnectedError 确实如此。我使用 smbclient 更新了 Q 的更多诊断信息。此外,我可以远程登录到 139 上的任何一台机器,当我输入垃圾时会收到“无法识别的请求”,所以那里有东西在听 有趣的是,您的代码适用于 samba 盒子,但不适用于 windows...File "...site-packages\smb\base.py", line 331, in _handleSessionChallenge_SMB2\n self.signing_session_key = (session_key + '\\0'*16)[:16]\n", "TypeError: can't concat bytes to str\n" @Basic 抱歉,这是针对 python 2.7 的:-/ 错过了 python3 标签。我什至不记得为什么我到处都有str。如果我传递了一个 unicode 字符串,我认为模块会引发异常。代码是几个月前的...... 我接受,因为这实际上为我指明了正确的方向。我使用了格式不正确的服务器名称(我使用的是srv.domain.local 而不仅仅是srv)。此后我遇到了另一个问题(缓冲区溢出),但这是一个不同的问题。感谢您的宝贵时间

以上是关于无法连接到 Windows 共享的主要内容,如果未能解决你的问题,请参考以下文章

windows 无法连接到打印机。操作失败,错误为0x0000011b?

windows无法连接到打印机。请检查打印机名并重试。如果这是网络打印机,请确保打印机已打开

Windows无法连接到打印机操作失败,错误为0x00000bcb

无法连接到 Windows 共享

windows远程桌面之前用于连接到xxx的凭据无法工作

MacOS从莫哈韦沙漠升级为卡塔琳娜之后,我无法连接到SMB共享