/* Editor Settings: expandtabs and use 4 spaces for indentation
* ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
*/
/*
* Copyright Likewise Software 2004-2008
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. You should have received a copy of the GNU General
* Public License along with this program. If not, see
* .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Copyright (C) Likewise Software. All rights reserved.
*
* Module Name:
*
* provider-main.c
*
* Abstract:
*
* Likewise Security and Authentication Subsystem (LSASS)
*
* Active Directory Authentication Provider
*
* Authors: Krishna Ganugapati (krishnag@likewisesoftware.com)
* Sriram Nambakam (snambakam@likewisesoftware.com)
* Wei Fu (wfu@likewisesoftware.com)
* Brian Dunstan (bdunstan@likewisesoftware.com)
* Kyle Stemen (kstemen@likewisesoftware.com)
*/
#include "adprovider.h"
static
DWORD
AD_GetNameWithReplacedSeparators(
IN PCSTR pszName,
OUT PSTR* ppszFreeName,
OUT PCSTR* ppszUseName
);
static
DWORD
AD_RemoveUserByNameFromCacheInternal(
IN HANDLE hProvider,
IN PCSTR pszLoginId
);
static
DWORD
LsaAdProviderStateCreate(
OUT PLSA_AD_PROVIDER_STATE* ppState
);
static
VOID
LsaAdProviderStateDestroy(
IN OUT PLSA_AD_PROVIDER_STATE pState
);
static
DWORD
AD_MachineCredentialsCacheClear(
VOID
);
static
BOOLEAN
AD_MachineCredentialsCacheIsInitialized(
VOID
);
static
VOID
LsaAdProviderMediaSenseTransitionCallback(
IN PVOID Context,
IN BOOLEAN bIsOffline
);
static
DWORD
AD_ResolveConfiguredLists(
HANDLE hProvider,
PLSA_HASH_TABLE *ppAllowedMemberList
);
static
VOID
LsaAdProviderLogServiceStartEvent(
PCSTR pszHostname,
PCSTR pszDomainDnsName,
BOOLEAN bIsDomainOffline,
DWORD dwErrCode
);
static
VOID
LsaAdProviderLogConfigReloadEvent(
VOID
);
static
VOID
LsaAdProviderLogRequireMembershipOfChangeEvent(
HANDLE hProvider
);
static
VOID
LsaAdProviderLogEventLogEnableChangeEvent(
VOID
);
static
DWORD
AD_JoinDomain(
HANDLE hProvider,
uid_t peerUID,
gid_t peerGID,
DWORD dwInputBufferSize,
PVOID pInputBuffer,
DWORD* pdwOutputBufferSize,
PVOID* ppOutputBuffer
);
static
DWORD
AD_TransitionJoined(
PLSA_AD_PROVIDER_STATE pState
);
static
DWORD
AD_Deactivate(
PLSA_AD_PROVIDER_STATE pState
);
static
DWORD
AD_TransitionNotJoined(
PLSA_AD_PROVIDER_STATE pState
);
void
InitADCacheFunctionTable(
PADCACHE_PROVIDER_FUNCTION_TABLE pCacheProviderTable
);
static
VOID
LsaAdProviderStateAcquireRead(
PLSA_AD_PROVIDER_STATE pState
);
static
VOID
LsaAdProviderStateAcquireWrite(
PLSA_AD_PROVIDER_STATE pState
);
static
void
LsaAdProviderStateRelease(
PLSA_AD_PROVIDER_STATE pState
);
static
void*
LsaAdStartupThread(
void* pData
);
static
DWORD
AD_Activate(
PLSA_AD_PROVIDER_STATE pState
);
static
DWORD
AD_InitializeProvider(
OUT PCSTR* ppszProviderName,
OUT PLSA_PROVIDER_FUNCTION_TABLE_2* ppFunctionTable
)
{
DWORD dwError = 0;
LSA_AD_CONFIG config = {0};
pthread_t startThread;
pthread_rwlock_init(&gADGlobalDataLock, NULL);
dwError = LsaAdProviderStateCreate(&gpLsaAdProviderState);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_NetInitMemory();
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_InitializeConfig(&config);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_ReadRegistry(&config);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_TransferConfigContents(
&config,
&gpLsaAdProviderState->config);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaSetDomainSeparator(
gpLsaAdProviderState->config.chDomainSeparator);
BAIL_ON_LSA_ERROR(dwError);
LsaAdProviderLogConfigReloadEvent();
InitADCacheFunctionTable(gpCacheProvider);
dwError = LwKrb5SetProcessDefaultCachePath(LSASS_CACHE_PATH);
BAIL_ON_LSA_ERROR(dwError);
dwError = ADState_OpenDb(
&gpLsaAdProviderState->hStateConnection);
BAIL_ON_LSA_ERROR(dwError);
switch (gpLsaAdProviderState->config.CacheBackend)
{
default:
#ifdef AD_CACHE_ENABLE_SQLITE
case AD_CACHE_SQLITE:
dwError = ADCacheOpen(
LSASS_AD_SQLITE_CACHE_DB,
&gpLsaAdProviderState->hCacheConnection);
BAIL_ON_LSA_ERROR(dwError);
break;
#endif
case AD_CACHE_IN_MEMORY:
dwError = ADCacheOpen(
LSASS_AD_MEMORY_CACHE_DB,
&gpLsaAdProviderState->hCacheConnection);
BAIL_ON_LSA_ERROR(dwError);
dwError = MemCacheSetSizeCap(
gpLsaAdProviderState->hCacheConnection,
AD_GetCacheSizeCap());
BAIL_ON_LSA_ERROR(dwError);
break;
}
dwError = ADUnprovPlugin_Initialize();
BAIL_ON_LSA_ERROR(dwError);
dwError = LwMapErrnoToLwError(pthread_create(
&startThread,
NULL,
LsaAdStartupThread,
gpLsaAdProviderState));
BAIL_ON_LSA_ERROR(dwError);
dwError = LwMapErrnoToLwError(pthread_detach(startThread));
BAIL_ON_LSA_ERROR(dwError);
*ppszProviderName = gpszADProviderName;
*ppFunctionTable = &gADProviderAPITable2;
cleanup:
AD_FreeConfigContents(&config);
return dwError;
error:
LsaAdProviderStateDestroy(gpLsaAdProviderState);
gpLsaAdProviderState = NULL;
if (gpADProviderData)
{
ADProviderFreeProviderData(gpADProviderData);
gpADProviderData = NULL;
}
*ppszProviderName = NULL;
*ppFunctionTable = NULL;
goto cleanup;
}
static
void*
LsaAdStartupThread(
void* pData
)
{
DWORD dwError = 0;
PLSA_AD_PROVIDER_STATE pState = (PLSA_AD_PROVIDER_STATE) pData;
LsaAdProviderStateAcquireWrite(pState);
dwError = LwKrb5GetMachineCreds(NULL, NULL, NULL, NULL);
if (dwError == 0)
{
dwError = AD_Activate(pState);
if (dwError == 0)
{
pState->joinState = LSA_AD_JOINED;
}
}
else
{
pState->joinState = LSA_AD_NOT_JOINED;
}
LsaAdProviderStateRelease(pState);
return NULL;
}
DWORD
AD_ShutdownProvider(
VOID
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireWrite(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState == LSA_AD_JOINED)
{
AD_Deactivate(gpLsaAdProviderState);
}
LsaAdProviderStateRelease(gpLsaAdProviderState);
ADUnprovPlugin_Cleanup();
dwError = AD_NetShutdownMemory();
if (dwError)
{
LSA_LOG_DEBUG("AD Provider Shutdown: Failed to shutdown net memory (error = %d)", dwError);
dwError = 0;
}
AD_FreeAllowedSIDs_InLock();
// This will clean up media sense too.
LsaAdProviderStateDestroy(gpLsaAdProviderState);
gpLsaAdProviderState = NULL;
return dwError;
}
static
DWORD
AD_Activate(
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
PSTR pszHostname = NULL;
PSTR pszUsername = NULL;
PSTR pszPassword = NULL;
PSTR pszDomainDnsName = NULL;
PSTR pszHostDnsDomain = NULL;
BOOLEAN bIsDomainOffline = FALSE;
dwError = LsaDnsGetHostInfo(&pszHostname);
BAIL_ON_LSA_ERROR(dwError);
LwStrToUpper(pszHostname);
dwError = LwKrb5GetMachineCreds(
&pszUsername,
&pszPassword,
&pszDomainDnsName,
&pszHostDnsDomain);
BAIL_ON_LSA_ERROR(dwError);
// Initialize domain manager before doing any network stuff.
dwError = LsaDmInitialize(
TRUE,
AD_GetDomainManagerCheckDomainOnlineSeconds(),
AD_GetDomainManagerUnknownDomainCacheTimeoutSeconds());
BAIL_ON_LSA_ERROR(dwError);
// Start media sense after starting up domain manager.
dwError = MediaSenseStart(&gpLsaAdProviderState->MediaSenseHandle,
LsaAdProviderMediaSenseTransitionCallback,
NULL);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaDmWrapLdapPingTcp(pszDomainDnsName);
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
bIsDomainOffline = TRUE;
dwError = 0;
}
BAIL_ON_LSA_ERROR(dwError);
if (!bIsDomainOffline)
{
dwError = AD_MachineCredentialsCacheInitialize();
if (dwError == LW_ERROR_CLOCK_SKEW)
{
bIsDomainOffline = TRUE;
dwError = LW_ERROR_SUCCESS;
}
BAIL_ON_LSA_ERROR(dwError);
}
if (bIsDomainOffline)
{
dwError = AD_MachineCredentialsCacheClear();
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_InitializeOperatingMode(
pszDomainDnsName,
pszUsername,
bIsDomainOffline);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaUmInitialize();
BAIL_ON_LSA_ERROR(dwError);
dwError = ADInitMachinePasswordSync();
BAIL_ON_LSA_ERROR(dwError);
dwError = ADStartMachinePasswordSync();
BAIL_ON_LSA_ERROR(dwError);
if (AD_EventlogEnabled())
{
LsaAdProviderLogServiceStartEvent(
pszHostname,
pszDomainDnsName,
bIsDomainOffline,
dwError);
}
cleanup:
LW_SAFE_FREE_STRING(pszHostname);
LW_SAFE_FREE_STRING(pszUsername);
LW_SAFE_CLEAR_FREE_STRING(pszPassword);
LW_SAFE_FREE_STRING(pszDomainDnsName);
LW_SAFE_FREE_STRING(pszHostDnsDomain);
return dwError;
error:
if (AD_EventlogEnabled())
{
LsaAdProviderLogServiceStartEvent(
pszHostname,
pszDomainDnsName,
bIsDomainOffline,
dwError);
}
ADShutdownMachinePasswordSync();
LsaDmCleanup();
goto cleanup;
}
static
DWORD
AD_TransitionJoined(
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
dwError = AD_Activate(pState);
BAIL_ON_LSA_ERROR(dwError);
pState->joinState = LSA_AD_JOINED;
error:
return dwError;
}
static
DWORD
AD_Deactivate(
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
BOOLEAN bInLock = FALSE;
ADShutdownMachinePasswordSync();
AD_MachineCredentialsCacheClear();
ENTER_AD_GLOBAL_DATA_RW_WRITER_LOCK(bInLock);
if (gpADProviderData)
{
ADProviderFreeProviderData(gpADProviderData);
gpADProviderData = NULL;
}
LEAVE_AD_GLOBAL_DATA_RW_WRITER_LOCK(bInLock);
if (pState->MediaSenseHandle)
{
MediaSenseStop(&pState->MediaSenseHandle);
pState->MediaSenseHandle = NULL;
}
LsaUmCleanup();
LsaDmCleanup();
return dwError;
}
static
DWORD
AD_TransitionNotJoined(
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
dwError = ADCacheEmptyCache(pState->hCacheConnection);
BAIL_ON_LSA_ERROR(dwError);
dwError = ADState_EmptyDb(pState->hStateConnection);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_Deactivate(pState);
BAIL_ON_LSA_ERROR(dwError);
pState->joinState = LSA_AD_NOT_JOINED;
error:
return dwError;
}
DWORD
AD_OpenHandle(
HANDLE hServer,
PHANDLE phProvider
)
{
DWORD dwError = 0;
PAD_PROVIDER_CONTEXT pContext = NULL;
dwError = LwAllocateMemory(
sizeof(AD_PROVIDER_CONTEXT),
(PVOID*)&pContext);
BAIL_ON_LSA_ERROR(dwError);
LsaSrvGetClientId(
hServer,
&pContext->uid,
&pContext->gid,
&pContext->pid);
*phProvider = (HANDLE)pContext;
cleanup:
return dwError;
error:
*phProvider = (HANDLE)NULL;
if (pContext)
{
AD_CloseHandle((HANDLE)pContext);
}
goto cleanup;
}
void
AD_CloseHandle(
HANDLE hProvider
)
{
PAD_PROVIDER_CONTEXT pContext = (PAD_PROVIDER_CONTEXT)hProvider;
if (pContext)
{
LwFreeMemory(pContext);
}
}
BOOLEAN
AD_ServicesDomain(
PCSTR pszDomain
)
{
BOOLEAN bResult = FALSE;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
goto cleanup;
}
//
// Added Trusted domains support
//
if (LW_IS_NULL_OR_EMPTY_STR(pszDomain) ||
LW_IS_NULL_OR_EMPTY_STR(gpADProviderData->szDomain) ||
LW_IS_NULL_OR_EMPTY_STR(gpADProviderData->szShortDomain)) {
goto cleanup;
}
bResult = LsaDmIsDomainPresent(pszDomain);
if (!bResult)
{
LSA_LOG_INFO("AD_ServicesDomain was passed unknown domain '%s'", pszDomain);
}
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return bResult;
}
DWORD
AD_AuthenticateUser(
HANDLE hProvider,
PCSTR pszLoginId,
PCSTR pszPassword
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_OnlineAuthenticateUser(
hProvider,
pszLoginId,
pszPassword);
}
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
dwError = AD_OfflineAuthenticateUser(
hProvider,
pszLoginId,
pszPassword);
}
error:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
}
DWORD
AD_AuthenticateUserEx(
HANDLE hProvider,
PLSA_AUTH_USER_PARAMS pUserParams,
PLSA_AUTH_USER_INFO *ppUserInfo
)
{
DWORD dwError = LW_ERROR_INTERNAL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (pUserParams->pszDomain)
{
BOOLEAN bFoundDomain = FALSE;
dwError = AD_ServicesDomainWithDiscovery(
pUserParams->pszDomain,
&bFoundDomain);
BAIL_ON_LSA_ERROR(dwError);
if (!bFoundDomain)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
}
dwError = LsaDmWrapAuthenticateUserEx(
gpADProviderData->szDomain,
pUserParams,
ppUserInfo);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
/* On this one, it is a good idea to fallback to
the local provider */
if (dwError == LW_ERROR_RPC_NETLOGON_FAILED) {
dwError = LW_ERROR_NOT_HANDLED;
}
goto cleanup;
}
DWORD
AD_ValidateUser(
HANDLE hProvider,
PCSTR pszLoginId,
PCSTR pszPassword
)
{
DWORD dwError = 0;
PLSA_LOGIN_NAME_INFO pLoginInfo = NULL;
PLSA_SECURITY_OBJECT pUserInfo = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LsaCrackDomainQualifiedName(
pszLoginId,
gpADProviderData->szDomain,
&pLoginInfo);
BAIL_ON_LSA_ERROR(dwError);
if (!AD_ServicesDomain(pLoginInfo->pszDomainNetBiosName)) {
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_FindUserObjectByName(
hProvider,
pszLoginId,
&pUserInfo);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_VerifyUserAccountCanLogin(
pUserInfo);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
ADCacheSafeFreeObject(&pUserInfo);
if (pLoginInfo)
{
LsaFreeNameInfo(pLoginInfo);
}
return dwError;
error:
goto cleanup;
}
DWORD
AD_CheckUserInList(
HANDLE hProvider,
PCSTR pszUserName,
PCSTR pszListName
)
{
DWORD dwError = 0;
size_t sNumGroupsFound = 0;
PLSA_SECURITY_OBJECT* ppGroupList = NULL;
PLSA_SECURITY_OBJECT pUserInfo = NULL;
size_t iGroup = 0;
PLSA_HASH_TABLE pAllowedMemberList = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_ResolveConfiguredLists(
hProvider,
&pAllowedMemberList);
BAIL_ON_LSA_ERROR(dwError);
if (!AD_ShouldFilterUserLoginsByGroup())
{
goto cleanup;
}
dwError = AD_FindUserObjectByName(hProvider, pszUserName, &pUserInfo);
BAIL_ON_LSA_ERROR(dwError);
if (AD_IsMemberAllowed(pUserInfo->pszObjectSid,
pAllowedMemberList))
{
goto cleanup;
}
dwError = AD_GetUserGroupObjectMembership(
hProvider,
pUserInfo,
FALSE,
&sNumGroupsFound,
&ppGroupList);
BAIL_ON_LSA_ERROR(dwError);
for (; iGroup < sNumGroupsFound; iGroup++)
{
if (AD_IsMemberAllowed(ppGroupList[iGroup]->pszObjectSid,
pAllowedMemberList))
{
goto cleanup;
}
}
dwError = EACCES;
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
ADCacheSafeFreeObjectList(sNumGroupsFound, &ppGroupList);
ADCacheSafeFreeObject(&pUserInfo);
LsaHashSafeFree(&pAllowedMemberList);
return dwError;
error:
if (dwError == EACCES)
{
LSA_LOG_ERROR("Error: User [%s] not in restricted login list", pszUserName);
}
else
{
LSA_LOG_ERROR("Error: Failed to validate restricted membership. [Error code: %u]", dwError);
}
goto cleanup;
}
DWORD
AD_FindUserObjectById(
IN HANDLE hProvider,
IN uid_t uid,
OUT PLSA_SECURITY_OBJECT* ppResult
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_OnlineFindUserObjectById(
hProvider,
uid,
ppResult);
}
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
dwError = AD_OfflineFindUserObjectById(
hProvider,
uid,
ppResult);
}
error:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
}
DWORD
AD_EnumUsersFromCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID,
IN DWORD dwInputBufferSize,
IN PVOID pInputBuffer,
OUT DWORD* pdwOutputBufferSize,
OUT PVOID* ppOutputBuffer
)
{
DWORD dwError = 0;
DWORD dwObjectCount = 0;
PLSA_SECURITY_OBJECT* ppUserObjectList = NULL;
PVOID pBlob = NULL;
size_t BlobSize = 0;
LWMsgContext* context = NULL;
LWMsgDataContext* pDataContext = NULL;
PLSA_AD_IPC_ENUM_USERS_FROM_CACHE_REQ request = NULL;
LSA_AD_IPC_ENUM_USERS_FROM_CACHE_RESP response = {0};
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
// restrict access to root
if (peerUID)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = MAP_LWMSG_ERROR(lwmsg_context_new(NULL, &context));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_context_new(context, &pDataContext));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_unmarshal_flat(
pDataContext,
LsaAdIPCGetEnumUsersFromCacheReqSpec(),
pInputBuffer,
dwInputBufferSize,
(PVOID*)&request));
BAIL_ON_LSA_ERROR(dwError);
dwError = ADCacheEnumUsersCache(
gpLsaAdProviderState->hCacheConnection,
request->dwMaxNumUsers,
request->pszResume,
&dwObjectCount,
&ppUserObjectList);
if ( dwError == LW_ERROR_NOT_HANDLED )
{
// no more results found
dwError = LW_ERROR_SUCCESS;
}
BAIL_ON_LSA_ERROR(dwError);
if ( dwObjectCount == request->dwMaxNumUsers )
{
dwError = LwAllocateString(
ppUserObjectList[dwObjectCount - 1]->pszObjectSid,
&response.pszResume);
BAIL_ON_LSA_ERROR(dwError);
}
// marshal the response data
response.dwNumUsers = dwObjectCount;
response.ppObjects = ppUserObjectList;
dwError = MAP_LWMSG_ERROR(lwmsg_data_marshal_flat_alloc(
pDataContext,
LsaAdIPCGetEnumUsersFromCacheRespSpec(),
&response,
&pBlob,
&BlobSize));
BAIL_ON_LSA_ERROR(dwError);
*pdwOutputBufferSize = BlobSize;
*ppOutputBuffer = pBlob;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
ADCacheSafeFreeObjectList(dwObjectCount, &ppUserObjectList);
if ( request )
{
lwmsg_data_free_graph(
pDataContext,
LsaAdIPCGetEnumUsersFromCacheReqSpec(),
request);
}
if (pDataContext)
{
lwmsg_data_context_delete(pDataContext);
}
if ( context )
{
lwmsg_context_delete(context);
}
LW_SAFE_FREE_STRING(response.pszResume);
return dwError;
error:
*pdwOutputBufferSize = 0;
*ppOutputBuffer = NULL;
if ( pBlob )
{
LwFreeMemory(pBlob);
}
goto cleanup;
}
DWORD
AD_RemoveUserByNameFromCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID,
IN PCSTR pszLoginId
)
{
DWORD dwError = 0;
PSTR pszLocalLoginId = NULL;
PLSA_LOGIN_NAME_INFO pUserNameInfo = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
// restrict access to root
if (peerUID)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
if (!strcasecmp(pszLoginId, "root"))
{
dwError = LW_ERROR_NO_SUCH_USER;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_RemoveUserByNameFromCacheInternal(
hProvider,
pszLoginId);
if (dwError == LW_ERROR_NO_SUCH_USER &&
AD_ShouldAssumeDefaultDomain())
{
dwError = LsaCrackDomainQualifiedName(
pszLoginId,
gpADProviderData->szDomain,
&pUserNameInfo);
BAIL_ON_LSA_ERROR(dwError);
if (pUserNameInfo->nameType == NameType_Alias)
{
dwError = ADGetDomainQualifiedString(
gpADProviderData->szShortDomain,
pszLoginId,
&pszLocalLoginId);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_RemoveUserByNameFromCacheInternal(
hProvider,
pszLocalLoginId);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = LW_ERROR_NO_SUCH_USER;
BAIL_ON_LSA_ERROR(dwError);
}
}
else
{
BAIL_ON_LSA_ERROR(dwError);
}
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
LW_SAFE_FREE_STRING(pszLocalLoginId);
if (pUserNameInfo)
{
LsaFreeNameInfo(pUserNameInfo);
}
return dwError;
error:
goto cleanup;
}
DWORD
AD_RemoveUserByIdFromCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID,
IN uid_t uid
)
{
DWORD dwError = 0;
PLSA_SECURITY_OBJECT pUserInfo = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
// restrict access to root
if (peerUID)
{
dwError = EACCES;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_OfflineFindUserObjectById(
hProvider,
uid,
&pUserInfo);
BAIL_ON_LSA_ERROR(dwError);
dwError = ADCacheRemoveUserBySid(
gpLsaAdProviderState->hCacheConnection,
pUserInfo->pszObjectSid);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
ADCacheSafeFreeObject(&pUserInfo);
return dwError;
error:
if ((dwError == LW_ERROR_DUPLICATE_USERNAME ||
dwError == LW_ERROR_DUPLICATE_USER_OR_GROUP)
&& AD_EventlogEnabled())
{
LsaSrvLogUserIDConflictEvent(
uid,
gpszADProviderName,
dwError);
}
goto cleanup;
}
static
DWORD
AD_PreJoinDomain(
HANDLE hProvider,
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
switch (pState->joinState)
{
case LSA_AD_UNKNOWN:
case LSA_AD_NOT_JOINED:
break;
case LSA_AD_JOINED:
dwError = AD_TransitionNotJoined(pState);
BAIL_ON_LSA_ERROR(dwError);
break;
}
error:
return dwError;
}
static
DWORD
AD_PostJoinDomain(
HANDLE hProvider,
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
dwError = AD_TransitionJoined(pState);
BAIL_ON_LSA_ERROR(dwError);
error:
return dwError;
}
static
DWORD
AD_JoinDomain(
HANDLE hProvider,
uid_t peerUID,
gid_t peerGID,
DWORD dwInputBufferSize,
PVOID pInputBuffer,
DWORD* pdwOutputBufferSize,
PVOID* ppOutputBuffer
)
{
DWORD dwError = 0;
LWMsgDataContext* pDataContext = NULL;
PLSA_AD_IPC_JOIN_DOMAIN_REQ pRequest = NULL;
PSTR pszMessage = NULL;
BOOLEAN bLocked = FALSE;
PSTR pszDC = NULL;
if (peerUID != 0)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = MAP_LWMSG_ERROR(lwmsg_data_context_new(NULL, &pDataContext));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_unmarshal_flat(
pDataContext,
LsaAdIPCGetJoinDomainReqSpec(),
pInputBuffer,
(size_t) dwInputBufferSize,
OUT_PPVOID(&pRequest)));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_print_graph_alloc(
pDataContext,
LsaAdIPCGetJoinDomainReqSpec(),
pRequest,
&pszMessage));
BAIL_ON_LSA_ERROR(dwError);
LSA_LOG_TRACE("Domain join request: %s", pszMessage);
dwError = LWNetGetDomainController(
pRequest->pszDomain,
&pszDC);
if (dwError)
{
LSA_LOG_VERBOSE("Failed to find DC for domain %s", LSA_SAFE_LOG_STRING(pRequest->pszDomain));
BAIL_ON_LSA_ERROR(dwError);
}
LSA_LOG_VERBOSE("Affinitized to DC '%s' for join request to domain '%s'",
LSA_SAFE_LOG_STRING(pszDC),
LSA_SAFE_LOG_STRING(pRequest->pszDomain));
LsaAdProviderStateAcquireWrite(gpLsaAdProviderState);
bLocked = TRUE;
dwError = AD_PreJoinDomain(hProvider, gpLsaAdProviderState);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaNetJoinDomain(
pRequest->pszHostname,
pRequest->pszHostDnsDomain,
pRequest->pszDomain,
pRequest->pszOU,
pRequest->pszUsername,
pRequest->pszPassword,
pRequest->pszOSName,
pRequest->pszOSVersion,
pRequest->pszOSServicePack,
pRequest->dwFlags);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_PostJoinDomain(hProvider, gpLsaAdProviderState);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaEnableDomainGroupMembership(pRequest->pszHostDnsDomain);
BAIL_ON_LSA_ERROR(dwError);
LSA_LOG_INFO("Joined domain: %s", pRequest->pszDomain);
cleanup:
if (bLocked)
{
LsaAdProviderStateRelease(gpLsaAdProviderState);
}
LW_SAFE_FREE_MEMORY(pszMessage);
if (pRequest)
{
lwmsg_data_free_graph(
pDataContext,
LsaAdIPCGetJoinDomainReqSpec(),
pRequest);
}
if (pDataContext)
{
lwmsg_data_context_delete(pDataContext);
}
LW_SAFE_FREE_STRING(pszDC);
return dwError;
error:
goto cleanup;
}
static
DWORD
AD_PreLeaveDomain(
HANDLE hProvider,
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
switch (pState->joinState)
{
case LSA_AD_UNKNOWN:
case LSA_AD_NOT_JOINED:
dwError = LW_ERROR_NOT_JOINED_TO_AD;
BAIL_ON_LSA_ERROR(dwError);
break;
case LSA_AD_JOINED:
AD_TransitionNotJoined(pState);
break;
}
error:
return dwError;
}
static
DWORD
AD_PostLeaveDomain(
HANDLE hProvider,
PLSA_AD_PROVIDER_STATE pState
)
{
DWORD dwError = 0;
return dwError;
}
static
DWORD
AD_LeaveDomain(
HANDLE hProvider,
uid_t peerUID,
gid_t peerGID,
DWORD dwInputBufferSize,
PVOID pInputBuffer,
DWORD* pdwOutputBufferSize,
PVOID* ppOutputBuffer
)
{
DWORD dwError = 0;
LWMsgDataContext* pDataContext = NULL;
PLSA_AD_IPC_LEAVE_DOMAIN_REQ pRequest = NULL;
PSTR pszMessage = NULL;
BOOLEAN bLocked = FALSE;
if (peerUID != 0)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = MAP_LWMSG_ERROR(lwmsg_data_context_new(NULL, &pDataContext));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_unmarshal_flat(
pDataContext,
LsaAdIPCGetLeaveDomainReqSpec(),
pInputBuffer,
(size_t) dwInputBufferSize,
OUT_PPVOID(&pRequest)));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_print_graph_alloc(
pDataContext,
LsaAdIPCGetLeaveDomainReqSpec(),
pRequest,
&pszMessage));
BAIL_ON_LSA_ERROR(dwError);
LSA_LOG_TRACE("Domain leave request: %s", pszMessage);
LsaAdProviderStateAcquireWrite(gpLsaAdProviderState);
bLocked = TRUE;
dwError = LsaDisableDomainGroupMembership();
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_PreLeaveDomain(hProvider, gpLsaAdProviderState);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaNetLeaveDomain(
pRequest->pszUsername,
pRequest->pszPassword);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_PostLeaveDomain(hProvider, gpLsaAdProviderState);
BAIL_ON_LSA_ERROR(dwError);
LSA_LOG_INFO("Left domain\n");
cleanup:
if (bLocked)
{
LsaAdProviderStateRelease(gpLsaAdProviderState);
}
LW_SAFE_FREE_MEMORY(pszMessage);
if (pRequest)
{
lwmsg_data_free_graph(
pDataContext,
LsaAdIPCGetLeaveDomainReqSpec(),
pRequest);
}
if (pDataContext)
{
lwmsg_data_context_delete(pDataContext);
}
return dwError;
error:
goto cleanup;
}
static
DWORD
AD_GetExpandedGroupUsersEx(
IN HANDLE hProvider,
IN PCSTR pszDomainName,
IN BOOLEAN bIsOffline,
IN PCSTR pszGroupSid,
IN BOOLEAN bIsCacheOnlyMode,
IN DWORD dwMaxDepth,
OUT PBOOLEAN pbIsFullyExpanded,
OUT size_t* psMemberUsersCount,
OUT PLSA_SECURITY_OBJECT** pppMemberUsers
)
{
DWORD dwError = LW_ERROR_SUCCESS;
BOOLEAN bIsFullyExpanded = FALSE;
PLSA_AD_GROUP_EXPANSION_DATA pExpansionData = NULL;
PLSA_SECURITY_OBJECT* ppGroupMembers = NULL;
size_t sGroupMembersCount = 0;
PLSA_SECURITY_OBJECT pGroupToExpand = NULL;
DWORD dwGroupToExpandDepth = 0;
PCSTR pszGroupToExpandSid = NULL;
PLSA_SECURITY_OBJECT* ppExpandedUsers = NULL;
size_t sExpandedUsersCount = 0;
dwError = AD_GroupExpansionDataCreate(
&pExpansionData,
LSA_MAX(1, dwMaxDepth));
BAIL_ON_LSA_ERROR(dwError);
pszGroupToExpandSid = pszGroupSid;
dwGroupToExpandDepth = 1;
while (pszGroupToExpandSid)
{
if (bIsOffline)
{
dwError = AD_OfflineGetGroupMembers(
pszGroupToExpandSid,
&sGroupMembersCount,
&ppGroupMembers);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
// ISSUE-2008/11/03-dalmeida -- Need to get domain from SID.
dwError = AD_OnlineGetGroupMembers(
hProvider,
pszDomainName,
pszGroupToExpandSid,
bIsCacheOnlyMode,
&sGroupMembersCount,
&ppGroupMembers);
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_GroupExpansionDataAddExpansionResults(
pExpansionData,
dwGroupToExpandDepth,
&sGroupMembersCount,
&ppGroupMembers);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_GroupExpansionDataGetNextGroupToExpand(
pExpansionData,
&pGroupToExpand,
&dwGroupToExpandDepth);
BAIL_ON_LSA_ERROR(dwError);
if (pGroupToExpand)
{
pszGroupToExpandSid = pGroupToExpand->pszObjectSid;
}
else
{
pszGroupToExpandSid = NULL;
}
}
dwError = AD_GroupExpansionDataGetResults(pExpansionData,
&bIsFullyExpanded,
&sExpandedUsersCount,
&ppExpandedUsers);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
AD_GroupExpansionDataDestroy(pExpansionData);
ADCacheSafeFreeObjectList(sGroupMembersCount, &ppGroupMembers);
if (pbIsFullyExpanded)
{
*pbIsFullyExpanded = bIsFullyExpanded;
}
*psMemberUsersCount = sExpandedUsersCount;
*pppMemberUsers = ppExpandedUsers;
return dwError;
error:
ADCacheSafeFreeObjectList(sExpandedUsersCount, &ppExpandedUsers);
sExpandedUsersCount = 0;
bIsFullyExpanded = FALSE;
goto cleanup;
}
DWORD
AD_GetExpandedGroupUsers(
IN HANDLE hProvider,
IN PCSTR pszDomainName,
IN PCSTR pszGroupSid,
IN BOOLEAN bIsCacheOnlyMode,
IN int iMaxDepth,
OUT BOOLEAN* pbAllExpanded,
OUT size_t* psCount,
OUT PLSA_SECURITY_OBJECT** pppResults
)
{
DWORD dwError = LW_ERROR_SUCCESS;
if (AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_GetExpandedGroupUsersEx(
hProvider,
pszDomainName,
FALSE,
pszGroupSid,
bIsCacheOnlyMode,
iMaxDepth,
pbAllExpanded,
psCount,
pppResults);
}
if (dwError == LW_ERROR_DOMAIN_IS_OFFLINE)
{
dwError = AD_GetExpandedGroupUsersEx(
hProvider,
pszDomainName,
TRUE,
pszGroupSid,
bIsCacheOnlyMode,
iMaxDepth,
pbAllExpanded,
psCount,
pppResults);
}
return dwError;
}
DWORD
AD_EnumGroupsFromCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID,
IN DWORD dwInputBufferSize,
IN PVOID pInputBuffer,
OUT DWORD* pdwOutputBufferSize,
OUT PVOID* ppOutputBuffer
)
{
DWORD dwError = 0;
DWORD dwObjectCount = 0;
PLSA_SECURITY_OBJECT* ppGroupObjectList = NULL;
PVOID pBlob = NULL;
size_t BlobSize;
LWMsgContext* context = NULL;
LWMsgDataContext* pDataContext = NULL;
PLSA_AD_IPC_ENUM_GROUPS_FROM_CACHE_REQ request = NULL;
LSA_AD_IPC_ENUM_GROUPS_FROM_CACHE_RESP response = {0};
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
// restrict access to root
if (peerUID)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = MAP_LWMSG_ERROR(lwmsg_context_new(NULL, &context));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_context_new(context, &pDataContext));
BAIL_ON_LSA_ERROR(dwError);
dwError = MAP_LWMSG_ERROR(lwmsg_data_unmarshal_flat(
pDataContext,
LsaAdIPCGetEnumGroupsFromCacheReqSpec(),
pInputBuffer,
dwInputBufferSize,
(PVOID*)&request));
BAIL_ON_LSA_ERROR(dwError);
dwError = ADCacheEnumGroupsCache(
gpLsaAdProviderState->hCacheConnection,
request->dwMaxNumGroups,
request->pszResume,
&dwObjectCount,
&ppGroupObjectList);
if ( dwError == LW_ERROR_NOT_HANDLED )
{
// no more results found
dwError = LW_ERROR_SUCCESS;
}
BAIL_ON_LSA_ERROR(dwError);
if ( dwObjectCount == request->dwMaxNumGroups )
{
dwError = LwAllocateString(
ppGroupObjectList[dwObjectCount - 1]->pszObjectSid,
&response.pszResume);
BAIL_ON_LSA_ERROR(dwError);
}
response.dwNumGroups = dwObjectCount;
response.ppObjects = ppGroupObjectList;
dwError = MAP_LWMSG_ERROR(lwmsg_data_marshal_flat_alloc(
pDataContext,
LsaAdIPCGetEnumGroupsFromCacheRespSpec(),
&response,
&pBlob,
&BlobSize));
BAIL_ON_LSA_ERROR(dwError);
*pdwOutputBufferSize = BlobSize;
*ppOutputBuffer = pBlob;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
ADCacheSafeFreeObjectList(dwObjectCount, &ppGroupObjectList);
if ( request )
{
lwmsg_data_free_graph(
pDataContext,
LsaAdIPCGetEnumGroupsFromCacheReqSpec(),
request);
}
if (pDataContext)
{
lwmsg_data_context_delete(pDataContext);
}
if ( context )
{
lwmsg_context_delete(context);
}
LW_SAFE_FREE_STRING(response.pszResume);
return dwError;
error:
*pdwOutputBufferSize = 0;
*ppOutputBuffer = NULL;
if ( pBlob )
{
LwFreeMemory(pBlob);
}
goto cleanup;
}
DWORD
AD_RemoveGroupByNameFromCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID,
IN PCSTR pszGroupName
)
{
DWORD dwError = 0;
PSTR pszFreeGroupName = NULL;
PCSTR pszUseGroupName = NULL;
PLSA_SECURITY_OBJECT pGroupInfo = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
// restrict access to root
if (peerUID)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_GetNameWithReplacedSeparators(
pszGroupName,
&pszFreeGroupName,
&pszUseGroupName);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_OfflineFindGroupObjectByName(
hProvider,
pszUseGroupName,
&pGroupInfo);
BAIL_ON_LSA_ERROR(dwError);
dwError = ADCacheRemoveGroupBySid(
gpLsaAdProviderState->hCacheConnection,
pGroupInfo->pszObjectSid);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
LW_SAFE_FREE_STRING(pszFreeGroupName);
ADCacheSafeFreeObject(&pGroupInfo);
return dwError;
error:
goto cleanup;
}
DWORD
AD_RemoveGroupByIdFromCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID,
IN gid_t gid
)
{
DWORD dwError = 0;
PLSA_SECURITY_OBJECT pObject = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
// restrict access to root
if (peerUID)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = ADCacheFindGroupById(
gpLsaAdProviderState->hCacheConnection,
gid,
&pObject);
if (dwError == LW_ERROR_NOT_HANDLED)
{
dwError = LW_ERROR_NO_SUCH_GROUP;
}
BAIL_ON_LSA_ERROR(dwError);
dwError = ADCacheRemoveGroupBySid(
gpLsaAdProviderState->hCacheConnection,
pObject->pszObjectSid);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaUtilFreeSecurityObject(pObject);
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
goto cleanup;
}
DWORD
AD_GetUserGroupObjectMembership(
IN HANDLE hProvider,
IN PLSA_SECURITY_OBJECT pUserInfo,
IN BOOLEAN bIsCacheOnlyMode,
OUT size_t* psNumGroupsFound,
OUT PLSA_SECURITY_OBJECT** pppResult
)
{
DWORD dwError = 0;
if (AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_OnlineGetUserGroupObjectMembership(
hProvider,
pUserInfo,
bIsCacheOnlyMode,
psNumGroupsFound,
pppResult);
}
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
dwError = AD_OfflineGetUserGroupObjectMembership(
hProvider,
pUserInfo,
psNumGroupsFound,
pppResult);
}
return dwError;
}
DWORD
AD_ChangePassword(
HANDLE hProvider,
PCSTR pszLoginId,
PCSTR pszPassword,
PCSTR pszOldPassword
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = AD_OfflineChangePassword(
hProvider,
pszLoginId,
pszPassword,
pszOldPassword);
}
else
{
dwError = AD_OnlineChangePassword(
hProvider,
pszLoginId,
pszPassword,
pszOldPassword);
}
error:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
}
DWORD
AD_SetPassword(
HANDLE hProvider,
PCSTR pszLoginId,
PCSTR pszPassword
)
{
return LW_ERROR_NOT_HANDLED;
}
DWORD
AD_AddUser(
HANDLE hProvider,
PLSA_USER_ADD_INFO pUserAddInfo
)
{
return LW_ERROR_NOT_HANDLED;
}
DWORD
AD_ModifyUser(
HANDLE hProvider,
PLSA_USER_MOD_INFO_2 pUserModInfo
)
{
return LW_ERROR_NOT_HANDLED;
}
DWORD
AD_DeleteObject(
HANDLE hProvider,
PCSTR pszSid
)
{
return LW_ERROR_NOT_HANDLED;
}
DWORD
AD_AddGroup(
HANDLE hProvider,
PLSA_GROUP_ADD_INFO pGroupAddInfo
)
{
return LW_ERROR_NOT_HANDLED;
}
DWORD
AD_ModifyGroup(
HANDLE hProvider,
PLSA_GROUP_MOD_INFO_2 pGroupModInfo
)
{
return LW_ERROR_NOT_HANDLED;
}
DWORD
AD_EmptyCache(
IN HANDLE hProvider,
IN uid_t peerUID,
IN gid_t peerGID
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (peerUID)
{
dwError = LW_ERROR_ACCESS_DENIED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = ADCacheEmptyCache(
gpLsaAdProviderState->hCacheConnection);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
goto cleanup;
}
DWORD
AD_OpenSession(
HANDLE hProvider,
PCSTR pszLoginId
)
{
DWORD dwError = 0;
PLSA_LOGIN_NAME_INFO pLoginInfo = NULL;
PLSA_SECURITY_OBJECT* ppObjects = NULL;
LSA_QUERY_LIST QueryList;
LSA_QUERY_TYPE QueryType = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LsaCrackDomainQualifiedName(
pszLoginId,
gpADProviderData->szDomain,
&pLoginInfo);
BAIL_ON_LSA_ERROR(dwError);
switch (pLoginInfo->nameType)
{
case NameType_NT4:
QueryType = LSA_QUERY_TYPE_BY_NT4;
break;
case NameType_Alias:
QueryType = LSA_QUERY_TYPE_BY_ALIAS;
break;
case NameType_UPN:
QueryType = LSA_QUERY_TYPE_BY_UPN;
break;
default:
dwError = LW_ERROR_INVALID_PARAMETER;
BAIL_ON_LSA_ERROR(dwError);
}
QueryList.ppszStrings = (PCSTR*) &pszLoginId;
dwError = AD_FindObjects(
hProvider,
0,
LSA_OBJECT_TYPE_USER,
QueryType,
1,
QueryList,
&ppObjects);
BAIL_ON_LSA_ERROR(dwError);
if (!ppObjects[0] || !ppObjects[0]->enabled)
{
dwError = LW_ERROR_NO_SUCH_USER;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_CreateHomeDirectory(ppObjects[0]);
BAIL_ON_LSA_ERROR(dwError);
if (AD_ShouldCreateK5Login())
{
dwError = AD_CreateK5Login(ppObjects[0]);
BAIL_ON_LSA_ERROR(dwError);
}
cleanup:
LsaUtilFreeSecurityObjectList(1, ppObjects);
LsaAdProviderStateRelease(gpLsaAdProviderState);
if (pLoginInfo)
{
LsaFreeNameInfo(pLoginInfo);
}
return dwError;
error:
goto cleanup;
}
DWORD
AD_CloseSession(
HANDLE hProvider,
PCSTR pszLoginId
)
{
DWORD dwError = 0;
PLSA_LOGIN_NAME_INFO pLoginInfo = NULL;
PLSA_SECURITY_OBJECT* ppObjects = NULL;
LSA_QUERY_LIST QueryList;
LSA_QUERY_TYPE QueryType = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LsaCrackDomainQualifiedName(
pszLoginId,
gpADProviderData->szDomain,
&pLoginInfo);
BAIL_ON_LSA_ERROR(dwError);
switch (pLoginInfo->nameType)
{
case NameType_NT4:
QueryType = LSA_QUERY_TYPE_BY_NT4;
break;
case NameType_Alias:
QueryType = LSA_QUERY_TYPE_BY_ALIAS;
break;
case NameType_UPN:
QueryType = LSA_QUERY_TYPE_BY_UPN;
break;
default:
dwError = LW_ERROR_INVALID_PARAMETER;
BAIL_ON_LSA_ERROR(dwError);
}
QueryList.ppszStrings = (PCSTR*) &pszLoginId;
dwError = AD_FindObjects(
hProvider,
0,
LSA_OBJECT_TYPE_USER,
QueryType,
1,
QueryList,
&ppObjects);
BAIL_ON_LSA_ERROR(dwError);
if (!ppObjects[0] || !ppObjects[0]->enabled)
{
dwError = LW_ERROR_NO_SUCH_USER;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LsaUmRemoveUser(ppObjects[0]->userInfo.uid);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LsaUtilFreeSecurityObjectList(1, ppObjects);
LsaAdProviderStateRelease(gpLsaAdProviderState);
if (pLoginInfo)
{
LsaFreeNameInfo(pLoginInfo);
}
return dwError;
error:
goto cleanup;
}
DWORD
AD_FindNSSArtefactByKey(
HANDLE hProvider,
PCSTR pszKeyName,
PCSTR pszMapName,
DWORD dwInfoLevel,
LSA_NIS_MAP_QUERY_FLAGS dwFlags,
PVOID* ppNSSArtefactInfo
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = AD_OfflineFindNSSArtefactByKey(
hProvider,
pszKeyName,
pszMapName,
dwInfoLevel,
dwFlags,
ppNSSArtefactInfo);
}
else
{
dwError = AD_OnlineFindNSSArtefactByKey(
hProvider,
pszKeyName,
pszMapName,
dwInfoLevel,
dwFlags,
ppNSSArtefactInfo);
}
error:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
}
DWORD
AD_BeginEnumNSSArtefacts(
HANDLE hProvider,
DWORD dwInfoLevel,
PCSTR pszMapName,
LSA_NIS_MAP_QUERY_FLAGS dwFlags,
PHANDLE phResume
)
{
DWORD dwError = 0;
PAD_ENUM_STATE pEnumState = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (!dwFlags)
{
dwError = LW_ERROR_INVALID_PARAMETER;
BAIL_ON_LSA_ERROR(dwError);
}
switch (gpADProviderData->dwDirectoryMode)
{
case DEFAULT_MODE:
case CELL_MODE:
dwError = AD_CreateNSSArtefactState(
hProvider,
dwInfoLevel,
pszMapName,
dwFlags,
&pEnumState);
BAIL_ON_LSA_ERROR(dwError);
LwInitCookie(&pEnumState->Cookie);
break;
case UNPROVISIONED_MODE:
dwError = LW_ERROR_NOT_SUPPORTED;
break;
}
*phResume = (HANDLE)pEnumState;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
*phResume = (HANDLE)NULL;
goto cleanup;
}
DWORD
AD_EnumNSSArtefacts(
HANDLE hProvider,
HANDLE hResume,
DWORD dwMaxNSSArtefacts,
PDWORD pdwNSSArtefactsFound,
PVOID** pppNSSArtefactInfoList
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = AD_OfflineEnumNSSArtefacts(
hProvider,
hResume,
dwMaxNSSArtefacts,
pdwNSSArtefactsFound,
pppNSSArtefactInfoList);
}
else
{
dwError = AD_OnlineEnumNSSArtefacts(
hProvider,
hResume,
dwMaxNSSArtefacts,
pdwNSSArtefactsFound,
pppNSSArtefactInfoList);
}
error:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
}
VOID
AD_EndEnumNSSArtefacts(
HANDLE hProvider,
HANDLE hResume
)
{
AD_FreeNSSArtefactState(hProvider, (PAD_ENUM_STATE)hResume);
}
DWORD
AD_GetStatus(
HANDLE hProvider,
PLSA_AUTH_PROVIDER_STATUS* ppProviderStatus
)
{
DWORD dwError = 0;
PLWNET_DC_INFO pDCInfo = NULL;
PLSA_AUTH_PROVIDER_STATUS pProviderStatus = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LwAllocateMemory(
sizeof(LSA_AUTH_PROVIDER_STATUS),
(PVOID*)&pProviderStatus);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwAllocateString(
gpszADProviderName,
&pProviderStatus->pszId);
BAIL_ON_LSA_ERROR(dwError);
switch (gpADProviderData->dwDirectoryMode)
{
case DEFAULT_MODE:
pProviderStatus->mode = LSA_PROVIDER_MODE_DEFAULT_CELL;
break;
case CELL_MODE:
pProviderStatus->mode = LSA_PROVIDER_MODE_NON_DEFAULT_CELL;
if (!LW_IS_NULL_OR_EMPTY_STR(gpADProviderData->cell.szCellDN))
{
dwError = LwAllocateString(
gpADProviderData->cell.szCellDN,
&pProviderStatus->pszCell);
BAIL_ON_LSA_ERROR(dwError);
}
break;
case UNPROVISIONED_MODE:
pProviderStatus->mode = LSA_PROVIDER_MODE_UNPROVISIONED;
break;
default:
pProviderStatus->mode = LSA_PROVIDER_MODE_UNKNOWN;
break;
}
switch (gpADProviderData->adConfigurationMode)
{
case SchemaMode:
pProviderStatus->subMode = LSA_AUTH_PROVIDER_SUBMODE_SCHEMA;
break;
case NonSchemaMode:
pProviderStatus->subMode = LSA_AUTH_PROVIDER_SUBMODE_NONSCHEMA;
break;
default:
pProviderStatus->subMode = LSA_AUTH_PROVIDER_SUBMODE_UNKNOWN;
break;
}
if (!LW_IS_NULL_OR_EMPTY_STR(gpADProviderData->szDomain))
{
dwError = LwAllocateString(
gpADProviderData->szDomain,
&pProviderStatus->pszDomain);
BAIL_ON_LSA_ERROR(dwError);
dwError = LWNetGetDCName(
NULL,
gpADProviderData->szDomain,
NULL,
DS_BACKGROUND_ONLY,
&pDCInfo);
if (ERROR_NO_SUCH_DOMAIN == dwError)
{
dwError = 0;
}
BAIL_ON_LSA_ERROR(dwError);
if (pDCInfo)
{
if (!LW_IS_NULL_OR_EMPTY_STR(pDCInfo->pszDnsForestName))
{
dwError = LwAllocateString(
pDCInfo->pszDnsForestName,
&pProviderStatus->pszForest);
BAIL_ON_LSA_ERROR(dwError);
}
if (!LW_IS_NULL_OR_EMPTY_STR(pDCInfo->pszDCSiteName))
{
dwError = LwAllocateString(
pDCInfo->pszDCSiteName,
&pProviderStatus->pszSite);
BAIL_ON_LSA_ERROR(dwError);
}
}
}
dwError = AD_GetTrustedDomainInfo(
&pProviderStatus->pTrustedDomainInfoArray,
&pProviderStatus->dwNumTrustedDomains);
BAIL_ON_LSA_ERROR(dwError);
if (AD_IsOffline())
{
pProviderStatus->status = LSA_AUTH_PROVIDER_STATUS_OFFLINE;
}
else
{
pProviderStatus->status = LSA_AUTH_PROVIDER_STATUS_ONLINE;
}
dwError = LsaDmQueryState(NULL, &pProviderStatus->dwNetworkCheckInterval, NULL);
BAIL_ON_LSA_ERROR(dwError);
*ppProviderStatus = pProviderStatus;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
LWNET_SAFE_FREE_DC_INFO(pDCInfo);
return dwError;
error:
*ppProviderStatus = NULL;
if (pProviderStatus)
{
AD_FreeStatus(pProviderStatus);
}
goto cleanup;
}
DWORD
AD_GetTrustedDomainInfo(
PLSA_TRUSTED_DOMAIN_INFO* ppDomainInfoArray,
PDWORD pdwNumTrustedDomains
)
{
DWORD dwError = 0;
PLSA_TRUSTED_DOMAIN_INFO pDomainInfoArray = NULL;
DWORD dwCount = 0;
PLSA_DM_ENUM_DOMAIN_INFO* ppDomainInfo = NULL;
dwError = LsaDmEnumDomainInfo(NULL, NULL, &ppDomainInfo, &dwCount);
BAIL_ON_LSA_ERROR(dwError);
if (dwCount)
{
DWORD iDomain = 0;
dwError = LwAllocateMemory(
sizeof(pDomainInfoArray[0]) * dwCount,
(PVOID*)&pDomainInfoArray);
BAIL_ON_LSA_ERROR(dwError);
for (iDomain = 0; iDomain < dwCount; iDomain++)
{
dwError = AD_FillTrustedDomainInfo(
ppDomainInfo[iDomain],
&pDomainInfoArray[iDomain]);
BAIL_ON_LSA_ERROR(dwError);
}
}
*ppDomainInfoArray = pDomainInfoArray;
*pdwNumTrustedDomains = dwCount;
cleanup:
LsaDmFreeEnumDomainInfoArray(ppDomainInfo);
return dwError;
error:
*ppDomainInfoArray = NULL;
*pdwNumTrustedDomains = 0;
if (pDomainInfoArray)
{
LsaFreeDomainInfoArray(dwCount, pDomainInfoArray);
}
goto cleanup;
}
VOID
AD_FreeTrustedDomainsInList(
PVOID pItem,
PVOID pUserData
)
{
if (pItem)
{
LsaFreeDomainInfo((PLSA_TRUSTED_DOMAIN_INFO)pItem);
}
}
DWORD
AD_FillTrustedDomainInfo(
IN PLSA_DM_ENUM_DOMAIN_INFO pDomainInfo,
OUT PLSA_TRUSTED_DOMAIN_INFO pTrustedDomainInfo
)
{
DWORD dwError = 0;
PLWNET_DC_INFO pDcInfo = NULL;
// Do not free dcInfo as it just points to other data.
LSA_DM_DC_INFO dcInfo = { 0 };
dwError = LwStrDupOrNull(
pDomainInfo->pszDnsDomainName,
&pTrustedDomainInfo->pszDnsDomain);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwStrDupOrNull(
pDomainInfo->pszNetbiosDomainName,
&pTrustedDomainInfo->pszNetbiosDomain);
BAIL_ON_LSA_ERROR(dwError);
if (pDomainInfo->pSid)
{
dwError = LsaAllocateCStringFromSid(
&pTrustedDomainInfo->pszDomainSID,
pDomainInfo->pSid);
BAIL_ON_LSA_ERROR(dwError);
}
if (pDomainInfo->pGuid)
{
CHAR szGUID[37] = "";
uuid_unparse(*pDomainInfo->pGuid, szGUID);
dwError = LwAllocateString(
szGUID,
&pTrustedDomainInfo->pszDomainGUID);
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LwStrDupOrNull(
pDomainInfo->pszTrusteeDnsDomainName,
&pTrustedDomainInfo->pszTrusteeDnsDomain);
BAIL_ON_LSA_ERROR(dwError);
pTrustedDomainInfo->dwTrustFlags = pDomainInfo->dwTrustFlags;
pTrustedDomainInfo->dwTrustType = pDomainInfo->dwTrustType;
pTrustedDomainInfo->dwTrustAttributes = pDomainInfo->dwTrustAttributes;
pTrustedDomainInfo->dwTrustDirection = pDomainInfo->dwTrustDirection;
pTrustedDomainInfo->dwTrustMode = pDomainInfo->dwTrustMode;
dwError = LwStrDupOrNull(
pDomainInfo->pszForestName,
&pTrustedDomainInfo->pszForestName);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwStrDupOrNull(
pDomainInfo->pszClientSiteName,
&pTrustedDomainInfo->pszClientSiteName);
BAIL_ON_LSA_ERROR(dwError);
pTrustedDomainInfo->dwDomainFlags = pDomainInfo->Flags;
if (pDomainInfo->DcInfo)
{
dwError = AD_BuildDCInfo(
pDomainInfo->DcInfo,
&pTrustedDomainInfo->pDCInfo);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = LWNetGetDCName(
NULL,
pDomainInfo->pszDnsDomainName,
NULL,
DS_BACKGROUND_ONLY,
&pDcInfo);
if (ERROR_NO_SUCH_DOMAIN == dwError)
{
dwError = 0;
}
BAIL_ON_LSA_ERROR(dwError);
if (pDcInfo)
{
dcInfo.dwDsFlags = pDcInfo->dwFlags;
dcInfo.pszName = pDcInfo->pszDomainControllerName;
dcInfo.pszAddress = pDcInfo->pszDomainControllerAddress;
dcInfo.pszSiteName = pDcInfo->pszDCSiteName;
dwError = AD_BuildDCInfo(
&dcInfo,
&pTrustedDomainInfo->pDCInfo);
BAIL_ON_LSA_ERROR(dwError);
if (!pTrustedDomainInfo->pszClientSiteName)
{
dwError = LwStrDupOrNull(
pDcInfo->pszClientSiteName,
&pTrustedDomainInfo->pszClientSiteName);
BAIL_ON_LSA_ERROR(dwError);
}
}
}
if (pDomainInfo->GcInfo)
{
dwError = AD_BuildDCInfo(
pDomainInfo->GcInfo,
&pTrustedDomainInfo->pGCInfo);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
LWNET_SAFE_FREE_DC_INFO(pDcInfo);
dwError = LWNetGetDCName(
NULL,
pDomainInfo->pszForestName,
NULL,
DS_GC_SERVER_REQUIRED | DS_BACKGROUND_ONLY,
&pDcInfo);
if (ERROR_NO_SUCH_DOMAIN == dwError)
{
dwError = 0;
}
BAIL_ON_LSA_ERROR(dwError);
if (pDcInfo)
{
dcInfo.dwDsFlags = pDcInfo->dwFlags;
dcInfo.pszName = pDcInfo->pszDomainControllerName;
dcInfo.pszAddress = pDcInfo->pszDomainControllerAddress;
dcInfo.pszSiteName = pDcInfo->pszDCSiteName;
dwError = AD_BuildDCInfo(
&dcInfo,
&pTrustedDomainInfo->pGCInfo);
BAIL_ON_LSA_ERROR(dwError);
}
}
cleanup:
LWNET_SAFE_FREE_DC_INFO(pDcInfo);
return dwError;
error:
LsaFreeDomainInfoContents(pTrustedDomainInfo);
goto cleanup;
}
DWORD
AD_BuildDCInfo(
PLSA_DM_DC_INFO pDCInfo,
PLSA_DC_INFO* ppDCInfo
)
{
DWORD dwError = 0;
PLSA_DC_INFO pDestDCInfo = NULL;
dwError = LwAllocateMemory(
sizeof(LSA_DC_INFO),
(PVOID*)&pDestDCInfo);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwStrDupOrNull(
pDCInfo->pszName,
&pDestDCInfo->pszName);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwStrDupOrNull(
pDCInfo->pszAddress,
&pDestDCInfo->pszAddress);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwStrDupOrNull(
pDCInfo->pszSiteName,
&pDestDCInfo->pszSiteName);
BAIL_ON_LSA_ERROR(dwError);
pDestDCInfo->dwFlags = pDCInfo->dwDsFlags;
*ppDCInfo = pDestDCInfo;
cleanup:
return dwError;
error:
*ppDCInfo = NULL;
if (pDestDCInfo)
{
LsaFreeDCInfo(pDestDCInfo);
}
goto cleanup;
}
VOID
AD_FreeStatus(
PLSA_AUTH_PROVIDER_STATUS pProviderStatus
)
{
LW_SAFE_FREE_STRING(pProviderStatus->pszId);
LW_SAFE_FREE_STRING(pProviderStatus->pszDomain);
LW_SAFE_FREE_STRING(pProviderStatus->pszForest);
LW_SAFE_FREE_STRING(pProviderStatus->pszSite);
LW_SAFE_FREE_STRING(pProviderStatus->pszCell);
if (pProviderStatus->pTrustedDomainInfoArray)
{
LsaFreeDomainInfoArray(
pProviderStatus->dwNumTrustedDomains,
pProviderStatus->pTrustedDomainInfoArray);
}
LwFreeMemory(pProviderStatus);
}
DWORD
AD_RefreshConfiguration(
HANDLE hProvider
)
{
DWORD dwError = 0;
LSA_AD_CONFIG config = {0};
BOOLEAN bInLock = FALSE;
BOOLEAN bUpdateCap = FALSE;
dwError = AD_InitializeConfig(&config);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_ReadRegistry(&config);
BAIL_ON_LSA_ERROR(dwError);
ENTER_AD_GLOBAL_DATA_RW_WRITER_LOCK(bInLock);
dwError = AD_TransferConfigContents(
&config,
&gpLsaAdProviderState->config);
BAIL_ON_LSA_ERROR(dwError);
dwError = LsaSetDomainSeparator(
gpLsaAdProviderState->config.chDomainSeparator);
BAIL_ON_LSA_ERROR(dwError);
AD_FreeAllowedSIDs_InLock();
dwError = LsaDmSetState(
NULL,
&gpLsaAdProviderState->config.DomainManager.dwCheckDomainOnlineSeconds,
&gpLsaAdProviderState->config.DomainManager.dwUnknownDomainCacheTimeoutSeconds);
BAIL_ON_LSA_ERROR(dwError);
if (gpLsaAdProviderState->config.CacheBackend == AD_CACHE_IN_MEMORY)
{
bUpdateCap = TRUE;
}
LEAVE_AD_GLOBAL_DATA_RW_WRITER_LOCK(bInLock);
if (bUpdateCap)
{
dwError = MemCacheSetSizeCap(
gpLsaAdProviderState->hCacheConnection,
AD_GetCacheSizeCap());
BAIL_ON_LSA_ERROR(dwError);
}
LsaAdProviderLogConfigReloadEvent();
LsaAdProviderLogRequireMembershipOfChangeEvent(hProvider);
LsaAdProviderLogEventLogEnableChangeEvent();
cleanup:
LEAVE_AD_GLOBAL_DATA_RW_WRITER_LOCK(bInLock);
return dwError;
error:
AD_FreeConfigContents(&config);
goto cleanup;
}
DWORD
AD_ProviderIoControl(
IN HANDLE hProvider,
IN uid_t peerUID,
IN uid_t peerGID,
IN DWORD dwIoControlCode,
IN DWORD dwInputBufferSize,
IN PVOID pInputBuffer,
OUT DWORD* pdwOutputBufferSize,
OUT PVOID* ppOutputBuffer
)
{
DWORD dwError = 0;
switch (dwIoControlCode)
{
case LSA_AD_IO_EMPTYCACHE:
dwError = AD_EmptyCache(
hProvider,
peerUID,
peerGID);
*pdwOutputBufferSize=0;
*ppOutputBuffer = NULL;
break;
case LSA_AD_IO_REMOVEUSERBYNAMECACHE:
dwError = AD_RemoveUserByNameFromCache(
hProvider,
peerUID,
peerGID,
(PCSTR)pInputBuffer);
*pdwOutputBufferSize=0;
*ppOutputBuffer = NULL;
break;
case LSA_AD_IO_REMOVEUSERBYIDCACHE:
dwError = AD_RemoveUserByIdFromCache(
hProvider,
peerUID,
peerGID,
*(uid_t *)pInputBuffer);
*pdwOutputBufferSize=0;
*ppOutputBuffer = NULL;
break;
case LSA_AD_IO_REMOVEGROUPBYNAMECACHE:
dwError = AD_RemoveGroupByNameFromCache(
hProvider,
peerUID,
peerGID,
(PCSTR)pInputBuffer);
*pdwOutputBufferSize=0;
*ppOutputBuffer = NULL;
break;
case LSA_AD_IO_REMOVEGROUPBYIDCACHE:
dwError = AD_RemoveGroupByIdFromCache(
hProvider,
peerUID,
peerGID,
*(gid_t *)pInputBuffer);
*pdwOutputBufferSize=0;
*ppOutputBuffer = NULL;
break;
case LSA_AD_IO_ENUMUSERSCACHE:
dwError = AD_EnumUsersFromCache(
hProvider,
peerUID,
peerGID,
dwInputBufferSize,
pInputBuffer,
pdwOutputBufferSize,
ppOutputBuffer);
break;
case LSA_AD_IO_ENUMGROUPSCACHE:
dwError = AD_EnumGroupsFromCache(
hProvider,
peerUID,
peerGID,
dwInputBufferSize,
pInputBuffer,
pdwOutputBufferSize,
ppOutputBuffer);
break;
case LSA_AD_IO_JOINDOMAIN:
dwError = AD_JoinDomain(
hProvider,
peerUID,
peerGID,
dwInputBufferSize,
pInputBuffer,
pdwOutputBufferSize,
ppOutputBuffer);
break;
case LSA_AD_IO_LEAVEDOMAIN:
dwError = AD_LeaveDomain(
hProvider,
peerUID,
peerGID,
dwInputBufferSize,
pInputBuffer,
pdwOutputBufferSize,
ppOutputBuffer);
break;
default:
dwError = LW_ERROR_NOT_HANDLED;
break;
}
BAIL_ON_LSA_ERROR(dwError);
cleanup:
return dwError;
error:
*pdwOutputBufferSize=0;
*ppOutputBuffer = NULL;
goto cleanup;
}
static
DWORD
AD_GetNameWithReplacedSeparators(
IN PCSTR pszName,
OUT PSTR* ppszFreeName,
OUT PCSTR* ppszUseName
)
{
DWORD dwError = 0;
// Capture the separator here so we consistent within
// this function in case it changes.
const CHAR chSeparator = AD_GetSpaceReplacement();
PSTR pszLocalName = NULL;
PCSTR pszUseName = NULL;
if (strchr(pszName, chSeparator))
{
dwError = LwAllocateString(
pszName,
&pszLocalName);
BAIL_ON_LSA_ERROR(dwError);
LwStrCharReplace(pszLocalName, chSeparator, ' ');
pszUseName = pszLocalName;
}
else
{
pszUseName = pszName;
}
*ppszFreeName = pszLocalName;
*ppszUseName = pszUseName;
cleanup:
return dwError;
error:
LW_SAFE_FREE_STRING(pszLocalName);
*ppszFreeName = NULL;
*ppszUseName = NULL;
goto cleanup;
}
static
DWORD
AD_FindUserObjectByNameInternal(
IN HANDLE hProvider,
IN PCSTR pszLoginId,
OUT PLSA_SECURITY_OBJECT* ppResult
)
{
DWORD dwError = 0;
PSTR pszFreeLoginId = NULL;
PCSTR pszUseLoginId = NULL;
PLSA_SECURITY_OBJECT pResult = NULL;
dwError = AD_GetNameWithReplacedSeparators(
pszLoginId,
&pszFreeLoginId,
&pszUseLoginId);
BAIL_ON_LSA_ERROR(dwError);
if (AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_OnlineFindUserObjectByName(
hProvider,
pszUseLoginId,
&pResult);
}
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
dwError = AD_OfflineFindUserObjectByName(
hProvider,
pszUseLoginId,
&pResult);
BAIL_ON_LSA_ERROR(dwError);
}
*ppResult = pResult;
cleanup:
LW_SAFE_FREE_STRING(pszFreeLoginId);
return dwError;
error:
*ppResult = NULL;
ADCacheSafeFreeObject(&pResult);
goto cleanup;
}
DWORD
AD_FindUserObjectByName(
IN HANDLE hProvider,
IN PCSTR pszLoginId,
OUT PLSA_SECURITY_OBJECT* ppResult
)
{
DWORD dwError = 0;
PSTR pszLocalLoginId = NULL;
PLSA_LOGIN_NAME_INFO pUserNameInfo = NULL;
PLSA_SECURITY_OBJECT pResult = NULL;
if (!strcasecmp(pszLoginId, "root"))
{
dwError = LW_ERROR_NO_SUCH_USER;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_FindUserObjectByNameInternal(
hProvider,
pszLoginId,
&pResult);
if (dwError == LW_ERROR_NO_SUCH_USER &&
AD_ShouldAssumeDefaultDomain())
{
dwError = LsaCrackDomainQualifiedName(
pszLoginId,
gpADProviderData->szDomain,
&pUserNameInfo);
BAIL_ON_LSA_ERROR(dwError);
if (pUserNameInfo->nameType == NameType_Alias)
{
dwError = ADGetDomainQualifiedString(
gpADProviderData->szShortDomain,
pszLoginId,
&pszLocalLoginId);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_FindUserObjectByNameInternal(
hProvider,
pszLocalLoginId,
&pResult);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = LW_ERROR_NO_SUCH_USER;
BAIL_ON_LSA_ERROR(dwError);
}
}
else
{
BAIL_ON_LSA_ERROR(dwError);
}
*ppResult = pResult;
cleanup:
LW_SAFE_FREE_STRING(pszLocalLoginId);
if (pUserNameInfo)
{
LsaFreeNameInfo(pUserNameInfo);
}
return dwError;
error:
*ppResult = NULL;
ADCacheSafeFreeObject(&pResult);
goto cleanup;
}
static
DWORD
AD_RemoveUserByNameFromCacheInternal(
IN HANDLE hProvider,
IN PCSTR pszLoginId
)
{
DWORD dwError = 0;
PSTR pszFreeLoginId = NULL;
PCSTR pszUseLoginId = NULL;
PLSA_SECURITY_OBJECT pUserInfo = NULL;
dwError = AD_GetNameWithReplacedSeparators(
pszLoginId,
&pszFreeLoginId,
&pszUseLoginId);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_OfflineFindUserObjectByName(
hProvider,
pszUseLoginId,
&pUserInfo);
BAIL_ON_LSA_ERROR(dwError);
dwError = ADCacheRemoveUserBySid(
gpLsaAdProviderState->hCacheConnection,
pUserInfo->pszObjectSid);
BAIL_ON_LSA_ERROR(dwError);
cleanup:
LW_SAFE_FREE_STRING(pszFreeLoginId);
ADCacheSafeFreeObject(&pUserInfo);
return dwError;
error:
goto cleanup;
}
static
DWORD
AD_FindGroupObjectByNameInternal(
IN HANDLE hProvider,
IN PCSTR pszGroupName,
OUT PLSA_SECURITY_OBJECT* ppResult
)
{
DWORD dwError = 0;
PSTR pszFreeGroupName = NULL;
PCSTR pszUseGroupName = NULL;
PLSA_SECURITY_OBJECT pResult = NULL;
dwError = AD_GetNameWithReplacedSeparators(
pszGroupName,
&pszFreeGroupName,
&pszUseGroupName);
BAIL_ON_LSA_ERROR(dwError);
if (AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_OnlineFindGroupObjectByName(
hProvider,
pszUseGroupName,
&pResult);
}
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
dwError = AD_OfflineFindGroupObjectByName(
hProvider,
pszUseGroupName,
&pResult);
BAIL_ON_LSA_ERROR(dwError);
}
*ppResult = pResult;
cleanup:
LW_SAFE_FREE_STRING(pszFreeGroupName);
return dwError;
error:
*ppResult = NULL;
ADCacheSafeFreeObject(&pResult);
goto cleanup;
}
DWORD
AD_FindGroupObjectByName(
IN HANDLE hProvider,
IN PCSTR pszGroupName,
OUT PLSA_SECURITY_OBJECT* ppResult
)
{
DWORD dwError = 0;
PSTR pszLocalGroupName = NULL;
PLSA_LOGIN_NAME_INFO pGroupNameInfo = NULL;
PLSA_SECURITY_OBJECT pResult = NULL;
if (!strcasecmp(pszGroupName, "root"))
{
dwError = LW_ERROR_NO_SUCH_GROUP;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_FindGroupObjectByNameInternal(
hProvider,
pszGroupName,
&pResult);
if (dwError == LW_ERROR_NO_SUCH_GROUP &&
AD_ShouldAssumeDefaultDomain())
{
dwError = LsaCrackDomainQualifiedName(
pszGroupName,
gpADProviderData->szDomain,
&pGroupNameInfo);
BAIL_ON_LSA_ERROR(dwError);
if (pGroupNameInfo->nameType == NameType_Alias)
{
dwError = ADGetDomainQualifiedString(
gpADProviderData->szShortDomain,
pszGroupName,
&pszLocalGroupName);
BAIL_ON_LSA_ERROR(dwError);
dwError = AD_FindGroupObjectByNameInternal(
hProvider,
pszLocalGroupName,
&pResult);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = LW_ERROR_NO_SUCH_GROUP;
BAIL_ON_LSA_ERROR(dwError);
}
}
else
{
BAIL_ON_LSA_ERROR(dwError);
}
*ppResult = pResult;
cleanup:
LW_SAFE_FREE_STRING(pszLocalGroupName);
if (pGroupNameInfo)
{
LsaFreeNameInfo(pGroupNameInfo);
}
return dwError;
error:
*ppResult = NULL;
ADCacheSafeFreeObject(&pResult);
goto cleanup;
}
static
VOID
AD_FilterBuiltinObjects(
IN DWORD dwCount,
PLSA_SECURITY_OBJECT* ppObjects
)
{
DWORD dwIndex = 0;
for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
{
if (ppObjects[dwIndex] &&
AdIsSpecialDomainSidPrefix(ppObjects[dwIndex]->pszObjectSid))
{
ADCacheSafeFreeObject(&ppObjects[dwIndex]);
}
}
}
DWORD
AD_UpdateObject(
IN OUT PLSA_SECURITY_OBJECT pObject
)
{
DWORD dwError = LW_ERROR_SUCCESS;
struct timeval current_tv = {0};
UINT64 u64current_NTtime = 0;
switch(pObject->type)
{
case LSA_OBJECT_TYPE_USER:
if (gettimeofday(¤t_tv, NULL) < 0)
{
dwError = errno;
BAIL_ON_LSA_ERROR(dwError);
}
ADConvertTimeUnix2Nt(current_tv.tv_sec,
&u64current_NTtime);
if (pObject->userInfo.bIsAccountInfoKnown)
{
if (pObject->userInfo.qwAccountExpires != 0LL &&
pObject->userInfo.qwAccountExpires != 9223372036854775807LL &&
u64current_NTtime >= pObject->userInfo.qwAccountExpires)
{
pObject->userInfo.bAccountExpired = TRUE;
}
pObject->userInfo.qwMaxPwdAge = gpADProviderData->adMaxPwdAge;
if ((!pObject->userInfo.bPasswordNeverExpires &&
pObject->userInfo.qwPwdExpires != 0 &&
u64current_NTtime >= pObject->userInfo.qwPwdExpires) ||
pObject->userInfo.qwPwdLastSet == 0)
{
//password is expired already
pObject->userInfo.bPasswordExpired = TRUE;
}
}
if (!pObject->userInfo.pszUnixName)
{
dwError = ADMarshalGetCanonicalName(pObject, &pObject->userInfo.pszUnixName);
BAIL_ON_LSA_ERROR(dwError);
}
break;
case LSA_OBJECT_TYPE_GROUP:
if (!pObject->groupInfo.pszUnixName)
{
dwError = ADMarshalGetCanonicalName(pObject, &pObject->groupInfo.pszUnixName);
BAIL_ON_LSA_ERROR(dwError);
}
break;
default:
break;
}
cleanup:
return dwError;
error:
goto cleanup;
}
static
DWORD
AD_UpdateObjects(
IN DWORD dwCount,
IN OUT PLSA_SECURITY_OBJECT* ppObjects)
{
DWORD dwError = 0;
DWORD dwIndex = 0;
for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
{
if (ppObjects[dwIndex])
{
dwError = AD_UpdateObject(ppObjects[dwIndex]);
BAIL_ON_LSA_ERROR(dwError);
}
}
error:
return dwError;
}
DWORD
AD_FindObjects(
IN HANDLE hProvider,
IN LSA_FIND_FLAGS FindFlags,
IN OPTIONAL LSA_OBJECT_TYPE ObjectType,
IN LSA_QUERY_TYPE QueryType,
IN DWORD dwCount,
IN LSA_QUERY_LIST QueryList,
OUT PLSA_SECURITY_OBJECT** pppObjects
)
{
DWORD dwError = 0;
PLSA_SECURITY_OBJECT* ppObjects = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = AD_OfflineFindObjects(
hProvider,
FindFlags,
ObjectType,
QueryType,
dwCount,
QueryList,
&ppObjects);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = AD_OnlineFindObjects(
hProvider,
FindFlags,
ObjectType,
QueryType,
dwCount,
QueryList,
&ppObjects);
BAIL_ON_LSA_ERROR(dwError);
}
if (ppObjects)
{
dwError = AD_UpdateObjects(dwCount, ppObjects);
BAIL_ON_LSA_ERROR(dwError);
AD_FilterBuiltinObjects(dwCount, ppObjects);
}
*pppObjects = ppObjects;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
*pppObjects = NULL;
if (ppObjects)
{
LsaUtilFreeSecurityObjectList(dwCount, ppObjects);
}
goto cleanup;
}
DWORD
AD_OpenEnumObjects(
IN HANDLE hProvider,
OUT PHANDLE phEnum,
IN LSA_FIND_FLAGS FindFlags,
IN LSA_OBJECT_TYPE ObjectType,
IN OPTIONAL PCSTR pszDomainName
)
{
DWORD dwError = 0;
PAD_ENUM_HANDLE pEnum = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LwAllocateMemory(sizeof(*pEnum), OUT_PPVOID(&pEnum));
BAIL_ON_LSA_ERROR(dwError);
pEnum->Type = AD_ENUM_HANDLE_OBJECTS;
pEnum->FindFlags = FindFlags;
pEnum->ObjectType = ObjectType;
if (ObjectType == LSA_OBJECT_TYPE_UNDEFINED)
{
pEnum->CurrentObjectType = LSA_OBJECT_TYPE_USER;
}
else
{
pEnum->CurrentObjectType = ObjectType;
}
LwInitCookie(&pEnum->Cookie);
*phEnum = pEnum;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
*phEnum = NULL;
if (pEnum)
{
AD_CloseEnum(pEnum);
}
goto cleanup;
}
DWORD
AD_EnumObjects(
IN HANDLE hEnum,
IN DWORD dwMaxObjectsCount,
OUT PDWORD pdwObjectsCount,
OUT PLSA_SECURITY_OBJECT** pppObjects
)
{
DWORD dwError = 0;
PLSA_SECURITY_OBJECT* ppObjects = NULL;
DWORD dwObjectsCount = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = AD_OnlineEnumObjects(
hEnum,
dwMaxObjectsCount,
&dwObjectsCount,
&ppObjects);
BAIL_ON_LSA_ERROR(dwError);
}
dwError = AD_UpdateObjects(dwObjectsCount, ppObjects);
BAIL_ON_LSA_ERROR(dwError);
*pdwObjectsCount = dwObjectsCount;
*pppObjects = ppObjects;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
*pdwObjectsCount = 0;
*pppObjects = NULL;
if (ppObjects)
{
LsaUtilFreeSecurityObjectList(dwObjectsCount, ppObjects);
}
goto cleanup;
}
DWORD
AD_OpenEnumMembers(
IN HANDLE hProvider,
OUT PHANDLE phEnum,
IN LSA_FIND_FLAGS FindFlags,
IN PCSTR pszSid
)
{
DWORD dwError = 0;
PAD_ENUM_HANDLE pEnum = NULL;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AdIsSpecialDomainSidPrefix(pszSid))
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LwAllocateMemory(sizeof(*pEnum), OUT_PPVOID(&pEnum));
BAIL_ON_LSA_ERROR(dwError);
pEnum->Type = AD_ENUM_HANDLE_MEMBERS;
pEnum->FindFlags = FindFlags;
LwInitCookie(&pEnum->Cookie);
if (AD_IsOffline())
{
dwError = AD_OfflineGetGroupMemberSids(
hProvider,
FindFlags,
pszSid,
&pEnum->dwSidCount,
&pEnum->ppszSids);
BAIL_ON_LSA_ERROR(dwError);
}
else
{
dwError = AD_OnlineGetGroupMemberSids(
hProvider,
FindFlags,
pszSid,
&pEnum->dwSidCount,
&pEnum->ppszSids);
BAIL_ON_LSA_ERROR(dwError);
}
*phEnum = pEnum;
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
*phEnum = NULL;
if (pEnum)
{
AD_CloseEnum(pEnum);
}
goto cleanup;
}
DWORD
AD_EnumMembers(
IN HANDLE hEnum,
IN DWORD dwMaxMemberSidCount,
OUT PDWORD pdwMemberSidCount,
OUT PSTR** pppszMemberSids
)
{
DWORD dwError = 0;
PAD_ENUM_HANDLE pEnum = hEnum;
DWORD dwMemberSidCount = dwMaxMemberSidCount;
PSTR* ppszMemberSids = NULL;
if (dwMemberSidCount > pEnum->dwSidCount - pEnum->dwSidIndex)
{
dwMemberSidCount = pEnum->dwSidCount - pEnum->dwSidIndex;
}
if (dwMemberSidCount == 0)
{
dwError = ERROR_NO_MORE_ITEMS;
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LwAllocateMemory(
sizeof(*ppszMemberSids) * dwMemberSidCount,
OUT_PPVOID(&ppszMemberSids));
BAIL_ON_LSA_ERROR(dwError);
memcpy(ppszMemberSids, &pEnum->ppszSids[pEnum->dwSidIndex], sizeof(*ppszMemberSids) * dwMemberSidCount);
memset(&pEnum->ppszSids[pEnum->dwSidIndex], 0, sizeof(*ppszMemberSids) * dwMemberSidCount);
pEnum->dwSidIndex += dwMemberSidCount;
*pdwMemberSidCount = dwMemberSidCount;
*pppszMemberSids = ppszMemberSids;
cleanup:
return dwError;
error:
if (ppszMemberSids)
{
LwFreeStringArray(ppszMemberSids, dwMemberSidCount);
}
goto cleanup;
}
DWORD
AD_QueryMemberOf(
IN HANDLE hProvider,
IN LSA_FIND_FLAGS FindFlags,
IN DWORD dwSidCount,
IN PSTR* ppszSids,
OUT PDWORD pdwGroupSidCount,
OUT PSTR** pppszGroupSids
)
{
DWORD dwError = 0;
LsaAdProviderStateAcquireRead(gpLsaAdProviderState);
if (gpLsaAdProviderState->joinState != LSA_AD_JOINED ||
FindFlags & LSA_FIND_FLAGS_LOCAL)
{
dwError = LW_ERROR_NOT_HANDLED;
BAIL_ON_LSA_ERROR(dwError);
}
if (AD_IsOffline())
{
dwError = AD_OfflineQueryMemberOf(
hProvider,
FindFlags,
dwSidCount,
ppszSids,
pdwGroupSidCount,
pppszGroupSids);
}
else
{
dwError = AD_OnlineQueryMemberOf(
hProvider,
FindFlags,
dwSidCount,
ppszSids,
pdwGroupSidCount,
pppszGroupSids);
}
cleanup:
LsaAdProviderStateRelease(gpLsaAdProviderState);
return dwError;
error:
goto cleanup;
}
VOID
AD_CloseEnum(
IN OUT HANDLE hEnum
)
{
PAD_ENUM_HANDLE pEnum = hEnum;
if (pEnum)
{
LwFreeCookieContents(&pEnum->Cookie);
if (pEnum->ppszSids)
{
LwFreeStringArray(pEnum->ppszSids, pEnum->dwSidCount);
}
LwFreeMemory(pEnum);
}
}
DWORD
AD_InitializeOperatingMode(
IN PCSTR pszDomain,
IN PCSTR pszHostName,
IN BOOLEAN bIsDomainOffline
)
{
DWORD dwError = LW_ERROR_SUCCESS;
PAD_PROVIDER_DATA pProviderData = NULL;
if (bIsDomainOffline || AD_IsOffline())
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
}
else
{
dwError = AD_OnlineInitializeOperatingMode(
&pProviderData,
pszDomain,
pszHostName);
}
// If we are offline, do the offline case
if (LW_ERROR_DOMAIN_IS_OFFLINE == dwError)
{
dwError = AD_OfflineInitializeOperatingMode(
&pProviderData,
pszDomain,
pszHostName);
BAIL_ON_LSA_ERROR(dwError);
if (bIsDomainOffline)
{
// The domain was originally offline, so we need to
// tell the domain manager about it.
// Note that we can only transition offline
// now that we set up the domains in the domain manager.
dwError = LsaDmTransitionOffline(pszDomain, FALSE);
BAIL_ON_LSA_ERROR(dwError);
}
}
else
{
// check whether we failed for some other reason.
BAIL_ON_LSA_ERROR(dwError);
}
gpADProviderData = pProviderData;
cleanup:
return dwError;
error:
// Note that gpADProviderData will already be NULL.
if (pProviderData)
{
ADProviderFreeProviderData(pProviderData);
pProviderData = NULL;
}
goto cleanup;
}
static
DWORD
LsaAdProviderStateCreate(
OUT PLSA_AD_PROVIDER_STATE* ppState
)
{
DWORD dwError = 0;
PLSA_AD_PROVIDER_STATE pState = NULL;
dwError = LwAllocateMemory(sizeof(*pState), (PVOID)&pState);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwMapErrnoToLwError(pthread_mutex_init(&pState->MachineCreds.Mutex, NULL));
BAIL_ON_LSA_ERROR(dwError);
pState->MachineCreds.pMutex = &pState->MachineCreds.Mutex;
dwError = AD_InitializeConfig(&pState->config);
BAIL_ON_LSA_ERROR(dwError);
pState->dwMaxAllowedClockDriftSeconds = AD_MAX_ALLOWED_CLOCK_DRIFT_SECONDS;
dwError = LwMapErrnoToLwError(pthread_rwlock_init(&pState->stateLock, NULL));
BAIL_ON_LSA_ERROR(dwError);
pState->pStateLock = &pState->stateLock;
*ppState = pState;
cleanup:
return dwError;
error:
LsaAdProviderStateDestroy(pState);
*ppState = NULL;
goto cleanup;
}
static
VOID
LsaAdProviderStateDestroy(
IN OUT PLSA_AD_PROVIDER_STATE pState
)
{
if (pState)
{
ADCacheSafeClose(&pState->hCacheConnection);
ADState_SafeCloseDb(&pState->hStateConnection);
if (pState->MediaSenseHandle)
{
MediaSenseStop(&pState->MediaSenseHandle);
pState->MediaSenseHandle = NULL;
}
if (pState->MachineCreds.pMutex)
{
pthread_mutex_destroy(pState->MachineCreds.pMutex);
pState->MachineCreds.pMutex = NULL;
}
AD_FreeConfigContents(&pState->config);
if (pState->pStateLock)
{
pthread_rwlock_destroy(pState->pStateLock);
}
LwFreeMemory(pState);
}
}
static
VOID
LsaAdProviderStateAcquireRead(
PLSA_AD_PROVIDER_STATE pState
)
{
LW_ASSERT(pthread_rwlock_rdlock(pState->pStateLock) == 0);
}
static
VOID
LsaAdProviderStateAcquireWrite(
PLSA_AD_PROVIDER_STATE pState
)
{
LW_ASSERT(pthread_rwlock_wrlock(pState->pStateLock) == 0);
}
static
void
LsaAdProviderStateRelease(
PLSA_AD_PROVIDER_STATE pState
)
{
LW_ASSERT(pthread_rwlock_unlock(pState->pStateLock) == 0);
}
static
DWORD
AD_MachineCredentialsCacheClear()
{
DWORD dwError = 0;
BOOLEAN bInLock = FALSE;
pthread_mutex_lock(gpLsaAdProviderState->MachineCreds.pMutex);
bInLock = TRUE;
if (gpLsaAdProviderState->MachineCreds.bIsInitialized)
{
dwError = LwKrb5CleanupMachineSession();
BAIL_ON_LSA_ERROR(dwError);
gpLsaAdProviderState->MachineCreds.bIsInitialized = FALSE;
}
error:
if (bInLock)
{
pthread_mutex_unlock(gpLsaAdProviderState->MachineCreds.pMutex);
}
return dwError;
}
static
BOOLEAN
AD_MachineCredentialsCacheIsInitialized(
VOID
)
{
BOOLEAN bIsInitialized = FALSE;
pthread_mutex_lock(gpLsaAdProviderState->MachineCreds.pMutex);
bIsInitialized = gpLsaAdProviderState->MachineCreds.bIsInitialized;
pthread_mutex_unlock(gpLsaAdProviderState->MachineCreds.pMutex);
return bIsInitialized;
}
DWORD
AD_MachineCredentialsCacheInitialize(
VOID
)
{
DWORD dwError = 0;
BOOLEAN bIsAcquired = FALSE;
PSTR pszHostname = NULL;
PSTR pszUsername = NULL;
PSTR pszPassword = NULL;
PSTR pszDomainDnsName = NULL;
PSTR pszHostDnsDomain = NULL;
DWORD dwGoodUntilTime = 0;
// Check before doing any work.
if (AD_MachineCredentialsCacheIsInitialized())
{
goto cleanup;
}
dwError = LsaDnsGetHostInfo(&pszHostname);
BAIL_ON_LSA_ERROR(dwError);
LwStrToUpper(pszHostname);
// Read password info before acquiring the lock.
dwError = LwKrb5GetMachineCreds(
&pszUsername,
&pszPassword,
&pszDomainDnsName,
&pszHostDnsDomain);
BAIL_ON_LSA_ERROR(dwError);
if (LsaDmIsDomainOffline(pszDomainDnsName))
{
dwError = LW_ERROR_DOMAIN_IS_OFFLINE;
BAIL_ON_LSA_ERROR(dwError);
}
pthread_mutex_lock(gpLsaAdProviderState->MachineCreds.pMutex);
bIsAcquired = TRUE;
// Verify that state did not change now that we have the lock.
if (gpLsaAdProviderState->MachineCreds.bIsInitialized)
{
goto cleanup;
}
ADSyncTimeToDC(pszDomainDnsName);
dwError = LwKrb5SetProcessDefaultCachePath(LSASS_CACHE_PATH);
BAIL_ON_LSA_ERROR(dwError);
dwError = LwSetupMachineSession(
pszUsername,
pszPassword,
pszDomainDnsName,
pszHostDnsDomain,
&dwGoodUntilTime);
if (dwError)
{
if (dwError == LW_ERROR_DOMAIN_IS_OFFLINE)
{
LsaDmTransitionOffline(pszDomainDnsName, FALSE);
}
ADSetMachineTGTExpiryError();
}
BAIL_ON_LSA_ERROR(dwError);
ADSetMachineTGTExpiry(dwGoodUntilTime);
gpLsaAdProviderState->MachineCreds.bIsInitialized = TRUE;
cleanup:
if (bIsAcquired)
{
pthread_mutex_unlock(gpLsaAdProviderState->MachineCreds.pMutex);
}
LW_SAFE_FREE_STRING(pszHostname);
LW_SAFE_FREE_STRING(pszUsername);
LW_SAFE_CLEAR_FREE_STRING(pszPassword);
LW_SAFE_FREE_STRING(pszDomainDnsName);
LW_SAFE_FREE_STRING(pszHostDnsDomain);
return dwError;
error:
goto cleanup;
}
static
VOID
LsaAdProviderMediaSenseTransitionCallback(
IN PVOID Context,
IN BOOLEAN bIsOffline
)
{
if (bIsOffline)
{
LsaDmMediaSenseOffline();
}
else
{
LsaDmMediaSenseOnline();
}
}
static
VOID
LsaAdProviderLogServiceStartEvent(
PCSTR pszHostname,
PCSTR pszDomainDnsName,
BOOLEAN bIsDomainOffline,
DWORD dwErrCode
)
{
DWORD dwError = 0;
PSTR pszDescription = NULL;
PSTR pszData = NULL;
PLWNET_DC_INFO pDCInfo = NULL;
PLWNET_DC_INFO pGCDCInfo = NULL;
dwError = LWNetGetDCName(
NULL,
pszDomainDnsName,
NULL,
DS_BACKGROUND_ONLY,
&pDCInfo);
if (pDCInfo)
{
dwError = LWNetGetDCName(
NULL,
pDCInfo->pszDnsForestName,
NULL,
DS_GC_SERVER_REQUIRED,
&pGCDCInfo);
}
dwError = LwAllocateStringPrintf(
&pszDescription,
"Likewise authentication service provider initialization %s.\r\n\r\n" \
" Authentication provider: %s\r\n\r\n" \
" Hostname: %s\r\n" \
" Domain: %s\r\n" \
" Current Domain Controller: %s\r\n" \
" Current Global Catalog: %s\r\n" \
" Offline Startup: %s",
dwErrCode ? "failed" : "succeeded",
LSA_SAFE_LOG_STRING(gpszADProviderName),
LSA_SAFE_LOG_STRING(pszHostname),
LSA_SAFE_LOG_STRING(pszDomainDnsName),
(pDCInfo) ? LSA_SAFE_LOG_STRING(pDCInfo->pszDomainControllerName) : "(Unknown)" ,
(pGCDCInfo) ? LSA_SAFE_LOG_STRING(pGCDCInfo->pszDomainControllerName) : "(Unknown)" ,
bIsDomainOffline ? "Yes" : "No");
BAIL_ON_LSA_ERROR(dwError);
if (dwErrCode)
{
dwError = LsaGetErrorMessageForLoggingEvent(
dwErrCode,
&pszData);
BAIL_ON_LSA_ERROR(dwError);
LsaSrvLogServiceFailureEvent(
LSASS_EVENT_FAILED_PROVIDER_INITIALIZATION,
SERVICE_EVENT_CATEGORY,
pszDescription,
pszData);
}
else
{
LsaSrvLogServiceSuccessEvent(
LSASS_EVENT_SUCCESSFUL_PROVIDER_INITIALIZATION,
SERVICE_EVENT_CATEGORY,
pszDescription,
NULL);
}
cleanup:
LW_SAFE_FREE_STRING(pszDescription);
LW_SAFE_FREE_STRING(pszData);
LWNET_SAFE_FREE_DC_INFO(pDCInfo);
LWNET_SAFE_FREE_DC_INFO(pGCDCInfo);
return;
error:
goto cleanup;
}
static
VOID
LsaAdProviderLogConfigReloadEvent(
VOID
)
{
DWORD dwError = 0;
PSTR pszDescription = NULL;
PSTR pszMemberList = NULL;
PDLINKEDLIST pIter = NULL;
for (pIter = gpLsaAdProviderState->config.pUnresolvedMemberList;
pIter;
pIter = pIter->pNext)
{
PSTR pszNewMemberList = NULL;
dwError = LwAllocateStringPrintf(
&pszNewMemberList,
"%s %s\r\n",
pszMemberList ? pszMemberList : "",
LSA_SAFE_LOG_STRING((PSTR)pIter->pItem));
BAIL_ON_LSA_ERROR(dwError);
LW_SAFE_FREE_STRING(pszMemberList);
pszMemberList = pszNewMemberList;
pszNewMemberList = NULL;
}
dwError = LwAllocateStringPrintf(
&pszDescription,
"Likewise authentication service provider configuration settings have been reloaded.\r\n\r\n" \
" Authentication provider: %s\r\n" \
" Current settings are...\r\n" \
" Cache reaper timeout (secs): %d\r\n" \
" Cache entry expiry (secs): %d\r\n" \
" Space replacement character: '%c'\r\n" \
" Domain separator character: '%c'\r\n" \
" Enable event log: %s\r\n" \
" Logon membership requirements: \r\n%s" \
" Log network connection events: %s\r\n" \
" Create K5Login file: %s\r\n" \
" Create home directory: %s\r\n" \
" Sign and seal LDAP traffic: %s\r\n" \
" Assume default domain: %s\r\n" \
" Sync system time: %s\r\n" \
" Refresh user credentials: %s\r\n" \
" Machine password sync lifetime: %d\r\n" \
" Default Shell: %s\r\n" \
" Default home directory prefix: %s\r\n" \
" Home directory template: %s\r\n" \
" Umask: %d\r\n" \
" Skeleton directory: %s\r\n" \
" Cell support: %s\r\n" \
" Trim user membership: %s\r\n" \
" NSS group members from cache only: %s\r\n" \
" NSS user members from cache only: %s\r\n" \
" NSS enumeration enabled: %s\r\n"
" Domain Manager check domain online (secs): %d\r\n"
" Domain Manager unknown domain cache timeout (secs): %d",
LSA_SAFE_LOG_STRING(gpszADProviderName),
gpLsaAdProviderState->config.dwCacheReaperTimeoutSecs,
gpLsaAdProviderState->config.dwCacheEntryExpirySecs,
gpLsaAdProviderState->config.chSpaceReplacement,
gpLsaAdProviderState->config.chDomainSeparator,
gpLsaAdProviderState->config.bEnableEventLog ? "true" : "false",
pszMemberList ? pszMemberList : " \r\n",
gpLsaAdProviderState->config.bShouldLogNetworkConnectionEvents ? "true" : "false",
gpLsaAdProviderState->config.bCreateK5Login ? "true" : "false",
gpLsaAdProviderState->config.bCreateHomeDir ? "true" : "false",
gpLsaAdProviderState->config.bLDAPSignAndSeal ? "true" : "false",
gpLsaAdProviderState->config.bAssumeDefaultDomain ? "true" : "false",
gpLsaAdProviderState->config.bSyncSystemTime ? "true" : "false",
gpLsaAdProviderState->config.bRefreshUserCreds ? "true" : "false",
gpLsaAdProviderState->config.dwMachinePasswordSyncLifetime,
LSA_SAFE_LOG_STRING(gpLsaAdProviderState->config.pszShell),
LSA_SAFE_LOG_STRING(gpLsaAdProviderState->config.pszHomedirPrefix),
LSA_SAFE_LOG_STRING(gpLsaAdProviderState->config.pszHomedirTemplate),
gpLsaAdProviderState->config.dwUmask,
LSA_SAFE_LOG_STRING(gpLsaAdProviderState->config.pszSkelDirs),
gpLsaAdProviderState->config.CellSupport == AD_CELL_SUPPORT_UNINITIALIZED ? "Uninitialized" :
gpLsaAdProviderState->config.CellSupport == AD_CELL_SUPPORT_FULL ? "Full" :
gpLsaAdProviderState->config.CellSupport == AD_CELL_SUPPORT_FILE ? "File" :
gpLsaAdProviderState->config.CellSupport == AD_CELL_SUPPORT_UNPROVISIONED ? "Unprovisioned" : "Invalid",
gpLsaAdProviderState->config.bTrimUserMembershipEnabled ? "true" : "false",
gpLsaAdProviderState->config.bNssGroupMembersCacheOnlyEnabled ? "true" : "false",
gpLsaAdProviderState->config.bNssUserMembershipCacheOnlyEnabled ? "true" : "false",
gpLsaAdProviderState->config.bNssEnumerationEnabled ? "true" : "false",
gpLsaAdProviderState->config.DomainManager.dwCheckDomainOnlineSeconds,
gpLsaAdProviderState->config.DomainManager.dwUnknownDomainCacheTimeoutSeconds);
BAIL_ON_LSA_ERROR(dwError);
LsaSrvLogServiceSuccessEvent(
LSASS_EVENT_INFO_SERVICE_CONFIGURATION_CHANGED,
SERVICE_EVENT_CATEGORY,
pszDescription,
NULL);
cleanup:
LW_SAFE_FREE_STRING(pszDescription);
LW_SAFE_FREE_STRING(pszMemberList);
return;
error:
goto cleanup;
}
static
VOID
LsaAdProviderLogRequireMembershipOfChangeEvent(
HANDLE hProvider
)
{
DWORD dwError = 0;
PSTR pszDescription = NULL;
PLSA_HASH_TABLE pAllowedMemberList = NULL;
LSA_HASH_ITERATOR hashIterator = {0};
LSA_HASH_ENTRY *pHashEntry = NULL;
PSTR pszMemberList = NULL;
DWORD i = 0;
dwError = AD_ResolveConfiguredLists(
hProvider,
&pAllowedMemberList);
BAIL_ON_LSA_ERROR(dwError);
if (pAllowedMemberList != NULL)
{
dwError = LsaHashGetIterator(pAllowedMemberList, &hashIterator);
BAIL_ON_LSA_ERROR(dwError);
for (i = 0; (pHashEntry = LsaHashNext(&hashIterator)) != NULL; i++)
{
PSTR pszNewMemberList = NULL;
dwError = LwAllocateStringPrintf(
&pszNewMemberList,
"%s %s\r\n",
pszMemberList ? pszMemberList : "",
LSA_SAFE_LOG_STRING(pHashEntry->pValue));
BAIL_ON_LSA_ERROR(dwError);
LW_SAFE_FREE_STRING(pszMemberList);
pszMemberList = pszNewMemberList;
pszNewMemberList = NULL;
}
}
else
{
dwError = LwAllocateStringPrintf(
&pszMemberList,
" \r\n");
BAIL_ON_LSA_ERROR(dwError);
}
dwError = LwAllocateStringPrintf(
&pszDescription,
"Likewise authentication service provider login restriction settings have been reloaded.\r\n\r\n" \
" Authentication provider: %s\r\n" \
" Current settings are...\r\n" \
" require-membership-of:\r\n%s",
LSA_SAFE_LOG_STRING(gpszADProviderName),
LSA_SAFE_LOG_STRING(pszMemberList));
BAIL_ON_LSA_ERROR(dwError);
LsaSrvLogServiceSuccessEvent(
LSASS_EVENT_INFO_REQUIRE_MEMBERSHIP_OF_UPDATED,
SERVICE_EVENT_CATEGORY,
pszDescription,
NULL);
cleanup:
LW_SAFE_FREE_STRING(pszDescription);
LW_SAFE_FREE_STRING(pszMemberList);
LsaHashSafeFree(&pAllowedMemberList);
return;
error:
goto cleanup;
}
static
VOID
LsaAdProviderLogEventLogEnableChangeEvent(
VOID
)
{
DWORD dwError = 0;
PSTR pszDescription = NULL;
dwError = LwAllocateStringPrintf(
&pszDescription,
"Likewise authentication service provider auditing settings have been updated.\r\n\r\n" \
" Authentication provider: %s\r\n" \
" Current settings are...\r\n" \
" Enable event log: %s\r\n",
LSA_SAFE_LOG_STRING(gpszADProviderName),
gpLsaAdProviderState->config.bEnableEventLog ? "true" : "false");
BAIL_ON_LSA_ERROR(dwError);
LsaSrvLogServiceSuccessEvent(
gpLsaAdProviderState->config.bEnableEventLog ?
LSASS_EVENT_INFO_AUDITING_CONFIGURATION_ENABLED :
LSASS_EVENT_INFO_AUDITING_CONFIGURATION_DISABLED,
SERVICE_EVENT_CATEGORY,
pszDescription,
NULL);
cleanup:
LW_SAFE_FREE_STRING(pszDescription);
return;
error:
goto cleanup;
}
static
DWORD
AD_ResolveConfiguredLists(
HANDLE hProvider,
PLSA_HASH_TABLE *ppAllowedMemberList
)
{
DWORD dwError = 0;
DWORD iMember = 0;
PSTR* ppszMembers = 0;
DWORD dwNumMembers = 0;
PLSA_HASH_TABLE pAllowedMemberList = NULL;
PLSA_SECURITY_OBJECT pGroupInfo = NULL;
PLSA_SECURITY_IDENTIFIER pSID = NULL;
PLSA_SECURITY_OBJECT* ppObjects = NULL;
LSA_QUERY_LIST QueryList;
LSA_QUERY_TYPE QueryType = 0;
PLSA_LOGIN_NAME_INFO pLoginInfo = NULL;
dwError = AD_GetMemberLists(
&ppszMembers,
&dwNumMembers,
&pAllowedMemberList);
BAIL_ON_LSA_ERROR(dwError);
for (iMember = 0; iMember < dwNumMembers; iMember++)
{
PSTR pszMember = *(ppszMembers + iMember);
LSA_LOG_VERBOSE("Resolving entry [%s] for restricted login", pszMember);
if (AD_STR_IS_SID(pszMember))
{
dwError = LsaAllocSecurityIdentifierFromString(
pszMember,
&pSID);
if (dwError)
{
LSA_LOG_ERROR("Removing invalid SID entry [%s] from required membership list", pszMember);
AD_DeleteFromMembersList(pszMember);
}
else
{
LSA_LOG_VERBOSE("Adding entry to allow login for SID [%s]", pszMember);
dwError = AD_AddAllowedMember(
pszMember,
pszMember,
&pAllowedMemberList);
BAIL_ON_LSA_ERROR(dwError);
if (pSID)
{
LsaFreeSecurityIdentifier(pSID);
pSID = NULL;
}
}
}
else // User or Group Name
{
dwError = LsaCrackDomainQualifiedName(
pszMember,
gpADProviderData->szDomain,
&pLoginInfo);
BAIL_ON_LSA_ERROR(dwError);
switch (pLoginInfo->nameType)
{
case NameType_NT4:
QueryType = LSA_QUERY_TYPE_BY_NT4;
break;
case NameType_Alias:
QueryType = LSA_QUERY_TYPE_BY_ALIAS;
break;
case NameType_UPN:
QueryType = LSA_QUERY_TYPE_BY_UPN;
break;
default:
dwError = LW_ERROR_INVALID_PARAMETER;
BAIL_ON_LSA_ERROR(dwError);
}
LsaFreeNameInfo(pLoginInfo);
pLoginInfo = NULL;
QueryList.ppszStrings = (PCSTR*) &pszMember;
dwError = AD_FindObjects(
hProvider,
0,
LSA_OBJECT_TYPE_UNDEFINED,
QueryType,
1,
QueryList,
&ppObjects);
BAIL_ON_LSA_ERROR(dwError);
if (!ppObjects[0] || !ppObjects[0]->enabled ||
(ppObjects[0]->type != LSA_OBJECT_TYPE_USER &&
ppObjects[0]->type != LSA_OBJECT_TYPE_GROUP))
{
LSA_LOG_WARNING("Restricted login list - couldn't resolve %s [%u]",
pszMember, LW_ERROR_NO_SUCH_OBJECT);
}
else if (ppObjects[0]->type == LSA_OBJECT_TYPE_USER)
{
LSA_LOG_VERBOSE("Adding entry to allow login for user [%s]", pszMember);
dwError = AD_AddAllowedMember(
ppObjects[0]->pszObjectSid,
pszMember,
&pAllowedMemberList);
BAIL_ON_LSA_ERROR(dwError);
}
else if (ppObjects[0]->type == LSA_OBJECT_TYPE_GROUP)
{
LSA_LOG_VERBOSE("Adding entry to allow login for group [%s]", pszMember);
dwError = AD_AddAllowedMember(
ppObjects[0]->pszObjectSid,
pszMember,
&pAllowedMemberList);
BAIL_ON_LSA_ERROR(dwError);
}
}
}
*ppAllowedMemberList = (PVOID)pAllowedMemberList;
cleanup:
LsaUtilFreeSecurityObjectList(1, ppObjects);
if (pLoginInfo)
{
LsaFreeNameInfo(pLoginInfo);
}
if (ppszMembers)
{
LwFreeStringArray(ppszMembers, dwNumMembers);
}
if (pSID)
{
LsaFreeSecurityIdentifier(pSID);
}
ADCacheSafeFreeObject(&pGroupInfo);
return dwError;
error:
*ppAllowedMemberList = NULL;
LsaHashSafeFree(&pAllowedMemberList);
goto cleanup;
}
void
InitADCacheFunctionTable(
PADCACHE_PROVIDER_FUNCTION_TABLE pCacheProviderTable
)
{
switch (gpLsaAdProviderState->config.CacheBackend)
{
default:
LSA_LOG_DEBUG("Unknown cache backend. Switching to default");
#ifdef AD_CACHE_ENABLE_SQLITE
case AD_CACHE_SQLITE:
InitializeDbCacheProvider(
pCacheProviderTable
);
break;
#endif
case AD_CACHE_IN_MEMORY:
InitializeMemCacheProvider(
pCacheProviderTable
);
break;
}
}
DWORD
LsaInitializeProvider2(
OUT PCSTR* ppszProviderName,
OUT PLSA_PROVIDER_FUNCTION_TABLE_2* ppFunctionTable
)
{
return AD_InitializeProvider(ppszProviderName, ppFunctionTable);
}
/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/