RFC 2657

LDAPv2 Client vs. the Index Mesh

πŸ“… published August 1999, from ietf

RFC 2657: LDAPv2 Client vs. the Index Mesh πŸ¦‹

okay bestie, this one is by R. Hedberg from Catalogix, published in August 1999 🌸 It's in the Experimental category, so it's a "let's try this" proposal and not an Internet standard ✨ The header doesn't list anything it obsoletes or updates.

Status of this Memo ✨

This memo defines an Experimental Protocol for the Internet community πŸ’… It does not specify an Internet standard of any kind. Discussion and suggestions for improvement are requested 🫢 Distribution of this memo is unlimited.

Copyright (C) The Internet Society (1999). All Rights Reserved.

Abstract πŸ’–

LDAPv2 clients implemented per RFC 1777 [1] have no concept of referrals 😭 The Common Indexing Protocol [2] wants clients to talk to an Index Mesh, and that whole setup leans really hard on referrals, so the client has to be handled in a special way. This document lays out one possible way to do it πŸ¦‹

1. Background 🌈

When the Common Indexing Protocol (CIP) was being built, one big assumption was that clients and the Index Mesh Servers [1] would be constantly passing referrals back and forth πŸ”₯ Protocols like LDAPv2 [2] don't have that feature, so they need another way to make up for it. This memo goes with making the client smarter 🧠 Two reasons: it's not a major enhancement, and whatever smarts you need to deal with the Index Mesh, including referral knowledge, end up living in the client anyway πŸ’…

2. The clients view of the Index Mesh πŸ‘‘

If an LDAPv2 client is going to interact with the Index Mesh, the Mesh has to look like something the client can understand ✨ Basically, that means showing the index servers and the indexes they hold as a defined directory information tree (DIT) [3,4], using a set of object classes and attribute types that have proven useful for this job 🧚

2.1. The CIP Object Classes 🌸

Object class descriptions are written according to the BNF defined in [5] πŸ€“

2.1.1. cIPIndex πŸ’œ

If an entry has the cIPIndex objectClass, it can hold one indexvalue plus the info connected to that value πŸŽ€

( 1.2.752.17.3.9
  NAME 'cIPIndex'
  SUP 'top'
  STRUCTURAL
  MUST ( extendedDSI $ idx )
  MAY ( indexOCAT )
)

2.1.2. cIPDataSet πŸ“

If an entry has the cIPDataSet objectClass, it holds info about one DataSet πŸ’–

( 1.2.752.17.3.10
  NAME 'cIPDataSet'
  SUP 'top'
  STRUCTURAL
  MUST ( dSI $ searchBase )
  MAY ( indexOCAT $ description $ indexType $
        accessPoint $ protocolVersion $ polledBy $
        updateIntervall $ securityOption $
        supplierURI $ consumerURI $ baseURI $
        attributeNamespace $ consistencyBase
   )
)

2.2. The CIP attributeTypes πŸ¦‹

The attributes idx, indexOCAT, extendedDSI, description, cIPIndexType, baseURI and dSI are the ones a client uses when it's accessing the index server πŸ‘€ The rest (accesspoint, protocolVersion, polledBy, updateIntervall, consumerURI, supplierURI and securityOption, attributeNamespace, consistencyBase) are for server to server interactions πŸ”

2.2.1. idx ✨

The index value, normally used as part of the RDN πŸ’…

( 1.2.752.17.1.20
  NAME 'idx'
  EQUALITY caseIgnoreIA5Match
  SYNTAX IA5String
  SINGLE-VALUE
   )

2.2.2. dSI 🌷

DataSet Identifier, a unique identifier for one particular set of information πŸ” It should be an OID, but it's stored as a string.

( 1.2.752.17.1.21
  NAME 'dSI'
  EQUALITY caseIgnoreIA5Match
  SYNTAX IA5String
)

2.2.3. indexOCAT 🌈

This describes the type of data stored in the entry, using objectClasses and attributeTypes πŸ“š The info is stored as an objectClass name, then a space, then an attributeType name. For whitepages info, a typical example is "person cn" πŸ’•

( 1.2.752.17.1.28
  NAME 'indexOCAT'
  EQUALITY caseIgnoreIA5Match
  SYNTAX IA5String
)

2.2.5. supplierURI πŸ›Έ

A URI describing which protocols, hostnames and ports an indexserver should use to talk to servers carrying index info for this dataSet 🌐

  ( 1.2.752.17.1.22
   NAME 'supplierURI'
   EQUALITY caseIgnoreIA5Match
   SYNTAX IA5String
)

2.2.6. baseURI πŸ¦‹

The value of this attribute is an LDAP URI πŸ’– You could imagine other URI syntaxes if the client knows about access protocols besides LDAP, and the client and server can't use referrals for some reason πŸ™ˆ

( 1.2.752.17.1.26
  NAME 'baseURI'
  EQUALITY caseExactIA5Match
  SYNTAX IA5String
)

2.2.7. protocolVersion πŸŽ€

Right now, the Common Indexing Protocol version should be 3 ✨

( 1.2.752.17.1.27
  NAME 'protocolVersion'
  EQUALITY numericStringMatch
  SYNTAX numericString
)

2.2.8. cIPIndexType πŸ’œ

The type of index Object used to pass index information around 🎁

( 1.2.752.17.1.29
  NAME 'cIPIndexType'
  EQUALITY caseIgnoreIA5Match
  SYNTAX IA5String
)

2.2.10. polledBy 🌸

The Distinguished Name of the Index servers that poll data from this indexserver 🫢

( 1.2.752.17.1.30
  NAME 'polledBy'
  EQUALITY distinguishedNameMatch
  SYNTAX DN
)

2.2.11. updateIntervall ⏰

The maximum duration, in seconds, between the generation of two updates by the supplier server ⭐

( 1.2.752.17.1.31
  Name 'updateIntervall'
  EQUALITY numericStringMatch
  SYNTAX numericString
  SINGLE-VALUE
)

2.2.12. securityOption πŸ”

Whether and how the supplier server should sign and encrypt the update before it sends it to the consumer server πŸ›‘οΈ

( 1.2.752.17.1.32
  NAME 'securityOption'
  EQUALITY caseIgnoreIA5Match
  SYNTAX IA5String
  SINGLE-VALUE
)

2.2.13. extendedDSI 🧩

A DataSet Identifier, possibly followed by a space and a taglist, with the taglist as specified by [6] πŸ’…

( 1.2.752.17.1.33
  NAME 'extendedDSI'
  EQUALITY caseIgnoreIA5Match
  SYNTAX IA5String
     )

2.2.14. consumerURI πŸ’Œ

A URI describing the means by which a server can accept index information πŸ“¬ An example is a mailto URI for MIME email based index transport πŸ’Œ

( 1.2.752.17.1.34
  NAME 'consumerURI'
  EQUALITY caseExactIA5Match
  SYNTAX IA5String
)

2.2.15. attributeNamespace πŸ—‚οΈ

Any consumer and supplier pair has to agree on which attribute should be used, and maybe also what the attribute names mean 🀝 The value of this attribute should, for example, be a URI pointing to a document where that agreement is written down πŸ“„

( 1.2.752.17.1.35 NAME 'attributeNamespace' EQUALITY
  caseExactIA5Match SYNTAX IA5String
)

2.2.16. consistencyBase 🧱

This attribute is specifically used by consumer and supplier pairs that use the tagged index object [6] 🏷️

( 1.2.752.17.1.36
  NAME 'consistencyBase'
  EQUALITY caseExactIA5Match
  SYNTAX IA5String
)

3. The interaction between a client and the Index Mesh πŸ¦‹

A client's interaction with the Index Mesh is made of a few pretty clear steps πŸͺœ First, find a suitable index to start from. Then, traverse the Index Mesh. Finally, query the servers that hold the original data ✨ Heads up: this section is about the client's view of the DIT, not how it's actually implemented under the hood πŸ‘€

3.1. Finding a Index Mesh πŸ”Ž

This approach depends on every index server in an Index Mesh being represented in the DIT by an entry of type cIPDataSet πŸ’œ That entry has a distinguished name (DN) whose most significant relative distinguished name (RDN) has the attributetype dSI. So finding a good indexserver to start searching from means searching the DIT in a sensible place for objects with the objectClass cIPIndexObject πŸ•΅οΈβ€β™€οΈ You can then evaluate each entry you find by looking at its description value and its indexOCAT value. The description should be human readable and understandable text that says what the index server is indexing πŸ“ For example: "This index covers all employees at Swedish Universities and University Colleges that has an email account" πŸ‡ΈπŸ‡ͺ The indexOCAT attribute tells you what kind of entries the index came from, and which attributes in those entries it came from. For example, if indexOCAT is "person cn", you can tell it's an index over persons and not roles, and that the attribute being indexed is commonName 🧠

3.2. Searching the mesh πŸ•ΈοΈ

Each index server keeps its information in the DIT as a very flat tree πŸ₯ž It's only one level deep.

                    0 Indexservers cIPDataSet
                   /|\
                  / | \
                 /  |  \
                /   |   \
               0    0    0
  cIPDataSet entries     cIPIndex entries
  one for each DataSet   one for each index value
  that this server has   that this indexserver
  gathered indexes from. has.

A search is really a set of searches πŸ” The first one looks for index entries that contain an indexvalue matching what the user wants. The second one searches based on the DSI information in the extendedDSI attribute values returned by the first search. If the cIPIndexType is tagged-index, the taglists should be compared to figure out which DSI might be useful to send further queries to 🏷️

When doing these searches, the client should keep in mind that index values, no matter where they came from (attributeTypes), are always stored in the index server as values of the idx attribute πŸ’‘

The second search is there to get info about the different DataSets involved, and it should normally be performed as a read πŸ“– Since DataSet info will probably stay pretty stable over time, it's a great candidate for caching πŸ’Ύ If more than one DataSet is involved at this stage, the User interface might use the description value to help the user pick which one to go with πŸ™‹β€β™€οΈ The content of the DataSet's searchBase value tells the client whether it points to another index server (the most significant part of the dn is a dSI attribute) or to an end server 🎯

3.3. Querying the end server 🎯

Once you reach the end server or servers that probably have the info you're after, you can use the indexOCAT attribute to build a suitable filter πŸ”§ For example, say you search for "Rol*" in an index whose indexOCAT value is "person cn", and it returns an idx entry with the idx value "Roland". A filter that could work is &(|(cn=* roland *)(cn=roland *)(cn=* roland))(objectclass=person). A complete example of a search process is given in Appendix A πŸ“œ

4. Security Considerations πŸ”

⚠️ Since this memo is about client behavior, it doesn't add anything that either enhances or diminishes the security features that already exist in LDAPv2 😭 Security is still a big deal, so keep that in mind.

5. Internationalization 🌍

Just like with security, this memo neither enhances nor diminishes how LDAPv2 handles internationalization 🌏


Part 1 is done, bestie! Part 2 is coming soon πŸ’–πŸŽ€

6. References πŸ“š

Okay bestie, here's the reading list πŸ€“ Every one of these is cited in the spec, so they all stay put:

  • [1] Yeong, W., Howes, T. and S. Kille, "Lightweight Directory Access Protocol", RFC 1777, March 1995.
  • [2] Allen, J. and M. Mealling "The Architecture of the Common Indexing Protocol (CIP)", RFC 2651, August 1999.
  • [3] The Directory: Overview of Concepts, Models and Service. CCITT Recommendation X.500, 1988.
  • [4] Information Processing Systems -- Open Systems Interconnection -- The Directory: Overview of Concepts, Models and Service. ISO/IEC JTC 1/SC21; International Standard 9594-1, 1988.
  • [5] Wahl, M., Coulbeck, A., Howes, T. and S. Kille, "Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions", RFC 2252, December 1997.
  • [6] Hedberg, R., Greenblatt, B., Moats, R. and M. Wahl, "A Tagged Index Object for use in the Common Indexing Protocol", RFC 2654, August 1999.

7. Author's Address πŸŽ€

This is who wrote it, and yes, this is the real contact info πŸ’Œ

Roland Hedberg
Catalogix
Dalsveien 53
0387 Oslo, Norway

Phone: +47 23 08 29 96
EMail: roland@catalogix.ac.se

Appendix A - Sample Session 🧚

Okay, the grand finale! πŸŽ‰ This is a worked example of a session between an LDAPv2 client and an index server mesh, as the memo describes. The client's big question is: what's the email address of a person named "Roland Hedberg" who works at "Umea University" in Sweden? Let's watch the detective work πŸ•΅οΈβ€β™€οΈβœ¨

Step 1.

So first, the client runs a single-level search with the base address c=SE and the filter (objectclass=cipDataset). The server sends back two indexes πŸ’…

DN: dSI=1.2.752.17.5.0,c=SE
dsi= 1.2.752.17.5.0
description= "index over employees with emailaddresses within Swedish
higher education"
indexOCAT= "cn person"
cIPIndexType= "x-tagged-index-1" ;
searchBase= "dsi=1.2.752.17.5.0,c=SE"
protocolVersion = 3

DN: dSI=1.2.752.23.1.3,c=SE
dsi= 1.2.752.23.1.3
description= "index over Swedish lawyers"
indexOCAT= "cn person"
cIPIndexType= "x-tagged-index-1" ;
searchBase= "dsi=1.2.752.23.1.3,c=SE"
protocolVersion = 3

Step 2.

The first index looks like the right crowd, so the client runs a single-level search with the base address dsi=1.2.752.17.5.0,c=SE and the filter (|(idx=roland)(idx=hedberg)). Here's what comes back πŸ‘€

DN: idx=Roland,dSI=1.2.752.17.5.0,c=SE
idx= Roland
extendedDSI= 1.2.752.17.5.10 1,473,612,879,1024
extendedDSI= 1.2.752.17.5.14 35,78,150,200
extendedDSI= 1.2.752.17.5.16 187,2031,3167,5284,6034-6040
extendedDSI= 1.2.752.17.5.17 17
DN: idx=Hedberg,dSI=1.2.752.17.5.0,c=SE
idx= Hedberg
extendedDSI= 1.2.752.17.5.8  24,548-552,1066
extendedDSI= 1.2.752.17.5.10 473,512,636,777,1350
extendedDSI= 1.2.752.17.5.14 84,112,143,200
extendedDSI= 1.2.752.17.5.15 1890-1912
extendedDSI= 1.2.752.17.5.17 44

Comparing the two sets of extendedDSIs, the datasets 1.2.752.17.5.10 and 1.2.752.17.5.14 are the ones with people named "Roland" and "Hedberg" in them 🎯 Next up is checking what those datasets actually are. Honestly, this kind of comparison shouldn't be left to the user, it's giving tedious ngl πŸ™„

Step. 3

Now the client does two base-level searches, one on dsi=1.2.752.17.5.10,dsi=1.2.752.17.5.0,c=SE and one on dsi=1.2.752.17.5.14,dsi=1.2.752.17.5.0,c=SE, both with the filter (objectclass=cipdataset). Results:

DN: dSI=1.2.752.17.5.10,dSI=1.2.752.17.5.0,c=SE
dsi= 1.2.752.17.5.10
description= "Employees at Umea University,Sweden"
indexOCAT= "person cn"
searchBase= "o=Umea Universitet,c=SE"

respectively

DN: dSI=1.2.752.17.5.14,dSI=1.2.752.17.5.0,c=SE
dsi= 1.2.752.17.5.14
description= "Employees at Lund University,Sweden"
indexOCAT= "person cn"
searchBase= "o=Lunds Universitet,c=SE"

Step 4

Based on those descriptions, 1.2.752.17.5.10 is the winner πŸ† Its searchBase tells us it's a base server, so the query has to be tweaked a bit. One option is to search the base object o=Umea Universitet,c=SE with the filter (&(cn=Roland Hedberg)(objectclass=person)). Main character energy πŸ‘‘


Legal stuff, but it's important, so here it is word for word so nothing gets lost in translation 🫢

Copyright (C) The Internet Society (1999).  All Rights Reserved.

This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works.  However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.

The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Acknowledgement 🌸

Funding for the RFC Editor function is currently provided by the Internet Society. Thank you to them for keeping the lights on πŸ’–

πŸ“¦ where this page comes from