Freeradius 3.2.x TEAP Support for Machine Only Authentication

Suriya Shankar suriya.dshankar at gmail.com
Mon Jun 15 23:43:30 UTC 2026


Hi Alan,

With the current EAP-TEAP implementation, we don't have the option to
support devices that only want to use Machine Auth. I implemented and
tested this on my machine and it works as expected. The changes I made as
follows


diff --git a/src/modules/rlm_eap/types/rlm_eap_teap/eap_teap.c
b/src/modules/rlm_eap/types/rlm_eap_teap/eap_teap.c
index b30ab7e3d3..36b2dbdfa3 100644
--- a/src/modules/rlm_eap/types/rlm_eap_teap/eap_teap.c
+++ b/src/modules/rlm_eap/types/rlm_eap_teap/eap_teap.c
@@ -1217,6 +1217,7 @@ static PW_CODE eap_teap_phase2(REQUEST *request,
eap_handler_t *eap_session,
 {
  PW_CODE code = PW_CODE_ACCESS_REJECT;
  rlm_rcode_t rcode;
+ bool machine_only = false;
  VALUE_PAIR *tvp;
  teap_tunnel_t *t = (teap_tunnel_t *)tls_session->opaque;
  int eap_method = 0;
@@ -1253,6 +1254,17 @@ static PW_CODE eap_teap_phase2(REQUEST *request,
eap_handler_t *eap_session,

  RDEBUG("Phase 2: Got tunneled identity of %s", t->username->vp_strvalue);

+ } else if (tvp &&
+    (tvp->vp_length == EAP_HEADER_LEN + 1) &&
+    (tvp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
+    (tvp->vp_strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY)) {
+ /*
+ * Empty inner EAP-Identity indicates machine-only auth: finish
+ * with final TEAP Result TLV, then wait for client Result echo.
+ */
+ RDEBUG2("Phase 2: Received empty inner EAP-Identity; treating as
machine-only TEAP completion");
+ machine_only = true;
+
  } else if (!fake->username) {
  /*
  * Don't reject the request outright,
@@ -1556,12 +1568,14 @@ done:
  * Call authentication recursively, which will
  * do PAP, CHAP, MS-CHAP, etc.
  */
- rad_virtual_server(fake, true);
+ if (!machine_only) {
+ rad_virtual_server(fake, true);
+ }

  /*
  * Decide what to do with the reply.
  */
- switch (fake->reply->code) {
+ switch (machine_only ? PW_CODE_ACCESS_CHALLENGE : fake->reply->code) {
  case 0:
  tvp = fr_pair_find_by_num(fake->config, PW_RESPONSE_PACKET_TYPE, 0,
TAG_ANY);
  if (tvp && (tvp->vp_integer == PW_CODE_ACCESS_CHALLENGE)) {
@@ -1573,6 +1587,15 @@ done:
  code = PW_CODE_ACCESS_REJECT;
  break;

+ case PW_CODE_ACCESS_CHALLENGE:
+ if (machine_only) {
+ t->result_final = true;
+ eap_teap_append_result(request, tls_session, PW_CODE_ACCESS_ACCEPT);
+ code = PW_CODE_ACCESS_CHALLENGE;
+ break;
+ }
+ /* FALL-THROUGH */
+
  case PW_CODE_ACCESS_ACCEPT:
  tvp = fr_pair_find_by_num(fake->packet->vps, PW_EAP_TYPE, 0, TAG_ANY);
  if (tvp) {





*And the logs from my testing *


*From the client we received after authenticating the Machine Certificate*
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap: Session established.
Proceeding to decode tunneled attributes
Mon Jun 15 22:14:10 2026 : Debug:   TEAP tunnel data total 101
  TEAP tunnel data in 00: 80 0c 00 4c 00 01 01 21 9a 89 af 0a 7d e6 5d b1
  TEAP tunnel data in 10: 22 9b 2a eb ad 14 80 9a 0b 72 1f a4 87 6b 65 a3
  TEAP tunnel data in 20: 22 3b 6e c8 31 c8 9b e5 00 00 00 00 00 00 00 00
  TEAP tunnel data in 30: 00 00 00 00 00 00 00 00 00 00 00 00 b6 0e 4f 32
  TEAP tunnel data in 40: 5f ab f5 f7 28 37 3d cd 9e 1c ee 0b 6a ab c8 05
  TEAP tunnel data in 50: 80 0a 00 02 00 01 00 02 00 02 00 01 80 09 00 05
  TEAP tunnel data in 60: 02 82 00 05 01
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap: Got Tunneled TEAP TLVs
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap:  Found the pair by
TEAP_TLV_IDENTITY copying the value to t->identity
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap:
FreeRADIUS-EAP-TEAP-Crypto-Binding =
0x000101219a89af0a7de65db1229b2aebad14809a0b721fa4876b65a3223b6ec831c89be50000000000000000000000000000000000000000b60e4f325fabf5f728373dcd9e1cee0b6aabc805
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap:
FreeRADIUS-EAP-TEAP-Intermediate-Result = Success
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap:
FreeRADIUS-EAP-TEAP-EAP-Payload = 0x0282000501
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap: BUFFER for Compound MAC
calculation - hexdump(len=123): 80 0c 00 4c 00 01 01 21 9a 89 af 0a 7d e6
5d b1 22 9b 2a eb ad 14 80 9a 0b 72 1f a4 87 6b 65 a3 22 3b 6e c8 31 c8 9b
e5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 01 00 26 53 5f 39 34
64 65 36 36 65 38 2d 35 35 36 61 2d 34 64 35 36 2d 38 37 38 30 2d 61 31 31
34 36 32 30 61 35 63 34 32
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap: S-IMCK[j] -
hexdump(len=40): 68 d4 a1 17 ad bb de f1 4b fb cb 4c 94 71 95 63 60 b2 f7
91 24 c4 6d ca ef 7d c8 13 56 a5 47 d4 b3 fd 0a 0a 18 ad 68 4d
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap: Derived key (MSK) -
hexdump(len=64): f3 93 64 e5 bd 76 78 39 ff c6 b6 8f 85 ad 95 ff 56 9e 60
ae 4e c9 51 c1 8b 55 20 5b 4a 59 ec a9 9e 58 9c d8 63 1c 4a b6 f4 3d cb f5
6f 07 14 13 ea 91 ff fb 7c b8 52 89 fd fa 5a f9 b5 ff 3f 9e
Mon Jun 15 22:14:10 2026 : Debug: (135) eap_teap: Derived key (EMSK) -
hexdump(len=64): 9b e4 9d 86 ff c5 f1 fa f0 16 62 11 ca 09 ed d7 39 6b c0
90 03 22 ac bd d4 6b b9 35 eb 26 5c b9 9f 20 c0 6b f7 a8 ec 5b 7f a7 4e 14
97 86 95 9e de 9f c4 e5 04 dc 85 dd 96 0f 8d 6e 68 27 30 56




02 82 00 05 01 -> Sending the identity packet without any username for the
client preferring Machine Only Authentication.



*When challenged by Accept as the changes shown in the diff, client accepts
the connection*
Debug:   TEAP tunnel data total 6
  TEAP tunnel data in 00: 80 03 00 02 00 01
Mon Jun 15 22:14:10 2026 : Debug: (136) eap_teap: Got Tunneled TEAP TLVs
Mon Jun 15 22:14:10 2026 : Debug: (136) eap_teap:
FreeRADIUS-EAP-TEAP-Result = Success
Mon Jun 15 22:14:10 2026 : Debug: (136)
eap_S_94de66e8-556a-4d56-8780-a114620a5c42: Sending


If you find this good, I would like to raise a PR. If any changes required
or if it's not the way as expected, will update it accordingly

Thanks,
Suriya


More information about the Freeradius-Users mailing list