Beispiel #1
0
    def authenticate(self,
                     username,
                     password,
                     client_ip,
                     pass_through_attrs=None):
        if pass_through_attrs is None:
            pass_through_attrs = {}
        id = yield self.id_list.request()
        request_packet = packet.AuthPacket(code=packet.AccessRequest,
                                           id=id,
                                           secret=self.secret.encode(),
                                           dict=base.radius_dictionary())
        request_packet['NAS-IP-Address'] = self.nas_ip
        add_packet_attributes(packet=request_packet, attrs=pass_through_attrs)
        request = ClientRequest(request_packet, self.pw_codec)
        request.username = username
        if password is not None:
            request.password = password
        if client_ip:
            request.client_ip = client_ip

        log.msg('Sending request for user %r to %r with id %r' %
                (username, self.addrs[0], id))

        # Send request; wait for response
        self.requests[id] = request
        self._send_request(request)
        response_packet = yield request.deferred
        defer.returnValue(response_packet)
Beispiel #2
0
    def _create_request(self, radius_attrs: Dict[str, Any]):
        """
        Creates a fake request packet used to generate a fake response

        Args:
            radius_attrs: The attributes to add to the created request

        Returns:
            packet.AuthPacket
        """
        request_id = yield self.id_list.request()
        request_packet = packet.AuthPacket(
            code=packet.AccessRequest,
            id=request_id,
            secret=self.secret.encode(),
            dict=base.radius_dictionary(),
        )
        add_packet_attributes(packet=request_packet, attrs=radius_attrs)

        # Turn the request packet into bytes for the wire even though we're not
        # sending it anywhere because that's when the authenticator gets
        # generated and set
        request_packet.RequestPacket()

        defer.returnValue(request_packet)
Beispiel #3
0
def parse_client_ip_attribute(config_dict):
    """
    Configures which RADIUS attribute is used to read the client's IP address.
    """
    attributes_map = {
        "paloalto": "PaloAlto-Client-Source-IP",
        "default": "Calling-Station-Id",
    }
    client_ip_attr = config_dict.get_str("client_ip_attr", "default")
    client_ip_attr = attributes_map.get(client_ip_attr, client_ip_attr)

    if client_ip_attr not in base.radius_dictionary():
        raise ConfigError(
            "Invalid configuration value for client_ip_attr: RADIUS attribute {0} unkonwn."
            .format(client_ip_attr))
    return client_ip_attr
Beispiel #4
0
def parse_client_ip_attribute(config_dict):
    """
    Configures which RADIUS attribute is used to read the client's IP address.
    """
    attributes_map = {
        'paloalto': 'PaloAlto-Client-Source-IP',
        'default': 'Calling-Station-Id'
    }
    client_ip_attr = config_dict.get_str('client_ip_attr', 'default')
    client_ip_attr = attributes_map.get(client_ip_attr, client_ip_attr)

    if client_ip_attr not in base.radius_dictionary():
        raise ConfigError(
            'Invalid configuration value for client_ip_attr: RADIUS attribute {0} unkonwn.'
            .format(client_ip_attr))
    return client_ip_attr
def _connect_radius(host, port, config, toolbox):
    """Spin up test client and send a Status-Server packet to check if we can reach the radius server"""
    secret = config.get_protected_str('secret_protected', 'secret').encode()
    client = Client(server=host,
                    authport=port,
                    secret=secret,
                    dict=base.radius_dictionary())
    client.timeout = const.DEFAULT_RADIUS_RETRY_WAIT

    request = client.CreateAuthPacket(code=pyrad.packet.StatusServer)

    # The request must contain a message authenticator.
    request.add_message_authenticator()

    try:
        nas_ip = config.get_str('nas_ip')
    except ConfigError:
        nas_ip = util.get_authproxy_ip()
    request.AddAttribute('NAS-IP-Address', nas_ip)

    return toolbox.test_connect_radius(client, request)
Beispiel #6
0
    def handle_response(self, datagram, source):
        response_packet = packet.AuthPacket(packet=datagram,
                                            dict=base.radius_dictionary())
        response_packet.source = source

        # make sure it's from the correct host (or properly ip-spoofed :)
        if (source[0], int(source[1])) not in self.addrs:
            raise packet.PacketError(
                'response packet from unknown address: %s:%s' % source, )

        # look up id
        try:
            request = self.requests[response_packet.id]
        except KeyError:
            raise packet.PacketError('unrecognized id in response packet: %s' %
                                     response_packet.id)

        # verify reply authentication
        if not request.packet.VerifyReply(response_packet, datagram):
            raise packet.PacketError(
                'response packet has invalid authenticator')
        response_packet.secret = self.secret.encode()
        # Validate Message-Authenticator, if any
        if response_packet.message_authenticator:
            if not response_packet.verify_message_authenticator(
                    original_authenticator=request.packet.authenticator):
                raise packet.PacketError(
                    'Invalid Message-Authenticator from {0}'.format(source[0]))
        response_packet.authenticator = request.packet.authenticator

        # clear request state
        self._request_done(request)

        log.msg(
            'Got response for id %r from %r; code %r' %
            (response_packet.id, response_packet.source, response_packet.code))

        # callback
        request.deferred.callback(response_packet)
Beispiel #7
0
    def _handle_request(self, datagram, host_port):
        host, port = host_port
        request_pkt = packet.AuthPacket(packet=datagram,
                                        dict=base.radius_dictionary())
        request_pkt.source = (host, port)

        # make sure it's an AccessRequest
        if request_pkt.code != packet.AccessRequest:
            raise packet.PacketError("non-AccessRequest packet received")

        # lookup secret
        secret_for_host = self.secret_for_host(host)
        if secret_for_host is not None:
            request_pkt.secret = secret_for_host.encode()
        else:
            raise packet.PacketError("Unknown Client: %s" % host)

        # Validate Message-Authenticator, if any
        if request_pkt.message_authenticator:
            if not request_pkt.verify_message_authenticator():
                raise packet.PacketError(
                    "Invalid Message-Authenticator from {0}".format(host))

        # check to see if it's a resend (i.e. client retry)
        old_request = self.requests.get((request_pkt.source, request_pkt.id))
        if old_request:
            old_request_pkt = old_request.packet
            if _match_request_packets(request_pkt, old_request_pkt):
                # enough things (src, id, authenticator, username,
                # password) match that it's probably safe to assume
                # it's a resend. so send our result back (if we have
                # one); otherwise ignore
                self.log_request(old_request, "Received duplicate request")
                self._resend_response(old_request)
                defer.returnValue(old_request)
            else:
                self._cleanup_request(old_request)

        # create request state
        log.msg("Received new request id %r from %r" %
                (request_pkt.id, request_pkt.source))
        request = _ProxyRequest(request_pkt, self.pw_codec,
                                self.client_ip_attr)
        self.requests[(request.source, request.id)] = request

        try:
            # Check if password property can decrypt using the current secret.
            if self._can_decode_password(request):
                # authenticate the user
                request.response = yield self._get_response(request)
            else:
                self.log_request(
                    request,
                    "Cannot decode password using the configured"
                    " radius_secret. Please ensure the client and"
                    " Authentication Proxy use the same shared"
                    " secret.",
                )
                msg = "Cannot decode password"
                log.auth_standard(
                    msg=msg,
                    username=request.username,
                    auth_stage=log.AUTH_UNKNOWN,
                    status=log.AUTH_ERROR,
                    server_section=self.server_section_name,
                    client_ip=request.client_ip,
                    server_section_ikey=self.server_section_ikey,
                )
                response = self.create_reject_packet(request, msg)
                request.response = response.ReplyPacket()

            self._send_response(request)
            defer.returnValue(request)
        except Exception as e:
            # Something went wrong. Clean up the request and raise.
            self._cleanup_request(request)
            raise e