JavaでWindows Serverのセキュリティ識別子(SID)をちょっと便利に扱うプログラム

火曜日 , 23, 8月 2022 Leave a comment

JavaでWindows Serverのセキュリティ識別子(SID)を文字列化したりバイナリ化したり変換するプログラムを作成したので公開します。

よく知られている SID』で掲載されているものや、Windows Serverのビルトインアカウントなどで確認を行っています。

JavaからActive Directoryのアクセス制御エントリを取得 / JavaからLDAP/Active Directoryサーバ認証』の続きです。

ソースコード

セキュリティ識別子を変換するプログラム

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;


/**
*  Windows Serverのセキュリティ識別子(SID: Security Identifier)を扱うプログラム
* 
* This software is distributed under the license of NYSL.
* <a href="http://www.kmonos.net/nysl/">http://www.kmonos.net/nysl/</a>
*  
*/
public class SidUtil {

	private static final int BYTE_MASK = 0xFF;
	private static final long LONG_MASK = 0xFFFFFFFFL;
	
	/**
	 * 	バイナリのセキュリティ識別子を文字列化する
	 * 
	 * @param data	セキュリティ識別子
	 * @return	文字列化されたセキュリティ識別子
	 */
	public static String toSidString(byte[] data) {
	
		ByteBuffer buffer = ByteBuffer.wrap(data);
		List<String>tokens = new ArrayList<String>();
		
		// signature
		tokens.add("S");
		
		// revision
		tokens.add(String.valueOf(buffer.get() & BYTE_MASK));
		
		// sub-auth count
		int subAuthCount = buffer.get() & BYTE_MASK;
		
		// auth
		buffer.limit(buffer.position() + 6);
		long auth = 0;
		while (buffer.hasRemaining()) {
			auth = auth << 8 | buffer.get() & BYTE_MASK;
		}
		tokens.add(String.valueOf(auth & LONG_MASK));
		
		// sub-auth
		for (int i = 0; i < subAuthCount; i++) {
			buffer.limit(buffer.position() + 4);
			long subauth = 0;
			int offset = 0;
			while (buffer.hasRemaining()) {
				subauth = subauth | (buffer.get() & BYTE_MASK) << offset;
				offset += 8;
			}
			tokens.add(String.valueOf(subauth & LONG_MASK));
		}
	
		return String.join("-", tokens);
	}
	
	/**
	 * 	文字列のセキュリティ識別子をバイナリ化する
	 * 
	 * @param sid	セキュリティ識別子
	 * @return	バイナリ化されたセキュリティ識別子
	 */
	public static byte[] toSidBinary(String sid) {
		
		String[] tokens = sid.split("-");
		int idx = 0;
		
		// signature
		idx++;
		
		int revision = Integer.valueOf(tokens[idx++]);
		long auth = Long.valueOf(tokens[idx++]);
		List<String>subAuthTokens = new ArrayList<String>();
		while (idx < tokens.length) {
			subAuthTokens.add(tokens[idx++]);
		}
		
		ByteBuffer buffer = ByteBuffer.allocate(1 + 1 + 6 + (4 * subAuthTokens.size()));
		// revision
		buffer.put((byte)(revision & BYTE_MASK));
		// sub-auth count
		buffer.put((byte)(subAuthTokens.size() & BYTE_MASK));
		
		// auth
		buffer.put((byte)((auth >> 40) & BYTE_MASK));
		buffer.put((byte)((auth >> 32) & BYTE_MASK));
		buffer.put((byte)((auth >> 24) & BYTE_MASK));
		buffer.put((byte)((auth >> 16) & BYTE_MASK));
		buffer.put((byte)((auth >> 8) & BYTE_MASK));
		buffer.put((byte)(auth & BYTE_MASK));
		
		// sub-auth
		for (String token:subAuthTokens) {
			long subauth = Long.valueOf(token);
			buffer.put((byte)(subauth & BYTE_MASK));
			buffer.put((byte)((subauth >> 8) & BYTE_MASK));
			buffer.put((byte)((subauth >> 16) & BYTE_MASK));
			buffer.put((byte)((subauth >> 24) & BYTE_MASK));
		}
		
		return buffer.array();
	}

}

Please give us your valuable comment

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください