Commit 41830b11 authored by jan.koester's avatar jan.koester
Browse files

test

parent 48543ab4
Loading
Loading
Loading
Loading
Loading
+1 −0
Changes for CMakeLists.txt: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ add_subdirectory(plugin/krb5)
add_subdirectory(plugin/ad)
add_subdirectory(plugin/dns)
add_subdirectory(plugin/oidc)
add_subdirectory(plugin/radius)
add_subdirectory(plugin/smb)
add_subdirectory(client)
add_subdirectory(cli)
+6 −0
Changes for plugin/radius/CMakeLists.txt: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
add_library(fenrirds-radius SHARED radiusd.cpp)
target_include_directories(fenrirds-radius PUBLIC ${JSONC_INCLUDE_DIR})
target_link_libraries(fenrirds-radius PUBLIC fenrirds-core uuidp::uuidp json-c::json-c netplus::netplus confplus::confplus)
set_target_properties(fenrirds-radius PROPERTIES OUTPUT_NAME "fenrirds-radius" VERSION ${version} SOVERSION 0)
install(TARGETS fenrirds-radius DESTINATION ${CMAKE_INSTALL_LIBDIR}/fenrirds)
install(FILES radiusd.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fenrirds)
+960 −0

File added.

Preview size limit exceeded, changes collapsed.

+139 −0
Changes for plugin/radius/radiusd.h: 139 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2026, Jan Koester jan.koester@tuxist.de
 * BSD license (see repository root).
 *******************************************************************************/
#pragma once

#include <atomic>
#include <condition_variable>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <vector>

#include <sys/socket.h>

#include <netplus/socket.h>
#include <netplus/crypto/tls.h>

#include "backend.h"
#include "plugin.h"
#include "radius/radius.h"

#ifdef Windows
#define VISIBILITY __declspec(dllexport)
#else
#define VISIBILITY __attribute__((visibility("default")))
#endif

namespace fenrirds {

    /***************************************************************************
     * RADIUS server (RFC 2865/2866/3579)
     *
     * Authenticates the users of the directory for switches, access points,
     * VPN gateways and captive portals:
     *     PAP, MS-CHAPv2 (with MPPE keys), EAP-PEAPv0/EAP-MSCHAPv2 and
     *     EAP-TTLS (PAP or MS-CHAPv2) for WPA-Enterprise / 802.1X,
     *     Status-Server, accounting.
     * The RADIUS clients (address, shared secret, allowed groups, VLAN per
     * group, groups as Filter-Id/Class) are RadiusObject records of a
     * domain, managed in the admin web interface (dirapi radius*); a
     * request is answered for the domain whose client matches its source.
     **************************************************************************/
    class VISIBILITY RadiusServer : public Plugin {
    public:
        RadiusServer(AuthBackend &adminBackend, const std::string &bindAddr, int authPort,
                     int acctPort, const std::string &cert, const std::string &key,
                     const std::string &serverName);
        ~RadiusServer() override;

        const char *name() const override { return "radius"; }
        void init() override;
        void run() override;
        void stop() override;

        struct Peer {
            sockaddr_storage addr{};
            socklen_t        len = 0;
            std::string      ip;
        };
        struct Session;
        struct User;

    private:
        struct Job {
            netplus::udp        *sock;
            Peer                 peer;
            std::vector<uint8_t> data;
        };

        void loop(netplus::udp *sock);
        void worker();
        void handle(netplus::udp *sock, const Peer &peer, const std::vector<uint8_t> &data);
        void send(netplus::udp *sock, const Peer &peer, const std::vector<uint8_t> &out);

        bool findNas(const std::string &ip, radius::Nas &nas, std::string &domain);

        radius::Bytes access(const radius::Packet &rq, const radius::Nas &nas, const std::string &dom);
        radius::Bytes accounting(const radius::Packet &rq, const radius::Nas &nas, const std::string &dom);
        radius::Bytes pap(const radius::Packet &rq, const radius::Nas &nas, const std::string &dom);
        radius::Bytes mschap(const radius::Packet &rq, const radius::Nas &nas, const std::string &dom);
        radius::Bytes eap(const radius::Packet &rq, const radius::Nas &nas, const std::string &dom);

        radius::Bytes accept(const radius::Packet &rq, const radius::Nas &nas, const User &u,
                             radius::Packet extra);
        radius::Bytes reject(const radius::Packet &rq, const radius::Nas &nas, const std::string &why,
                             radius::Packet extra = {});
        bool authorize(const radius::Nas &nas, const User &u, std::string &why) const;

        /* EAP */
        std::shared_ptr<Session> session(const radius::Bytes &state);
        std::shared_ptr<Session> newSession(const std::string &dom, const std::string &nas);
        void dropSession(const radius::Bytes &state);
        radius::Bytes challenge(const radius::Packet &rq, const radius::Nas &nas, Session &s,
                                const radius::Bytes &eapReq);
        radius::Bytes eapTls(const radius::Packet &rq, const radius::Nas &nas, Session &s,
                             const radius::Bytes &eapResp);
        radius::Bytes nextFragment(const radius::Packet &rq, const radius::Nas &nas, Session &s);
        radius::Bytes tunnel(const radius::Packet &rq, const radius::Nas &nas, Session &s,
                             const radius::Bytes &plain);
        radius::Bytes peapInner(const radius::Packet &rq, const radius::Nas &nas, Session &s,
                                const radius::Bytes &plain);
        radius::Bytes ttlsInner(const radius::Packet &rq, const radius::Nas &nas, Session &s,
                                const radius::Bytes &plain);
        radius::Bytes eapDone(const radius::Packet &rq, const radius::Nas &nas, Session &s, bool ok,
                              const std::string &why);

        AuthBackend &_AdminBackend;
        std::string  _BindAddr;
        int          _AuthPort, _AcctPort;
        std::string  _ServerName;
        std::shared_ptr<const std::map<std::string, netplus::tls::CertificateBundle>> _Certs;

        netplus::udp *_Auth = nullptr, *_Acct = nullptr;
        std::atomic<bool> _Running{true};
        std::thread _AcctThread;
        std::vector<std::thread> _Workers;
        std::mutex _JobMtx;
        std::condition_variable _JobCv;
        std::deque<Job> _Jobs;
        std::mutex _SendMtx;

        /* retransmissions get the same answer (and do not advance EAP) */
        struct Dup { int64_t t; std::vector<uint8_t> resp; };
        std::mutex _DupMtx;
        std::map<std::string, Dup> _Dups;

        std::mutex _SessMtx;
        std::map<radius::Bytes, std::shared_ptr<Session>> _Sessions;

        /* RADIUS clients per domain, reloaded when the domain changed */
        struct NasCache { uint64_t rev = 0; std::vector<radius::Nas> nas; };
        std::mutex _NasMtx;
        std::map<std::string, NasCache> _Nas;
    };
};
+1 −0
Changes for src/CMakeLists.txt: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ list(APPEND fenrirdsSrcs
    rpc/drsuapi.cpp
    rpc/srvsvc.cpp
    oauth/oauth.cpp
    radius/radius.cpp
    smb/smb2.cpp
)

Loading