<?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>ScottDotDot </title>
	<atom:link href="http://s.co.tt/tag/ejabberd/feed/" rel="self" type="application/rss+xml" />
	<link>http://s.co.tt</link>
	<description>Babblings of a computer curmudgeon.</description>
	<lastBuildDate>Mon, 26 Jan 2026 16:08:52 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1</generator>
	<item>
		<title>Making ejabberd 14.12 work with Microsoft Windows Active Directory LDAP</title>
		<link>http://s.co.tt/2015/02/05/making-ejabberd-14-12-work-with-microsoft-windows-active-directory-ldap/</link>
		<comments>http://s.co.tt/2015/02/05/making-ejabberd-14-12-work-with-microsoft-windows-active-directory-ldap/#comments</comments>
		<pubDate>Thu, 05 Feb 2015 22:19:14 +0000</pubDate>
		<dc:creator><![CDATA[Scott]]></dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[computer]]></category>
		<category><![CDATA[ejabberd]]></category>
		<category><![CDATA[howto]]></category>

		<guid isPermaLink="false">http://s.co.tt/blog/?p=1025</guid>
		<description><![CDATA[Why ejabberd? My office uses Google Talk for intra-employee instant messaging. This Monday all users got a broadcast message from Google saying that the Google Talk desktop client will cease working on February 15. (Though this may be an old automated notification from when Google was threatening to EOL Talk last February.) Update (2015-03-09): They finally did kill Talk for Windows as of February 23, 2015. Of course we can&#8217;t take the risk of Google actually shutting down our IMs, and I personally don&#8217;t like the new Hangouts Chrome app. Moreover, we want to limit employees to only messaging other people in our organization. We also don&#8217;t necessarily want Google being a party to all of our communication. That means … <a class="continue-reading-link" href="http://s.co.tt/2015/02/05/making-ejabberd-14-12-work-with-microsoft-windows-active-directory-ldap/"> Continue reading</a>]]></description>
				<content:encoded><![CDATA[<h2>Why ejabberd?</h2>
<p>My office uses Google Talk for intra-employee instant messaging.  This Monday all users got a broadcast message from Google saying that the Google Talk desktop client will cease working on February 15.  (Though this may be an old automated notification from <a href="http://www.ticbiz.com/Blog/Post/10/Google-Talk----End-of-Life-February-2014">when Google was threatening to EOL Talk last February</a>.)</p>
<p><strong>Update</strong> (2015-03-09)<strong>:</strong>  <a href="http://s.co.tt/wp-content/uploads/2015/02/google_talk_windows_no_longer_supported_email_20150309.png">They finally did kill Talk</a> for Windows as of February 23, 2015.</p>
<p>Of course we can&#8217;t take the risk of Google actually shutting down our IMs, <strong>and I personally don&#8217;t like the new Hangouts Chrome app</strong>.</p>
<p>Moreover, we want to limit employees to only messaging other people in our organization.  We also don&#8217;t necessarily want Google being a party to all of our communication.  That means running our own IM server.</p>
<p><strong>ejabberd is a well-known workhorse for IM.</strong>  Yes, I&#8217;ve heard great things about Openfire and others, but I decided to go ejabberd nonetheless.</p>
<h2>Environment and Goals</h2>
<p>Our organization runs a Windows 2008 AD infrastructure that is very simple:  One forest, one domain, one organizational unit.  (There&#8217;s only about 15 employees.)</p>
<p>I had three goals for our IM solution beyond the obvious ability to chat:</p>
<ul>
<li>Authentication to AD</li>
<li>Interchange of employee particulars (real name, email address, etc.) between the IM server and AD</li>
<li>Chat contacts defined in AD</li>
</ul>
<p>The reason for all three of these is that it&#8217;s an administrative pain to maintain a separate system and have to create all user accounts twice (something I was doing with Google).  Out of the box, <strong>ejabberd fit the bill on all three</strong> with the following features:</p>
<ul>
<li>LDAP authentication</li>
<li>mod_vcard_ldap</li>
<li>mod_shared_roster_ldap</li>
</ul>
<p>We are largely a Windows workstation / Linux server shop, which is why we use Active Directory and I&#8217;m running ejabberd on Linux.</p>
<p>It sounded perfect on paper, but <strong>in reality it was quite an affair to get it 95% functional</strong>.</p>
<h2>The Challenges</h2>
<h3>Installation Woes</h3>
<p>By default, the installation binary puts ejabberd in the path <code>/opt/ejabberd-14.12</code>.  There are no external dependencies and no config files in <code>etc</code>.  Everything is within that directory.</p>
<p>I&#8217;m using CentOS, so I followed along with <a href="https://www.ejabberd.im/node/4398" target="_blank">these comments</a>:</p>
<blockquote><p>The init file doesn&#8217;t support chkconfig because it&#8217;s missing the required header:</p>
<p>Just adding the following to the beginning of ejabberd.init does the trick:</p>
<pre><code>#!/bin/sh
#
# ejabberd	Startup script for the ejabberd XMPP Server
#
# chkconfig: - 99 10
# description:	ejabberd XMPP server

# Source function library.
. /etc/init.d/functions

set -o errexit</code></pre>
<p>The numbers after chkconfig are boot-up and shutdown priorities, they may need tunning but those seem safe. I don&#8217;t think chkconfig is distro-specific, I&#8217;ll ask ejabberd developers to add this to the distribution package.</p>
<p>So after adding that to ejabberd.init, all that is left to do is:</p>
<pre><code>cp ejabberd.init /etc/init.d/ejabberd
chmod +x /etc/init.d/ejabberd
/usr/sbin/groupadd -r ejabberd
/usr/sbin/useradd -g ejabberd -p ejabberd -r ejabberd
/sbin/chkconfig --add ejabberd
/sbin/chkconfig ejabberd on</code></pre>
</blockquote>
<p>Another issue I ran into was that I installed ejabberd as <code>root</code>, but I was trying to run it as the user <code>ejabberd</code> and so got the error:</p>
<pre><code>sed: can't read /opt/ejabberd-14.12/conf/ejabberd.yml: Permission denied
sed: can't read /opt/ejabberd-14.12/conf/ejabberd.yml: Permission denied
sed: can't read /opt/ejabberd-14.12/conf/ejabberd.yml: Permission denied
sed: can't read /opt/ejabberd-14.12/conf/ejabberd.yml: Permission denied
mkdir: cannot create directory `/opt/ejabberd-14.12/database': Permission denied
./ejabberdctl: line 125: cd: /opt/ejabberd-14.12/database/ejabberd@localhost: Permission denied
sh: /opt/ejabberd-14.12/bin/erl: Permission denied</code></pre>
<p>The solution there is pretty simple:  <code>chown -R ejabberd:ejabberd /opt/ejabberd-14.12</code></p>
<p><strong>Should the ejabberd server fail to start or if it crashes</strong>, there may still be ejabberd processes running in the background.  That may prevent it from starting again.</p>
<pre><code># ps -ef |grep ejabberd
ejabberd  1429     1  0 17:04 ?        00:00:00 /opt/ejabberd-14.12/bin/epmd -daemon
ejabberd  1431     1  3 17:04 ?        00:00:04 /opt/ejabberd-14.12/bin/beam.smp -K true -P 250000 -- -root /opt/ejabberd-14.12 -progname /opt/ejabberd-14.12/bin/erl -- -home /opt/ejabberd-14.12 -- -sname ejabberd@localhost -noshell -noinput -noshell -noinput -pa /opt/ejabberd-14.12/lib/ejabberd-14.12/ebin -mnesia dir "/opt/ejabberd-14.12/database/ejabberd@localhost" -ejabberd log_rate_limit 100 log_rotate_size 10485760 log_rotate_count 1 log_rotate_date "" -s ejabberd -sasl sasl_error_logger {file,"/opt/ejabberd-14.12/logs/erlang.log"} -smp auto start

# kill 1429
# kill 1431
</code></pre>
<p>Finally, I had one more issue when <strong>stopping</strong> the service:</p>
<pre><code>service ejabberd stop
Stopping ejabberd...
/opt/ejabberd-14.12/bin/ejabberdctl: line 364: epmd: command not found</code></pre>
<p>Another easy one, because the error message is quite clear.  There are a few lines in the file <code>/opt/ejabberd-14.12/bin/ejabberdctl</code> which assume that <code>epmd</code> is in the same directory&#8230; which it is!  However, <code>ejabberdctl</code> is being invoked by the init script without changing directory to that path.</p>
<p>You can deal with this in three ways:</p>
<ul>
<li>Change ejabberdctl to contain the full path of <code>epmd</code></li>
<li>Change the init script to <code>cd</code> into <code>/opt/ejabberd-14.12/bin</code></li>
<li>Add <code>/opt/ejabberd-14.12/bin</code> to the path</li>
</ul>
<h3>Default SSL Certificate</h3>
<p>The first thing I did was start up a plain-Jane configuration of ejabberd and try to connect to it.  I was testing it out with both <strong>Pidgin</strong> and <strong>Spark</strong (from Ignite Realtime).</p>
<p>I don&#8217;t remember which of the two clients it was, but one of them refused to connect to the server due to an SSL error.  The error message wasn&#8217;t explicit, but from what I read online it appeared that an <strong>expired certificate</strong> would stymie the client.  So it seems that the default PEM file included with the ejabberd binaries is invalid.</p>
<p>A self-signed cert isn&#8217;t a problem, so I <a href="http://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl" target="_blank">generated one using OpenSSL</a> and gave it an expiration 10 years hence.  Not a real issue, but something that you should do right off the bat.</p>
<h3>LDAP Authentication</h3>
<p>Getting LDAP authentication working wasn&#8217;t much of a problem.  The <a href="http://www.process-one.net/docs/ejabberd/guide_en.html#htoc36" target="_blank">documentation</a> is pretty much all you need.</p>
<p>Here&#8217;s a sanitized snippet of my LDAP configuration.  Note that I created a user with the common name <strong><code>Ejabberd LDAP</code></strong> as an LDAP reader.</p>
<pre><code>auth_method: ldap
ldap_servers:
   - "dcserver01.mydomain.com"
   - "dcserver02.mydomain.com"
ldap_encrypt: none
ldap_port: 389
ldap_rootdn: "CN=Ejabberd LDAP,CN=Users,dc=mydomain,dc=com"
ldap_password: "SomePassword0239"
ldap_base: "cn=Users,dc=mydomain,dc=com"
ldap_uids:
   - "sAMAccountName"
ldap_filter: ""
</code></pre>
<p>That&#8217;s enough to get LDAP authentication working.</p>
<p>By the way, if you want to get the <strong><code>ldap_rootdn</code></strong> (the user&#8217;s Active Directory <em>distinguished name</em>) fire up <strong>Active Directory Users and Computers</strong>.  Open the properties of the user, click on the <strong>Attribute Editor</strong> tab, and scroll down until you find <strong>distinguishedName</strong> in the list.</p>
<p><a href="http://s.co.tt/wp-content/uploads/2015/02/aduc_distinguishedName.png"><img src="http://s.co.tt/wp-content/uploads/2015/02/aduc_distinguishedName.png" alt="Active Directory Users and Computers - Distinguished Name" width="740" class="aligncenter size-full wp-image-1026" /></a></p>
<h3>mod_vcard_ldap</h3>
<p>This <strong>should have been easy</strong>, but it was far from it.</p>
<p>First off, at some point the developers of ejabberd switched to a <a href="http://www.yaml.org/" target="_blank">YAML</a>-formatted config file, so most of the examples you&#8217;ll find online are in JSON.  Once you get a handle on YAML it&#8217;s not a big deal to visually bounce between the two, but I&#8217;m not accustomed to YAML so there was a bit of a learning curve there.  (By the way, &#8220;<a href="http://www.yaml.org/spec/1.2/spec.html#id2759572" target="_blank">every JSON file is also a valid YAML file</a>&#8220;.)</p>
<hr />
<h2>Update (2016-03-25)</h2>
<p>Below I point out that <strong>a typo in the documentation caused me some grief</strong>.  I&#8217;m leaving that in this post for posterity (or in case you&#8217;re referencing an old or archived version of the docs), however <a href="http://s.co.tt/2015/02/05/making-ejabberd-14-12-work-with-microsoft-windows-active-directory-ldap/#comment-2908">Mickaël Rémond from ProcessOne was kind enough to comment</a> that the doc has since been fixed.</p>
<p>Thanks Mickaël, much appreciated!</p>
<hr />
<p>The real problem was that I copied the <code>mod_vcard_ldap</code> config snippet <a href="http://www.process-one.net/docs/ejabberd/guide_en.html#ad" target="_blank">straight from the docs</a> on Active Directory LDAP integration.  Here&#8217;s what it says:</p>
<pre><code>  mod_vcard_ldap: 
    ldap_vcard_map: 
      "NICKNAME": {"%u", []}
      "GIVEN": {"%s", ["givenName"]}
      "MIDDLE": {"%s", ["initials"]}
      "FAMILY": {"%s", ["sn"]}
      "FN": {"%s", ["displayName"]}
      "EMAIL": {"%s", ["mail"]}
      "ORGNAME": {"%s", ["company"]}
      "ORGUNIT": {"%s", ["department"]}
      "CTRY": {"%s", ["c"]}
      "LOCALITY": {"%s", ["l"]}
      "STREET": {"%s", ["streetAddress"]}
      "REGION": {"%s", ["st"]}
      "PCODE": {"%s", ["postalCode"]}
      "TITLE": {"%s", ["title"]}
      "URL": {"%s", ["wWWHomePage"]}
      "DESC": {"%s", ["description"]}
      "TEL": {"%s", ["telephoneNumber"]}]}
</code></pre>
<p>Do you see the problem?  I sure didn&#8217;t, and ejabberd was spitting out the following error in the log file:</p>
<p><code><strong>2015-02-03 17:17:08.699 [error] <0.36.0> CRASH REPORT Process <0.36.0> with 0 neighbours exited with reason: {undefined_macro,''} in application_master:init/4 line 133</strong></code></p>
<p>Here&#8217;s the problem: <strong>The documentation&#8217;s example uses commas when it should be using colons.</strong>  That&#8217;s it.  Of course I didn&#8217;t notice/know that for a few hours, so I tried every single bit of nonsense possible to reformat that section into valid YAML.</p>
<p>This is the <strong>correct, working</strong> <code>mod_vcard_ldap</code> section of my configuration.  Note that I pared it down a bit because I don&#8217;t populate all of the VCard fields in Active Directory anyhow:</p>
<pre><code>  mod_vcard_ldap:
    ldap_uids: {"sAMAccountName": "%u"}
    ldap_filter: ""
    matches: infinity
    ldap_vcard_map:
      "NICKNAME": {"%s": ["displayName"]}
      "FN": {"%s": ["displayName"]}
      "EMAIL": {"%s": ["mail"]}
      "GIVEN": {"%s": ["givenName"]}
      "MIDDLE": {"%s": ["initials"]}
      "FAMILY": {"%s": ["sn"]}
      "ORGNAME": {"%s": ["company"]}
      "ORGUNIT": {"%s": ["department"]}
      "TITLE": {"%s": ["title"]}
      "TEL": {"%s": ["telephoneNumber"]}
    ldap_search_fields:
      "User": "%u"
      "Full Name":  "displayName"
      "Email": "mail"
    ldap_search_reported:
      "Full Name": "FN"
      "Nickname": "NICKNAME"
      "Email": "EMAIL"
</code></pre>
<p>It&#8217;s not strictly-speaking necessary to define <code>ldap_uids</code> in this section because ejabberd will use the LDAP settings you&#8217;ve previously defined.  <strong>However</strong> you should note that both the documentation and the plurality implied by the field name are inaccurate.  In the main LDAP config, the <code>ldap_uids</code> can be a list (array, whatever):</p>
<pre><code># Correct in main LDAP section
ldap_uids:
   - "sAMAccountName"
</code></pre>
<p>In the <code>mod_vcard_ldap</code> section, <strong>it is an object/mapping/whatever</strong>.  An error is thrown if you provide more than one uid field.  Also, the second (<code>%u</code>) parameter is required.</p>
<pre><code># Correct in mod_vcard_ldap section
ldap_uids: {"sAMAccountName": "%u"}
</code></pre>
<p>Hopefully my configuration examples here will save you the same headache I faced.</p>
<h3>mod_shared_roster</h3>
<p><strong>Oh man, was this ever a pain.</strong>  There are many conflicting examples, many half-baked workarounds, and many compromises to be decided upon.</p>
<p>I&#8217;m unclear on whether or not this is still true in the current release, but <strong>apparently spaces in a user&#8217;s CN causes <code>mod_shared_roster</code> to fail silently</strong>.</p>
<blockquote><p><strong>mikekaganski wrote:</strong><br />
That&#8217;s the most trouble, because the &#8220;member&#8221; stores its members as DNs, thus if you have your users like &#8220;CN=John Doe,OU=blah,OU=blah,DC=example,DC=com&#8221;, <strong>then we&#8217;re stuck</strong>. In the better case when you have CNs of your users without spaces, you may choose to use ldap_memberattr_format_re = &#8220;CN=(\\w*),(OU=.*,)*DC=example,DC=com&#8221; (this is from the guide, I didn&#8217;t test this regex).  <em>Source: <a href="https://www.ejabberd.im/node/4826" target="_blank">https://www.ejabberd.im/node/4826</a></em></p></blockquote>
<p>It took me a while to find that.  What does it mean?  Well the overly-simplified version of the <a href="http://www.process-one.net/docs/ejabberd/guide_en.html#msrlconfigroster" target="_blank">shared roster LDAP module&#8217;s alogrithm</a> goes like this:</p>
<ol>
<li>Run the <code>ldap_rfilter</code> query to get a list of groups that contain Jabber-able contacts</li>
<li>For each of those groups, run the <code>ldap_gfilter</code> query to get the group&#8217;s displayable name and member list.</li>
<li>For each distinct group member retrieved in step 2, get the user&#8217;s displayable name.</li>
</ol>
<p>Everything went wrong for me in step 2.  All of my users have their full name as their common name, as you can see below:</p>
<pre><code># ldapsearch -LLL -H ldap://dcserver01.mydomain.com -x -D 'mydomain\ejabberd.ldap' -w 'SomePassword2098' -E pr=1000/noprompt -b 'dc=mydomain,dc=com' '(&#038;(objectCategory=group)(cn=All Employees))' displayName member

dn: CN=All Employees,CN=Users,DC=mydomain,DC=com
member: CN=Jennifer Doe,CN=Users,DC=mydomain,DC=com
member: CN=Eric Von Lastname,CN=Users,DC=mydomain,DC=com
member: CN=Kieran Wonderbra,CN=Users,DC=mydomain,DC=com
displayName: All Employees
</code></pre>
<p><em>Note that I truncated and sanitized the output above.</em></p>
<p>As you can see, all the common names have spaces in them, and so it (I believe) is unparsable.  I tried variations on the <code>ldap_memberattr_format</code> and <code>ldap_memberattr_format_re</code> properties with no success.</p>
<p>After <strong>much hair pulling</strong>, this is my working configuration:</p>
<pre><code>  mod_shared_roster_ldap:
    ldap_groupattr: "sAMAccountName"
    ldap_groupdesc: ""
    ldap_memberattr: "sAMAccountName"
    ldap_memberattr_format: "%u"
    ldap_useruid: "sAMAccountName"
    ldap_userdesc: "displayName"
    ldap_rfilter: "(&#038;(objectCategory=group)(cn=All Employees))"
    ldap_gfilter: "(&#038;(objectCategory=user)(memberOf=CN=All Employees,CN=Users,DC=mydomain,DC=com))"
    ldap_ufilter: "(&#038;(objectClass=user)(sAMAccountName=%u))"
    ldap_filter: ""
    ldap_group_cache_validity: 60
    ldap_user_cache_validity: 60
    ldap_auth_check: off
</code></pre>
<p>Remember what I said about compromises?  Well, my <code>ldap_gfilter</code> query isn&#8217;t really giving the module what it wants:  A list of group members <strong>and the group&#8217;s displayable name</strong>.  That&#8217;s why I left <code>ldap_groupdesc</code> blank;  My query does not return the group&#8217;s name.  This means that my group&#8217;s name isn&#8217;t propagating to the chat clients.  The clients simply display a list of contacts outside of any particular group.  <strong>I have no problem with that, because I only have the one group that contains all employees.</strong></p>
<p>Here&#8217;s the output of my <code>ldap_gfilter</code> to <strong>contrast with the earlier example</strong> that retrieved a group&#8217;s members with <strong>just</strong> their distinguished names:</p>
<pre><code># ldapsearch -LLL -H ldap://dcserver01.mydomain.com -x -D 'mydomain\ejabberd.ldap' -w 'SomePassword2098' -E pr=1000/noprompt -b 'dc=mydomain,dc=com' 
\ '(&#038;(objectCategory=user)(memberOf=CN=All Employees,CN=Users,DC=mydomain,DC=com))' sAMAccountName

dn: CN=Kieran Wonderbra,CN=Users,DC=mydomain,DC=com
sAMAccountName: kwonderbra

dn: CN=Eric Von Lastname,CN=Users,DC=mydomain,DC=com
sAMAccountName: elastname

dn: CN=Jennifer Doe,CN=Users,DC=mydomain,DC=com
sAMAccountName: jdoe
</code></pre>
<p><em>Again, the output above has been sanitized and truncated for brevity.</em></p>
<p>I&#8217;m now retrieving the <code>sAMAccountName</code>, which I&#8217;ve referenced in the <code>ldap_useruid</code>.  The contents of <code>sAMAccountName</code> (e.g. <strong>jdoe</strong>) is then used in the <code>ldap_ufilter</code> in place of <code>%u</code>.</p>
<p>Also, note that I left my group common name (CN) of &#8220;All Employees&#8221; hard-coded in all three filters.  In the <code>ldap_gfilter</code> and the <code>ldap_ufilter</code> fields you can use <code><strong>%g</strong></code>, which will be replaced with the content of the field defined in <code>ldap_groupattr</code> (which is &#8220;sAMAccountName&#8221; in my example).  I only want to have one group which represents all ejabberd users, so this works for me.</p>
<h2>Debugging Tools</h2>
<h3>ldapsearch</h3>
<p>Install and run this on your ejabberd server.  First off, <strong>you&#8217;re ensuring that you have connectivity</strong> between that server and your LDAP server (e.g. domain controller).</p>
<p>It will also allow you to <strong>independently test all of the LDAP filters</strong> in your configuration.</p>
<p>ldapsearch is <a href="http://www.openldap.org/software/man.cgi?query=ldapsearch&#038;apropos=0&#038;sektion=0&#038;manpath=OpenLDAP+2.0-Release&#038;format=html" target="_blank">well documented</a>, but here&#8217;s an example of its usage as appropriate to my environment:</p>
<p><code>ldapsearch -LLL -H ldap://dcserver01.mydomain.com -x -D 'mydomain\ejabberd.ldap' -w 'SomePassword2098' -E pr=1000/noprompt -b 'dc=mydomain,dc=com' '(&#038;(objectClass=user)(sAMAccountName=scott))'</code></p>
<p>That statement will retrieve all of the LDAP attributes for the <code>scott</code> user account.</p>
<h3>tcpdump and Wireshark</h3>
<p>OK, these are by no means the <strong>only</strong> appropriate tools out there, but they&#8217;re what I used.</p>
<p>In my environment, the traffic between the ejabberd server (in the public server &#8220;DMZ&#8221; network) and my domain controller (in the private office network) pass through a Linux-based router (i.e. a desktop PC with a lot of NICs).  I used <code>tcpdump</code> on the router to capture all of the packets between the two machines on port 389 (LDAP) to a file, and then used <code>scp</code> to transfer the packet dump to my Windows workstation for analysis with Wireshark.</p>
<p>Incidentally, the reason I captured packets at the router instead of on the ejabberd server was so that I could rule out connectivity/firewall issues.  The reason I didn&#8217;t run Wireshark on my domain controller is because I consider it bad practice to install anything unnecessary on my DC.</p>
<p>Here&#8217;s the <code>tcpdump</code> command to get a file that Wireshark will parse (obviously replace the IP address with that of your own ejabberd server):</p>
<p><code>tcpdump -s 0 -w ~/tcpdump.ldap.20150205-1202.pcap -nnXSvi eth4 "port 389 and host 10.101.1.57"</code></p>
<p>Also, I chose to use Wireshark rather than reading through the raw <code>tcpdump</code> output because it formats everything quite nicely:</p>
<p><a href="http://s.co.tt/wp-content/uploads/2015/02/wireshark_tcpdump_ldap_example.png"><img src="http://s.co.tt/wp-content/uploads/2015/02/wireshark_tcpdump_ldap_example-1024x751.png" alt="Wireshark tcpdump LDAP example" width="740" class="aligncenter size-large wp-image-1036" /></a></p>
<h2>Conclusion</h2>
<p>ejabberd does suffer a bit from being long on examples but short on consistency due to its old age.  It&#8217;s also developed (logically) by Linux/erlang people, and so they&#8217;re not as Active Directory LDAP friendly as I&#8217;d hoped.  (I don&#8217;t blame them for that, of course.  I went with a Linux-based ejabberd server for a reason.)</p>
<p>On the other hand, ejabberd is quite mature and extremely stable.  It&#8217;s been a great replacement for the proprietary and non-AD-integrated Google Talk.</p>
<p>I know that I didn&#8217;t give a comprehensive how-to guide here, but I&#8217;m hoping that at the very least my example configuration snippets point you in the right direction.</p>
<p><strong>As stated in the title, I am using ejabberd 14.12.</strong>  I installed using the binary installer <a href="http://www.process-one.net/en/ejabberd/downloads">from the <b>process one</b> website</a>.</b></p>
]]></content:encoded>
			<wfw:commentRss>http://s.co.tt/2015/02/05/making-ejabberd-14-12-work-with-microsoft-windows-active-directory-ldap/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
