軽量ディレクトリアクセスプロトコル(LDAP / ˈ ɛ l d æ p /)は、X.500データおよびサービスモデルに従って動作するディレクトリ情報サービスにアクセスするためのインターネットプロトコルです。 [ 1 ]プロトコルの詳細な説明は、「軽量ディレクトリアクセスプロトコル(LDAP)技術仕様ロードマップ」 RFC 4510およびその参照文献に記載されています。
ディレクトリサービスは、ネットワーク全体でユーザー、システム、ネットワーク、サービス、アプリケーションに関する情報を共有できるようにすることで、イントラネットやインターネットアプリケーションの開発において重要な役割を果たします。 [ 2 ]例として、ディレクトリサービスは、多くの場合階層構造を持つ、整理されたレコードのセットを提供できます。たとえば、企業の電子メールディレクトリなどです。同様に、電話帳は、住所と電話番号を持つ加入者のリストです。
LDAPの一般的な用途は、ユーザー名とパスワードを一元的に保存することです。これにより、さまざまなアプリケーションやサービスがLDAPサーバーに接続してユーザーを検証できるようになります。[ 3 ]
LDAP は、 X.500 シリーズ、特に X.511ディレクトリ アクセス プロトコルのよりシンプルな (軽量な) サブセットです。[ 4 ] [ 5 ] この関係から、LDAP はX.500 Liteと呼ばれることもあります。[ 6 ]
LDAPの主な構成要素は以下のとおりです。
電話帳の作成と管理に約70年を費やした通信会社は、電話帳の要件に関する理解を深めてきました。これらの企業は、情報技術とコンピュータネットワークにディレクトリサービスの概念を導入し、その貢献は、 1980年代に国際電気通信連合(ITU)によって作成された一連のプロトコルである包括的なX.500仕様[ 9 ]に結実しました。
X.500ディレクトリサービスは従来、 OSI(Open Systems Interconnection )プロトコルスタックを必要とするX.511ディレクトリアクセスプロトコル(DAP)を介してアクセスされていました。LDAPは当初、よりシンプルで(そして現在では広く普及している) TCP/IPプロトコルスタックを介してX.500ディレクトリサービスにアクセスするための軽量な代替プロトコルとして開発されました。このディレクトリアクセス方式は、DIXIEおよびディレクトリアシスタンスサービスプロトコルから着想を得ています。
このプロトコルは、もともとミシガン大学のティム・ハウズ、 Isode Limited のスティーブ・キル、Nexorのコリン・ロビンス、 Performance Systems Internationalのウェンイク・ヨンによって1993 年頃にDIXIEとDASの後継として作成されました[ 11 ] 。 Critical Angle Inc. のマーク・ウォール、ティム・ハウズ、スティーブ・キルは、インターネット技術タスクフォース(IETF)の後援の下、1996 年に LDAP の新バージョンである LDAPv3 の開発に着手しました。 1997年に初めて公開された LDAPv3 は、LDAPv2 に取って代わり、拡張性のサポートを追加し、簡易認証およびセキュリティレイヤーを統合し、プロトコルを 1993 年版の X.500 により適合させました。 LDAPv3 仕様自体のさらなる開発と、LDAPv3 に機能を追加する多数の拡張機能の開発は、IETFを通じて行われました。
LDAPの開発初期段階では、軽量ディレクトリブラウジングプロトコル(LDBP)と呼ばれていました。ディレクトリの閲覧や検索だけでなく、ディレクトリの更新機能も含むようにプロトコルの範囲が拡大された際に、名称が変更されました。軽量という名称は、前身のDAPほどネットワーク負荷が高くなく、比較的少ない帯域幅使用量でインターネット上で容易に実装できたことに由来します。
LDAPは、X.500の後のバージョン、XML対応ディレクトリ(XED)、ディレクトリサービスマークアップ言語(DSML)、サービスプロビジョニングマークアップ言語(SPML)、サービスロケーションプロトコル(SLP)など、その後のインターネットプロトコルに影響を与えてきました。また、 MicrosoftのActive Directoryの基盤としても使用されています。
クライアントは、デフォルトではTCPおよびUDPポート389、またはLDAPS (TLS/SSL 上の LDAP、下記参照)の場合はポート 636 で、ディレクトリ システム エージェント(DSA) と呼ばれる LDAP サーバーに接続して LDAP セッションを開始します。 [ 12 ]次に、クライアントはサーバーに操作要求を送信し、サーバーは応答を返します。いくつかの例外を除き、クライアントは次の要求を送信する前に応答を待つ必要はなく、サーバーは任意の順序で応答を送信できます。すべての情報は、基本エンコーディング ルール(BER) を使用して送信されます。
クライアントは以下の操作を依頼することができます。
さらに、サーバーは、接続がタイムアウトする前など、いかなるリクエストにも応答しない「未承諾通知」を送信する場合があります。
LDAP 通信を保護する一般的な代替方法として、SSLトンネルを使用する方法があります。SSL 経由の LDAP のデフォルト ポートは 636 です。LDAP 経由の SSL の使用は LDAP バージョン 2 (LDAPv2) では一般的でしたが、正式な仕様で標準化されたことはありませんでした。この使用法は、2003 年に正式に廃止された LDAPv2 とともに非推奨になりました。[ 13 ]
このプロトコルは、1993年版X.500規格に準拠したディレクトリとのインターフェースを提供する。
/foo/bar/myfile.txt、DNがの場合、myfile.txtRDNはとなります)。DNは、エントリの存続期間中に変化する可能性があります。例えば、エントリがツリー内で移動された場合などです。エントリを確実かつ明確に識別するために、エントリの操作属性セットにUUIDを指定することが考えられます。
エントリは、LDAPデータ交換フォーマット(LDIF)で表現される場合、次のようになります。LDIFはプレーンテキスト形式です( LDAP自体のようなバイナリプロトコルとは異なります)。
dn : cn = John Doe , dc = example , dc = com cn : John Doe givenName : John sn : Doe telephoneNumber : +1 888 555 6789 telephoneNumber : +1 888 555 1232 mail : john@example.com manager : cn=Barbara Doe,dc=example,dc=com objectClass : inetOrgPerson objectClass : organizationalPerson objectClass : person objectClass : top「dn」はエントリの識別名であり、属性でもエントリの一部でもありません。「cn=John Doe」はエントリの RDN (相対識別名) であり、「dc=example,dc=com」は親エントリの DN です。ここで「dc」は「ドメイン コンポーネント」を表します。その他の行はエントリの属性を示します。属性名は通常、共通cn名を表す「 」、dcドメイン コンポーネントを表す「 」、mail電子メール アドレスを表す「 」、sn姓を表す「 」などの覚えやすい文字列です。[ 14 ]
サーバーは、特定のエントリ(例:「 」)とその子から始まるサブツリーを保持しますdc=example,dc=com。サーバーは他のサーバーへの参照も保持できるため、「 」へのアクセスを試みると、ディレクトリツリーのその部分を保持するサーバーへの参照または継続参照がou=department,dc=example,dc=com返される可能性があります。クライアントはその後、他のサーバーに問い合わせることができます。一部のサーバーはチェイニングもサポートしており、これはサーバーが他のサーバーに問い合わせて結果をクライアントに返すことを意味します。
LDAPでは、順序付けが規定されることはほとんどありません。サーバーは、属性の値、エントリ内の属性、検索操作によって見つかったエントリを任意の順序で返すことができます。これは、正式な定義に基づいています。エントリは属性の集合として定義され、属性は値の集合であり、集合は必ずしも順序付けられる必要はありません。
ADD操作は、ディレクトリサーバーのデータベースに新しいエントリを挿入します。[ 15 ]追加要求の識別名が既にディレクトリに存在する場合、サーバーは重複エントリを追加せず、追加結果の結果コードを10進数68「entryAlreadyExists」に設定します。[ 16 ]
dn : uid = user 、ou = people 、dc = example 、dc = com changetype : add objectClass : top objectClass : person uid : user sn : last-name cn : common-name userPassword : password上記の例では、uid=user,ou=people,dc=example,dc=comは存在してはならず、ou=people,dc=example,dc=comは存在しなければなりません。
LDAPセッションが作成されるとき、つまりLDAPクライアントがサーバーに接続するとき、セッションの認証状態は匿名に設定されます。BIND操作によってセッションの認証状態が確立されます。
シンプルBINDとSASL PLAINは、ユーザーのDNとパスワードを平文で送信する可能性があるため、シンプルBINDまたはSASL PLAINを使用する接続は、トランスポート層セキュリティ(TLS)を使用して暗号化する必要があります。サーバーは通常、userPassword 名前付きエントリの属性に対してパスワードをチェックします。匿名BIND(DNとパスワードが空の場合)は、接続を匿名状態にリセットします。
SASL (Simple Authentication and Security Layer) BIND は、 KerberosやTLS で送信されるクライアント証明書など、さまざまなメカニズムを通じて認証サービスを提供します。 [ 17 ]
BINDは、バージョン番号を整数として送信することで、LDAPプロトコルのバージョンも設定します。クライアントがサーバーがサポートしていないバージョンを要求した場合、サーバーはBIND応答の結果コードをプロトコルエラーのコードに設定する必要があります。通常、クライアントはLDAPv3を使用します。これはプロトコルのデフォルトですが、LDAPライブラリでは必ずしもデフォルトではありません。
LDAPv2では、BINDはセッションの最初の操作である必要がありましたが、LDAPv3以降は必須ではありません。LDAPv3では、BINDリクエストが成功するたびにセッションの認証状態が変更され、BINDリクエストが失敗するたびにセッションの認証状態がリセットされます。
エントリを削除するには、LDAPクライアントは適切な形式の削除要求をサーバーに送信します。[ 18 ]
hasSubordinates操作属性numSubordinates[ 19 ]numSubordinatesをサポートしています。検索操作は、エントリの検索と読み取りの両方に使用されます。そのパラメータは次のとおりです。
BaseObject(指定されたエントリのみを検索する。通常は 1 つのエントリを読み取る場合に使用)、singleLevel(ベース DN の直下のエントリ)、またはwholeSubtree(ベース DN から始まるサブツリー全体)のいずれかになります。(&(objectClass=person)(|(givenName=John)(mail=john*)))「persons」(objectClass の要素)を選択し、それらの属性の値がフィルタのアサーションに一致するかどうかを判断します。よくある誤解として、LDAP データは大文字と小文字を区別しますが、実際には、一致ルールと順序ルールによって、一致、比較、および相対的な値の関係が決定されます。例のフィルタで属性値の大文字と小文字を一致させる必要がある場合は、拡張可能な一致フィルタを使用する必要があります。たとえば、persongivenNamemail(&(objectClass=person)(|(givenName:caseExactMatch:=John)(mail:caseExactSubstringsMatch:=john*)))サーバーは一致するエントリと、場合によっては継続参照を返します。これらは任意の順序で返される可能性があります。最終結果には結果コードが含まれます。
比較操作は、DN、属性名、属性値を受け取り、指定されたエントリにその属性とその値が含まれているかどうかを確認します。
MODIFY操作は、LDAPクライアントがLDAPサーバーに既存のエントリを変更するよう要求するために使用されます。[ 20 ]存在しないエントリを変更しようとすると失敗します。MODIFY要求は、サーバーによって実装されたアクセス制御の対象となります。
MODIFY操作では、エントリの識別名(DN)と変更シーケンスを指定する必要があります。シーケンス内の各変更は、次のいずれかでなければなりません。
属性に値を追加するLDIFの例:
dn : dc = example 、dc = com changetype : modify add : cn cn :追加する新しい cn の値-既存の属性の値を置き換えるには、replaceキーワードを使用します。属性が複数値の場合、クライアントは更新する属性の値を指定する必要があります。
エントリから属性を削除するには、キーワードdeleteと変更タイプ指定子を使用しますmodify。属性が複数値の場合、クライアントは削除する属性の値を指定する必要があります。
また、増分可能な属性値を指定された量だけ増分できるModify-Increment 拡張機能[ 21 ]もあります。LDIF を使用した次の例では、employeeNumber次のように増分します5。
dn : uid = user.0 、ou = people 、dc = example 、dc = com changetype : modify increment : employeeNumber employeeNumber : 5 -LDAP サーバーがレプリケートされたトポロジにある場合、LDAP クライアントは更新後に検索を行う代わりに、ポスト リード コントロールを使用して更新を確認することを検討する必要があります。[ 22 ]ポスト リード コントロールは、アプリケーションが更新後に検索要求を発行する必要がないように設計されています。レプリケーションの最終的な整合性モデルのため、更新が機能したかどうかを確認するためだけにエントリを取得するのは好ましくありません。アーキテクトが LDAP クライアントとサーバーの間にロード バランサーや LDAP プロキシ、またはその両方を配置している可能性があるため、LDAP クライアントは要求ごとに同じディレクトリ サーバーに接続すると想定すべきではありません。
DN の変更 (エントリの移動/名前変更) では、新しい RDN (相対識別名)、オプションで新しい親の DN、および古い RDN に一致するエントリ内の値を削除するかどうかを示すフラグを指定します。サーバーによっては、ディレクトリ サブツリー全体の名前変更をサポートしている場合があります。
更新操作はアトミックです。他の操作では、新しいエントリか古いエントリのどちらかしか参照できません。一方、LDAP は複数の操作のトランザクションを定義していません。エントリを読み取ってから変更した場合、その間に別のクライアントがエントリを更新している可能性があります。ただし、サーバーはこれをサポートする拡張機能[ 23 ]を実装している場合があります。
拡張操作は、元のプロトコル仕様には含まれていなかった新しい操作を定義できる汎用的なLDAP操作です。StartTLSは最も重要な拡張機能の1つです。その他の例としては、キャンセルやパスワード変更などがあります。
StartTLS操作は、接続上にトランスポート層セキュリティ(SSLの後継)を確立します。これにより、データの機密性(第三者によるデータの傍受を防ぐ)および/またはデータの完全性保護(データの改ざんを防ぐ)が実現できます。TLSネゴシエーション中、サーバーは自身の身元を証明するためにX.509証明書を送信します。クライアントも自身の身元を証明するために証明書を送信できます。その後、クライアントはSASL /EXTERNALを使用できます。SASL /EXTERNALを使用することで、クライアントはサーバーに対し、下位レベル(TLSなど)で提供された認証情報から自身の身元を取得するように要求します。技術的には、サーバーは下位レベルで確立された任意の身元情報を使用できますが、通常はTLSによって確立された身元情報を使用します。
サーバーは、多くの場合、別のポート(デフォルトでは636番)で非標準の「LDAPS」(「セキュアLDAP」、一般に「SSL経由のLDAP」として知られる)プロトコルもサポートしています。LDAPSはLDAPと2つの点で異なります。1)接続時に、クライアントとサーバーはLDAPメッセージが転送される前にTLSを確立します(StartTLS操作は不要)。2)TLS接続が切断されると、LDAPS接続も切断する必要があります。
一部の「LDAPS」クライアントライブラリは通信を暗号化するだけで、ホスト名が提供された証明書の名前と照合されません。[ 24 ]
Abandon操作は、メッセージIDで指定された操作をサーバーが中止するように要求します。サーバーはこの要求に応じる必要はありません。Abandon操作も、正常に中止された操作も、応答を送信しません。同様のCancel拡張操作は応答を送信しますが、すべての実装がこれをサポートしているわけではありません。
アンバインド操作は、未処理の操作をすべて破棄し、接続を閉じます。応答はありません。この名前は歴史的な由来のものであり、バインド操作の反対ではありません。 [ 25 ]
クライアントは接続を閉じるだけでセッションを中止できますが、Unbind を使用する必要があります。[ 26 ] Unbind を使用すると、サーバーは接続を正常に閉じ、クライアントが接続を放棄したことを検出するまでしばらくの間保持するリソースを解放できます。また、キャンセル可能な操作をキャンセルし、キャンセルできない操作に対する応答を送信しないようにサーバーに指示します。[ 27 ]
LDAP の統一リソース識別子 (URI)スキームが存在し、クライアントはこれを様々な程度でサポートし、サーバーは参照および継続参照でこれを返します (RFC 4516 を参照)。
ldap://host:port/DN?attributes?scope?filter?extensions
以下に説明するコンポーネントのほとんどはオプションです。
(objectClass=*)RFC 4515 で定義されているように。例えば、「ldap://ldap.example.com/cn=John%20Doe,dc=example,dc=com」は、 の John Doe のエントリにあるすべてのユーザー属性を参照しますldap.example.com。一方、「ldap:///dc=example,dc=com??sub?(givenName=John)」は、デフォルト サーバーでエントリを検索します (ホストを省略するトリプル スラッシュと、属性を省略するダブル クエスチョン マークに注意してください)。他の URL と同様に、特殊文字はパーセント エンコードする必要があります。
SSL 経由の LDAP にも、同様の非標準ldapsURI スキームが存在します。これは、標準スキームを使用して StartTLS 操作によって実現される TLS を使用した LDAP とは混同しないでくださいldap。
サブツリー内のエントリの内容は、ディレクトリスキーマ、つまりディレクトリ情報ツリー(DIT)の構造に関する定義と制約のセットによって規定されます。
ディレクトリサーバーのスキーマは、サーバーが保持できる情報の種類を規定する一連のルールを定義します。スキーマには、以下のような要素が含まれます。
属性はディレクトリに情報を格納する役割を担う要素であり、スキーマはエントリで使用できる属性の種類、それらの属性が持つことができる値の種類、およびクライアントがそれらの値とどのようにやり取りできるかに関する規則を定義します。
クライアントは、適切なサブスキーマのサブエントリを取得することで、サーバーがサポートするスキーマ要素について知ることができます。
スキーマはオブジェクトクラスを定義します。各エントリには、スキーマで定義された名前付きクラスを含む objectClass 属性が必要です。エントリのクラスのスキーマ定義は、エントリがどのような種類のオブジェクト(例:人物、組織、ドメイン)を表すことができるかを定義します。オブジェクトクラスの定義には、値を持つ必要がある属性のリストと、値を持つことができる属性のリストも定義されます。
例えば、人物を表すエントリは、「top」クラスと「person」クラスに属する可能性があります。「person」クラスに属するには、エントリに「sn」属性と「cn」属性が含まれている必要があり、さらに「userPassword」、「telephoneNumber」、その他の属性を含めることもできます。エントリは複数の ObjectClasses 値を持つことができるため、各エントリは、それが表すオブジェクト クラスの和集合から形成される、オプション属性と必須属性の複雑なセットを持ちます。ObjectClasses は継承でき、単一のエントリは、エントリ自体の使用可能な属性と必須属性を定義する複数の ObjectClasses 値を持つことができます。オブジェクト クラスのスキーマに類似するものは、オブジェクト指向プログラミングにおけるクラス定義とインスタンスであり、それぞれ LDAP オブジェクトクラスと LDAP エントリを表します。
ディレクトリサーバーは、エントリのサブスキーマサブエントリ操作属性で指定されたベースDNに、エントリを制御するディレクトリスキーマを公開する場合があります。(操作属性は、ユーザー情報ではなくディレクトリの操作を記述するものであり、明示的に要求された場合にのみ検索結果として返されます。)
サーバー管理者は、提供されているスキーマ要素に加えて、追加のスキーマエントリを追加できます。組織内の個人を表すスキーマは、ホワイトページスキーマと呼ばれます。
LDAPインジェクションは、SQLインジェクションに似たコンピュータセキュリティ攻撃であり、LDAPを実装するアプリケーションがユーザー入力を適切にサニタイズしない場合に発生する可能性があります。[ 28 ]
例として、ユーザーが名前cn属性で人物を検索できるLDAP検索クエリを考えてみましょう。悪意のあるユーザーは、有効な名前を*、属性を持つすべてのオブジェクトに一致する文字に置き換える可能性がありますcn。アプリケーションがこの攻撃に対して脆弱な場合、検索ユーザーが閲覧する権限のない属性が表示される可能性があります。[ 29 ]
LDAPインジェクションの脆弱性は、変数をエスケープすることで軽減されます。エスケープは、識別名用と検索文字列用の2つの異なるエンコード関数を使用して行われます。これは、それぞれ異なる特殊文字を許容するためです。一部のWebフレームワークには、エスケープ機能が組み込まれています。[ 30 ]
TCP/IPの他の部分と同様に、LDAPは当初暗号化なしで作成されました。そのため、バインド処理中に攻撃者が認証情報を傍受する中間者攻撃に対して脆弱です。この攻撃は、認証情報を含むすべてのバインドでLDAPSまたはStartTLSを要求することで軽減できます。[ 31 ]
サーバーの運用に関する多くの事項は、実装者または管理者の判断に委ねられています。そのため、サーバーは多種多様なシナリオに対応できるように設定できます。
例えば、サーバーにおけるデータ保存方法は規定されていません。サーバーはフラットファイル、データベースを使用する可能性があり、あるいは単に他のサーバーへのゲートウェイとして機能するだけかもしれません。アクセス制御も標準化されていませんが、一般的に使用されているモデルは存在します。ユーザーのパスワードは、ユーザーのエントリ内、あるいは別の場所に保存される可能性があります。サーバーは、必要に応じて操作の実行を拒否したり、様々な制限を課したりすることができます。
LDAPのほとんどの部分は拡張可能です。例えば、新しい操作を定義できます。コントロールによってリクエストとレスポンスを変更でき、例えば検索結果をソートしてリクエストできます。新しい検索範囲やバインド方法を定義できます。属性には、その意味を変更するオプションを設定できます。
LDAP が勢いを増すにつれ、ベンダーはそれを他のサービスへのアクセス プロトコルとして提供するようになった。実装では、LDAP/X.500 モデルを模倣するようにデータを再構成するが、このモデルにどれだけ忠実に従うかは様々である。たとえば、 LDAP は必ずしも適しているわけではないが、LDAP を介してSQLデータベースにアクセスするソフトウェアが存在する。[ 32 ] X.500 サーバーも LDAP をサポートしている可能性がある。
同様に、以前は他の種類のデータストアに保存されていたデータが、LDAPディレクトリに移動されることもあります。例えば、Unixのユーザー情報やグループ情報はLDAPに保存され、PAMやNSSモジュールを介してアクセスできます。LDAPは、認証や認可(既に認証済みのユーザーがどのサービスでどのような操作を実行できるか)のために、他のサービスでもよく利用されます。例えば、Active Directoryでは、認証ステップでKerberosが使用され、認可ステップでLDAPが使用されます。
このようなデータモデルの一例として、GLUEスキーマ[ 33 ]が挙げられます。これはLDAPに基づく分散情報システムで使用され、ユーザー、アプリケーション、サービスがグリッドインフラストラクチャに存在するサービスや、それらの構造と状態に関する詳細情報を発見できるようにします。
LDAPサーバーは、自身で処理できないリクエストに対して、他のサーバーへの参照を返す場合があります。そのため、LDAPエントリには命名構造が必要となり、特定の識別名(DN)を持つサーバーを特定できるようになります。識別名(DN)はX.500ディレクトリで定義され、LDAPでも使用される概念です。組織のLDAPサーバーを特定するもう1つの方法は、DNSサーバーレコード(SRV)を使用することです。
ドメイン example.org を持つ組織は、トップレベルの LDAP DN dc=example, dc=org( dcはドメイン コンポーネントを意味します) を使用できます。LDAP サーバーの名前も ldap.example.org の場合、組織のトップレベルの LDAP URL は になりますldap://ldap.example.org/dc=example,dc=org。
X.500 [2008] と LDAPv3 では、主に 2 つの一般的な命名スタイルが使用されています。これらは ITU 仕様と IETF RFC に記載されています。元の形式では、最上位オブジェクトが国オブジェクトとして扱われます。たとえばc=US、 、などですc=FR。ドメイン コンポーネント モデルでは、上記のモデルが使用されます。国ベースの命名の例としてはl=Locality, ou=Some Organizational Unit, o=Some Organization, c=FR、 、 または米国の 、 などが挙げられますcn=Common Name, l=Locality, ou=Some Organizational Unit, o=Some Organization, st=CA, c=US。
X.500 (1993) ディレクトリ抽象サービス [X.511] のサブセットにマッピングできます。ただし、LDAP操作とX.500ディレクトリアクセスプロトコル (DAP) 操作の間には1対1のマッピングはありません。