void LsaFreeGroupModInfo2( PLSA_GROUP_MOD_INFO_2 pGroupModInfo ) { LW_SAFE_FREE_STRING(pGroupModInfo->pszSid); LwFreeStringArray(pGroupModInfo->ppszAddMembers, pGroupModInfo->dwAddMembersNum); LwFreeStringArray(pGroupModInfo->ppszRemoveMembers, pGroupModInfo->dwRemoveMembersNum); LwFreeMemory(pGroupModInfo); }
VOID AD_FreeConfigContents( PLSA_AD_CONFIG pConfig ) { LW_SAFE_FREE_STRING(pConfig->pszHomedirPrefix); LW_SAFE_FREE_STRING(pConfig->pszHomedirTemplate); LW_SAFE_FREE_STRING(pConfig->pszRemoteHomeDirTemplate); LW_SAFE_FREE_STRING(pConfig->pszShell); LW_SAFE_FREE_STRING(pConfig->pszSkelDirs); LW_SAFE_FREE_MEMORY(pConfig->pszaIgnoreUserNameList); LW_SAFE_FREE_MEMORY(pConfig->pszaIgnoreGroupNameList); LW_SAFE_FREE_STRING(pConfig->pszUserDomainPrefix); if (pConfig->pUnresolvedMemberList) { LwDLinkedListForEach( pConfig->pUnresolvedMemberList, &AD_FreeConfigMemberInList, NULL); LwDLinkedListFree(pConfig->pUnresolvedMemberList); pConfig->pUnresolvedMemberList = NULL; } LwFreeStringArray( pConfig->DomainManager.ppszTrustExceptionList, pConfig->DomainManager.dwTrustExceptionCount); pConfig->DomainManager.ppszTrustExceptionList = NULL; pConfig->DomainManager.dwTrustExceptionCount = 0; }
static DWORD AD_ConvertMultiStringToStringArray( IN PCSTR pszMultiString, OUT PSTR** pppszStringArray, OUT PDWORD pdwCount ) { DWORD dwError = 0; PSTR* ppszStringArray = NULL; DWORD dwCount = 0; PCSTR pszIter = NULL; DWORD dwIndex = 0; dwCount = 0; for (pszIter = pszMultiString; pszIter && *pszIter; pszIter += strlen(pszIter) + 1) { dwCount++; } if (dwCount) { dwError = LwAllocateMemory( dwCount * sizeof(*ppszStringArray), OUT_PPVOID(&ppszStringArray)); BAIL_ON_LSA_ERROR(dwError); } dwIndex = 0; for (pszIter = pszMultiString; pszIter && *pszIter; pszIter += strlen(pszIter) + 1) { dwError = LwAllocateString(pszIter, &ppszStringArray[dwIndex]); BAIL_ON_LSA_ERROR(dwError); dwIndex++; } LSA_ASSERT(dwIndex == dwCount); cleanup: *pppszStringArray = ppszStringArray; *pdwCount = dwCount; return dwError; error: LwFreeStringArray(ppszStringArray, dwCount); ppszStringArray = NULL; dwCount = 0; goto cleanup; }
VOID LwpsLegacyFreeStringArray( IN PSTR* ppszDomainList, IN DWORD dwCount ) { if (ppszDomainList) { LwFreeStringArray(ppszDomainList, dwCount); } }
DWORD LwDuplicateStringArray( PSTR** pppNewStringArray, PDWORD pdwNewCount, PSTR* ppStringArray, DWORD dwCount ) { DWORD dwError = 0; PSTR* ppNewStringArray = NULL; DWORD dwNewCount = 0; if (dwCount) { DWORD i = 0; dwError = LwAllocateMemory( dwCount * sizeof(*ppNewStringArray), OUT_PPVOID(&ppNewStringArray)); BAIL_ON_LW_ERROR(dwError); dwNewCount = dwCount; for (i = 0; i < dwCount; i++) { dwError = LwAllocateString( ppStringArray[i], &ppNewStringArray[i]); BAIL_ON_LW_ERROR(dwError); } } cleanup: *pppNewStringArray = ppNewStringArray; if (pdwNewCount) { *pdwNewCount = dwNewCount; } return dwError; error: LwFreeStringArray(ppNewStringArray, dwNewCount); ppNewStringArray = NULL; dwNewCount = 0; goto cleanup; }
static VOID DestroyQueryListEntry( IN OUT PLSA_AD_QUERY_LISTS_ENTRY* ppEntry ) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = *ppEntry; if (pEntry) { LwFreeStringArray(pEntry->ppszQueryValues, pEntry->dwQueryCount); LwFreeMemory(pEntry); *ppEntry = NULL; } }
DWORD LsaGetMatchingFilePathsInFolder( PCSTR pszDirPath, PCSTR pszFileNameRegExp, PSTR** pppszHostFilePaths, PDWORD pdwNPaths ) { typedef struct __PATHNODE { PSTR pszPath; struct __PATHNODE *pNext; } PATHNODE, *PPATHNODE; DWORD dwError = 0; DIR* pDir = NULL; struct dirent* pDirEntry = NULL; regex_t rx; BOOLEAN rxAllocated = FALSE; regmatch_t* pResult = NULL; size_t nMatch = 1; DWORD dwNPaths = 0; DWORD iPath = 0; PSTR* ppszHostFilePaths = NULL; CHAR szBuf[PATH_MAX+1]; struct stat statbuf; PPATHNODE pPathList = NULL; PPATHNODE pPathNode = NULL; BOOLEAN bDirExists = FALSE; dwError = LsaCheckDirectoryExists(pszDirPath, &bDirExists); BAIL_ON_LSA_ERROR(dwError); if(!bDirExists) { dwError = ERROR_FILE_NOT_FOUND; BAIL_ON_LSA_ERROR(dwError); } if (regcomp(&rx, pszFileNameRegExp, REG_EXTENDED) != 0) { dwError = LW_ERROR_REGEX_COMPILE_FAILED; BAIL_ON_LSA_ERROR(dwError); } rxAllocated = TRUE; dwError = LwAllocateMemory(sizeof(regmatch_t), (PVOID*)&pResult); BAIL_ON_LSA_ERROR(dwError); pDir = opendir(pszDirPath); if (!pDir) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } while ((pDirEntry = readdir(pDir)) != NULL) { int copied = snprintf( szBuf, sizeof(szBuf), "%s/%s", pszDirPath, pDirEntry->d_name); if (copied >= sizeof(szBuf)) { //Skip pathnames that are too long continue; } memset(&statbuf, 0, sizeof(struct stat)); if (lstat(szBuf, &statbuf) < 0) { if(errno == ENOENT) { //This occurs when there is a symbolic link pointing to a //location that doesn't exist, because stat looks at the final //file, not the link. Since this file doesn't exist anyway, //just skip it. continue; } dwError = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(dwError); } /* * For now, we are searching only for regular files * This may be enhanced in the future to support additional * file system entry types */ if (((statbuf.st_mode & S_IFMT) == S_IFREG) && (regexec(&rx, pDirEntry->d_name, nMatch, pResult, 0) == 0)) { dwNPaths++; dwError = LwAllocateMemory(sizeof(PATHNODE), (PVOID*)&pPathNode); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateString(szBuf, &pPathNode->pszPath); BAIL_ON_LSA_ERROR(dwError); pPathNode->pNext = pPathList; pPathList = pPathNode; pPathNode = NULL; } } if (pPathList) { dwError = LwAllocateMemory(sizeof(PSTR)*dwNPaths, (PVOID*)&ppszHostFilePaths); BAIL_ON_LSA_ERROR(dwError); /* * The linked list is in reverse. * Assign values in reverse to get it right */ iPath = dwNPaths-1; pPathNode = pPathList; while (pPathNode) { *(ppszHostFilePaths+iPath) = pPathNode->pszPath; pPathNode->pszPath = NULL; pPathNode = pPathNode->pNext; iPath--; } } *pppszHostFilePaths = ppszHostFilePaths; *pdwNPaths = dwNPaths; cleanup: if (pPathNode) { LW_SAFE_FREE_STRING(pPathNode->pszPath); LwFreeMemory(pPathNode); } while(pPathList) { pPathNode = pPathList; pPathList = pPathList->pNext; LW_SAFE_FREE_STRING(pPathNode->pszPath); LwFreeMemory(pPathNode); } if (rxAllocated) { regfree(&rx); } LW_SAFE_FREE_MEMORY(pResult); if (pDir) { closedir(pDir); } return dwError; error: if (ppszHostFilePaths) { LwFreeStringArray(ppszHostFilePaths, dwNPaths); } goto cleanup; }
DWORD LwFindFilesInPaths( IN PCSTR pszName, IN LWFILE_TYPE type, IN const PCSTR* ppszSearchPaths, OUT PDWORD pdwFoundCount, OUT PSTR** pppszFoundPaths ) { DWORD dwError = 0; DWORD dwIndex = 0; PSTR pszTestPath = NULL; DWORD dwFoundCount = 0; PSTR* ppszFoundPaths = NULL; PSTR* ppszNewFoundPaths = NULL; BOOLEAN bExists = FALSE; for (dwIndex = 0; ppszSearchPaths[dwIndex]; dwIndex++) { LW_SAFE_FREE_STRING(pszTestPath); dwError = LwAllocateStringPrintf( &pszTestPath, "%s/%s", ppszSearchPaths[dwIndex], pszName); BAIL_ON_LW_ERROR(dwError); dwError = LwCheckFileTypeExists( pszTestPath, type, &bExists); BAIL_ON_LW_ERROR(dwError); if (bExists) { dwError = LwReallocMemory( ppszFoundPaths, OUT_PPVOID(&ppszNewFoundPaths), (dwFoundCount + 1) * sizeof(ppszFoundPaths[0])); BAIL_ON_LW_ERROR(dwError); ppszFoundPaths = ppszNewFoundPaths; ppszFoundPaths[dwFoundCount] = pszTestPath; pszTestPath = NULL; dwFoundCount++; } } *pdwFoundCount = dwFoundCount; *pppszFoundPaths = ppszFoundPaths; cleanup: return dwError; error: *pdwFoundCount = 0; *pppszFoundPaths = NULL; if (ppszFoundPaths) { LwFreeStringArray( ppszFoundPaths, dwFoundCount); } goto cleanup; }
DWORD LocalDirEnumMembers( IN HANDLE hEnum, IN DWORD dwMaxMemberSidCount, OUT PDWORD pdwMemberSidCount, OUT PSTR** pppszMemberSids ) { DWORD dwError = 0; LOCAL_ENUM_HANDLE pEnum = (LOCAL_ENUM_HANDLE) hEnum; PLOCAL_PROVIDER_CONTEXT pContext = (PLOCAL_PROVIDER_CONTEXT) pEnum->hProvider; LONG64 llSequenceNumber = 0; DWORD dwAllocCount = 0; PSTR* ppszMemberSids = NULL; DWORD dwIndex = 0; PDIRECTORY_ENTRY pEntry = NULL; static WCHAR wszAttrNameObjectSID[] = LOCAL_DIR_ATTR_OBJECT_SID; if (pEnum->dwIndex >= pEnum->dwCount) { dwError = ERROR_NO_MORE_ITEMS; BAIL_ON_LSA_ERROR(dwError); } dwError = LocalGetSequenceNumber( pContext, &llSequenceNumber); BAIL_ON_LSA_ERROR(dwError); if (llSequenceNumber != pEnum->llSequenceNumber) { dwError = ERROR_INVALID_DATA; BAIL_ON_LSA_ERROR(dwError); } dwAllocCount = dwMaxMemberSidCount; if (dwAllocCount > pEnum->dwCount - pEnum->dwIndex) { dwAllocCount = pEnum->dwCount - pEnum->dwIndex; } dwError = LwAllocateMemory(sizeof(*ppszMemberSids) * dwAllocCount, OUT_PPVOID(&ppszMemberSids)); BAIL_ON_LSA_ERROR(dwError); for(dwIndex = 0; dwIndex < dwAllocCount; dwIndex++) { pEntry = &pEnum->pEntries[pEnum->dwIndex++]; dwError = LocalMarshalAttrToANSIFromUnicodeString( pEntry, wszAttrNameObjectSID, &ppszMemberSids[dwIndex]); BAIL_ON_LSA_ERROR(dwError); } *pdwMemberSidCount = dwAllocCount; *pppszMemberSids = ppszMemberSids; cleanup: return dwError; error: *pdwMemberSidCount = 0; *pppszMemberSids = NULL; if (ppszMemberSids) { LwFreeStringArray(ppszMemberSids, dwAllocCount); } goto cleanup; }
DWORD LocalDirQueryMemberOf( IN HANDLE hProvider, IN LSA_FIND_FLAGS FindFlags, IN DWORD dwSidCount, IN PSTR* ppszSids, OUT PDWORD pdwGroupSidCount, OUT PSTR** pppszGroupSids ) { DWORD dwError = 0; DWORD dwIndex = 0; PLW_HASH_TABLE pGroupHash = NULL; LW_HASH_ITERATOR hashIterator = {0}; LW_HASH_ENTRY* pHashEntry = NULL; DWORD dwGroupSidCount = 0; PSTR* ppszGroupSids = NULL; dwError = LwHashCreate( 13, LwHashCaselessStringCompare, LwHashCaselessStringHash, NULL, NULL, &pGroupHash); BAIL_ON_LSA_ERROR(dwError); for (dwIndex = 0; dwIndex < dwSidCount; dwIndex++) { dwError = LocalDirQueryMemberOfInternal( hProvider, FindFlags, ppszSids[dwIndex], pGroupHash); BAIL_ON_LSA_ERROR(dwError); } dwGroupSidCount = (DWORD) LwHashGetKeyCount(pGroupHash); if (dwGroupSidCount) { dwError = LwAllocateMemory( sizeof(*ppszGroupSids) * dwGroupSidCount, OUT_PPVOID(&ppszGroupSids)); BAIL_ON_LSA_ERROR(dwError); dwError = LwHashGetIterator(pGroupHash, &hashIterator); BAIL_ON_LSA_ERROR(dwError); for(dwIndex = 0; (pHashEntry = LwHashNext(&hashIterator)) != NULL; dwIndex++) { ppszGroupSids[dwIndex] = (PSTR) pHashEntry->pValue; pHashEntry->pValue = NULL; } } *pdwGroupSidCount = dwGroupSidCount; *pppszGroupSids = ppszGroupSids; cleanup: if (pGroupHash) { if (LwHashGetIterator(pGroupHash, &hashIterator) == 0) { while ((pHashEntry = LwHashNext(&hashIterator))) { LW_SAFE_FREE_MEMORY(pHashEntry->pValue); } } LwHashSafeFree(&pGroupHash); } return dwError; error: *pdwGroupSidCount = 0; *pppszGroupSids = NULL; if (ppszGroupSids) { LwFreeStringArray(ppszGroupSids, dwGroupSidCount); } goto cleanup; }
static DWORD EVTCreateAccessDescriptor( PCSTR pszAllowReadTo, PCSTR pszAllowWriteTo, PCSTR pszAllowDeleteTo, PSECURITY_DESCRIPTOR_ABSOLUTE* ppDescriptor, PBOOLEAN pbFullyResolved ) { PSECURITY_DESCRIPTOR_ABSOLUTE pDescriptor = NULL; DWORD dwCount = 0; PSTR* ppszArray = NULL; DWORD dwReadCount = 0; DWORD dwWriteCount = 0; DWORD dwDeleteCount = 0; PSID* ppReadList = NULL; PSID* ppWriteList = NULL; PSID* ppDeleteList = NULL; PACL pDacl = NULL; DWORD dwDaclSize = 0; PLW_MAP_SECURITY_CONTEXT pContext = NULL; DWORD dwError = 0; PSID pLocalSystem = NULL; PSID pAdministrators = NULL; BOOLEAN bFullyResolved = TRUE; dwError = LwAllocateWellKnownSid( WinLocalSystemSid, NULL, &pLocalSystem, NULL); BAIL_ON_EVT_ERROR(dwError); dwError = LwAllocateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &pAdministrators, NULL); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( LwMapSecurityCreateContext( &pContext)); BAIL_ON_EVT_ERROR(dwError); dwError = LwAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, (PVOID*)&pDescriptor); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateSecurityDescriptorAbsolute( pDescriptor, SECURITY_DESCRIPTOR_REVISION)); BAIL_ON_EVT_ERROR(dwError); dwError = EVTStringSplit( pszAllowReadTo, &dwCount, &ppszArray); BAIL_ON_EVT_ERROR(dwError); dwError = EVTNamesToSids( pContext, dwCount, ppszArray, &dwReadCount, &ppReadList); BAIL_ON_EVT_ERROR(dwError); if (dwReadCount < dwCount) { bFullyResolved = FALSE; } LwFreeStringArray( ppszArray, dwCount); ppszArray = NULL; dwError = EVTStringSplit( pszAllowWriteTo, &dwCount, &ppszArray); BAIL_ON_EVT_ERROR(dwError); dwError = EVTNamesToSids( pContext, dwCount, ppszArray, &dwWriteCount, &ppWriteList); BAIL_ON_EVT_ERROR(dwError); if (dwWriteCount < dwCount) { bFullyResolved = FALSE; } LwFreeStringArray( ppszArray, dwCount); ppszArray = NULL; dwError = EVTStringSplit( pszAllowDeleteTo, &dwCount, &ppszArray); BAIL_ON_EVT_ERROR(dwError); dwError = EVTNamesToSids( pContext, dwCount, ppszArray, &dwDeleteCount, &ppDeleteList); BAIL_ON_EVT_ERROR(dwError); if (dwDeleteCount < dwCount) { bFullyResolved = FALSE; } LwFreeStringArray( ppszArray, dwCount); ppszArray = NULL; dwDaclSize = ACL_HEADER_SIZE + EVTGetAllowAcesSize(dwReadCount, ppReadList) + EVTGetAllowAcesSize(dwWriteCount, ppWriteList) + EVTGetAllowAcesSize(dwDeleteCount, ppDeleteList); dwError = LwAllocateMemory( dwDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION)); BAIL_ON_EVT_ERROR(dwError); dwError = EVTAddAllowAces( pDacl, dwReadCount, ppReadList, EVENTLOG_READ_RECORD); BAIL_ON_EVT_ERROR(dwError); dwError = EVTAddAllowAces( pDacl, dwWriteCount, ppWriteList, EVENTLOG_WRITE_RECORD); BAIL_ON_EVT_ERROR(dwError); dwError = EVTAddAllowAces( pDacl, dwWriteCount, ppWriteList, EVENTLOG_DELETE_RECORD); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetDaclSecurityDescriptor( pDescriptor, TRUE, pDacl, FALSE)); BAIL_ON_EVT_ERROR(dwError); pDacl = NULL; dwError = LwNtStatusToWin32Error( RtlSetOwnerSecurityDescriptor( pDescriptor, pLocalSystem, FALSE)); BAIL_ON_EVT_ERROR(dwError); pLocalSystem = NULL; dwError = LwNtStatusToWin32Error( RtlSetGroupSecurityDescriptor( pDescriptor, pAdministrators, FALSE)); BAIL_ON_EVT_ERROR(dwError); pAdministrators = NULL; *ppDescriptor = pDescriptor; if (pbFullyResolved) { *pbFullyResolved = bFullyResolved; } cleanup: if (ppszArray) { LwFreeStringArray( ppszArray, dwCount); } EVTFreeSidArray( pContext, dwReadCount, ppReadList); EVTFreeSidArray( pContext, dwWriteCount, ppWriteList); EVTFreeSidArray( pContext, dwDeleteCount, ppDeleteList); LwMapSecurityFreeContext(&pContext); return dwError; error: EVTFreeSecurityDescriptor(pDescriptor); *ppDescriptor = NULL; if (pbFullyResolved) { *pbFullyResolved = FALSE; } LW_SAFE_FREE_MEMORY(pDacl); LW_SAFE_FREE_MEMORY(pLocalSystem); LW_SAFE_FREE_MEMORY(pAdministrators); goto cleanup; }
static DWORD EVTStringSplit( PCSTR pszInput, PDWORD pdwCount, PSTR** pppszArray ) { DWORD dwError = 0; DWORD dwCount = 0; PCSTR pszStart = NULL; PCSTR pszEnd = NULL; PSTR* ppszArray = NULL; PSTR pszAdd = NULL; for (pszStart = pszInput; *pszStart != 0; pszStart++) { if (*pszStart == ',') dwCount++; } dwCount++; dwError = LwAllocateMemory( (dwCount+1)*sizeof(PCSTR), (PVOID *)&ppszArray); dwCount = 0; pszStart = pszInput; while (TRUE) { pszEnd = strchr(pszStart, ','); if ( pszEnd ) { dwError = LwStrndup( pszStart, pszEnd - pszStart, &pszAdd); BAIL_ON_EVT_ERROR(dwError); } else { dwError = LwAllocateString( pszStart, &pszAdd); BAIL_ON_EVT_ERROR(dwError); } LwStripWhitespace(pszAdd, TRUE, TRUE); if (pszAdd[0]) { ppszArray[dwCount++] = pszAdd; pszAdd = NULL; } else { LW_SAFE_FREE_STRING(pszAdd); } if (pszEnd) { pszStart = pszEnd + 1; } else { break; } } *pppszArray = ppszArray; *pdwCount = dwCount; cleanup: LW_SAFE_FREE_STRING(pszAdd); return dwError; error: LwFreeStringArray( ppszArray, dwCount); goto cleanup; }
DWORD ADLdap_GetObjectGroupMembership( IN PAD_PROVIDER_CONTEXT pContext, IN PLSA_SECURITY_OBJECT pObject, OUT int* piPrimaryGroupIndex, OUT size_t* psNumGroupsFound, OUT PLSA_SECURITY_OBJECT** pppGroupInfoList ) { DWORD dwError = 0; PLSA_DM_LDAP_CONNECTION pConn = NULL; PSTR pszFullDomainName = NULL; INT i = 0; PLSA_SECURITY_OBJECT* ppGroupInfoList = NULL; size_t sNumGroupsFound = 0; int iPrimaryGroupIndex = -1; DWORD gcMembershipCount = 0; PSTR* ppGcMembershipList = NULL; DWORD dcMembershipCount = 0; PSTR* ppDcMembershipList = NULL; PLW_HASH_TABLE pGroupHash = NULL; LSA_TRUST_DIRECTION trustDirection = LSA_TRUST_DIRECTION_UNKNOWN; LSA_TRUST_MODE trustMode = LSA_TRUST_MODE_UNKNOWN; DWORD index = 0; DWORD totalSidCount = 0; PSTR* ppTotalSidList = NULL; // If we cannot get dn, then we cannot get DN information for this objects, hence BAIL if (LW_IS_NULL_OR_EMPTY_STR(pObject->pszDN)) { dwError = LW_ERROR_NO_SUCH_USER; BAIL_ON_LSA_ERROR(dwError); } dwError = LwLdapConvertDNToDomain( pObject->pszDN, &pszFullDomainName); BAIL_ON_LSA_ERROR(dwError); // Note that this function is called only for 2-way trusts. However, // the trust could be an external trust or a forest trust. We can only // query the GC if there is a forest trust. dwError = AD_DetermineTrustModeandDomainName( pContext->pState, pszFullDomainName, &trustDirection, &trustMode, NULL, NULL); BAIL_ON_LSA_ERROR(dwError); // We could only have the DN path for the user if (s)he came from a two way // trusted domain or the joined domain. LSA_ASSERT(LSA_TRUST_DIRECTION_TWO_WAY == trustDirection || LSA_TRUST_DIRECTION_SELF == trustDirection); if (trustMode != LSA_TRUST_MODE_EXTERNAL) { // Get forest info from domain's GC since there is a forest trust. // This will only include universal group information. (The domain // global groups will not include membership info in the GC.) dwError = LsaDmLdapOpenGc( pContext, pszFullDomainName, &pConn); BAIL_ON_LSA_ERROR(dwError); dwError = ADLdap_GetAttributeValuesList( pConn, pObject->pszDN, AD_LDAP_MEMBEROF_TAG, TRUE, TRUE, &gcMembershipCount, &ppGcMembershipList); BAIL_ON_LSA_ERROR(dwError); LsaDmLdapClose(pConn); pConn = NULL; } dwError = LsaDmLdapOpenDc( pContext, pszFullDomainName, &pConn); BAIL_ON_LSA_ERROR(dwError); dwError = ADLdap_GetAttributeValuesList( pConn, pObject->pszDN, AD_LDAP_MEMBEROF_TAG, TRUE, TRUE, &dcMembershipCount, &ppDcMembershipList); BAIL_ON_LSA_ERROR(dwError); dwError = LwHashCreate( (dcMembershipCount + gcMembershipCount + 1) * 2, LwHashCaselessStringCompare, LwHashCaselessStringHash, ADLdap_FreeHashStringValue, NULL, &pGroupHash); BAIL_ON_LSA_ERROR(dwError); for (index = 0; index < gcMembershipCount; index++) { PSTR pSid = ppGcMembershipList[index]; if (!LwHashExists(pGroupHash, pSid)) { // Set the value of the hash entry as NULL so this string is not // freed with the hash. dwError = LwHashSetValue(pGroupHash, pSid, NULL); BAIL_ON_LSA_ERROR(dwError); } } for (index = 0; index < dcMembershipCount; index++) { PSTR pSid = ppDcMembershipList[index]; if (!LwHashExists(pGroupHash, pSid)) { // Set the value of the hash entry as NULL so this string is not // freed with the hash. dwError = LwHashSetValue(pGroupHash, pSid, NULL); BAIL_ON_LSA_ERROR(dwError); } } if (pObject->type == LSA_OBJECT_TYPE_USER && pObject->userInfo.pszPrimaryGroupSid) { // Add the pszPrimaryGroupSID entry to the hash PSTR pSid = pObject->userInfo.pszPrimaryGroupSid; if (!LwHashExists(pGroupHash, pSid)) { // Set the value of the hash entry as NULL so this string is not // freed with the hash. dwError = LwHashSetValue(pGroupHash, pSid, NULL); BAIL_ON_LSA_ERROR(dwError); } } // Check if the user came from a domain other than the computer's domain if (LSA_TRUST_DIRECTION_TWO_WAY == trustDirection) { dwError = ADLdap_AddDomainLocalGroups( pContext, pObject, pGroupHash); BAIL_ON_LSA_ERROR(dwError); } dwError = ADLdap_MoveHashKeysToArray( pGroupHash, &totalSidCount, (PVOID**)(PVOID)&ppTotalSidList); BAIL_ON_LSA_ERROR(dwError); dwError = AD_FindObjectsBySidList( pContext, totalSidCount, ppTotalSidList, &sNumGroupsFound, &ppGroupInfoList); BAIL_ON_LSA_ERROR(dwError); AD_FilterNullEntries( ppGroupInfoList, &sNumGroupsFound); // Determine primary group index if (pObject->type == LSA_OBJECT_TYPE_USER && pObject->userInfo.pszPrimaryGroupSid && ppGroupInfoList && sNumGroupsFound) { for (i = (INT)sNumGroupsFound - 1; i >= 0; i--) { if (!strcmp(ppGroupInfoList[i]->pszObjectSid, pObject->userInfo.pszPrimaryGroupSid)) { iPrimaryGroupIndex = i; break; } } } *psNumGroupsFound = sNumGroupsFound; *pppGroupInfoList = ppGroupInfoList; *piPrimaryGroupIndex = iPrimaryGroupIndex; cleanup: LwHashSafeFree(&pGroupHash); LW_SAFE_FREE_STRING(pszFullDomainName); LwFreeStringArray(ppGcMembershipList, gcMembershipCount); LwFreeStringArray(ppDcMembershipList, dcMembershipCount); // Do not free the string pointers inside. They are borrowed from the // hash. LW_SAFE_FREE_MEMORY(ppTotalSidList); LsaDmLdapClose(pConn); return dwError; error: *pppGroupInfoList = NULL; *psNumGroupsFound = 0; *piPrimaryGroupIndex = -1; if ( dwError != LW_ERROR_DOMAIN_IS_OFFLINE ) { LSA_LOG_ERROR("Failed to group memberships of SID=%s. [error code:%u]", pObject->pszObjectSid, dwError); } ADCacheSafeFreeObjectList((DWORD)sNumGroupsFound, &ppGroupInfoList); goto cleanup; }
DWORD LsaAdBatchBuildQueryForRpc( IN PCSTR pszNetbiosDomainName, IN LSA_AD_BATCH_QUERY_TYPE QueryType, // List of PLSA_AD_BATCH_ITEM IN PLSA_LIST_LINKS pFirstLinks, IN PLSA_LIST_LINKS pEndLinks, OUT PLSA_LIST_LINKS* ppNextLinks, IN DWORD dwMaxQueryCount, OUT PDWORD pdwQueryCount, OUT PSTR** pppszQueryList ) { DWORD dwError = 0; PLSA_LIST_LINKS pLinks = NULL; PSTR* ppszQueryList = NULL; PLSA_LIST_LINKS pLastLinks = pFirstLinks; DWORD dwQueryCount = 0; DWORD dwSavedQueryCount = 0; pLinks = pFirstLinks; for (pLinks = pFirstLinks; pLinks != pEndLinks; pLinks = pLinks->Next) { PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks); PCSTR pszQueryTerm = NULL; switch (QueryType) { case LSA_AD_BATCH_QUERY_TYPE_BY_SID: { if (pBatchItem->pszSid) { pszQueryTerm = pBatchItem->pszSid; } else if (QueryType == pBatchItem->QueryTerm.Type) { pszQueryTerm = pBatchItem->QueryTerm.pszString; } break; } case LSA_AD_BATCH_QUERY_TYPE_BY_NT4: { if (pBatchItem->pszSamAccountName) { pszQueryTerm = pBatchItem->pszSamAccountName; } else if (QueryType == pBatchItem->QueryTerm.Type) { pszQueryTerm = pBatchItem->QueryTerm.pszString; } break; } default: LSA_ASSERT(FALSE); dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } if (!LW_IS_NULL_OR_EMPTY_STR(pszQueryTerm)) { DWORD dwNewQueryCount = dwQueryCount + 1; if (dwMaxQueryCount && (dwNewQueryCount > dwMaxQueryCount)) { break; } dwQueryCount = dwNewQueryCount; } } pLastLinks = pLinks; dwSavedQueryCount = dwQueryCount; if (dwQueryCount < 1) { goto cleanup; } dwError = LwAllocateMemory(dwQueryCount*sizeof(*ppszQueryList), (PVOID*)&ppszQueryList); BAIL_ON_LSA_ERROR(dwError); dwQueryCount = 0; // Loop until we reach last links. for (pLinks = pFirstLinks; pLinks != pLastLinks; pLinks = pLinks->Next) { PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks); if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM)) { LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm); ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM); } switch (QueryType) { case LSA_AD_BATCH_QUERY_TYPE_BY_SID: { PCSTR pszUseSid = NULL; if (pBatchItem->pszSid) { pszUseSid = pBatchItem->pszSid; } else if (QueryType == pBatchItem->QueryTerm.Type) { pszUseSid = pBatchItem->QueryTerm.pszString; } // We might not have a SID if we failed to find a pseudo. if (pszUseSid) { dwError = LwAllocateString(pszUseSid, &ppszQueryList[dwQueryCount++]); BAIL_ON_LSA_ERROR(dwError); pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSid; } break; } case LSA_AD_BATCH_QUERY_TYPE_BY_NT4: { PCSTR pszUseSamAccountName = NULL; if (pBatchItem->pszSamAccountName) { pszUseSamAccountName = pBatchItem->pszSamAccountName; } else if (QueryType == pBatchItem->QueryTerm.Type) { pszUseSamAccountName = pBatchItem->QueryTerm.pszString; } if (pszUseSamAccountName) { dwError = LwAllocateStringPrintf( &ppszQueryList[dwQueryCount++], "%s\\%s", pszNetbiosDomainName, pszUseSamAccountName); BAIL_ON_LSA_ERROR(dwError); pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSamAccountName; } break; } default: LSA_ASSERT(FALSE); dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } } assert(dwSavedQueryCount == dwQueryCount); cleanup: // We handle error here instead of error label // because there is a goto cleanup above. if (dwError) { LwFreeStringArray(ppszQueryList, dwSavedQueryCount); ppszQueryList = NULL; dwQueryCount = 0; dwSavedQueryCount = 0; pLastLinks = pFirstLinks; } *pppszQueryList = ppszQueryList; *pdwQueryCount = dwQueryCount; *ppNextLinks = pLastLinks; return dwError; error: // Do not actually handle any errors here. goto cleanup; }
// Give an attribute name "pszAttributeName" // Return all the values of the attribute for a given DN "pszDN" // The number of values can be more than 1500 since "ranging" is handled correctly in the routine // Now accept whether to do an extended DN search and whether to parse result to get Sids DWORD ADLdap_GetAttributeValuesList( IN PLSA_DM_LDAP_CONNECTION pConn, IN PCSTR pszDN, IN PCSTR pszAttributeName, IN BOOLEAN bDoExtDnSearch, IN BOOLEAN bDoSidParsing, OUT PDWORD pdwTotalCount, OUT PSTR** pppszValues ) { DWORD dwError = 0; // Do not free "szAttributeList" PSTR szAttributeList[2] = {NULL,NULL}; PSTR* ppszValuesTotal = NULL; PSTR* ppszValues = NULL; LDAPMessage* pMessage = NULL; DWORD dwCount = 0; DWORD dwTotalCount = 0; PLW_DLINKED_LIST pList = NULL; PLW_DLINKED_LIST pNode = NULL; PLSA_AD_QUERY_LISTS_ENTRY pEntry = NULL; PSTR pszRangeAttr = NULL; LDAP* pLd = NULL; BerElement* pBer = NULL; PSTR pszRetrievedAttr = NULL; //Do Not free "pszRetrievedRangeAttr" PSTR pszRetrievedRangeAttr = NULL; BOOLEAN bIsEnd = FALSE; DWORD iValues = 0; DWORD iValuesTotal = 0; PSTR pszAttributeRangedName = NULL; HANDLE hDirectory = NULL; BAIL_ON_INVALID_STRING(pszAttributeName); szAttributeList[0] = (PSTR)pszAttributeName; for (;;) { if (pMessage) { ldap_msgfree(pMessage); pMessage = NULL; } if (!bDoExtDnSearch && bDoSidParsing) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } if (bDoExtDnSearch) { dwError = LsaDmLdapDirectoryExtendedDNSearch( pConn, pszDN, "(objectClass=*)", szAttributeList, LDAP_SCOPE_BASE, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); } else { dwError = LsaDmLdapDirectorySearch( pConn, pszDN, LDAP_SCOPE_BASE, "(objectClass=*)", szAttributeList, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); } pLd = LwLdapGetSession(hDirectory); dwError = LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszAttributeName, bDoSidParsing, &ppszValues, &dwCount); BAIL_ON_LSA_ERROR(dwError); if (ppszValues && dwCount) { if (pList) { // This is the case where we started out getting // ranged info but the info became non-ranged. // We might actually want to allow this to handle // a case where the membership list is trimmed // while we are enumerating. dwError = LW_ERROR_LDAP_ERROR; BAIL_ON_LSA_ERROR(dwError); } dwTotalCount = dwCount; ppszValuesTotal = ppszValues; dwCount = 0; ppszValues = NULL; break; } if (pszRetrievedAttr) { ldap_memfree(pszRetrievedAttr); pszRetrievedAttr = NULL; } if (pBer) { ber_free(pBer, 0); } LW_SAFE_FREE_STRING(pszAttributeRangedName); dwError = LwAllocateStringPrintf( &pszAttributeRangedName, "%s;Range=", pszAttributeName); BAIL_ON_LSA_ERROR(dwError); pszRetrievedAttr = ldap_first_attribute(pLd, pMessage, &pBer); while (pszRetrievedAttr) { if (!strncasecmp(pszRetrievedAttr, pszAttributeRangedName, strlen(pszAttributeRangedName))) { pszRetrievedRangeAttr = pszRetrievedAttr; break; } ldap_memfree(pszRetrievedAttr); pszRetrievedAttr = NULL; pszRetrievedAttr = ldap_next_attribute(pLd, pMessage, pBer); } if (!pszRetrievedRangeAttr) { // This happens when we have an group with no members, break; } if ('*' == pszRetrievedRangeAttr[strlen(pszRetrievedRangeAttr)-1]) { bIsEnd = TRUE; } dwError = LwLdapGetStringsWithExtDnResult( hDirectory, pMessage, pszRetrievedRangeAttr, bDoSidParsing, &ppszValues, &dwCount); BAIL_ON_LSA_ERROR(dwError); dwTotalCount += dwCount; dwError = CreateQueryListEntry( &pEntry, dwCount, ppszValues); BAIL_ON_LSA_ERROR(dwError); ppszValues = NULL; dwCount = 0; dwError = LwDLinkedListPrepend(&pList, pEntry); BAIL_ON_LSA_ERROR(dwError); pEntry = NULL; if (bIsEnd) { break; } LW_SAFE_FREE_STRING(pszRangeAttr); dwError = LwAllocateStringPrintf( &pszRangeAttr, "%s%u-*", pszAttributeRangedName, dwTotalCount); BAIL_ON_LSA_ERROR(dwError); szAttributeList[0] = pszRangeAttr; } if (pList && !ppszValuesTotal) { dwError = LwAllocateMemory( sizeof(*ppszValuesTotal) * dwTotalCount, (PVOID*)&ppszValuesTotal); BAIL_ON_LSA_ERROR(dwError); for (pNode = pList; pNode; pNode = pNode->pNext) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem; for (iValues = 0; iValues < pEntry->dwQueryCount; iValues++) { ppszValuesTotal[iValuesTotal] = pEntry->ppszQueryValues[iValues]; pEntry->ppszQueryValues[iValues] = NULL; iValuesTotal++; } } } *pdwTotalCount = dwTotalCount; *pppszValues = ppszValuesTotal; cleanup: if (pMessage) { ldap_msgfree(pMessage); } if (pszRetrievedAttr) { ldap_memfree(pszRetrievedAttr); } if (pBer) { ber_free(pBer, 0); } LwFreeStringArray(ppszValues, dwCount); DestroyQueryListEntry(&pEntry); LW_SAFE_FREE_STRING(pszAttributeRangedName); LW_SAFE_FREE_STRING(pszRangeAttr); for (pNode = pList; pNode; pNode = pNode->pNext) { PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem; DestroyQueryListEntry(&pEntry); } LwDLinkedListFree(pList); return dwError; error: LwFreeStringArray(ppszValuesTotal, iValuesTotal); *pdwTotalCount = 0; *pppszValues = NULL; goto cleanup; }
DWORD ADGetConfigurationMode( IN PLSA_DM_LDAP_CONNECTION pConn, PCSTR pszDN, ADConfigurationMode* pADConfMode ) { DWORD dwError = 0; LDAP *pLd = NULL; PSTR szAttributeList[] = {AD_LDAP_DESCRIPTION_TAG, NULL}; LDAPMessage *pMessage = NULL; DWORD dwCount = 0; ADConfigurationMode adConfMode = NonSchemaMode; HANDLE hDirectory = NULL; PSTR* ppszValues = NULL; DWORD dwNumValues = 0; DWORD i = 0; BAIL_ON_INVALID_POINTER(pConn); dwError = LsaDmLdapDirectorySearch( pConn, pszDN, LDAP_SCOPE_BASE, "(objectClass=*)", szAttributeList, &hDirectory, &pMessage); if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT){ dwError = LW_ERROR_INCOMPATIBLE_MODES_BETWEEN_TRUSTEDDOMAINS; } BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); dwCount = ldap_count_entries( pLd, pMessage ); if (dwCount < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (dwCount == 0) { dwError = LW_ERROR_NO_SUCH_CELL; } else if (dwCount > 1) { dwError = LW_ERROR_INTERNAL; } BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapGetStrings( hDirectory, pMessage, AD_LDAP_DESCRIPTION_TAG, &ppszValues, &dwNumValues); BAIL_ON_LSA_ERROR(dwError); for (i = 0; i < dwNumValues; i++) { if (!strncasecmp(ppszValues[i], "use2307Attrs=", sizeof("use2307Attrs=")-1)) { PSTR pszValue = ppszValues[i] + sizeof("use2307Attrs=") - 1; if (!LW_IS_NULL_OR_EMPTY_STR(pszValue) && !strcasecmp(pszValue, "true")) { adConfMode = SchemaMode; break; } } } *pADConfMode = adConfMode; cleanup: if (pMessage) { ldap_msgfree(pMessage); } if (ppszValues) { LwFreeStringArray(ppszValues, dwNumValues); } return dwError; error: *pADConfMode = UnknownMode; goto cleanup; }
DWORD AD_GetMemberLists( IN PLSA_AD_PROVIDER_STATE pState, PSTR** pppszMembers, PDWORD pdwNumMembers, PLW_HASH_TABLE* ppAllowedMemberList ) { DWORD dwError = 0; BOOLEAN bInLock = FALSE; DWORD dwNumMembers = 0; PLW_DLINKED_LIST pIter = NULL; PSTR* ppszMembers = NULL; PLW_HASH_TABLE pAllowedMemberList = NULL; ENTER_AD_CONFIG_RW_READER_LOCK(bInLock, pState); for (pIter = pState->config.pUnresolvedMemberList; pIter; pIter = pIter->pNext) { dwNumMembers++; } if (dwNumMembers) { DWORD iMember = 0; dwError = LwAllocateMemory( dwNumMembers * sizeof(PSTR), (PVOID*)&ppszMembers); BAIL_ON_LSA_ERROR(dwError); for (pIter = pState->config.pUnresolvedMemberList; pIter; pIter = pIter->pNext, iMember++) { dwError = LwAllocateString( (PSTR)pIter->pItem, &ppszMembers[iMember]); BAIL_ON_LSA_ERROR(dwError); } } if (pState->pAllowedSIDs) { dwError = LwHashCopy( pState->pAllowedSIDs, &pAllowedMemberList); BAIL_ON_LSA_ERROR(dwError); } *pppszMembers = ppszMembers; *pdwNumMembers = dwNumMembers; *ppAllowedMemberList = pAllowedMemberList; cleanup: LEAVE_AD_CONFIG_RW_READER_LOCK(bInLock, pState); return dwError; error: if (ppszMembers) { LwFreeStringArray(ppszMembers, dwNumMembers); } *pppszMembers = NULL; *pdwNumMembers = 0; *ppAllowedMemberList = NULL; LwHashSafeFree(&pAllowedMemberList); goto cleanup; }
// Must return at least one of NT4 or SID. // Can optionally return alias as well. DWORD ADUnprovPlugin_QueryById( IN PLSA_AD_PROVIDER_STATE pState, IN BOOLEAN bIsUser, IN DWORD dwId, OUT PSTR* ppszSid, OUT PSTR* ppszAlias ) { DWORD dwError = LW_ERROR_SUCCESS; PSTR* ppszDomainNames = NULL; DWORD dwDomainCount = 0; DWORD i = 0; // lsass unprovisioned mode converts a group/user uid/gid to objectSid/name with the same algorithm dwError = ADUnprovPlugin_QueryByIdWithDomainName( pState, bIsUser, dwId, pState->pProviderData->szDomain, ppszSid, ppszAlias); if (LW_ERROR_NO_SUCH_OBJECT == dwError || LW_ERROR_NO_SUCH_DOMAIN == dwError) { dwError = 0; } BAIL_ON_LSA_ERROR(dwError); if (!LW_IS_NULL_OR_EMPTY_STR(*ppszSid)) goto cleanup; dwError = LsaDmEnumDomainNames( pState->hDmState, NULL, NULL, &ppszDomainNames, &dwDomainCount); BAIL_ON_LSA_ERROR(dwError); for (i = 0; i < dwDomainCount; i++) { dwError = ADUnprovPlugin_QueryByIdWithDomainName( pState, bIsUser, dwId, ppszDomainNames[i], ppszSid, ppszAlias); if (LW_ERROR_NO_SUCH_OBJECT == dwError || LW_ERROR_NO_SUCH_DOMAIN == dwError) { dwError = 0; continue; } BAIL_ON_LSA_ERROR(dwError); if (!LW_IS_NULL_OR_EMPTY_STR(*ppszSid)) goto cleanup; } cleanup: if (dwError) { *ppszSid = NULL; *ppszAlias = NULL; } LwFreeStringArray(ppszDomainNames, dwDomainCount); return dwError; error: goto cleanup; }
DWORD ADLdap_GetGroupMembers( IN PAD_PROVIDER_CONTEXT pContext, IN PCSTR pszDomainName, IN PCSTR pszSid, OUT size_t* psCount, OUT PLSA_SECURITY_OBJECT** pppResults ) { DWORD dwError = LW_ERROR_SUCCESS; DWORD dwSidCount = 0; PSTR pszDnsDomainName = NULL; PLSA_SECURITY_OBJECT pGroupObj = NULL; PLSA_SECURITY_OBJECT* ppResults = NULL; PSTR *ppszLDAPValues = NULL; size_t sFoundCount = 0; PLSA_DM_LDAP_CONNECTION pConn = NULL; dwError = AD_FindObjectBySid( pContext, pszSid, &pGroupObj); BAIL_ON_LSA_ERROR(dwError); if (pGroupObj->type != LSA_OBJECT_TYPE_GROUP) { dwError = LW_ERROR_DATA_ERROR; BAIL_ON_LSA_ERROR(dwError); } dwError = LsaDmWrapGetDomainName( pContext->pState->hDmState, pszDomainName, &pszDnsDomainName, NULL); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDmLdapOpenDc( pContext, pszDnsDomainName, &pConn); BAIL_ON_LSA_ERROR(dwError); dwError = ADLdap_GetAttributeValuesList( pConn, pGroupObj->pszDN, AD_LDAP_MEMBER_TAG, TRUE, TRUE, &dwSidCount, &ppszLDAPValues); BAIL_ON_LSA_ERROR(dwError); dwError = AD_FindObjectsBySidList( pContext, dwSidCount, ppszLDAPValues, &sFoundCount, &ppResults); BAIL_ON_LSA_ERROR(dwError); *psCount = sFoundCount; *pppResults = ppResults; cleanup: LW_SAFE_FREE_STRING(pszDnsDomainName); ADCacheSafeFreeObject(&pGroupObj); LwFreeStringArray(ppszLDAPValues, dwSidCount); LsaDmLdapClose(pConn); return dwError; error: *psCount = 0; *pppResults = NULL; LSA_LOG_ERROR("Failed to find group's members of objectSid=%s. [error code:%u]", LSA_SAFE_LOG_STRING(pszSid), dwError); ADCacheSafeFreeObjectList((DWORD)sFoundCount, &ppResults); goto cleanup; }
BOOLEAN FindSshAndConfig( PCSTR pSshOrSshd, PSTR *ppSshBinary, PSTR *ppSshConfig, LWException **ppExc) { DWORD ceError = ERROR_SUCCESS; /* Mac OS X stores the configuration in /etc */ /* CSW ssh on Solaris uses /opt/csw/etc/ssh */ const PCSTR ppSshConfigPaths[] = { "/etc/ssh", "/opt/ssh/etc", "/usr/local/etc", "/etc", "/etc/openssh", "/usr/openssh/etc", "/opt/csw/etc/ssh", NULL }; DWORD foundConfigCount = 0; PSTR* ppFoundConfigs = NULL; /* Solaris Sparc 10 stores sshd in /usr/lib/ssh */ /* Experian says their sshd is at /usr/openssh/sbin/sshd */ /* CSW ssh on Solaris uses /opt/csw/sbin/sshd */ const PCSTR ppSshBinaryPaths[] = { "/usr/sbin", "/opt/ssh/sbin", "/usr/local/sbin", "/usr/bin", "/opt/ssh/bin", "/usr/local/bin", "/usr/lib/ssh", "/usr/openssh/sbin", "/usr/openssh/bin", "/opt/csw/sbin", "/opt/csw/bin", "/opt/ssh/hpux64/sbin", NULL }; DWORD foundBinaryCount = 0; PSTR* ppFoundBinaries = NULL; PSTR pConfigFilename = NULL; PSTR pBinaryFilename = NULL; PSTR pFoundConfigList = NULL; PSTR pFoundBinaryList = NULL; DWORD index = 0; *ppSshBinary = NULL; *ppSshConfig = NULL; LW_CLEANUP_CTERR(ppExc, CTAllocateStringPrintf( &pConfigFilename, "%s_config", pSshOrSshd)); LW_CLEANUP_CTERR(ppExc, CTAllocateStringPrintf( &pBinaryFilename, "%s", pSshOrSshd)); ceError = LwFindFilesInPaths( pConfigFilename, LWFILE_REGULAR, ppSshConfigPaths, &foundConfigCount, &ppFoundConfigs); LW_CLEANUP_CTERR(ppExc, ceError); ceError = LwRemoveDuplicateInodes( &foundConfigCount, ppFoundConfigs); LW_CLEANUP_CTERR(ppExc, ceError); ceError = LwFindFilesInPaths( pBinaryFilename, LWFILE_REGULAR, ppSshBinaryPaths, &foundBinaryCount, &ppFoundBinaries); LW_CLEANUP_CTERR(ppExc, ceError); ceError = LwRemoveDuplicateInodes( &foundBinaryCount, ppFoundBinaries); LW_CLEANUP_CTERR(ppExc, ceError); // Ssh version A.04.40.005 on HP-UX Itanimum has these paths: // /opt/ssh/hpux64/sbin/sshd (ELF-64 IA64) // /opt/ssh/sbin/sshd (ELF-32 IA64) // /usr/sbin/sshd (symlink to /opt/ssh/hpux64/sbin/sshd) // // Ssh version A.04.30.007 on HP-UX Itanimum has these paths: // /opt/ssh/hpux64/sbin/sshd (ELF-64 IA64) // /opt/ssh/sbin/sshd (ELF-32 IA64) // /usr/sbin/sshd (symlink to /opt/ssh/sbin/sshd) // // Both files point to the same config path. An exception must exist for // this case since the inodes are different for the two architectures. // // The symlink at /usr/sbin/sshd wins the duplication removal process. So // if it is found, the other path must be removed. for (index = 0; index < foundBinaryCount; index++) { if (!strcmp(ppFoundBinaries[index], "/usr/sbin/sshd")) { // Remove /opt/ssh/sbin/sshd or /opt/ssh/hpux64/sbin/sshd if they // are in the list for (index = 0; index < foundBinaryCount; index++) { if (!strcmp(ppFoundBinaries[index], "/opt/ssh/sbin/sshd") || !strcmp(ppFoundBinaries[index], "/opt/ssh/hpux64/sbin/sshd")) { LW_SAFE_FREE_STRING(ppFoundBinaries[index]); memmove(&ppFoundBinaries[index], &ppFoundBinaries[index+1], (foundBinaryCount - index - 1) * sizeof(ppFoundBinaries[index])); foundBinaryCount--; break; } } break; } } if ((foundConfigCount | foundBinaryCount) > 0 && foundConfigCount != foundBinaryCount) { ceError = CombinePaths( foundConfigCount, ppFoundConfigs, &pFoundConfigList); LW_CLEANUP_CTERR(ppExc, ceError); ceError = CombinePaths( foundBinaryCount, ppFoundBinaries, &pFoundBinaryList); LW_CLEANUP_CTERR(ppExc, ceError); if ((foundConfigCount | foundBinaryCount) == 1) { ceError = ERROR_FILE_NOT_FOUND; } else { ceError = ERROR_DUPLICATE_SERVICE_NAME; } LW_RAISE_EX(ppExc, ceError, "Unable to find ssh binary", "A %s config file was at %s, and a %s binary file was found at %s. Exactly one config file and one binary must exist on the system in a standard location. Uninstall any unused copies of ssh.", pSshOrSshd, pFoundConfigList, pSshOrSshd, pFoundBinaryList); } if (foundConfigCount == 1) { DJ_LOG_INFO("Found config file %s", ppFoundConfigs[0]); *ppSshConfig = ppFoundConfigs[0]; ppFoundConfigs[0] = NULL; } if (foundBinaryCount == 1) { DJ_LOG_INFO("Found binary %s", ppFoundBinaries[0]); *ppSshBinary = ppFoundBinaries[0]; ppFoundBinaries[0] = NULL; } cleanup: if (ppFoundConfigs) { LwFreeStringArray( ppFoundConfigs, foundConfigCount); } if (ppFoundBinaries) { LwFreeStringArray( ppFoundBinaries, foundBinaryCount); } LW_SAFE_FREE_STRING(pConfigFilename); LW_SAFE_FREE_STRING(pBinaryFilename); LW_SAFE_FREE_STRING(pFoundConfigList); LW_SAFE_FREE_STRING(pFoundBinaryList); return (foundConfigCount == 1); }
static DWORD LsaGetGroupsForUserBySid( IN HANDLE hLsaConnection, IN PCSTR pszSid, IN LSA_FIND_FLAGS FindFlags, IN DWORD dwGroupInfoLevel, OUT PDWORD pdwGroupsFound, OUT PVOID** pppGroupInfoList ) { DWORD dwError = 0; DWORD dwGroupSidCount = 0; PSTR* ppszGroupSids = 0; LSA_QUERY_LIST QueryList; PLSA_SECURITY_OBJECT* ppObjects = NULL; DWORD dwObjectsUsed = 0; DWORD dwInfoCount = 0; PVOID* ppGroupInfo = NULL; dwError = LsaQueryMemberOf( hLsaConnection, NULL, FindFlags, 1, (PSTR*) &pszSid, &dwGroupSidCount, &ppszGroupSids); BAIL_ON_LSA_ERROR(dwError); if (dwGroupSidCount == 0) { *pdwGroupsFound = 0; *pppGroupInfoList = NULL; } else { QueryList.ppszStrings = (PCSTR*) ppszGroupSids; dwError = LsaFindObjects( hLsaConnection, NULL, FindFlags, LSA_OBJECT_TYPE_GROUP, LSA_QUERY_TYPE_BY_SID, dwGroupSidCount, QueryList, &ppObjects); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory(sizeof(*ppGroupInfo) * dwGroupSidCount, OUT_PPVOID(&ppGroupInfo)); BAIL_ON_LSA_ERROR(dwError); dwError = LsaMarshalGroupInfoList( hLsaConnection, FindFlags, dwGroupSidCount, ppObjects, dwGroupInfoLevel, dwGroupSidCount, ppGroupInfo, &dwObjectsUsed, &dwInfoCount); BAIL_ON_LSA_ERROR(dwError); if (dwInfoCount == 0) { *pdwGroupsFound = 0; *pppGroupInfoList = NULL; LW_SAFE_FREE_MEMORY(ppObjects); } else { *pdwGroupsFound = dwInfoCount; *pppGroupInfoList = ppGroupInfo; } } cleanup: if (ppObjects) { LsaUtilFreeSecurityObjectList(dwGroupSidCount, ppObjects); } if (ppszGroupSids) { LwFreeStringArray(ppszGroupSids, dwGroupSidCount); } return dwError; error: *pdwGroupsFound = 0; *pppGroupInfoList = NULL; if (ppGroupInfo) { LsaFreeGroupInfoList(dwGroupInfoLevel, ppGroupInfo, dwInfoCount); } goto cleanup; }