On Thu, Mar 02, 2023 at 09:09:31AM -0700, Todd C. Miller wrote:
> On Thu, 02 Mar 2023 09:07:38 -0700, "Theo de Raadt" wrote:
>
> > + if (auth.length > total_length)
> >
> > Isn't auth.length a network byte order value?
>
> Ah yes, good catch; it needs an ntohs().
>
> - todd
Hi,
I just looked up RADIUS in RFC 2865 and on page 15 it reads:
--------->
Length
The Length field is two octets. It indicates the length of the
packet including the Code, Identifier, Length, Authenticator and
Attribute fields. Octets outside the range of the Length field
MUST be treated as padding and ignored on reception. If the
packet is shorter than the Length field indicates, it MUST be
silently discarded. The minimum length is 20 and maximum length
is 4096.
<---------
Notice the silent discard, so perhaps we should try again? I adjusted
the patch for this, but I can't test.
Best Regards,
-peter
Index: raddauth.c
===================================================================
RCS file: /cvs/src/libexec/login_radius/raddauth.c,v
retrieving revision 1.30
diff -u -p -u -r1.30 raddauth.c
--- raddauth.c 28 Jun 2019 13:32:53 -0000 1.30
+++ raddauth.c 2 Mar 2023 16:24:02 -0000
@@ -114,6 +114,7 @@
char *radius_dir = RADIUS_DIR;
char auth_secret[MAXSECRETLEN+1];
volatile sig_atomic_t timedout;
+int silent_discard;
int alt_retries;
int retries;
int sockfd;
@@ -325,7 +326,7 @@ retry:
break;
default:
- if (timedout)
+ if (timedout || silent_discard)
goto retry;
snprintf(_pwstate, sizeof(_pwstate),
"invalid response type %d\n", i);
@@ -451,17 +452,24 @@ rad_recv(char *state, char *challenge, u
struct sockaddr_in sin;
u_char recv_vector[AUTH_VECTOR_LEN], test_vector[AUTH_VECTOR_LEN];
MD5_CTX context;
+ ssize_t total_length;
salen = sizeof(sin);
+ silent_discard = 0;
alarm(timeout);
- if ((recvfrom(sockfd, &auth, sizeof(auth), 0,
- (struct sockaddr *)&sin, &salen)) < AUTH_HDR_LEN) {
+ total_length = recvfrom(sockfd, &auth, sizeof(auth), 0,
+ (struct sockaddr *)&sin, &salen);
+ alarm(0);
+ if (total_length < AUTH_HDR_LEN) {
if (timedout)
return(-1);
errx(1, "bogus auth packet from server");
}
- alarm(0);
+ if (ntohs(auth.length) > total_length) {
+ silent_discard = 1;
+ return(-1);
+ }
if (sin.sin_addr.s_addr != auth_server)
errx(1, "bogus authentication server");