文档章节

解决ubuntu下twistd xxx --auth unix出现验证错误

疯狂的小企鹅
 疯狂的小企鹅
发布于 2014/08/31 12:16
字数 1124
阅读 39
收藏 0

测试了一下,在centos也是有效的。

首先给出程序的源代码。。使用twisted的plugin功能实现一个echo和远程执行命令的服务端:

 

 

#!/usr/bin/env python
#coding:utf8
# Author          : tuxpy
# Email           : q8886888@qq.com
# Last modified   : 2014-08-31 10:37:58
# Filename        : tw_cred.py
# Description     : 
from zope.interface import implements,Interface,implementer
from twisted.cred import checkers,credentials,portal
from twisted.internet import protocol,reactor
 
from twisted.protocols import basic
 
class IProtocolAvatar(Interface):
    def logout():
        """
        clean up per-login resources ollocated to this avator.
        """
    
 
 
 
class Avatar(object):
    implements(IProtocolAvatar)
 
    def logout(self):
        self.transport.loseConnection()
 
class EchoAvatar(Avatar):
    pass
 
class DoAvatara(Avatar):
 
    def do_comm(self,cmd,*args):
        from twisted.internet import utils
        output=utils.getProcessOutput(cmd,args=args,
                errortoo=True)
        output.addCallback(self.writeResponse)
 
    def writeResponse(self,result):
        self.transport.write(result)
 
 
 
class Echo(basic.LineReceiver):
    protal=None
    avatar=None
    logout=None
    delimiter='\n'
 
    def cocnnectionLost(self,reason):
        if self.logout:
            self.logout()
            self.avater=None
            seslf.logout=None
 
    def lineReceived(self,line):
        if not self.avatar:
            username,password=line.strip().split(" ")+[]
            self.tryLogin(username,password)
        else:
            if line.lower().strip()=='quit':
                self.avatar.logout()
            try:
                line=line.strip()
                cmd_parser=line.split(' ',1)
                if len(cmd_parser)>1:
                    cmd=cmd_parser[0]
                    args=cmd_parser[1:]
                else:
                    cmd,args=cmd_parser[0],tuple()
                self.avatar.do_comm(cmd.strip(),*args)
            except AttributeError,e:
                self.sendLine(line)
 
 
    def tryLogin(self,username,password):
        self.portal.login(credentials.UsernamePassword(username,
            password),
            None,IProtocolAvatar).addCallbacks(self._cbLogin,
                    self._ebLogin)
 
    def _cbLogin(self,(interface,avatar,logout)):
        self.avatar=avatar
        self.logout=logout
        self.avatar.transport=self.transport
        self.sendLine("Login successful,please procees.")
 
    def _ebLogin(self,failure):
        self.sendLine("Login denied,goodbye.")
     #   print failure
        self.transport.loseConnection()
 
class EchoFactory(protocol.Factory):
    def __init__(self,portal):
        self.portal=portal
 
    def buildProtocol(self,addr):
        protocol=Echo()
        protocol.portal=self.portal
        return protocol
        
class Realm(object):
    implements(portal.IRealm)
    
    def requestAvatar(self,avatarId,mind,*interfaces):
        if avatarId=='root':
            avatar=DoAvatara()
        else:
            avatar=EchoAvatar()
        return None,avatar,avatar.logout
 
        raise NotImplementedError("This realm only supports the IProtocolAvatar interface.")

插件文件:gedit  twisted/plugins/echo.py

#!/usr/bin/env python
#coding:utf8
# Author          : tuxpy
# Email           : q8886888@qq.com
# Last modified   : 2014-08-31 11:20:44
# Filename        : twisted/plugins/echo.py
# Description     : 
from twisted.application import internet,service
from twisted.plugin import IPlugin
from twisted.cred import credentials,portal,strcred
import sys
import os
sys.path.append(os.getcwd())
from tw_cred import EchoFactory,Realm
 
from twisted.python import usage
from zope.interface import implements
 
class Options(usage.Options,strcred.AuthOptionMixin):
    supportedInterfaces=(credentials.IUsernamePassword,)
    optParameters=[
            ["port",'p',1234,"The port number to listen on."]
            ]
 
class EchoServiceMaker(object):
    implements(service.IServiceMaker,IPlugin)
    tapname="echo"
    description="A TCP-base echo server."
    options=Options
 
    def makeService(self,options):
        p=portal.Portal(Realm(),options["credCheckers"])
        return internet.TCPServer(int(options['port']),EchoFactory(p))
serviceMaker=EchoServiceMaker()

启动:sudo twistd -n echo --auth unix -p 1235(为什么要用sudo,后面看cred_unix.py源代码中就会明白的)

但是这样启动好的话,按 书上说,我可以使用用户名和密码来验证,但是我怎么也验证不通过。因为我们的Options继承了strcred.AuthOptionMixin,同时我们又指定了credentials.IUsernamePassword接口,所以我们的插件会实现cred_*的那些checkers。于是查看twisted源代码。

 twisted/plugins/cred_unix.py

# -*- test-case-name: twisted.test.test_strcred -*-
#
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Cred plugin for UNIX user accounts.
"""
from zope.interface import implements
from twisted import plugin
from twisted.cred.strcred import ICheckerFactory
from twisted.cred.checkers import ICredentialsChecker
from twisted.cred.credentials import IUsernamePassword
from twisted.cred.error import UnauthorizedLogin
from twisted.internet import defer
def verifyCryptedPassword(crypted, pw):
    if crypted[0] == '$': # md5_crypt encrypted
        salt = '$1$' + crypted.split('$')[2]
    else:
        salt = crypted[:2]
    try:
        import crypt
    except ImportError:
        crypt = None
    if crypt is None:
        raise NotImplementedError("cred_unix not supported on this platform")
    return crypt.crypt(pw, salt) == crypted
class UNIXChecker(object):
    """
    A credentials checker for a UNIX server. This will check that
    an authenticating username/password is a valid user on the system.
    Does not work on Windows.
    Right now this supports Python's pwd and spwd modules, if they are
    installed. It does not support PAM.
    """
    implements(ICredentialsChecker)
    credentialInterfaces = (IUsernamePassword,)
    def checkPwd(self, pwd, username, password):
        try:
            cryptedPass = pwd.getpwnam(username)[1]
        except KeyError:
            return defer.fail(UnauthorizedLogin())
        else:
            if cryptedPass in ('*', 'x'):
                # Allow checkSpwd to take over
                return None
            elif verifyCryptedPassword(cryptedPass, password):
                return defer.succeed(username)
    def checkSpwd(self, spwd, username, password):
        try:
            cryptedPass = spwd.getspnam(username)[1]
        except KeyError:
            return defer.fail(UnauthorizedLogin())
        else:
            if verifyCryptedPassword(cryptedPass, password):
                return defer.succeed(username)
    def requestAvatarId(self, credentials):
        username, password = credentials.username, credentials.password
        try:
            import pwd
        except ImportError:
            pwd = None
        if pwd is not None:
            checked = self.checkPwd(pwd, username, password)
            if checked is not None:
                return checked
        try:
            import spwd
        except ImportError:
            spwd = None
        if spwd is not None:
            checked = self.checkSpwd(spwd, username, password)
            if checked is not None:
                return checked
        # TODO: check_pam?
        # TODO: check_shadow?
        return defer.fail(UnauthorizedLogin())
unixCheckerFactoryHelp = """
This checker will attempt to use every resource available to
authenticate against the list of users on the local UNIX system.
(This does not support Windows servers for very obvious reasons.)
Right now, this includes support for:
  * Python's pwd module (which checks /etc/passwd)
  * Python's spwd module (which checks /etc/shadow)
Future versions may include support for PAM authentication.
"""
class UNIXCheckerFactory(object):
    """
    A factory for L{UNIXChecker}.
    """
    implements(ICheckerFactory, plugin.IPlugin)
    authType = 'unix'
    authHelp = unixCheckerFactoryHelp
    argStringFormat = 'No argstring required.'
    credentialInterfaces = UNIXChecker.credentialInterfaces
    def generateChecker(self, argstring):
        """
        This checker factory ignores the argument string. Everything
        needed to generate a user database is pulled out of the local
        UNIX environment.
        """
        return UNIXChecker()
theUnixCheckerFactory = UNIXCheckerFactory()

verifyCryptedPassword函数中,也许是因为加密方式的不同,这样的验证会出现问题。只需要把verifyCryptedPassword函数改成这样,就能使用本地的username password验证了。。

 

def verifyCryptedPassword(crypted, pw):
    import platform
    if crypted[0] == '$': # md5_crypt encrypted
        if platform.system().lower() == "linux":
            salt = crypted
        else:
            salt = '$1$' + crypted.split('$')[2]
    else:
        salt = crypted[:2]
    try:
        import crypt
    except ImportError:
        crypt = None
 
    if crypt is None:
        raise NotImplementedError("cred_unix not supported on this platform")
    return crypt.crypt(pw, salt) == crypted




刚才在执行twistd时,为什么要加sudo?

通过源代码也可以看出,当pwd模块无法取得“密码”时,会使用spwd模块,而spwd模块是需要操作/etc/shadow文件,这个文件一般情况下,普通用户是没有读取权限的。spwd 会出现找不到用户的异常。



© 著作权归作者所有

疯狂的小企鹅

疯狂的小企鹅

粉丝 14
博文 42
码字总数 20243
作品 6
杭州
程序员
私信 提问
在 Linux 中使用日志来排错

人们创建日志的主要原因是排错。通常你会诊断为什么问题发生在你的 Linux 系统或应用程序中。错误信息或一系列的事件可以给你提供找出根本原因的线索,说明问题是如何发生的,并指出如何解决...

酱醋茶丶
2015/09/10
126
0
Ubuntu 安装 mysql && Ubuntu 安装 mysql 忘记初始密码解决方法

查看是否安装Mysql 如果为空则没有安装,进行安装: 根据提示输入密码,然后确认.. Mysql 连接测试 启动,停止,重启 Mysql命令 Ubuntu 安装 mysql 忘记初始密码解决方法 输入命令进入mysql...

legend3
2018/08/07
50
0
在twisted中按天进行日志切分

以往使用twsited服务器记录log使用的都是按照大小对日志切分,而现在有一个服务需要对log按照天进行切分,于是研究了一下twisted的日志记录方式,最后终于搞定。这里将分析过程记录下,以帮助...

疯子张
2014/02/12
287
0
rsync3.0.6服务端和客户端搭建(前期铺垫)

服务端:(环境:centos5.5 64位) 1.安装 : 使用yum -y install rsync 配置 vi /etc/xinetd.d/rsync 修改disable为no 不禁用 在/etc下创建rsyncd.conf文件 uid = root () gid = root use c......

哎哎哎
2013/07/25
658
0
Linux-PAM系统管理指南

By 书生, 出处:Morgan, Andrew G. 1.简介 Linux-PAM(Pluggable Authentication Modules for Linux.基于Linux的插入式验证模块)是一组共享库,使用这些模块,系统管理者可以自由选择应用程序...

LionelShen
2013/02/26
3.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

射频特征阻抗

Characteris Impendance(特性阻抗,也称为‘特征阻抗’)是我们经常看到并使用自己的术语之一,但非常模糊且难以解释。以下是来自几个不同来源的Characteris Impendance(特性阻抗)的一些定义。...

demyar
17分钟前
1
0
Spring Boot Tomcat配置项

参数配置容器 server.xx开头的是所有servlet容器通用的配置,server.tomcat.xx开头的是tomcat特有的参数,其它类似。 所有参数绑定配置类:org.springframework.boot.autoconfigure.web.Serv...

xiaomin0322
21分钟前
2
0
微课程 | 第二课《Docker 安装方式介绍》

微课程 | 第二课《Docker 安装方式介绍》视频 https://v.youku.com/v_show/id_XNDQ0NDUzNjkxNg==.html?spm=a2hzp.8244740.0.0 上一期我们介绍了 DBLE 的基本概况,下面进入我们的正题,正题基...

爱可生
21分钟前
2
0
GUAVA--基础工具(Preconditions)

1、前置条件 俗话说丑话讲在前面,在做某些事情的时候是需要做一些前置条件的。假如需要修改一条数据的话,当参数传进来,我们要先查询这条数据是否存在。这时候就需要一个if了,如果参数还需...

MrYuZixian
34分钟前
6
0
PythonSpot 中文系列教程 · 翻译完成

原文:PythonSpot Python Tutorials 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 在线阅读 ApacheCN 学习资源 目录 PythonSpot 中文系列教...

ApacheCN_飞龙
43分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部