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: be8f6ff9855cd2b46c35c289c3ba1d08a304b33b $
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: be8f6ff9855cd2b46c35c289c3ba1d08a304b33b $")
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{
51
52 /*
53 * For now we only support unconnected UDP server sockets.
54 *
55 * Connected TCP server sockets require the ability to create new BIOs and add new sockets on the fly.
56 */
58
59 my = talloc_zero(ctx, fr_radius_server_fd_bio_t);
60 if (!my) return NULL;
61
62 my->fd = fr_bio_fd_alloc(my, fd_cfg, 0);
63 if (!my->fd) {
64 fail:
66 return NULL;
67 }
68
69 /*
70 * So that read / write pause / resume callbacks can find us
71 */
72 my->fd->uctx = my;
73
74 my->info.fd_info = fr_bio_fd_info(my->fd);
75 fr_assert(my->info.fd_info != NULL);
76
77 my->mem = fr_bio_mem_alloc(my, read_size, 2 * 4096, my->fd);
78 if (!my->mem) goto fail;
79 my->mem->uctx = &my->cfg.verify;
80
81 my->cfg = *cfg;
82
83 my->common.bio = my->mem;
84
85 return my;
86}
87
89{
90 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
91 fr_packet_t *request = reply->uctx;
92 ssize_t slen;
93
94 fr_assert(!reply->data);
95
96 fr_assert(reply->code > 0);
98
99 /*
100 * Encode the packet.
101 */
102 if (fr_packet_encode(reply, list, request, (char const *) my->cfg.verify.secret) < 0) {
103 fail:
104 return fr_bio_error(GENERIC);
105 }
106
107 if (fr_packet_sign(reply, request, (char const *) my->cfg.verify.secret) < 0) goto fail;
108
109 slen = fr_bio_write(my->common.bio, &reply->socket, reply->data, reply->data_len);
110 if (slen < 0) {
111 fr_assert((slen != fr_bio_error(IO_WOULD_BLOCK)) || my->common.write_blocked);
112
113 return slen;
114 }
115
116 my->info.write_blocked = false;
117
118 return 0;
119}
120
121
122int fr_radius_server_fd_bio_read(fr_bio_packet_t *bio, UNUSED void **packet_ctx_p, fr_packet_t **packet_p,
123 TALLOC_CTX *out_ctx, fr_pair_list_t *out)
124{
125 ssize_t slen;
126 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
127 fr_packet_t *packet;
128
129 /*
130 * We don't need to set up response.socket for connected bios.
131 */
132 fr_packet_t base = {};
133
134 /*
135 * We read the response packet ctx into our local structure. If we have a real response, we will
136 * swap to using the request context, and not the response context.
137 */
138 slen = fr_bio_read(my->common.bio, &base, &my->buffer, sizeof(my->buffer));
139 if (!slen) return 0;
140
141 if (slen < 0) {
142 fr_assert(slen != fr_bio_error(IO_WOULD_BLOCK));
143 return slen;
144 }
145
146
147 /*
148 * Allocate the packet data structure
149 */
150 packet = fr_packet_alloc(out_ctx, false);
151 if (!packet) return -1;
152
153 packet->data = talloc_memdup(packet, my->buffer, slen);
154 if (!packet->data) {
155 talloc_free(packet);
156 return -1;
157 }
158 packet->data_len = slen;
159
160 packet->code = packet->data[0];
161 packet->id = packet->data[1];
162 memcpy(packet->vector, packet->data + 4, sizeof(packet->vector));
163
164 /*
165 * If this fails, we're out of memory.
166 */
167 if (fr_radius_decode_simple(packet, out, packet->data, packet->data_len,
168 NULL, (char const *) my->cfg.verify.secret) < 0) {
169 talloc_free(packet);
170 return -1;
171 }
172
173 *packet_p = packet;
174
175 return 1;
176}
177
179{
180 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
181
182 return my->fd;
183}
184
186{
187 fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_server_fd_bio_t);
188
189 return &my->info;
190}
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:184
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:161
#define fr_bio_error(_x)
Definition base.h:200
#define RCSID(id)
Definition build.h:485
#define UNUSED
Definition build.h:317
@ 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:968
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:1284
@ 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:81
char const * path
for Unix domain sockets
Definition fd.h:102
char const * filename
for files
Definition fd.h:108
int socket_type
SOCK_STREAM or SOCK_DGRAM.
Definition fd.h:83
Configuration for sockets.
Definition fd.h:80
void fr_bio_shutdown & my
Definition fd_errno.h:70
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:723
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:1213
int fr_packet_sign(fr_packet_t *packet, fr_packet_t const *original, char const *secret)
Sign a previously encoded packet.
Definition packet.c:155
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:43
#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:122
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:48
fr_bio_t * fr_radius_server_bio_get_fd(fr_bio_packet_t *bio)
Definition server.c:178
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:88
fr_radius_server_bio_info_t const * fr_radius_server_bio_info(fr_bio_packet_t *bio)
Definition server.c:185
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:1023