I made the radius integration for mpd. During this work I missed some functions in libradius.
I attached patches for libradius for adding this missing functions, here is a short changelog:
- added rad_demangle for demangling user-passwords (needed for MS-CHAPv1 MPPE-keys).
- added rad_demangle_mppe_key for demangling mppe-keys (needed for MS-CHAPv2 MPPE-keys).
- added some typecasts to avoid compilation warnings
The rad_demangle_mppe_key function was taken from userland ppp.
I hope that someone with enough karma can make a short review and then commit this code.
bye,
--
------------------------------- ----------------------------------
Michael Bretterklieber - [EMAIL PROTECTED] JAWA Management Software GmbH - http://www.jawa.at
Liebenauer Hauptstr. 200 -------------- privat ------------
A-8041 GRAZ GSM: ++43-(0)676-93 96 698 Tel: ++43-(0)316-403274-12 E-mail: [EMAIL PROTECTED]
Fax: ++43-(0)316-403274-10 http://www.bretterklieber.com
------------------------------- ----------------------------------
"...the number of UNIX installations has grown to 10, with more expected..." - Dennis Ritchie and Ken Thompson, June 1972
diff -u libradius/Makefile libradius_new/Makefile
--- libradius/Makefile Mon Dec 23 16:07:51 2002
+++ libradius_new/Makefile Mon Dec 23 16:02:46 2002
@@ -25,13 +25,13 @@
# $FreeBSD: src/lib/libradius/Makefile,v 1.3.2.2 2002/06/17 02:24:57 brian Exp $
LIB= radius
-SRCS= radlib.c
+SRCS= radlib.c radlib_vs.c
INCS= radlib.h radlib_vs.h
CFLAGS+= -Wall
DPADD+= ${LIBMD}
LDADD+= -lmd
SHLIB_MAJOR= 1
-SHLIB_MINOR= 0
+SHLIB_MINOR= 1
MAN= libradius.3 radius.conf.5
.include <bsd.lib.mk>
diff -u libradius/radlib.c libradius_new/radlib.c
--- libradius/radlib.c Mon Dec 23 16:08:01 2002
+++ libradius_new/radlib.c Mon Dec 23 16:00:19 2002
@@ -45,8 +45,6 @@
#include "radlib_private.h"
static void clear_password(struct rad_handle *);
-static void generr(struct rad_handle *, const char *, ...)
- __printflike(2, 3);
static void insert_scrambled_password(struct rad_handle *, int);
static void insert_request_authenticator(struct rad_handle *, int);
static int is_valid_response(struct rad_handle *, int,
@@ -67,7 +65,7 @@
h->pass_pos = 0;
}
-static void
+void
generr(struct rad_handle *h, const char *format, ...)
{
va_list ap;
@@ -243,7 +241,7 @@
sizeof srvp->addr.sin_addr);
}
if (port != 0)
- srvp->addr.sin_port = htons(port);
+ srvp->addr.sin_port = htons((u_short)port);
else {
struct servent *sent;
@@ -513,8 +511,8 @@
for (i = 0; i < LEN_AUTH; i += 2) {
long r;
r = random();
- h->request[POS_AUTH+i] = r;
- h->request[POS_AUTH+i+1] = r >> 8;
+ h->request[POS_AUTH+i] = (u_char)r;
+ h->request[POS_AUTH+i+1] = (u_char)(r >> 8);
}
h->req_len = POS_ATTRS;
clear_password(h);
@@ -569,7 +567,7 @@
}
type = h->response[h->resp_pos++];
*len = h->response[h->resp_pos++] - 2;
- if (h->resp_pos + *len > h->resp_len) {
+ if (h->resp_pos + (int)*len > h->resp_len) {
generr(h, "Malformed attribute in response");
return -1;
}
@@ -945,3 +943,51 @@
return (h->servers[h->srv].secret);
}
+int
+rad_demangle(struct rad_handle *h, const void *mangled, size_t mlen, u_char
+*demangled)
+{
+ char R[LEN_AUTH];
+ const char *S;
+ int i, Ppos;
+ MD5_CTX Context;
+ u_char b[16], *C;
+
+ if ((mlen % 16 != 0) || (mlen > 128)) {
+ generr(h, "Cannot interpret mangled data of length %ld", (u_long)mlen);
+ return -1;
+ }
+
+ C = (u_char *)mangled;
+
+ /* We need the shared secret as Salt */
+ S = rad_server_secret(h);
+
+ /* We need the request authenticator */
+ if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) {
+ generr(h, "Cannot obtain the RADIUS request authenticator");
+ return -1;
+ }
+
+ MD5Init(&Context);
+ MD5Update(&Context, S, strlen(S));
+ MD5Update(&Context, R, LEN_AUTH);
+ MD5Final(b, &Context);
+ Ppos = 0;
+ while (mlen) {
+
+ mlen -= 16;
+ for (i = 0; i < 16; i++)
+ demangled[Ppos++] = C[i] ^ b[i];
+
+ if (mlen) {
+ MD5Init(&Context);
+ MD5Update(&Context, S, strlen(S));
+ MD5Update(&Context, C, 16);
+ MD5Final(b, &Context);
+ }
+
+ C += 16;
+ }
+
+ return 0;
+}
diff -u libradius/radlib.h libradius_new/radlib.h
--- libradius/radlib.h Mon Dec 23 10:48:59 2002
+++ libradius_new/radlib.h Mon Dec 23 16:00:58 2002
@@ -167,6 +167,8 @@
struct timeval;
__BEGIN_DECLS
+void generr(struct rad_handle *, const char *, ...)
+ __printflike(2, 3);
struct rad_handle *rad_acct_open(void);
int rad_add_server(struct rad_handle *,
const char *, int, const char *, int, int);
@@ -195,6 +197,9 @@
int rad_send_request(struct rad_handle *);
const char *rad_server_secret(struct rad_handle *);
const char *rad_strerror(struct rad_handle *);
+int rad_demangle(struct rad_handle *,
+ const void *, size_t, u_char *);
+
__END_DECLS
#endif /* _RADLIB_H_ */
Only in libradius_new: radlib_vs.c
diff -u libradius/radlib_vs.h libradius_new/radlib_vs.h
--- libradius/radlib_vs.h Mon Dec 23 16:09:07 2002
+++ libradius_new/radlib_vs.h Mon Dec 23 16:02:02 2002
@@ -66,6 +66,8 @@
#define RAD_MICROSOFT_MS_SECONDARY_NBNS_SERVER 31
#define RAD_MICROSOFT_MS_ARAP_CHALLENGE 33
+#define SALT_LEN 2
+
struct rad_handle;
__BEGIN_DECLS
@@ -75,6 +77,7 @@
size_t);
int rad_put_vendor_int(struct rad_handle *, int, int, u_int32_t);
int rad_put_vendor_string(struct rad_handle *, int, int, const char *);
+int rad_demangle_mppe_key(struct rad_handle *, const void *, size_t, u_char *,
+size_t *);
__END_DECLS
#endif /* _RADLIB_VS_H_ */
/*- * Copyright 2002 Michael Bretterklieber <[EMAIL PROTECTED]> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include <sys/types.h>
#include <md5.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <netgraph/ng_mppc.h>
#include "radlib_private.h"
#include "radlib.h"
#include "radlib_vs.h"
int
rad_demangle_mppe_key(struct rad_handle *h, const void *mangled, size_t mlen, u_char
*demangled, size_t *len)
{
char R[LEN_AUTH]; /* variable names as per rfc2548 */
const char *S;
u_char b[16];
const u_char *A, *C;
MD5_CTX Context;
int Slen, i, Clen, Ppos;
u_char *P;
if (mlen % 16 != SALT_LEN) {
generr(h, "Cannot interpret mangled data of length %ld", (u_long)mlen);
return -1;
}
/* We need the RADIUS Request-Authenticator */
if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) {
generr(h, "Cannot obtain the RADIUS request authenticator");
return -1;
}
A = (const u_char *)mangled; /* Salt comes first */
C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */
Clen = mlen - SALT_LEN;
S = rad_server_secret(h); /* We need the RADIUS secret */
Slen = strlen(S);
P = alloca(Clen); /* We derive our plaintext */
MD5Init(&Context);
MD5Update(&Context, S, Slen);
MD5Update(&Context, R, LEN_AUTH);
MD5Update(&Context, A, SALT_LEN);
MD5Final(b, &Context);
Ppos = 0;
while (Clen) {
Clen -= 16;
for (i = 0; i < 16; i++)
P[Ppos++] = C[i] ^ b[i];
if (Clen) {
MD5Init(&Context);
MD5Update(&Context, S, Slen);
MD5Update(&Context, C, 16);
MD5Final(b, &Context);
}
C += 16;
}
/*
* The resulting plain text consists of a one-byte length, the text and
* maybe some padding.
*/
*len = *P;
if (*len > mlen - 1) {
generr(h, "Mangled data seems to be garbage %d %d", *len, mlen-1);
return -1;
}
if (*len > MPPE_KEY_LEN) {
generr(h, "Key to long (%d) for me max. %d", *len, MPPE_KEY_LEN);
return -1;
}
memcpy(demangled, P + 1, *len);
return 0;
}
