/src/kea/src/hooks/dhcp/radius/radius_request.cc
Line | Count | Source |
1 | | // Copyright (C) 2020-2025 Internet Systems Consortium, Inc. ("ISC") |
2 | | // |
3 | | // This Source Code Form is subject to the terms of the Mozilla Public |
4 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
6 | | |
7 | | #include <config.h> |
8 | | |
9 | | #include <radius_request.h> |
10 | | #include <radius_access.h> |
11 | | #include <radius_accounting.h> |
12 | | #include <radius_log.h> |
13 | | #include <sstream> |
14 | | |
15 | | using namespace isc::asiolink; |
16 | | using namespace isc::dhcp; |
17 | | using namespace isc::radius; |
18 | | using namespace std; |
19 | | namespace ph = std::placeholders; |
20 | | |
21 | | namespace isc { |
22 | | namespace radius { |
23 | | |
24 | 0 | uint32_t getNASPort(uint32_t subnet_id) { |
25 | 0 | const map<uint32_t, uint32_t>& remap = RadiusImpl::instance().remap_; |
26 | 0 | auto const by_id = remap.find(subnet_id); |
27 | 0 | if (by_id != remap.end()) { |
28 | 0 | return (by_id->second); |
29 | 0 | } |
30 | 0 | auto const by_id0 = remap.find(SUBNET_ID_DEFAULT); |
31 | 0 | if (by_id0 != remap.end()) { |
32 | 0 | return (by_id0->second); |
33 | 0 | } |
34 | 0 | return (subnet_id); |
35 | 0 | } |
36 | | |
37 | | RadiusRequest::RadiusRequest(const MsgCode code, |
38 | | uint32_t subnet_id, |
39 | | const AttributesPtr& send_attrs, |
40 | | bool sync, |
41 | 0 | const Exchange::Handler& handler) { |
42 | 0 | AttributesPtr attrs; |
43 | 0 | if (send_attrs) { |
44 | 0 | attrs.reset(new Attributes(*send_attrs)); |
45 | 0 | } else { |
46 | 0 | attrs.reset(new Attributes()); |
47 | 0 | } |
48 | 0 | nas_port_ = getNASPort(subnet_id); |
49 | 0 | if (!attrs->get(PW_NAS_PORT)) { |
50 | 0 | attrs->add(Attribute::fromInt(PW_NAS_PORT, nas_port_)); |
51 | 0 | } |
52 | 0 | MessagePtr request(new Message(code, 0, vector<uint8_t>(), |
53 | 0 | "to-be-set", attrs)); |
54 | 0 | unsigned maxretries = RadiusImpl::instance().retries_; |
55 | 0 | Servers servers; |
56 | 0 | if (code == PW_ACCESS_REQUEST) { |
57 | 0 | servers = RadiusImpl::instance().auth_->servers_; |
58 | 0 | } else { |
59 | 0 | servers = RadiusImpl::instance().acct_->servers_; |
60 | 0 | } |
61 | 0 | if (sync) { |
62 | 0 | exchange_.reset(new Exchange(request, maxretries, servers)); |
63 | 0 | } else { |
64 | 0 | exchange_.reset(new Exchange(RadiusImpl::instance().getIOContext(), |
65 | 0 | request, maxretries, servers, |
66 | 0 | handler)); |
67 | 0 | } |
68 | 0 | } |
69 | | |
70 | | void |
71 | 0 | RadiusSyncAuth::start() { |
72 | 0 | AttributesPtr send_attrs; |
73 | 0 | MessagePtr request = exchange_->getRequest(); |
74 | 0 | if (request) { |
75 | 0 | send_attrs = request->getAttributes(); |
76 | 0 | } |
77 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, RADIUS_AUTHENTICATION_SYNC) |
78 | 0 | .arg(nas_port_) |
79 | 0 | .arg(send_attrs ? send_attrs->toText() : "no attributes"); |
80 | |
|
81 | 0 | RadiusRequest::start(); |
82 | |
|
83 | 0 | int result = getRC(); |
84 | 0 | AttributesPtr recv_attrs = getRespAttrs(); |
85 | 0 | if (result == OK_RC) { |
86 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
87 | 0 | RADIUS_AUTHENTICATION_SYNC_ACCEPTED) |
88 | 0 | .arg(recv_attrs ? recv_attrs->toText() : "no attributes"); |
89 | 0 | } else if (result == REJECT_RC) { |
90 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
91 | 0 | RADIUS_AUTHENTICATION_SYNC_REJECTED) |
92 | 0 | .arg(recv_attrs ? recv_attrs->toText() : "no attributes"); |
93 | 0 | } else { |
94 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
95 | 0 | RADIUS_AUTHENTICATION_SYNC_FAILED) |
96 | 0 | .arg(result) |
97 | 0 | .arg(exchangeRCtoText(result)); |
98 | 0 | } |
99 | |
|
100 | 0 | if (callback_) { |
101 | 0 | try { |
102 | 0 | callback_(result, recv_attrs); |
103 | 0 | } catch (...) { |
104 | 0 | } |
105 | 0 | } |
106 | 0 | exchange_->shutdown(); |
107 | 0 | } |
108 | | |
109 | | RadiusAsyncAuth::RadiusAsyncAuth(uint32_t subnet_id, |
110 | | const AttributesPtr& send_attrs, |
111 | | const CallbackAuth& callback) |
112 | 0 | : RadiusAuth(subnet_id, send_attrs, false, |
113 | 0 | std::bind(&RadiusAsyncAuth::invokeCallback, |
114 | 0 | callback, ph::_1)) { |
115 | 0 | } |
116 | | |
117 | | void |
118 | 0 | RadiusAsyncAuth::start() { |
119 | 0 | AttributesPtr send_attrs; |
120 | 0 | MessagePtr request = exchange_->getRequest(); |
121 | 0 | if (request) { |
122 | 0 | send_attrs = request->getAttributes(); |
123 | 0 | } |
124 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, RADIUS_AUTHENTICATION_ASYNC) |
125 | 0 | .arg(nas_port_) |
126 | 0 | .arg(send_attrs ? send_attrs->toText() : "no attributes"); |
127 | |
|
128 | 0 | RadiusRequest::start(); |
129 | 0 | } |
130 | | |
131 | | void |
132 | | RadiusAsyncAuth::invokeCallback(const CallbackAuth& callback, |
133 | 0 | const ExchangePtr exchange) { |
134 | 0 | int result = ERROR_RC; |
135 | 0 | AttributesPtr recv_attrs; |
136 | 0 | if (exchange) { |
137 | 0 | result = exchange->getRC(); |
138 | 0 | MessagePtr response = exchange->getResponse(); |
139 | 0 | if (response) { |
140 | 0 | recv_attrs = response->getAttributes(); |
141 | 0 | } |
142 | 0 | } |
143 | 0 | if (result == OK_RC) { |
144 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
145 | 0 | RADIUS_AUTHENTICATION_ASYNC_ACCEPTED) |
146 | 0 | .arg(recv_attrs ? recv_attrs->toText() : "no attributes"); |
147 | 0 | } else if (result == REJECT_RC) { |
148 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
149 | 0 | RADIUS_AUTHENTICATION_ASYNC_REJECTED) |
150 | 0 | .arg(recv_attrs ? recv_attrs->toText() : "no attributes"); |
151 | 0 | } else { |
152 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
153 | 0 | RADIUS_AUTHENTICATION_ASYNC_FAILED) |
154 | 0 | .arg(result) |
155 | 0 | .arg(exchangeRCtoText(result)); |
156 | 0 | } |
157 | |
|
158 | 0 | if (callback) { |
159 | 0 | try { |
160 | 0 | callback(result, recv_attrs); |
161 | 0 | } catch (...) { |
162 | 0 | } |
163 | 0 | } |
164 | 0 | exchange->shutdown(); |
165 | 0 | RadiusImpl::instance().unregisterExchange(exchange); |
166 | 0 | } |
167 | | |
168 | | void |
169 | 0 | RadiusSyncAcct::start() { |
170 | 0 | AttributesPtr send_attrs; |
171 | 0 | MessagePtr request = exchange_->getRequest(); |
172 | 0 | if (request) { |
173 | 0 | send_attrs = request->getAttributes(); |
174 | 0 | } |
175 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, RADIUS_ACCOUNTING_SYNC) |
176 | 0 | .arg(nas_port_) |
177 | 0 | .arg(send_attrs ? send_attrs->toText() : "no attributes"); |
178 | |
|
179 | 0 | RadiusRequest::start(); |
180 | |
|
181 | 0 | int result = getRC(); |
182 | 0 | if (result == OK_RC) { |
183 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
184 | 0 | RADIUS_ACCOUNTING_SYNC_SUCCEED); |
185 | 0 | } else { |
186 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
187 | 0 | RADIUS_ACCOUNTING_SYNC_FAILED) |
188 | 0 | .arg(result) |
189 | 0 | .arg(exchangeRCtoText(result)); |
190 | 0 | } |
191 | |
|
192 | 0 | if (callback_) { |
193 | 0 | try { |
194 | 0 | callback_(result); |
195 | 0 | } catch (...) { |
196 | 0 | } |
197 | 0 | } |
198 | 0 | exchange_->shutdown(); |
199 | 0 | } |
200 | | |
201 | | RadiusAsyncAcct::RadiusAsyncAcct(uint32_t subnet_id, |
202 | | const AttributesPtr& send_attrs, |
203 | | const CallbackAcct& callback) |
204 | 0 | : RadiusAcct(subnet_id, send_attrs, false, |
205 | 0 | std::bind(&RadiusAsyncAcct::invokeCallback, |
206 | 0 | callback, ph::_1)) { |
207 | 0 | } |
208 | | |
209 | | void |
210 | 0 | RadiusAsyncAcct::start() { |
211 | 0 | AttributesPtr send_attrs; |
212 | 0 | MessagePtr request = exchange_->getRequest(); |
213 | 0 | if (request) { |
214 | 0 | send_attrs = request->getAttributes(); |
215 | 0 | } |
216 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, RADIUS_ACCOUNTING_ASYNC) |
217 | 0 | .arg(nas_port_) |
218 | 0 | .arg(send_attrs ? send_attrs->toText() : "no attributes"); |
219 | |
|
220 | 0 | RadiusRequest::start(); |
221 | 0 | } |
222 | | |
223 | | void |
224 | | RadiusAsyncAcct::invokeCallback(const CallbackAcct& callback, |
225 | 0 | const ExchangePtr exchange) { |
226 | 0 | int result = ERROR_RC; |
227 | 0 | if (exchange) { |
228 | 0 | result = exchange->getRC(); |
229 | 0 | } |
230 | 0 | if (result == OK_RC) { |
231 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
232 | 0 | RADIUS_ACCOUNTING_ASYNC_SUCCEED); |
233 | 0 | } else { |
234 | 0 | LOG_DEBUG(radius_logger, RADIUS_DBG_TRACE, |
235 | 0 | RADIUS_ACCOUNTING_ASYNC_FAILED) |
236 | 0 | .arg(result) |
237 | 0 | .arg(exchangeRCtoText(result)); |
238 | 0 | } |
239 | |
|
240 | 0 | if (callback) { |
241 | 0 | try { |
242 | 0 | callback(result); |
243 | 0 | } catch (...) { |
244 | 0 | } |
245 | 0 | } |
246 | 0 | exchange->shutdown(); |
247 | 0 | RadiusImpl::instance().unregisterExchange(exchange); |
248 | 0 | } |
249 | | |
250 | | } // end of namespace radius |
251 | | } // end of namespace isc |