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();
}
Example #2
0
VOID
AD_ConfigLockAcquireWrite(
    PLSA_AD_PROVIDER_STATE pState
)
{
    int status = 0;

    status = pthread_rwlock_wrlock(pState->pConfigLock);
    LW_ASSERT(status == 0);
}
Example #3
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();
    }
}
Example #5
0
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 );
}
Example #6
0
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();
    }
}
Example #7
0
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;
}
Example #8
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, &params);
    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.
    }
}
Example #10
0
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);
        }
    }
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #16
0
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;
}
Example #17
0
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;
    }
}