Пример #1
0
    def test_success_okta(self, a, b):
        self.server.hosts["127.0.0.1"] = os.getenv('RADIUS_SECRET')
        self.server.BindToAddress("127.0.0.1")

        Client(server="127.0.0.1", secret=os.getenv('RADIUS_SECRET').encode(), dict=Dictionary("dictionary"))

        # create request
        req = AuthPacket(
            id=AccessRequest,
            secret=os.getenv('RADIUS_SECRET').encode(),
            authenticator=b'01234567890ABCDEF',
            dict=Dictionary("dictionary")
        )
        req["User-Name"] = '*****@*****.**'
        req["User-Password"] = req.PwCrypt('fake')
        req["Proxy-State"] = 'state'.encode("ascii")
        req.source = ("test", "port")
        fd = MockFd()
        req.fd = fd

        # send request
        with self.assertLogs('server', level='INFO') as log:
            self.server.auth_handler(req)
            self.assertEqual(fd.data, b'\x02\x01\x00\x1b\x82\xb4\x88\xb4G\xbc:\xde\xc1\xe5A\xe0\xe7y\r\x1f!\x07state')
            self.assertIn('INFO:server:Push approved by [email protected].', log.output)
Пример #2
0
    def HandleAuthPacket(self:server.Server, pkt:packet.AuthPacket):
        print(vars())
        print("Auth request: ")
        print(pkt)
        reply = self.CreateReplyPacket(pkt, **{"Service-Type": "Framed-User", "Framed-IP-Address": pkt['Framed-IP-Address'][0]})  # type: packet.AuthPacket
        print(dir(reply))
        reply.code = packet.AccessReject
        for attr in pkt.keys():
            print("%s: %s" % (attr, pkt[attr]))
        if "User-Password" in pkt.keys():

            print("Checking Password")
            print(pkt.secret)
            pkt.dict
            passwd = pkt.PwDecrypt(pkt.get(2)[0])
            print(passwd)
            # Remove expired vouchers before authenticating
            GuestServer.removeExpiredVouchers()
            # Auth against current tokens
            print(list(map(lambda v: str(v), GuestServer.vouchers)))
            if GuestServer.vouchers and reduce(lambda a, b: a or b, map(lambda v: v.authenticate(passwd), GuestServer.vouchers)):
                print("Auth Success")
                reply.code = packet.AccessAccept
            else:
                print("Auth Failed")
        self.SendReplyPacket(pkt.fd, reply)
Пример #3
0
def process_request(data, address, secret):
    error_message = None

    pkt = AuthPacket(packet=data, secret=secret, dict={})
    reply_pkt = pkt.CreateReply()
    reply_pkt.code = AccessReject

    try:
        username = pkt.get(1)[0]
        try:
            password = pkt.PwDecrypt(pkt.get(2)[0])
        except UnicodeDecodeError:
            logger.error("Error decrypting password -- probably incorrect secret")
            reply_pkt.code = AccessReject
            return reply_pkt.ReplyPacket()

        auth_status = auth_with_foxpass(username, password) and two_factor(username)

        if auth_status:
            logger.info('Successful auth')
            reply_pkt.code = AccessAccept
            return reply_pkt.ReplyPacket()

        logger.info('Incorrect password')
        error_message = 'Incorrect password'

    except Exception as e:
        logger.exception(e)
        error_message = 'Unknown error'

    if error_message:
        reply_pkt.AddAttribute(18, error_message)
    return reply_pkt.ReplyPacket()
Пример #4
0
def add_mppe(
    reply: AuthPacket,
    send_key: bytes,
    recv_key: bytes,
    secret: bytes,
    authenticator: bytes,
) -> None:
    """
    Add MPPE (Microsoft Point to Point Encryption) Send and Recv keys to the provided packet

    Args:
        reply: the reply to add the send key and recv key to
        send_key: The plaintext MS-MPPE-Send-Key to encrypt and add to the reply
        recv_key: The plaintext MS-MPPE-Recv-Key to encrypt and add to the reply
        secret: the RADIUS secret
        authenticator: RADIUS authenticator. Should be 16 bytes.

    """
    sodiumchloride = _generator.randint(32768,
                                        65535)  # Leftmost bit must be set
    potassiumnitrate = _generator.randint(32768,
                                          65535)  # Leftmost bit must be set
    send_key_salt = struct.pack(">H", sodiumchloride)
    recv_key_salt = struct.pack(">H", potassiumnitrate)

    encrypted_send_key = encrypt_mppe(send_key, secret, authenticator,
                                      send_key_salt)
    encrypted_recv_key = encrypt_mppe(recv_key, secret, authenticator,
                                      recv_key_salt)

    reply.AddAttribute((MICROSOFT_VENDOR_ID, MS_MPPE_SEND_KEY_TYPE),
                       send_key_salt + encrypted_send_key)
    reply.AddAttribute((MICROSOFT_VENDOR_ID, MS_MPPE_RECV_KEY_TYPE),
                       recv_key_salt + encrypted_recv_key)
Пример #5
0
    def test_using_samaccountname_flag(self, o, mock_get, mock_post):
        self.assertIsNotNone(os.environ.get('OKTA_USE_SAMACCOUNTNAME'))

        self.server.hosts["127.0.0.1"] = os.getenv('RADIUS_SECRET')
        self.server.BindToAddress("127.0.0.1")

        Client(server="127.0.0.1", secret=os.getenv('RADIUS_SECRET').encode(), dict=Dictionary("dictionary"))

        # create request
        req = AuthPacket(
            id=AccessRequest,
            secret=os.getenv('RADIUS_SECRET').encode(),
            authenticator=b'01234567890ABCDEF',
            dict=Dictionary("dictionary")
        )
        req["User-Name"] = 'username'
        req["User-Password"] = req.PwCrypt('fake')
        req["Proxy-State"] = 'state'.encode()
        req.source = ("test", "port")
        fd = MockFd()
        req.fd = fd

        # send request
        with self.assertLogs('server', level='INFO') as log:
            o.return_value = '00ub0oNGTSWTBKOLGLNR'
            self.server.auth_handler(req)
            o.assert_called_once_with('username')
            self.assertEqual(fd.data, b'\x02\x01\x00\x1b\x82\xb4\x88\xb4G\xbc:\xde\xc1\xe5A\xe0\xe7y\r\x1f!\x07state')
            self.assertIn('INFO:server:Push approved by username.', log.output)
Пример #6
0
 def __init__(self,
              code=AccessRequest,
              id=None,
              secret=six.b(''),
              authenticator=None,
              **attributes):
     AuthPacket.__init__(self, code, id, secret, authenticator,
                         **attributes)
Пример #7
0
 def __init__(self, code=AccessRequest, id=None, secret=six.b(''),
         authenticator=None, **attributes):
     AuthPacket.__init__(self, code, id, secret, authenticator, **attributes)
     self.deferred = Deferred()
     self.source_user = None
     self.vendor_id = 0
     self.vlanid = 0
     self.vlanid2 = 0
     self.client_macaddr = None
     self.created = datetime.datetime.now()
Пример #8
0
    def _create_reply(self, request_packet: packet.AuthPacket,
                      success: bool) -> AuthResult:
        """
        Creates an AuthResult as a reply the given request_packet
        Args:
            request_packet: The request to create a reply to
            success: True if the reply should have code AccessAccept, false for AccessReject
        """
        pass_through_attrs = copy.copy(self.pass_through_radius_attrs)

        reply = request_packet.CreateReply()
        reply.code = packet.AccessAccept if success else packet.AccessReject
        reply.authenticator = request_packet.authenticator
        reply.AddAttribute("Reply-Message", "Hello")

        # If it's an MS-CHAPv2 request, add the MS-MPPE-Send-Key and MS-MPPE-Recv-Key
        if ("MS-CHAP-Challenge" in request_packet
                or "MS-CHAP2-Response" in request_packet):
            mppe.add_mppe(
                reply,
                self.ms_mppe_send_key,
                self.ms_mppe_recv_key,
                self.secret.encode(),
                request_packet.authenticator,
            )

        # Include error info in response, if it's MS-CHAP2 and an error
        if not success and self.chap_challenge:
            pass_through_attrs["MS-CHAP-Error"] = [b"\x00E=691 R=0 V=3"]
        if request_packet.get("MS-CHAP2-Response") == [
                self.chap2_response_expired.encode()
        ]:
            pass_through_attrs["MS-CHAP-Error"] = [b"\x00E=648 R=0 V=3"]

        add_packet_attributes(reply, pass_through_attrs)

        # Wrap the reply in an AuthResult
        pass_through_attr_names = (list(pass_through_attrs.keys()) +
                                   MS_CHAP2_RESPONSE_ATTRS)
        auth_result = AuthResult.from_radius_packet(reply,
                                                    pass_through_attr_names)

        return auth_result
Пример #9
0
def process_request(data, address, secret):
    error_message = None

    pkt = AuthPacket(packet=data, secret=secret, dict={})
    reply_pkt = pkt.CreateReply()
    reply_pkt.code = AccessReject

    try:
        username = pkt.get(1)[0]
        try:
            password = pkt.PwDecrypt(pkt.get(2)[0])
        except UnicodeDecodeError:
            logger.error(
                "Error decrypting password -- probably incorrect secret")
            reply_pkt.code = AccessReject
            return reply_pkt.ReplyPacket()

        auth_status = auth_with_foxpass(username,
                                        password) and two_factor(username)

        if auth_status:
            logger.info('Successful auth')
            reply_pkt.code = AccessAccept
            return reply_pkt.ReplyPacket()

        logger.info('Incorrect password')
        error_message = 'Incorrect password'

    except Exception as e:
        logger.exception(e)
        error_message = 'Unknown error'

    if error_message:
        reply_pkt.AddAttribute(18, error_message)
    return reply_pkt.ReplyPacket()
def process_request(data, address, secret):
    error_message = None

    pkt = AuthPacket(packet=data, secret=secret, dict={})
    reply_pkt = pkt.CreateReply()
    reply_pkt.code = AccessReject

    try:
        username = pkt.get(1)[0]
        logger.info("Auth attempt for '%s'" % (username,))
        try:
            password = pkt.get(2)
            if not password:
                logger.error("No password field in request")
                reply_pkt.code = AccessReject
                return reply_pkt.ReplyPacket()

            password = pkt.PwDecrypt(password[0])
        except UnicodeDecodeError:
            logger.error("Error decrypting password -- probably incorrect secret")
            reply_pkt.code = AccessReject
            return reply_pkt.ReplyPacket()

        auth_status = auth_with_foxpass(username, password) and group_match(username) and two_factor(username)

        if auth_status:
            logger.info("Successful auth for '%s'" % (username,))
            reply_pkt.code = AccessAccept
            return reply_pkt.ReplyPacket()

        logger.info("Authentication failed for '%s'" % (username,))
        error_message = 'Authentication failed'

    except Exception as e:
        logger.exception(e)
        error_message = str(e)

    if error_message:
        reply_pkt.AddAttribute(18, error_message)
    return reply_pkt.ReplyPacket()
Пример #11
0
 def handle(self, data, address):
     ip, port = address
     print('from %s, data: %r' % (ip, data))
     # 处理
     request = AuthPacket(dict=self.dictionary, secret=SECRET, packet=data)
     is_user = True
     if is_user:
         reply = access_accept(request)
         print('access_accept')
     else:
         reply = access_reject(request)
         print('access_reject')
     reply['Acct-Interim-Interval'] = 60
     # 返回
     self.socket.sendto(reply.ReplyPacket(), address)
Пример #12
0
def add_mppe(reply: AuthPacket, keys: List[bytes], secret: bytes,
             auth: bytes) -> None:
    """
    Add MPPE (Microsoft Point to Point Encryption) attributes to the reply packet

    Args:
        reply (AuthPacket): the reply that will be sent
        keys [bytes, bytes]: two-element list of bytes that are the MPPE keys
        secret (bytes): the RADIUS secret
        auth (bytes): RADIUS authenticator

    """
    sodiumchloride = _generator.randint(32768,
                                        65535)  # Leftmost bit must be set
    potassiumnitrate = _generator.randint(32768,
                                          65535)  # Leftmost bit must be set
    salt = struct.pack('>H', sodiumchloride)
    salt2 = struct.pack('>H', potassiumnitrate)
    encrypted_keys = [
        encrypt_mppe(keys[0], secret, auth, salt),
        encrypt_mppe(keys[1], secret, auth, salt2)
    ]
    reply.AddAttribute(26, ms_attr(17, salt + encrypted_keys[0]))  # Recv-key
    reply.AddAttribute(26, ms_attr(16, salt2 + encrypted_keys[1]))  # Send-Key
Пример #13
0
    def testSendPacket(self):
        def MockSend(self, pkt, port):
            self._mock_pkt = pkt
            self._mock_port = port

        _SendPacket = Client._SendPacket
        Client._SendPacket = MockSend

        self.client.SendPacket(AuthPacket())
        self.assertEqual(self.client._mock_port, self.client.authport)

        self.client.SendPacket(AcctPacket())
        self.assertEqual(self.client._mock_port, self.client.acctport)

        Client._SendPacket = _SendPacket
Пример #14
0
    def CreateAuthPacket(self, **args):
        """Create a new RADIUS packet.
        This utility function creates a new RADIUS packet which can
        be used to communicate with the RADIUS server this client
        talks to. This is initializing the new packet with the
        dictionary and secret used for the client.

        :return: a new empty packet instance
        :rtype:  pyrad.packet.Packet
        """
        if not self.protocol_auth:
            raise Exception('Transport not initialized')

        return AuthPacket(dict=self.dict,
                          id=self.protocol_auth.create_id(),
                          secret=self.secret, **args)
Пример #15
0
    def handle(self, data, address):
        ip, port = address
        # print('from %s, data: %r' % (ip, data))

        # 解析报文
        request = AuthPacket(dict=self.dictionary, secret=SECRET, packet=data)

        # 验证用户
        auth_user = verify(request)

        # 接受或拒绝
        reply = access_reject(request)
        if auth_user.is_valid:
            if is_unique_session(mac_address=auth_user.mac_address):
                reply = access_accept(request)

        # 返回
        reply['Acct-Interim-Interval'] = ACCT_INTERVAL
        self.socket.sendto(reply.ReplyPacket(), address)
Пример #16
0
def process_request(data, address, secret):
    error_message = None

    pkt = AuthPacket(packet=data,
                     secret=secret,
                     dict=Dictionary(io.StringIO(DICTIONARY_DATA)))
    reply_pkt = pkt.CreateReply()
    reply_pkt.code = AccessReject

    try:
        # [0] is needed because pkt.get returns a list
        pkt_username = pkt.get('User-Name')[0]
        logger.info("Auth attempt for '%s'" % (pkt_username, ))
        try:
            password = pkt.get('Password')
            if not password:
                logger.error("No password field in request")
                reply_pkt.code = AccessReject
                return reply_pkt.ReplyPacket()

            # [0] is needed because pkt.get returns a list
            password = pkt.PwDecrypt(password[0])
        except UnicodeDecodeError:
            logger.error(
                "Error decrypting password -- probably incorrect secret")
            reply_pkt.code = AccessReject
            return reply_pkt.ReplyPacket()

        (auth_status, username) = auth_with_foxpass(pkt_username, password)
        auth_status = auth_status and group_match(username) and two_factor(
            username)

        if auth_status:
            logger.info("Successful auth for '%s'" % (pkt_username, ))
            reply_pkt.code = AccessAccept
            return reply_pkt.ReplyPacket()

        logger.info("Authentication failed for '%s'" % (pkt_username, ))
        error_message = 'Authentication failed'

    except Exception as e:
        logger.exception(e)
        error_message = str(e)

    if error_message:
        reply_pkt.AddAttribute('Reply-Message', error_message)
    return reply_pkt.ReplyPacket()
Пример #17
0
 def __init__(self, code=AccessRequest, id=None, secret=six.b(''),
         authenticator=None, **attributes):
     AuthPacket.__init__(self, code, id, secret, authenticator, **attributes)   
Пример #18
0
    def datagram_received(self, data, addr):
        self.logger.debug('[%s:%d] Received %d bytes from %s', self.ip,
                          self.port, len(data), addr)

        receive_date = datetime.utcnow()

        if addr[0] in self.hosts:
            remote_host = self.hosts[addr[0]]
        elif '0.0.0.0' in self.hosts:
            remote_host = self.hosts['0.0.0.0']
        else:
            self.logger.warn('[%s:%d] Drop package from unknown source %s',
                             self.ip, self.port, addr)
            return

        try:
            self.logger.debug('[%s:%d] Received from %s packet: %s', self.ip,
                              self.port, addr, data.hex())
            req = Packet(packet=data, dict=self.server.dict)
        except Exception as exc:
            self.logger.error('[%s:%d] Error on decode packet: %s', self.ip,
                              self.port, exc)
            return

        try:
            if req.code in (AccountingResponse, AccessAccept, AccessReject,
                            CoANAK, CoAACK, DisconnectNAK, DisconnectACK):
                raise ServerPacketError('Invalid response packet %d' %
                                        req.code)

            elif self.server_type == ServerType.Auth:
                if req.code != AccessRequest:
                    raise ServerPacketError(
                        'Received non-auth packet on auth port')
                req = AuthPacket(secret=remote_host.secret,
                                 dict=self.server.dict,
                                 packet=data)
                if self.server.enable_pkt_verify:
                    if req.VerifyAuthRequest():
                        raise PacketError('Packet verification failed')

            elif self.server_type == ServerType.Coa:
                if req.code != DisconnectRequest and req.code != CoARequest:
                    raise ServerPacketError(
                        'Received non-coa packet on coa port')
                req = CoAPacket(secret=remote_host.secret,
                                dict=self.server.dict,
                                packet=data)
                if self.server.enable_pkt_verify:
                    if req.VerifyCoARequest():
                        raise PacketError('Packet verification failed')

            elif self.server_type == ServerType.Acct:

                if req.code != AccountingRequest:
                    raise ServerPacketError(
                        'Received non-acct packet on acct port')
                req = AcctPacket(secret=remote_host.secret,
                                 dict=self.server.dict,
                                 packet=data)
                if self.server.enable_pkt_verify:
                    if req.VerifyAcctRequest():
                        raise PacketError('Packet verification failed')

            # Call request callback
            self.request_callback(self, req, addr)
        except Exception as exc:
            if self.server.debug:
                self.logger.exception('[%s:%d] Error for packet from %s',
                                      self.ip, self.port, addr)
            else:
                self.logger.error('[%s:%d] Error for packet from %s: %s',
                                  self.ip, self.port, addr, exc)

        process_date = datetime.utcnow()
        self.logger.debug('[%s:%d] Request from %s processed in %d ms',
                          self.ip, self.port, addr,
                          (process_date - receive_date).microseconds / 1000)
Пример #19
0
    def datagram_received(self, data, addr):
        self.logger.debug('[%s:%d] Received %d bytes from %s', self.ip,
                          self.port, len(data), addr)

        receive_date = datetime.utcnow()

        remote_host = self.__get_remote_host__(addr[0])

        if remote_host:

            try:
                if self.server.debug:
                    self.logger.info('[%s:%d] Received from %s packet: %s.' %
                                     (self.ip, self.port, addr, data.hex()))
                req = Packet(packet=data, dict=self.server.dict)

            except Exception as exc:
                self.logger.error(
                    '[%s:%d] Error on decode packet: %s. Ignore it.' %
                    (self.ip, self.port, exc))
                req = None

            if not req:
                return

            try:
                if req.code in (AccountingResponse, AccessAccept, AccessReject,
                                CoANAK, CoAACK, DisconnectNAK, DisconnectACK):
                    raise ServerPacketError('Invalid response packet %d' %
                                            req.code)

                elif self.server_type == ServerType.Auth:

                    if req.code != AccessRequest:
                        raise ServerPacketError(
                            'Received not-authentication packet '
                            'on authentication port')
                    req = AuthPacket(secret=remote_host.secret,
                                     dict=self.server.dict,
                                     packet=data)

                    if self.server.enable_pkt_verify and \
                            req.message_authenticator and \
                        not req.verify_message_authenticator():
                        raise PacketError(
                            'Received invalid Message-Authenticator')

                elif self.server_type == ServerType.Coa:

                    if req.code != DisconnectRequest and \
                            req.code != CoARequest:
                        raise ServerPacketError(
                            'Received not-coa packet on coa port')
                    req = CoAPacket(secret=remote_host.secret,
                                    dict=self.server.dict,
                                    packet=data)
                    if self.server.enable_pkt_verify:
                        if not req.VerifyCoARequest():
                            raise PacketError('Packet verification failed')
                        if req.message_authenticator and \
                            not req.verify_message_authenticator():
                            raise PacketError(
                                'Received invalid Message-Authenticator')

                elif self.server_type == ServerType.Acct:

                    if req.code != AccountingRequest:
                        raise ServerPacketError(
                            'Received not-accounting packet on '
                            'accounting port')
                    req = AcctPacket(secret=remote_host.secret,
                                     dict=self.server.dict,
                                     packet=data)

                    if self.server.enable_pkt_verify:
                        if not req.VerifyAcctRequest():
                            raise PacketError('Packet verification failed')
                        if req.message_authenticator and not \
                            req.verify_message_authenticator():
                            raise PacketError(
                                'Received invalid Message-Authenticator')

                # Call request callback
                self.request_callback(self, req, addr)

                self.requests += 1

            except Exception as e:
                self.logger.error(
                    '[%s:%d] Unexpected error for packet from %s: %s' %
                    (self.ip, self.port, addr,
                     (e, '\n'.join(traceback.format_exc().splitlines())
                      )[self.server.debug]))

        else:
            self.logger.error('[%s:%d] Drop package from unknown source %s',
                              self.ip, self.port, addr)

        process_date = datetime.utcnow()
        self.logger.debug('[%s:%d] Request from %s processed in %d ms',
                          self.ip, self.port, addr,
                          (process_date - receive_date).microseconds / 1000)