RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu) { char szFreqLevels[20]; /* Should be enough to get the highest level which is always the first. */ size_t cbFreqLevels = sizeof(szFreqLevels); if (!RTMpIsCpuOnline(idCpu)) return 0; memset(szFreqLevels, 0, sizeof(szFreqLevels)); /* * CPU 0 has the freq levels entry. ENOMEM is ok as we don't need all supported * levels but only the first one. */ int rc = sysctlbyname("dev.cpu.0.freq_levels", szFreqLevels, &cbFreqLevels, NULL, NULL); if ( (rc && (errno != ENOMEM)) || (cbFreqLevels == 0)) return 0; /* Clear everything starting from the '/' */ unsigned i = 0; do { if (szFreqLevels[i] == '/') { memset(&szFreqLevels[i], 0, sizeof(szFreqLevels) - i); break; } i++; } while (i < sizeof(szFreqLevels)); /* Returns 0 on failure. */ return RTStrToUInt32(szFreqLevels); }
DECLINLINE(int) vboxNetAdpGetUnitByName(const char *pcszName) { uint32_t iUnit = RTStrToUInt32(pcszName + sizeof(VBOXNETADP_NAME) - 1); bool fOld; if (iUnit >= VBOXNETADP_MAX_UNITS) return -1; fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit); return fOld ? -1 : (int)iUnit; }
/** * Returns a 32-bit unsigned integer of a specified key. * * @return IPRT status code. VERR_NOT_FOUND if key was not found. * @param pszKey Name of key to get the value for. * @param puVal Pointer to value to return. */ int GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const { AssertPtrReturn(pszKey, VERR_INVALID_POINTER); AssertPtrReturn(puVal, VERR_INVALID_POINTER); const char *pszValue = GetString(pszKey); if (pszValue) { *puVal = RTStrToUInt32(pszValue); return VINF_SUCCESS; } return VERR_NOT_FOUND; }
int localMappings(const ComNatPtr& nat, AddressToOffsetMapping& mapping) { mapping.clear(); ComBstrArray strs; size_t cStrs; HRESULT hrc = nat->COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs)); if ( SUCCEEDED(hrc) && (cStrs = strs.size())) { for (size_t i = 0; i < cStrs; ++i) { char szAddr[17]; RTNETADDRIPV4 ip4addr; char *pszTerm; uint32_t u32Off; com::Utf8Str strLo2Off(strs[i]); const char *pszLo2Off = strLo2Off.c_str(); RT_ZERO(szAddr); pszTerm = RTStrStr(pszLo2Off, "="); if ( pszTerm && (pszTerm - pszLo2Off) <= INET_ADDRSTRLEN) { memcpy(szAddr, pszLo2Off, (pszTerm - pszLo2Off)); int rc = RTNetStrToIPv4Addr(szAddr, &ip4addr); if (RT_SUCCESS(rc)) { u32Off = RTStrToUInt32(pszTerm + 1); if (u32Off != 0) mapping.insert( AddressToOffsetMapping::value_type(ip4addr, u32Off)); } } } } else return VERR_NOT_FOUND; return VINF_SUCCESS; }
uint32_t CollectorSolaris::getInstance(const char *pszIfaceName, char *pszDevName) { /* * Get the instance number from the interface name, then clip it off. */ int cbInstance = 0; int cbIface = strlen(pszIfaceName); const char *pszEnd = pszIfaceName + cbIface - 1; for (int i = 0; i < cbIface - 1; i++) { if (!RT_C_IS_DIGIT(*pszEnd)) break; cbInstance++; pszEnd--; } uint32_t uInstance = RTStrToUInt32(pszEnd + 1); strncpy(pszDevName, pszIfaceName, cbIface - cbInstance); pszDevName[cbIface - cbInstance] = '\0'; return uInstance; }
static uint32_t getInterfaceSpeed(const char *pszName) { /* * I wish I could do simple ioctl here, but older kernels require root * privileges for any ethtool commands. */ char szBuf[256]; uint32_t uSpeed = 0; /* First, we try to retrieve the speed via sysfs. */ RTStrPrintf(szBuf, sizeof(szBuf), "/sys/class/net/%s/speed", pszName); FILE *fp = fopen(szBuf, "r"); if (fp) { if (fscanf(fp, "%u", &uSpeed) != 1) uSpeed = 0; fclose(fp); } if (uSpeed == 10) { /* Check the cable is plugged in at all */ unsigned uCarrier = 0; RTStrPrintf(szBuf, sizeof(szBuf), "/sys/class/net/%s/carrier", pszName); fp = fopen(szBuf, "r"); if (fp) { if (fscanf(fp, "%u", &uCarrier) != 1 || uCarrier == 0) uSpeed = 0; fclose(fp); } } if (uSpeed == 0) { /* Failed to get speed via sysfs, go to plan B. */ int rc = NetIfAdpCtlOut(pszName, "speed", szBuf, sizeof(szBuf)); if (RT_SUCCESS(rc)) uSpeed = RTStrToUInt32(szBuf); } return uSpeed; }
RTR3DECL(bool) RTProcIsRunningByName(const char *pszName) { /* * Quick validation. */ if (!pszName) return false; bool const fWithPath = RTPathHavePath(pszName); /* * Enumerate /proc. */ RTDIR hDir; int rc = RTDirOpen(&hDir, "/proc"); AssertMsgRCReturn(rc, ("RTDirOpen on /proc failed: rc=%Rrc\n", rc), false); if (RT_SUCCESS(rc)) { RTDIRENTRY DirEntry; while (RT_SUCCESS(RTDirRead(hDir, &DirEntry, NULL))) { /* * Filter numeric directory entries only. */ if ( ( DirEntry.enmType == RTDIRENTRYTYPE_DIRECTORY || DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN) && RTStrToUInt32(DirEntry.szName) > 0) { /* * Try readlink on exe first since it's more faster and reliable. * Fall back on reading the first line in cmdline if that fails * (access errors typically). cmdline is unreliable as it might * contain whatever the execv caller passes as argv[0]. */ char szName[RTPATH_MAX]; RTStrPrintf(szName, sizeof(szName), "/proc/%s/exe", &DirEntry.szName[0]); char szExe[RTPATH_MAX]; int cchLink = readlink(szName, szExe, sizeof(szExe) - 1); if ( cchLink > 0 && (size_t)cchLink < sizeof(szExe)) { szExe[cchLink] = '\0'; rc = VINF_SUCCESS; } else { RTStrPrintf(szName, sizeof(szName), "/proc/%s/cmdline", &DirEntry.szName[0]); PRTSTREAM pStream; rc = RTStrmOpen(szName, "r", &pStream); if (RT_SUCCESS(rc)) { rc = RTStrmGetLine(pStream, szExe, sizeof(szExe)); RTStrmClose(pStream); } } if (RT_SUCCESS(rc)) { /* * We are interested on the file name part only. */ char const *pszProcName = fWithPath ? szExe : RTPathFilename(szExe); if (RTStrCmp(pszProcName, pszName) == 0) { /* Found it! */ RTDirClose(hDir); return true; } } } } RTDirClose(hDir); } return false; }
int main(int argc, char **argv) { int rcRet = 0; int i; int rc; int cIterations = argc > 1 ? RTStrToUInt32(argv[1]) : 32; if (cIterations == 0) cIterations = 64; /* * Init. */ RTR3InitExe(argc, &argv, 0); PSUPDRVSESSION pSession; rc = SUPR3Init(&pSession); rcRet += rc != 0; RTPrintf("tstInt: SUPR3Init -> rc=%Rrc\n", rc); char szFile[RTPATH_MAX]; if (!rc) { rc = RTPathExecDir(szFile, sizeof(szFile) - sizeof("/VMMR0.r0")); } char szAbsFile[RTPATH_MAX]; if (RT_SUCCESS(rc)) { strcat(szFile, "/VMMR0.r0"); rc = RTPathAbs(szFile, szAbsFile, sizeof(szAbsFile)); } if (RT_SUCCESS(rc)) { /* * Load VMM code. */ rc = SUPR3LoadVMM(szAbsFile); if (RT_SUCCESS(rc)) { /* * Create a fake 'VM'. */ PVMR0 pVMR0 = NIL_RTR0PTR; PVM pVM = NULL; const unsigned cPages = RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT; PSUPPAGE paPages = (PSUPPAGE)RTMemAllocZ(cPages * sizeof(SUPPAGE)); if (paPages) rc = SUPR3LowAlloc(cPages, (void **)&pVM, &pVMR0, &paPages[0]); else rc = VERR_NO_MEMORY; if (RT_SUCCESS(rc)) { pVM->pVMRC = 0; pVM->pVMR3 = pVM; pVM->pVMR0 = pVMR0; pVM->paVMPagesR3 = paPages; pVM->pSession = pSession; pVM->enmVMState = VMSTATE_CREATED; rc = SUPR3SetVMForFastIOCtl(pVMR0); if (!rc) { /* * Call VMM code with invalid function. */ for (i = cIterations; i > 0; i--) { rc = SUPR3CallVMMR0(pVMR0, NIL_VMCPUID, VMMR0_DO_SLOW_NOP, NULL); if (rc != VINF_SUCCESS) { RTPrintf("tstInt: SUPR3CallVMMR0 -> rc=%Rrc i=%d Expected VINF_SUCCESS!\n", rc, i); rcRet++; break; } } RTPrintf("tstInt: Performed SUPR3CallVMMR0 %d times (rc=%Rrc)\n", cIterations, rc); /* * The fast path. */ if (rc == VINF_SUCCESS) { RTTimeNanoTS(); uint64_t StartTS = RTTimeNanoTS(); uint64_t StartTick = ASMReadTSC(); uint64_t MinTicks = UINT64_MAX; for (i = 0; i < 1000000; i++) { uint64_t OneStartTick = ASMReadTSC(); rc = SUPR3CallVMMR0Fast(pVMR0, VMMR0_DO_NOP, 0); uint64_t Ticks = ASMReadTSC() - OneStartTick; if (Ticks < MinTicks) MinTicks = Ticks; if (RT_UNLIKELY(rc != VINF_SUCCESS)) { RTPrintf("tstInt: SUPR3CallVMMR0Fast -> rc=%Rrc i=%d Expected VINF_SUCCESS!\n", rc, i); rcRet++; break; } } uint64_t Ticks = ASMReadTSC() - StartTick; uint64_t NanoSecs = RTTimeNanoTS() - StartTS; RTPrintf("tstInt: SUPR3CallVMMR0Fast - %d iterations in %llu ns / %llu ticks. %llu ns / %#llu ticks per iteration. Min %llu ticks.\n", i, NanoSecs, Ticks, NanoSecs / i, Ticks / i, MinTicks); /* * The ordinary path. */ RTTimeNanoTS(); StartTS = RTTimeNanoTS(); StartTick = ASMReadTSC(); MinTicks = UINT64_MAX; for (i = 0; i < 1000000; i++) { uint64_t OneStartTick = ASMReadTSC(); rc = SUPR3CallVMMR0Ex(pVMR0, NIL_VMCPUID, VMMR0_DO_SLOW_NOP, 0, NULL); uint64_t OneTicks = ASMReadTSC() - OneStartTick; if (OneTicks < MinTicks) MinTicks = OneTicks; if (RT_UNLIKELY(rc != VINF_SUCCESS)) { RTPrintf("tstInt: SUPR3CallVMMR0Ex -> rc=%Rrc i=%d Expected VINF_SUCCESS!\n", rc, i); rcRet++; break; } } Ticks = ASMReadTSC() - StartTick; NanoSecs = RTTimeNanoTS() - StartTS; RTPrintf("tstInt: SUPR3CallVMMR0Ex - %d iterations in %llu ns / %llu ticks. %llu ns / %#llu ticks per iteration. Min %llu ticks.\n", i, NanoSecs, Ticks, NanoSecs / i, Ticks / i, MinTicks); } } else { RTPrintf("tstInt: SUPR3SetVMForFastIOCtl failed: %Rrc\n", rc); rcRet++; } } else { RTPrintf("tstInt: SUPR3ContAlloc(%#zx,,) failed\n", sizeof(*pVM)); rcRet++; } /* * Unload VMM. */ rc = SUPR3UnloadVMM(); if (rc) { RTPrintf("tstInt: SUPR3UnloadVMM failed with rc=%Rrc\n", rc); rcRet++; } } else { RTPrintf("tstInt: SUPR3LoadVMM failed with rc=%Rrc\n", rc); rcRet++; } /* * Terminate. */ rc = SUPR3Term(false /*fForced*/); rcRet += rc != 0; RTPrintf("tstInt: SUPR3Term -> rc=%Rrc\n", rc); }
/** @note To be called only from #AssignMachine() */ HRESULT Session::grabIPCSemaphore() { HRESULT rc = E_FAIL; /* open the IPC semaphore based on the sessionId and try to grab it */ Bstr ipcId; rc = mControl->GetIPCId(ipcId.asOutParam()); AssertComRCReturnRC(rc); LogFlowThisFunc(("ipcId='%ls'\n", ipcId.raw())); #if defined(RT_OS_WINDOWS) /* * Since Session is an MTA object, this method can be executed on * any thread, and this thread will not necessarily match the thread on * which close() will be called later. Therefore, we need a separate * thread to hold the IPC mutex and then release it in close(). */ mIPCThreadSem = ::CreateEvent(NULL, FALSE, FALSE, NULL); AssertMsgReturn(mIPCThreadSem, ("Cannot create an event sem, err=%d", ::GetLastError()), E_FAIL); void *data[3]; data[0] = (void*)(BSTR)ipcId.raw(); data[1] = (void*)mIPCThreadSem; data[2] = 0; /* will get an output from the thread */ /* create a thread to hold the IPC mutex until signalled to release it */ RTTHREAD tid; int vrc = RTThreadCreate(&tid, IPCMutexHolderThread, (void*)data, 0, RTTHREADTYPE_MAIN_WORKER, 0, "IPCHolder"); AssertRCReturn(vrc, E_FAIL); /* wait until thread init is completed */ DWORD wrc = ::WaitForSingleObject(mIPCThreadSem, INFINITE); AssertMsg(wrc == WAIT_OBJECT_0, ("Wait failed, err=%d\n", ::GetLastError())); Assert(data[2]); if (wrc == WAIT_OBJECT_0 && data[2]) { /* memorize the event sem we should signal in close() */ mIPCSem = (HANDLE)data[2]; rc = S_OK; } else { ::CloseHandle(mIPCThreadSem); mIPCThreadSem = NULL; rc = E_FAIL; } #elif defined(RT_OS_OS2) /* We use XPCOM where any message (including close()) can arrive on any * worker thread (which will not necessarily match this thread that opens * the mutex). Therefore, we need a separate thread to hold the IPC mutex * and then release it in close(). */ int vrc = RTSemEventCreate(&mIPCThreadSem); AssertRCReturn(vrc, E_FAIL); void *data[3]; data[0] = (void*)ipcId.raw(); data[1] = (void*)mIPCThreadSem; data[2] = (void*)false; /* will get the thread result here */ /* create a thread to hold the IPC mutex until signalled to release it */ vrc = RTThreadCreate(&mIPCThread, IPCMutexHolderThread, (void *) data, 0, RTTHREADTYPE_MAIN_WORKER, 0, "IPCHolder"); AssertRCReturn(vrc, E_FAIL); /* wait until thread init is completed */ vrc = RTThreadUserWait (mIPCThread, RT_INDEFINITE_WAIT); AssertReturn(RT_SUCCESS(vrc) || vrc == VERR_INTERRUPTED, E_FAIL); /* the thread must succeed */ AssertReturn((bool)data[2], E_FAIL); #elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) # ifdef VBOX_WITH_NEW_SYS_V_KEYGEN Utf8Str ipcKey = ipcId; key_t key = RTStrToUInt32(ipcKey.c_str()); AssertMsgReturn (key != 0, ("Key value of 0 is not valid for IPC semaphore"), E_FAIL); # else /* !VBOX_WITH_NEW_SYS_V_KEYGEN */ Utf8Str semName = ipcId; char *pszSemName = NULL; RTStrUtf8ToCurrentCP (&pszSemName, semName); key_t key = ::ftok (pszSemName, 'V'); RTStrFree (pszSemName); # endif /* !VBOX_WITH_NEW_SYS_V_KEYGEN */ mIPCSem = ::semget (key, 0, 0); AssertMsgReturn (mIPCSem >= 0, ("Cannot open IPC semaphore, errno=%d", errno), E_FAIL); /* grab the semaphore */ ::sembuf sop = { 0, -1, SEM_UNDO }; int rv = ::semop (mIPCSem, &sop, 1); AssertMsgReturn (rv == 0, ("Cannot grab IPC semaphore, errno=%d", errno), E_FAIL); #else # error "Port me!" #endif return rc; }
static int getInterfaceInfo(int iSocket, const char *pszName, PNETIFINFO pInfo) { // Zeroing out pInfo is a bad idea as it should contain both short and long names at // this point. So make sure the structure is cleared by the caller if necessary! // memset(pInfo, 0, sizeof(*pInfo)); struct ifreq Req; memset(&Req, 0, sizeof(Req)); strncpy(Req.ifr_name, pszName, sizeof(Req.ifr_name) - 1); if (ioctl(iSocket, SIOCGIFHWADDR, &Req) >= 0) { switch (Req.ifr_hwaddr.sa_family) { case ARPHRD_ETHER: pInfo->enmMediumType = NETIF_T_ETHERNET; break; default: pInfo->enmMediumType = NETIF_T_UNKNOWN; break; } /* Generate UUID from name and MAC address. */ RTUUID uuid; RTUuidClear(&uuid); memcpy(&uuid, Req.ifr_name, RT_MIN(sizeof(Req.ifr_name), sizeof(uuid))); uuid.Gen.u8ClockSeqHiAndReserved = (uuid.Gen.u8ClockSeqHiAndReserved & 0x3f) | 0x80; uuid.Gen.u16TimeHiAndVersion = (uuid.Gen.u16TimeHiAndVersion & 0x0fff) | 0x4000; memcpy(uuid.Gen.au8Node, &Req.ifr_hwaddr.sa_data, sizeof(uuid.Gen.au8Node)); pInfo->Uuid = uuid; memcpy(&pInfo->MACAddress, Req.ifr_hwaddr.sa_data, sizeof(pInfo->MACAddress)); if (ioctl(iSocket, SIOCGIFADDR, &Req) >= 0) memcpy(pInfo->IPAddress.au8, &((struct sockaddr_in *)&Req.ifr_addr)->sin_addr.s_addr, sizeof(pInfo->IPAddress.au8)); if (ioctl(iSocket, SIOCGIFNETMASK, &Req) >= 0) memcpy(pInfo->IPNetMask.au8, &((struct sockaddr_in *)&Req.ifr_addr)->sin_addr.s_addr, sizeof(pInfo->IPNetMask.au8)); if (ioctl(iSocket, SIOCGIFFLAGS, &Req) >= 0) pInfo->enmStatus = Req.ifr_flags & IFF_UP ? NETIF_S_UP : NETIF_S_DOWN; FILE *fp = fopen("/proc/net/if_inet6", "r"); if (fp) { RTNETADDRIPV6 IPv6Address; unsigned uIndex, uLength, uScope, uTmp; char szName[30]; for (;;) { memset(szName, 0, sizeof(szName)); int n = fscanf(fp, "%08x%08x%08x%08x" " %02x %02x %02x %02x %20s\n", &IPv6Address.au32[0], &IPv6Address.au32[1], &IPv6Address.au32[2], &IPv6Address.au32[3], &uIndex, &uLength, &uScope, &uTmp, szName); if (n == EOF) break; if (n != 9 || uLength > 128) { Log(("getInterfaceInfo: Error while reading /proc/net/if_inet6, n=%d uLength=%u\n", n, uLength)); break; } if (!strcmp(Req.ifr_name, szName)) { pInfo->IPv6Address.au32[0] = htonl(IPv6Address.au32[0]); pInfo->IPv6Address.au32[1] = htonl(IPv6Address.au32[1]); pInfo->IPv6Address.au32[2] = htonl(IPv6Address.au32[2]); pInfo->IPv6Address.au32[3] = htonl(IPv6Address.au32[3]); ASMBitSetRange(&pInfo->IPv6NetMask, 0, uLength); } } fclose(fp); } /* * Don't even try to get speed for non-Ethernet interfaces, it only * produces errors. */ pInfo->uSpeedMbits = 0; if (pInfo->enmMediumType == NETIF_T_ETHERNET) { /* * I wish I could do simple ioctl here, but older kernels require root * privileges for any ethtool commands. */ char szBuf[256]; /* First, we try to retrieve the speed via sysfs. */ RTStrPrintf(szBuf, sizeof(szBuf), "/sys/class/net/%s/speed", pszName); fp = fopen(szBuf, "r"); if (fp) { if (fscanf(fp, "%u", &pInfo->uSpeedMbits) != 1) pInfo->uSpeedMbits = 0; fclose(fp); } if (pInfo->uSpeedMbits == 10) { /* Check the cable is plugged in at all */ unsigned uCarrier = 0; RTStrPrintf(szBuf, sizeof(szBuf), "/sys/class/net/%s/carrier", pszName); fp = fopen(szBuf, "r"); if (fp) { if (fscanf(fp, "%u", &uCarrier) != 1 || uCarrier == 0) pInfo->uSpeedMbits = 0; fclose(fp); } } if (pInfo->uSpeedMbits == 0) { /* Failed to get speed via sysfs, go to plan B. */ int rc = NetIfAdpCtlOut(pszName, "speed", szBuf, sizeof(szBuf)); if (RT_SUCCESS(rc)) pInfo->uSpeedMbits = RTStrToUInt32(szBuf); } } } return VINF_SUCCESS; }
/* * Backend entry points. */ static DECLCALLBACK(int) iface_Open(PREMOTEUSBBACKEND pInstance, const char *pszAddress, size_t cbAddress, PREMOTEUSBDEVICE *ppDevice) { int rc = VINF_SUCCESS; RemoteUSBBackend *pThis = (RemoteUSBBackend *)pInstance; REMOTEUSBDEVICE *pDevice = (REMOTEUSBDEVICE *)RTMemAllocZ(sizeof(REMOTEUSBDEVICE)); if (!pDevice) { rc = VERR_NO_MEMORY; } else { /* Parse given address string to find the device identifier. * The format is "REMOTEUSB0xAAAABBBB&0xCCCCDDDD", where AAAABBBB is hex device identifier * and CCCCDDDD is hex client id. */ if (strncmp(pszAddress, REMOTE_USB_BACKEND_PREFIX_S, REMOTE_USB_BACKEND_PREFIX_LEN) != 0) { AssertFailed(); rc = VERR_INVALID_PARAMETER; } else { /* Initialize the device structure. */ pDevice->pOwner = pThis; pDevice->fWokenUp = false; rc = RTCritSectInit(&pDevice->critsect); AssertRC(rc); if (RT_SUCCESS(rc)) { pDevice->id = RTStrToUInt32(&pszAddress[REMOTE_USB_BACKEND_PREFIX_LEN]); size_t l = strlen(pszAddress); if (l >= REMOTE_USB_BACKEND_PREFIX_LEN + strlen("0x12345678&0x87654321")) { const char *p = &pszAddress[REMOTE_USB_BACKEND_PREFIX_LEN + strlen("0x12345678")]; if (*p == '&') { pDevice->u32ClientId = RTStrToUInt32(p + 1); } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } } else { AssertFailed(); rc = VERR_INVALID_PARAMETER; } if (RT_SUCCESS(rc)) { VRDE_USB_REQ_OPEN_PARM parm; parm.code = VRDE_USB_REQ_OPEN; parm.id = pDevice->id; pThis->VRDPServer()->SendUSBRequest(pDevice->u32ClientId, &parm, sizeof(parm)); } } } } if (RT_SUCCESS(rc)) { *ppDevice = pDevice; pThis->addDevice(pDevice); } else { RTMemFree(pDevice); } return rc; }
DECLEXPORT(int) pam_sm_authenticate(pam_handle_t *hPAM, int iFlags, int argc, const char **argv) { RT_NOREF1(iFlags); /* Parse arguments. */ for (int i = 0; i < argc; i++) { if (!RTStrICmp(argv[i], "debug")) g_verbosity = 1; else pam_vbox_error(hPAM, "pam_vbox_authenticate: unknown command line argument \"%s\"\n", argv[i]); } pam_vbox_log(hPAM, "pam_vbox_authenticate called\n"); int rc = pam_vbox_init(hPAM); if (RT_FAILURE(rc)) return PAM_SUCCESS; /* Jump out as early as we can to not mess around. */ bool fFallback = true; #ifdef VBOX_WITH_GUEST_PROPS uint32_t uClientId; rc = VbglR3GuestPropConnect(&uClientId); if (RT_SUCCESS(rc)) { char szVal[256]; rc = pam_vbox_read_prop(hPAM, uClientId, "/VirtualBox/GuestAdd/PAM/CredsWait", true /* Read-only on guest */, szVal, sizeof(szVal)); if (RT_SUCCESS(rc)) { /* All calls which are checked against rc2 are not critical, e.g. it does * not matter if they succeed or not. */ uint32_t uTimeoutMS = RT_INDEFINITE_WAIT; /* Wait infinite by default. */ int rc2 = pam_vbox_read_prop(hPAM, uClientId, "/VirtualBox/GuestAdd/PAM/CredsWaitTimeout", true /* Read-only on guest */, szVal, sizeof(szVal)); if (RT_SUCCESS(rc2)) { uTimeoutMS = RTStrToUInt32(szVal); if (!uTimeoutMS) { pam_vbox_error(hPAM, "pam_vbox_authenticate: invalid waiting timeout value specified, defaulting to infinite timeout\n"); uTimeoutMS = RT_INDEFINITE_WAIT; } else uTimeoutMS = uTimeoutMS * 1000; /* Make ms out of s. */ } rc2 = pam_vbox_read_prop(hPAM, uClientId, "/VirtualBox/GuestAdd/PAM/CredsMsgWaiting", true /* Read-only on guest */, szVal, sizeof(szVal)); const char *pszWaitMsg = NULL; if (RT_SUCCESS(rc2)) pszWaitMsg = szVal; rc2 = vbox_set_msg(hPAM, 0 /* Info message */, pszWaitMsg ? pszWaitMsg : "Waiting for credentials ..."); if (RT_FAILURE(rc2)) /* Not critical. */ pam_vbox_error(hPAM, "pam_vbox_authenticate: error setting waiting information message, rc=%Rrc\n", rc2); if (RT_SUCCESS(rc)) { /* Before we actuall wait for credentials just make sure we didn't already get credentials * set so that we can skip waiting for them ... */ rc = pam_vbox_check_creds(hPAM); if (rc == VERR_NOT_FOUND) { rc = pam_vbox_wait_for_creds(hPAM, uClientId, uTimeoutMS); if (rc == VERR_TIMEOUT) { pam_vbox_log(hPAM, "pam_vbox_authenticate: no credentials given within time\n"); rc2 = pam_vbox_read_prop(hPAM, uClientId, "/VirtualBox/GuestAdd/PAM/CredsMsgWaitTimeout", true /* Read-only on guest */, szVal, sizeof(szVal)); if (RT_SUCCESS(rc2)) { rc2 = vbox_set_msg(hPAM, 0 /* Info message */, szVal); AssertRC(rc2); } } else if (rc == VERR_CANCELLED) { pam_vbox_log(hPAM, "pam_vbox_authenticate: waiting aborted\n"); rc2 = pam_vbox_read_prop(hPAM, uClientId, "/VirtualBox/GuestAdd/PAM/CredsMsgWaitAbort", true /* Read-only on guest */, szVal, sizeof(szVal)); if (RT_SUCCESS(rc2)) { rc2 = vbox_set_msg(hPAM, 0 /* Info message */, szVal); AssertRC(rc2); } } } /* If we got here we don't need the fallback, so just deactivate it. */ fFallback = false; } } VbglR3GuestPropDisconnect(uClientId); } #endif /* VBOX_WITH_GUEST_PROPS */ if (fFallback) { pam_vbox_log(hPAM, "pam_vbox_authenticate: falling back to old method\n"); /* If anything went wrong in the code above we just do a credentials * check like it was before: Try retrieving the stuff and authenticating. */ int rc2 = pam_vbox_check_creds(hPAM); if (RT_SUCCESS(rc)) rc = rc2; } pam_vbox_shutdown(hPAM); pam_vbox_log(hPAM, "pam_vbox_authenticate: overall result rc=%Rrc\n", rc); /* Never report an error here because if no credentials from the host are available or something * went wrong we then let do the authentication by the next module in the stack. */ /* We report success here because this is all we can do right now -- we passed the credentials * to the next PAM module in the block above which then might do a shadow (like pam_unix/pam_unix2) * password verification to "really" authenticate the user. */ return PAM_SUCCESS; }