void BasicIOServiceRunner::start( void ) { // Make sure that the handlers have been set before we start. LW_ASSERT( m_handleConnectionError ); LW_ASSERT( m_handleConnection ); // Then start. m_ioServiceTack.reset( new boost::asio::io_service::work( m_ioService ) ); m_ioStartCondition.notify_all(); }
VOID AD_ConfigLockAcquireWrite( PLSA_AD_PROVIDER_STATE pState ) { int status = 0; status = pthread_rwlock_wrlock(pState->pConfigLock); LW_ASSERT(status == 0); }
void AD_ConfigLockRelease( PLSA_AD_PROVIDER_STATE pState ) { int status = 0; status = pthread_rwlock_unlock(pState->pConfigLock); LW_ASSERT(status == 0); }
BasicIOServiceRunner::~BasicIOServiceRunner( void ) { // Stop the IO service. if( !m_ioService.stopped() ) { stop(); } LW_ASSERT( m_ioService.stopped() ); // Then stop the thread. if( m_ioServiceRunner.joinable() ) { m_ioStartCondition.notify_all(); // In case start was never called. m_ioServiceRunner.join(); } }
void BasicConnection::_receiveComplete( const BufferMap::key_type bufferId, ReceiveCallback callback, const ErrorCode& error, const size_t size ){ // TODO: Better error handling. LW_ASSERT( !error ); std::string data; m_bufferMap[ bufferId ].swapData( data ); callback( data ); m_bufferMap.erase( bufferId ); }
void BasicConnection::_sendComplete( const BufferMap::key_type bufferId, SendCallback callback, const ErrorCode& error, const size_t size ){ // Ensure no error occurred and then remove the message. // TODO: Better error handling. LW_ASSERT( !error ); m_bufferMap.erase( bufferId ); if( callback != nullptr ){ callback(); } }
NTSTATUS SvcmStop( PLW_SVCM_INSTANCE pInstance ) { UMN_LOG_VERBOSE("Shutting down threads"); UmnSrvStopPollerThread(); UmnSrvFreeConfig(gpAPIConfig); LW_ASSERT(pthread_rwlock_destroy(&gUmnConfigLock) == 0); UMN_LOG_INFO("Usermonitor Service exiting..."); return 0; }
static VOID NtpCtxFreeResponse( IN LWMsgCall* pCall, IN LWMsgTag ResponseType, IN PVOID pResponse ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; LWMsgParams params = LWMSG_PARAMS_INITIALIZER; params.tag = ResponseType; params.data = pResponse; status = lwmsg_call_destroy_params(pCall, ¶ms); LW_ASSERT(status == LWMSG_STATUS_SUCCESS); }
json::Node PreparedQueryBase::_resultValueToJSONValue( const size_t index ){ // First check if the value is null. MYSQL_BIND& binder = m_results[ index ]; if( *binder.is_null ){ return json::Node( JSON_NULL ); } // After that we check what the result's type is. switch( (Type)binder.buffer_type ){ // case Type::Bool: // Same as Type::TinyInt case Type::TinyInt: return binder.is_unsigned ? json::Node( "", *((u8*)binder.buffer) ) : json::Node( "", *((s8*)binder.buffer) ) ; case Type::SmallInt: return binder.is_unsigned ? json::Node( "", *((u16*)binder.buffer) ) : json::Node( "", *((s16*)binder.buffer) ) ; case Type::MediumInt: case Type::Integer: return binder.is_unsigned ? json::Node( "", *((u32*)binder.buffer) ) : json::Node( "", *((s32*)binder.buffer) ) ; case Type::BigInt: return binder.is_unsigned ? json::Node( "", *((u64*)binder.buffer) ) : json::Node( "", *((s64*)binder.buffer) ) ; case Type::Float: return json::Node( "", *((f32*)binder.buffer) ); case Type::Double: return json::Node( "", *((f64*)binder.buffer) ); case Type::Char: case Type::VarChar: return _refetchStringValue( index ); default: LW_ASSERT( false ); // Unsupported type. } }
static VOID LsaPcachepReleaseEntry( IN PLSA_MACHINEPWD_CACHE_ENTRY pEntry ) { if (pEntry) { LONG count = LwInterlockedDecrement(&pEntry->RefCount); LW_ASSERT(count >= 0); if (0 == count) { LsaImplFreeMachinePasswordInfoContentsA(&pEntry->PasswordInfoA); LsaImplFreeMachinePasswordInfoContentsW(&pEntry->PasswordInfoW); LwFreeMemory(pEntry); } } }
DWORD LwLdapDirectoryExtendedDNSearch( IN HANDLE hDirectory, IN PCSTR pszObjectDN, IN PCSTR pszQuery, IN PSTR* ppszAttributeList, IN int scope, OUT LDAPMessage** ppMessage ) { DWORD dwError = LW_ERROR_SUCCESS; CHAR ExtDNCriticality = 'T'; LDAPControl *pExtDNControl = NULL; LDAPControl *ppInputControls[2] = { NULL, NULL }; LDAPMessage* pMessage = NULL; struct berval value = {0}; // Setup the extended DN control, in order to be windows 2000 compatible, // Do not specify control value, hence, the return result will always be in hexadecimal string format. value.bv_len = 0; value.bv_val = NULL; dwError = ldap_control_create(LDAP_CONTROL_X_EXTENDED_DN, ExtDNCriticality, &value, 0, &pExtDNControl); BAIL_ON_LDAP_ERROR(dwError); ppInputControls[0] = pExtDNControl; dwError = LwLdapDirectorySearchEx( hDirectory, pszObjectDN, scope, pszQuery, ppszAttributeList, ppInputControls, 0, &pMessage); BAIL_ON_LW_ERROR(dwError); LW_ASSERT(pMessage != NULL); *ppMessage = pMessage; cleanup: ppInputControls[0] = NULL; if (pExtDNControl) { ldap_control_free(pExtDNControl); } return (dwError); error: if (pMessage) { ldap_msgfree(pMessage); } *ppMessage = NULL; goto cleanup; }
DWORD LwLdapDirectoryOnePagedSearch( HANDLE hDirectory, PCSTR pszObjectDN, PCSTR pszQuery, PSTR* ppszAttributeList, DWORD dwPageSize, PLW_SEARCH_COOKIE pCookie, int scope, LDAPMessage** ppMessage ) { DWORD dwError = LW_ERROR_SUCCESS; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = NULL; ber_int_t pageCount = 0; CHAR pagingCriticality = 'T'; LDAPControl *pPageControl = NULL; LDAPControl *ppInputControls[2] = { NULL, NULL }; LDAPControl **ppReturnedControls = NULL; int errorcodep = 0; LDAPMessage* pMessage = NULL; BOOLEAN bSearchFinished = FALSE; struct berval * pBerCookie = (struct berval *)pCookie->pvData; LW_ASSERT(pCookie->pfnFree == NULL || pCookie->pfnFree == LwLdapFreeCookie); pDirectory = (PLW_LDAP_DIRECTORY_CONTEXT)hDirectory; // dwError = ADEnablePageControlOption(hDirectory); // BAIL_ON_LW_ERROR(dwError); dwError = ldap_create_page_control(pDirectory->ld, dwPageSize, pBerCookie, pagingCriticality, &pPageControl); BAIL_ON_LDAP_ERROR(dwError); ppInputControls[0] = pPageControl; dwError = LwLdapDirectorySearchEx( hDirectory, pszObjectDN, scope, pszQuery, ppszAttributeList, ppInputControls, 0, &pMessage); BAIL_ON_LW_ERROR(dwError); dwError = ldap_parse_result(pDirectory->ld, pMessage, &errorcodep, NULL, NULL, NULL, &ppReturnedControls, 0); BAIL_ON_LDAP_ERROR(dwError); if (pBerCookie != NULL) { ber_bvfree(pBerCookie); pBerCookie = NULL; } dwError = ldap_parse_page_control(pDirectory->ld, ppReturnedControls, &pageCount, &pBerCookie); BAIL_ON_LDAP_ERROR(dwError); if (pBerCookie == NULL || pBerCookie->bv_len < 1) { bSearchFinished = TRUE; } if (ppReturnedControls) { ldap_controls_free(ppReturnedControls); ppReturnedControls = NULL; } ppInputControls[0] = NULL; ldap_control_free(pPageControl); pPageControl = NULL; pCookie->bSearchFinished = bSearchFinished; *ppMessage = pMessage; pCookie->pvData = pBerCookie; pCookie->pfnFree = LwLdapFreeCookie; cleanup: /* dwError_disable = ADDisablePageControlOption(hDirectory); if (dwError_disable) LW_RTL_LOG_ERROR("Error: LDAP Disable PageControl Info: failed");*/ if (ppReturnedControls) { ldap_controls_free(ppReturnedControls); } ppInputControls[0] = NULL; if (pPageControl) { ldap_control_free(pPageControl); } return (dwError); error: *ppMessage = NULL; pCookie->pvData = NULL; pCookie->pfnFree = NULL; pCookie->bSearchFinished = TRUE; if (pBerCookie != NULL) { ber_bvfree(pBerCookie); pBerCookie = NULL; } goto cleanup; }
DWORD NtlmValidateResponse( IN HANDLE Handle, IN NTLM_CRED_HANDLE hCred, IN PNTLM_RESPONSE_MESSAGE_V1 pRespMsg, IN DWORD dwRespMsgSize, IN PNTLM_CONTEXT pChlngCtxt, OUT BYTE pSessionKey[NTLM_SESSION_KEY_SIZE] ) { DWORD dwError = LW_ERROR_SUCCESS; PNTLM_CREDENTIALS pCred = (PNTLM_CREDENTIALS)hCred; LSA_AUTH_USER_PARAMS Params; PLSA_AUTH_USER_INFO pUserInfo = NULL; PBYTE pLMRespBuffer = NULL; PBYTE pNTRespBuffer = NULL; LW_LSA_DATA_BLOB Challenge; LW_LSA_DATA_BLOB LMResp; LW_LSA_DATA_BLOB NTResp; PSTR pUserName = NULL; PSTR pDomainName = NULL; PSTR pWorkstation = NULL; PSTR pDomainInstance = NULL; BYTE sessionNonce[MD5_DIGEST_LENGTH]; BYTE sessionHashUntrunc[MD5_DIGEST_LENGTH]; BOOLEAN bInLock = FALSE; memset(&Params, 0, sizeof(Params)); memset(&Challenge, 0, sizeof(Challenge)); memset(&LMResp, 0, sizeof(LMResp)); memset(&NTResp, 0, sizeof(NTResp)); // sanity check if (!pRespMsg || ! pChlngCtxt) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } if (dwRespMsgSize < sizeof(*pRespMsg)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } dwError = LwAllocateMemory( LW_LTOH16(pRespMsg->LmResponse.usLength), OUT_PPVOID(&pLMRespBuffer)); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory( LW_LTOH16(pRespMsg->NtResponse.usLength), OUT_PPVOID(&pNTRespBuffer)); BAIL_ON_LSA_ERROR(dwError); // The username, domain, and workstation values might come back as Unicode. // We could technically prevent this by not allowing NTLM_FLAG_UNICODE to be // set during the negotiation phase, but that seems like an odd restriction // for now. dwError = NtlmGetUserNameFromResponse( pRespMsg, dwRespMsgSize, pChlngCtxt->NegotiatedFlags & NTLM_FLAG_UNICODE, &pUserName); BAIL_ON_LSA_ERROR(dwError); dwError = NtlmGetDomainNameFromResponse( pRespMsg, dwRespMsgSize, pChlngCtxt->NegotiatedFlags & NTLM_FLAG_UNICODE, &pDomainName); BAIL_ON_LSA_ERROR(dwError); if (pDomainName[0] == 0) { LW_SAFE_FREE_STRING(pDomainName); } dwError = NtlmGetWorkstationFromResponse( pRespMsg, dwRespMsgSize, pChlngCtxt->NegotiatedFlags & NTLM_FLAG_UNICODE, &pWorkstation); BAIL_ON_LSA_ERROR(dwError); if (LW_LTOH32(pRespMsg->LmResponse.dwOffset) + LW_LTOH16(pRespMsg->LmResponse.usLength) > dwRespMsgSize) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } memcpy( pLMRespBuffer, (PBYTE)pRespMsg + LW_LTOH32(pRespMsg->LmResponse.dwOffset), LW_LTOH16(pRespMsg->LmResponse.usLength)); if (LW_LTOH32(pRespMsg->NtResponse.dwOffset) + LW_LTOH16(pRespMsg->NtResponse.usLength) > dwRespMsgSize) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } memcpy( pNTRespBuffer, (PBYTE)pRespMsg + LW_LTOH32(pRespMsg->NtResponse.dwOffset), LW_LTOH16(pRespMsg->NtResponse.usLength)); if (LW_LTOH16(pRespMsg->NtResponse.usLength) == 24 && pChlngCtxt->NegotiatedFlags & NTLM_FLAG_NTLM2) { // The client sent an NTLM2 session response. That means we need to // calculate the challenge the client used. if (LW_LTOH16(pRespMsg->LmResponse.usLength) < 8) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } // Calculate the session nonce first memcpy(sessionNonce + 0, pChlngCtxt->Challenge, 8); memcpy(sessionNonce + 8, pLMRespBuffer, 8); MD5(sessionNonce, 16, sessionHashUntrunc); Challenge.dwLen = NTLM_CHALLENGE_SIZE; Challenge.pData = sessionHashUntrunc; } else { Challenge.dwLen = NTLM_CHALLENGE_SIZE; Challenge.pData = pChlngCtxt->Challenge; } LMResp.dwLen = LW_LTOH16(pRespMsg->LmResponse.usLength); LMResp.pData = pLMRespBuffer; NTResp.dwLen = LW_LTOH16(pRespMsg->NtResponse.usLength); NTResp.pData = pNTRespBuffer; Params.AuthType = LSA_AUTH_CHAP; Params.pass.chap.pChallenge = &Challenge; Params.pass.chap.pLM_resp = &LMResp; Params.pass.chap.pNT_resp = &NTResp; Params.pszAccountName = pUserName; Params.pszDomain = pDomainName; Params.pszWorkstation = pWorkstation; if (pCred) { NTLM_LOCK_MUTEX(bInLock, &pCred->Mutex); if (pCred->pszDomainName) { dwError = LwAllocateStringPrintf( &pDomainInstance, ":%s", pCred->pszDomainName); BAIL_ON_LSA_ERROR(dwError); } NTLM_UNLOCK_MUTEX(bInLock, &pCred->Mutex); } dwError = LsaSrvAuthenticateUserEx( Handle, pDomainInstance, &Params, &pUserInfo ); BAIL_ON_LSA_ERROR(dwError); LW_ASSERT(pUserInfo->pSessionKey->dwLen == NTLM_SESSION_KEY_SIZE); if (LW_LTOH16(pRespMsg->NtResponse.usLength) == 24 && pChlngCtxt->NegotiatedFlags & NTLM_FLAG_NTLM2) { HMAC( EVP_md5(), pUserInfo->pSessionKey->pData, NTLM_SESSION_KEY_SIZE, sessionNonce, 16, pSessionKey, NULL); } else { memcpy(pSessionKey, pUserInfo->pSessionKey->pData, NTLM_SESSION_KEY_SIZE); } pChlngCtxt->pUserInfo = pUserInfo; pUserInfo = NULL; cleanup: if (pCred) { NTLM_UNLOCK_MUTEX(bInLock, &pCred->Mutex); } if (pUserInfo) { LsaFreeAuthUserInfo(&pUserInfo); } LW_SAFE_FREE_MEMORY(pLMRespBuffer); LW_SAFE_FREE_MEMORY(pNTRespBuffer); LW_SAFE_FREE_STRING(pUserName); LW_SAFE_FREE_STRING(pDomainName); LW_SAFE_FREE_STRING(pWorkstation); LW_SAFE_FREE_STRING(pDomainInstance); return dwError; error: goto cleanup; }
static DWORD LsaPcachepEnsurePasswordInfoAndLock( IN LSA_MACHINEPWD_CACHE_HANDLE pPcache ) ///< /// Ensure that there is password information and lock the pcache. /// /// This function ensures that the password information is locked /// and acquires a lock on the pcache. Note that the lock will /// be at least a read lock but may be a write lock. However, /// callers cannot rely on it being any more than a read lock. /// /// Note that making this always return a read lock is not optimal /// as it must acquire a write lock in the case where the password /// information is not already loaded. To make it return a read /// lock in that case would require dropping the write lock and /// re-checking that the password information is still loaded. /// This could result in looping and unnecessarily complex code. /// /// @return Windows error code /// { DWORD dwError = 0; BOOLEAN bInLock = FALSE; if (!pPcache) { dwError = NERR_SetupNotJoined; BAIL_ON_LSA_ERROR(dwError); } PTHREAD_CALL_MUST_SUCCEED(pthread_rwlock_rdlock(pPcache->pStateLock)); bInLock = TRUE; if (!pPcache->bIsLoaded) { PTHREAD_CALL_MUST_SUCCEED(pthread_rwlock_unlock(pPcache->pStateLock)); bInLock = FALSE; PTHREAD_CALL_MUST_SUCCEED(pthread_rwlock_wrlock(pPcache->pStateLock)); bInLock = TRUE; if (!pPcache->bIsLoaded) { dwError = LsaPcachepLoadPasswordInfoInLock(pPcache); BAIL_ON_LSA_ERROR(dwError); } } error: if (dwError) { if (bInLock) { PTHREAD_CALL_MUST_SUCCEED(pthread_rwlock_unlock(pPcache->pStateLock)); bInLock = FALSE; } } LW_ASSERT(LW_IS_BOTH_OR_NEITHER(0 == dwError, bInLock)); return dwError; }
static DWORD LsaAdBatchBuilderCreateQuery( IN PAD_PROVIDER_DATA pProviderData, IN PCSTR pszQueryPrefix, IN PCSTR pszQuerySuffix, IN PCSTR pszAttributeName, IN PVOID pFirstItem, IN PVOID pEndItem, OUT PVOID* ppNextItem, IN OPTIONAL PVOID pCallbackContext, IN LSA_AD_BATCH_BUILDER_GET_ATTR_VALUE_CALLBACK pGetAttributeValueCallback, IN OPTIONAL LSA_AD_BATCH_BUILDER_FREE_VALUE_CONTEXT_CALLBACK pFreeValueContextCallback, IN LSA_AD_BATCH_BUILDER_NEXT_ITEM_CALLBACK pNextItemCallback, IN DWORD dwMaxQuerySize, IN DWORD dwMaxQueryCount, OUT PDWORD pdwQueryCount, OUT PSTR* ppszQuery ) { DWORD dwError = 0; PVOID pCurrentItem = NULL; PSTR pszQuery = NULL; PVOID pLastItem = pFirstItem; const char szOrPrefix[] = "(|"; const char szOrSuffix[] = ")"; const DWORD dwOrPrefixLength = sizeof(szOrPrefix)-1; const DWORD dwOrSuffixLength = sizeof(szOrSuffix)-1; DWORD dwAttributeNameLength = strlen(pszAttributeName); DWORD dwQuerySize = 0; DWORD dwQueryCount = 0; PVOID pFreeValueContext = NULL; DWORD dwQueryPrefixLength = 0; DWORD dwQuerySuffixLength = 0; DWORD dwQueryOffset = 0; DWORD dwSavedQueryCount = 0; if (pszQueryPrefix) { dwQueryPrefixLength = strlen(pszQueryPrefix); } if (pszQuerySuffix) { dwQuerySuffixLength = strlen(pszQuerySuffix); } // The overhead is: // prefix + orPrefix + <CONTENT> + orSuffix + suffix + NULL dwQuerySize = dwQueryPrefixLength + dwOrPrefixLength + dwOrSuffixLength + dwQuerySuffixLength + 1; pCurrentItem = pFirstItem; while (pCurrentItem != pEndItem) { PCSTR pszAttributeValue = NULL; if (pFreeValueContext) { pFreeValueContextCallback(pCallbackContext, &pFreeValueContext); } dwError = pGetAttributeValueCallback( pProviderData, pCallbackContext, pCurrentItem, &pszAttributeValue, &pFreeValueContext); BAIL_ON_LSA_ERROR(dwError); if (pszAttributeValue) { // "(" + attributeName + "=" + attributeValue + ")" DWORD dwAttributeValueLength = strlen(pszAttributeValue); DWORD dwItemLength = (1 + dwAttributeNameLength + 1 + dwAttributeValueLength + 1); DWORD dwNewQuerySize = dwQuerySize + dwItemLength; DWORD dwNewQueryCount = dwQueryCount + 1; if (dwNewQuerySize < dwQuerySize) { // overflow dwError = LW_ERROR_DATA_ERROR; BAIL_ON_LSA_ERROR(dwError); } if (dwMaxQuerySize && (dwNewQuerySize > dwMaxQuerySize)) { break; } if (dwMaxQueryCount && (dwNewQueryCount > dwMaxQueryCount)) { break; } dwQuerySize = dwNewQuerySize; dwQueryCount = dwNewQueryCount; } pCurrentItem = pNextItemCallback(pCallbackContext, pCurrentItem); } pLastItem = pCurrentItem; dwSavedQueryCount = dwQueryCount; if (dwQueryCount < 1) { goto cleanup; } dwError = LwAllocateMemory(dwQuerySize, (PVOID*)&pszQuery); BAIL_ON_LSA_ERROR(dwError); // Set up the query dwQueryOffset = 0; dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, pszQueryPrefix, dwQueryPrefixLength); BAIL_ON_LSA_ERROR(dwError); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, szOrPrefix, dwOrPrefixLength); BAIL_ON_LSA_ERROR(dwError); dwQueryCount = 0; pCurrentItem = pFirstItem; while (pCurrentItem != pLastItem) { PCSTR pszAttributeValue = NULL; if (pFreeValueContext) { pFreeValueContextCallback(pCallbackContext, &pFreeValueContext); } dwError = pGetAttributeValueCallback( pProviderData, pCallbackContext, pCurrentItem, &pszAttributeValue, &pFreeValueContext); BAIL_ON_LSA_ERROR(dwError); if (pszAttributeValue) { DWORD dwAttributeValueLength = strlen(pszAttributeValue); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, "(", 1); BAIL_ON_LSA_ERROR(dwError); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, pszAttributeName, dwAttributeNameLength); BAIL_ON_LSA_ERROR(dwError); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, "=", 1); BAIL_ON_LSA_ERROR(dwError); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, pszAttributeValue, dwAttributeValueLength); BAIL_ON_LSA_ERROR(dwError); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, ")", 1); BAIL_ON_LSA_ERROR(dwError); dwQueryCount++; } pCurrentItem = pNextItemCallback(pCallbackContext, pCurrentItem); } dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, szOrSuffix, dwOrSuffixLength); BAIL_ON_LSA_ERROR(dwError); dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize, pszQuerySuffix, dwQuerySuffixLength); BAIL_ON_LSA_ERROR(dwError); LW_ASSERT(dwQueryOffset + 1 == dwQuerySize); LW_ASSERT(dwSavedQueryCount == dwQueryCount); cleanup: // We handle error here instead of error label // because there is a goto cleanup above. if (dwError) { LW_SAFE_FREE_STRING(pszQuery); dwQueryCount = 0; pLastItem = pFirstItem; } if (pFreeValueContext) { pFreeValueContextCallback(pCallbackContext, &pFreeValueContext); } *ppszQuery = pszQuery; *pdwQueryCount = dwQueryCount; *ppNextItem = pLastItem; return dwError; error: // Do not actually handle any errors here. goto cleanup; }
DWORD LwLdapOpenDirectoryServer( IN PCSTR pszServerAddress, IN PCSTR pszServerName, IN DWORD dwFlags, OUT PHANDLE phDirectory ) { DWORD dwError = LW_ERROR_SUCCESS; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = NULL; DWORD dwAttempt = 0; struct timespec sleepTime; DWORD dwTimeoutSec = 15; LW_BAIL_ON_INVALID_STRING(pszServerName); LW_BAIL_ON_INVALID_STRING(pszServerAddress); for (dwAttempt = 1; dwAttempt <= 3; dwAttempt++) { // dwTimeoutSec controls how long openldap will wait for the connection // to be established. For the first attempt, this is set to 15 seconds // (which is the same amount of time netlogon will wait to get the dc // name). The second attempt halves the value to 7 seconds. The third // attempt halves it again to 3 seconds. dwError = LwLdapOpenDirectoryServerSingleAttempt( pszServerAddress, pszServerName, dwTimeoutSec, dwFlags, &pDirectory); if (dwError == ETIMEDOUT) { LW_ASSERT(pDirectory == NULL); LW_RTL_LOG_ERROR("The ldap connection to %s was disconnected. This was attempt #%d", pszServerAddress, dwAttempt); dwTimeoutSec /= 2; // This is the amount of time to sleep before trying to reconnect // again. It is: .1 seconds * dwAttempt sleepTime.tv_sec = 0; sleepTime.tv_nsec = dwAttempt * 100000000; while (nanosleep(&sleepTime, &sleepTime) == -1) { if (errno != EINTR) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LW_ERROR(dwError); } } continue; } BAIL_ON_LW_ERROR(dwError); break; } *phDirectory = (HANDLE)pDirectory; cleanup: return(dwError); error: if (pDirectory) { LwLdapCloseDirectory(pDirectory); } *phDirectory = (HANDLE)NULL; goto cleanup; }
static VOID Transceiver( PLW_TASK pTask, PVOID pContext, LW_TASK_EVENT_MASK WakeMask, LW_TASK_EVENT_MASK* pWaitMask, PLONG64 pllTime ) { PSOCKET pSocket = (PSOCKET) pContext; size_t sendSize = gpSettings->ulBufferSize / gpSettings->usSendSegments; ssize_t transferred = 0; NTSTATUS status; long opts = 0; int err = 0; if (WakeMask & LW_TASK_EVENT_CANCEL || pSocket->Iteration >= gpSettings->ulIterations) { *pWaitMask = 0; status = LwRtlSetTaskFd(pTask, pSocket->Fd, 0); ASSERT_SUCCESS(status); close(pSocket->Fd); pSocket->Fd = -1; return; } else if (WakeMask & LW_TASK_EVENT_INIT) { assert(pSocket->Iteration == 0); /* Put socket in nonblock mode */ opts = fcntl(pSocket->Fd, F_GETFL, 0); assert(opts >= 0); opts |= O_NONBLOCK; err = fcntl(pSocket->Fd, F_SETFL, opts); LW_ASSERT(err == 0); status = LwRtlSetTaskFd( pTask, pSocket->Fd, LW_TASK_EVENT_FD_READABLE | LW_TASK_EVENT_FD_WRITABLE); ASSERT_SUCCESS(status); } switch(pSocket->State) { case STATE_SEND: if (sendSize > gpSettings->ulBufferSize - pSocket->Position) sendSize = gpSettings->ulBufferSize - pSocket->Position; transferred = write( pSocket->Fd, pSocket->pBuffer + pSocket->Position, sendSize); assert(transferred >= 0 || errno == EAGAIN); if (transferred < 0 && errno == EAGAIN) { *pWaitMask = LW_TASK_EVENT_FD_WRITABLE; break; } pSocket->Position += transferred; pSocket->ullTotalTransferred += transferred; if (pSocket->Position >= gpSettings->ulBufferSize) { pSocket->State = STATE_RECV; pSocket->Position = 0; pSocket->Iteration++; } *pWaitMask = LW_TASK_EVENT_YIELD; break; case STATE_RECV: transferred = read( pSocket->Fd, pSocket->pBuffer + pSocket->Position, gpSettings->ulBufferSize - pSocket->Position); assert(transferred >= 0 || errno == EAGAIN); if (transferred < 0 && errno == EAGAIN) { *pWaitMask = LW_TASK_EVENT_FD_READABLE; break; } pSocket->Position += transferred; pSocket->ullTotalTransferred += transferred; if (pSocket->Position >= gpSettings->ulBufferSize) { pSocket->State = STATE_SEND; pSocket->Position = 0; pSocket->Iteration++; } *pWaitMask = LW_TASK_EVENT_YIELD; break; } }