The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
server.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 3e9122ec7fde3776836b7ff86a6df49a007534fd $
19 *
20 * @file protocols/radius/server.c
21 * @brief Functions to support RADIUS bio handlers for server sockets
22 *
23 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
24 */
25RCSID("$Id: 3e9122ec7fde3776836b7ff86a6df49a007534fd $")
26
27#include <freeradius-devel/radius/server.h>
28#include <freeradius-devel/radius/server_udp.h>
29#include <freeradius-devel/radius/server_priv.h>
30
32{
33 fr_assert(fd_cfg->type == FR_BIO_FD_UNCONNECTED); /* UDP sockets only for now */
34
35 if (fd_cfg->path || fd_cfg->filename) {
36 fr_strerror_const("Domain sockets and files are not supported");
37 return NULL;
38 }
39
40 if (fd_cfg->socket_type == SOCK_DGRAM) return fr_radius_server_udp_bio_alloc(ctx, cfg, fd_cfg);
41
42 fr_strerror_const("No TCP for you.");
43 return NULL;
44
45// return fr_radius_server_tcp_bio_alloc(ctx, cfg, fd_cfg);
46}
47
49{
50 if (fr_bio_shutdown(my->common.bio) < 0) return -1;
51
52 if (fr_bio_free(my->common.bio) < 0) return -1;
53
54 return 0;
55}
56
57
59{
61
62 /*
63 * For now we only support unconnected UDP server sockets.
64 *
65 * Connected TCP server sockets require the ability to create new BIOs and add new sockets on the fly.
66 */
68
69 my = talloc_zero(ctx, fr_radius_server_fd_bio_t);
70 if (!my) return NULL;
71
72 my->fd = fr_bio_fd_alloc(my, fd_cfg, 0);
73 if (!my->fd) {
74 fail:
76 return NULL;
77 }
78
79 /*
80 * So that read / write pause / resume callbacks can find us
81 */
82 my->fd->uctx = my;
83
84 my->info.fd_info = fr_bio_fd_info(my->fd);
85 fr_assert(my->info.fd_info != NULL);
86
87 my->mem = fr_bio_mem_alloc(my, read_size, 2 * 4096, my->fd);
88 if (!my->mem) goto fail;
89 my->mem->uctx = &my->cfg.verify;
90
91 my->cfg = *cfg;
92
93 my->common.bio = my->mem;
94
95 talloc_set_destructor(my, _radius_server_fd_bio_free);
96
97 return my;
98}
99
101{
102 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
103 fr_packet_t *request = reply->uctx;
104 ssize_t slen;
105
106 fr_assert(!reply->data);
107
108 fr_assert(reply->code > 0);
110
111 /*
112 * Encode the packet.
113 */
114 if (fr_packet_encode(reply, list, request, (char const *) my->cfg.verify.secret) < 0) {
115 fail:
116 return fr_bio_error(GENERIC);
117 }
118
119 if (fr_packet_sign(reply, request, (char const *) my->cfg.verify.secret) < 0) goto fail;
120
121 slen = fr_bio_write(my->common.bio, &reply->socket, reply->data, reply->data_len);
122 if (slen < 0) {
123 fr_assert((slen != fr_bio_error(IO_WOULD_BLOCK)) || my->common.write_blocked);
124
125 return slen;
126 }
127
128 my->info.write_blocked = false;
129
130 return 0;
131}
132
133
134int fr_radius_server_fd_bio_read(fr_bio_packet_t *bio, UNUSED void **packet_ctx_p, fr_packet_t **packet_p,
135 TALLOC_CTX *out_ctx, fr_pair_list_t *out)
136{
137 ssize_t slen;
138 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
139 fr_packet_t *packet;
140
141 /*
142 * We don't need to set up response.socket for connected bios.
143 */
144 fr_packet_t base = {};
145
146 /*
147 * We read the response packet ctx into our local structure. If we have a real response, we will
148 * swap to using the request context, and not the response context.
149 */
150 slen = fr_bio_read(my->common.bio, &base, &my->buffer, sizeof(my->buffer));
151 if (!slen) return 0;
152
153 if (slen < 0) {
154 fr_assert(slen != fr_bio_error(IO_WOULD_BLOCK));
155 return slen;
156 }
157
158
159 /*
160 * Allocate the packet data structure
161 */
162 packet = fr_packet_alloc(out_ctx, false);
163 if (!packet) return -1;
164
165 packet->data = talloc_memdup(packet, my->buffer, slen);
166 if (!packet->data) {
167 talloc_free(packet);
168 return -1;
169 }
170 packet->data_len = slen;
171
172 packet->code = packet->data[0];
173 packet->id = packet->data[1];
174 memcpy(packet->vector, packet->data + 4, sizeof(packet->vector));
175
176 /*
177 * If this fails, we're out of memory.
178 */
179 if (fr_radius_decode_simple(packet, out, packet->data, packet->data_len,
180 NULL, (char const *) my->cfg.verify.secret) < 0) {
181 talloc_free(packet);
182 return -1;
183 }
184
185 *packet_p = packet;
186
187 return 1;
188}
189
191{
192 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
193
194 return my->fd;
195}
196
198{
199 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
200
201 return &my->info;
202}
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
Definition base.h:172
static ssize_t fr_bio_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read raw data from a bio.
Definition base.h:149
#define fr_bio_error(_x)
Definition base.h:192
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
@ FR_RADIUS_CODE_MAX
Maximum possible protocol code.
Definition defs.h:53
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
Definition fd.c:1018
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
Definition fd.c:1338
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition fd.h:65
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition fd.h:82
char const * path
for Unix domain sockets
Definition fd.h:99
char const * filename
for files
Definition fd.h:105
int socket_type
SOCK_STREAM or SOCK_DGRAM.
Definition fd.h:84
Configuration for sockets.
Definition fd.h:81
fr_bio_shutdown & my
Definition fd_errno.h:59
int fr_bio_free(fr_bio_t *bio)
Free this bio, and everything it calls.
Definition base.c:105
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition base.c:141
fr_bio_t * fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
Allocate a memory buffer bio.
Definition mem.c:727
talloc_free(reap)
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
long int ssize_t
ssize_t fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, uint8_t const *vector, char const *secret)
Simple wrapper for callers who just need a shared secret.
Definition base.c:1196
int fr_packet_sign(fr_packet_t *packet, fr_packet_t const *original, char const *secret)
Sign a previously encoded packet.
Definition packet.c:164
ssize_t fr_packet_encode(fr_packet_t *packet, fr_pair_list_t *list, fr_packet_t const *original, char const *secret)
Encode a packet.
Definition packet.c:52
#define fr_assert(_expr)
Definition rad_assert.h:38
int fr_radius_server_fd_bio_read(fr_bio_packet_t *bio, UNUSED void **packet_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out)
Definition server.c:134
fr_radius_server_fd_bio_t * fr_radius_server_fd_bio_alloc(TALLOC_CTX *ctx, size_t read_size, fr_radius_server_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Definition server.c:58
fr_bio_t * fr_radius_server_bio_get_fd(fr_bio_packet_t *bio)
Definition server.c:190
static int _radius_server_fd_bio_free(fr_radius_server_fd_bio_t *my)
Definition server.c:48
fr_bio_packet_t * fr_radius_server_bio_alloc(TALLOC_CTX *ctx, fr_radius_server_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Definition server.c:31
int fr_radius_server_fd_bio_write(fr_bio_packet_t *bio, UNUSED void *pctx, fr_packet_t *reply, fr_pair_list_t *list)
Definition server.c:100
fr_radius_server_bio_info_t const * fr_radius_server_bio_info(fr_bio_packet_t *bio)
Definition server.c:197
fr_bio_packet_t * fr_radius_server_udp_bio_alloc(TALLOC_CTX *ctx, fr_radius_server_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Allocate a RADIUS bio for receiving packets from clients.
Definition server_udp.c:107
void * uctx
Definition packet.h:79
unsigned int code
Packet code (type).
Definition packet.h:61
fr_socket_t socket
This packet was received on.
Definition packet.h:57
int id
Packet ID (used to link requests/responses).
Definition packet.h:60
uint8_t * data
Packet data (body).
Definition packet.h:63
size_t data_len
Length of packet data.
Definition packet.h:64
uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH]
RADIUS authentication vector.
Definition packet.h:69
#define fr_strerror_const(_msg)
Definition strerror.h:223
static size_t char ** out
Definition value.h:997