]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/radius/server.cpp
Radius (#9)
[stg.git] / projects / stargazer / plugins / other / radius / server.cpp
1 #include "server.h"
2 #include "radproto/packet_codes.h"
3 #include "stg/common.h"
4 #include <cstring>
5 #include <functional>
6
7 using STG::Server;
8 using boost::system::error_code;
9
10 Server::Server(boost::asio::io_service& io_service, const std::string& secret, uint16_t port, const std::string& filePath, std::stop_token token, PluginLogger& logger)
11     : m_radius(io_service, secret, port),
12       m_dictionaries(filePath),
13       m_token(std::move(token)),
14       m_logger(logger)
15 {
16     start();
17 }
18
19 void Server::start()
20 {
21     startReceive();
22 }
23
24 void Server::stop()
25 {
26     error_code ec;
27     m_radius.close(ec);
28 }
29
30 void Server::startReceive()
31 {
32     m_radius.asyncReceive([this](const auto& error, const auto& packet, const boost::asio::ip::udp::endpoint& source){ handleReceive(error, packet, source); });
33 }
34
35 RadProto::Packet Server::makeResponse(const RadProto::Packet& request)
36 {
37     std::vector<RadProto::Attribute*> attributes;
38     attributes.push_back(new RadProto::String(m_dictionaries.attributeCode("User-Name"), "test"));
39     attributes.push_back(new RadProto::Integer(m_dictionaries.attributeCode("NAS-Port"), 20));
40     std::array<uint8_t, 4> address {127, 104, 22, 17};
41     attributes.push_back(new RadProto::IpAddress(m_dictionaries.attributeCode("NAS-IP-Address"), address));
42     std::vector<uint8_t> bytes {'1', '2', '3', 'a', 'b', 'c'};
43     attributes.push_back(new RadProto::Bytes(m_dictionaries.attributeCode("Callback-Number"), bytes));
44     std::vector<uint8_t> chapPassword {'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
45     attributes.push_back(new RadProto::ChapPassword(m_dictionaries.attributeCode("CHAP-Password"), 1, chapPassword));
46
47     std::vector<RadProto::VendorSpecific> vendorSpecific;
48     std::vector<uint8_t> vendorValue {0, 0, 0, 3};
49     vendorSpecific.push_back(RadProto::VendorSpecific(m_dictionaries.vendorCode("Dlink"), m_dictionaries.vendorAttributeCode("Dlink", "Dlink-User-Level"), vendorValue));
50
51     if (request.type() == RadProto::ACCESS_REQUEST)
52         return RadProto::Packet(RadProto::ACCESS_ACCEPT, request.id(), request.auth(), attributes, vendorSpecific);
53
54     return RadProto::Packet(RadProto::ACCESS_REJECT, request.id(), request.auth(), attributes, vendorSpecific);
55 }
56
57 void Server::handleSend(const error_code& ec)
58 {
59     if (m_token.stop_requested())
60         return;
61
62     if (ec)
63     {
64         m_logger("Error asyncSend: %s", ec.message().c_str());
65         printfd(__FILE__, "Error asyncSend: '%s'\n", ec.message().c_str());
66     }
67     startReceive();
68 }
69
70 void Server::handleReceive(const error_code& error, const std::optional<RadProto::Packet>& packet, const boost::asio::ip::udp::endpoint& source)
71 {
72     if (m_token.stop_requested())
73         return;
74
75     if (error)
76     {
77         m_logger("Error asyncReceive: %s", error.message().c_str());
78         printfd(__FILE__, "Error asyncReceive: '%s'\n", error.message().c_str());
79     }
80
81     if (packet == std::nullopt)
82     {
83         m_logger("Error asyncReceive: the request packet is missing\n");
84         printfd(__FILE__, "Error asyncReceive: the request packet is missing\n");
85         return;
86     }
87     m_radius.asyncSend(makeResponse(*packet), source, [this](const auto& ec){ handleSend(ec); });
88 }