]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/radius/config.cpp
Sending attributes from <auth>/send section. (#13)
[stg.git] / projects / stargazer / plugins / other / radius / config.cpp
1 #include "config.h"
2 #include "radproto/error.h"
3 #include "stg/common.h"
4 #include <boost/tokenizer.hpp>
5 #include <boost/algorithm/string.hpp>
6
7 #include <vector>
8 #include <utility>
9 #include <iterator>
10 #include <algorithm>
11 #include <iostream>
12
13 using STG::Config;
14 using AttrValue = Config::AttrValue;
15 using ASection = Config::ASection;
16
17 namespace
18 {
19     std::string ShowRules(const std::vector<std::pair<std::string, AttrValue>>& rules)
20     {
21         std::string result;
22         for (const auto& at : rules)
23         {
24             if (!result.empty())
25                 result += ", ";
26
27             if (at.second.type == AttrValue::Type::PARAM_NAME)
28                 result.append(at.first + " = " + at.second.value);
29             else
30                 result.append(at.first + " = '" + at.second.value + "'");
31         }
32         return result;
33     }
34 }
35
36 std::vector<std::pair<std::string, AttrValue>> Config::ParseRules(const std::string& value, const std::string& paramName)
37 {
38     using tokenizer = boost::tokenizer<boost::char_separator<char>>;
39     const boost::char_separator<char> sep(",");
40
41     const tokenizer tokens(value, sep);
42
43     std::vector<std::pair<std::string, AttrValue>> res;
44
45     for (const auto& token : tokens)
46     {
47         std::vector<std::string> keyValue;
48
49         split(keyValue, boost::algorithm::trim_copy_if(token, boost::is_any_of(" \t")), boost::is_any_of(" ="), boost::token_compress_on);
50
51         if (keyValue.size() != 2)
52         {
53             m_logger("The '%s' attribute specification has an incorrect format: '%s'.", paramName.c_str(),  token.c_str());
54             printfd(__FILE__, "The '%s' attribute specification has an incorrect format: '%s'.", paramName.c_str(), token.c_str());
55             return {};
56         }
57
58         auto type = AttrValue::Type::PARAM_NAME;
59         std::string valueName = keyValue[1];
60         if (valueName.front() == '\'' && valueName.back() == '\'')
61         {
62             type = AttrValue::Type::VALUE;
63             valueName.erase(0, 1);
64             valueName.erase(valueName.length() - 1, 1);
65         }
66         else if ((valueName.front() == '\'' && valueName.back() != '\'') || (valueName.front() != '\'' && valueName.back() == '\''))
67         {
68             m_logger("Error ParseRules: '%s' attribute parameter value is invalid.\n", paramName.c_str());
69             printfd(__FILE__, "Error ParseRules: '%s' attribute parameter value is invalid.\n", paramName.c_str());
70             return {};
71         }
72         res.emplace_back(keyValue[0], AttrValue{valueName, type});
73     }
74     return res;
75 }
76
77 ASection Config::parseASection(const std::vector<ParamValue>& conf)
78 {
79     ASection res;
80     const auto mit = std::find(conf.begin(), conf.end(), ParamValue("match", {}));
81     if (mit != conf.end())
82         res.match = ParseRules(mit->value[0], mit->param);
83
84     const auto sit = std::find(conf.begin(), conf.end(), ParamValue("send", {}));
85     if (sit != conf.end())
86         res.send = ParseRules(sit->value[0], sit->param);
87
88     return res;
89 }
90
91 Config::Config()
92     : m_port(1812),
93       m_dictionaries("/usr/share/freeradius/dictionary"),
94       m_logger(PluginLogger::get("radius"))
95 {}
96
97 int Config::ParseSettings(const ModuleSettings & s)
98 {
99     ParamValue pv;
100     int p;
101
102     pv.param = "Port";
103     auto pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
104     if (pvi != s.moduleParams.end() && !pvi->value.empty())
105     {
106         if (ParseIntInRange(pvi->value[0], 2, 65535, &p) != 0)
107         {
108             m_errorStr = "Cannot parse parameter \'Port\': " + m_errorStr;
109             printfd(__FILE__, "Cannot parse parameter 'Port'\n");
110             return -1;
111         }
112         m_port = static_cast<uint16_t>(p);
113     }
114
115     pv.param = "Secret";
116     pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
117     if (pvi == s.moduleParams.end() || pvi->value.empty())
118     {
119         m_errorStr = "Parameter \'Secret\' not found.";
120         printfd(__FILE__, "Parameter 'Secret' not found\n");
121         return -1;
122     }
123     else
124         m_secret = pvi->value[0];
125
126     pv.param = "Dictionaries";
127     pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
128     if (pvi != s.moduleParams.end() && !pvi->value.empty())
129         m_dictionaries = pvi->value[0];
130
131     const auto authIt = std::find(s.moduleParams.begin(), s.moduleParams.end(), ParamValue("auth", {}));
132     if (authIt != s.moduleParams.end())
133         m_auth = parseASection(authIt->sections);
134
135     const auto autzIt = std::find(s.moduleParams.begin(), s.moduleParams.end(), ParamValue("autz", {}));
136     if (autzIt != s.moduleParams.end())
137         m_autz = parseASection(autzIt->sections);
138
139     printfd(__FILE__, " auth.match = \"%s\"\n", ShowRules(m_auth.match).c_str());
140     printfd(__FILE__, " auth.send = \"%s\"\n", ShowRules(m_auth.send).c_str());
141     printfd(__FILE__, " autz.match = \"%s\"\n", ShowRules(m_autz.match).c_str());
142     printfd(__FILE__, " autz.send = \"%s\"\n", ShowRules(m_autz.send).c_str());
143
144     return 0;
145 }
146