<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri","sans-serif";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=EN-AU link=blue vlink=purple>
<div class=WordSection1>
<p class=MsoNormal><span lang=EN-US>The current ldap_auth module is assuming
that the username is the same as the LDAP dn entry. In more complex LDAP
installations this is often not the case and LDAP authentication is a bit more
complicated:<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* Bind as a dedicated “search LDAP
user”<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* Search the directory tree for the
username<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* Get the DN from the search result<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* Bind as the DN with the user password<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US> I modified the current ldap_auth.rb
to use this more complex process if the auth.conf file defines “search_filter”.
In this case it expects “search_filter” to contain a suitable
search string with “@@LOGIN@@” instead of the user name (to be
replaced at runtime). E.g. something like: “(&(cn=@@LOGIN@@)(objectClass=user))”<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>It also expects the following config
entries:<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* sec_principal : the DN of the LDAP search
user.<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* sec_passwd: The password for the
sec_principal<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>* search_base: The base in the LDAP tree
from which to search<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>Code below:<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>#
--------------------------------------------------------------------------<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># Copyright 2010, C12G Labs S.L., CSIRO<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>#<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># This file is part of OpenNebula Ldap
Authentication.<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>#<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># OpenNebula Ldap Authentication is free
software: you can redistribute it and/or modify<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># it under the terms of the GNU General
Public License as published by<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># the Free Software Foundation, either
version 3 of the License, or the hope<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># That it will be useful, but (at your
option) any later version.<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>#<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># OpenNebula Ldap Authentication is
distributed in WITHOUT ANY WARRANTY; without even<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># PURPOSE. See the GNU General Public
License for more details.<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>#<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># You should have received a copy of the
GNU General Public License<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US># along with OpenNebula Ldap Authentication
. If not, see <http://www.gnu.org/licenses/><o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>#
--------------------------------------------------------------------------<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>require 'rubygems'<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>require 'net/ldap'<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US># Ldap authentication module.<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>class LdapAuth<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> def initialize(config)<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
@config = config<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US> def getLdap(user,
password) <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> ldap =
Net::LDAP.new<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> ldap.host =
@config[:ldap][:host]<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> ldap.port =
@config[:ldap][:port]<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> ldap.auth
user, password<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> ldap<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US> def getLdapDN(user) <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
search_filter = @config[:ldap][:search_filter]<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> if
(search_filter.nil?)<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
return user<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
search_filter = search_filter.gsub("@@LOGIN@@", user)<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> ldap =
getLdap(@config[:ldap][:sec_principal], @config[:ldap][:sec_passwd])<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> begin<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
ldap.search( :base => @config[:ldap][:search_base], :attributes => 'dn', <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
:filter => search_filter, :return_result => true ) do |entry|<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
STDERR.puts "Found #{entry.dn}"<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
return entry.dn<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> rescue
Exception => e <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
STDERR.puts "LDAP search failed: #{e.message}"<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> return nil<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> def auth(user_id, user,
password, token)<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> dn =
getLdapDN(user)<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> if(dn.nil?)<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
STDERR.puts("User #{user} not found in LDAP")<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
return false<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> begin <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
if getLdap(dn, token).bind<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
STDERR.puts "User #{user} authenticated!"<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
return true<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> rescue
Exception => e <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
STDERR.puts "User authentication failed for #{entry.dn}:
#{e.message}"<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US>
return false<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> <o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> STDERR.puts
"User #{user} could not be authenticated."<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> return false<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US> end<o:p></o:p></span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
</div>
</body>
</html>