radius authentication challenge

background

We do based on two-factor authentication radius, but does not find a convenient test radius server, the Internet looking for freeradius, toss for a long time did not get, if you can write your own thought, as long as the prototype of a radius of a challenge should be made relatively simple.

pyrad

Found pyrad, this library is to provide the basic operation of a radius, providing client and server libraries, the server tried it, get up on the windows, so they can only write from scratch.
The basic idea is that you create a udp socket, listen, after receiving the packets, using pyrad be resolved, then do that handles authentication, and then pyrad create a response message.
code show as below:

from pyrad import *
import socket
import pyrad.host
import random

BUFSIZE = 1024
KEY = b"testing123"
CHALLENGE = "test2"

class RadiusServer(pyrad.host.Host):
    def __init__(self):
        dict = pyrad.dictionary.Dictionary("dictionary.rfc2865") #从freeradius中搞一个通用的字典使用
        pyrad.host.Host.__init__(self, dict=dict)

    def get_challenge(self): #产生一个4字节的随机挑战码
        challenge = ""
        challenge = challenge + str(chr(random.randint(65,90)))
        challenge = challenge + str(chr(random.randint(65,90)))
        challenge = challenge + str(chr(random.randint(65,90)))
        challenge = challenge + str(chr(random.randint(65,90)))
        return challenge

    def check_pass(self, radpkt): #检查用户名密码,这里简单处理一下,如果密码是test则发起挑战,如果输入正确的挑战码,回应正确,否则失败
        global CHALLENGE
        print("check user")
        if radpkt.PwCrypt(CHALLENGE) == radpkt["User-Password"][0]:
            radpkt.code = packet.AccessAccept
            CHALLENGE = self.get_challenge() #挑战码使用过后就更换掉
            print("AccessAccept")
        elif radpkt.PwCrypt("test") == radpkt["User-Password"][0]:
            radpkt.code = packet.AccessChallenge
            CHALLENGE = self.get_challenge()
            radpkt.AddAttribute("Reply-Message", CHALLENGE) #把挑战码发给客户端
            print("AccessChallenge, please input", CHALLENGE)
        else:
            radpkt.code = packet.AccessReject
            print("AccessReject")

    def get_pkt(self, pkt):
        get_pw = None
        get_name = None
        radpkt = self.CreateAuthPacket(packet=pkt) #解析请求报文
        print("code:", radpkt.code)
        print("authenticator:", radpkt.authenticator)
        print("id:", radpkt.id)
        #radpkt.code = packet.AccessChallenge
        radpkt.secret = KEY

        for key in radpkt.keys():
            print(key, radpkt[key])
            if key == "User-Password":
                get_pw = 1
            if key == "User-Name":
                get_name = 1
        
        if 1 == get_pw and 1 == get_name:
            self.check_pass(radpkt)

        return radpkt.ReplyPacket()

ip_port = ('', 1812)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # udp协议
server.bind(ip_port)


while True:
    data,client_addr = server.recvfrom(BUFSIZE)
    srv = RadiusServer()
    reply = srv.get_pkt(data)
    server.sendto(reply, client_addr)

Test, using freeradius comes with ratest test.

使用第一次验证用的密码进行请求:  
C:\FreeRADIUS.net\bin>radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.1 auth testing123
Sending Access-Request of id 172 to 127.0.0.1 port 1812
        User-Name = "admin"
        User-Password = "test"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123
rad_recv: Access-Challenge packet from host 127.0.0.1:1812, id=172, length=63
        User-Name = "admin"
        User-Password = "test"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123
        Reply-Message = "PFJT"

           Total approved auths:  1
             Total denied auths:  0
               Total lost auths:  0
PS C:\FreeRADIUS.net\bin> .\radtest.bat

收到了应答,里面带了挑战码

#使用挑战码去请求:  
C:\FreeRADIUS.net\bin>radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.1 auth testing123
Sending Access-Request of id 0 to 127.0.0.1 port 1812
        User-Name = "admin"
        User-Password = "PFJT"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123
rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=0, length=57
        User-Name = "admin"
        User-Password = "PFJT"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123

           Total approved auths:  1
             Total denied auths:  0
               Total lost auths:  0
PS C:\FreeRADIUS.net\bin> .\radtest.bat


第二次使用挑战码请求,挑战码已经失效,应该请求失败:
C:\FreeRADIUS.net\bin>radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.1 auth testing123
Sending Access-Request of id 196 to 127.0.0.1 port 1812
        User-Name = "admin"
        User-Password = "PFJT"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123
rad_recv: Access-Reject packet from host 127.0.0.1:1812, id=196, length=57
        User-Name = "admin"
        User-Password = "PFJT"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123

           Total approved auths:  0
             Total denied auths:  1
               Total lost auths:  0

And then improve it, to respond to the message be less the requested attributes.

from pyrad import *
import socket
import pyrad.host
import random

BUFSIZE = 1024
KEY = b"testing123"
CHALLENGE = "test2"

class RadiusServer(pyrad.host.Host):
    def __init__(self):
        dict = pyrad.dictionary.Dictionary("dictionary.rfc2865") #从freeradius中搞一个通用的字典使用
        pyrad.host.Host.__init__(self, dict=dict)

    def get_challenge(self): #产生一个4字节的随机挑战码
        challenge = ""
        challenge = challenge + str(chr(random.randint(65,90)))
        challenge = challenge + str(chr(random.randint(65,90)))
        challenge = challenge + str(chr(random.randint(65,90)))
        challenge = challenge + str(chr(random.randint(65,90)))
        return challenge

    def check_pass(self, radpkt, get_pw): #检查用户名密码,这里简单处理一下,如果密码是test则发起挑战,如果输入正确的挑战码,回应正确,否则失败
        global CHALLENGE
        print("check user")
        pwd = ""
        
        if 1 == get_pw:
            pwd = radpkt["User-Password"][0]    
            
            if radpkt.PwCrypt(CHALLENGE) == pwd:
                radpkt.code = packet.AccessAccept
                CHALLENGE = self.get_challenge() #挑战码使用过后就更换掉
                print("AccessAccept")
            elif radpkt.PwCrypt("test") == pwd:
                radpkt.code = packet.AccessChallenge
                CHALLENGE = self.get_challenge()
                radpkt.AddAttribute("Reply-Message", CHALLENGE) #把挑战码发给客户端
                print("AccessChallenge, please input", CHALLENGE)
            else:
                radpkt.code = packet.AccessReject
                print("AccessReject")
                    
    def get_pkt(self, pkt):
        get_pw = None
        get_name = None
        radpkt = self.CreateAuthPacket(packet=pkt) #解析请求报文
        print("code:", radpkt.code)
        print("authenticator:", radpkt.authenticator)
        print("id:", radpkt.id)
        #radpkt.code = packet.AccessChallenge
        radpkt.secret = KEY

        for key in radpkt.keys():
            print(key, radpkt[key])
            if key == "User-Password":
                get_pw = 1
            if key == "User-Name":
                get_name = 1
        
        if 1 == get_pw and 1 == get_name:
            self.check_pass(radpkt, get_pw)
            
        reply = radpkt.CreateReply()
        
        for key in radpkt.keys():
            if key == "User-Name":
                reply.AddAttribute("User-Name", radpkt["User-Name"][0])

            if key == "Reply-Message":
                reply.AddAttribute("Reply-Message", radpkt["Reply-Message"][0])

            if key == "NAS-IP-Address":
                reply.AddAttribute("NAS-IP-Address", radpkt["NAS-IP-Address"][0])

            #reply.source = radpkt.source
            reply.code = radpkt.code

        return reply.ReplyPacket()

ip_port = ('', 1812)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # udp协议
server.bind(ip_port)


while True:
    data,client_addr = server.recvfrom(BUFSIZE)
    srv = RadiusServer()
    reply = srv.get_pkt(data)
    server.sendto(reply, client_addr)

test:

PS C:\FreeRADIUS.net\bin> .\radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.0.0.1 auth testing123
Sending Access-Request of id 48 to 127.0.0.1 port 1812
        User-Name = "admin"
        User-Password = "test"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123
rad_recv: Access-Challenge packet from host 127.0.0.1:1812, id=48, length=39
        User-Name = "admin"
        NAS-IP-Address = 127.0.0.1
        Reply-Message = "UTJG"

           Total approved auths:  1
             Total denied auths:  0
               Total lost auths:  0
PS C:\FreeRADIUS.net\bin> .\radclient.exe -d ..\etc\raddb -f radtest.txt -x -s 127.0.0.1 auth testing123
Sending Access-Request of id 228 to 127.0.0.1 port 1812
        User-Name = "admin"
        User-Password = "UTJG"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 123
rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=228, length=33
        User-Name = "admin"
        NAS-IP-Address = 127.0.0.1

           Total approved auths:  1
             Total denied auths:  0
               Total lost auths:  0

Guess you like

Origin www.cnblogs.com/luckpiky/p/11441916.html