I want to contribute a module a just wrote for FreeRadius:
rlm_pre_proxy_pap2chap allows FreeRadius to receive a PAP authorization request and forwards it to a remote RADIUS server using the CHAP protocol.
The PAP to CHAP convertion is usefull in the cases where the remote RADIUS server doesn't accept PAP or it's incovenient to use it. For example, the Novell RADIUS server accepts PAP or CHAP authentication requests but the user must provide a different password for each kind of request. (http://support.novell.com/cgi-bin/search/searchtid.cgi?/10063812.htm).
Of course someone may configure the NAS to accept just CHAP, but it will annoy users who have not enabled or can't enable their machines to authenticate using CHAP.
Comments are welcomed.
Regards,
Carlos Henrique Bauer
Patche for freeradius-0.9.1
diff -urN freeradius-0.9.1-orig/doc/rlm_pre_proxy_pap2chap freeradius-0.9.1/doc/rlm_pre_proxy_pap2chap
--- freeradius-0.9.1-orig/doc/rlm_pre_proxy_pap2chap 1969-12-31 21:00:00.000000000 -0300
+++ freeradius-0.9.1/doc/rlm_pre_proxy_pap2chap 2003-10-13 11:31:30.000000000 -0200
@@ -0,0 +1,47 @@
+PRE PROXY PAP TO CHAP AUTHENCATION CONVERTION module
+
+0. Introduction
+
+ rlm_pre_proxy_pap2chap allows FreeRadius to receive a PAP
+authorization request and forwards it to a remote RADIUS server
+using the CHAP protocol.
+
+ The PAP to CHAP convertion is usefull in the cases where
+the remote RADIUS server doesn't accept PAP or it's incovenient
+to use it. For example, the Novell RADIUS server accepts
+PAP or CHAP authentication requests but the user must provide
+a different password for each kind of request.
+(http://support.novell.com/cgi-bin/search/searchtid.cgi?/10063812.htm).
+
+Of course someone may configure the NAS to accept just CHAP,
+but it will annoy users who have not enabled or can't enable
+their machines to authenticate using CHAP.
+
+1. What does it do
+
+ This module intercepts an authorization request before it's
+forwarded to a remote RADIUS server, checks if it uses the PAP
+protocol and converts it to CHAP protocol.
+
+2. How should I configure it
+
+First, edit radiusd.conf file, in the 'modules' section, add the
+following subsection:
+
+ pre_proxy_pap2chap {
+ realms = realm1 realm2 realm3
+ }
+
+where realms is the list of the realms for which PAP 2 CHAP
+conversion is required.
+
+pre-proxy{} section:
+
+Add the pre_proxy_pap2chap module:
+
+Example:
+
+ pre-proxy {
+ # attr_rewrite
+ pre_proxy_pap2chap
+ }
diff -urN freeradius-0.9.1-orig/raddb/radiusd.conf.in freeradius-0.9.1/raddb/radiusd.conf.in
--- freeradius-0.9.1-orig/raddb/radiusd.conf.in 2003-08-26 09:25:40.000000000 -0300
+++ freeradius-0.9.1/raddb/radiusd.conf.in 2003-10-13 10:55:34.000000000 -0200
@@ -1334,6 +1334,10 @@
# ANSI X9.9 token support. Not included by default.
# $INCLUDE ${confdir}/x99.conf
+ + pre_proxy_pap2chap {
+ realms = realm
+ }
}
@@ -1603,6 +1607,7 @@
#
pre-proxy {
# attr_rewrite
+# pre_proxy_pap2chap
}#
diff -urN freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/config.h.in freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/config.h.in
--- freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/config.h.in 1969-12-31 21:00:00.000000000 -0300
+++ freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/config.h.in 2003-09-17 13:11:22.000000000 -0300
@@ -0,0 +1,52 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `printf' function. */
+#undef HAVE_PRINTF
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
diff -urN freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/configure.in freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/configure.in
--- freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/configure.in 1969-12-31 21:00:00.000000000 -0300
+++ freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/configure.in 2003-09-17 13:09:38.000000000 -0300
@@ -0,0 +1,50 @@
+AC_INIT(rlm_pre_proxy_pap2chap.c) +AC_REVISION($Revision: 0.1 $)
+AC_DEFUN(modname,[rlm_pre_proxy_pap2chap]) +
+if test x$with_[]modname != xno; then
+
+ AC_PROG_CC
+ AC_PROG_CPP
+
+ dnl put configuration checks here. + dnl set $fail to what's missing, on fatal errors.
+ dnl use AC_MSG_WARN() on important messages.
+ AC_CHECK_LIB(c, printf,
+ [ pre_proxy_pap2chap_ldflags="$pre_proxy_pap2chap_ldflags -lc" ],
+ [ fail=$fail" printf" ]
+ )
+
+ AC_CHECK_HEADER(stdio.h,
+ [ pre_proxy_pap2chap_cflags="$pre_proxy_pap2chap_cflags -I/usr/include" ],
+ [ fail=$fail" stdio.h" ]
+ )
+
+ AC_CHECK_HEADERS(stdio.h stdlib.h) # for the config.h defs
+ AC_CHECK_FUNCS(printf) # for the config.h defs
+
+ targetname=modname # keep this! Don't change!
+else
+ targetname= # keep this! Don't change!
+ echo \*\*\* module modname is disabled. # keep this! Don't change!
+fi
+
+dnl Don't change this section.
+if test x"$fail" != x""; then
+ if test x"${enable_strict_dependencies}" = x"yes"; then
+ AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
+ else
+ AC_MSG_WARN([silently not building ]modname[.])
+ AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]);
+ targetname=""
+ fi
+fi
+
+
+AC_SUBST(pre_proxy_pap2chap_cflags) +AC_SUBST(pre_proxy_pap2chap_ldflags) +
+AC_CONFIG_HEADER(config.h) # delete if you don't want a config.h file.
+
+AC_SUBST(targetname) # keep this! Don't change!
+AC_OUTPUT(Makefile) # keep this! Don't change!
diff -urN freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/Makefile.clean freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/Makefile.clean
--- freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/Makefile.clean 1969-12-31 21:00:00.000000000 -0300
+++ freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/Makefile.clean 2003-09-12 16:51:49.000000000 -0300
@@ -0,0 +1,11 @@
+TARGET = rlm_example
+SRCS = rlm_example.c other.c
+HEADERS = config.h other.h
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
diff -urN freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/Makefile.in freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/Makefile.in
--- freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+++ freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/Makefile.in 2003-09-17 13:11:04.000000000 -0300
@@ -0,0 +1,35 @@
+#######################################################################
+#
+# TARGET should be set by autoconf only. Don't touch it.
+#
+# The SRCS definition should list ALL source files.
+#
+# The HEADERS definition should list ALL header files
+#
+# RLM_CFLAGS defines addition C compiler flags. You usually don't
+# want to modify this, though. Get it from autoconf.
+#
+# The RLM_LIBS definition should list ALL required libraries.
+# These libraries really should be pulled from the 'config.mak'
+# definitions, if at all possible. These definitions are also
+# echoed into another file in ../lib, where they're picked up by
+# ../main/Makefile for building the version of the server with
+# statically linked modules. Get it from autoconf.
+#
+# RLM_INSTALL is the names of additional rules you need to install
+# some particular portion of the module. Usually, leave it blank.
+#
+#######################################################################
+TARGET = @targetname@
+SRCS = rlm_pre_proxy_pap2chap.c
+HEADERS =
+RLM_CFLAGS = @pre_proxy_pap2chap_cflags@
+RLM_LIBS = @pre_proxy_pap2chap_ldflags@
+RLM_INSTALL =
+
+## this uses the RLM_CFLAGS and RLM_LIBS and SRCS defs to make TARGET.
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
diff -urN freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/rlm_pre_proxy_pap2chap.c freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/rlm_pre_proxy_pap2chap.c
--- freeradius-0.9.1-orig/src/modules/rlm_pre_proxy_pap2chap/rlm_pre_proxy_pap2chap.c 1969-12-31 21:00:00.000000000 -0300
+++ freeradius-0.9.1/src/modules/rlm_pre_proxy_pap2chap/rlm_pre_proxy_pap2chap.c 2003-10-13 13:25:46.000000000 -0200
@@ -0,0 +1,501 @@
+/*
+ * rlm_pre_proxy_pap2chap.c + *
+ * Version: $Id: rlm_pre_proxy_pap2chap.c,v 0.0.0.1 2003/07/14 17:29:29 aland Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright 2003 The FreeRADIUS server project
+ * Copyright 2003 Carlos Henrique Bauer <[EMAIL PROTECTED]>
+ */
+
+#include "autoconf.h"
+#include "libradius.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "radiusd.h"
+#include "modules.h"
+#include "conffile.h"
+
+
+static const char rcsid[] = "$Id: rlm_pre_proxy_pap2chap.c,v 0.0.0.1 2003/07/14 17:29:29 aland Exp $";
+
+
+/**
+ * Define a element of a linked list of the realm names which
+ * require pap to chap password conversion.
+ */
+typedef struct rlm_pre_proxy_pap2chap_realm_list_t {
+
+ /* realm name */
+ char * realm;
+ + /* next realm in the list */
+ struct rlm_pre_proxy_pap2chap_realm_list_t * next;
+
+} rlm_pre_proxy_pap2chap_realm_list_t;
+
+
+/**
+ * A structure for the module configuration.
+ */
+typedef struct rlm_pre_proxy_pap2chap_config_t {
+
+ /* A string containing a list of the realms names requiring
+ pap to chap password conversion, separated by commas. */
+ char * realms;
+
+} rlm_pre_proxy_pap2chap_config_t;
+
+
+/**
+ * A mapping of configuration file names to internal variables.
+ */
+static CONF_PARSER module_config[] = {
+
+ /* A string containing a list of the realms names requiring
+ pap to chap password conversion, separated by commas. */
+ { "realms", PW_TYPE_STRING_PTR,
+ offsetof(rlm_pre_proxy_pap2chap_config_t,realms), NULL, NULL},
+
+ /* end the list */
+ { NULL, -1, 0, NULL, NULL }
+};
+
+/**
+ * Create a new element of the realms linked list.
+ */
+static rlm_pre_proxy_pap2chap_realm_list_t * rlm_pre_proxy_pap2chap_makerealm(char * name)
+{
+
+ rlm_pre_proxy_pap2chap_realm_list_t * newrealm;
+
+ /* allocate memory for the new element */
+ newrealm = rad_malloc(sizeof(*newrealm));
+
+ if(NULL == newrealm) {
+ return NULL;
+ }
+
+ /* initialize it */
+ memset(newrealm, 0, sizeof(*newrealm));
+
+ /* make a copy of the realm name */
+ if(NULL != name) {
+ newrealm->realm = strdup(name);
+ }
+
+ return newrealm;
+}
+
+/**
+ * Destroy a realm and its contents.
+ */
+static void rlm_pre_proxy_pap2chap_deleterealm(rlm_pre_proxy_pap2chap_realm_list_t * realm)
+{
+ if(NULL == realm) {
+ return;
+ }
+
+ /* free the realm name memory */
+ if(NULL != realm->realm) {
+ free(realm->realm);
+ }
+
+ /* free the realm memory */
+ free(realm);
+}
+
+/**
+ * Destroy all the elements of a linked list of realms.
+ */
+static void rlm_pre_proxy_pap2chap_deleterealmlist(rlm_pre_proxy_pap2chap_realm_list_t * first)
+{
+ rlm_pre_proxy_pap2chap_realm_list_t * cur = first;
+ rlm_pre_proxy_pap2chap_realm_list_t * next;
+
+ /* if it didn't got to the end of the list */
+ while(NULL != cur) {
+
+ /* save a pointer to the next element */
+ next = cur->next;
+
+ /* destroy the current element */
+ rlm_pre_proxy_pap2chap_deleterealm(cur);
+
+ /* go to the next */
+ cur = next;
+ } +}
+
+
+/**
+ * Add a realm to the end of a linked list of realms.
+ *
+ * Parameters:
+ *
+ * first: the first element of the linked list.
+ *
+ * new: the element will be added to the list.
+ */
+static void
+rlm_pre_proxy_pap2chap_addrealm(
+ rlm_pre_proxy_pap2chap_realm_list_t * first,
+ rlm_pre_proxy_pap2chap_realm_list_t * new)
+{
+ rlm_pre_proxy_pap2chap_realm_list_t * cur;
+
+ if(NULL == first) {
+ + /* there is no list, nothing can't be done */
+ return;
+ } + + /* find the end of the list */
+ cur = first;
+ + while(NULL != cur->next) {
+ cur = cur->next;
+ }
+
+ /* add the new element to list */
+ cur->next = new;
+}
+
+/**
+ * Given the name of a realm find it in a linked list.
+ *
+ * Parameters:
+ * + * first: the first element of the linked list.
+ *
+ * name: the name of the realm will be searched.
+ */
+static rlm_pre_proxy_pap2chap_realm_list_t *
+rlm_pre_proxy_pap2chap_findrealm(
+ rlm_pre_proxy_pap2chap_realm_list_t * first,
+ char * name) {
+ + rlm_pre_proxy_pap2chap_realm_list_t * cur;
+ + if(NULL == first) {
+ + /* there's no linked list, nothing can't be done */
+ return NULL;
+ }
+
+ /* start the search */
+ cur = first;
+
+ /* if it didn't got to the end of the list */
+ while(NULL != cur) {
+ + /* if it found the realm, stop the search */
+ if(!(NULL == cur->realm || strcmp(cur->realm, name))) {
+ break;
+ }
+ + /* go to the next element in the list */
+ cur = cur->next;
+ }
+ + return cur;
+}
+
+
+/**
+ * Do any per-module initialization. e.g. set up connections
+ * to external databases, read configuration files, set up
+ * dictionary entries, etc.
+ *
+ * Try to avoid putting too much stuff in here - it's better to
+ * do it in instantiate() where it is not global.
+ */
+static int pre_proxy_pap2chap_init(void)
+{
+ /*
+ * Everything's OK, return without an error.
+ */
+ return NULL;
+}
+
+
+/**
+ * Do any per-module initialization that is separate to each
+ * configured instance of the module. e.g. set up connections
+ * to external databases, read configuration files, set up
+ * dictionary entries, etc.
+ *
+ * If configuration information is given in the config section
+ * that must be referenced in later calls, store a handle to it
+ * in *instance otherwise put a null pointer there.
+ */
+static int pre_proxy_pap2chap_instantiate(CONF_SECTION *conf, void **instance)
+{
+ rlm_pre_proxy_pap2chap_realm_list_t * data;
+ rlm_pre_proxy_pap2chap_realm_list_t * newrealm;
+ rlm_pre_proxy_pap2chap_config_t * config;
+ + char buffer[256];
+ char * ptr;
+ + DEBUG(" rlm_pre_proxy_pap2chap: instantiating module ...");
+ + config = rad_malloc(sizeof(*config));
+ + memset(config, 0, sizeof(*config));
+ + /* Set up a storage area for instance data */
+ data = rlm_pre_proxy_pap2chap_makerealm(NULL);
+ + if (!config) {
+ + radlog(L_ERR|L_CONS, "no memory");
+ + return -1;
+ }
+ + if (!data) {
+ radlog(L_ERR|L_CONS, "no memory");
+ return -1;
+ }
+ + /* If the configuration parameters can't be parsed, then fail. */
+ if (cf_section_parse(conf, config, module_config) < 0) {
+ + DEBUG(" rlm_pre_proxy_pap2chap: can't parse configuration parameters ...");
+ + rlm_pre_proxy_pap2chap_deleterealmlist(data);
+ + return -1;
+ }
+ + /* If configurations was parsed... */
+ if(NULL != config->realms) {
+ + /* create a list of realm to which the pap2chap conversion
+ * should be applied */
+ + ptr = config->realms;
+ + + while(1) {
+ + /* get a realm name from the realm list */
+ + getword(&ptr, buffer, sizeof(buffer));
+ + if(!buffer[0]) {
+ break;
+ }
+ + /* add the realm name to our list */
+ DEBUG(" rlm_pre_proxy_pap2chap: adding realm %s...", buffer);
+ + newrealm = rlm_pre_proxy_pap2chap_makerealm(buffer);
+ + if(NULL != newrealm) {
+ + rlm_pre_proxy_pap2chap_addrealm(data, newrealm);
+ } else {
+
+ /* couldn't create a realm */ + + radlog(L_ERR|L_CONS, "no memory");
+ + free(config->realms); + free(config);
+ + rlm_pre_proxy_pap2chap_deleterealmlist(data);
+ + return -1;
+ }
+ }
+ } + + /* we don't need config.realms anymore */
+ free(config->realms);
+ free(config);
+ + /* save our data for the future ... */ + *instance = data;
+ + return 0;
+}
+
+
+/**
+ * Find the named user in this modules database. Create the set
+ * of attribute-value pairs to check and reply with for this user
+ * from the database. The authentication code only needs to check
+ * the password, the rest is done here.
+ */
+static int pre_proxy_pap2chap_pre_proxy(void *instance, REQUEST *request)
+{
+ VALUE_PAIR * tmp;
+ VALUE_PAIR * realmpair;
+ + char pass_str[AUTH_VECTOR_LEN];
+ + DEBUG(" rlm_pre_proxy_pap2chap: pre-proxy processing started for %s.",
+ ((NULL != request->username->strvalue) ?
+ (char*)request->username->strvalue : (char*)"NULL"));
+ + /* was any password supplied? */
+ if (!request->password) {
+ + /* no, stop further processing */
+ return RLM_MODULE_NOOP;
+ }
+ + /* get the name of destination realm */
+ realmpair = pairfind(request->packet->vps, PW_REALM);
+
+ if(NULL == realmpair) {
+ + DEBUG(" rlm_pre_proxy_pap2chap: REALM not set, ignoring.");
+
+ return RLM_MODULE_NOOP;
+ }
+
+ /* should pap2chap conversation apply to the target realm? */
+ if(rlm_pre_proxy_pap2chap_findrealm(
+ + (rlm_pre_proxy_pap2chap_realm_list_t *) instance,
+ realmpair->strvalue)) {
+
+ DEBUG(" rlm_pre_proxy_pap2chap: pap2chap conversation "
+ "is set for realm %s, going ahead...", realmpair->strvalue);
+ } else {
+ /* no, stop further processing */
+ DEBUG( "rlm_pre_proxy_pap2chap: pap2chap conversation "
+ "is not set for realm %s, ignoring.", realmpair->strvalue);
+ + return RLM_MODULE_NOOP;
+ }
+
+ /* the supplied password is a PAP one? */
+ if (request->password->attribute != PW_PASSWORD) {
+ + /* no, we don't need convert it */
+ DEBUG(" rlm_pre_proxy_pap2chap: isn't a PAP_PASSWORD, ignoring.");
+ + return RLM_MODULE_OK;
+ }
+
+ /* the supplied password has a valid length */
+ if (request->password->length == 0) {
+ /* no, we can't go ahead */
+ + radlog(L_ERR, "rlm_pre_proxy_pap2chap: empty password supplied.");
+ return RLM_MODULE_INVALID;
+ }
+
+ /* convert the password from CHAP to CHAP */
+ DEBUG(" rlm_pre_proxy_pap2chap: converting PAP password to CHAP.");
+ DEBUG(" rlm_pre_proxy_pap2chap: PAP password received: '%s'.",
+ request->password->strvalue);
+
+ rad_chap_encode(request->packet, pass_str, request->packet->id,
+ request->password);
+
+ DEBUG(" rlm_pre_proxy_pap2chap: CHAP password created.");
+
+ /* remove the PAP password from the proxied request */
+ pairdelete(&request->proxy->vps, PW_PASSWORD);
+
+ /* create a CHAP password attribute */
+ tmp = paircreate(PW_CHAP_PASSWORD, PW_TYPE_STRING);
+ + if (!tmp) {
+ radlog(L_ERR|L_CONS, "no memory");
+ exit(1);
+ }
+ + memcpy(tmp->strvalue, pass_str, sizeof(pass_str));
+ tmp->length = sizeof(pass_str);
+ + /* add it to the proxied request */
+ pairadd(&request->proxy->vps, tmp);
+
+ DEBUG(" rlm_pre_proxy_pap2chap: CHAP challenge created.");
+
+ /* create the companion CHAP challenge */
+ + /* stolen from main/proxy.c */
+ tmp = paircreate(PW_CHAP_CHALLENGE, PW_TYPE_OCTETS);
+ + if (!tmp) {
+ + radlog(L_ERR|L_CONS, "no memory");
+ exit(1);
+ }
+
+ tmp->length = AUTH_VECTOR_LEN;
+ memcpy(tmp->strvalue, request->packet->vector, AUTH_VECTOR_LEN);
+ + /* add it to proxied request */
+ pairadd(&request->proxy->vps, tmp);
+ + return RLM_MODULE_UPDATED;
+}
+
+/**
+ * Do module cleanup. Free the memory allocated on the module
+ * initialization.
+ */
+static int pre_proxy_pap2chap_detach(void *instance)
+{
+ /* delete the linked list of the realms */
+ rlm_pre_proxy_pap2chap_deleterealmlist(instance);
+
+ /* free the module's data */
+ free(instance);
+
+ return 0;
+}
+
+
+/*
+ * The module name should be the only globally exported symbol.
+ * That is, everything else should be 'static'.
+ *
+ * If the module needs to temporarily modify it's instantiation
+ * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ * The server will then take care of ensuring that the module
+ * is single-threaded.
+ */
+module_t rlm_pre_proxy_pap2chap = {
+ "pre_proxy_pap2chap", + RLM_TYPE_THREAD_SAFE, /* type */
+ pre_proxy_pap2chap_init, /* initialization */
+ pre_proxy_pap2chap_instantiate, /* instantiation */
+ {
+ NULL, /* authentication */
+ NULL, /* authorization */
+ NULL, /* preaccounting */
+ NULL, /* accounting */
+ NULL, /* checksimul */
+ pre_proxy_pap2chap_pre_proxy, /* pre-proxy */
+ NULL, /* post-proxy */
+ NULL /* post-auth */
+ },
+ pre_proxy_pap2chap_detach, /* detach */
+ NULL, /* destroy */
+};
+
diff -urN freeradius-0.9.1-orig/src/modules/stable freeradius-0.9.1/src/modules/stable
--- freeradius-0.9.1-orig/src/modules/stable 2003-05-26 13:00:36.000000000 -0300
+++ freeradius-0.9.1/src/modules/stable 2003-09-22 12:01:53.000000000 -0300
@@ -25,3 +25,4 @@
rlm_sql
rlm_unix
rlm_x99_token
+rlm_pre_proxy_pap2chap
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
