View comments | RSS feed

Advanced topics

The following sections present advanced topics that enable you to use LDAP directories more effectively.

Specifying an attribute that includes a comma or semicolon

LDAP attribute values can contain commas. The cfldap tag normally uses commas to separate attribute values in a value list. Similarly, an attribute can contain a semicolon, which cfldap normally uses to delimit (separate) attributes in an attribute list. To override the default separator and delimiter characters, you use the cfldap tag separator and delimiter attributes.

For example, assume you want to add the following attributes to an LDAP entry:

cn=Proctor, Goodman, and Jones
description=Friends of the company; Rationalists

Use the cfldap tag in the following way:

<cfldap action="modify"
  modifyType="add"
  attributes="cn=Proctor, Goodman, and Jones: description=Friends
of the company; Rationalists"
  dn="uid=goodco, ou=People, o=Airius.com"
  separator="&"
  delimiter=":"
  server=#myServer#
  username=#myUserName#
  password=#myPassword#>

Using cfldap output

You can create a searchable Verity collection from LDAP data. building a Verity collection using an LDAP directory, see "Indexing cfldap query results," in Chapter24.

The ability to generate queries from other queries is very useful when cfldap queries return complex data. For more information on querying queries, see Chapter 22, "Using Query of Queries"

Viewing a directory schema

LDAP v3 exposes a directory's schema information in a special entry in the root DN. You use the directory root subschemaSubentry attribute to access this information.

The following ColdFusion query shows how to get and display the directory schema. It displays information from the schema's object class and attribute type definitions. For object classes, it displays the class name, superior class, required attribute types, and optional attribute types. For attribute types, it displays the type name, type description, and whether the type is single- or multivalued.

The example does not display all the information in the schema. For example, it does not display the matching rules. It also does not display the object class IDs, attribute type IDs, attribute type syntax IDs, or the object class descriptions. (The object class description values are all "Standard Object Class.")

Note:   To be able to view the schema for an LDAP server, the server must support LDAP v3.

This example does not work on iPlanet Directory Server 5.0. It does work on a 4.x server.

To view the schema for an LDAP directory:

  1. Create a new file that looks like the following:
    <html>
    <head>
      <title>LDAP Schema</title>
    </head>
    
    <body>
    <!--- Start at Root DSE to get the subschemaSubentry attribute --->
    <cfldap 
      name="EntryList"
      server="ldap.mycorp.com"
      action="query"
      attributes="subschemaSubentry"
      scope="base"
      start="">
    
    <!--- Use the DN from the subschemaSubEntry attribute to get the schema --->
    <cfldap 
      name="EntryList2"
      server="ldap.mycorp.com"
      action="query"
      attributes="objectclasses, attributetypes"
      scope="base"
      filter="objectclass=*"
      start=#entryList.subschemaSubentry#>
    
    <!--- Only one record is returned, so query loop is not required --->
    <h2>Object Classes</h2>
    <table border="1">
      <tr>
        <th>Name</th>
        <th>Superior class</th>
        <th>Must have</th>
        <th>May have</th>
      </tr>
      <cfloop index = "thisElement" list = #Entrylist2.objectclasses#>
        <cfscript>
          thiselement = Trim(thisElement);
          nameloc = Find("NAME", thisElement);
          descloc = Find("DESC", thisElement);
          suploc = Find("SUP", thisElement);
          mustloc = Find("MUST", thisElement);
          mayloc = Find("MAY", thisElement);
          endloc = Len(thisElement);
        </cfscript>
        <tr>
          <td><cfoutput>#Mid(thisElement, nameloc+6, descloc-nameloc-8)#
            </cfoutput></td>
          <cfif #suploc# NEQ 0>
            <td><cfoutput>#Mid(thisElement, suploc+5, mustloc-suploc-7)#
            </cfoutput></td>
          <cfelse>
            <td>NONE</td>
          </cfif>
          <cfif #mayloc# NEQ 0>
            <td><cfoutput>#Replace(Mid(thisElement, mustloc+6,
              mayloc-mustloc-9), " $ ", ", ", "all")#</cfoutput></td>
            <td><cfoutput>#Replace(Mid(thisElement, mayloc+5, endloc-mayloc-8),
              " $ ", ", ", "all")#</cfoutput></td>
          <cfelse>
            <td><cfoutput>#Replace(Mid(thisElement, mustloc+6,
              endloc-mustloc-9), " $ ", ", ", "all")#</cfoutput></td>
            <td>NONE</td>
          </cfif>
        </tr>
      </cfloop> 
    </table>
    <br><br>
    
      <h2>Attribute Types</h2>
    <table border="1" >
      <tr>
        <th>Name</th>
        <th>Description</th>
        <th>multivalued?</th>
      </tr>
      <cfloop index = "thisElement" 
        list = #ReplaceNoCase(EntryList2.attributeTypes, ", alias", "<br> Alias", 
        "all")# delimiters = ",">
        <cfscript>
          thiselement = Trim(thisElement);
          nameloc = Find("NAME", thisElement);
          descloc = Find("DESC", thisElement);
          syntaxloc = Find("SYNTAX", thisElement);
          singleloc = Find("SINGLE", thisElement);
          endloc = Len(thisElement);
        </cfscript>
        <tr>
          <td><cfoutput>#Mid(thisElement, nameloc+6, descloc-nameloc-8)#
            </cfoutput></td>
          <td><cfoutput>#Mid(thisElement, descloc+6, syntaxloc-descloc-8)#
            </cfoutput></td>
          <cfif #singleloc# EQ 0>
             <td><cfoutput>Yes</cfoutput></td>
          <cfelse>
             <td><cfoutput>No</cfoutput></td>
          </cfif>
        </tr>
      </cfloop> 
    </table>
    </body>
    </html>
    
  2. Change the server from ldap.mycorp.com to your LDAP server. You might also need to specify a user ID and password in the cfldap tag.
  3. Save the template as ldapschema.cfm in myapps under your web root directory and view it in your browser.

Reviewing the code

The following table describes the code and its function:
Code
Description
<cfldap 
	name="EntryList"
	server="ldap.mycorp.com"
	action="query"
	attributes="subschemaSubentry"
	scope="base"
	start="">
Gets the value of the subschemaSubentry attribute from the root of the directory server. The value is the DN of the schema.
<cfldap 
	name="EntryList2"
	server="ldap.mycorp.com"
	action="query"
	attributes="objectclasses,
		attributetypes"
	scope="base"
	filter="objectclass=*"
	start=#entryList.subschemaSubentry#>
Uses the schema DN to get the objectclasses and attributetypes attributes from the schema.
<h2>Object Classes</h2>
<table border="1">
	<tr>
		<th>Name</th>
		<th>Superior class</th>
		<th>Must have</th>
		<th>May have</th>
	</tr>
	<cfloop index = "thisElement" list =
			#Entrylist2.objectclasses#>
		<cfscript>
			thisElement = Trim(thisElement);
			nameloc = Find("NAME",
				thisElement);
			descloc = Find("DESC",
				thisElement);
			suploc = Find("SUP", thisElement);
			mustloc = Find("MUST",
				thisElement);
			mayloc = Find("MAY", thisElement);
			endloc = Len(thisElement);
		</cfscript>
Displays the object class name, superior class, required attributes, and optional attributes for each object class in a table.
The schema contains the definitions of all object classes in a comma delimited list, so the code uses a list type cfloop tag.
The thisElement variable contains the object class definition. Trim off any leading or trailing spaces, then use the class definition field keywords in Find functions to get the starting locations of the required fields, including the Object class ID. (The ID is not displayed.)
Gets the length of the thisElement string for use in later calculations.
		<tr>
			<td><cfoutput>#Mid(thisElement,
				nameloc+6, descloc-nameloc-8)
				#</cfoutput></td>
			<cfif #suploc# NEQ 0>
				<td><cfoutput>#Mid(thisElement,
				suploc+5, mustloc-suploc-7)#
				</cfoutput></td>
			<cfelse>
				<td>NONE</td>
			</cfif>
			<cfif #mayloc# NEQ 0>
			 <td><cfoutput>#Replace
				(Mid(thisElement, mustloc+6,
				mayloc-mustloc-9), " $ ", ", ",
				"all")#</cfoutput></td>
			 <td><cfoutput>#Replace
				(Mid(thisElement, mayloc+5,
				endloc-mayloc-8), " $ ", ", ",
				"all")#</cfoutput></td>
			<cfelse>
			 <td><cfoutput>#Replace
				(Mid(thisElement, mustloc+6,
				endloc-mustloc-9), " $ ", ", ",
				"all")#</cfoutput></td>
			 <td>NONE</td>
			</cfif>
		</tr>
	</cfloop>
</table>
Displays the field values. Uses the Mid function to extract individual field values from the thisElement string.
The top object class does not have a superior class entry. Handles this special case by testing the suploc location variable. If the value is not 0, handles normally, otherwise, output "NONE".
There might not be any optional attributes. Handles this case similarly to the superior class. The calculation of the location of required attributes uses the location of the optional attributes if the field exists; otherwise, uses the end of the object class definition string.
	<h2>Attribute Types</h2>
	<table border="1" >
		<tr>
			<th>Name</th>
			<th>Description</th>
			<th>Multivalued?</th>
		</tr>
		<cfloop index = "thisElement" list =
			 #ReplaceNoCase(attributeTypes, ",
			 alias", "<br> Alias", "all")#
			 delimiters = ",">
			<cfscript>
			 thiselement = Trim(thisElement);
			 nameloc = Find("NAME",
				thisElement);
			 descloc = Find("DESC",
				thisElement);
			 syntaxloc = Find("SYNTAX",
				thisElement);
			 singleloc = Find("SINGLE",
				thisElement);
			 endloc = Len(thisElement);
			</cfscript>
		<tr>
			<td><cfoutput>#Mid(thisElement,
				nameloc+6, descloc-nameloc-8)#
				</cfoutput></td>
			<td><cfoutput>#Mid(thisElement,
				descloc+6, syntaxloc-descloc-8)
				#</cfoutput></td>
			<cfif #singleloc# EQ 0>
				 <td><cfoutput>Yes</cfoutput>
				</td>
			<cfelse>
				 <td><cfoutput>No</cfoutput>
				</td>
			</cfif>
		</tr>
	</cfloop> 
</table>
</cfloop>
Does the same types of calculations for the attribute types as for the object classes.



The attribute type field can contain the text ", alias for....". This text includes a comma, which also delimits attribute entries. Use the ReplaceNoCase function to replace any comma that precedes the word "alias" with an HTML <br> tag.



The attribute definition includes a numeric syntax identifier, which the code does not display, but uses its location in calculating the locations of the other fields.

Referrals

An LDAP database can be distributed over multiple servers. If the requested information is not on the current server, the LDAP v3 standard provides a mechanism for the server to return a referral to the client that informs the client of an alternate server. (This feature is also included in some LDAP v2-compliant servers.)

ColdFusion can handle referrals automatically. If you specify a nonzero referral attribute in the cfldap tag, ColdFusion sends the request to the server specified in the referral.

The referral attribute value specifies the number of referrals allowed for the request. For example, if the referral attribute is 1, and server A sends a referral to server B, which then sends a referral to server C, ColdFusion returns an error. If the referral attribute is 2, and server C has the information, the LDAP request succeeds. The value to use depends on the topology of the distributed LDAP directory, the importance of response speed, and the value of response completeness.

When ColdFusion follows a referral, the rebind attribute specifies whether ColdFusion uses the cfldap tag login information in the request to the new server. The default, No, sends an anonymous login to the server.

Managing LDAP security

When you consider how to implement LDAP security, you must consider server security and application security.

Server security

The cfldap tag supports secure socket layer (SSL) v2, security. This security provides certificate-based validation of the LDAP server. It also encrypts data transferred between the ColdFusion Server and the LDAP server, including the user password, and ensures the integrity of data passed between the servers.

The LDAP server sends a certificate that is securely "signed" by a trusted authority and identifies (authenticates) the sender. The ColdFusion server uses the certificate to ensure that the server is valid. The ColdFusion server does not send the LDAP server a certificate, and you must use the cfldap tag username and password attributes to authenticate yourself to the LDAP server.

To use security, first ensure that the LDAP server supports SSL v3 security.

Specify the cfldap tag secure attribute as follows:

secure = "cfssl_basic"

For example:

<cfldap action="modify"
  modifyType="add"
  atributes="cn=Lizzie"
  dn="uid=lborden, ou=People, o=Airius.com"
  server=#myServer#
  username=#myUserName#
  password=#myPassword#
  secure="cfssl_basic"
  port=636>

The port attribute specifies the server port used for secure LDAP communications, which is 636 by default. If you do not specify a port, ColdFusion attempts to connect to the default, nonsecure, LDAP port 389.

Application security

To ensure application security, you must prevent outsiders from gaining access to the passwords that you use in cfldap tags. The best way to do this is to use variables for your username and password attributes. You can set these variables on one encrypted application page. For more information on securing applications, see Chapter 16, "Securing Applications".

ColdFusion 9 | ColdFusion 8 | ColdFusion MX 7 | ColdFusion MX 6.1 | ColdFusion MX | Forums | Developer Center | Bug Reporting

Version 6

Comments are no longer accepted for ColdFusion MX. ColdFusion 8 is the current version.

Comments


No screen name said on Sep 2, 2003 at 6:11 PM :
(SSL + LDAP) doesn’t work

I have installed a CA and issued a Certificate to my DC (Windows 2003 DC) and it is serving requests via SSL on port 636

But all I get is the following:
Connection to LDAP Server failed
This is my code:

<cfldap action="QUERY"
name="results"
attributes="sn,givenname,department,telephoneNumber,mobile,mail"
start="cn=users,dc=Domain,dc=local"
filter="(objectclass=user)"
server="10.10.1.13"
username="doamin.local\adminaccount"
password="adminpassword"
secure="cfssl_basic"
port=636>

If I remove the Secure and Port 636 I get the following:

Inappropriate authentication
I think because MS Win2K3 makes you use SSL so you can’t send clear text password to LDAP.

Please Help!
cfugottawa said on Sep 10, 2003 at 7:40 AM :
I think you have to add to the secure attribute. Currently you have secure="cfssl_basic" but the documentation says you need to have something like: secure="cfssl_basic,c:\cfusiondap\cert7.db
halL said on Sep 10, 2003 at 9:13 AM :
You should not specify a cert7.db file.
See the comment by sgilson102 in the livedocs comments on the cfldap reference page,
http://livedocs.macromedia.com/coldfusion/6/CFML_Reference/Tags-pt165.htm
thecoolcoder said on Dec 10, 2003 at 12:09 PM :
Why do you not elaborate on SSL v3 method using SSL_CLIENT_AUTH attribute? I have found nothing that is self explanatory anywhere.
J.C. said on Oct 13, 2004 at 8:56 AM :
Can you elaborate more on updating Active Directory attributes. I've been successful updating the homePhone, cn, samaccountname attributes, but I've had no luck updating the group membership attribute, "memberof". I've discovered that you must update the "member" attribute of a group, but I've only had luck updating the "description" field of a group and the "member" field throws me errors. I'm hoping you can give detail as to how this attribute is updated.

Thank you!
Cubonic said on Oct 18, 2004 at 11:13 PM :
I had a similar problem updating group membership. I found that the problem was due to the dn being miss interpreted. In particular the commas in the dn caused the were interpreted as additional values for the attributes. This problem can be worked around by changing the separator character.

For instance
after setting up all the appropriate coldfusion variables
<pre>
&lt;CFSET userdn="CN=#id#,#accountTree#"&gt;
&lt;CFLDAP SERVER="#ldapServer#"
USERNAME="#ldapAdmin#"
PASSWORD="#ldapPassword#"
SEPARATOR="&"
DN="#group#,#groupTree#"
ACTION="Modify"
MODIFYTYPE="Add"
ATTRIBUTES="member=#userdn#"
&gt;
kh91 said on Mar 9, 2005 at 10:14 AM :
Has anyone gotten this working with Windows Server 2003?

I'm trying to do a simple query to return info for a single user. I have not set up SSL security on the Windows server side, if I attempt the query without doing a bind (username= password=) then I get a "You must bind inorder to perform this query" back from Windows. If I add username/password I get ColdFusion blowing up with the "Inappropriate authentication" message.

This works FINE using perl, or PHP from the same computer, it's only with ColdFusion it won't work. Help please?
jrunrandy said on Mar 14, 2005 at 1:13 PM :
LiveDocs does not receive enough traffic to handle questions like this effectively. You will get a better and quicker response by posting your issue to the online forums: http://webforums.macromedia.com/coldfusion/
jrunrandy said on Mar 14, 2005 at 1:56 PM :
kh91 e-mailed me to say that the problem is fixed:
***
Actually I solved it. I assumed that the username would be in
DN format if you do that then ColdFusion gives you the error I mentioned.
If you just use the raw username it works.
***
No screen name said on Mar 18, 2005 at 11:35 AM :
Hi Everyone,

I am trying to make an LDAP query with SSL, my query connects without SSL, in my code. I have SSL setup on the server that it is talking to, that works correctly, confirmed it with the LDAP browser provided by Microsoft. The problem is that it does not connect with my code that is at port 636 and CFBasic, I am suppose to import the CA certificate or ldap certificate so ColdFusion understands it with this command -->
--------------------------
X:\CFusionMX7\runtime\jre\bin\keytool.exe -import -keystore cacerts -file {C:\web.cer} -alias ldapserver-cert -storepass xxxxxxx

//XXXX means password provided
--------------------------
It gives me an error stating it cannot find the file, the file is there, i checked it, Any ideas on what the heck I am missing in this? Macromedia also states that I should import the CA certificate or the ldap certificate(where are they usually located on a enterprise certificate server?????), can I use any certifcate? I checked with ColdFusions website the code is exact for the import command. I am kinda lost at this point.


Thanks,
Ross
jrunrandy said on Mar 24, 2005 at 12:49 PM :
You will get a better and quicker answer by posting questions like this to the online forums: http://webforums.macromedia.com/

 

RSS feed | Send me an e-mail when comments are added to this page | Comment Report

Current page: http://livedocs.adobe.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/LDAP7.htm