⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sspi_workbench.cpp

📁 sspi_workbench
💻 CPP
📖 第 1 页 / 共 3 页
字号:

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 + -