Python Samba: 用户凭据未传递(cli_init_creds)?

1 投票
1 回答
3425 浏览
提问于 2025-04-17 00:07

我现在在Ubuntu上遇到一个问题,就是无法访问Windows的打印共享(因为在公司,所以我没法接触到他们的设置)。于是我开始研究Gnome的一个叫做'system-config-printer'的程序,它是用Python写的,并且使用了Python的smbc库来处理Samba。

 

我基本上把问题缩小到了这段代码,这段代码来自于/usr/share/system-config-printer/pysmb.py,我在python命令行中运行它:

import smbc, os 
def do_auth (svr, shr, wg, un, pw):
  return ("myworkdomain.com", "MYWORKUSERNAME", "MYWORKPASSWORD")

ctx = smbc.Context (debug=10, auth_fn=do_auth)
f = ctx.open ("smb://%s/%s" % ("printserver.myworkdomain.com", "PRINTSHARENAME"), os.O_RDWR, 0777)

 

第一个(算是)问题是,当执行ctx = smbc.Context...这一行时,Python总是会报错:

params.c:OpenConfFile() - Unable to open configuration file "/home/MYUSERNAME/.smb/smb.conf":
    No such file or directory

... 但这可能不算真正的问题?(也许smbc 本来就是要重新创建这个文件的?

 

真正的大问题是,我无法连接到共享:在执行f = ctx.open...这一行后,会有大量的Samba通信信息,Windows服务器似乎在回应什么,但连接的尝试最终还是失败了:

SPNEGO login failed: Logon failure
cli_init_creds: user  domain myworkdomain.com
 session setup ok
map_errno_from_nt_status: 32 bit codes: code=c0000022
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
smbc.PermissionError: (13, 'Permission denied')

基本上,我对Samba了解得太少,无法看懂后面的错误日志,但我发现这一行:

cli_init_creds: user  domain myworkdomain.com

... 让我觉得很可疑——看起来这里的'user'是一个空字符串——尽管我本来期待它是'MYWORKUSERNAME',正如上面do_auth函数所指定的那样!!

注意,这个失败有点像我在命令行使用smbclient时遇到的NT_STATUS_LOGON_FAILURE错误(参见获取Windows打印共享SMB设置(用于tsclient/rdesktop在Linux上) - Super User),那个问题是通过在命令行中明确指定Windows工作组解决的——不过,我不确定在Python的情况下是否也是这个问题;或者说,用户名没有传递过来(或者是其他完全不同的原因)。编辑:这个有效的命令行(用于列出共享)是(针对这个例子):

smbclient -L \\printserver.myworkdomain.com -U MYWORKUSERNAME -W myworkdomain.com

 

提前感谢任何建议,
谢谢!

1 个回答

1

好的,我想我终于明白了,感谢在Bug #848065 “system-config-printer无法认证Windows Samba打印机,而smbclient可以(cli_init_creds)”中的评论,以及查看newprinter.py(来自system-config-printer)...

首先,给大家简单介绍一下情况:

  • 我在Ubuntu机器上的本地用户名是:MYUSERNAME
  • 工作网络的主地址(域名)是:myworkdomain.com
  • 我在工作网络上的账户名是:MYWORKUSERNAME
  • 我的工作账户属于工作组MYWORKGROUP,这个工作组还有一个子域名myworkgroup.myworkdomain.com
  • 工作网络上的打印服务器地址是printserver.myworkdomain.com
  • 我想访问的打印服务器上的打印机名称(共享)是PRINTSHARENAME

 

结果发现,上面test.py脚本中的一行是错的 - 应该是:

return ("myworkdomain.com", "MYWORKUSERNAME", "MYWORKPASSWORD")

... 应该改成:

return ("MYWORKGROUP", "MYWORKUSERNAME", "MYWORKPASSWORD")

...(MYWORKGROUP要全大写,这在Windows中是常见的)

 

有趣的是,使用工作组的子域名并不有效:

return ("myworkgroup.myworkdomain.com", "MYWORKUSERNAME", "MYWORKPASSWORD")

... 这样也会出现'smbc.PermissionError: (13, 'Permission denied')'的错误(就像原帖中的例子一样)。

 

解决“权限被拒绝”错误的一种方法是查看日志 - 它显示的内容大致是这样的:

    DomainNameLen            : 0x000c (12)
    DomainNameMaxLen         : 0x000c (12)
    DomainName               : *
        DomainName               : 'myworkdomain.com'
    UserNameLen              : 0x0004 (4)
    UserNameMaxLen           : 0x0004 (4)
    UserName                 : *
        UserName                 : 'MYWORKUSERNAME'
    WorkstationLen           : 0x0012 (18)
    WorkstationMaxLen        : 0x0012 (18)
    Workstation              : *
        Workstation              : 'MYPC'

... 显然,域名应该是:

        DomainName               : 'MYWORKGROUP'

 

作为参考,这里是“工作”设置的日志片段(使用return ("MYWORKGROUP" ...):

...
cli_init_creds: user MYWORKUSERNAME domain MYWORKGROUP
 session setup ok
 tconx ok
...
Could not retrieve case sensitivity flag: NT_STATUS_INVALID_DEVICE_REQUEST.
Server connect ok: //printserver.myworkdomain.com/PRINTSHARENAME: 0xa297768
Performing aggressive shutdown.
...
smbc_remove_usused_server: 0xa297768 removed.
Context 0xa276658 successfully freed

撰写回答