問題タブ [gssapi]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
kerberos - SSPI を使用して、Kerberos トークンを GSSAPI 対応の HTTP プロキシ サーバーに送信するにはどうすればよいですか?
Web サイトにアクセスするための単純なクライアント ソケット アプリケーションがあります。クライアントがインターネットにアクセスするには、HTTP プロキシ サーバーを経由する必要があります (Microsoft Forefront Threat Management Gateway を使用しています)。プロキシ サーバーは認証を必要とし、GSSAPI 経由で Kerberos を受け入れるように構成されています。
私のクライアントでは、Microsoft の SSPI を使用しています。
まず、成功して返されるAcquireCredentialsHandleを呼び出しますSEC_E_OK
次に、InitializeSecurityContextを呼び出します。これも成功して戻りますSEC_E_OK
ここまでは順調ですね。しかし今、承認のためにトークンをプロキシサーバーに送信する必要があります。これが問題を引き起こしている部分です。
Internet Explorer を使用してプロキシ サーバーに接続すると、Wireshark を介してパケット交換を監視できます。IE は Kerberos とチケットをネゴシエートし、Proxy-Authorization ヘッダーを介して送信するように見えます。ヘッダーの内容は base64 でエンコードされているようです。
から返されたトークンを単に取得し、InitializeSecurityContext
それを base64 エンコードして、結果を のようなヘッダーを介してプロキシ サーバーに送信するとProxy-Authorization: Negotiate <base64Data>
、認証は失敗します。
近づいたような気がしますが、まだ何かが欠けています。あるサイトでは、送信前にトークンで EncryptMessage を使用することについて説明していました。相互認証の使用について別の議論がありました (IE が相互認証を使用しているとは思いません。なぜなら、クライアントは認証を 1 回しか送信していないようで、サーバーからのフィードバック データがないためです ( InitializeSecurityContext
2 回目に呼び出す)。別のサイトでは、トークンをさまざまなSEC_BUFFER
タイプ(パディング、データなど)と暗号化方法に関するドキュメントがあまり見つからないため、これが必要なことだと思います。
洞察や提案をいただければ幸いです。
UPDATE 7/19/2014: 明確にするために、SSPI を使用して「base64Data」フィールドを計算する方法を尋ねています (上記参照)。SECBUFFER_TOKEN のバッファに含まれるコンテンツの base64 エンコーディングを計算することは私の最初の推測でしたが、サーバーは結果を受け入れないため、明らかに無効です。
さらなる調査によると、トークンを「ラップ」する必要があり (別名、SSPI を介して「EncryptMessage」)、GSSAPI と互換性のある方法で暗号化するには、3 つのバッファーを使用する必要があります (順序: SECBUFFER_TOKEN、SECBUFFER_DATA、および SECBUFFER_PADDING)。これは昨日ですが、成功しませんでした。
java - GSSManager を使用して Kerberos チケットを検証する
次のコードがあります。
もちろん失敗します。例外は次のとおりです。
GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
これを解決するために何をすべきかわかりません。正直なところ、私は Kerberos をよく理解していません。
WWW-Authenticate
値として「Negotiate」を含む適切なヘッダーを付けて 401 を送信することで、このチケットを取得しました。authorization
ブラウザーは、このチケットを含むヘッダーを使用して、同じ要求をすぐに再度発行しました。
チケットを検証して、ユーザーが誰であるかを特定できることを望んでいました。
キータブファイルは必要ですか? もしそうなら、どの資格情報でこれを実行しますか? Web サイトの認証に Kerberos チケットを使用しようとしています。資格情報は IIS からの資格情報でしょうか?
私は何が欠けていますか?
更新 1 Michael-O の返信から、もう少しグーグルで調べたところ、この記事が見つかり、この記事にたどり着きました。
table 3
で、 を見つけました1.3.6.1.5.5.2 SPNEGO
。
最初の記事の例に従って、資格情報にそれを追加しました。これが私のコードです:
しかし、コードは次のcreateCredential
エラーで失敗しています。
チケット全体は次のとおりです。YIGCBgYrBgEFBQKgeDB2oDAwLgYKKwYBBAGCNwICCgYJKoZIgvcSAQICBgkqhkiG9xIBAgIGCisGAQQBgjcCAh6iQgRATlRMTVNTUAABAAAAl7II4g4ADgAyAAAACgAKACgAAAAGAbEdAAAAD0xBUFRPUC0yNDVMSUZFQUNDT1VOVExMQw==
java - Java で GSSAPI 認証を使用すると、Active Directory からの検索結果に LDAP Continuity Reference エラーが表示される
更新:以下の @Michael-O からのコメントに基づいて、LDAP JNDI プロバイダーまたは SASL 実装がホスト名を正規化する場合、この問題を処理する正しい方法のように思われます。 KRN サービス チケットのリクエスト。Open JDK セキュリティ リストにアクセスして、そこから回答が得られるかどうかを確認してみます。
Kerberos LoginContextのサブジェクトを使用して GSSAPI 経由で認証されたセッションを使用して、Active Directory サーバーに対してルート DN で再帰的な LDAP 検索を実行しようとしています。
URL を使用してサーバーに正常にバインドできましたldap://dc1.example.com
。InitidalDirContextには、java.naming.referralがに設定されていfollow
ます。
(&(objectClass=user)(userPrincipalName=sample_user@EXAMPLE.COM))
のルート DN に対して検索を実行するとdc=example,dc=com
、1 つのSearchResultが返されます。
そして、いくつかの継続参照:
SearchResultを問題なく反復できますが、継続に遭遇するとすぐにPartialResultsExceptionが発生します。DNS を確認したところ、上記のホスト名はすべて正しく解決されました。私が得る例外は次のようになります:
Kerberos トレースを見ると、このエラーは理にかなっています。続きをたどろうとすると、LDAP ライブラリは にバインドしようとしますldap://example.com
。認証に GSSAPI を使用しているため、これにより のサービス チケット要求がトリガーされldap/example.com
ます。ログに表示される応答は次のとおりです。
Active Directory を確認したところ、ドメイン コントローラのどこにも値が設定されたservicePrincipalName属性がないことを確認しました。SAVANT-DC1 ドメイン コントローラのマシン アカウントにldap/example.com
SPN を手動で追加しようとしました。ldap/example.com
これは一時的に機能しますが、Active Directory は数分後に SPN エントリを自動的に削除するようです。
解決策は次のいずれかを行うことのようです
- Active Directory を取得して、ドメインではなくドメイン コントローラーの名前を含む継続を返します。の形式で SPN のサービス チケットを取得できることがわかってい
ldap/dc1.example.com
ます。 - どういうわけか、リダイレクト先のJavaの終わりに継続をマップ
ldap://example.com
しますldap://dc1.example.com
(1)のやり方がわかりません。
(2)のJNDI手動参照処理例を参考にやってみました。java.naming.referralプロパティをに切り替え、参照コンテキストでjava.naming.provider.urlthrow
プロパティを手動でオーバーライドするカスタム参照ハンドラを作成しました。ただし、 java.naming.provider.url環境プロパティを無視しているようです。LdapReferralContext.javaへの OpenJDK コードを見ると、これが確認されているようです (105 行目)。LdapReferralException.getReferralContext()
つまり、JNDI API によってリフェラルがブラック ボックスとして扱われるため、Java 側でリフェラルをインターセプトして操作することはできません。LDAP SPN はディレクトリに永続的に保持されないため、AD 側で手動で LDAP SPN を作成することはできません。私が見逃しているものは他にありますか?
これが私が実行しているコードです
ここに私のkrb5.confがあります:
上記のコードからの出力は次のとおりです
python-2.7 - Python と Azure Service Bus で必要な認証メカニズム
Linux で python を使用して、azure サービス バスに接続したいと考えています。そのために、qpid-proton と amqp プロトコルを使用しています。
ただし、サービス バスに接続しようとすると、次のエラーが発生します。
qpid.messaging.exceptions.AuthenticationFailure: sasl ネゴシエーションに失敗しました: メカニズムが合意されていません
サービス バスが SASL ユーザー名/パスワード スキームをサポートしていることは理解していますが、他に何が必要ですか? GSSAPIが使用されているという漠然とした考えがあります。
c - クライアントから送信されたトークンを使用してセキュリティコンテキストを受け入れる前にユーザー名を取得する方法は?
サーバーとして機能し、Kerberos 認証に GSSAPI を使用するアプリケーションを使用しています。
クライアントがネゴシエートを送信するたびに資格情報を取得します:
トークン
は gss_accept_sec_context を使用してコンテキストを受け入れ
、表示名を呼び出して MyName@DOMAIN のようなユーザー名を取得します
現在、アプリケーションはセッションごとに認証を実行しています。
キャッシュを使用した SSO 認証
しかし、最初のセッションで一度認証を実行し、何かを使用してユーザーを再認証するために何かをキャッシュするようにアプリケーションを変更したいと思います。ここでは、ユーザー名アプリケーションを再度取得してコンテキストを受け入れ、表示名を呼び出すため、ユーザー名 (MyName@DOMAIN) をキャッシュできません。
キャッシュを使用して SSO 認証を実行する方法はありますか?