ユーザーが Active Directory で自分のパスワードをリセットできる Web アプリを開発しています。管理者としてバインドして実行しており、正常に動作しますが、ディレクトリ ポリシー (再利用履歴、文字など) が適用されていません。現在のパスワードがないため、ユーザーとしてバインドできません。
Active Directoryでそれを行うためにWindows 2008 R2 SP1で導入されたLDAP_SERVER_POLICY_HINTSコントロールについて読み、Spring LDAPを使用してそれを作成した人を見つけました
私は UnboundID を使用しており、そのための標準コントロールは出荷されていないため、独自のコントロール クラスを作成する必要があると考えました。文書化された OID は 1.2.840.113556.1.4.2239 で、値は {48, 3, 2, 1, 1} です。
public class PolicyHintsControl extends Control {
private static final long serialVersionUID = 1L;
public final static String LDAP_SERVER_POLICY_HINTS_OID = "1.2.840.113556.1.4.2066";
public final static byte[] LDAP_SERVER_POLICY_HINTS_DATA = { 48,
(byte) 132, 0, 0, 0, 3, 2, 1, 1 };
public PolicyHintsControl() {
super(LDAP_SERVER_POLICY_HINTS_OID, false, new ASN1OctetString(
LDAP_SERVER_POLICY_HINTS_DATA));
}
@Override
public String getControlName() {
return "LDAP Server Policy Hints Control";
}
@Override
public void toString(StringBuilder buffer) {
buffer.append("LDAPServerPolicyHints(isCritical=");
buffer.append(isCritical());
buffer.append(')');
}
}
そこで、次のように変更リクエストにこの新しいコントロールを追加しました。
public static void main(String[] args) throws Exception {
final String host = "ldap.example.com";
final int port = 636;
String adminDn = "admin@example.com";
String adminPassword = "passwd";
String userDn = "CN=user,ou=people,dc=example,dc=com";
String userPassword = "passwd";
String keystoreFile = "/path/to/keystore.jks";
String keystorePassword = "passwd";
String passwordAttribute = "unicodePwd";
//Password change requires SSL
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keystoreFile), keystorePassword.toCharArray());
TrustManagerFactory factory = TrustManagerFactory.getInstance("x509");
factory.init(keyStore);
final SSLUtil sslUtil = new SSLUtil(factory.getTrustManagers());
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
Debug.setEnabled(true);
// Connect as the configured administrator
LDAPConnection ldapConnection = new LDAPConnection(socketFactory, host,
port, adminDn, adminPassword);
// Set password in AD format
final String newQuotedPassword = "\"" + userPassword + "\"";
final byte[] newPasswordBytes = newQuotedPassword.getBytes("UTF-16LE");
String encryptedNewPwd = new String(newPasswordBytes);
//Build modifications array and request
final ArrayList<Modification> modifications = new ArrayList<Modification>();
modifications.add(new Modification(ModificationType.REPLACE,
passwordAttribute, encryptedNewPwd));
ModifyRequest modifyRequest = new ModifyRequest(userDn, modifications);
//Add the policy hints control
modifyRequest.addControl(new PolicyHintsControl());
//Modify already
ldapConnection.modify(modifyRequest);
ldapConnection.close();
}
次の例外が発生します。
Exception in thread "main" LDAPException(resultCode=53 (unwilling to perform), errorMessage='0000052D: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
', diagnosticMessage='0000052D: SvcErr: DSID-031A120C, problem 5003 (WILL_NOT_PERFORM), data 0
')
もう少し調査した結果、Windows 2012 には、OID を 1.2.840.113556.1.4.2066 に変更し、古い OID を廃止する同じコントロールの別の更新プログラムがあることがわかりました。
このアプリは任意のバージョンの AD で構成できるため、すべてのシナリオ (Windows 2012、Windows 2008 R2 SP1 など) を適切に処理したいと考えています。私の質問は次のとおりです。
- UnboundID でこれを成功させた人はいますか?
- 変更要求の前にコントロールが利用可能かどうかを知る方法はありますか?
- 同じコントロールの異なるバージョンの AD の異なる OID を処理する最良の方法は何でしょうか? 同じクラスか違うクラスか?