SID と名前の変換 ~ SID ルックアップ・ツール
Windows の仕組みは "誰が" 何をしたいのか、ということが基本となるセキュリティシステムです。 その意味でユーザーを識別するということはとても大切です。
ここでは詳細は省きますが、 ユーザーアカウントには、ユーザー名やパスワード (いわゆるクレデンシャル) 情報やコメント、住所の他に、 ユーザーを識別するための ID である SID (Security SID) が含まれています。
SID の実体は可変長のバイナリデータですが、読解可能なテキスト表現も可能です。 S-R-I-S-S フォーマットというものです。この詳細は今回は省略しますが、 要はユーザー名と SID (のテキスト表現) の相互変換が可能なのです。
今回 SID ルックアップツール という簡単なツールを作りました。 これを使うと、SID とユーザー名の変換が出来ます。
このツールはこちらからダウンロード可能です。
このツールは、いろんなユーザー名を入力して SID にしてみて遊ぶ (?) だけではなく、様々なトラブルシューティングにも利用できます。
通常セキュリティで保護するオブジェクト、データ等を作成する場合は、「どのユーザー」 に 「どの権限を与える・拒否する」 という形で設定します。こういう場合ユーザーを登録すると、そのデータ内に SID を残します。その後、ユーザーアカウントを削除するなどすると、 プライベートなデータ内にのみ SID が残る場合があります。
このような SID が有効なデータなのかどうか確認する時に、このツールを使うと良いでしょう。ユーザーを再作成したのにうまく動かない、というようなトラブル解決・原因調査に役立ちます。
SID ルックアップツールの作成
次のコードを sidlookup.cpp として保存します。
#include "resource.h" #include <windows.h> #include <windowsx.h> #include <Sddl.h> #include <tchar.h> #include <stdio.h> #include <assert.h> void DisplayError(HWND hwnd, DWORD dwGle) { LPVOID lpMessageBuffer; DWORD dwRet; dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwGle, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL ); if (dwRet) { ::MessageBox ( hwnd, (LPTSTR) lpMessageBuffer, TEXT("Error"), MB_OK | MB_ICONERROR); LocalFree( lpMessageBuffer ); } } void GetSid ( HWND hwnd ) { TCHAR szName [512]; Edit_GetText(GetDlgItem(hwnd, IDC_NAMEORSID), szName, 512); if ( !_tcslen ( szName ) ) { return; } BOOL bRet; BYTE szSidBuff [256]; PSID pSid = (PSID) szSidBuff; DWORD cbSid = sizeof (szSidBuff); TCHAR szDomainName [256]; DWORD cbDomainName = sizeof (szDomainName); SID_NAME_USE snUse; LPTSTR lpszName; lpszName = szName; // // ユーザーの SID 取得 // // はじめに LookupAccountName API を呼び必要なバッファサイズを得る bRet = LookupAccountName ( NULL, szName, pSid, &cbSid, szDomainName, &cbDomainName, &snUse); if (!bRet ) { DisplayError (hwnd, GetLastError()); return; } // // SID のテキスト表現 // LPTSTR pStringSid; bRet = ConvertSidToStringSid (pSid, &pStringSid); if (!bRet) { DisplayError (hwnd, GetLastError()); return; } Edit_SetText ( GetDlgItem (hwnd, IDC_RESULT), pStringSid); LocalFree (pStringSid); } void GetName ( HWND hwnd ) { TCHAR szStringSID [256]; Edit_GetText(GetDlgItem(hwnd, IDC_NAMEORSID), szStringSID, 256); if ( !_tcslen ( szStringSID ) ) { return; } BOOL bRet; PSID pSid = NULL; DWORD cbSid = 0; bRet = ConvertStringSidToSid ( szStringSID, &pSid); if ( !bRet ) { DisplayError (hwnd, GetLastError()); return; } SID_NAME_USE snu; TCHAR szName [256]; DWORD cbName = sizeof ( szName ); TCHAR szDomainName [256]; DWORD cbDomainName = sizeof ( szDomainName ); bRet = LookupAccountSid ( NULL, pSid, szName, &cbName, szDomainName, &cbDomainName, &snu); if ( !bRet ) { DisplayError (hwnd, GetLastError()); return; } TCHAR szResult [512]; ::ZeroMemory ( szResult, sizeof (szResult)); wsprintf (szResult, TEXT("%s"), szDomainName); _tcscat ( szResult, TEXT("\\")); _tcscat ( szResult, szName); Edit_SetText ( GetDlgItem (hwnd, IDC_RESULT), szResult); LocalFree ( pSid ); pSid = NULL; } /////////////////////////////////////////////////////////////////////////////// // // ダイアログの初期化 // BOOL OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam) { return TRUE; } /////////////////////////////////////////////////////////////////////////////// // // WM_COMMAND メッセージの処理 // void OnCommand(HWND hWnd, int nID, HWND hWndCtl, UINT codeNotify) { switch(nID) { case IDC_GETNAME: GetName ( hWnd ); break; case IDC_GETSID: GetSid ( hWnd ); break; case IDCANCEL: EndDialog(hWnd, 0); break; } } /////////////////////////////////////////////////////////////////////////////// // // ウィンドウ (ダイアログ) プロシージャ // BOOL CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hWnd, WM_INITDIALOG, OnInitDialog); HANDLE_MSG(hWnd, WM_COMMAND, OnCommand); } return FALSE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ::DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, MainWndProc); return 0; }
次の内容を resource.h として保存します。
#ifndef IDC_STATIC #define IDC_STATIC (-1) #endif #define IDD_DIALOG1 100 #define IDC_NAMEORSID 1000 #define IDC_RESULT 1008 #define IDC_GETNAME 1009 #define IDC_GETSID 1010
次の内容を resource.rc として保存します。
// Generated by ResEdit 1.4.3 // Copyright (C) 2006-2008 // http://www.resedit.net #include "resource.h" #include <windows.h> // // Dialog resources // LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT IDD_DIALOG1 DIALOGEX 0, 0, 247, 72 STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_VISIBLE | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU CAPTION "SID Lookup Tool" FONT 8, "Ms Shell Dlg 2", 400, 0, 1 BEGIN EDITTEXT IDC_NAMEORSID, 5, 5, 222, 12, ES_AUTOHSCROLL EDITTEXT IDC_RESULT, 5, 22, 222, 12, ES_AUTOHSCROLL | ES_READONLY PUSHBUTTON "Name", IDC_GETNAME, 5, 52, 52, 15 PUSHBUTTON "SID", IDC_GETSID, 62, 52, 52, 15 END
makefile は以下の通りです。
TARGETNAME=sidlookup OUTDIR=.\chk ALL : "$(OUTDIR)\$(TARGETNAME).exe" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" # compile CPP_PROJ=\ /MT\ /W3\ /Fo"$(OUTDIR)\\"\ /Fd"$(OUTDIR)\\"\ /c\ /Zi\ /DWIN32\ /DUNICODE\ /D_UNICODE\ /D_WIN32_WINNT=0x0501 RSC_PROJ=/fo"$(OUTDIR)\$(TARGETNAME).res" #link LINK32=link.exe LINK32_FLAGS=\ user32.lib\ advapi32.lib\ /subsystem:windows\ /pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\ /machine:I386\ /out:"$(OUTDIR)\$(TARGETNAME).exe"\ /DEBUG\ /RELEASE LINK32_OBJS= \ "$(OUTDIR)\$(TARGETNAME).obj" "$(OUTDIR)\$(TARGETNAME).res" "$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS) $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS) .cpp{$(OUTDIR)}.obj: $(CPP) $(CPP_PROJ) $< "$(OUTDIR)\sidlookup.res": resource.rc rc.exe $(RSC_PROJ) resource.rc
以上を nmake すると、サブディレクトリ chk に sidlookup.exe が作られます。