]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
auth_type handling
authorAlan T. DeKok <aland@freeradius.org>
Tue, 7 Mar 2023 19:41:18 +0000 (14:41 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 8 Mar 2023 20:28:05 +0000 (15:28 -0500)
parse it, verify it, verify the secret, and sign the packets

src/listen/bfd/proto_bfd.c
src/listen/bfd/session.c

index 4965431a7d8f3be4758af1c4b6a1ce91a12bd4bb..834499d194d06afe245261c9733af957c953eb28 100644 (file)
@@ -30,6 +30,7 @@
 extern fr_app_t proto_bfd;
 
 static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, CONF_PARSER const *rule);
+static int auth_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, CONF_PARSER const *rule);
 
 /** How to parse a BFD listen section
  *
@@ -47,6 +48,9 @@ static const CONF_PARSER peer_config[] = {
        { FR_CONF_OFFSET("max_timeouts", FR_TYPE_UINT32, proto_bfd_peer_t, detect_multi ) },
        { FR_CONF_OFFSET("demand", FR_TYPE_BOOL, proto_bfd_peer_t, demand_mode ) },
 
+       { FR_CONF_OFFSET("auth_type", FR_TYPE_VOID, proto_bfd_peer_t, auth_type ),
+       .func = auth_type_parse },
+
        CONF_PARSER_TERMINATOR
 };
 
@@ -138,6 +142,34 @@ static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF
        return 0;
 }
 
+/** Parse auth_type
+ *
+ * @param[in] ctx      to allocate data in (instance of proto_bfd).
+ * @param[out] out     Where to write the auth_type value
+ * @param[in] parent   Base structure address.
+ * @param[in] ci       #CONF_PAIR specifying the name of the type module.
+ * @param[in] rule     unused.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+static int auth_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
+{
+       char const              *name = cf_pair_value(cf_item_to_pair(ci));
+       int                     auth_type;
+
+       auth_type = fr_table_value_by_str(bfd_auth_type_table, name, -1);
+       if (auth_type < 0) {
+               cf_log_err(ci, "Invalid value for 'auth_type'");
+               return -1;
+       }
+
+       *(bfd_auth_type_t *) out = auth_type;
+
+       return 0;
+}
+
+
 /** Decode the packet
  *
  */
@@ -448,6 +480,35 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx)
                                goto error;
                        }
 
+                       /*
+                        *      Secret and auth_type handling.
+                        */
+                       if (c->secret && !*c->secret) {
+                               cf_log_err(cs, "Secret cannot be an empty string");
+                               goto error;
+                       }
+                       peer->secret_len = strlen(c->secret);
+
+                       switch (peer->auth_type) {
+                       case BFD_AUTH_RESERVED:
+                               if (c->secret) cf_log_warn(cs, "Ignoring 'secret' due to 'auth_type = none'");
+                               break;
+
+                       case BFD_AUTH_SIMPLE:
+                               if (strlen(c->secret) > 16) {
+                                       cf_log_err(cs, "Length of 'secret' must be no more than 16 octets for 'auth_type = simple'");
+                                       goto error;
+                               }
+                               break;
+
+                               /*
+                                *      Secrets can be any length.
+                                */
+                       default:
+                               break;
+
+                       }
+
                        if (!fr_rb_insert(inst->peers, c)) {
                                cf_log_err(cs, "Failed to add peer %s", cf_section_name2(cs));
                                goto error;
index 4972c3fed0b78be7af84d5ce249e10cb5849506a..3a18d91d9e565b46af11cfe023ec3acdb4a934c6 100644 (file)
 
 #include "session.h"
 
-
-#define BFD_MAX_SECRET_LENGTH 20
-
 #if 0
-typedef struct {
-       uint8_t         auth_type;
-       uint8_t         auth_len;
-       uint8_t         key_id;
-} __attribute__ ((packed)) bfd_auth_basic_t;
-
-
-typedef struct {
-       uint8_t         auth_type;
-       uint8_t         auth_len;
-       uint8_t         key_id;
-       uint8_t         password[16];
-} __attribute__ ((packed)) bfd_auth_simple_t;
-
-typedef struct {
-       uint8_t         auth_type;
-       uint8_t         auth_len;
-       uint8_t         key_id;
-       uint8_t         reserved;
-       uint32_t        sequence_no;
-       uint8_t         digest[MD5_DIGEST_LENGTH];
-} __attribute__ ((packed)) bfd_auth_md5_t;
-
-typedef struct {
-       uint8_t         auth_type;
-       uint8_t         auth_len;
-       uint8_t         key_id;
-       uint8_t         reserved;
-       uint32_t        sequence_no;
-       uint8_t         digest[SHA1_DIGEST_LENGTH];
-} __attribute__ ((packed)) bfd_auth_sha1_t;
-
-typedef union bfd_auth_t {
-       bfd_auth_basic_t        basic;
-       bfd_auth_simple_t       password;
-       bfd_auth_md5_t          md5;
-       bfd_auth_sha1_t         sha1;
-} __attribute__ ((packed)) bfd_auth_t;
-
-
-static int bfd_verify_sequence(proto_bfd_peer_t *session, uint32_t sequence_no,
-                              int keyed)
-{
-       uint32_t start, stop;
-
-       start = session->recv_auth_seq;
-       if (keyed) {
-               start++;
-       }
-       stop = start + 3 * session->detect_multi;
-
-       if (start < stop) {
-               if ((sequence_no < start) ||
-                   (sequence_no > stop)) {
-                       return 0;
-               }
-
-       } else {        /* start is ~2^32, stop is ~10 */
-               if ((sequence_no > start) &&
-                   (sequence_no < stop)) {
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-static void bfd_calc_md5(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       bfd_auth_md5_t *md5 = &bfd->auth.md5;
-
-       fr_assert(session->secret_len <= sizeof(md5->digest));
-       fr_assert(md5->auth_len == sizeof(*md5));
-
-       memset(md5->digest, 0, sizeof(md5->digest));
-       memcpy(md5->digest, session->secret, session->secret_len);
-
-       fr_md5_calc(md5->digest,(const uint8_t *) bfd, bfd->length);
-}
-
-static void bfd_auth_md5(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       bfd_auth_md5_t *md5 = &bfd->auth.md5;
-
-       md5->auth_type = session->auth_type;
-       md5->auth_len = sizeof(*md5);
-       bfd->length += md5->auth_len;
-
-       md5->key_id = 0;
-       md5->sequence_no = session->xmit_auth_seq++;
-
-       bfd_calc_md5(session, bfd);
-}
-
-static int bfd_verify_md5(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       int rcode;
-       bfd_auth_md5_t *md5 = &bfd->auth.md5;
-       uint8_t digest[sizeof(md5->digest)];
-
-       if (md5->auth_len != sizeof(*md5)) return 0;
-
-       if (md5->key_id != 0) return 0;
-
-       memcpy(digest, md5->digest, sizeof(digest));
-
-       bfd_calc_md5(session, bfd);
-       rcode = fr_digest_cmp(digest, md5->digest, sizeof(digest));
-
-       memcpy(md5->digest, digest, sizeof(md5->digest)); /* pedantic */
-
-       if (rcode != 0) {
-               DEBUG("BFD %s MD5 Digest failed: **** RE-ENTER THE SECRET ON BOTH ENDS ****", session->client.shortname);
-               return 0;
-       }
-
-       /*
-        *      Do this AFTER the authentication instead of before!
-        */
-       if (!session->auth_seq_known) {
-               session->auth_seq_known = 1;
-
-       } else if (!bfd_verify_sequence(session, md5->sequence_no,
-                                       (md5->auth_type == BFD_AUTH_MET_KEYED_MD5))) {
-               DEBUG("MD5 sequence out of window");
-               return 0;
-       }
-
-       session->recv_auth_seq = md5->sequence_no;
-
-       return 1;
-}
-
-static void bfd_calc_sha1(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       fr_sha1_ctx ctx;
-       bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
-
-       fr_assert(session->secret_len <= sizeof(sha1->digest));
-       fr_assert(sha1->auth_len == sizeof(*sha1));
-
-       memset(sha1->digest, 0, sizeof(sha1->digest));
-       memcpy(sha1->digest, session->secret, session->secret_len);
-
-       fr_sha1_init(&ctx);
-       fr_sha1_update(&ctx, (const uint8_t *) bfd, bfd->length);
-       fr_sha1_final(sha1->digest, &ctx);
-}
-
-static void bfd_auth_sha1(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
-
-       sha1->auth_type = session->auth_type;
-       sha1->auth_len = sizeof(*sha1);
-       bfd->length += sha1->auth_len;
-
-       sha1->key_id = 0;
-       sha1->sequence_no = session->xmit_auth_seq++;
-
-       bfd_calc_sha1(session, bfd);
-}
-
-static int bfd_verify_sha1(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       int rcode;
-       bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
-       uint8_t digest[sizeof(sha1->digest)];
-
-       if (sha1->auth_len != sizeof(*sha1)) return 0;
-
-       if (sha1->key_id != 0) return 0;
-
-       memcpy(digest, sha1->digest, sizeof(digest));
-
-       bfd_calc_sha1(session, bfd);
-       rcode = fr_digest_cmp(digest, sha1->digest, sizeof(digest));
-
-       memcpy(sha1->digest, digest, sizeof(sha1->digest)); /* pedantic */
-
-       if (rcode != 0) {
-               DEBUG("BFD %d SHA1 Digest failed: **** RE-ENTER THE SECRET ON BOTH ENDS ****", session->number);
-               return 0;
-       }
-
-       /*
-        *      Do this AFTER the authentication instead of before!
-        */
-       if (!session->auth_seq_known) {
-               session->auth_seq_known = 1;
-
-       } else if (!bfd_verify_sequence(session, sha1->sequence_no,
-                                       (sha1->auth_type == BFD_AUTH_MET_KEYED_SHA1))) {
-               DEBUG("SHA1 sequence out of window");
-               return 0;
-       }
-
-       session->recv_auth_seq = sha1->sequence_no;
-
-       return 1;
-}
-
-
-static int bfd_authenticate(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       switch (bfd->auth.basic.auth_type) {
-       case BFD_AUTH_RESERVED:
-               return 0;
-
-       case BFD_AUTH_SIMPLE:
-               break;
-
-       case BFD_AUTH_KEYED_MD5:
-       case BFD_AUTH_MET_KEYED_MD5:
-               return bfd_verify_md5(session, bfd);
-
-       case BFD_AUTH_KEYED_SHA1:
-       case BFD_AUTH_MET_KEYED_SHA1:
-               return bfd_verify_sha1(session, bfd);
-       }
-
-       return 0;
-}
-
-
-
-static void bfd_sign(proto_bfd_peer_t *session, bfd_packet_t *bfd)
-{
-       if (bfd->auth_present) {
-               switch (session->auth_type) {
-               case BFD_AUTH_RESERVED:
-                       break;
-
-               case BFD_AUTH_SIMPLE:
-                       break;
-
-               case BFD_AUTH_KEYED_MD5:
-               case BFD_AUTH_MET_KEYED_MD5:
-                       bfd_auth_md5(session, bfd);
-                       break;
-
-               case BFD_AUTH_KEYED_SHA1:
-               case BFD_AUTH_MET_KEYED_SHA1:
-                       bfd_auth_sha1(session, bfd);
-                       break;
-               }
-       }
-}
-
-
 /*
  *     Send an immediate response to a poll request.
  *
@@ -701,223 +448,230 @@ static int bfd_socket_recv(rad_listen_t *listener)
        return bfd_process(session, &bfd);
 }
 
-static int bfd_parse_ip_port(CONF_SECTION *cs, fr_ipaddr_t *ipaddr, uint16_t *port)
+#endif
+
+static void bfd_start_packets(proto_bfd_peer_t *session);
+static void bfd_start_control(proto_bfd_peer_t *session);
+static int bfd_stop_control(proto_bfd_peer_t *session);
+//static int bfd_process(proto_bfd_peer_t *session, bfd_packet_t *bfd);
+static void bfd_set_timeout(proto_bfd_peer_t *session, fr_time_t when);
+
+/*
+ *     Verify and/or calculate auth-type digests.
+ */
+static void bfd_calc_md5(proto_bfd_peer_t *session, bfd_packet_t *bfd)
 {
-       int rcode;
+       bfd_auth_md5_t *md5 = &bfd->auth.md5;
 
-       /*
-        *      Try IPv4 first
-        */
-       memset(ipaddr, 0, sizeof(*ipaddr));
-       ipaddr->addr.v4.s_addr = htonl(INADDR_NONE);
-       rcode = cf_pair_parse(NULL, cs, "ipaddr", FR_ITEM_POINTER(FR_TYPE_IPV4_ADDR, ipaddr), NULL, T_INVALID);
-       if (rcode < 0) return -1;
-
-       if (rcode == 0) { /* successfully parsed IPv4 */
-               ipaddr->af = AF_INET;
-
-       } else {        /* maybe IPv6? */
-               rcode = cf_pair_parse(NULL, cs, "ipv6addr", FR_ITEM_POINTER(FR_TYPE_IPV6_ADDR, ipaddr), NULL, T_INVALID);
-               if (rcode < 0) return -1;
-
-               if (rcode == 1) {
-                       cf_log_err(cf_section_to_item(cs),
-                                  "No address specified in section");
-                       return -1;
-               }
-               ipaddr->af = AF_INET6;
-       }
+       fr_assert(session->secret_len <= sizeof(md5->digest));
+       fr_assert(md5->auth_len == sizeof(*md5));
 
-       rcode = cf_pair_parse(NULL, cs, "port", FR_ITEM_POINTER(FR_TYPE_UINT16, port), "0", T_INVALID);
-       if (rcode < 0) return -1;
+       memset(md5->digest, 0, sizeof(md5->digest));
+       memcpy(md5->digest, session->client.secret, session->secret_len);
 
-       return 0;
+       fr_md5_calc(md5->digest,(const uint8_t *) bfd, bfd->length);
 }
 
-/*
- *     @fixme: move some of this to parse
- */
-static int bfd_init_sessions(CONF_SECTION *cs, bfd_socket_t *sock, int sockfd)
+static void bfd_auth_md5(proto_bfd_peer_t *session, bfd_packet_t *bfd)
 {
-       CONF_ITEM *ci;
-       CONF_SECTION *peer;
-       uint16_t port;
-       fr_ipaddr_t ipaddr;
-
-       for (ci=cf_item_next(cs, NULL);
-            ci != NULL;
-            ci=cf_item_next(cs, ci)) {
-               proto_bfd_peer_t *session, my_session;
+       bfd_auth_md5_t *md5 = &bfd->auth.md5;
 
-              if (!cf_item_is_section(ci)) continue;
+       md5->auth_type = session->auth_type;
+       md5->auth_len = sizeof(*md5);
+       bfd->length += md5->auth_len;
 
-              peer = cf_item_to_section(ci);
+       md5->key_id = 0;
+       md5->sequence_no = session->xmit_auth_seq++;
 
-              if (strcmp(cf_section_name1(peer), "peer") != 0) continue;
+       bfd_calc_md5(session, bfd);
+}
 
-              if (bfd_parse_ip_port(peer, &ipaddr, &port) < 0) {
-                      return -1;
-              }
+static void bfd_calc_sha1(proto_bfd_peer_t *session, bfd_packet_t *bfd)
+{
+       fr_sha1_ctx ctx;
+       bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
 
-              my_session.socket.inet.dst_ipaddr = ipaddr;
-              my_session.socket.inet.dst_port = port;
-              if (fr_rb_find(sock->session_tree, &my_session) != NULL) {
-                      cf_log_err(ci, "Peers must have unique IP addresses");
-                      return -1;
-              }
+       fr_assert(session->secret_len <= sizeof(sha1->digest));
+       fr_assert(sha1->auth_len == sizeof(*sha1));
 
-              session = bfd_new_session(sock, sockfd, peer, &ipaddr, port);
-              if (!session) return -1;
-       }
+       memset(sha1->digest, 0, sizeof(sha1->digest));
+       memcpy(sha1->digest, session->client.secret, session->secret_len);
 
-       return 0;
+       fr_sha1_init(&ctx);
+       fr_sha1_update(&ctx, (const uint8_t *) bfd, bfd->length);
+       fr_sha1_final(sha1->digest, &ctx);
 }
 
-
-/*
- *     None of these functions are used.
- */
-static int bfd_socket_send(UNUSED rad_listen_t *listener, UNUSED request_t *request)
+static void bfd_auth_sha1(proto_bfd_peer_t *session, bfd_packet_t *bfd)
 {
-       fr_assert(0 == 1);
-       return 0;
-}
+       bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
 
+       sha1->auth_type = session->auth_type;
+       sha1->auth_len = sizeof(*sha1);
+       bfd->length += sha1->auth_len;
 
-static int bfd_socket_encode(UNUSED rad_listen_t *listener, UNUSED request_t *request)
-{
-       fr_assert(0 == 1);
-       return 0;
-}
+       sha1->key_id = 0;
+       sha1->sequence_no = session->xmit_auth_seq++;
 
+       bfd_calc_sha1(session, bfd);
+}
 
-static int bfd_socket_decode(UNUSED rad_listen_t *listener, UNUSED request_t *request)
+#if 0
+static int bfd_verify_sequence(proto_bfd_peer_t *session, uint32_t sequence_no,
+                              int keyed)
 {
-       fr_assert(0 == 1);
-       return 0;
+       uint32_t start, stop;
+
+       start = session->recv_auth_seq;
+       if (keyed) {
+               start++;
+       }
+       stop = start + 3 * session->detect_multi;
+
+       if (start < stop) {
+               if ((sequence_no < start) ||
+                   (sequence_no > stop)) {
+                       return 0;
+               }
+
+       } else {        /* start is ~2^32, stop is ~10 */
+               if ((sequence_no > start) &&
+                   (sequence_no < stop)) {
+                       return 0;
+               }
+       }
+
+       return 1;
 }
 
-static fr_table_num_sorted_t const auth_types[] = {
-       { L("keyed-md5"),               BFD_AUTH_KEYED_MD5      },
-       { L("keyed-sha1"),              BFD_AUTH_KEYED_SHA1     },
-       { L("met-keyed-md5"),   BFD_AUTH_MET_KEYED_MD5  },
-       { L("met-keyed-sha1"),  BFD_AUTH_MET_KEYED_SHA1 },
-       { L("none"),            BFD_AUTH_RESERVED       },
-       { L("simple"),          BFD_AUTH_SIMPLE         }
-};
-static size_t auth_types_len = NUM_ELEMENTS(auth_types);
-
-static int bfd_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
+static int bfd_verify_md5(proto_bfd_peer_t *session, bfd_packet_t *bfd)
 {
-       bfd_socket_t *sock = this->data;
-       char const *auth_type_str = NULL;
-       uint16_t listen_port;
-       fr_ipaddr_t ipaddr;
+       int rcode;
+       bfd_auth_md5_t *md5 = &bfd->auth.md5;
+       uint8_t digest[sizeof(md5->digest)];
+
+       if (md5->auth_len != sizeof(*md5)) return 0;
 
-       fr_assert(sock != NULL);
+       if (md5->key_id != 0) return 0;
 
-       if (bfd_parse_ip_port(cs, &ipaddr, &listen_port) < 0) {
-               return -1;
+       memcpy(digest, md5->digest, sizeof(digest));
+
+       bfd_calc_md5(session, bfd);
+       rcode = fr_digest_cmp(digest, md5->digest, sizeof(digest));
+
+       memcpy(md5->digest, digest, sizeof(md5->digest)); /* pedantic */
+
+       if (rcode != 0) {
+               DEBUG("BFD %s MD5 Digest failed: **** RE-ENTER THE SECRET ON BOTH ENDS ****", session->client.shortname);
+               return 0;
        }
 
-       sock->my_ipaddr = ipaddr;
-       sock->my_port = listen_port;
-
-       if (cf_pair_parse(sock, cs, "interface", FR_ITEM_POINTER(FR_TYPE_STRING, &sock->interface), NULL, T_INVALID) < 0) return -1;
-
-       if (cf_pair_parse(sock, cs, "min_receive_interval", FR_ITEM_POINTER(FR_TYPE_UINT32,
-                         &sock->min_rx_interval), "1000", T_BARE_WORD) < 0) return -1;
-       if (cf_pair_parse(sock, cs, "max_timeouts", FR_ITEM_POINTER(FR_TYPE_UINT32,
-                         &sock->max_timeouts), "3", T_BARE_WORD) < 0) return -1;
-       if (cf_pair_parse(sock, cs, "demand", FR_ITEM_POINTER(FR_TYPE_BOOL, &sock->demand),
-                         "no", T_DOUBLE_QUOTED_STRING) < 0) return -1;
-       if (cf_pair_parse(NULL, cs, "auth_type", FR_ITEM_POINTER(FR_TYPE_STRING, &auth_type_str),
-                         NULL, T_INVALID) < 0) return -1;
-
-       if (!this->server) {
-               char const *server;
-               if (cf_pair_parse(sock, cs, "server", FR_ITEM_POINTER(FR_TYPE_STRING, &server),
-                                 NULL, T_INVALID) < 0) return -1;
-               sock->server_cs = virtual_server_find(server);
-       } else {
-               sock->server_cs = this->server_cs;
+       /*
+        *      Do this AFTER the authentication instead of before!
+        */
+       if (!session->auth_seq_known) {
+               session->auth_seq_known = 1;
+
+       } else if (!bfd_verify_sequence(session, md5->sequence_no,
+                                       (md5->auth_type == BFD_AUTH_MET_KEYED_MD5))) {
+               DEBUG("MD5 sequence out of window");
+               return 0;
        }
 
-       if (sock->min_tx_interval < 100) sock->min_tx_interval = 100;
-       if (sock->min_tx_interval > 10000) sock->min_tx_interval = 10000;
+       session->recv_auth_seq = md5->sequence_no;
 
-       if (sock->min_rx_interval < 100) sock->min_rx_interval = 100;
-       if (sock->min_rx_interval > 10000) sock->min_rx_interval = 10000;
+       return 1;
+}
 
-       if (sock->max_timeouts == 0) sock->max_timeouts = 1;
-       if (sock->max_timeouts > 10) sock->max_timeouts = 10;
+static int bfd_verify_sha1(proto_bfd_peer_t *session, bfd_packet_t *bfd)
+{
+       int rcode;
+       bfd_auth_sha1_t *sha1 = &bfd->auth.sha1;
+       uint8_t digest[sizeof(sha1->digest)];
 
-       sock->auth_type = fr_table_value_by_str(auth_types, auth_type_str, BFD_AUTH_INVALID);
-       if (sock->auth_type == BFD_AUTH_INVALID) {
-               ERROR("Unknown auth_type '%s'", auth_type_str);
-               return -1;
-       }
+       if (sha1->auth_len != sizeof(*sha1)) return 0;
 
-       if (sock->auth_type == BFD_AUTH_SIMPLE) {
-               ERROR("'simple' authentication is insecure and is not supported");
-               return -1;
-       }
+       if (sha1->key_id != 0) return 0;
 
-       if (sock->auth_type != BFD_AUTH_RESERVED) {
-               sock->secret_len = bfd_parse_secret(cs, sock->secret);
+       memcpy(digest, sha1->digest, sizeof(digest));
 
-               if (sock->secret_len == 0) {
-                       ERROR("Cannot have empty secret");
-                       return -1;
-               }
+       bfd_calc_sha1(session, bfd);
+       rcode = fr_digest_cmp(digest, sha1->digest, sizeof(digest));
 
-               if (((sock->auth_type == BFD_AUTH_KEYED_MD5) ||
-                    (sock->auth_type == BFD_AUTH_MET_KEYED_MD5)) &&
-                   (sock->secret_len > 16)) {
-                       ERROR("Secret must be no more than 16 bytes when using MD5");
-                       return -1;
-               }
-       }
+       memcpy(sha1->digest, digest, sizeof(sha1->digest)); /* pedantic */
 
-       sock->session_tree = fr_rb_inline_talloc_alloc(sock, proto_bfd_peer_t, node, bfd_session_cmp, bfd_session_free);
-       if (!sock->session_tree) {
-               ERROR("Failed creating session tree!");
-               return -1;
+       if (rcode != 0) {
+               DEBUG("BFD %s SHA1 Digest failed: **** RE-ENTER THE SECRET ON BOTH ENDS ****", session->client.shortname);
+               return 0;
        }
 
        /*
-        *      Find the sibling "bfd" section of the "listen" section.
+        *      Do this AFTER the authentication instead of before!
         */
-       sock->unlang = cf_section_find(cf_item_to_section(cf_parent(cs)), "bfd", NULL);
+       if (!session->auth_seq_known) {
+               session->auth_seq_known = 1;
 
-       return 0;
+       } else if (!bfd_verify_sequence(session, sha1->sequence_no,
+                                       (sha1->auth_type == BFD_AUTH_MET_KEYED_SHA1))) {
+               DEBUG("SHA1 sequence out of window");
+               return 0;
+       }
+
+       session->recv_auth_seq = sha1->sequence_no;
+
+       return 1;
 }
 
-       /*
-        *      Bootstrap the initial set of connections.
-        */
-       if (bfd_init_sessions(cs, sock, this->fd) < 0) {
-               return -1;
+static int bfd_authenticate(proto_bfd_peer_t *session, bfd_packet_t *bfd)
+{
+       switch (bfd->auth.basic.auth_type) {
+       case BFD_AUTH_RESERVED:
+               return 0;
+
+       case BFD_AUTH_SIMPLE:
+               break;
+
+       case BFD_AUTH_KEYED_MD5:
+       case BFD_AUTH_MET_KEYED_MD5:
+               return bfd_verify_md5(session, bfd);
+
+       case BFD_AUTH_KEYED_SHA1:
+       case BFD_AUTH_MET_KEYED_SHA1:
+               return bfd_verify_sha1(session, bfd);
        }
 
        return 0;
 }
 #endif
 
-static void bfd_start_packets(proto_bfd_peer_t *session);
-static void bfd_start_control(proto_bfd_peer_t *session);
-static int bfd_stop_control(proto_bfd_peer_t *session);
-//static int bfd_process(proto_bfd_peer_t *session, bfd_packet_t *bfd);
-static void bfd_set_timeout(proto_bfd_peer_t *session, fr_time_t when);
 
-static const char *bfd_state[] = {
-       "admin-down",
-       "down",
-       "init",
-       "up"
-};
+static void bfd_sign(proto_bfd_peer_t *session, bfd_packet_t *bfd)
+{
+       if (bfd->auth_present) {
+               switch (session->auth_type) {
+               case BFD_AUTH_RESERVED:
+                       break;
 
+               case BFD_AUTH_SIMPLE:
+                       break;
+
+               case BFD_AUTH_KEYED_MD5:
+               case BFD_AUTH_MET_KEYED_MD5:
+                       bfd_auth_md5(session, bfd);
+                       break;
 
+               case BFD_AUTH_KEYED_SHA1:
+               case BFD_AUTH_MET_KEYED_SHA1:
+                       bfd_auth_sha1(session, bfd);
+                       break;
+               }
+       }
+}
+
+
+/*
+ *     Initialize a control packet.
+ */
 static void bfd_control_packet_init(proto_bfd_peer_t *session,
                                   bfd_packet_t *bfd)
 {
@@ -978,10 +732,10 @@ static void bfd_send_packet(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, vo
                bfd_start_packets(session);
        }
 
-//     bfd_sign(session, &bfd);
+       bfd_sign(session, &bfd);
 
        DEBUG("BFD %s sending packet state %s",
-             session->client.shortname, bfd_state[session->session_state]);
+             session->client.shortname, fr_bfd_packet_names[session->session_state]);
 
 #if 0
        if (sendto(session->socket.fd, &bfd, bfd.length, 0,
@@ -1135,7 +889,7 @@ static void bfd_detection_timeout(UNUSED fr_event_list_t *el, fr_time_t now, voi
        proto_bfd_peer_t *session = ctx;
 
        DEBUG("BFD %s Timeout state %s ****** ", session->client.shortname,
-             bfd_state[session->session_state]);
+             fr_bfd_packet_names[session->session_state]);
 
        if (!session->demand_mode) {
                switch (session->session_state) {