VBoxCredProvPoller::threadPoller(RTTHREAD hThreadSelf, void *pvUser) { VBoxCredProvVerbose(0, "VBoxCredProvPoller: Starting, pvUser=0x%p\n", pvUser); VBoxCredProvPoller *pThis = (VBoxCredProvPoller*)pvUser; AssertPtr(pThis); for (;;) { int rc; rc = VbglR3CredentialsQueryAvailability(); if (RT_FAILURE(rc)) { if (rc != VERR_NOT_FOUND) VBoxCredProvVerbose(0, "VBoxCredProvPoller: Could not retrieve credentials! rc=%Rc\n", rc); } else { VBoxCredProvVerbose(0, "VBoxCredProvPoller: Credentials available, notifying provider\n"); if (pThis->m_pProv) pThis->m_pProv->OnCredentialsProvided(); } /* Wait a bit. */ if (RTThreadUserWait(hThreadSelf, 500) == VINF_SUCCESS) { VBoxCredProvVerbose(0, "VBoxCredProvPoller: Terminating\n"); break; } } return VINF_SUCCESS; }
DECLCALLBACK(int) VBoxCredPoller::threadPoller(RTTHREAD ThreadSelf, void *pvUser) { Log(("VBoxCredPoller::threadPoller\n")); VBoxCredPoller *pThis = (VBoxCredPoller *)pvUser; do { int rc; rc = VbglR3CredentialsQueryAvailability(); if (RT_FAILURE(rc)) { if (rc != VERR_NOT_FOUND) Log(("VBoxCredPoller::threadPoller: Could not retrieve credentials! rc = %Rc\n", rc)); } else { Log(("VBoxCredPoller::threadPoller: Credentials available.\n")); Assert(pThis); rc = pThis->credentialsRetrieve(); } /* Wait a bit. */ if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS) { Log(("VBoxCredPoller::threadPoller: Terminating\n")); /* We were asked to terminate, do that instantly! */ return 0; } } while (1); return 0; }
/** * Poller thread. Checks periodically whether there are credentials. */ static DECLCALLBACK(int) credentialsPoller(RTTHREAD ThreadSelf, void *pvUser) { RT_NOREF(pvUser); VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller\n"); do { int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller: got credentials, simulating C-A-D\n"); /* tell WinLogon to start the attestation process */ pWlxFuncs->WlxSasNotify(hGinaWlx, WLX_SAS_TYPE_CTRL_ALT_DEL); /* time to say goodbye */ return 0; } if ( RT_FAILURE(rc) && rc != VERR_NOT_FOUND) { static int s_cBitchedQueryAvail = 0; if (s_cBitchedQueryAvail++ < 5) VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller: querying for credentials failed with rc=%Rrc\n", rc); } /* wait a bit */ if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS) { VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller: we were asked to terminate\n"); /* we were asked to terminate, do that instantly! */ return 0; } } while (1); return 0; }
/** * Checks and retrieves credentials provided by the host + does account lookup on eventually * renamed user accounts. * * @return IPRT status code. */ int VBoxCredProvCredential::RetrieveCredentials(void) { int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating); rc = VbglR3CredentialsRetrieveUtf16(&m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD], &m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc); } if (RT_SUCCESS(rc)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: User=%ls, Password=%ls, Domain=%ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], #ifdef DEBUG m_apwszCredentials[VBOXCREDPROV_FIELDID_PASSWORD], #else L"XXX" /* Don't show any passwords in release mode. */, #endif m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); /* * In case we got a "display name" (e.g. "John Doe") * instead of the real user name (e.g. "jdoe") we have * to translate the data first ... */ PWSTR pwszAcount; if (TranslateAccountName(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name %ls -> %ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], pwszAcount); if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount; } else { /* * Okay, no display name, but maybe it's a * principal name from which we have to extract the domain from? * ([email protected] -> jdoe in domain my-domain.sub.net.com.) */ PWSTR pwszDomain; if (ExtractAccoutData(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], &pwszAcount, &pwszDomain)) { /* Update user name. */ if (m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME] = pwszAcount; /* Update domain. */ if (m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) { RTMemWipeThoroughly(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME], RTUtf16Len(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]) + sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); } m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME] = pwszDomain; VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account data pwszAccount=%ls, pwszDomain=%ls\n", m_apwszCredentials[VBOXCREDPROV_FIELDID_USERNAME], m_apwszCredentials[VBOXCREDPROV_FIELDID_DOMAINNAME]); } } m_fHaveCreds = true; } else { /* If credentials already were retrieved by a former call, don't try to retrieve new ones * and just report back the already retrieved ones. */ if (m_fHaveCreds) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Credentials already retrieved\n"); rc = VINF_SUCCESS; } } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc); return rc; }
/** * Tries to retrieve credentials and enters them into the specified windows, * optionally followed by a button press to confirm/abort the dialog. * * @return IPRT status code. * @param hwndDlg Handle of dialog to enter credentials into. * @param hwndUserId Handle of username text field. Optional. * @param hwndPassword Handle of password text field. Optional. * @param hwndDomain Handle of domain text field. Optional. * @param wButtonToPress Button ID of dialog to press after successful * retrieval + storage. If set to 0 no button will * be pressed. */ int credentialsHandle(HWND hwndDlg, HWND hwndUserId, HWND hwndPassword, HWND hwndDomain, WORD wButtonToPress) { int rc = VINF_SUCCESS; if (!VBoxGINAHandleCurrentSession()) rc = VERR_NOT_FOUND; if (RT_SUCCESS(rc)) { rc = VbglR3CredentialsQueryAvailability(); if (RT_FAILURE(rc)) { if (rc != VERR_NOT_FOUND) VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: error querying for credentials, rc=%Rrc\n", rc); } } if (RT_SUCCESS(rc)) { VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: credentials available\n"); /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxGINAReportStatus(VBoxGuestFacilityStatus_Terminating); PRTUTF16 pwszUser, pwszPassword, pwszDomain; rc = VbglR3CredentialsRetrieveUtf16(&pwszUser, &pwszPassword, &pwszDomain); if (RT_SUCCESS(rc)) { #ifdef DEBUG VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: retrieved credentials: user=%ls, password=%ls, domain=%ls\n", pwszUser, pwszPassword, pwszDomain); #else VBoxGINAVerbose(0, "VBoxGINA::credentialsHandle: retrieved credentials: user=%ls, password=XXX, domain=%ls\n", pwszUser, pwszDomain); #endif /* Fill in credentials to appropriate UI elements. */ rc = credentialsToUI(hwndDlg, hwndUserId, hwndPassword, hwndDomain, pwszUser, pwszPassword, pwszDomain); if (RT_SUCCESS(rc)) { /* Confirm/cancel the dialog by pressing the appropriate button. */ if (wButtonToPress) { WPARAM wParam = MAKEWPARAM(wButtonToPress, BN_CLICKED); PostMessage(hwndDlg, WM_COMMAND, wParam, 0); } } VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* Passes */); } } VBoxGINAVerbose(3, "VBoxGINA::credentialsHandle: returned with rc=%Rrc\n", rc); return rc; }
/** * Checks and retrieves credentials provided by the host + does account lookup on eventually * renamed user accounts. * * @return IPRT status code. */ int VBoxCredProvCredential::RetrieveCredentials(void) { PRTUTF16 pwszUser = NULL; PRTUTF16 pwszPassword = NULL; PRTUTF16 pwszDomain = NULL; int rc = VbglR3CredentialsQueryAvailability(); if (RT_SUCCESS(rc)) { /* * Set status to "terminating" to let the host know this module now * tries to receive and use passed credentials so that credentials from * the host won't be sent twice. */ VBoxCredProvReportStatus(VBoxGuestFacilityStatus_Terminating); rc = VbglR3CredentialsRetrieveUtf16(&pwszUser, &pwszPassword, &pwszDomain); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Retrieved credentials with rc=%Rrc\n", rc); } if (RT_SUCCESS(rc)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Received credentials for user '%ls'\n", pwszUser); /* * In case we got a "display name" (e.g. "John Doe") * instead of the real user name (e.g. "jdoe") we have * to translate the data first ... */ PWSTR pwszExtractedName = NULL; if ( TranslateAccountName(pwszUser, &pwszExtractedName) && pwszExtractedName) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Translated account name '%ls' -> '%ls'\n", pwszUser, pwszExtractedName); RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszUser); pwszUser = RTUtf16Dup(pwszExtractedName); CoTaskMemFree(pwszExtractedName); pwszExtractedName = NULL; } else { /* * Okay, no display name, but maybe it's a * principal name from which we have to extract the domain from? * ([email protected] -> jdoe in domain my-domain.sub.net.com.) */ PWSTR pwszExtractedDomain = NULL; if (ExtractAccoutData(pwszUser, &pwszExtractedName, &pwszExtractedDomain)) { /* Update user name. */ if (pwszExtractedName) { if (pwszUser) { RTMemWipeThoroughly(pwszUser, (RTUtf16Len(pwszUser) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszUser); } pwszUser = RTUtf16Dup(pwszExtractedName); CoTaskMemFree(pwszExtractedName); pwszExtractedName = NULL; } /* Update domain. */ if (pwszExtractedDomain) { if (pwszDomain) { RTMemWipeThoroughly(pwszDomain, (RTUtf16Len(pwszDomain) + 1) * sizeof(RTUTF16), 3 /* Passes */); RTUtf16Free(pwszDomain); } pwszDomain = RTUtf16Dup(pwszExtractedDomain); CoTaskMemFree(pwszExtractedDomain); pwszExtractedDomain = NULL; } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Extracted account name '%ls' + domain '%ls'\n", pwszUser ? pwszUser : L"<NULL>", pwszDomain ? pwszDomain : L"<NULL>"); } } m_fHaveCreds = true; } if (m_fHaveCreds) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Setting fields\n"); setField(VBOXCREDPROV_FIELDID_USERNAME, pwszUser, true /* fNotifyUI */); setField(VBOXCREDPROV_FIELDID_PASSWORD, pwszPassword, true /* fNotifyUI */); setField(VBOXCREDPROV_FIELDID_DOMAINNAME, pwszDomain, true /* fNotifyUI */); } VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Wiping ...\n"); VbglR3CredentialsDestroyUtf16(pwszUser, pwszPassword, pwszDomain, 3 /* cPasses */); VBoxCredProvVerbose(0, "VBoxCredProvCredential::RetrieveCredentials: Returned rc=%Rrc\n", rc); return rc; }
/** * Checks for credentials provided by the host / HGCM. * * @return IPRT status code. VERR_NOT_FOUND if no credentials are available, * VINF_SUCCESS on successful retrieval or another IPRT error. * @param hPAM PAM handle. */ static int pam_vbox_check_creds(pam_handle_t *hPAM) { int rc = VbglR3CredentialsQueryAvailability(); if (RT_FAILURE(rc)) { if (rc != VERR_NOT_FOUND) pam_vbox_error(hPAM, "pam_vbox_check_creds: could not query for credentials! rc=%Rrc. Aborting\n", rc); #ifdef DEBUG else pam_vbox_log(hPAM, "pam_vbox_check_creds: no credentials available\n"); #endif } else { char *pszUsername; char *pszPassword; char *pszDomain; rc = VbglR3CredentialsRetrieve(&pszUsername, &pszPassword, &pszDomain); if (RT_FAILURE(rc)) { pam_vbox_error(hPAM, "pam_vbox_check_creds: could not retrieve credentials! rc=%Rrc. Aborting\n", rc); } else { #ifdef DEBUG pam_vbox_log(hPAM, "pam_vbox_check_creds: credentials retrieved: user=%s, password=%s, domain=%s\n", pszUsername, pszPassword, pszDomain); #else /* Don't log passwords in release mode! */ pam_vbox_log(hPAM, "pam_vbox_check_creds: credentials retrieved: user=%s, password=XXX, domain=%s\n", pszUsername, pszDomain); #endif /* Fill credentials into PAM. */ int pamrc = pam_set_item(hPAM, PAM_USER, pszUsername); if (pamrc != PAM_SUCCESS) { pam_vbox_error(hPAM, "pam_vbox_check_creds: could not set user name! pamrc=%d, msg=%s. Aborting\n", pamrc, pam_strerror(hPAM, pamrc)); } else { pamrc = pam_set_item(hPAM, PAM_AUTHTOK, pszPassword); if (pamrc != PAM_SUCCESS) pam_vbox_error(hPAM, "pam_vbox_check_creds: could not set password! pamrc=%d, msg=%s. Aborting\n", pamrc, pam_strerror(hPAM, pamrc)); } /** @todo Add handling domains as well. */ VbglR3CredentialsDestroy(pszUsername, pszPassword, pszDomain, 3 /* Three wipe passes */); pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with pamrc=%d, msg=%s\n", pamrc, pam_strerror(hPAM, pamrc)); } } #ifdef DEBUG pam_vbox_log(hPAM, "pam_vbox_check_creds: returned with rc=%Rrc\n", rc); #endif return rc; }