]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
added radius_server_udp
authorAlan T. DeKok <aland@freeradius.org>
Wed, 3 May 2017 18:57:36 +0000 (14:57 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 3 May 2017 18:58:03 +0000 (14:58 -0400)
in src/lib/io for now, until we go clean up the rest of the code

src/lib/io/all.mk
src/lib/io/radius_server_udp.c [new file with mode: 0644]
src/protocols/radius/radius.h [new file with mode: 0644]

index 4d986c6b5e4726afa351a1727c2f4f32268530b8..d8720620063862c47f4d586a8cb494a952d42546 100644 (file)
@@ -1,7 +1,7 @@
 TARGET := libfreeradius-io.a
 
 SOURCES        :=      ring_buffer.c message.c atomic_queue.c queue.c time.c channel.c track.c worker.c \
-               schedule.c network.c control.c
+               schedule.c network.c control.c radius_server_udp.c
 
 TGT_PREREQS    := libfreeradius-util.la
 TGT_LDLIBS     := $(LIBS)
diff --git a/src/lib/io/radius_server_udp.c b/src/lib/io/radius_server_udp.c
new file mode 100644 (file)
index 0000000..98bd6a6
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @brief RADIUS Server UDP front-end
+ * @file io/radius_server_udp.c
+ *
+ * @copyright 2017 Alan DeKok <aland@freeradius.org>
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/io/transport.h>
+#include <freeradius-devel/md5.h>
+#include <freeradius-devel/radius.h>
+#include <freeradius-devel/token.h>
+#include <freeradius-devel/inet.h>
+#include <freeradius-devel/radius/radius.h>
+#include <freeradius-devel/rad_assert.h>
+
+#ifndef RDEBUG
+#define RDEBUG(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
+#endif
+
+#ifndef DEBUG
+#define DEBUG(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
+#endif
+
+typedef struct fr_packet_ctx_t {
+       int             sockfd;
+
+       uint8_t const   *secret;
+       size_t          secret_len;
+
+       uint8_t         original[20];
+       uint8_t         id;
+
+       struct sockaddr_storage src;
+       socklen_t       salen;
+} fr_packet_ctx_t;
+
+
+static int mod_decode(void const *ctx, uint8_t *const data, size_t data_len, REQUEST *request)
+{
+       fr_packet_ctx_t const *pc = ctx;
+
+       RDEBUG("\t\tDECODE <<< request %zd - %p data %p size %zd\n", request->number, pc, data, data_len);
+
+       return 0;
+}
+
+static ssize_t mod_encode(void const *ctx, REQUEST *request, uint8_t *buffer, size_t buffer_len)
+{
+       fr_packet_ctx_t const *pc = ctx;
+
+       RDEBUG("\t\tENCODE >>> request %zd - data %p %p room %zd\n", request->number, pc, buffer, buffer_len);
+
+       buffer[0] = PW_CODE_ACCESS_ACCEPT;
+       buffer[1] = pc->id;
+       buffer[2] = 0;
+       buffer[3] = 20;
+
+       (void) fr_radius_sign(buffer, pc->original, pc->secret, pc->secret_len);
+
+       return 20;
+}
+
+static size_t mod_nak(void const *ctx, uint8_t *const packet, size_t packet_len, UNUSED uint8_t *reply, UNUSED size_t reply_len)
+{
+       DEBUG("\t\tNAK !!! request %d - data %p %p size %zd\n", packet[1], ctx, packet, packet_len);
+
+       return 10;
+}
+
+static fr_transport_final_t mod_process(REQUEST *request, fr_transport_action_t action)
+{
+       RDEBUG("\t\tPROCESS --- request %zd action %d\n", request->number, action);
+
+       return FR_TRANSPORT_REPLY;
+}
+
+static ssize_t mod_read(int sockfd, void *ctx, uint8_t *buffer, size_t buffer_len)
+{
+       ssize_t data_size;
+       size_t packet_len;
+       fr_packet_ctx_t *pc = ctx;
+       decode_fail_t reason;
+
+       pc->salen = sizeof(pc->src);
+
+       data_size = recvfrom(sockfd, buffer, buffer_len, 0, (struct sockaddr *) &pc->src, &pc->salen);
+       if (data_size <= 0) return data_size;
+
+       packet_len = data_size;
+       if (!fr_radius_ok(buffer, &packet_len, false, &reason)) {
+               return 0;
+       }
+
+       if (!fr_radius_verify(buffer, NULL, pc->secret, pc->secret_len)) {
+               return 0;
+       }
+
+       pc->id = buffer[1];
+       memcpy(pc->original, buffer, sizeof(pc->original));
+
+       return packet_len;
+}
+
+
+static ssize_t mod_write(int sockfd, void *ctx, uint8_t *buffer, size_t buffer_len)
+{
+       ssize_t data_size;
+       fr_packet_ctx_t *pc = ctx;
+
+       pc->salen = sizeof(pc->src);
+
+       /*
+        *      @todo - do more stuff
+        */
+       data_size = sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr *) &pc->src, pc->salen);
+       if (data_size <= 0) return data_size;
+
+       /*
+        *      @todo - post-write cleanups
+        */
+
+       return data_size;
+}
+
+extern fr_transport_t fr_radius_server_udp;
+fr_transport_t fr_radius_server_udp = {
+       .name                   = "radius_server_udp",
+       .id                     = 1,            /* @todo fix me later */
+       .default_message_size   = 4096,
+       .read                   = mod_read,
+       .write                  = mod_write,
+       .decode                 = mod_decode,
+       .encode                 = mod_encode,
+       .nak                    = mod_nak,
+       .process                = mod_process
+};
diff --git a/src/protocols/radius/radius.h b/src/protocols/radius/radius.h
new file mode 100644 (file)
index 0000000..8392c7b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef _FR_RADIUS_RADIUS_H
+#define _FR_RADIUS_RADIUS_H
+/*
+ * $Id$
+ *
+ * @file radius/radius.h
+ * @brief Structures and prototypes for base RADIUS functionality.
+ *
+ * @copyright 1999-2017 The FreeRADIUS server project
+ */
+
+/*
+ *     protocols/radius/base.c
+ */
+#define AUTH_PASS_LEN (AUTH_VECTOR_LEN)
+#define MAX_PASS_LEN (128)
+#define        FR_TUNNEL_PW_ENC_LENGTH(_x) (2 + 1 + _x + PAD(_x + 1, 16))
+extern FR_NAME_NUMBER const fr_request_types[];
+
+typedef enum {
+       DECODE_FAIL_NONE = 0,
+       DECODE_FAIL_MIN_LENGTH_PACKET,
+       DECODE_FAIL_MIN_LENGTH_FIELD,
+       DECODE_FAIL_MIN_LENGTH_MISMATCH,
+       DECODE_FAIL_HEADER_OVERFLOW,
+       DECODE_FAIL_UNKNOWN_PACKET_CODE,
+       DECODE_FAIL_INVALID_ATTRIBUTE,
+       DECODE_FAIL_ATTRIBUTE_TOO_SHORT,
+       DECODE_FAIL_ATTRIBUTE_OVERFLOW,
+       DECODE_FAIL_MA_INVALID_LENGTH,
+       DECODE_FAIL_ATTRIBUTE_UNDERFLOW,
+       DECODE_FAIL_TOO_MANY_ATTRIBUTES,
+       DECODE_FAIL_MA_MISSING,
+       DECODE_FAIL_MAX
+} decode_fail_t;
+
+int            fr_radius_sign(uint8_t *packet, uint8_t const *original,
+                              uint8_t const *secret, size_t secret_len) CC_HINT(nonnull (1,3));
+int            fr_radius_verify(uint8_t *packet, uint8_t const *original,
+                                uint8_t const *secret, size_t secret_len) CC_HINT(nonnull (1,3));
+bool           fr_radius_ok(uint8_t const *packet, size_t *packet_len_p, bool require_ma,
+                            decode_fail_t *reason) CC_HINT(nonnull (1,2));
+
+void           fr_radius_ascend_secret(uint8_t *digest, uint8_t const *vector,
+                                       char const *secret, uint8_t const *value) CC_HINT(nonnull);
+
+ssize_t                fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code);
+
+#endif /* _FR_RADIUS_RADIUS_H */