Commit 6a58d3eb authored by wurblzap%gmail.com's avatar wurblzap%gmail.com

Bug 380187 – Bugzilla should support RADIUS authentication.

Patch by Marc Schumann <wurblzap@gmail.com>; r=mkanat, a=mkanat
parent 037a33e6
# -*- 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;
......@@ -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
},
......
......@@ -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>
......
# -*- 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;
......@@ -170,6 +170,12 @@ sub OPTIONAL_MODULES {
feature => 'LDAP Authentication'
},
{
package => 'RadiusPerl',
module => 'Authen::Radius',
version => 0,
feature => 'RADIUS Authentication'
},
{
package => 'SOAP-Lite',
module => 'SOAP::Lite',
version => 0,
......
<!-- <!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>
......@@ -420,6 +420,13 @@
<listitem>
<para>
Authen::Radius
(&min-authen-radius-ver;) for RADIUS Authentication
</para>
</listitem>
<listitem>
<para>
<link linkend="install-modules-soap-lite">SOAP::Lite</link>
(&min-soap-lite-ver;) for the web service interface
</para>
......@@ -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>
......
/* 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;
}
......@@ -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;
......
......@@ -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"
......@@ -67,12 +68,23 @@
${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>",
......@@ -121,4 +133,4 @@
"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
%]
......@@ -17,11 +17,14 @@
# 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>
......@@ -53,6 +56,57 @@
</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 %]
......
......@@ -57,6 +57,7 @@
title = title
message = message
style_urls = ['skins/standard/params.css']
javascript_urls = ['js/params.js']
%]
<table border="0" width="100%">
......
[%# 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>.",
}
%]
......@@ -463,6 +463,10 @@
'link_uri'
],
'admin/params/common.html.tmpl' => [
'sortlist_separator',
],
'admin/products/groupcontrol/confirm-edit.html.tmpl' => [
'group.count',
],
......
......@@ -337,6 +337,9 @@
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment