RFC 4524

COSINE LDAP/X.500 Schema

๐Ÿ“… published June 2006, from ietf

RFC 4524: COSINE LDAP/X.500 Schema ๐ŸŽ€

Okay bestie, so this is RFC 4524 ๐Ÿ’–. It's called COSINE LDAP/X.500 Schema, and it was written by K. Zeilenga, Ed. at the OpenLDAP Foundation in June 2006 โœจ. It's a Standards Track doc in the Network Working Group, and it obsoletes RFC 1274 and updates RFC 2247 and RFC 2798 ๐Ÿงš. Get ready for some schema realness.


Status of This Memo โœจ

This document is an Internet standards track protocol for the Internet community, and it's basically asking everyone for discussion and suggestions to make it better ๐Ÿซถ. If you want to know where this protocol stands in standardization, check the current edition of the "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited, so share away ๐Ÿ’….

Copyright (C) The Internet Society (2006). Mine, yours, everyone's, lol ๐Ÿ’œ.

Abstract ๐Ÿฆ‹

This doc is a collection of schema elements for the Lightweight Directory Access Protocol (LDAP), coming from the COSINE and Internet X.500 pilot projects ๐ŸŒธ.

It obsoletes RFC 1274 and updates RFCs 2247 and 2798, so it's a whole glow-up moment ๐Ÿ‘‘.

Table of Contents ๐Ÿ“š

   1. Introduction ....................................................3
      1.1. Relationship to Other Documents ............................3
      1.2. Terminology and Conventions ................................4
   2. COSINE Attribute Types ..........................................4
      2.1. associatedDomain ...........................................4
      2.2. associatedName .............................................5
      2.3. buildingName ...............................................5
      2.4. co .........................................................5
      2.5. documentAuthor .............................................6
      2.6. documentIdentifier .........................................6
      2.7. documentLocation ...........................................6
      2.8. documentPublisher ..........................................7
      2.9. documentTitle ..............................................7
      2.10. documentVersion ...........................................7
      2.11. drink .....................................................8
      2.12. homePhone .................................................8
      2.13. homePostalAddress .........................................8
      2.14. host ......................................................9
      2.15. info ......................................................9
      2.16. mail ......................................................9
      2.17. manager ..................................................10
      2.18. mobile ...................................................10
      2.19. organizationalStatus .....................................11
      2.20. pager ....................................................11
      2.21. personalTitle ............................................11
      2.22. roomNumber ...............................................12
      2.23. secretary ................................................12
      2.24. uniqueIdentifier .........................................12
      2.25. userClass ................................................13
   3. COSINE Object Classes ..........................................13
      3.1. account ...................................................13
      3.2. document ..................................................14
      3.3. documentSeries ............................................14
      3.4. domain ....................................................15
      3.5. domainRelatedObject .......................................16
      3.6. friendlyCountry ...........................................16
      3.7. rFC822LocalPart ...........................................17
      3.8. room ......................................................18
      3.9. simpleSecurityObject ......................................18
   4. Security Considerations ........................................18
   5. IANA Considerations ............................................19
   6. Acknowledgements ...............................................20
   7. References .....................................................20
      7.1. Normative References ......................................20
      7.2. Informative References ....................................21
   Appendix A.  Changes since RFC 1274 ...............................23
      A.1.  LDAP Short Names .........................................23
      A.2.  pilotObject ..............................................23
      A.3.  pilotPerson ..............................................23
      A.4.  dNSDomain ................................................24
      A.5.  pilotDSA and qualityLabelledData .........................24
      A.6.  Attribute Syntaxes .......................................24
   Appendix B.  Changes since RFC 2247 ...............................24

1. Introduction ๐Ÿงš

Okay, history time ๐Ÿ“–. In the late 1980s, the CCITT (Commite' Consultatif International de Telegraphique et Telephonique), which is now part of the ITU (International Telephone Union), standardized X.500 Directory Services ๐Ÿ’…. That led to directory piloting in the early 1990s, including the COSINE (Co-operation and Open Systems Interconnection in Europe) PARADISE Project pilot [COSINEpilot] in Europe ๐ŸŒ. Because large-scale directory pilots needed a standard, RFC 1274 came out to standardize the directory schema and naming architecture for the COSINE and other Internet X.500 pilots [RFC1274] โœจ.

Then X.500 kept growing ๐Ÿฆ‹. It picked up new capabilities and even new protocols. The big one is the Lightweight Directory Access Protocol (LDAP) [RFC4510], which showed up in the early 1990s [RFC1487], with Version 3 arriving in the late 1990s [RFC2251] and getting revised again in 2005 [RFC4510] ๐ŸŒธ.

Here's the tea โ˜•. A lot of RFC 1274 has been superseded by later ITU-T Recommendations and IETF RFCs, but many of its schema elements still don't have standardized schema descriptions for modern X.500 and LDAP directory services ๐Ÿ˜ญ. Those elements are super widely used today, though! And since the old schema descriptions can't be used without adapting them, interoperability problems can pop up because the modern standardized descriptions are missing ๐Ÿ’€.

So this document fixes that ๐Ÿซถ. It offers standardized schema descriptions, where they're needed, for the widely used COSINE schema elements ๐Ÿ’–.

1.1. Relationship to Other Documents ๐Ÿ”—

This document, together with [RFC4519] and [RFC4517], obsoletes RFC 1274 in its entirety ๐Ÿ‘‘. [RFC4519] replaces Sections 9.3.1 (Userid) and 9.3.21 (Domain Component) of RFC 1274. [RFC4517] replaces Section 9.4 (Generally useful syntaxes) of RFC 1274 ๐ŸŽ€.

This document replaces the rest of RFC 1274. Appendix A talks about the changes since RFC 1274, and also explains why some schema elements weren't carried forward into this revision of the COSINE schema ๐Ÿ“. Every element that didn't make it is to be regarded as Historic ๐Ÿฅ€.

The description of the 'domain' object class in this document supersedes the one in RFC 2247. In other words, Section 3.4 of this document replaces Section 5.2 of [RFC2247] โœจ.

Some schema elements here were described in RFC 2798 (inetOrgPerson schema), and this document supersedes those descriptions ๐Ÿฆ‹. This document, together with [RFC4519], replaces Section 9.1.3 of RFC 2798 ๐Ÿ’….

1.2. Terminology and Conventions ๐Ÿ“

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] ๐ŸŒˆ. These are the spec vibes, so pay attention ๐Ÿ‘€.

Some quick terms ๐Ÿ’œ:

DIT stands for Directory Information Tree. DN stands for Distinguished Name. DSA stands for Directory System Agent, a server. DSE stands for DSA-Specific Entry. DUA stands for Directory User Agent, a client.

These terms are discussed in [RFC4512] ๐Ÿ“š.

Schema definitions use LDAP description formats [RFC4512] ๐Ÿงš. The definitions here are line-wrapped for readability, so they look nice in your terminal ๐Ÿ’….

2. COSINE Attribute Types ๐ŸŒธ

This section breaks down the COSINE attribute types for use in LDAP ๐Ÿ’–.

2.1. associatedDomain ๐ŸŒ

The 'associatedDomain' attribute specifies DNS [RFC1034][RFC2181] host names [RFC1123] that are associated with an object ๐Ÿฆ‹. Basically, values of this attribute should conform to the following ABNF:

    domain = root / label *( DOT label )
    root   = SPACE
    label  = LETDIG [ *61( LETDIG / HYPHEN ) LETDIG ]
    LETDIG = %x30-39 / %x41-5A / %x61-7A ; "0" - "9" / "A"-"Z" / "a"-"z"
    SPACE  = %x20                        ; space (" ")
    HYPHEN = %x2D                        ; hyphen ("-")
    DOT    = %x2E                        ; period (".")

For example, the entry in the DIT with a DN <DC=example,DC=com> might have an associated domain of "example.com" ๐Ÿ“.

      ( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain'
        EQUALITY caseIgnoreIA5Match
        SUBSTR caseIgnoreIA5SubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

The IA5String (1.3.6.1.4.1.1466.115.121.1.26) syntax and the 'caseIgnoreIA5Match' and 'caseIgnoreIA5SubstringsMatch' rules are described in [RFC4517] ๐Ÿ“–.

Real talk: the directory will not make sure values of this attribute follow the <domain> production above ๐Ÿ™ˆ. Making sure the domains stored here are represented properly is the application's job ๐Ÿ’….

Also, applications that support Internationalized Domain Names SHALL use the ToASCII method [RFC3490] to produce <label> components of the <domain> production ๐ŸŒˆ. No skipping this one, bestie ๐Ÿซถ.

2.2. associatedName ๐Ÿข

The 'associatedName' attribute specifies names of entries in the organizational DIT that are associated with a DNS domain [RFC1034][RFC2181] โœจ.

      ( 0.9.2342.19200300.100.1.38 NAME 'associatedName'
        EQUALITY distinguishedNameMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )

The DistinguishedName (1.3.6.1.4.1.1466.115.121.1.12) syntax and the 'distinguishedNameMatch' rule are described in [RFC4517] ๐Ÿ’œ.

2.3. buildingName ๐Ÿ›๏ธ

The 'buildingName' attribute specifies names of the buildings where an organization or organizational unit is based, like "The White House" ๐Ÿ‡บ๐Ÿ‡ธ๐ŸŽ€.

      ( 0.9.2342.19200300.100.1.48 NAME 'buildingName'
        EQUALITY caseIgnoreMatch
        SUBSTR caseIgnoreSubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐Ÿฆ‹.

2.4. co ๐ŸŒ

The 'co' (Friendly Country Name) attribute specifies names of countries in a human-readable format, like "Germany" and "Federal Republic of Germany" ๐Ÿฅจ. It's commonly used together with the 'c' (Country Name) [RFC4519] attribute, whose values are restricted to the two-letter codes defined in [ISO3166] ๐Ÿ—บ๏ธ.

      ( 0.9.2342.19200300.100.1.43 NAME 'co'
        EQUALITY caseIgnoreMatch
        SUBSTR caseIgnoreSubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐Ÿ’….

2.5. documentAuthor โœ๏ธ

The 'documentAuthor' attribute specifies the distinguished names of authors (or editors) of a document ๐ŸŒธ. For example:

      ( 0.9.2342.19200300.100.1.14 NAME 'documentAuthor'
        EQUALITY distinguishedNameMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )

The DistinguishedName (1.3.6.1.4.1.1466.115.121.1.12) syntax and the 'distinguishedNameMatch' rule are described in [RFC4517] ๐Ÿ’–.

2.6. documentIdentifier โœจ

okay so the documentIdentifier attribute is for giving a document its unique IDs ๐Ÿชช, and a single doc can have more than one. Like, RFC 3383 and BCP 64 are two different unique IDs that (presently) point at the same document. Iconic double identity ๐Ÿ’…

( 0.9.2342.19200300.100.1.11 NAME 'documentIdentifier'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are all explained over in [RFC4517] ๐Ÿ“–

2.7. documentLocation ๐Ÿ—บ๏ธ

the documentLocation attribute tells you where the document's original lives. So, the source, the OG version ๐Ÿซถ

( 0.9.2342.19200300.100.1.15 NAME 'documentLocation'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

Same deal as before: the DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐ŸŒธ

2.8. documentPublisher ๐Ÿ“š

the documentPublisher attribute is for the people and/or organizations that put the document out there. When a doc is published jointly, you get one value per publisher, so everybody gets their flowers ๐Ÿ’

( 0.9.2342.19200300.100.1.56 NAME 'documentPublisher'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐Ÿ’œ

2.9. documentTitle ๐ŸŽ€

the documentTitle attribute holds a doc's titles. You can have several, because you want a long one AND a short one, or because the doc just has multiple names, like "The Lightweight Directory Access Protocol Technical Specification" and "The LDAP Technical Specification". Main character energy, multiple names ๐Ÿ‘‘

( 0.9.2342.19200300.100.1.12 NAME 'documentTitle'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] โœจ

2.10. documentVersion ๐Ÿ”–

the documentVersion attribute is the version info for a document. Version tracking, but make it cute ๐Ÿงš

( 0.9.2342.19200300.100.1.13 NAME 'documentVersion'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐Ÿฆ‹

2.11. drink ๐Ÿฅค

the drink attribute (aka favoriteDrink) is an object's, or a person's, fave drinks. Think "cola" and "beer" ๐Ÿ“ no judgment, we all have our era

( 0.9.2342.19200300.100.1.5 NAME 'drink'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐Ÿ’…

2.12. homePhone ๐Ÿ“ž

the homePhone attribute (Home Telephone Number) is a person's home phone numbers, like "+1 775 555 1234". Call your bestie at home ๐Ÿซถ

( 0.9.2342.19200300.100.1.20 NAME 'homePhone'
  EQUALITY telephoneNumberMatch
  SUBSTR telephoneNumberSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )

The telephoneNumber (1.3.6.1.4.1.1466.115.121.1.50) syntax and the 'telephoneNumberMatch' and 'telephoneNumberSubstringsMatch' rules are described in [RFC4517] ๐ŸŒˆ

2.13. homePostalAddress ๐Ÿก

the homePostalAddress attribute holds home postal addresses for an object. Each value should be limited to up to 6 directory strings of 30 characters each. (Note: It is not intended that the directory service enforce these limits.) so it's a soft suggestion, not a bouncer ๐Ÿ’€

( 0.9.2342.19200300.100.1.39 NAME 'homePostalAddress'
  EQUALITY caseIgnoreListMatch
  SUBSTR caseIgnoreListSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )

The PostalAddress (1.3.6.1.4.1.1466.115.121.1.41) syntax and the 'caseIgnoreListMatch' and 'caseIgnoreListSubstringsMatch' rules are described in [RFC4517] ๐Ÿงš

2.14. host ๐Ÿ–ฅ๏ธ

the host attribute is for host computers, usually named by their main fully qualified domain name, like my-host.example.com. Your server's full name tag ๐Ÿท๏ธ

( 0.9.2342.19200300.100.1.9 NAME 'host'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐Ÿ’–

2.15. info โ„น๏ธ

the info attribute is any general info about an object. Heads up, this info is not necessarily descriptive of the object ๐Ÿ™ˆ

Applications should not attach specific semantics to values of this attribute. The 'description' attribute [RFC4519] is the one for descriptive info about an object, so use that one for the actual vibes ๐Ÿซถ

( 0.9.2342.19200300.100.1.4 NAME 'info'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{2048} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] โœจ

2.16. mail ๐Ÿ“ง

the mail (rfc822mailbox) attribute type holds Internet mail addresses in Mailbox [RFC2821] form, like user@example.com. Email, but make it structured ๐Ÿ’Œ

( 0.9.2342.19200300.100.1.3 NAME 'mail'
  EQUALITY caseIgnoreIA5Match
  SUBSTR caseIgnoreIA5SubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )

The IA5String (1.3.6.1.4.1.1466.115.121.1.26) syntax and the 'caseIgnoreIA5Match' and 'caseIgnoreIA5SubstringsMatch' rules are described in [RFC4517].

okay this part is important bestie ๐Ÿ‘€ the directory will NOT check that values here match the <Mailbox> production [RFC2821]. So it's the application's job to make sure any domains it stores here are represented properly ๐Ÿซ 

Also, the directory compares values using the matching rules named in the attribute type description above. Those rules are different from the usual <Mailbox> comparisons, so operational issues can pop up. For example, the assertion (mail=joe@example.com) will match "JOE@example.com" even though the <local-parts> differ. And if a user has two <Mailbox>es whose addresses differ only by the case of the <local-part>, you can't list both as values of the user's mail attribute, since the 'caseIgnoreIA5Match' rule considers them equal. Plot twist ๐Ÿ˜ญ

Also, applications supporting internationalized domain names SHALL use the ToASCII method [RFC3490] to produce <sub-domain> components of the <Mailbox> production. Not optional, periodt ๐Ÿ”ฅ

2.17. manager ๐Ÿ‘”

the manager attribute names the managers of a person (or entity), by distinguished name. Who's your boss, in DN form ๐Ÿข

( 0.9.2342.19200300.100.1.10 NAME 'manager'
  EQUALITY distinguishedNameMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )

The DistinguishedName (1.3.6.1.4.1.1466.115.121.1.12) syntax and the 'distinguishedNameMatch' rule are described in [RFC4517] ๐ŸŒธ

2.18. mobile ๐Ÿ“ฑ

the mobile (mobileTelephoneNumber) attribute specifies a person's (or entity's) mobile phone numbers, like "+1 775 555 6789". Your pocket line ๐Ÿฆ‹

( 0.9.2342.19200300.100.1.41 NAME 'mobile'
  EQUALITY telephoneNumberMatch
  SUBSTR telephoneNumberSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )

The telephoneNumber (1.3.6.1.4.1.1466.115.121.1.50) syntax and the 'telephoneNumberMatch' and 'telephoneNumberSubstringsMatch' rules are described in [RFC4517] ๐Ÿ’œ

2.19. organizationalStatus ๐ŸŽ“

the organizationalStatus attribute is the categories a person is often referred to by in an organization. In academia that could be "undergraduate student", "researcher", "professor", or "staff". Multiple values are allowed when the person sits in several categories at once, so you can be a whole multi-hyphenate ๐ŸŒŸ

( 0.9.2342.19200300.100.1.45 NAME 'organizationalStatus'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517].

Directory admins and app designers SHOULD consider carefully the distinctions between this and the 'title' and 'userClass' attributes. Don't mix these up, it's giving confusion ๐Ÿ™ƒ

2.20. pager ๐Ÿ“Ÿ

the pager (pagerTelephoneNumber) attribute is for an object's pager phone numbers, like "+1 775 555 5555". Retro, but still iconic ๐Ÿฅน

( 0.9.2342.19200300.100.1.42 NAME 'pager'
  EQUALITY telephoneNumberMatch
  SUBSTR telephoneNumberSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )

The telephoneNumber (1.3.6.1.4.1.1466.115.121.1.50) syntax and the 'telephoneNumberMatch' and 'telephoneNumberSubstringsMatch' rules are described in [RFC4517] ๐ŸŽ€

2.21. personalTitle ๐ŸŽฉ

the personalTitle attribute holds a person's personal titles, like "Frau", "Dr.", "Herr", and "Professor". Respect the honorifics ๐Ÿซก

( 0.9.2342.19200300.100.1.40 NAME 'personalTitle'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] โœจ

2.22. roomNumber ๐Ÿšช

the roomNumber attribute is the room number of an object. During renumbering, or whenever a room has several valid numbers, you can list multiple values. Quick note: the 'cn' (commonName) attribute type SHOULD be used for naming room objects, so your rooms get proper names too ๐Ÿ 

( 0.9.2342.19200300.100.1.6 NAME 'roomNumber'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517] ๐ŸŒท

2.23. secretary ๐Ÿ—‚๏ธ

the secretary attribute names secretaries and/or administrative assistants, by distinguished name. The unsung heroes ๐Ÿซถ

( 0.9.2342.19200300.100.1.21 NAME 'secretary'
  EQUALITY distinguishedNameMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )

The DistinguishedName (1.3.6.1.4.1.1466.115.121.1.12) syntax and the 'distinguishedNameMatch' rule are described in [RFC4517] ๐Ÿ’…

2.24. uniqueIdentifier ๐Ÿ”‘

the uniqueIdentifier attribute is a unique ID for an object in the Directory. The domain it's unique within, and what it means, are for local definition. For a person it might be an institution-wide payroll number, and for an org unit it might be a department code. Each place does its own thing ๐Ÿซ

( 0.9.2342.19200300.100.1.44 NAME 'uniqueIdentifier'
  EQUALITY caseIgnoreMatch
  SUBSTR caseIgnoreSubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the 'caseIgnoreMatch' and 'caseIgnoreSubstringsMatch' rules are described in [RFC4517].

Note: X.520 also describes an attribute called 'uniqueIdentifier' (2.5.4.45), which is called 'x500UniqueIdentifier' in LDAP [RFC4519]. The attribute detailed here ought not be confused with 'x500UniqueIdentifier'. Don't mix these two up, bestie ๐Ÿ™

2.25. userClass โœจ

okay so the userClass attribute is for saying what kind of computer or application user someone is ๐Ÿ’… The meaning is totally up to whoever is running the place (local interpretation, bestie) ๐ŸŒธ Academia uses stuff like "student", "staff", and "faculty" ๐ŸŽ“ ngl, organizationalStatus is lowkey the one people reach for now, since it doesn't care whether it's a person or a user ๐Ÿซถ

( 0.9.2342.19200300.100.1.8 NAME 'userClass'
      EQUALITY caseIgnoreMatch
      SUBSTR caseIgnoreSubstringsMatch
      SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )

The DirectoryString (1.3.6.1.4.1.1466.115.121.1.15) syntax and the caseIgnoreMatch and caseIgnoreSubstringsMatch rules are described in [RFC4517]. ๐Ÿ“–


3. COSINE Object Classes โœจ

okay this section is where the COSINE object classes get the full spotlight ๐Ÿฆ‹ It details them for use in LDAP, so get ready to meet your new favourite entries ๐Ÿ’œ

3.1. account

The account object class is used to define entries representing computer accounts ๐Ÿ’ป The 'uid' attribute SHOULD be used for naming entries of this object class ๐ŸŽ€

( 0.9.2342.19200300.100.4.5 NAME 'account'
  SUP top STRUCTURAL
  MUST uid
  MAY ( description $ seeAlso $ l $ o $ ou $ host ) )

The 'top' object class is described in [RFC4512]. The 'description', 'seeAlso', 'l', 'o', 'ou', and 'uid' attribute types are described in [RFC4519]. The 'host' attribute type is described in Section 2 of this document. ๐ŸŒˆ

3.3. documentSeriesExample:

dn: uid=kdz,cn=Accounts,dc=Example,dc=COM
objectClass: account
uid: kdz
seeAlso: cn=Kurt D. Zeilenga,cn=Persons,dc=Example,dc=COM

3.2. document

The document object class is used to define entries that represent documents ๐Ÿ“„๐ŸŒธ

( 0.9.2342.19200300.100.4.6 NAME 'document'
  SUP top STRUCTURAL
  MUST documentIdentifier
  MAY ( cn $ description $ seeAlso $ l $ o $ ou $
    documentTitle $ documentVersion $ documentAuthor $
    documentLocation $ documentPublisher ) )

The 'top' object class is described in [RFC4512]. The 'cn', 'description', 'seeAlso', 'l', 'o', and 'ou' attribute types are described in [RFC4519]. The 'documentIdentifier', 'documentTitle', 'documentVersion', 'documentAuthor', 'documentLocation', and 'documentPublisher' attribute types are described in Section 2 of this document. โœจ

Example:

dn: documentIdentifier=RFC 4524,cn=RFC,dc=Example,dc=COM
objectClass: document
documentIdentifier: RFC 4524
documentTitle: COSINE LDAP/X.500 Schema
documentAuthor: cn=Kurt D. Zeilenga,cn=Persons,dc=Example,dc=COM
documentLocation: http://www.rfc-editor.org/rfc/rfc4524.txt
documentPublisher: Internet Engineering Task Force
description: A collection of schema elements for use in LDAP
description: Obsoletes RFC 1274
seeAlso: documentIdentifier=RFC 4510,cn=RFC,dc=Example,dc=COM
seeAlso: documentIdentifier=RFC 1274,cn=RFC,dc=Example,dc=COM

3.3. documentSeries

The documentSeries object class is used to define an entry that represents a series of documents (e.g., The Request For Comments memos) ๐Ÿ“š this is the whole RFC family, iykyk ๐Ÿ“

( 0.9.2342.19200300.100.4.9 NAME 'documentSeries'
  SUP top STRUCTURAL
  MUST cn
  MAY ( description $ l $ o $ ou $ seeAlso $
    telephonenumber ) )

The 'top' object class is described in [RFC4512]. The 'description', 'l', 'o', 'ou', 'seeAlso', and 'telephoneNumber' attribute types are described in [RFC4519]. ๐Ÿฆ‹

Example:

dn: cn=RFC,dc=Example,dc=COM
objectClass: documentSeries
cn: Request for Comments
cn: RFC
description: a series of memos about the Internet

3.4. domain

The domain object class is used to define entries that represent DNS domains for objects that are not organizations, organizational units, or other kinds of objects more appropriately defined using an object class specific to the kind of object being defined (e.g., 'organization', 'organizationUnit') ๐ŸŒ it's the catch-all for domains that don't need a fancier outfit ๐Ÿ’…

The 'dc' attribute should be used for naming entries of the 'domain' object class ๐ŸŽ€

( 0.9.2342.19200300.100.4.13 NAME 'domain'
  SUP top STRUCTURAL
  MUST dc
  MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
    x121Address $ registeredAddress $ destinationIndicator $
    preferredDeliveryMethod $ telexNumber $
    teletexTerminalIdentifier $ telephoneNumber $
    internationaliSDNNumber $ facsimileTelephoneNumber $ street $
    postOfficeBox $ postalCode $ postalAddress $
    physicalDeliveryOfficeName $ st $ l $ description $ o $
    associatedName ) )

The 'top' object class and the 'dc', 'userPassword', 'searchGuide', 'seeAlso', 'businessCategory', 'x121Address', 'registeredAddress', 'destinationIndicator', 'preferredDeliveryMethod', 'telexNumber', 'teletexTerminalIdentifier', 'telephoneNumber', 'internationaliSDNNumber', 'facsimileTelephoneNumber', 'street', 'postOfficeBox', 'postalCode', 'postalAddress', 'physicalDeliveryOfficeName', 'st', 'l', 'description', and 'o' types are described in [RFC4519]. The 'associatedName' attribute type is described in Section 2 of this document. ๐ŸŒธ

Example:

dn: dc=com
objectClass: domain
dc: com
description: the .COM TLD

3.5. domainRelatedObject

The domainRelatedObject object class is used to define entries that represent DNS domains that are "equivalent" to an X.500 domain, e.g., an organization or organizational unit ๐Ÿขโœจ

( 0.9.2342.19200300.100.4.17 NAME 'domainRelatedObject'
  SUP top AUXILIARY
  MUST associatedDomain )

The 'top' object class is described in [RFC4512]. The 'associatedDomain' attribute type is described in Section 2 of this document. ๐Ÿ’œ

Example:

dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
objectClass: domainRelatedObject
dc: example
associatedDomain: example.com
o: Example Organization

The 'organization' and 'dcObject' object classes and the 'dc' and 'o' attribute types are described in [RFC4519]. ๐Ÿงš

3.6. friendlyCountry

The friendlyCountry object class is used to define entries representing countries in the DIT ๐ŸŒ It exists so countries can get friendlier names than the object class 'country' [RFC4519] allows ๐Ÿซถ

( 0.9.2342.19200300.100.4.18 NAME 'friendlyCountry'
  SUP country STRUCTURAL
  MUST co )

The 'country' object class is described in [RFC4519]. The 'co' attribute type is described in Section 2 of this document. ๐ŸŽ€

Example:

dn: c=DE
objectClass: country
objectClass: friendlyCountry
c: DE
co: Deutschland
co: Germany
co: Federal Republic of Germany
co: FRG

The 'c' attribute type is described in [RFC4519]. โœจ

3.7. rFC822LocalPart

The rFC822LocalPart object class is used to define entries that represent the local part of Internet mail addresses [RFC2822] ๐Ÿ“ง This treats the local part of the address as a 'domain' object, which is a very main character move ๐Ÿ‘‘

( 0.9.2342.19200300.100.4.14 NAME 'rFC822localPart'
  SUP domain STRUCTURAL
  MAY ( cn $ description $ destinationIndicator $
    facsimileTelephoneNumber $ internationaliSDNNumber $
    physicalDeliveryOfficeName $ postalAddress $ postalCode $
    postOfficeBox $ preferredDeliveryMethod $ registeredAddress $
    seeAlso $ sn $ street $ telephoneNumber $
    teletexTerminalIdentifier $ telexNumber $ x121Address ) )

The 'domain' object class is described in Section 3.4 of this document. The 'cn', 'description', 'destinationIndicator', 'facsimileTelephoneNumber', 'internationaliSDNNumber, 'physicalDeliveryOfficeName', 'postalAddress', 'postalCode', 'postOfficeBox', 'preferredDeliveryMethod', 'registeredAddress', 'seeAlso', 'sn, 'street', 'telephoneNumber', 'teletexTerminalIdentifier', 'telexNumber', and 'x121Address' attribute types are described in [RFC4519]. ๐Ÿฆ‹

Example:

dn: dc=kdz,dc=example,dc=com
objectClass: domain
objectClass: rFC822LocalPart
dc: kdz
associatedName: cn=Kurt D. Zeilenga,cn=Persons,dc=Example,dc=COM

The 'dc' attribute type is described in [RFC4519]. ๐Ÿ’–

3.8. room

The room object class is used to define entries representing rooms ๐Ÿšช The 'cn' (commonName) attribute SHOULD be used for naming entries of this object class ๐Ÿ“

( 0.9.2342.19200300.100.4.7 NAME 'room'
  SUP top STRUCTURAL
  MUST cn
  MAY ( roomNumber $ description $ seeAlso $ telephoneNumber ) )

The 'top' object class is described in [RFC4512]. The 'cn', 'description', 'seeAlso', and 'telephoneNumber' attribute types are described in [RFC4519]. The 'roomNumber' attribute type is described in Section 2 of this document. ๐ŸŒธ

dn: cn=conference room,dc=example,dc=com
objectClass: room
cn: conference room
telephoneNumber: +1 755 555 1111

3.9. simpleSecurityObject

The simpleSecurityObject object class is used to require an entry to have a 'userPassword' attribute when the entry's structural object class does not require (or allow) the 'userPassword attribute' ๐Ÿ” bestie, this one is the bouncer at the door ๐Ÿ’…

( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
  SUP top AUXILIARY
  MUST userPassword )

The 'top' object class is described in [RFC4512]. The 'userPassword' attribute type is described in [RFC4519]. ๐ŸŽ€

dn: dc=kdz,dc=Example,dc=COM
objectClass: account
objectClass: simpleSecurityObject
uid: kdz
userPassword: My Password
seeAlso: cn=Kurt D. Zeilenga,cn=Persons,dc=Example,dc=COM

4. Security Considerations ๐Ÿ”๐Ÿ˜ญ

okay this part is SERIOUS, bestie, so read it properly ๐Ÿ’€

General LDAP security considerations [RFC4510] are applicable to the use of this schema. Additional considerations are noted above where appropriate. ๐Ÿ›ก๏ธ

Directories administrators should ensure that access to sensitive information be restricted to authorized entities and that appropriate data security services, including data integrity and data confidentiality, are used to protect against eavesdropping. Nobody gets to snoop on the tea ๐Ÿซฃ๐Ÿ‘€

Simple authentication (e.g., plain text passwords) mechanisms should only be used when adequate data security services are in place. LDAP offers reasonably strong authentication and data security services [RFC4513]. Plain-text passwords with no protection are a hard no, periodt ๐Ÿšซ๐Ÿ’…

5. IANA Considerations โœจ

okay so IANA (the folks who keep the Internet's registries tidy ๐Ÿ—‚๏ธ) updated the LDAP descriptors registry [RFC4520] using the template below, bestie ๐Ÿ’…

   Subject: Request for LDAP Descriptor Registration Update
   Descriptor (short name): see comment
   Object Identifier: see comments
   Person & email address to contact for further information:
       Kurt Zeilenga <kurt@OpenLDAP.org>
   Usage: see comments
   Specification: RFC 4524
   Author/Change Controller: IESG
   Comments:

   The following descriptors have been updated to refer to RFC 4524.

     NAME                           Type OID
     ------------------------       ---- --------------------------
     account                        O    0.9.2342.19200300.100.4.5
     associatedDomain               A    0.9.2342.19200300.100.1.37
     associatedName                 A    0.9.2342.19200300.100.1.38
     buildingName                   A    0.9.2342.19200300.100.1.48
     co                             A    0.9.2342.19200300.100.1.43
     document                       O    0.9.2342.19200300.100.4.6
     documentAuthor                 A    0.9.2342.19200300.100.1.14
     documentIdentifier             A    0.9.2342.19200300.100.1.11
     documentLocation               A    0.9.2342.19200300.100.1.15
     documentPublisher              A    0.9.2342.19200300.100.1.56
     documentSeries                 O    0.9.2342.19200300.100.4.8
     documentTitle                  A    0.9.2342.19200300.100.1.12
     documentVersion                A    0.9.2342.19200300.100.1.13
     domain                         O    0.9.2342.19200300.100.4.13
     domainRelatedObject            O    0.9.2342.19200300.100.4.17
     drink                          A    0.9.2342.19200300.100.1.5
     favouriteDrink                 A*   0.9.2342.19200300.100.1.5
     friendlyCountry                O    0.9.2342.19200300.100.4.18
     friendlyCountryName            A*   0.9.2342.19200300.100.1.43
     homePhone                      A    0.9.2342.19200300.100.1.20
     homePostalAddress              A    0.9.2342.19200300.100.1.39
     homeTelephone                  A*   0.9.2342.19200300.100.1.20
     host                           A    0.9.2342.19200300.100.1.9
     info                           A    0.9.2342.19200300.100.1.4
     mail                           A    0.9.2342.19200300.100.1.3
     manager                        A    0.9.2342.19200300.100.1.10
     mobile                         A    0.9.2342.19200300.100.1.41
     mobileTelephoneNumber          A*   0.9.2342.19200300.100.1.41
     organizationalStatus           A    0.9.2342.19200300.100.1.45
     pager                          A    0.9.2342.19200300.100.1.42
     pagerTelephoneNumber           A*   0.9.2342.19200300.100.1.42
     personalTitle                  A    0.9.2342.19200300.100.1.40
     rFC822LocalPart                O    0.9.2342.19200300.100.4.14
     rfc822Mailbox                  A*   0.9.2342.19200300.100.1.3
     room                           O    0.9.2342.19200300.100.4.7
     roomNumber                     A    0.9.2342.19200300.100.1.6
     secretary                      A    0.9.2342.19200300.100.1.21
     simpleSecurityObject           O    0.9.2342.19200300.100.4.19
     singleLevelQuality             A    0.9.2342.19200300.100.1.50
     uniqueIdentifier               A    0.9.2342.19200300.100.1.44
     userClass                      A    0.9.2342.19200300.100.1.8

where Type A is Attribute, Type O is ObjectClass, and * indicates that the registration is historic in nature. ๐Ÿ•ฐ๏ธ

6. Acknowledgements ๐Ÿ™

big thanks to the people this document is built on ๐Ÿซถ It's based on RFC 1274, by Paul Barker and Steve Kille, and on RFC 2247, by Steve Kill, Mark Wahl, Al Grimstad, Rick Huber, and Sri Satulari. ๐Ÿ’œ

7. References ๐Ÿ“š

7.1. Normative References

[RFC1034]     Mockapetris, P., "Domain names - concepts and
              facilities", STD 13, RFC 1034, November 1987.

[RFC1123]     Braden, R., "Requirements for Internet Hosts -
              Application and Support", STD 3, RFC 1123, October
              1989.

[RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2181]     Elz, R. and R. Bush, "Clarifications to the DNS
              Specification", RFC 2181, July 1997.

[RFC2247]     Kille, S., Wahl, M., Grimstad, A., Huber, R., and S.
              Sataluri, "Using Domains in LDAP/X.500 Distinguished
              Names", RFC 2247, January 1998.

[RFC2821]     Klensin, J., Ed., "Simple Mail Transfer Protocol", RFC
              2821, April 2001.

[RFC2822]     Resnick, P., "Internet Message Format", RFC 2822, April
              2001.

[RFC3490]     Faltstrom, P., Hoffman, P., and A. Costello,
              "Internationalizing Domain Names in Applications
              (IDNA)", RFC 3490, March 2003.

[RFC4510]     Zeilenga, K., Ed.,  "Lightweight Directory Access
              Protocol (LDAP): Technical Specification Road Map", RFC
              4510, June 2006.

[RFC4512]     Zeilenga, K., "Lightweight Directory Access Protocol
              (LDAP): Directory Information Models", RFC 4512, June
              2006.

[RFC4513]     Harrison, R., "Lightweight Directory Access Protocol
              (LDAP): Authentication Methods and Security
              Mechanisms", RFC 4513, June 2006.

[RFC4517]     Legg, S., Ed., "Lightweight Directory Access Protocol
              (LDAP): Syntaxes and Matching Rules", RC 4517, June
              2006.

[RFC4519]     Sciberras, A., Ed., "Lightweight Directory Access
              Protocol (LDAP): Schema for User Applications", RFC
              4519, June 2006.

[X.501]       International Telecommunication Union -
              Telecommunication Standardization Sector, "The
              Directory -- Models," X.501(1993) (also ISO/IEC 9594-
              2:1994).

7.2. Informative References

[COSINEpilot] Goodman, D., "PARADISE" section of the March 1991
              INTERNET MONTHLY REPORTS (p. 28-29),
              http://www.iana.org/periodic-reports/imr-mar91.txt

[ISO3166]     International Organization for Standardization, "Codes
              for the representation of names of countries", ISO
              3166.

[RFC1274]     Barker, P. and S. Kille, "The COSINE and Internet X.500
              Schema", RFC 1274, November 1991.

[RFC1279]     Hardcastle-Kille, S., "X.500 and Domains", RFC 1279,
              November 1991.

[RFC1487]     Yeong, W., Howes, T., and S. Kille, "X.500 Lightweight
              Directory Access Protocol", RFC 1487, July 1993.

[RFC2251]     Wahl, M., Howes, T., and S. Kille, "Lightweight
              Directory Access Protocol (v3)", RFC 2251, December
              1997.

[RFC2798]     Smith, M., "Definition of the inetOrgPerson LDAP Object
              Class", RFC 2798, April 2000.

[RFC3494]     Zeilenga, K., "Lightweight Directory Access Protocol
              version 2 (LDAPv2) to Historic Status", RFC 3494, March
              2003.

[RFC4520]     Zeilenga, K., "Internet Assigned Numbers Authority
              (IANA) Considerations for the Lightweight Directory
              Access Protocol (LDAP)", BCP 64, RFC 4520.

Appendix A. Changes since RFC 1274 ๐Ÿ”

this doc is a substantial rewrite of RFC 1274 ๐Ÿ’– The bits below sum up the big changes, fr fr.

A.1. LDAP Short Names ๐Ÿท๏ธ

a bunch of COSINE attribute types got short names in LDAP โœจ

X.500 Name              LDAP Short Name
-------------           ---------------
domainComponent         dc
favoriteDrink           drink
friendCountryName       co
homeTelephoneNumber     homePhone
mobileTelephoneNumber   mobile
pagerTelephoneNumber    pager
rfc822Mailbox           mail
userid                  uid

the LDAP short names are mostly what gets used in LDAP, but some implementations may (for legacy reasons [RFC3494]) recognize the attribute type by its X.500 name. So the X.500 names have been reserved solely for this purpose. ๐Ÿง

Note: 'uid' and 'dc' are described in [RFC4519].

A.2. pilotObject ๐Ÿ›ธ

the 'pilotObject' object class wasn't brought forward, because its job is mostly taken over by operational attributes from X.500(93) [X.501] and LDAP version 3 [RFC4512]. For example, the function of the 'lastModifiedBy' and 'lastModifiedTime' attribute types is now handled by the 'creatorsName', 'createTimestamp', 'modifiersName', and 'modifyTimestamp' operational attributes [RFC4512]. ๐Ÿ”„

A.3. pilotPerson ๐Ÿง‘

the 'pilotPerson' object class wasn't brought forward either, since its function is mostly replaced by the 'organizationalPerson' [RFC4512] object class and its subclasses, such as 'inetOrgPerson' [RFC2798].

most of the related attribute types (e.g., 'mail', 'manager') were brought forward, because they're used in other object classes. ๐Ÿ’…

A.4. dNSDomain ๐ŸŒ

the 'dNSDomain' object class and related attribute types weren't brought forward, since their use is primarily experimental [RFC1279]. ๐Ÿงช

A.5. pilotDSA and qualityLabelledData ๐Ÿ“‰

the 'pilotDSA' and 'qualityLabelledData' object classes, along with their related attribute types, weren't brought forward, since their use is primarily experimental [QoS]. ๐Ÿงช

A.6. Attribute Syntaxes ๐Ÿงฉ

RFC 1274 defined and used the caseIgnoreIA5StringSyntax attribute syntax. That's been replaced with the IA5String syntax and appropriate matching rules in 'mail' and 'associatedDomain'. โœจ

RFC 1274 restricted 'mail' to have non-zero length values. That restriction isn't reflected in the IA5String syntax used in the definitions in this specification. However, since values are supposed to conform to the <Mailbox> production, 'mail' should not contain zero-length values. ๐Ÿ™ƒ Unfortunately, the directory service won't enforce this restriction. ๐Ÿ˜ญ

Appendix B. Changes since RFC 2247 ๐Ÿ”

the 'domainNameForm' name form wasn't brought forward, because specifying name forms used in LDAP is left to a future specification. ๐Ÿ”ฎ

Editor's Address ๐Ÿ“ฌ

Kurt D. Zeilenga OpenLDAP Foundation

EMail: Kurt@OpenLDAP.org

Copyright (C) The Internet Society (2006).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM 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.

Intellectual Property ๐Ÿ’…

okay so this part is about who owns what, and the IETF is being super careful here bestie ๐Ÿซถ The IETF doesn't take a side on whether any Intellectual Property Rights or other rights that someone might claim over the tech in this doc are valid or in scope. It also doesn't say whether you can actually get a license for them. And it hasn't gone looking to find any of those rights either ๐Ÿ™ˆ If you want the rules on rights in RFC documents, check out BCP 78 and BCP 79 ๐Ÿ’œ

Copies of IPR disclosures sent to the IETF Secretariat are available, along with any licensing assurances, or the results of any attempt to get a general license or permission for implementers or users to use those proprietary rights. You can find all of that in the IETF on-line IPR repository at http://www.ietf.org/ipr โœจ

The IETF also invites anyone to tell them about copyrights, patents, patent applications, or other proprietary rights that might cover tech needed to implement this standard. Send that info to the IETF at ietf-ipr@ietf.org ๐Ÿ“ฌ bestie, flag it early!! ๐Ÿšฉ

Acknowledgement ๐ŸŒธ

The RFC Editor function is funded by the IETF Administrative Support Activity (IASA). So the people keeping the RFC library running get their paycheck from there ๐Ÿงš๐Ÿ’–

๐Ÿ“ฆ where this page comes from