Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Oct 1999 11:18:53 +0200
From:      "Oleg Semyonov" <os@altavista.net>
To:        <jdp@polstra.com>
Cc:        <freebsd-isp@freebsd.org>
Subject:   FreeBSD libradius accounting patch suggestion
Message-ID:  <000b01bf13c9$a4afc480$0400a8c0@admin.dnepr.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hello John!

    Excuse me for my "English" but I'm sure you understand me.

    I need the pppd-2.3.9(10) daemon with RADIUS authentication and
accounting.
I've patched original pppd-2.3.9 distribution for FreeBSD specifics and put
into
source the RADIUS capabilities with almost full support for auth and
accounting.
To do so I've patched your libradius sources extracted from FreeBSD 3.* for
accounting support. Patches are attached. They includes:

1. #define for RAD_CONNECT_INFO (non-rfc, but widely used).
2. #defines for Framed-Compression and NAS-Port-Type values.
2. #defines for accounting support.
3. internal insert_request_authenticator() for accounting request packets.
4. rad_auth_open() and rad_acct_open() calls for opening a handle as
   auth or acct server with appropriate defaults(for defaults only).
   rad_open() call preserved for compatibility and is equivalent to
   rad_auth_open().
5. No mans changed, sorry.
6. Default accounting config file is /etc/radacct.conf (not the best
   solution, IMHO, but no way to extend radius.conf(5) file format to
   support accounting and maintain the compatibility with current libradius
   version).
7. #define for __printflike (for FreeBSD 2.2.8).
8. library and header renamed for compatibility with old version
   (as temporary solution).

I'm planning to release my pppd patches for public, so it is best if you
put my patches (or my idea in your version) into standard FreeBSD
radius library. And put it into 2.2.8-STABLE source tree because seems
to me no any incompatibilities here, and your code is fully compilable
and usable on 2.2.8.

Mail me if you find my suggestion useful, and I will update my pppd
RADIUS support for new standard FreeBSD RADIUS library before release
it to public (anybody want it?).

Thanks!
OS

---
Oleg Semyonov, the Head of IT Department of KTPK "Dnepr", Energodar, UA
Internet mail: os@altavista.net, finger/talk: os@ktpk.dp.ua, ICQ:31256452


[-- Attachment #2 --]
diff -urP libradius/Makefile libradius+/Makefile
--- libradius/Makefile	Sat Jan 30 00:44:47 1999
+++ libradius+/Makefile	Sat Oct  9 17:54:47 1999
@@ -24,7 +24,7 @@
 #
 #	$FreeBSD: src/lib/libradius/Makefile,v 1.2 1999/01/29 22:44:47 brian Exp $
 
-LIB=		radius
+LIB=		radius+
 SRCS=		radlib.c
 CFLAGS+=	-Wall
 DPADD+=		${LIBMD}
@@ -33,9 +33,10 @@
 SHLIB_MINOR=	0
 MAN3+=		libradius.3
 MAN5+=		radius.conf.5
+#NOMAN=		noman
 
 beforeinstall:
 	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \
-	    ${.CURDIR}/radlib.h ${DESTDIR}/usr/include
+	    ${.CURDIR}/radlib.h ${DESTDIR}${INCLUDEDIR}/radlib+.h
 
 .include <bsd.lib.mk>
diff -urP libradius/radlib.c libradius+/radlib.c
--- libradius/radlib.c	Fri Feb  5 13:23:44 1999
+++ libradius+/radlib.c	Sat Oct  9 09:38:28 1999
@@ -42,12 +42,18 @@
 #include <string.h>
 #include <unistd.h>
 
+/* For FreeBSD 2.2.8-STABLE */
+#ifndef __printflike
+#define __printflike(x,y)
+#endif
+
 #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,
 		    const struct sockaddr_in *);
 static int	 put_password_attr(struct rad_handle *, int,
@@ -110,6 +116,23 @@
 	}
 }
 
+static void
+insert_request_authenticator(struct rad_handle *h, int srv)
+{
+	MD5_CTX ctx;
+	const struct rad_server *srvp;
+
+	srvp = &h->servers[srv];
+
+	/* Create the request authenticator */
+	MD5Init(&ctx);
+	MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
+	MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
+	MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
+	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
+	MD5Final(&h->request[POS_AUTH], &ctx);
+}
+
 /*
  * Return true if the current response is valid for a request to the
  * specified server.
@@ -229,9 +252,14 @@
 	else {
 		struct servent *sent;
 
-		srvp->addr.sin_port =
-		    (sent = getservbyname("radius", "udp")) != NULL ?
-			sent->s_port : htons(RADIUS_PORT);
+		if (h->type == RADIUS_AUTH)
+			srvp->addr.sin_port =
+			    (sent = getservbyname("radius", "udp")) != NULL ?
+				sent->s_port : htons(RADIUS_PORT);
+		else
+			srvp->addr.sin_port =
+			    (sent = getservbyname("radacct", "udp")) != NULL ?
+				sent->s_port : htons(RADACCT_PORT);
 	}
 	if ((srvp->secret = strdup(secret)) == NULL) {
 		generr(h, "Out of memory");
@@ -269,7 +297,8 @@
 	int retval;
 
 	if (path == NULL)
-		path = PATH_RADIUS_CONF;
+		path = (h->type == RADIUS_AUTH)
+		    ? PATH_RADIUS_CONF : PATH_RADACCT_CONF;
 	if ((fp = fopen(path, "r")) == NULL) {
 		generr(h, "Cannot open \"%s\": %s", path, strerror(errno));
 		return -1;
@@ -421,9 +450,13 @@
 		if (++h->srv >= h->num_servers)
 			h->srv = 0;
 
-	/* Insert the scrambled password into the request */
-	if (h->pass_pos != 0)
-		insert_scrambled_password(h, h->srv);
+	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST)
+		/* Insert the request authenticator into the request */
+		insert_request_authenticator(h, h->srv);
+	else
+		/* Insert the scrambled password into the request */
+		if (h->pass_pos != 0)
+			insert_scrambled_password(h, h->srv);
 
 	/* Send the request */
 	n = sendto(h->fd, h->request, h->req_len, 0,
@@ -552,14 +585,22 @@
 		}
 	}
 
-	/* Make sure the user gave us a password */
-	if (h->pass_pos == 0 && !h->chap_pass) {
-		generr(h, "No User or Chap Password attributes given");
-		return -1;
-	}
-	if (h->pass_pos != 0 && h->chap_pass) {
-		generr(h, "Both User and Chap Password attributes given");
-		return -1;
+	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
+		/* Make sure no password given */
+		if (h->pass_pos || h->chap_pass) {
+			generr(h, "User or Chap Password in accounting request");
+			return -1;
+		}
+	} else {
+		/* Make sure the user gave us a password */
+		if (h->pass_pos == 0 && !h->chap_pass) {
+			generr(h, "No User or Chap Password attributes given");
+			return -1;
+		}
+		if (h->pass_pos != 0 && h->chap_pass) {
+			generr(h, "Both User and Chap Password attributes given");
+			return -1;
+		}
 	}
 
 	/* Fill in the length field in the message */
@@ -591,7 +632,7 @@
  * In that case, it returns NULL.
  */
 struct rad_handle *
-rad_open(void)
+rad_auth_open(void)
 {
 	struct rad_handle *h;
 
@@ -606,8 +647,26 @@
 		h->pass_len = 0;
 		h->pass_pos = 0;
 		h->chap_pass = 0;
+		h->type = RADIUS_AUTH;
 	}
 	return h;
+}
+
+struct rad_handle *
+rad_acct_open(void)
+{
+	struct rad_handle *h;
+
+	h = rad_open();
+	if (h != NULL)
+	        h->type = RADIUS_ACCT;
+	return h;
+}
+
+struct rad_handle *
+rad_open(void)
+{
+    return rad_auth_open();
 }
 
 int
diff -urP libradius/radlib.h libradius+/radlib.h
--- libradius/radlib.h	Fri Feb  5 13:23:44 1999
+++ libradius+/radlib.h	Thu Oct  7 19:46:18 1999
@@ -36,6 +36,8 @@
 #define RAD_ACCESS_REQUEST		1
 #define RAD_ACCESS_ACCEPT		2
 #define RAD_ACCESS_REJECT		3
+#define RAD_ACCOUNTING_REQUEST		4
+#define RAD_ACCOUNTING_RESPONSE		5
 #define RAD_ACCESS_CHALLENGE		11
 
 /* Attribute types and values */
@@ -66,6 +68,9 @@
 #define RAD_FILTER_ID			11	/* String */
 #define RAD_FRAMED_MTU			12	/* Integer */
 #define RAD_FRAMED_COMPRESSION		13	/* Integer */
+	#define RAD_COMP_NONE			0
+	#define RAD_COMP_VJ			1
+	#define RAD_COMP_IPXHDR			2
 #define RAD_LOGIN_IP_HOST		14	/* IP address */
 #define RAD_LOGIN_SERVICE		15	/* Integer */
 #define RAD_LOGIN_TCP_PORT		16	/* Integer */
@@ -95,8 +100,54 @@
      /* reserved for accounting		40-59 */
 #define RAD_CHAP_CHALLENGE		60	/* String */
 #define RAD_NAS_PORT_TYPE		61	/* Integer */
+	#define RAD_ASYNC			0
+	#define RAD_SYNC			1
+	#define RAD_ISDN_SYNC			2
+	#define RAD_ISDN_ASYNC_V120		3
+	#define RAD_ISDN_ASYNC_V110		4
+	#define RAD_VIRTUAL			5
 #define RAD_PORT_LIMIT			62	/* Integer */
 #define RAD_LOGIN_LAT_PORT		63	/* Integer */
+#define RAD_CONNECT_INFO		77	/* String */
+
+/* Accounting attribute types and values */
+#define RAD_ACCT_STATUS_TYPE		40	/* Integer */
+	#define RAD_START			1
+	#define RAD_STOP			2
+	#define RAD_ACCOUNTING_ON		7
+	#define RAD_ACCOUNTING_OFF		8
+#define RAD_ACCT_DELAY_TIME		41	/* Integer */
+#define RAD_ACCT_INPUT_OCTETS		42	/* Integer */
+#define RAD_ACCT_OUTPUT_OCTETS		43	/* Integer */
+#define RAD_ACCT_SESSION_ID		44	/* String */
+#define RAD_ACCT_AUTHENTIC		45	/* Integer */
+	#define RAD_AUTH_RADIUS			1
+	#define RAD_AUTH_LOCAL			2
+	#define RAD_AUTH_REMOTE			3
+#define RAD_ACCT_SESSION_TIME		46	/* Integer */
+#define RAD_ACCT_INPUT_PACKETS		47	/* Integer */
+#define RAD_ACCT_OUTPUT_PACKETS		48	/* Integer */
+#define RAD_ACCT_TERMINATE_CAUSE	49	/* Integer */
+        #define RAD_TERM_USER_REQUEST		1
+        #define RAD_TERM_LOST_CARRIER		2
+        #define RAD_TERM_LOST_SERVICE		3
+        #define RAD_TERM_IDLE_TIMEOUT		4
+        #define RAD_TERM_SESSION_TIMEOUT	5
+        #define RAD_TERM_ADMIN_RESET		6
+        #define RAD_TERM_ADMIN_REBOOT		7
+        #define RAD_TERM_PORT_ERROR		8
+        #define RAD_TERM_NAS_ERROR		9
+        #define RAD_TERM_NAS_REQUEST		10
+        #define RAD_TERM_NAS_REBOOT		11
+        #define RAD_TERM_PORT_UNNEEDED		12
+        #define RAD_TERM_PORT_PREEMPTED		13
+        #define RAD_TERM_PORT_SUSPENDED		14
+        #define RAD_TERM_SERVICE_UNAVAILABLE    15
+        #define RAD_TERM_CALLBACK		16
+        #define RAD_TERM_USER_ERROR		17
+        #define RAD_TERM_HOST_REQUEST		18
+#define	RAD_ACCT_MULTI_SESSION_ID	50	/* String */
+#define	RAD_ACCT_LINK_COUNT		51	/* Integer */
 
 struct rad_handle;
 struct timeval;
@@ -117,6 +168,8 @@
 int			 rad_init_send_request(struct rad_handle *, int *,
 			    struct timeval *);
 struct rad_handle	*rad_open(void);
+struct rad_handle	*rad_auth_open(void);
+struct rad_handle	*rad_acct_open(void);
 int			 rad_put_addr(struct rad_handle *, int, struct in_addr);
 int			 rad_put_attr(struct rad_handle *, int,
 			    const void *, size_t);
diff -urP libradius/radlib_private.h libradius+/radlib_private.h
--- libradius/radlib_private.h	Fri Feb  5 13:23:44 1999
+++ libradius+/radlib_private.h	Thu Oct  7 19:28:58 1999
@@ -34,10 +34,16 @@
 
 #include "radlib.h"
 
+/* Handle types */
+#define RADIUS_AUTH		0   /* RADIUS authentication, default */
+#define RADIUS_ACCT		1   /* RADIUS accounting */
+
 /* Defaults */
 #define MAXTRIES		3
 #define PATH_RADIUS_CONF	"/etc/radius.conf"
+#define PATH_RADACCT_CONF	"/etc/radacct.conf"
 #define RADIUS_PORT		1812
+#define RADACCT_PORT		1813
 #define TIMEOUT			3	/* In seconds */
 
 /* Limits */
@@ -81,6 +87,7 @@
 	int		 total_tries;	/* How many requests we'll send */
 	int		 try;		/* How many requests we've sent */
 	int		 srv;		/* Server number we did last */
+	int		 type;		/* Handle type */
 };
 
 #endif

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?000b01bf13c9$a4afc480$0400a8c0>