<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Felipe Alfaro Solana &#187; LDAP</title>
	<atom:link href="http://www.felipe-alfaro.org/blog/category/ldap/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.felipe-alfaro.org/blog</link>
	<description>A little bit of technology, security and networking with Linux, FreeBSD and Mac OS X, plus some personal opinions.</description>
	<lastBuildDate>Sun, 23 Oct 2011 16:46:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Enterprise mail routing with Postfix and LDAP</title>
		<link>http://www.felipe-alfaro.org/blog/2006/05/24/enterprise-mail-routing-with-postfix-and-ldap/</link>
		<comments>http://www.felipe-alfaro.org/blog/2006/05/24/enterprise-mail-routing-with-postfix-and-ldap/#comments</comments>
		<pubDate>Tue, 23 May 2006 19:49:35 +0000</pubDate>
		<dc:creator>Felipe Alfaro Solana</dc:creator>
				<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Postfix]]></category>

		<guid isPermaLink="false">http://felipe-alfaro.org/blog/2006/05/24/enterprise-mail-routing-with-postfix-and-ldap/</guid>
		<description><![CDATA[A LDAP directory offers a single, logically centralized, hierarchical store to keep data, like information about users, groups, mailboxes, services, etc. There are a number of applications out there than can leverage this LDAP store. For example, PAM can authenticate by checking against an LDAP directory, Cyrus-IMAP can check whether a certain user has a [...]]]></description>
			<content:encoded><![CDATA[<p><b>A LDAP directory offers a single, logically centralized, hierarchical store</b> to keep data, like information about users, groups, mailboxes, services, etc. There are a number of applications out there than can leverage this LDAP store. For example, PAM can authenticate by checking against an LDAP directory, Cyrus-IMAP can check whether a certain user has a IMAP/POP mailbox available, and <b>Postfix can contact an LDAP directory in order to route an incoming mail to its corresponding mail host</b>.</p>
<p>LDAP is flexible enough to describe abstract concepts, like persons, by using <b>object classes</b>. Each object class is built upon attributes. An <b>attribute</b> is the minimal unit of information and tells about a property, such as the name of a person, its postal address or e-mail address. The minimal storage unit is an LDAP <b>entry</b>, however, which is an instance of one ore several object classes. The collection of attributes and object classes is called <b>schema</b>, while the collection of LDAP entries is called <b>Directory Information Tree (DIT)</b>.</p>
<p>There are several RFC documents out there describing most of the standard LDAP object classes for the LDAPv3 protocol. There are other object classes which are either propietary or non-standard. For example, <b>Fedora Directory Server</b> defines an object class named <em>mailRecipient</em>. This legacy object class was used by the Netscape Messaging Server 4 to define a mailbox and is defined as:</p>
<div>
<pre>
objectclasses: ( 2.16.840.1.113730.3.2.3
NAME 'mailRecipient'
DESC '' SUP top AUXILIARY
MUST ( objectClass )
MAY ( cn $ mail $ mailAlternateAddress $
mailHost $ mailRoutingAddress $
mailAccessDomain $ mailAutoReplyMode $
mailAutoReplyText $ mailDeliveryOption $
mailForwardingAddress $
mailMessageStore $ mailProgramDeliveryInfo $
mailQuota $ multiLineDescription $ uid $
userPassword )
X-ORIGIN 'Netscape Messaging Server 4.x' )
</pre>
</div>
<p>This object class is particularly simple and interesting since it defines a few concepts we can use when routing mail, like the idea of multiple mail aliases for a single mailbox. </p>
<h4>Describing our purpouses</h4>
<p>Take this scenario: we have a real user, John Smith which owns a mailbox which is stored at host <em>mail1.internal</em>. The mailbox for John Smith is <em>john.smith@mail1.internal</em>, since it&#8217;s stored in host <em>mail1.internal</em>. Let&#8217;s say this real user has the following e-mail addresses assigned to him (assigned to its mailbox):</p>
<ul>
<li><em>sample.user@example.com</em></li>
<li><em>sample_user@example.com</em></li>
<li><em>sampleuser@example.com</em></li>
<li><em>sample@example.com</em></li>
<li><em>john.smith@example.com</em></li>
</ul>
<p>These are the e-mail addresses. The last e-mail address is, in fact, the real e-mail address that anyone could expect John Smith to have. The other e-mail addresses are in fact aliases.</p>
<p>Whenever a Postfix MTA in the enterprise receives a mail for any of these e-mail addresses, we want it to be delivered to a mailbox named <em>john.smith</em> in host <em>mail1.internal</em>, that is, delivered to <em>john.smith@mail1.internal</em>, and so, <em>john.smith@mail1.internal</em> is the real address where messages sent to John Smith, using any of the previous e-mail addresses, must be routed to. Thus, <em>john.smith@mail1.internal</em> is what we will call the <b>mail routing address</b>.</p>
<p>We will configure Postfix to use an LDAP-based <b>virtual alias map</b>. Each time a mail is sent to Postfix, it will perform an LDAP query for that e-mail address and will try to guess its mail routing address. If one is found, Postfix will deliver that mail to it:</p>
<ul>
<li>If the domain part (the address at the right of the <code>@</code> sign) of the mail routing address <strong>equals</strong> the FQDN of the Postfix host:
<p>Postfix will try to deliver the message locally, usually using an MDA, like procmail or <em>cyrus-imapd/deliver</em> (Cyrus-IMAP local delivery agent used to deliver messages to a IMAP mailbox).</p>
<p>For example, let be <em>john.smith@mail1.internal</em> the mail routing address and <em>mail1.internal</em> Postfix&#8217;s hostname FQDN. In this case, Postfix will deliver the message locally using a MDA.</li>
<li>If the domain part (the address at the right of the <code>@</code> sign) of the mail routing address <strong>does not</strong> equal the FQDN of the Postfix host:
<p>Postfix will trigger the message routing process again in order to deliver it to its final destination, checking querying the LDAP directory again if necessary.</li>
</ul>
<p>To store mail routing addresses and it&#8217;s corresponding mail aliases, we will use the <em>mailRecipient</em> object class. The multi-valued <em>mail</em> attribute will hold all mail aliases and <em>mailRoutingAddress</em> will the real, final destination for any of them.</p>
<p>A sample entry, exemplifying the John Smith user we described before, in LDIF syntax is:</p>
<div>
<pre>
dn: uid=john.smith,ou=People, dc=example, dc=com
givenName: John
sn: Smith
<b>mail: sample.user@example.com
mail: sample_user@example.com
mail: sampleuser@example.com
mail: sample@example.com
mail: john.smith@example.com</b>
objectClass: top
objectClass: mailRecipient
uid: john.smith
<b>mailRoutingAddress: john.smith@mail1.internal</b>
</pre>
</div>
<p>Note the absence of the <em>posixAccount</em> object class. This means John Smith is <strong>not</strong> a regular UNIX user and thus, this mailbox cannot be used to log in through PAM, for example. Note the absence of the <em>inetOrgPerson</em> object class too, which could mean this mailbox is not assigned to a real user.</p>
<h4>Configuring Postfix</h4>
<p>The first thing that is required is creating a configuration file with details about how the LDAP directory server should be queried and contacted. The name of this file is not relevant, but I decided to name it <code>/etc/postfix/ldap-aliases.cf</code>:</p>
<div>
<pre>
# cat /etc/postfix/ldap-aliases.cf
bind = no
version = 3
timeout = 20

## set the size_limit to 1 since we only
## want to find one email address match
size_limit = 1
expansion_limit = 0

start_tls = no
#tls_require_cert = no

server_host = ldap://ldap1.internal/ ldap://ldap2.internal/
search_base = dc=example,dc=com
scope = sub
query_filter = (&#038;(objectclass=mailRecipient)(mail=%s))
result_attribute = mailRoutingAddress
special_result_filter = %s@%d
</pre>
</div>
<p>The configuration options are described in detail in the Postfix <a href="http://www.postfix.org/ldap_table.5.html" title="ldap_table(5)">ldap_table(5)</a> manual page. A brief description lies hereafter:</p>
<ul>
<li><code>bind = no</code> tells Postfix to perform an unauthenticated (anonymous) BIND against the LDAP directory.</li>
<li><code>size_limit = 1</code> tells Postfix to request one, and only one, LDAP entry matching the <code>query_filter</code>, starting the search operation at the LDAP entry whose DN is specified by <code>search_base</code>, and using a <code>scope</code> search scope.
<p>The search scope is one of: <em>sub, one, base</em>.</li>
<li><code>server_host</code> defines one or several LDAP hosts, trying them in order should the first one fail.</li>
<li><code>query_filter</code> defines the LDAP search that Postfix will use in order to retrieve the mail routing address given a mail address.
<p>In the previous configuration file, the LDAP search filter will look for entries belonging to the <em>mailRecipient</em> object class whose <em>mail</em> attribute matches the recipient <em>mail</em> address of the incoming message.</p>
<p>If one is found (at most only one entry will be retrieved since <code>size_limit = 1</code>), the <em>mailRoutingAddress</em> attribute, defined to by <code>result_attribute</code>, points to the final destination for the message, that is the mail routing address.</li>
</ul>
<p>Finally, we will add the <code>virtual_alias_maps</code> directive to Postfix&#8217;s <code>/etc/postfix/main.cf</code> configuration file:</p>
<div>
<pre>
# tail -1 /etc/postfix/main.cf
virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf
</pre>
</div>
<p>For example, when receiving a message for <em>sample.user@example.com</em>, Postfix will first look to see if this mail address is an alias or a real address. The LDAP query can be tested by running:</p>
<div>
<pre>
$ ldapsearch -x -b"dc=example,dc=coml" \
"(&#038;(objectclass=mailRecipient)(mail=sample.user@example.com))" \
mailRoutingAddress
# extended LDIF
#
# LDAPv3
# base <dc =example,dc=com> with scope sub
# filter: (&#038;(objectclass=mailRecipient)(mail=sample.user@example.com))
# requesting: mailRoutingAddress
#

dn: uid=john.smith,ou=People, dc=example, dc=com
<strong>mailRoutingAddress: john.smith@mail1.internal</strong>

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1
</dc></pre>
</div>
<p>Thus, Postfix will route any message to <em>sample.user@example.com</em> to a mailbox named <em>john.smith</em> at mailhost <em>mail1.internal</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.felipe-alfaro.org/blog/2006/05/24/enterprise-mail-routing-with-postfix-and-ldap/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>User management using LDAP and libuser</title>
		<link>http://www.felipe-alfaro.org/blog/2006/05/18/user-management-using-ldap-and-libuser/</link>
		<comments>http://www.felipe-alfaro.org/blog/2006/05/18/user-management-using-ldap-and-libuser/#comments</comments>
		<pubDate>Thu, 18 May 2006 09:20:20 +0000</pubDate>
		<dc:creator>Felipe Alfaro Solana</dc:creator>
				<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://felipe-alfaro.org/blog/2006/05/18/user-management-using-ldap-and-libuser/</guid>
		<description><![CDATA[libuser is a collection of libraries and tools to manage users and groups under Linux or UNIX-like systems. libuser has several modules allowing to manage users and groups through different backends, like local (password and shadow) and LDAP (the LDAP backend has been somewhat unusable up to version 0.52). The LDAP module, however, requires the [...]]]></description>
			<content:encoded><![CDATA[<p><em>libuser</em> is a collection of libraries and tools to manage users and groups under Linux or UNIX-like systems. <em>libuser</em> has several modules allowing to manage users and groups through different backends, like local (password and shadow) and LDAP (the LDAP backend has been somewhat unusable up to version 0.52).</p>
<p>The LDAP module, however, requires the user to supply a BIND_PW (password) for the BIND_DN (user) in order to authenticate against the LDAP directory server an perform the modifications. In automated deployment scenarios, it&#8217;s essential to be able to perform operations on to the LDAP directory server without asking the user for the password. Instead, the password used to authenticate against the LDAP directory server could be well stored in libuser&#8217;s configuration file, /etc/libuser.conf.</p>
<p>I&#8217;ve made a patch against libuser that implements a new configuration parameter for the LDAP module. This new parameter is named <strong>password</strong>, and specifies the password for the user <strong>binddn</strong> user.</p>
<p>Here is a sample of libuser&#8217;s configuration file, <code>/etc/libuser.conf</code>:</p>
<div>
<pre>[defaults]
# The default (/usr/lib*/libuser) is usually correct
# moduledir = /your/custom/directory
skeleton = /etc/skel
mailspooldir = /var/mail
modules = ldap
create_modules = ldap
crypt_style = md5

[userdefaults]
LU_USERNAME = %n
LU_UIDNUMBER = 10000
LU_GIDNUMBER = %u
LU_HOMEDIRECTORY = /home/%n
LU_LOGINSHELL = /bin/bash

[groupdefaults]
LU_GROUPNAME = %n
LU_GIDNUMBER = 10000

[ldap]
# Setting these is always necessary.
server = ldap://directory.server.fqdn
basedn = dc=example,dc=com

# Setting these is rarely necessary, since it's usually correct.
userBranch = ou=People
groupBranch = ou=Groups

# Set only if your administrative user uses simple bind operations to
# connect to the server.
binddn = cn=Directory Manager
<strong>password = secret</strong></pre>
</div>
<p>The patched SRPM and diff patch can be obtained from here: <a id="p130" href="http://felipe-alfaro.org/blog/wp-content/uploads/2006/05/libuser-0.52.5-1.el4.1.tar.gz">libuser-0.52.5-1.el4.1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.felipe-alfaro.org/blog/2006/05/18/user-management-using-ldap-and-libuser/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Renaming an LDAP entry</title>
		<link>http://www.felipe-alfaro.org/blog/2006/04/19/renaming-an-ldap-entry/</link>
		<comments>http://www.felipe-alfaro.org/blog/2006/04/19/renaming-an-ldap-entry/#comments</comments>
		<pubDate>Tue, 18 Apr 2006 22:31:00 +0000</pubDate>
		<dc:creator>Felipe Alfaro Solana</dc:creator>
				<category><![CDATA[LDAP]]></category>

		<guid isPermaLink="false">http://felipe-alfaro.org/blog/2006/04/19/renaming-an-ldap-entry/</guid>
		<description><![CDATA[The modrdn LDAP operation allows an authorized user to rename an LDAP entry&#8217;s RDN (that is, modifying the RDN of that entry). Optionally, the modrdn operation can keep the old attributes that form the pristine RDN. This can be accomplished by specifiying deleteOldRDN:0 at the end of the modrdn data. If deleteOldRND:1 is specified at [...]]]></description>
			<content:encoded><![CDATA[<p>The <code>modrdn</code> LDAP operation allows an authorized user to rename an LDAP entry&#8217;s RDN (that is, modifying the RDN of that entry).</p>
<p>Optionally, the <code>modrdn</code> operation can keep  the old attributes that form the pristine RDN. This can be accomplished by specifiying <code>deleteOldRDN:0</code> at the end of the <code>modrdn</code> data. If <code>deleteOldRND:1</code> is specified at the end of the <code>modrdn</code> operation, or it is not specified at all, the <code>modrdn</code> operation will keep the attributes (and its values) that formed the pristine RDN.</p>
<p>For example, let&#8217;s add a sample entry:</p>
<div>
<pre>
<b>$ ldapmodify ...</b>
dn:cn=John Smith,ou=People,dc=sample,dc=com
changeType:add
objectClass:top
objectClass:person
cn:John Smith
sn:Smith
</pre>
</div>
<p>The attributes for the newly added entry are:</p>
<div>
<pre>
<b>$ ldapsearch -x \
  -b"cn=John Smith,ou=People,dc=sample,dc=com" \
  -s base</b>
dn: cn=John Smith,ou=People,dc=sample,dc=com
objectClass: top
objectClass: person
cn: John Smith
sn: Smith
</pre>
</div>
<p>Now, using the <code>ldapmodify</code> command, let&#8217;s invoke the <code>modrdn</code> operation onto the sample entry:</p>
<div>
<pre>
<b>$ ldapmodify ...</b>
dn:cn=John Smith,ou=People,dc=sample,dc=com
changeType:modrdn
newrdn:cn=John A. Smith
deleteOldRDN:1
</pre>
</div>
<p>Since <code>deleteOldRND:1</code> has been specified, the old <code>cn</code> attribiute (<code>commonName</code>), which was part of the RDN, is removed and then replaced by the new <code>cn</code> attribute and it&#8217;s new value.</p>
<div>
<pre>
<b>$ ldapsearch -x \
  -b"cn=John A. Smith,ou=People,dc=sample,dc=com" \
  -s base</b>
dn: cn=John A. Smith,ou=People,dc=sample,dc=com
objectClass: top
objectClass: person
sn: Smith
cn: John A. Smith
</pre>
</div>
<p>Should have we specified <code>deleteOldRND:0</code>, then the entry would have looked as follows:</p>
<div>
<pre>
<b>$ ldapsearch -x \
  -b"cn=John A. Smith,ou=People,dc=sample,dc=com" \
  -s base</b>
dn: cn=John A. Smith,ou=People,dc=sample,dc=com
objectClass: top
objectClass: person
cn: John Smith
cn: John A. Smith
sn: Smith
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.felipe-alfaro.org/blog/2006/04/19/renaming-an-ldap-entry/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automatic start-up for SSL-enabled instances of Fedora Directory Server</title>
		<link>http://www.felipe-alfaro.org/blog/2006/02/14/automatic-start-up-for-ssl-enabled-instances-of-fedora-directory-server/</link>
		<comments>http://www.felipe-alfaro.org/blog/2006/02/14/automatic-start-up-for-ssl-enabled-instances-of-fedora-directory-server/#comments</comments>
		<pubDate>Mon, 13 Feb 2006 23:18:26 +0000</pubDate>
		<dc:creator>Felipe Alfaro Solana</dc:creator>
				<category><![CDATA[Fedora]]></category>
		<category><![CDATA[LDAP]]></category>

		<guid isPermaLink="false">http://felipe-alfaro.org/blog/2006/02/14/automatic-start-up-for-ssl-enabled-instances-of-fedora-directory-server/</guid>
		<description><![CDATA[Fedora Directory Server protects its internal, software-based, cryptographic repository with a PIN (passphrase). When an instance of a Fedora Directory Server is configured for SSL/TLS support, by default, the start-up script interactively prompts for that PIN in order to unlock the private key. This can be a problem for automated system start-ups. However, there is [...]]]></description>
			<content:encoded><![CDATA[<p>Fedora Directory Server protects its internal, software-based, cryptographic repository with a PIN (passphrase).</p>
<p>When an instance of a Fedora Directory Server is configured for SSL/TLS support, by default, the start-up script interactively prompts for that PIN in order to unlock the private key. This can be a problem for automated system start-ups.</p>
<p>However, there is a way to configure Fedora Directory Server in such a way that the PIN is stored into a root-only readable configuration file. Thus, during start-up, the directory server instance can retrieve the PIN from that configuration file wihout asking it.</p>
<p>The PIN is stored into a file called:</p>
<div>
<pre>
/opt/fedora-ds/alias/slapd-[instance_name]-pin.txt
</pre>
</div>
<p>and should contain a single line with the following format:</p>
<div>
<pre>
Internal (Software) Token:[pin or passphrase]
</pre>
</div>
<p>For example, if the Fedora Directory Server instance is named <code>"server1"</code> and the PIN or passphrase needed to unlock the SSL/TLS private key is <code>"secret"</code>:</p>
<div>
<pre>
# echo "Internal (Software) Token:secret" > \
   /opt/fedora-ds/alias/slapd-server1-pin.txt
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.felipe-alfaro.org/blog/2006/02/14/automatic-start-up-for-ssl-enabled-instances-of-fedora-directory-server/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Relative Distinguised Name</title>
		<link>http://www.felipe-alfaro.org/blog/2005/11/04/relative-distinguised-name/</link>
		<comments>http://www.felipe-alfaro.org/blog/2005/11/04/relative-distinguised-name/#comments</comments>
		<pubDate>Thu, 03 Nov 2005 21:56:52 +0000</pubDate>
		<dc:creator>Felipe Alfaro Solana</dc:creator>
				<category><![CDATA[LDAP]]></category>

		<guid isPermaLink="false">http://felipe-alfaro.org/blog/2005/11/04/relative-distinguised-name/</guid>
		<description><![CDATA[From RFC2251, Section 4,6, &#8220;Modify Operation&#8221;: The Modify Operation cannot be used to remove from an entry any of its distinguised values, those values which form the entry&#8217;s relative distinguised name. An attempt to do so will result in the server returning the error notAllowedOnRDN. The Modify DN Operation described in section 4.9 is used [...]]]></description>
			<content:encoded><![CDATA[<p>From <a title="RFC 2251, Section 4.6" href="http://www.ietf.org/rfc/rfc2251.txt">RFC2251, Section 4,6, &#8220;Modify Operation&#8221;</a>:</p>
<blockquote><p>The Modify Operation cannot be used to remove from an entry any of its distinguised values, those values which form the entry&#8217;s relative distinguised name. An attempt to do so will result in the server returning the error notAllowedOnRDN. The Modify DN Operation described in section 4.9 is used to rename an entry.</p></blockquote>
<p>From <a title="RFC 2253, Section 2.2" href="http://www.ietf.org/rfc/rfc2253.txt">RFC2253, Section 2,2, &#8220;Converting RelativeDistinguishedName&#8221;</a>:</p>
<blockquote><p>When converting from an ASN.1 RelativeDistinguishedName to a string, the output consists of the string encodings of each AttributeTypeAndValue (according to 2.3), in any order.</p>
<p>Where there is a multi-valued RDN, the outputs from adjoining AttributeTypeAndValues are separated by a plus (&#8216;+&#8217; ASCII 43) character.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.felipe-alfaro.org/blog/2005/11/04/relative-distinguised-name/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

