]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Import squid_radius_auth helper for basic authentication to RADIUS
authorhno <>
Mon, 25 Jun 2007 17:02:34 +0000 (17:02 +0000)
committerhno <>
Mon, 25 Jun 2007 17:02:34 +0000 (17:02 +0000)
17 files changed:
configure.in
helpers/basic_auth/Makefile.am
helpers/basic_auth/squid_radius_auth/COPYRIGHT [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/Changelog [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/Make.inc [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/Makefile.am [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/Makefile.default [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/Makefile.in [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/Makefile.solaris [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/README [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/md5.c [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/md5.h [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/radius.h [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/squid_rad_auth.c [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/squid_radius_auth.8 [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/util.c [new file with mode: 0644]
helpers/basic_auth/squid_radius_auth/util.h [new file with mode: 0644]

index 14a2bfa41e765a5f18e415c3301f552c721c2b69..6dba1c0242c83e173f65a786e1e6a4e299bf5690 100644 (file)
@@ -1,7 +1,7 @@
 
 dnl  Configuration input file for Squid
 dnl
-dnl  $Id: configure.in,v 1.460 2007/06/24 22:34:15 hno Exp $
+dnl  $Id: configure.in,v 1.461 2007/06/25 11:02:34 hno Exp $
 dnl
 dnl
 dnl
@@ -11,7 +11,7 @@ AM_CONFIG_HEADER(include/autoconf.h)
 AC_CONFIG_AUX_DIR(cfgaux)
 AC_CONFIG_SRCDIR([src/main.cc])
 AM_INIT_AUTOMAKE([tar-ustar])
-AC_REVISION($Revision: 1.460 $)dnl
+AC_REVISION($Revision: 1.461 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AM_MAINTAINER_MODE
 
@@ -3356,6 +3356,7 @@ AC_CONFIG_FILES([\
        helpers/basic_auth/SASL/Makefile \
        helpers/basic_auth/POP3/Makefile \
        helpers/basic_auth/DB/Makefile \
+       helpers/basic_auth/squid_radius_auth/Makefile \
        helpers/digest_auth/Makefile \
        helpers/digest_auth/password/Makefile \
        helpers/digest_auth/ldap/Makefile \
index 1254d7685e52cb0ea5dc48352f1a38d0ef442ea9..11698c1fbe29206f756a8bb82c5284d254077563 100644 (file)
@@ -1,7 +1,7 @@
 #  Makefile for storage modules in the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.8 2007/06/02 23:49:23 hno Exp $
+#  $Id: Makefile.am,v 1.9 2007/06/25 11:02:35 hno Exp $
 #
 
-DIST_SUBDIRS   = getpwnam LDAP MSNT multi-domain-NTLM NCSA PAM SMB YP SASL mswin_sspi POP3 DB
+DIST_SUBDIRS   = getpwnam LDAP MSNT multi-domain-NTLM NCSA PAM SMB YP SASL mswin_sspi POP3 DB squid_radius_auth
 SUBDIRS                = @BASIC_AUTH_HELPERS@
diff --git a/helpers/basic_auth/squid_radius_auth/COPYRIGHT b/helpers/basic_auth/squid_radius_auth/COPYRIGHT
new file mode 100644 (file)
index 0000000..f6f2226
--- /dev/null
@@ -0,0 +1,113 @@
+This program is based on code from Livingston Enterprises, Inc. and parts are
+
+               COPYRIGHT NOTICE SQUID_RAD_AUTH
+
+Copyright (C) 1992-1995 Livingston Enterprises, Inc and Cistron Internet Services
+B.V. who both have given permission to modify and distribute those parts. The new
+parts of the code is Copyright (C) 1998 R.M. van Selm <selm@cistron.nl> with
+modifications Copyright (C) 2004 Henrik Nordstrom <hno@squid-cache.org>
+
+Permission to use, copy, modify, and distribute this software for any purpose
+and without fee is hereby granted, provided that this copyright and permission
+notice appear on all copies and supporting documentation, the name of
+Livingston Enterprises, Inc. not be used in advertising or publicity pertaining
+to distribution of the program without specific prior permission, and notice be
+given in supporting documentation that copying and distribution is by
+permission of Livingston Enterprises, Inc. and Cistron Internet Services B.V.
+
+Neither Livingston Enterprises, Inc. nor Cistron Internet Services B.V. nor I
+(R.M. van Selm) make representations about the suitability of this software for
+any purpose. It isprovided "as is" without express or implied warranty.
+
+Marc van Selm <selm@cistron.nl>
+
+
+               COPYRIGHT NOTICE SQUID_RAD_AUTH Documentation
+
+Copyright (C) 2004 Henrik Nordstrom
+
+Permission to use, copy, modify, and distribute this software for any purpose
+and without fee is hereby granted, provided that this copyright and permission
+notice appear on all copies and supporting documentation, the name of Henrik
+Nordstrom. not be used in advertising or publicity pertaining to distribution
+of the program without specific prior permission.
+
+The author makes no representations about the suitability of this documentation
+for any purpose. It isprovided "as is" without express or implied warranty.
+
+Henrik Nordstrom <hno@squid-cache.org>
+
+               COPYRIGHT NOTICE CISTRON RADIUS
+
+/* This program is based on code from Livingston Enterprises, Inc. and parts are
+ * Copyright (C) 1992-1995 Livingston Enterprises, Inc who has given permission
+ * to modify and distribute those parts. The new code is Copyright (C) 1996-1997
+ * Cistron Internet Services B.V.
+ *
+ * Permission to use, copy, modify, and distribute this software for any purpose
+ * and without fee is hereby granted, provided that this copyright and permission
+ * notice appear on all copies and supporting documentation, the name of
+ * Livingston Enterprises, Inc. not be used in advertising or publicity pertaining
+ * to distribution of the program without specific prior permission, and notice be
+ * given in supporting documentation that copying and distribution is by
+ * permission of Livingston Enterprises, Inc. and Cistron Internet Services B.V.
+
+ * Neither Livingston Enterprises, Inc. nor Cistron Internet Services B.V. make
+ * representations about the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+*/
+
+               COPYRIGHT NOTICE LIVINGSTON RADIUS 1.16
+
+/*
+ *
+ *     RADIUS
+ *     Remote Authentication Dial In User Service
+ *
+ *
+ *     Livingston Enterprises, Inc.
+ *     6920 Koll Center Parkway
+ *     Pleasanton, CA   94566
+ *
+ *     Copyright 1992 Livingston Enterprises, Inc.
+ *
+ *     Permission to use, copy, modify, and distribute this software for any
+ *     purpose and without fee is hereby granted, provided that this
+ *     copyright and permission notice appear on all copies and supporting
+ *     documentation, the name of Livingston Enterprises, Inc. not be used
+ *     in advertising or publicity pertaining to distribution of the
+ *     program without specific prior permission, and notice be given
+ *     in supporting documentation that copying and distribution is by
+ *     permission of Livingston Enterprises, Inc.   
+ *
+ *     Livingston Enterprises, Inc. makes no representations about
+ *     the suitability of this software for any purpose.  It is
+ *     provided "as is" without express or implied warranty.
+ *
+
+
+               COPYRIGHT NOTICE RSA Data Security MD5 (md5.c)
+
+MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
diff --git a/helpers/basic_auth/squid_radius_auth/Changelog b/helpers/basic_auth/squid_radius_auth/Changelog
new file mode 100644 (file)
index 0000000..05d5cb0
--- /dev/null
@@ -0,0 +1,55 @@
+1.09: - RADIUS protocol fixes by Henrik Nordstrom <hno@squid-cache.org>
+      - Corrected how retransmits & timeouts is handled
+      - The shared secret now verified properly
+      - Request/response processing paired properly
+      - New -t command line option to tune the RADIUS timeout
+1.08: - RADIUS port/service option by Joost de Heer <sanguis@xs4all.nl>
+      - Added service/port tags to the configuration file allowing
+       manual override of the RADIUS port number via the config
+       file in addition to the already existing -p command line
+       option doing the same.
+      - The default port used if the radius service could not be found
+       in /etc/services changed from the obsolete 1645 to the official
+       port 1812
+1.07: - Squid-2.5 update by Henrik Nordstrom <hno@squid-cache.org>
+       The Basic auth helper communication has changed slightly in
+       Squid-2.5 to use URL-encoded strings. This to allow use of "odd"
+       characters such as space without problems.
+      - Major cleanup to remove dead code and unneeded references to
+       RADIUS dictionary files.
+      - Added commandline opttions. No more hardcoded paths.
+      - Added manpage documentation to document the configuration of this
+       helper
+1.06: - Included byte-order patch from Klaus Weidner <kw@w-m-p.com>
+       The assignment of 'auth->length' erroneously used 'htonl' instead
+       of 'htons' to assign a 16-bit value. The symptom was that the radius
+       server ignored the requests, because they had zero length according
+       to the data header.
+      - Initial warnings confused Squid. Most (all) of them now warn to stderr
+       so you should see them in the cache.log
+      - A fix by Moslem Saleh: A select timeout causes the redirector to skip
+       the reply. Moslem detected/fixed this issue on a BSD 4.1 (on Intel)
+       system.
+1.05a: - Minor fixes and warnings. Should fix some compiler issues (compiler
+        fixes are untested except on Debian Linux 1.3 & GCC-2.95-2)
+1.04: - Rolled in patches from Mike McCauley and Andrea Dell'Amico:
+       These patches fix a few bugs and make the kit more platform 
+       independent. 
+       also  fixes:
+       Unwanted characters in the reply. This confuses Squid. 
+       This is caused by unexpected replies from the RADIUS server 
+       and should have been ignored by
+       the authenticator; 
+       It enables long passwords (up to 254 characters); 
+       It allows passwords with embedded spaces. 
+       Mike McCauley mikem@open.com.au
+       Added Makefile.solaris for Solaris 2.5.1
+1.03: - Fixes for Solaris(2.5)
+       (UINT4 *)ptr = htonln(nas_ipaddr) causes a coredumps in Solaris.
+       This works better:
+         nip=htonl(nas_ipaddr);
+         memcpy(prt, nip, 4)
+      - Also portno is changed in this fashion.
+
+1.02: - Pre release (various fixes)
+1.01: - various bug fixes
diff --git a/helpers/basic_auth/squid_radius_auth/Make.inc b/helpers/basic_auth/squid_radius_auth/Make.inc
new file mode 100644 (file)
index 0000000..a231b65
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Makefile     RADIUS authentifications for squid
+#
+#
+
+PREFIX  = /usr/local/squid
+BINDIR = $(PREFIX)/libexec/
+MANDIR  = $(PREFIX)/man/man8
+MANEXT = .8
+CONFDIR  = $(PREFIX)/etc
+
+INCLUDES       = radius.h md5.h
+
+ALL:   squid_radius_auth
+
+
+attrprint.o: attrprint.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c attrprint.c
+
+dict.o: dict.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c dict.c
+
+util.o: util.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c util.c
+
+squid_radius_auth: squid_rad_auth.o md5.o util.o
+       $(CC) $(LDFLAGS) -o squid_radius_auth squid_rad_auth.o md5.o util.o $(LIBS)
+
+squid_radius_auth.o: squid_rad_auth.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c squid_rad_auth.c
+
+md5.o: md5.c md5.h
+       $(CC) $(CFLAGS) -c md5.c
+
+clean:
+       rm -f *.o squid_radius_auth
+
+install: squid_radius_auth
+       mkdir -p $(DESTDIR)$(BINDIR)
+       install -m 755 -s squid_radius_auth $(DESTDIR)$(BINDIR)/squid_radius_auth
+       mkdir -p $(DESTDIR)$(MANDIR)
+       install -m 755 squid_radius_auth.8 $(DESTDIR)$(MANDIR)/squid_radius_auth$(MANEXT)
+       mkdir -p $(DESTDIR)$(CONFDIR)
+       install -m 644 etc/squid_radius_auth.conf $(DESTDIR)$(CONFDIR)/squid_radius_auth.conf.default
+       if ! test -f $(DESTDIR)$(CONFDIR)/squid_radius_auth.conf; then \
+           cp -p $(DESTDIR)$(CONFDIR)/squid_radius_auth.conf.default $(DESTDIR)$(CONFDIR)/squid_radius_auth.conf; \
+       fi
+
+
diff --git a/helpers/basic_auth/squid_radius_auth/Makefile.am b/helpers/basic_auth/squid_radius_auth/Makefile.am
new file mode 100644 (file)
index 0000000..bcd6033
--- /dev/null
@@ -0,0 +1,18 @@
+#
+#  Makefile for the Squid LDAP authentication helper
+#
+#  $Id: Makefile.am,v 1.1 2007/06/25 11:02:35 hno Exp $
+#
+#  Uncomment and customize the following to suit your needs:
+#
+
+libexec_PROGRAMS       = squid_radius_auth
+man_MANS               = squid_radius_auth.8
+EXTRA_DIST             = squid_radius_auth.8
+squid_radius_auth_SOURCES = \
+                       squid_rad_auth.c \
+                       md5.c md5.h \
+                       radius.h \
+                       util.c util.h
+
+LDADD = $(XTRA_LIBS)
diff --git a/helpers/basic_auth/squid_radius_auth/Makefile.default b/helpers/basic_auth/squid_radius_auth/Makefile.default
new file mode 100644 (file)
index 0000000..93072d9
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile RADIUS authentifications for squid & Linux (2.0.x, lib5 or libc6)
+#
+#
+
+CC     = gcc
+CFLAGS = -O2 -Wall -g
+LDFLAGS        = -g
+LIBS   = 
+
+include Make.inc
diff --git a/helpers/basic_auth/squid_radius_auth/Makefile.in b/helpers/basic_auth/squid_radius_auth/Makefile.in
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/helpers/basic_auth/squid_radius_auth/Makefile.solaris b/helpers/basic_auth/squid_radius_auth/Makefile.solaris
new file mode 100644 (file)
index 0000000..a33a2ee
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile RADIUS authentifications for squid & Solaris 2.5.1
+#
+#
+
+CC     = gcc
+CFLAGS = -O2 -Wall -g
+LDFLAGS        = -g
+LIBS   = -lsocket -lnsl
+
+include Make.inc
diff --git a/helpers/basic_auth/squid_radius_auth/README b/helpers/basic_auth/squid_radius_auth/README
new file mode 100644 (file)
index 0000000..2c62542
--- /dev/null
@@ -0,0 +1,72 @@
+Squid_radius_auth V1.09
+
+This kit is loosely based on radtest from the Cistron-radiusd which
+again is based on Livingston sources. See COPYRIGHT for details.
+
+This authenticator is specifically made for Squid-2.5 and later.
+
+Installation:
+
+Copy the correct makefile to Makefile
+   Makefile.default = Most OS:es.
+   Makefile.solaris = SunOS5 (Solaris)
+
+cp Makefile.default Makefile   
+make clean
+make install
+
+or if you want the helper installed elsewhere than /usr/local/squid
+(the default installation path of Squid-2.5) use something like:
+
+make CONFDIR=/etc PREFIX=/usr BINDIR='${PREFIX}/libexec/squid' install
+
+Complete list of make options for tweakin the installation paths:
+
+  PREFIX   Top level installation directory (/usr/local/squid)
+  BINDIR   Where the binary is installed (PREFIX/libexec)
+  CONFDIR  Where the configuration file is installed (PREFIX/etc)
+  MANDIR   Where the manpage is installed (PREFIX/man/man8)
+  MANEXT   Manpage extension (.8)
+  DESTDIR  Root prefix for packaging
+
+
+Configuration:
+
+The RADIUS authenticator is configured using a small configuration file.
+
+The configuration file should look like this:
+# squid_rad_auth configuration file
+# MvS: 28-10-1998
+server suncone.cistron.nl
+secret testje
+
+An example can be found in etc/squid_rad_auth.conf 
+
+
+/etc/services:
+
+Modify /etc/services and add:
+radius          1812/udp
+
+Adding this is not mandatory because it used the default port 1812 anyway.
+
+Note: Some old RADIUS servers uses the unofficial port 1645, and you may
+need to override the service port used either by editing /etc/services
+or by specifying the port using the -p command line option or the port
+tag in squid_rad_auth.conf
+
+
+Test it:
+
+Start squid_rad_auth and type a username and a username. The authenticator
+returns OK if the radiusd accepted your password. In any other case you'll
+get ERR.
+
+
+Squid:
+
+Add the authenticator to squid.conf. See the instructions from squid for
+help.
+
+Marc van Selm <selm@cistron.nl>
+Henrik Nordstrom <hno@squid-cache.org>
diff --git a/helpers/basic_auth/squid_radius_auth/md5.c b/helpers/basic_auth/squid_radius_auth/md5.c
new file mode 100644 (file)
index 0000000..d68ef5a
--- /dev/null
@@ -0,0 +1,333 @@
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+static void Encode PROTO_LIST
+  ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+  ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context;                                        /* context */
+{
+  context->count[0] = context->count[1] = 0;
+  /* Load magic initialization constants.
+*/
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+  operation, processing another message block, and updating the
+  context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context;                                        /* context */
+unsigned char *input;                                /* input block */
+unsigned int inputLen;                     /* length of input block */
+{
+  unsigned int i, index, partLen;
+
+  /* Compute number of bytes mod 64 */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+   < ((UINT4)inputLen << 3))
+ context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+
+  partLen = 64 - index;
+
+  /* Transform as many times as possible.
+*/
+  if (inputLen >= partLen) {
+ MD5_memcpy
+   ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+   MD5Transform (context->state, &input[i]);
+
+ index = 0;
+  }
+  else
+ i = 0;
+
+  /* Buffer remaining input */
+  MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+  inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+  the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16];                         /* message digest */
+MD5_CTX *context;                                       /* context */
+{
+  unsigned char bits[8];
+  unsigned int index, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+*/
+  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (index < 56) ? (56 - index) : (120 - index);
+  MD5Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  /* Store state in digest */
+  Encode (digest, context->state, 16);
+
+  /* Zeroize sensitive information.
+*/
+  MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information.
+*/
+  MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+  a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+  a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+   (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+  unsigned int i;
+
+  for (i = 0; i < len; i++)
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+  unsigned int i;
+
+  for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
diff --git a/helpers/basic_auth/squid_radius_auth/md5.h b/helpers/basic_auth/squid_radius_auth/md5.h
new file mode 100644 (file)
index 0000000..2162473
--- /dev/null
@@ -0,0 +1,77 @@
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+  function argument prototyping.
+  The following makes PROTOTYPES default to 0 if it has not already
+  been defined with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#  if __STDC__
+#    define PROTOTYPES 1
+#  else
+#    define PROTOTYPES 0
+#  endif
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+#if defined(__alpha) && (defined(__osf__) || defined(__linux__))
+typedef unsigned int UINT4;
+#else
+typedef unsigned long int UINT4;
+#endif
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+  returns an empty list.
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* MD5 context. */
+typedef struct {
+  UINT4 state[4];                                   /* state (ABCD) */
+  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+  ((MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+void md5_calc PROTO_LIST ((unsigned char *output, unsigned char *input, unsigned int inlen));
+
diff --git a/helpers/basic_auth/squid_radius_auth/radius.h b/helpers/basic_auth/squid_radius_auth/radius.h
new file mode 100644 (file)
index 0000000..359f6c2
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *
+ *     RADIUS
+ *     Remote Authentication Dial In User Service
+ *
+ *
+ *     Livingston Enterprises, Inc.
+ *     6920 Koll Center Parkway
+ *     Pleasanton, CA   94566
+ *
+ *     Copyright 1992 Livingston Enterprises, Inc.
+ *
+ *     Permission to use, copy, modify, and distribute this software for any
+ *     purpose and without fee is hereby granted, provided that this
+ *     copyright and permission notice appear on all copies and supporting
+ *     documentation, the name of Livingston Enterprises, Inc. not be used
+ *     in advertising or publicity pertaining to distribution of the
+ *     program without specific prior permission, and notice be given
+ *     in supporting documentation that copying and distribution is by
+ *     permission of Livingston Enterprises, Inc.   
+ *
+ *     Livingston Enterprises, Inc. makes no representations about
+ *     the suitability of this software for any purpose.  It is
+ *     provided "as is" without express or implied warranty.
+ *
+ */
+
+/*
+ *     @(#)radius.h    2.0  03-Aug-1996
+ */
+
+#define AUTH_VECTOR_LEN                16
+#define AUTH_PASS_LEN          16
+#define AUTH_STRING_LEN                128     /* maximum of 254 */
+
+
+typedef struct pw_auth_hdr {
+       u_char          code;
+       u_char          id;
+       u_short         length;
+       u_char          vector[AUTH_VECTOR_LEN];
+       u_char          data[2];
+} AUTH_HDR;
+
+#define AUTH_HDR_LEN                   20
+#define CHAP_VALUE_LENGTH              16
+
+#define PW_AUTH_UDP_PORT               1812
+#define PW_ACCT_UDP_PORT               1813
+
+#define VENDORPEC_USR                  429
+
+#define PW_TYPE_STRING                 0
+#define PW_TYPE_INTEGER                        1
+#define PW_TYPE_IPADDR                 2
+#define PW_TYPE_DATE                   3
+
+
+#define        PW_AUTHENTICATION_REQUEST       1
+#define        PW_AUTHENTICATION_ACK           2
+#define        PW_AUTHENTICATION_REJECT        3
+#define        PW_ACCOUNTING_REQUEST           4
+#define        PW_ACCOUNTING_RESPONSE          5
+#define        PW_ACCOUNTING_STATUS            6
+#define PW_PASSWORD_REQUEST            7
+#define PW_PASSWORD_ACK                        8
+#define PW_PASSWORD_REJECT             9
+#define        PW_ACCOUNTING_MESSAGE           10
+#define PW_ACCESS_CHALLENGE            11
+
+#define        PW_USER_NAME                    1
+#define        PW_PASSWORD                     2
+#define        PW_CHAP_PASSWORD                3
+#define        PW_NAS_IP_ADDRESS               4
+#define        PW_NAS_PORT_ID                  5
+#define        PW_SERVICE_TYPE                 6
+#define        PW_FRAMED_PROTOCOL              7
+#define        PW_FRAMED_IP_ADDRESS            8
+#define        PW_FRAMED_IP_NETMASK            9
+#define        PW_FRAMED_ROUTING               10
+#define        PW_FILTER_ID                    11
+#define        PW_FRAMED_MTU                   12
+#define        PW_FRAMED_COMPRESSION           13
+#define        PW_LOGIN_IP_HOST                14
+#define        PW_LOGIN_SERVICE                15
+#define        PW_LOGIN_TCP_PORT               16
+#define PW_OLD_PASSWORD                        17
+#define PW_REPLY_MESSAGE               18
+#define PW_CALLBACK_NUMBER             19
+#define PW_CALLBACK_ID                 20
+#define PW_EXPIRATION                  21
+#define PW_FRAMED_ROUTE                        22
+#define PW_FRAMED_IPXNET               23
+#define PW_STATE                       24
+#define PW_CLASS                       25
+#define PW_VENDOR_SPECIFIC             26
+#define PW_SESSION_TIMEOUT             27
+#define PW_IDLE_TIMEOUT                        28
+#define PW_CALLED_STATION_ID           30
+#define PW_CALLING_STATION_ID          31
+#define PW_NAS_ID                      32
+#define PW_PROXY_STATE                 33
+
+#define PW_ACCT_STATUS_TYPE            40
+#define PW_ACCT_DELAY_TIME             41
+#define PW_ACCT_INPUT_OCTETS           42
+#define PW_ACCT_OUTPUT_OCTETS          43
+#define PW_ACCT_SESSION_ID             44
+#define PW_ACCT_AUTHENTIC              45
+#define PW_ACCT_SESSION_TIME           46
+#define PW_ACCT_INPUT_PACKETS          47
+#define PW_ACCT_OUTPUT_PACKETS         48
+
+#define PW_CHAP_CHALLENGE              60
+#define PW_NAS_PORT_TYPE               61
+#define PW_PORT_LIMIT                  62
+#define PW_CONNECT_INFO                        77
+
+#define PW_HUNTGROUP_NAME              221
+#define PW_AUTHTYPE                    1000
+#define PW_PREFIX                      1003
+#define PW_SUFFIX                      1004
+#define PW_GROUP                       1005
+#define PW_CRYPT_PASSWORD              1006
+#define PW_CONNECT_RATE                        1007
+#define PW_USER_CATEGORY               1029
+#define PW_GROUP_NAME                  1030
+#define PW_SIMULTANEOUS_USE            1034
+#define PW_STRIP_USERNAME              1035
+#define PW_FALL_THROUGH                        1036
+#define PW_ADD_PORT_TO_IP_ADDRESS      1037
+#define PW_EXEC_PROGRAM                        1038
+#define PW_EXEC_PROGRAM_WAIT           1039
+#define PW_HINT                                1040
+#define PAM_AUTH_ATTR                  1041
+#define PW_LOGIN_TIME                  1042
+
+/*
+ *     INTEGER TRANSLATIONS
+ */
+
+/*     USER TYPES      */
+
+#define        PW_LOGIN_USER                   1
+#define        PW_FRAMED_USER                  2
+#define        PW_DIALBACK_LOGIN_USER          3
+#define        PW_DIALBACK_FRAMED_USER         4
+
+/*     FRAMED PROTOCOLS        */
+
+#define        PW_PPP                          1
+#define        PW_SLIP                         2
+
+/*     FRAMED ROUTING VALUES   */
+
+#define        PW_NONE                         0
+#define        PW_BROADCAST                    1
+#define        PW_LISTEN                       2
+#define        PW_BROADCAST_LISTEN             3
+
+/*     FRAMED COMPRESSION TYPES        */
+
+#define        PW_VAN_JACOBSEN_TCP_IP          1
+
+/*     LOGIN SERVICES  */
+
+#define        PW_TELNET                       0
+#define        PW_RLOGIN                       1
+#define        PW_TCP_CLEAR                    2
+#define        PW_PORTMASTER                   3
+
+/*     AUTHENTICATION LEVEL    */
+
+#define PW_AUTHTYPE_LOCAL              0
+#define PW_AUTHTYPE_SYSTEM             1
+#define PW_AUTHTYPE_SECURID            2
+#define PW_AUTHTYPE_CRYPT              3
+#define PW_AUTHTYPE_REJECT             4
+#define PW_AUTHTYPE_PAM                        253
+#define PW_AUTHTYPE_ACCEPT             254
+
+/*     PORT TYPES              */
+#define PW_NAS_PORT_ASYNC              0
+#define PW_NAS_PORT_SYNC               1
+#define PW_NAS_PORT_ISDN               2
+#define PW_NAS_PORT_ISDN_V120          3
+#define PW_NAS_PORT_ISDN_V110          4
+
+/*     STATUS TYPES    */
+
+#define PW_STATUS_START                        1
+#define PW_STATUS_STOP                 2
+#define PW_STATUS_ALIVE                        3
+#define PW_STATUS_ACCOUNTING_ON                7
+#define PW_STATUS_ACCOUNTING_OFF       8
+
diff --git a/helpers/basic_auth/squid_radius_auth/squid_rad_auth.c b/helpers/basic_auth/squid_radius_auth/squid_rad_auth.c
new file mode 100644 (file)
index 0000000..0db7b58
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ *      RADIUS
+ *      Remote Authentication Dial In User Service
+ *
+ *
+ *      Livingston Enterprises, Inc.
+ *      6920 Koll Center Parkway
+ *      Pleasanton, CA   94566
+ *
+ *      Copyright 1992 Livingston Enterprises, Inc.
+ *
+ *      Permission to use, copy, modify, and distribute this software for any
+ *      purpose and without fee is hereby granted, provided that this
+ *      copyright and permission notice appear on all copies and supporting
+ *      documentation, the name of Livingston Enterprises, Inc. not be used
+ *      in advertising or publicity pertaining to distribution of the
+ *      program without specific prior permission, and notice be given
+ *      in supporting documentation that copying and distribution is by
+ *      permission of Livingston Enterprises, Inc.   
+ *
+ *      Livingston Enterprises, Inc. makes no representations about
+ *      the suitability of this software for any purpose.  It is
+ *      provided "as is" without express or implied warranty.
+ *
+ * The new parts of the code is Copyright (C) 1998 R.M. van Selm <selm@cistron.nl>
+ * with modifications
+ *      Copyright (C) 2004 Henrik Nordstrom <hno@squid-cache.org>
+ *      Copyright (C) 2006 Henrik Nordstrom <hno@squid-cache.org>
+ */
+
+/* Squid_rad_auth is a RADIUS authenticator for Squid-2.5 and later.
+ * The authenticator reads a line with a user and password combination.
+ * If access is granted OK is returned. Else ERR.
+ *
+ * Squid_rad_auth-1.0 is based on modules from the Cistron-radiusd-1.5.4.
+ *
+ * Currently you should only start 1 authentificator at a time because the
+ * the ID's of the different programs can start to conflict. I'm not sure it
+ * would help anyway. I think the RADIUS server is close by and I don't think
+ * it will handle requests in parallel anyway (correct me if I'm wrong here)
+ *
+ * Marc van Selm <selm@cistron.nl>
+ * with contributions from
+ * Henrik Nordstrom <hno@squid-cache.org>
+ * and many others
+ */
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <netinet/in.h>
+#include       <sys/time.h>
+#include       <unistd.h>
+#include       <fcntl.h>
+
+#include       <ctype.h>
+#include       <stdio.h>
+#include       <unistd.h>
+#include       <netdb.h>
+#include       <pwd.h>
+#include       <stdlib.h>
+#include       <time.h>
+#include       <string.h>
+
+#include       "md5.h"
+#include       "radius.h"
+#include       "util.h"
+
+#define MAXPWNAM       254
+#define MAXPASS                254
+#define MAXLINE         254
+
+
+static int i_send_buffer[2048];
+static int i_recv_buffer[2048];
+static char *send_buffer = (char *) i_send_buffer;
+static char *recv_buffer = (char *) i_recv_buffer;
+static int sockfd;
+static int request_id;
+static char vector[AUTH_VECTOR_LEN];
+static char secretkey[MAXPASS + 1] = "";
+static char server[MAXLINE] = "";
+static char identifier[MAXLINE] = "";
+static char svc_name[MAXLINE] = "radius";
+static int nasport = 111;
+static int nasporttype = 0;
+static UINT4 nas_ipaddr;
+static UINT4 auth_ipaddr;
+static int retries = 30;
+
+char *progname = "squid_rad_auth";
+int debug_flag = 0;
+
+/*
+ *    Diff two timeval, b - a
+ */
+static int
+timeval_diff(const struct timeval *a, const struct timeval *b)
+{
+    return (b->tv_sec - a->tv_sec) * 1000000 + (b->tv_usec - a->tv_usec);
+}
+
+/*
+ *    Time since a timeval
+ */
+static int
+time_since(const struct timeval *when)
+{
+    struct timeval now;
+    gettimeofday(&now, NULL);
+    return timeval_diff(when, &now);
+}
+
+/*
+ *    Receive and verify the result.
+ */
+static int
+result_recv(UINT4 host, u_short udp_port, char *buffer, int length)
+{
+    AUTH_HDR *auth;
+    int totallen;
+    unsigned char reply_digest[AUTH_VECTOR_LEN];
+    unsigned char calc_digest[AUTH_VECTOR_LEN];
+    int secretlen;
+    /* VALUE_PAIR   *req; */
+
+    auth = (AUTH_HDR *) buffer;
+    totallen = ntohs(auth->length);
+
+    if (totallen != length) {
+       fprintf(stderr,
+           "Squid_rad_auth: Received invalid reply length from server (want %d/ got %d)\n",
+           totallen, length);
+       return -1;
+    }
+
+    if (auth->id != request_id) {
+       /* Duplicate response of an earlier query, ignore */
+       return -1;
+    }
+
+    /* Verify the reply digest */
+    memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);
+    memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
+    secretlen = strlen(secretkey);
+    memcpy(buffer + length, secretkey, secretlen);
+    md5_calc(calc_digest, (unsigned char *) auth, length + secretlen);
+
+    if (memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {
+       fprintf(stderr, "Warning: Received invalid reply digest from server\n");
+       return -1;
+    }
+
+    if (auth->code != PW_AUTHENTICATION_ACK)
+       return 1;
+
+    return 0;
+}
+
+
+/*
+ *    Generate a random vector.
+ */
+static void
+random_vector(char *vector)
+{
+    int randno;
+    int i;
+
+    srand((time(0) ^ rand()) + rand());
+    for (i = 0; i < AUTH_VECTOR_LEN;) {
+       randno = rand();
+       memcpy(vector, &randno, sizeof(int));
+       vector += sizeof(int);
+       i += sizeof(int);
+    }
+}
+
+/* read the config file
+ * The format should be something like:
+ * # squid_rad_auth configuration file
+ * # MvS: 28-10-1998
+ * server suncone.cistron.nl
+ * secret testje
+ */
+static int
+rad_auth_config(const char *cfname)
+{
+    FILE *cf;
+    char line[MAXLINE];
+    int srv = 0, crt = 0;
+
+    if ((cf = fopen(cfname, "r")) == NULL) {
+       perror(cfname);
+       return -1;
+    }
+    while (fgets(line, MAXLINE, cf) != NULL) {
+       if (!memcmp(line, "server", 6))
+           srv = sscanf(line, "server %s", server);
+       if (!memcmp(line, "secret", 6))
+           crt = sscanf(line, "secret %s", secretkey);
+       if (!memcmp(line, "identifier", 10))
+           sscanf(line, "identifier %s", identifier);
+       if (!memcmp(line, "service", 7))
+           sscanf(line, "service %s", svc_name);
+       if (!memcmp(line, "port", 4))
+           sscanf(line, "port %s", svc_name);
+    }
+    if (srv && crt)
+       return 0;
+    return -1;
+}
+
+static void
+urldecode(char *dst, const char *src, int size)
+{
+    char tmp[3];
+    tmp[2] = '\0';
+    while (*src && size > 1) {
+       if (*src == '%' && src[1] != '\0' && src[2] != '\0') {
+           src++;
+           tmp[0] = *src++;
+           tmp[1] = *src++;
+           *dst++ = strtol(tmp, NULL, 16);
+       } else {
+           *dst++ = *src++;
+       }
+       size--;
+    }
+    *dst++ = '\0';
+}
+
+static int
+authenticate(int sockfd, const char *username, const char *passwd)
+{
+    AUTH_HDR *auth;
+    u_short total_length;
+    u_char *ptr;
+    int length;
+    char passbuf[MAXPASS];
+    u_char md5buf[256];
+    int secretlen;
+    u_char cbc[AUTH_VECTOR_LEN];
+    int i, j;
+    UINT4 ui;
+    struct sockaddr_in saremote;
+    fd_set readfds;
+    socklen_t salen;
+    int retry = retries;
+
+    /*
+     *    Build an authentication request
+     */
+    auth = (AUTH_HDR *) send_buffer;
+    auth->code = PW_AUTHENTICATION_REQUEST;
+    auth->id = ++request_id;
+    random_vector(vector);
+    memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
+    total_length = AUTH_HDR_LEN;
+    ptr = auth->data;
+
+    /*
+     *    User Name
+     */
+    *ptr++ = PW_USER_NAME;
+    length = strlen(username);
+    if (length > MAXPWNAM) {
+       length = MAXPWNAM;
+    }
+    *ptr++ = length + 2;
+    memcpy(ptr, username, length);
+    ptr += length;
+    total_length += length + 2;
+
+    /*
+     *    Password
+     */
+    length = strlen(passwd);
+    if (length > MAXPASS) {
+       length = MAXPASS;
+    }
+    memset(passbuf, 0, MAXPASS);
+    memcpy(passbuf, passwd, length);
+
+    /* 
+     * Length is rounded up to multiple of 16,
+     * and the password is encoded in blocks of 16 
+     * with cipher block chaining
+     */
+    length = ((length / AUTH_VECTOR_LEN) + 1) * AUTH_VECTOR_LEN;
+
+    *ptr++ = PW_PASSWORD;
+    *ptr++ = length + 2;
+
+    secretlen = strlen(secretkey);
+    /* Set up the Cipher block chain */
+    memcpy(cbc, auth->vector, AUTH_VECTOR_LEN);
+    for (j = 0; j < length; j += AUTH_VECTOR_LEN) {
+       /* Calculate the MD5 Digest */
+       strcpy((char *)md5buf, secretkey);
+       memcpy(md5buf + secretlen, cbc, AUTH_VECTOR_LEN);
+       md5_calc(cbc, md5buf, secretlen + AUTH_VECTOR_LEN);
+
+       /* Xor the password into the MD5 digest */
+       for (i = 0; i < AUTH_VECTOR_LEN; i++) {
+           *ptr++ = (cbc[i] ^= passbuf[j + i]);
+       }
+    }
+    total_length += length + 2;
+
+    *ptr++ = PW_NAS_PORT_ID;
+    *ptr++ = 6;
+
+    ui = htonl(nasport);
+    memcpy(ptr, &ui, 4);
+    ptr += 4;
+    total_length += 6;
+
+    *ptr++ = PW_NAS_PORT_TYPE;
+    *ptr++ = 6;
+
+    ui = htonl(nasporttype);
+    memcpy(ptr, &ui, 4);
+    ptr += 4;
+    total_length += 6;
+
+    if (*identifier) {
+       int len = strlen(identifier);
+       *ptr++ = PW_NAS_ID;
+       *ptr++ = len + 2;
+       memcpy(ptr, identifier, len);
+       ptr += len;
+    } else {
+       *ptr++ = PW_NAS_IP_ADDRESS;
+       *ptr++ = 6;
+
+       ui = htonl(nas_ipaddr);
+       memcpy(ptr, &ui, 4);
+       ptr += 4;
+       total_length += 6;
+    }
+
+    /* Klaus Weidner <kw@w-m-p.com> changed this
+     * from htonl to htons. It might have caused
+     * you trouble or not. That depends on the byte
+     * order of your system.
+     * The symptom was that the radius server
+     * ignored the requests, because they had zero 
+     * length according to the data header.
+     */
+    auth->length = htons(total_length);
+
+    while(retry--) {
+       int time_spent;
+       struct timeval sent;
+       /*
+        *    Send the request we've built.
+        */
+       gettimeofday(&sent, NULL);
+       send(sockfd, (char *) auth, total_length, 0);
+       while ((time_spent = time_since(&sent)) < 1000000) {
+           struct timeval tv;
+           int rc, len;
+           if (!time_spent) {
+               tv.tv_sec = 1;
+               tv.tv_usec = 0;
+           } else {
+               tv.tv_sec = 0;
+               tv.tv_usec = 1000000 - time_spent;
+           }
+           FD_ZERO(&readfds);
+           FD_SET(sockfd, &readfds);
+           if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0)     /* Select timeout */
+               break;
+           salen = sizeof(saremote);
+           len = recvfrom(sockfd, recv_buffer, sizeof(i_recv_buffer),
+               0, (struct sockaddr *) &saremote, &salen);
+
+           if (len < 0)
+               continue;
+
+           rc = result_recv(saremote.sin_addr.s_addr, saremote.sin_port, recv_buffer, len);
+           if (rc == 0)
+               return 1;
+           if (rc == 1)
+               return 0;
+       }
+    }
+
+    fprintf(stderr, "%s: No response from RADIUS server\n", progname);
+
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    struct sockaddr_in salocal;
+    struct sockaddr_in saremote;
+    struct servent *svp;
+    u_short svc_port;
+    char username[MAXPWNAM];
+    char passwd[MAXPASS];
+    char *ptr;
+    char authstring[MAXLINE];
+    const char *cfname = NULL;
+    int err = 0;
+    socklen_t salen;
+    int c;
+
+    while ((c = getopt(argc, argv, "h:p:f:w:i:t:")) != -1) {
+       switch(c) {
+       case 'f':
+           cfname = optarg;
+           break;
+       case 'h':
+           strcpy(server, optarg);
+           break;
+       case 'p':
+           strcpy(svc_name, optarg);
+           break;
+       case 'w':
+           strcpy(secretkey, optarg);
+           break;
+       case 'i':
+           strcpy(identifier, optarg);
+           break;
+       case 't':
+           retries = atoi(optarg);
+           break;
+       }
+    }
+    /* make standard output line buffered */
+    if (setvbuf(stdout, NULL, _IOLBF, 0) != 0)
+       return 1;
+
+    if (cfname) {
+       if (rad_auth_config(cfname) < 0) {
+           fprintf(stderr, "%s: can't open configuration file '%s'.\n", argv[0], cfname);
+           exit(1);
+       }
+    }
+
+    if (!*server) {
+       fprintf(stderr, "%s: Server not specified\n", argv[0]);
+       exit(1);
+    }
+
+    if (!*secretkey) {
+       fprintf(stderr, "%s: Shared secret not specified\n", argv[0]);
+       exit(1);
+    }
+
+    /*
+     *    Open a connection to the server.
+     */
+    svp = getservbyname(svc_name, "udp");
+    if (svp != NULL)
+       svc_port = ntohs((u_short) svp->s_port);
+    else
+       svc_port = atoi(svc_name);
+    if (svc_port == 0)
+       svc_port = PW_AUTH_UDP_PORT;
+
+    /* Get the IP address of the authentication server */
+    if ((auth_ipaddr = get_ipaddr(server)) == 0) {
+       fprintf(stderr, "Couldn't find host %s\n", server);
+       exit(1);
+    }
+    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sockfd < 0) {
+       perror("socket");
+       exit(1);
+    }
+    memset(&saremote, 0, sizeof(saremote));
+    saremote.sin_family = AF_INET;
+    saremote.sin_addr.s_addr = htonl(auth_ipaddr);
+    saremote.sin_port = htons(svc_port);
+
+    if (connect(sockfd, (struct sockaddr *) &saremote, sizeof(saremote)) < 0) {
+       perror("connect");
+       exit(1);
+    }
+    salen = sizeof(salocal);
+    if (getsockname(sockfd, (struct sockaddr *) &salocal, &salen) < 0) {
+       perror("getsockname");
+       exit(1);
+    }
+#ifdef O_NONBLOCK
+    fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
+#endif
+    nas_ipaddr = ntohl(salocal.sin_addr.s_addr);
+    while (fgets(authstring, MAXLINE, stdin) != NULL) {
+       char *end;
+       /* protect me form to long lines */
+       if ((end = strchr(authstring, '\n')) == NULL) {
+           err = 1;
+           continue;
+       }
+       if (err) {
+           printf("ERR\n");
+           err = 0;
+           continue;
+       }
+       if (strlen(authstring) > MAXLINE) {
+           printf("ERR\n");
+           continue;
+       }
+       /* Strip off the trailing newline */
+       *end = '\0';
+
+       /* Parse out the username and password */
+       ptr = authstring;
+       while (isspace(*ptr))
+           ptr++;
+       if ((end = strchr(ptr, ' ')) == NULL) {
+           printf("ERR\n");    /* No password */
+           continue;
+       }
+       *end = '\0';
+       urldecode(username, ptr, MAXPWNAM);
+       ptr = end + 1;
+       while (isspace(*ptr))
+           ptr++;
+       urldecode(passwd, ptr, MAXPASS);
+
+       if (authenticate(sockfd, username, passwd))
+           printf("OK\n");
+       else
+           printf("ERR\n");
+    }
+    close(sockfd);
+    exit(1);
+}
diff --git a/helpers/basic_auth/squid_radius_auth/squid_radius_auth.8 b/helpers/basic_auth/squid_radius_auth/squid_radius_auth.8
new file mode 100644 (file)
index 0000000..c381873
--- /dev/null
@@ -0,0 +1,88 @@
+.TH squid_radius_auth 8 "7 August 2004" "Squid RADIUS Auth"
+.
+.SH NAME
+squid_radius_auth - Squid RADIUS authentication helper
+.
+.SH SYNOPSIS
+.B squid_radius_auth
+-f configfile
+.br
+.B squid_radius_auth
+-h "server" [-p port] [-i identifier] -w secret
+.
+.SH DESCRIPTION
+This helper allows Squid to connect to a RADIUS server to
+validate the user name and password of Basic HTTP authentication.
+.
+.TP
+.BI "-f " "configfile "
+Specifies the path to a configuration file. See the CONFIGURATION section
+for details.
+.
+.TP
+.BI "-h " server
+Alternative method of specifying the server to connect to
+.
+.TP
+.BI "-p " port
+Specify another server port where the RADIUS server listens for requests
+if different from the default RADIUS port.  Normally not specified.
+.
+.TP
+.BI "-i " identifier
+Unique identifier identifying this Squid proxy to the RADIUS server.
+If not specified the IP address is used as to identify the proxy.
+.TP
+.BI "-w " secret
+Alternative method of specifying the shared secret. Using the
+configuration file is generally more secure and recommended.
+.
+.TP
+.BI "-t " timeout
+RADIUS request timeout. Default 10 seconds.
+.
+.SH CONFIGURATION
+The configuration specifies how the helper connects to RADIUS.
+The file contains a list of directives (one per line). Lines
+beginning with a # is ignored.
+.
+.TP
+.BI "server " radiusserver
+specifies the name or address of the RADIUS server to connect to.
+.
+.TP
+.BI "secret " somesecretstring
+specifies the shared RADIUS secret.
+.
+.TP
+.BI "identifier " nameofserver
+specifies what the proxy should identify itsels as to the RADIUS server.
+This directive is optional.
+.
+.TP
+.BI "port " portnumber
+Specifies the port number or service name where the helper should connect.
+.SH AUTHOR
+This manual page was written by 
+.I Henrik Nordstrom <hno@squid-cache.org>
+.P
+squid_radius_auth is written by 
+.I Marc van Selm <selm@cistron.nl>
+with contributions from
+.I Henrik Nordstrom <hno@squid-cache.org>
+and many others
+.
+.SH QUESTIONS
+Any questions on usage can be sent to 
+.IR "Squid Users <squid-users@squid-cache.org>" ,
+or to your favorite RADIUS list/friend if the question is more related to
+RADIUS than Squid.
+.
+.SH REPORTING BUGS
+Report bugs or bug-fixes to
+.I Squid Bugs <squid-bugs@squid-cache.org>
+or ideas for new improvements to 
+.I Squid Developers <squid-dev@squid-cache.org>
+.
+.SH "SEE ALSO"
+.BR RFC2058 " - Remote Authentication Dial In User Service (RADIUS)"
diff --git a/helpers/basic_auth/squid_radius_auth/util.c b/helpers/basic_auth/squid_radius_auth/util.c
new file mode 100644 (file)
index 0000000..3ee530d
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *
+ *     RADIUS
+ *     Remote Authentication Dial In User Service
+ *
+ *
+ *     Livingston Enterprises, Inc.
+ *     6920 Koll Center Parkway
+ *     Pleasanton, CA   94566
+ *
+ *     Copyright 1992 Livingston Enterprises, Inc.
+ *     Copyright 1997 Cistron Internet Services B.V.
+ *
+ *     Permission to use, copy, modify, and distribute this software for any
+ *     purpose and without fee is hereby granted, provided that this
+ *     copyright and permission notice appear on all copies and supporting
+ *     documentation, the name of Livingston Enterprises, Inc. not be used
+ *     in advertising or publicity pertaining to distribution of the
+ *     program without specific prior permission, and notice be given
+ *     in supporting documentation that copying and distribution is by
+ *     permission of Livingston Enterprises, Inc.   
+ *
+ *     Livingston Enterprises, Inc. makes no representations about
+ *     the suitability of this software for any purpose.  It is
+ *     provided "as is" without express or implied warranty.
+ *
+ */
+
+/*
+ * util.c      Miscellanous generic functions.
+ *
+ */
+
+char util_sccsid[] =
+"@(#)util.c    1.5 Copyright 1992 Livingston Enterprises Inc\n"
+"              2.1 Copyright 1997 Cistron Internet Services B.V.";
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <netdb.h>
+#include       <pwd.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <signal.h>
+
+#include       "md5.h"
+#include       "util.h"
+
+/*
+ *     Check for valid IP address in standard dot notation.
+ */
+static int good_ipaddr(char *addr)
+{
+       int     dot_count;
+       int     digit_count;
+
+       dot_count = 0;
+       digit_count = 0;
+       while(*addr != '\0' && *addr != ' ') {
+               if(*addr == '.') {
+                       dot_count++;
+                       digit_count = 0;
+               }
+               else if(!isdigit(*addr)) {
+                       dot_count = 5;
+               }
+               else {
+                       digit_count++;
+                       if(digit_count > 3) {
+                               dot_count = 5;
+                       }
+               }
+               addr++;
+       }
+       if(dot_count != 3) {
+               return(-1);
+       }
+       else {
+               return(0);
+       }
+}
+
+/*
+ *     Return an IP address in host long notation from
+ *     one supplied in standard dot notation.
+ */
+static UINT4 ipstr2long(char *ip_str)
+{
+       char    buf[6];
+       char    *ptr;
+       int     i;
+       int     count;
+       UINT4   ipaddr;
+       int     cur_byte;
+
+       ipaddr = (UINT4)0;
+       for(i = 0;i < 4;i++) {
+               ptr = buf;
+               count = 0;
+               *ptr = '\0';
+               while(*ip_str != '.' && *ip_str != '\0' && count < 4) {
+                       if(!isdigit(*ip_str)) {
+                               return((UINT4)0);
+                       }
+                       *ptr++ = *ip_str++;
+                       count++;
+               }
+               if(count >= 4 || count == 0) {
+                       return((UINT4)0);
+               }
+               *ptr = '\0';
+               cur_byte = atoi(buf);
+               if(cur_byte < 0 || cur_byte > 255) {
+                       return((UINT4)0);
+               }
+               ip_str++;
+               ipaddr = ipaddr << 8 | (UINT4)cur_byte;
+       }
+       return(ipaddr);
+}
+
+/*
+ *     Return an IP address in host long notation from a host
+ *     name or address in dot notation.
+ */
+UINT4 get_ipaddr(char *host)
+{
+       struct hostent  *hp;
+
+       if(good_ipaddr(host) == 0) {
+               return(ipstr2long(host));
+       }
+       else if((hp = gethostbyname(host)) == (struct hostent *)NULL) {
+               return((UINT4)0);
+       }
+       return(ntohl(*(UINT4 *)hp->h_addr));
+}
+
+
+void md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen)
+{
+       MD5_CTX context;
+
+       MD5Init(&context);
+       MD5Update(&context, input, inlen);
+       MD5Final(output, &context);
+}
+
diff --git a/helpers/basic_auth/squid_radius_auth/util.h b/helpers/basic_auth/squid_radius_auth/util.h
new file mode 100644 (file)
index 0000000..b8e3385
--- /dev/null
@@ -0,0 +1,2 @@
+/* util.c */
+UINT4          get_ipaddr (char *);