From 29cf2c93fbca988911c42c47245ae2b8cab37ea4 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3350651-DimitriPapadopoulos@users.noreply.gitlab.com> Date: Tue, 19 May 2026 18:47:40 +0200 Subject: [PATCH] Handle RADIUS Access-Challenge State as bytes `state` is a string we receive from the RADIUS server and we do not parse but echo back. According to RFC 2866, all strings we receive from the RADIUS server are octet strings, not null-terminated strings: Note that none of the types in RADIUS terminate with a NUL (hex 00). In particular, types "text" and "string" in RADIUS do not terminate with a NUL (hex 00). The Attribute has a length field and does not use a terminator. Text contains UTF-8 encoded 10646 characters and String contains 8-bit binary data. Servers and servers and clients MUST be able to deal with embedded nulls. RADIUS implementers using C are cautioned not to use strcpy() when handling strings. Therefore, ensure we treat `state` as a proper octet string rather than a null-terminated string. Resolves: #729 Signed-off-by: Dimitri Papadopoulos <3350651-DimitriPapadopoulos@users.noreply.gitlab.com> --- src/auth/radius.c | 16 ++++++++++------ src/auth/radius.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/auth/radius.c b/src/auth/radius.c index 96768f6b..2df32bf4 100644 --- a/src/auth/radius.c +++ b/src/auth/radius.c @@ -411,7 +411,7 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned int pass_len) if (pctx->state != NULL) { if (rc_avpair_add(pctx->vctx->rh, &send, PW_STATE, pctx->state, - -1, 0) == NULL) { + pctx->state_len, 0) == NULL) { oc_syslog( LOG_ERR, "%s:%u: error in constructing radius message for user '%s'", @@ -421,6 +421,7 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned int pass_len) } talloc_free(pctx->state); pctx->state = NULL; + pctx->state_len = 0; } pctx->pass_msg[0] = 0; @@ -593,15 +594,18 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned int pass_len) if (vp->attribute == PW_STATE && vp->type == PW_TYPE_STRING) { /* State */ - if (vp->lvalue > 0) - pctx->state = talloc_strdup( - pctx, vp->strvalue); + if (vp->lvalue > 0) { + pctx->state = talloc_memdup( + pctx, vp->strvalue, vp->lvalue); + pctx->state_len = + pctx->state ? vp->lvalue : 0; + } pctx->id++; oc_syslog( LOG_DEBUG, - "radius-auth: Access-Challenge response stage %u, State %s", - pctx->passwd_counter, vp->strvalue); + "radius-auth: Access-Challenge response stage %u, State length %u", + pctx->passwd_counter, vp->lvalue); ret = ERR_AUTH_CONTINUE; } vp = vp->next; diff --git a/src/auth/radius.h b/src/auth/radius.h index e84c3e22..a7fd07a5 100644 --- a/src/auth/radius.h +++ b/src/auth/radius.h @@ -74,6 +74,7 @@ struct radius_ctx_st { struct radius_vhost_ctx *vctx; char *state; + unsigned int state_len; unsigned int passwd_counter; size_t prev_prompt_hash; };