2

Spring-LDAP を使用して、Java でプログラムを作成しています。SID でユーザーを検索するメソッドを実装する必要があります。このため、 のようなフィルターを使用します"&((objectClass=User)(objectSid="+sid+"))"。のような文字列形式の sid では検索できません"S-1-12-345677-5676743-223344-..."

Apache Directory Studio を使用して、次のようなフィルターを使用して定期的に AD LDAP データベースにクエリを実行できます(objectSid=\ff\01\03\04\1a\2b\...)。これは、16 進形式の objectSid です。

さて、Javaでプログラム内でSIDを文字列から16進数に、またはその逆に変換する方法は?

4

5 に答える 5

5

Advapi32Utilクラスには メソッドconvertSidToStringSidconvertStringSidToSidメソッドがあります。

それがあなたが必要とする正確なフォーマットになるかどうかはわかりませんが、うまくいけばあなたが近づくでしょう.

また、役立つかもしれない SID 形式について説明しているブログ投稿を次に示します。

于 2011-08-19T08:02:50.777 に答える
3

ho1 (Advapi32Util を使用) クラスによって提案されたソリューションには、2 つの制限があります。

  1. JNA ライブラリが必要です。
  2. Windows-API を使用するため、Windows プラットフォームで実行している場合にのみ機能します。

したがって、私は純粋な Java であり、外部依存関係がなく、すべてのプラットフォームで動作するクラスを作成しました。このクラスは、セキュリティ識別子をバイナリからテキスト表現に、またはその逆に変換できます。

Spring-LDAP を使用している場合は、LdapUtils クラスによって提供されるメソッドも使用できますが、これらのメソッドは SID の形式のチェックを実行しないため、誤った結果や予期しない例外が発生する可能性があります。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class SidConverter {

    private final static int MASK_8_BIT = 0xff;
    private final static long MASK_32_BIT = 0xffffffffL;
    private final static long MASK_48_BIT = 0xffffffffffffL;

    public static String bytesToString(byte[] bytes) {
        if (bytes.length < 8) {
            throw new IllegalArgumentException(
                    "Binary SID representation must have at least 8 bytes but passed byte array has only "
                            + bytes.length + " bytes.");
        }
        // The revision number is an unsigned 8-bit unsigned integer.
        int revision = bytes[0] & MASK_8_BIT;
        // The number of sub-authority parts is specified as an 8-bit unsigned
        // integer.
        int numberOfSubAuthorityParts = bytes[1] & MASK_8_BIT;
        if (bytes.length != 8 + numberOfSubAuthorityParts * 4) {
            throw new IllegalArgumentException(
                    "According to byte 1 of the SID it total length should be "
                            + (8 + 4 * numberOfSubAuthorityParts)
                            + " bytes, however its actual length is "
                            + bytes.length + " bytes.");
        }
        // The authority is a 48-bit unsigned integer stored in big-endian
        // format.
        long authority = ByteBuffer.wrap(bytes).getLong() & MASK_48_BIT;
        // The sub-authority consists of up to 255 32-bit unsigned integers in
        // little-endian format. The number of integers is specified by
        // numberOfSubAuthorityParts.
        int[] subAuthority = new int[numberOfSubAuthorityParts];
        ByteBuffer.wrap(bytes, 8, bytes.length - 8)
                .order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().put(subAuthority);
        StringBuilder sb = new StringBuilder();
        sb.append("S-");
        sb.append(revision);
        sb.append("-");
        sb.append(authority);
        for (int subAuthorityPart : subAuthority) {
            sb.append("-");
            sb.append(subAuthorityPart & MASK_32_BIT);
        }
        return sb.toString();
    }

    public static byte[] stringToBytes(String sid) {
        if (!sid.startsWith("S-") && !sid.startsWith("s-")) {
            throw new IllegalArgumentException("Invalid SID \"" + sid
                    + "\": A valid SID must start with \"S-\".");
        }
        String[] parts = sid.split("-");
        if (parts.length < 3) {
            throw new IllegalArgumentException("Invalid SID \"" + sid
                    + "\": A valid SID must have at least two dashes.");
        }
        if (parts.length > MASK_8_BIT + 3) {
            throw new IllegalArgumentException("Invalid SID \"" + sid
                    + "\": A valid SID must not have more than 257 dashes.");
        }
        int revision;
        try {
            revision = Integer.parseInt(parts[1]);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(
                    "Invalid revision part in SID \""
                            + sid
                            + "\": The revision must be an integer number between 0 and 255.");
        }
        if (revision < 0 || revision > MASK_8_BIT) {
            throw new IllegalArgumentException(
                    "Invalid revision part in SID \""
                            + sid
                            + "\": The revision must be an integer number between 0 and 255.");
        }
        int numberOfSubAuthorityParts = parts.length - 3;
        long authority;
        try {
            authority = Long.parseLong(parts[2]);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(
                    "Invalid authority part in SID \""
                            + sid
                            + "\": The authority must be an integer number between 0 and 281474976710655.");
        }
        if (authority < 0 || authority > MASK_48_BIT) {
            throw new IllegalArgumentException(
                    "Invalid authority part in SID \""
                            + sid
                            + "\": The authority must be an integer number between 0 and 281474976710655.");
        }
        int[] subAuthority = new int[numberOfSubAuthorityParts];
        for (int i = 0; i < numberOfSubAuthorityParts; i++) {
            long subAuthorityPart;
            try {
                subAuthorityPart = Long.parseLong(parts[3 + i]);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        "Invalid sub-authority part in SID \""
                                + sid
                                + "\": The sub-authority parts must be integer numbers between 0 and 4294967295.");
            }
            if (subAuthorityPart < 0 || subAuthorityPart > MASK_32_BIT) {
                throw new IllegalArgumentException(
                        "Invalid sub-authority part in SID \""
                                + sid
                                + "\": The sub-authority parts must be integer numbers between 0 and 4294967295.");
            }
            subAuthority[i] = (int) subAuthorityPart;
        }
        byte[] bytes = new byte[8 + numberOfSubAuthorityParts * 4];
        // We have to write the authority first, otherwise it would overwrite
        // the revision and length bytes.
        ByteBuffer.wrap(bytes).putLong(authority);
        bytes[0] = (byte) revision;
        bytes[1] = (byte) numberOfSubAuthorityParts;
        ByteBuffer.wrap(bytes, 8, bytes.length - 8)
                .order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().put(subAuthority);
        return bytes;
    }

}
于 2014-02-17T00:11:44.997 に答える
1

JNA を使用しない例

JNA を使用せずに SID を変換するためのコンパクトなコードを次に示します。何かが正しくない場合に NULL、EMPTY、または長さ 0 の配列を返すことによって、いくつかの「エラー チェック」が組み込まれています。

SID から文字列の場合:

/**
 * Converts Windows SID to a String. NULL input returns NULL.
 * Invalid byte array returns EMPTY.
 * @param sid SID as byte array.
 * @return SID as String.
 */
public static String convertSidToStr(byte[] sid) {
    if (sid==null) return null;
    if (sid.length<8 || sid.length % 4 != 0) return "";
    StringBuilder sb = new StringBuilder();
    sb.append("S-").append(sid[0]);
    int c = sid[1]; // Init with Subauthority Count.
    ByteBuffer bb = ByteBuffer.wrap(sid);
    // bb.order(ByteOrder.BIG_ENDIAN); // Not needed, default big endian.
    sb.append("-").append((long)bb.getLong() & 0XFFFFFFFFFFFFL);
    bb.order(ByteOrder.LITTLE_ENDIAN); // Now switch.
    for (int i=0; i<c; i++) { // Create Subauthorities.
        sb.append("-").append((long)bb.getInt() & 0xFFFFFFFFL);
    }        
    return sb.toString();    
}

文字列から SID の場合:

/**
 * Converts Windows SID String to byte array. NULL input returns NULL.
 * Invalid String returns zero-length byte array.
 * @param sid SID as String.
 * @return SID as byte array.
 */
public static byte[] convertStrToSid(String sid) {
    if (sid==null) return null;
    if (!sid.matches("^[sS]-\\d-\\d{1,13})"
            + "(?:-\\d{1,10})*$")) return new byte[0];
    String[] ss = sid.split("-");
    int c=ss.length-3; // Init with Subauthority Count.
    byte[] b=new byte[2+6+(c*4)];
    ByteBuffer bb = ByteBuffer.wrap(b);
    // bb.order(ByteOrder.BIG_ENDIAN); // Not needed, default big endian.
    bb.putLong(Long.parseLong(ss[2]));
    // Overlay bytes 0 and 1 with Revision and Identifier Authority.
    b[0]=(byte)Short.parseShort(ss[1]);
    b[1]=(byte)c;
    bb.order(ByteOrder.LITTLE_ENDIAN); // Now switch.
    for (int i=0; i<c; i++) { // Create Subauthorities.
        bb.putInt((int)Long.parseLong(ss[i+3]));
    }
    return b;    
}

参考として、TechNet のSecurity Identifier Structureを参照してください。

于 2017-01-08T15:05:08.797 に答える