📄 sspi_workbench.cpp
字号:
bool _encrypt() {
_ASSERT(mpPlain == s_msgProtection);
bool bOk = false;
const DWORD cbMessage = s_cbMsgBuf;
void* pSealedMessage;
DWORD cbSealedMessage;
if (s_pModel->encryptMessage(s_msgBuf, cbMessage, s_nMsgSequence, &pSealedMessage, &cbSealedMessage)) {
_ASSERT(cbSealedMessage <= sizeof s_msgBuf);
CopyMemory(s_msgBuf, pSealedMessage, cbSealedMessage);
free(pSealedMessage);
s_cbMsg = cbMessage;
s_cbMsgBuf = cbSealedMessage;
s_msgProtection = mpEncrypted;
bOk = true;
}
return bOk;
}
bool _decrypt() {
_ASSERT(mpEncrypted == s_msgProtection);
void* pvMessage;
const bool bOk = s_pModel->decryptMessage(s_msgBuf, s_cbMsgBuf, s_cbMsg, s_nMsgSequence, &pvMessage);
if (bOk) {
CopyMemory(s_msgBuf, pvMessage, s_cbMsgBuf = s_cbMsg);
free(pvMessage);
s_msgProtection = mpPlain;
}
return bOk;
}
bool _verifySig() {
_ASSERT(mpSigned == s_msgProtection);
void* pvMessage;
const bool bOk = s_pModel->verifySignature(s_msgBuf, s_cbMsgBuf, s_cbMsg, s_nMsgSequence, &pvMessage);
if (bOk) {
CopyMemory(s_msgBuf, pvMessage, s_cbMsgBuf = s_cbMsg);
free(pvMessage);
s_msgProtection = mpPlain;
}
return bOk;
}
void _clear() {
_clearMessage();
}
void _transition(int reason) {
switch (s_appState) {
case asChoosingSSP:
_ASSERT(IDB_SSP_OK == reason);
if (_chooseSSP())
s_appState = asChoosingCreds;
break;
case asChoosingCreds:
_ASSERT(IDB_ACQUIRE_CREDS == reason);
s_appState = _chooseCreds();
break;
case asChoosingCtxReq:
_ASSERT(IDB_INIT_SEC_CTX == reason);
_ASSERT(!s_bServer);
s_appState = _initSecurityCtx(true);
break;
case asDoneNeedTx:
_ASSERT(IDB_TX == reason);
if (_tx())
s_appState = asAuthComplete;
break;
case asNotDoneNeedTx:
_ASSERT(IDB_TX == reason);
if (_tx())
s_appState = asNeedToRx;
break;
case asNeedToRx:
_ASSERT(IDB_RX == reason);
if (_rx())
s_appState = asViewingRxToken;
break;
case asViewingRxToken:
_ASSERT(IDB_INIT_SEC_CTX == reason);
if (s_bServer)
s_appState = _acceptSecurityCtx();
else s_appState = _initSecurityCtx();
break;
case asAuthComplete:
case asSentMessage:
switch (reason) {
case IDB_COMPOSE:
s_appState = asComposingMsg;
break;
case IDB_RX:
if (_rx(true))
s_appState = asViewingRxMessage;
break;
}
break;
case asComposingMsg: {
_ASSERT(mpPlain == s_msgProtection);
_readComposedMessage();
bool bOk = false;
switch (reason) {
case IDB_SIGN:
bOk = _sign();
if (bOk)
s_appState = asViewingTxMessage;
break;
case IDB_ENCRYPT:
bOk = _encrypt();
if (bOk)
s_appState = asViewingTxMessage;
break;
case IDB_TX: // simply wants to send cleartext message
bOk = _tx(true);
if (bOk)
s_appState = asSentMessage;
break;
default:
_ASSERT(FALSE);
break;
}
if (!bOk)
_clearMessage();
break;
}
case asViewingTxMessage:
// either signed or encrypted the packet already
_ASSERT(mpSigned == s_msgProtection || mpEncrypted == s_msgProtection);
_ASSERT(IDB_TX == reason);
if (_tx(true))
s_appState = asSentMessage;
break;
case asViewingRxMessage:
switch (reason) {
case IDB_DECRYPT:
_ASSERT(mpEncrypted == s_msgProtection);
_decrypt();
break;
case IDB_VERIFY_SIG:
_ASSERT(mpSigned == s_msgProtection);
_verifySig();
break;
case IDB_CLEAR:
_clear();
s_appState = asAuthComplete;
break;
default:
_ASSERT(FALSE);
break;
}
break;
default:
_ASSERT(FALSE);
break;
}
_syncUIControlState();
_syncBufViewer();
}
void _initSSPList() {
HWND hwndList = GetDlgItem(s_hwnd, IDC_SSP_DROPDOWN);
ULONG cSSPs;
PSecPkgInfo pSSPs;
s_pModel->enumSSPs(&cSSPs, &pSSPs);
ComboBox_ResetContent(hwndList);
for (ULONG i = 0; i < cSSPs; ++i) {
if (pSSPs[i].fCapabilities & SECPKG_FLAG_CONNECTION && pSSPs[i].wRPCID != RPC_C_AUTHN_GSS_NEGOTIATE)
ComboBox_AddString(hwndList, pSSPs[i].Name);
}
s_pModel->freeEnumData(pSSPs);
}
void _reset() {
delete s_pModel;
s_pModel = new Model(s_bServer, _err);
_initSSPList();
s_appState = asChoosingSSP;
s_msgProtection = mpPlain;
s_msgProtectionUponRx = mpPlain;
s_nMsgSequence = 0;
s_grfCtxAttrs = 0;
_clearMessage();
_syncUIControlState();
_syncBufViewer();
}
bool _dumpStringToFile(const wchar_t* pszFile, const wchar_t* pszContents) {
HANDLE h = CreateFile(pszFile, FILE_WRITE_DATA, 0, 0, CREATE_ALWAYS, 0, 0);
if (INVALID_HANDLE_VALUE == h) {
_err(L"CreateFile", true);
return false;
}
const DWORD cb = lstrlen(pszContents) * sizeof *pszContents;
DWORD cbWritten;
if (!WriteFile(h, pszContents, cb, &cbWritten, 0))
_err(L"WriteFile");
if (cb != cbWritten)
_err(L"WriteFile");
CloseHandle(h);
return true;
}
void _browseTokenDump(BSTR bstr) {
wchar_t szTempPath[MAX_PATH];
GetTempPath(sizeof szTempPath / sizeof *szTempPath, szTempPath);
wchar_t szTemp[MAX_PATH];
if (!GetTempFileName(szTempPath, L"dmp", 0, szTemp))
_err(L"GetTempFileName");
wchar_t szDrive[_MAX_DRIVE];
wchar_t szDir [_MAX_DIR];
wchar_t szFname[_MAX_FNAME];
wchar_t szExt [_MAX_EXT];
_wsplitpath(szTemp, szDrive, szDir, szFname, szExt);
_wmakepath (szTemp, szDrive, szDir, szFname, L"html");
_dumpStringToFile(szTemp, bstr);
ShellExecute(0, L"open", szTemp, 0, 0, SW_MAXIMIZE);
}
void _impersonate() {
ITokDump* ptd;
HRESULT hr = CoCreateInstance(CLSID_TokDump, 0, CLSCTX_ALL, __uuidof(ptd), (void**)&ptd);
if (SUCCEEDED(hr)) {
BSTR bstr;
s_pModel->impersonate();
hr = ptd->TokenDump(0xFFFF, &bstr);
s_pModel->revert();
_browseTokenDump(bstr);
SysFreeString(bstr);
ptd->Release();
}
else _err(L"CoCreateInstance(CLSID_TokDump)", true, hr);
}
void _calcFonts() {
HWND hwndSample = GetDlgItem(s_hwnd, IDB_RESET);
s_hfontNormal = GetWindowFont(hwndSample);
LOGFONT lf;
if (!GetObject(s_hfontNormal, sizeof lf, &lf))
_err(L"GetObject");
lf.lfWeight = FW_BOLD;
s_hfontHighlighted = CreateFontIndirect(&lf);
if (!s_hfontHighlighted)
_err(L"CreateFontIndirect");
}
void _updateUIString(HWND hwnd, const wchar_t* pszClientOrServer) {
wchar_t szt[256];
if (!GetWindowText(hwnd, szt, sizeof szt / sizeof *szt))
_err(L"GetWindowText");
wchar_t sz[256];
wchar_t* psz = const_cast<wchar_t*>(pszClientOrServer);
if (!FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
szt, 0, 0, sz, sizeof sz / sizeof *sz,
reinterpret_cast<va_list*>(&psz)))
_err(L"FormatMessage");
SetWindowText(hwnd, sz);
}
void _updateUIStrings(const wchar_t* pszClientOrServer) {
int rgid[] = {
IDC_GROUP_SELECT_SSP,
IDC_GROUP_CHOOSE_CREDS,
};
const int* const end = rgid + sizeof rgid / sizeof *rgid;
for (const int* it = rgid; it != end; ++it)
_updateUIString(GetDlgItem(s_hwnd, *it), pszClientOrServer);
_updateUIString(s_hwnd, pszClientOrServer);
}
void _hideDlgItem(int id) {
ShowWindow(GetDlgItem(s_hwnd, id), SW_HIDE);
}
void _onInitDialog() {
_centerWindow(s_hwnd);
wchar_t sz[256];
const wchar_t* pszINISection = 0;
if (s_bServer) {
pszINISection = s_pszINISectionServer;
_updateUIStrings(L"Server");
SetDlgItemText(s_hwnd, IDB_INIT_SEC_CTX, L"Accept");
_hideDlgItem(IDC_HOST_ADDR);
_hideDlgItem(IDC_STATIC_HOST);
}
else {
pszINISection = s_pszINISectionClient;
_updateUIStrings(L"Client");
GetPrivateProfileString(pszINISection, L"host_addr", L"127.0.0.1", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_HOST_ADDR, sz);
GetPrivateProfileString(pszINISection, L"server_principal_name", L"bob@bar.com", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_SPN, sz);
_persistCheckboxState(s_pszINISectionClient, L"ctx_req_mutual", IDC_MUTUAL_AUTHN, false);
_persistCheckboxState(s_pszINISectionClient, L"ctx_req_delegate", IDC_DELEGATE, false);
_persistCheckboxState(s_pszINISectionClient, L"ctx_req_prompt", IDC_PROMPT_FOR_CREDS, false);
}
GetPrivateProfileString(pszINISection, L"host_port", L"4242", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_HOST_PORT, sz);
SetWindowFont(GetDlgItem(s_hwnd, IDC_VIEWER), GetStockFont(ANSI_FIXED_FONT), FALSE);
_calcFonts();
_reset(); // fills in SSP droplist, whose selection we initialize next
GetPrivateProfileString(pszINISection, L"ssp", L"Kerberos", sz, sizeof sz / sizeof *sz, _getINIPath());
if (0 == lstrcmpi(L"Negotiate", sz)) {
_manageAutoRadioButtonGroup(IDC_SPNEGO, IDC_SPNEGO);
GetPrivateProfileString(pszINISection, L"pkg_list", L"Kerberos,NTLM", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_PKGLIST, sz);
}
else {
_manageAutoRadioButtonGroup(IDC_SPNEGO, IDC_CHOOSE_SSP);
ComboBox_SelectString(GetDlgItem(s_hwnd, IDC_SSP_DROPDOWN), -1, sz);
}
int nCredSource = IDC_CRED_CUR_LOGON_SESSION;
switch (GetPrivateProfileInt(pszINISection, L"cred_source", 0, _getINIPath())) {
case 1: nCredSource = IDC_CRED_CUR_LOGON_SESSION; break;
case 2: nCredSource = IDC_CRED_EXPLICIT; break;
}
_manageAutoRadioButtonGroup(IDC_CRED_CUR_LOGON_SESSION, nCredSource);
GetPrivateProfileString(pszINISection, L"alt_authority", L"", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_AUTHORITY, sz);
GetPrivateProfileString(pszINISection, L"alt_principal", L"", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_PRINCIPAL, sz);
GetPrivateProfileString(pszINISection, L"alt_password", L"", sz, sizeof sz / sizeof *sz, _getINIPath());
SetDlgItemText(s_hwnd, IDC_PASSWORD, sz);
}
void _onCommand(int id, HWND, UINT codeNotify) {
switch (id) {
case IDB_SSP_OK:
case IDB_ACQUIRE_CREDS:
case IDB_INIT_SEC_CTX:
case IDB_TX:
case IDB_RX:
case IDB_COMPOSE:
case IDB_SIGN:
case IDB_ENCRYPT:
case IDB_DECRYPT:
case IDB_VERIFY_SIG:
case IDB_CLEAR:
_transition(id);
break;
case IDB_RESET:
_reset();
break;
case IDB_IMPERSONATE:
_impersonate();
break;
case IDCANCEL:
// somewhat kludgy way to unwind the call stack
PostMessage(s_hwnd, WM_USER, 0, 0);
EndDialog(s_hwnd, id);
break;
case IDC_PKGLIST:
if (EN_CHANGE == codeNotify) {
_manageAutoRadioButtonGroup(IDC_SPNEGO, IDC_SPNEGO);
}
break;
case IDC_SSP_DROPDOWN:
if (LBN_SELCHANGE == codeNotify) {
_manageAutoRadioButtonGroup(IDC_SPNEGO, IDC_CHOOSE_SSP);
}
break;
}
}
INT_PTR CALLBACK _chooseRoleDlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM) {
if (WM_COMMAND == msg) {
const int id = LOWORD(wp);
switch (id) {
case IDB_CLIENT:
case IDB_SERVER:
case IDCANCEL:
if (BN_CLICKED == HIWORD(wp))
EndDialog(hwnd, id);
}
return TRUE;
}
else if (WM_INITDIALOG == msg) {
_centerWindow(hwnd);
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK _mainDlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_INITDIALOG:
s_hwnd = hwnd;
_onInitDialog();
return FALSE;
case WM_COMMAND:
_onCommand(LOWORD(wp), reinterpret_cast<HWND>(lp), HIWORD(wp));
break;
default:
return FALSE;
}
return TRUE;
}
void _formINIFname() {
wchar_t szDrive[_MAX_DRIVE];
wchar_t szDir [_MAX_DIR];
wchar_t szFname[_MAX_FNAME];
wchar_t szExt [_MAX_EXT];
GetModuleFileName(0, s_szINIPath, sizeof s_szINIPath / sizeof *s_szINIPath);
_wsplitpath(s_szINIPath, szDrive, szDir, szFname, szExt);
_wmakepath (s_szINIPath, szDrive, szDir, L"sspi_workbench.ini", 0);
}
int WINAPI WinMain(HINSTANCE hModule, HINSTANCE, char*, int) {
_formINIFname();
CoInitialize(0); // COM needed for tokdump component
INITCOMMONCONTROLSEX iccex = { sizeof iccex, ICC_INTERNET_CLASSES };
if (!InitCommonControlsEx(&iccex))
return -1;
Transport::Init(_err);
const int nRoleChoice = DialogBox(hModule, MAKEINTRESOURCE(IDD_CHOOSE_ROLE), 0, _chooseRoleDlgProc);
switch (nRoleChoice) {
case IDB_SERVER:
s_bServer = true;
case IDB_CLIENT:
DialogBox(hModule, MAKEINTRESOURCE(IDD_MAINDLG), 0, _mainDlgProc);
break;
}
Transport::Shutdown();
CoUninitialize();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -