The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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  */
25 RCSID("$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:
75  talloc_free(my);
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 
134 int 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
Definition: base.h:112
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
@ 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:1012
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:1323
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition: fd.h:62
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition: fd.h:79
char const * path
for Unix domain sockets
Definition: fd.h:94
char const * filename
for files
Definition: fd.h:100
int socket_type
SOCK_STREAM or SOCK_DGRAM.
Definition: fd.h:81
Configuration for sockets.
Definition: fd.h:78
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
Definition: merged_model.c:24
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:1195
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
fr_bio_t * fr_radius_server_bio_get_fd(fr_bio_packet_t *bio)
Definition: server.c:190
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_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
static int _radius_server_fd_bio_free(fr_radius_server_fd_bio_t *my)
Definition: server.c:48
fr_radius_server_bio_info_t const * fr_radius_server_bio_info(fr_bio_packet_t *bio)
Definition: server.c:197
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
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_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
fr_assert(0)
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