2 #include "radproto/packet_codes.h"
3 #include "radproto/attribute_types.h"
6 #include "stg/common.h"
9 #include <cstdint> //uint8_t, uint32_t
12 using boost::system::error_code;
14 Server::Server(boost::asio::io_context& io_context, const std::string& secret, uint16_t port, const std::string& filePath, std::stop_token token, PluginLogger& logger, Users* users)
15 : m_radius(io_context, secret, port),
16 m_dictionaries(filePath),
18 m_token(std::move(token)),
35 void Server::startReceive()
37 m_radius.asyncReceive([this](const auto& error, const auto& packet, const boost::asio::ip::udp::endpoint& source){ handleReceive(error, packet, source); });
40 RadProto::Packet Server::makeResponse(const RadProto::Packet& request)
42 std::vector<RadProto::Attribute*> attributes;
43 attributes.push_back(new RadProto::String(m_dictionaries.attributeCode("User-Name"), "test"));
44 attributes.push_back(new RadProto::Integer(m_dictionaries.attributeCode("NAS-Port"), 20));
45 std::array<uint8_t, 4> address {127, 104, 22, 17};
46 attributes.push_back(new RadProto::IpAddress(m_dictionaries.attributeCode("NAS-IP-Address"), address));
47 std::vector<uint8_t> bytes {'1', '2', '3', 'a', 'b', 'c'};
48 attributes.push_back(new RadProto::Bytes(m_dictionaries.attributeCode("Callback-Number"), bytes));
49 std::vector<uint8_t> chapPassword {'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
50 attributes.push_back(new RadProto::ChapPassword(m_dictionaries.attributeCode("CHAP-Password"), 1, chapPassword));
52 std::vector<RadProto::VendorSpecific> vendorSpecific;
53 std::vector<uint8_t> vendorValue {0, 0, 0, 3};
54 vendorSpecific.push_back(RadProto::VendorSpecific(m_dictionaries.vendorCode("Dlink"), m_dictionaries.vendorAttributeCode("Dlink", "Dlink-User-Level"), vendorValue));
56 if (request.type() != RadProto::ACCESS_REQUEST)
57 return RadProto::Packet(RadProto::ACCESS_REJECT, request.id(), request.auth(), {}, {});
59 if (findUser(request))
60 return RadProto::Packet(RadProto::ACCESS_ACCEPT, request.id(), request.auth(), attributes, vendorSpecific);
62 printfd(__FILE__, "Error findUser\n");
63 return RadProto::Packet(RadProto::ACCESS_REJECT, request.id(), request.auth(), {}, {});
66 void Server::handleSend(const error_code& ec)
68 if (m_token.stop_requested())
73 m_logger("Error asyncSend: %s", ec.message().c_str());
74 printfd(__FILE__, "Error asyncSend: '%s'\n", ec.message().c_str());
79 void Server::handleReceive(const error_code& error, const std::optional<RadProto::Packet>& packet, const boost::asio::ip::udp::endpoint& source)
81 if (m_token.stop_requested())
86 m_logger("Error asyncReceive: %s", error.message().c_str());
87 printfd(__FILE__, "Error asyncReceive: '%s'\n", error.message().c_str());
90 if (packet == std::nullopt)
92 m_logger("Error asyncReceive: the request packet is missing\n");
93 printfd(__FILE__, "Error asyncReceive: the request packet is missing\n");
97 m_radius.asyncSend(makeResponse(*packet), source, [this](const auto& ec){ handleSend(ec); });
100 bool Server::findUser(const RadProto::Packet& packet)
103 std::string password;
104 for (const auto& attribute : packet.attributes())
106 if (attribute->type() == RadProto::USER_NAME)
107 login = attribute->toString();
109 if (attribute->type() == RadProto::USER_PASSWORD)
110 password = attribute->toString();
113 User* user = nullptr;
114 if (m_users->FindByName(login, &user))
116 m_logger("User '%s' not found.", login.c_str());
117 printfd(__FILE__, "User '%s' NOT found!\n", login.c_str());
121 printfd(__FILE__, "User '%s' FOUND!\n", user->GetLogin().c_str());
123 if (password != user->GetProperties().password.Get())
125 m_logger("User's password is incorrect. %s", password.c_str());
126 printfd(__FILE__, "User's password is incorrect.\n", password.c_str());