]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 380187 â\80\93 Bugzilla should support RADIUS authentication.
authorwurblzap%gmail.com <>
Fri, 3 Aug 2007 03:38:37 +0000 (03:38 +0000)
committerwurblzap%gmail.com <>
Fri, 3 Aug 2007 03:38:37 +0000 (03:38 +0000)
Patch by Marc Schumann <wurblzap@gmail.com>;
r=mkanat, a=mkanat

14 files changed:
Bugzilla/Auth/Verify/RADIUS.pm [new file with mode: 0755]
Bugzilla/Config/Auth.pm
Bugzilla/Config/Common.pm
Bugzilla/Config/RADIUS.pm [new file with mode: 0755]
Bugzilla/Install/Requirements.pm
docs/xml/installation.xml
js/params.js [new file with mode: 0755]
skins/standard/params.css
template/en/default/admin/params/auth.html.tmpl
template/en/default/admin/params/common.html.tmpl
template/en/default/admin/params/editparams.html.tmpl
template/en/default/admin/params/radius.html.tmpl [new file with mode: 0755]
template/en/default/filterexceptions.pl
template/en/default/global/code-error.html.tmpl

diff --git a/Bugzilla/Auth/Verify/RADIUS.pm b/Bugzilla/Auth/Verify/RADIUS.pm
new file mode 100755 (executable)
index 0000000..da36c3b
--- /dev/null
@@ -0,0 +1,64 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Marc Schumann.
+# Portions created by Marc Schumann are Copyright (c) 2007 Marc Schumann.
+# All rights reserved.
+#
+# Contributor(s): Marc Schumann <wurblzap@gmail.com>
+
+package Bugzilla::Auth::Verify::RADIUS;
+use strict;
+use base qw(Bugzilla::Auth::Verify);
+
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Util;
+
+use Authen::Radius;
+
+use constant admin_can_create_account => 0;
+use constant user_can_create_account  => 0;
+
+sub check_credentials {
+    my ($self, $params) = @_;
+    my $dbh = Bugzilla->dbh;
+    my $address_suffix = Bugzilla->params->{'RADIUS_email_suffix'};
+    my $username = $params->{username};
+
+    # If we're using RADIUS_email_suffix, we may need to cut it off from
+    # the login name.
+    if ($address_suffix) {
+        $username =~ s/\Q$address_suffix\E$//i;
+    }
+
+    # Create RADIUS object.
+    my $radius =
+        new Authen::Radius(Host   => Bugzilla->params->{'RADIUS_server'},
+                           Secret => Bugzilla->params->{'RADIUS_secret'})
+        || return { failure => AUTH_ERROR, error => 'radius_preparation_error',
+                    details => {errstr => Authen::Radius::strerror() } };
+
+    # Check the password.
+    $radius->check_pwd($username, $params->{password},
+                       Bugzilla->params->{'RADIUS_NAS_IP'} || undef)
+        || return { failure => AUTH_LOGINFAILED };
+
+    # Build the user account's e-mail address.
+    $params->{bz_username} = $username . $address_suffix;
+
+    return $params;
+}
+
+1;
index 65ebc1b79b0d3db1873981c090914b90983ec81a..cbd94617a2799ecbfc788011677b8449937bc93f 100644 (file)
@@ -76,8 +76,8 @@ sub get_param_list {
 
   {
    name => 'user_verify_class',
-   type => 's',
-   choices => [ 'DB', 'LDAP', 'DB,LDAP', 'LDAP,DB' ],
+   type => 'o',
+   choices => [ 'DB', 'RADIUS', 'LDAP' ],
    default => 'DB',
    checker => \&check_user_verify_class
   },
index 188ef0c909d52553570702d4869e4bee05cdaafe..14406019ddb9a251780752135d4079c4e76f7479 100644 (file)
@@ -27,6 +27,7 @@
 #                 Joseph Heenan <joseph@heenan.me.uk>
 #                 Erik Stambaugh <erik@dasbistro.com>
 #                 Frédéric Buclin <LpSolit@gmail.com>
+#                 Marc Schumann <wurblzap@gmail.com>
 #
 
 package Bugzilla::Config::Common;
@@ -64,8 +65,8 @@ sub check_multi {
 
         return "";
     }
-    elsif ($param->{'type'} eq "m") {
-        foreach my $chkParam (@$value) {
+    elsif ($param->{'type'} eq 'm' || $param->{'type'} eq 'o') {
+        foreach my $chkParam (split(',', $value)) {
             unless (scalar(grep {$_ eq $chkParam} (@{$param->{'choices'}}))) {
                 return "Invalid choice '$chkParam' for multi-select list param '$param->{'name'}'";
             }
@@ -268,18 +269,27 @@ sub check_user_verify_class {
     # So don't do that.
 
     my ($list, $entry) = @_;
+    $list || return 'You need to specify at least one authentication mechanism';
     for my $class (split /,\s*/, $list) {
         my $res = check_multi($class, $entry);
         return $res if $res;
         if ($class eq 'DB') {
             # No params
-        } elsif ($class eq 'LDAP') {
+        }
+        elsif ($class eq 'RADIUS') {
+            eval "require Authen::Radius";
+            return "Error requiring Authen::Radius: '$@'" if $@;
+            return "RADIUS servername (RADIUS_server) is missing" unless Bugzilla->params->{"RADIUS_server"};
+            return "RADIUS_secret is empty" unless Bugzilla->params->{"RADIUS_secret"};
+        }
+        elsif ($class eq 'LDAP') {
             eval "require Net::LDAP";
             return "Error requiring Net::LDAP: '$@'" if $@;
-            return "LDAP servername is missing" unless Bugzilla->params->{"LDAPserver"};
+            return "LDAP servername (LDAPserver) is missing" unless Bugzilla->params->{"LDAPserver"};
             return "LDAPBaseDN is empty" unless Bugzilla->params->{"LDAPBaseDN"};
-        } else {
-                return "Unknown user_verify_class '$class' in check_user_verify_class";
+        }
+        else {
+            return "Unknown user_verify_class '$class' in check_user_verify_class";
         }
     }
     return "";
@@ -363,9 +373,8 @@ sub check_timezone {
 # b -- A boolean value (either 1 or 0)
 # m -- A list of values, with many selectable (shows up as a select box)
 #      To specify the list of values, make the 'choices' key be an array
-#      reference of the valid choices. The 'default' key should be an array
-#      reference for the list of selected values (which must appear in the
-#      first anonymous array), i.e.:
+#      reference of the valid choices. The 'default' key should be a string
+#      with a list of selected values (as a comma-separated list), i.e.:
 #       {
 #         name => 'multiselect',
 #         desc => 'A list of options, choose many',
@@ -381,6 +390,11 @@ sub check_timezone {
 #      &check_multi should always be used as the param verification function
 #      for list (single and multiple) parameter types.
 #
+# o -- A list of values, orderable, and with many selectable (shows up as a
+#      JavaScript-enhanced select box if JavaScript is enabled, and a text
+#      entry field if not)
+#      Set up in the same way as type m.
+#
 # s -- A list of values, with one selectable (shows up as a select box)
 #      To specify the list of values, make the 'choices' key be an array
 #      reference of the valid choices. The 'default' key should be one of
@@ -422,7 +436,7 @@ All parameter checking functions are called with two parameters:
 
 =item C<check_multi>
 
-Checks that a multi-valued parameter (ie type C<s> or type C<m>) satisfies
+Checks that a multi-valued parameter (ie types C<s>, C<o> or C<m>) satisfies
 its contraints.
 
 =item C<check_numeric>
diff --git a/Bugzilla/Config/RADIUS.pm b/Bugzilla/Config/RADIUS.pm
new file mode 100755 (executable)
index 0000000..6701d6f
--- /dev/null
@@ -0,0 +1,60 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Marc Schumann.
+# Portions created by Marc Schumann are Copyright (c) 2007 Marc Schumann.
+# All rights reserved.
+#
+# Contributor(s): Marc Schumann <wurblzap@gmail.com>
+#
+
+package Bugzilla::Config::RADIUS;
+
+use strict;
+
+use Bugzilla::Config::Common;
+
+$Bugzilla::Config::RADIUS::sortkey = "09";
+
+sub get_param_list {
+  my $class = shift;
+  my @param_list = (
+  {
+   name =>    'RADIUS_server',
+   type =>    't',
+   default => ''
+  },
+
+  {
+   name =>    'RADIUS_secret',
+   type =>    't',
+   default => ''
+  },
+
+  {
+   name =>    'RADIUS_NAS_IP',
+   type =>    't',
+   default => ''
+  },
+
+  {
+   name =>    'RADIUS_email_suffix',
+   type =>    't',
+   default => ''
+  },
+  );
+  return @param_list;
+}
+
+1;
index 7cc51a5e61c62f4731a2c09491e738f133d5c837..321f90f8de1eac84e0a45403b40f1f2a68a34f64 100644 (file)
@@ -169,6 +169,12 @@ sub OPTIONAL_MODULES {
         version => 0,
         feature => 'LDAP Authentication'
     },
+    {
+        package => 'RadiusPerl',
+        module  => 'Authen::Radius',
+        version => 0,
+        feature => 'RADIUS Authentication'
+    },
     {
         package => 'SOAP-Lite',
         module  => 'SOAP::Lite',
index 0f859bbf05a746c96395b2a4aac5ce7e81663b25..337c1b4315fccf34f5dd0e38d8813bc09fe96bdd 100644 (file)
@@ -1,5 +1,5 @@
 <!-- <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"> -->
-<!-- $Id: installation.xml,v 1.139 2007/07/24 18:22:02 timeless%mozdev.org Exp $ -->
+<!-- $Id: installation.xml,v 1.140 2007/08/02 22:38:43 wurblzap%gmail.com Exp $ -->
 <chapter id="installing-bugzilla">
   <title>Installing Bugzilla</title>
 
           </para>
         </listitem>
 
+        <listitem>
+          <para>
+            Authen::Radius
+            (&min-authen-radius-ver;) for RADIUS Authentication
+          </para>
+        </listitem>
+
         <listitem>
           <para>
             <link linkend="install-modules-soap-lite">SOAP::Lite</link>
@@ -1506,6 +1513,72 @@ c:\perl\bin\perl.exe -xc:\bugzilla -wT "%s" %s
 
     </section>
     
+    <section id="bzradius">
+      <title>RADIUS Authentication</title>
+
+      <para>RADIUS authentication is a module for Bugzilla's plugin 
+      authentication architecture.
+      Most caveats that apply to LDAP authentication apply to RADIUS
+      authentication as well.
+      </para>
+
+      <para>Parameters required to use RADIUS Authentication:</para>
+
+      <variablelist>
+        <varlistentry id="param-user_verify_class">
+          <term>user_verify_class</term>
+          <listitem>
+            <para>If you want to list <quote>RADIUS</quote> here,
+            make sure to have set up the other parameters listed below.
+            Unless you have other (working) authentication methods listed as
+            well, you may otherwise not be able to log back in to Bugzilla once
+            you log out.
+            If this happens to you, you will need to manually edit
+            <filename>data/params</filename> and set user_verify_class to
+            <quote>DB</quote>.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry id="param-RADIUS_server">
+          <term>RADIUS_server</term>
+          <listitem>
+            <para>This parameter should be set to the name (and optionally the
+            port) of your RADIUS server.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry id="param-RADIUS_secret">
+          <term>RADIUS_secret</term>
+          <listitem>
+            <para>This parameter should be set to the RADIUS server's secret.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry id="param-RADIUS_email_suffix">
+          <term>RADIUS_email_suffix</term>
+          <listitem>
+            <para>Bugzilla needs an e-mail address for each user account.
+            Therefore, it needs to determine the e-mail address corresponding
+            to a RADIUS user.
+            Bugzilla offers only a simple way to do this: it can concatenate
+            a suffix to the RADIUS user name to convert it into an e-mail
+            address.
+            You can specify this suffix in the RADIUS_email_suffix parameter.
+            </para>
+            <para>If this simple solution does not work for you, you'll
+            probably need to modify
+            <filename>Bugzilla/Auth/Verify/RADIUS.pm</filename> to match your
+            requirements.
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+
+    </section>
+    
     <section id="bzldap">
       <title>LDAP Authentication</title>
 
@@ -1553,12 +1626,12 @@ c:\perl\bin\perl.exe -xc:\bugzilla -wT "%s" %s
         <varlistentry id="param-user_verify_class">
           <term>user_verify_class</term>
           <listitem>
-            <para>This parameter should be set to <quote>LDAP</quote>
-            <emphasis>only</emphasis> if you will be using an LDAP directory
-            for authentication. If you set this param to <quote>LDAP</quote> but
-            fail to set up the other parameters listed below you will not be
-            able to log back in to Bugzilla one you log out. If this happens
-            to you, you will need to manually edit
+            <para>If you want to list <quote>LDAP</quote> here,
+            make sure to have set up the other parameters listed below.
+            Unless you have other (working) authentication methods listed as
+            well, you may otherwise not be able to log back in to Bugzilla once
+            you log out.
+            If this happens to you, you will need to manually edit
             <filename>data/params</filename> and set user_verify_class to
             <quote>DB</quote>.
             </para>
diff --git a/js/params.js b/js/params.js
new file mode 100755 (executable)
index 0000000..4537407
--- /dev/null
@@ -0,0 +1,61 @@
+/* The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Bugzilla Bug Tracking System.
+ *
+ * The Initial Developer of the Original Code is Marc Schumann.
+ * Portions created by Marc Schumann are Copyright (c) 2007 Marc Schumann.
+ * All rights reserved.
+ *
+ * Contributor(s): Marc Schumann <wurblzap@gmail.com>
+ */
+
+function sortedList_moveItem(paramName, direction, separator) {
+    var select = document.getElementById('select_' + paramName);
+    var inputField = document.getElementById('input_' + paramName);
+    var currentIndex = select.selectedIndex;
+    var newIndex = currentIndex + direction;
+    var optionCurrentIndex;
+    var optionNewIndex;
+
+    /* Return if no selection */
+    if (currentIndex < 0) return;
+    /* Return if trying to move upward out of list */
+    if (newIndex < 0) return;
+    /* Return if trying to move downward out of list */
+    if (newIndex >= select.length) return;
+
+    /* Move selection */
+    optionNewIndex = select.options[newIndex];
+    optionCurrentIndex = select.options[currentIndex];
+    /* Because some browsers don't accept the same option object twice in a
+     * selection list, we need to put a blank option here first */
+    select.options[newIndex] = new Option();
+    select.options[currentIndex] = optionNewIndex;
+    select.options[newIndex] = optionCurrentIndex;
+    select.selectedIndex = newIndex;
+    populateInputField(select, inputField, separator);
+}
+
+function populateInputField(select, inputField, separator) {
+    var i;
+    var stringRepresentation = '';
+
+    for (i = 0; i < select.length; i++) {
+        if (select.options[i].value == separator) {
+            break;
+        }
+        if (stringRepresentation != '') {
+            stringRepresentation += ',';
+        }
+        stringRepresentation += select.options[i].value;
+    }
+    inputField.value = stringRepresentation;
+}
index 8d34d0e055767edddf2a37823cdc7e1366eaeb46..4eec75261c51a0de75d30cef18e3a1bd58fe6a8f 100644 (file)
@@ -48,6 +48,12 @@ dd {
   margin-bottom: 1.5em;
 }
 
+.sortlist_separator {
+    font-weight: bold;
+    font-size: 80%;
+    background-color: #dddddd;
+}
+
 .contribute {
     border: 1px dotted black;
     padding: .5em;
index 040190699890fd1fd345bde46b526cae423691f0..2e52426bf698c1b58d14e21ef02c3d4ab99f2ec1 100644 (file)
@@ -18,6 +18,7 @@
   #
   # Contributor(s): Dave Miller <justdave@bugzilla.org>
   #                 Frédéric Buclin <LpSolit@gmail.com>
+  #                 Marc Schumann <wurblzap@gmail.com>
   #%]
 [%
    title = "User Authentication"
                             ${terms.Bugzilla}'s built-in authentication. This is the most common
                             choice.
                           </dd>
+                          <dt>RADIUS</dt>
+                          <dd>
+                            RADIUS authentication using a RADIUS server.
+                            This method is experimental; please see the
+                            $terms.Bugzilla documentation for more information.
+                            Using this method requires
+                            <a href=\"?section=radius\">additional
+                            parameters</a> to be set.
+                          </dd>
                           <dt>LDAP</dt>
                           <dd>
-                            LDAP authentication using an LDAP server. This method is
-                            experimental; please see the $terms.Bugzilla documentation for more
-                            information. Using this method requires additional parameters
-                            to be set above.
+                            LDAP authentication using an LDAP server.
+                            This method is experimental; please see the
+                            $terms.Bugzilla documentation for more information.
+                            Using this method requires
+                            <a href=\"?section=ldap\">additional
+                            parameters</a> to be set.
                           </dd>
                         </dl>",
 
                        "to be created. If this parameter is left blank, no users " _
                        "will be permitted to create their own accounts and all accounts " _
                        "will have to be created by an administrator." }
-%]
\ No newline at end of file
+%]
index 34cd1d39c5b53dbfdd3dd9913b3c6b9d8abca889..4e2b8f82120f09f7ac0fc349f984380ac5c9b74c 100644 (file)
   # Rights Reserved.
   #
   # Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
+  #                 Marc Schumann <wurblzap@gmail.com>
   #%]
 [%# INTERFACE:
   # panel: hash representing the current panel.
   #%]
 
+[% sortlist_separator = '---' %]
+
 <dl>
   [% FOREACH param = panel.param_list %]
     <dt><a name="[% param.name FILTER html %]">[% param.name FILTER html %]</a></dt>
             </option>
           [% END %]
         </select>
+      [% ELSIF param.type == "o" %]
+        <script type="text/javascript"><!--
+          document.write("<span style=\"display: none\">");
+        // -->
+        </script>
+        <input id="input_[% param.name FILTER html %]" size="80"
+               name="[% param.name FILTER html %]"
+               value="[% Param(param.name) FILTER html %]"><br>
+        <script type="text/javascript"><!--
+          document.write("<\/span>");
+        // -->
+        </script>
+        [% boxSize = 7 %]
+        [% boxSize = 3 + param.choices.size IF param.choices.size < 7 %]
+        [% plist = Param(param.name).split(',') %]
+
+        <script type="text/javascript"><!--
+          document.write(
+            '<table>' +
+            '  <tr>' +
+            '    <td rowspan="2">' +
+            '      <select id="select_[% param.name FILTER html %]"' +
+            '              size="[% boxSize FILTER html %]"' +
+            '              name="select_[% param.name FILTER html %]">' +
+                     [% FOREACH item = plist %]
+            '          <option value="[% item FILTER html %]">[% item FILTER html %]<\/option>' +
+                     [% END %]
+            '        <option class="sortlist_separator"' +
+            '                disabled="disabled"' +
+            '                value="[% sortlist_separator %]">active&uarr;&nbsp;&darr;inactive<\/option>' +
+                     [% FOREACH item = param.choices %]
+                       [% IF lsearch(plist, item) == -1 %]
+            '            <option value="[% item FILTER html %]">[% item FILTER html %]<\/option>' +
+                       [% END %]
+                     [% END %]
+            '      <\/select>' +
+            '    <\/td>' +
+            '    <td style="vertical-align: bottom">' +
+            '      <button type="button"' +
+            '              onClick="sortedList_moveItem(\'[% param.name FILTER html %]\', -1, \'[% sortlist_separator %]\');">&uarr;<\/button>' +
+            '    <\/td>' +
+            '  <\/tr>' +
+            '  <tr>' +
+            '    <td style="vertical-align: top">' +
+            '      <button type="button"' +
+            '              onClick="sortedList_moveItem(\'[% param.name FILTER html %]\', +1, \'[% sortlist_separator %]\');">&darr;<\/button>' +
+            '    <\/td>' +
+            '  <\/tr>' +
+            '<\/table>');
+        // -->
+        </script>
       [% ELSIF param.type == "s" %]
         <select name="[% param.name FILTER html %]">
           [% FOREACH item = param.choices %]
index 2a9b785a6d11eec63c76879dc4655e94f843a2a8..588abd5c5a2ee7aa76d2c94a2b1df24b6ee615c9 100644 (file)
@@ -57,6 +57,7 @@
    title = title
    message = message
    style_urls = ['skins/standard/params.css']
+   javascript_urls = ['js/params.js']
 %]
 
 <table border="0" width="100%">
diff --git a/template/en/default/admin/params/radius.html.tmpl b/template/en/default/admin/params/radius.html.tmpl
new file mode 100755 (executable)
index 0000000..4fc5a8d
--- /dev/null
@@ -0,0 +1,55 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+  # License Version 1.1 (the "License"); you may not use this file
+  # except in compliance with the License. You may obtain a copy of
+  # the License at http://www.mozilla.org/MPL/
+  #
+  # Software distributed under the License is distributed on an "AS
+  # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  # implied. See the License for the specific language governing
+  # rights and limitations under the License.
+  #
+  # The Original Code is the Bugzilla Bug Tracking System.
+  #
+  # The Initial Developer of the Original Code is Marc Schumann.
+  # Portions created by Marc Schumann are Copyright (c) 2007 Marc Schumann.
+  # All rights reserved.
+  #
+  # Contributor(s): Marc Schumann <wurblzap@gmail.com>
+  #%]
+[%
+   title = "RADIUS"
+   desc = "Configure this first before choosing RADIUS as an authentication method"
+%]
+
+[% param_descs = {
+  RADIUS_server => "The name (and optionally port) of your RADIUS server " _
+                   "(e.g. <code>radius.company.com</code>, or " _
+                   "<code>radius.company.com:portnum</code>).<br>" _
+                   "Required only if " _
+                   "<a href=\"?section=auth#user_verify_class\">the " _
+                   "<code>user_verify_class</code> parameter</a> contains " _
+                   "<code>RADIUS</code>.",
+
+  RADIUS_secret => "Your RADIUS server's secret.<br>" _
+                   "Required only if " _
+                   "<a href=\"?section=auth#user_verify_class\">the " _
+                   "<code>user_verify_class</code> parameter</a> contains " _
+                   "<code>RADIUS</code>.",
+
+  RADIUS_NAS_IP => "The NAS-IP-Address attribute to be used when exchanging " _
+                   "data with your RADIUS server. " _
+                   "If unspecified, <code>127.0.0.1</code> will be used.<br>" _
+                   "Useful only if " _
+                   "<a href=\"?section=auth#user_verify_class\">the " _
+                   "<code>user_verify_class</code> parameter</a> " _
+                   "contains <code>RADIUS</code>.",
+
+  RADIUS_email_suffix => "Suffix to append to a RADIUS user name to form an " _
+                         "e-mail address.<br>" _
+                         "Useful only if " _
+                         "<a href=\"?section=auth#user_verify_class\">the " _
+                         "<code>user_verify_class</code> parameter</a> " _
+                         "contains <code>RADIUS</code>.",
+  }
+%]
index 7d1c369f7c1e0fc4af7fd6655720c476f25d6ed0..73d42224aa717f5e25726a208d4aef4edd9fbca5 100644 (file)
   'link_uri'
 ],
 
+'admin/params/common.html.tmpl' => [
+  'sortlist_separator', 
+],
+
 'admin/products/groupcontrol/confirm-edit.html.tmpl' => [
   'group.count', 
 ],
index a7b65b0f13a9a79e84b52dc623b18130f4b567d8..51f52b4fe3b9739e3b28eebddcc4caf218e40ae0 100644 (file)
     outside the package. This function may only be called from
     a subclass of <code>[% superclass FILTER html %]</code>.
 
+  [% ELSIF error == "radius_preparation_error" %]
+    An error occurred while preparing for a RADIUS authentication request:
+    <code>[% errstr FILTER html %]</code>.
 
   [% ELSIF error == "unknown_comparison_type" %]
     Specified comparison type is not supported.