Coverage Report

Created: 2025-12-31 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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