static DWORD AppendStringArray( PDWORD pdwCount, PWSTR** pppwszArray, PWSTR pwszString ) { DWORD dwError = 0; PWSTR* ppwszNewArray = NULL; dwError = LwReallocMemory( *pppwszArray, OUT_PPVOID(&ppwszNewArray), sizeof(*ppwszNewArray) * (*pdwCount + 1)); BAIL_ON_SRVSVC_ERROR(dwError); ppwszNewArray[(*pdwCount)++] = pwszString; *pppwszArray = ppwszNewArray; error: return dwError; }
DWORD LWSetCapacity( DynamicArray *array, size_t itemSize, size_t capacity ) { DWORD dwError = 0; /* Resize the array */ dwError = LwReallocMemory(array->data, &array->data, capacity * itemSize); BAIL_ON_MAC_ERROR(dwError); array->capacity = capacity; if (array->size > capacity) { array->size = capacity; } cleanup: return dwError; error: goto cleanup; }
static DWORD ParseQueryItem( PCSTR pszArg ) { DWORD dwError = 0; unsigned long id = 0; LSA_QUERY_LIST NewList; switch (gState.QueryType) { case LSA_QUERY_TYPE_BY_UNIX_ID: id = strtoul(pszArg, NULL, 10); dwError = LwReallocMemory( gState.QueryList.pdwIds, OUT_PPVOID(&NewList.pdwIds), sizeof(*NewList.pdwIds) * (gState.dwCount + 1)); BAIL_ON_LSA_ERROR(dwError); NewList.pdwIds[gState.dwCount] = (DWORD) id; gState.QueryList.pdwIds = NewList.pdwIds; gState.dwCount++; break; default: dwError = LwReallocMemory( gState.QueryList.ppszStrings, OUT_PPVOID(&NewList.ppszStrings), sizeof(*NewList.ppszStrings) * (gState.dwCount + 1)); BAIL_ON_LSA_ERROR(dwError); NewList.ppszStrings[gState.dwCount] = pszArg; gState.QueryList.ppszStrings = NewList.ppszStrings; gState.dwCount++; break; } error: return dwError; }
DWORD LsaModifyGroup_RemoveMembers( PLSA_GROUP_MOD_INFO pGroupModInfo, PVOID pData ) { DWORD dwError = 0; PCSTR pszSID = NULL; DWORD iMember = 0; BAIL_ON_INVALID_POINTER(pGroupModInfo); pszSID = (PCSTR)pData; pGroupModInfo->dwRemoveMembersNum++; dwError = LwReallocMemory(pGroupModInfo->pRemoveMembers, (PVOID*)&pGroupModInfo->pRemoveMembers, sizeof(pGroupModInfo->pRemoveMembers[0]) * pGroupModInfo->dwRemoveMembersNum); BAIL_ON_LSA_ERROR(dwError); if (pszSID) { iMember = pGroupModInfo->dwRemoveMembersNum - 1; dwError = LwAllocateString( pszSID, &pGroupModInfo->pRemoveMembers[iMember].pszSid); BAIL_ON_LSA_ERROR(dwError); pGroupModInfo->actions.bRemoveMembers = TRUE; } cleanup: return dwError; error: 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 AD_BuildHomeDirFromTemplate( PLSA_AD_PROVIDER_STATE pState, PCSTR pszHomedirTemplate, PCSTR pszNetBIOSDomainName, PCSTR pszSamAccountName, PSTR* ppszHomedir ) { DWORD dwError = 0; PSTR pszHomedirPrefix = NULL; PSTR pszHomedir = NULL; DWORD dwOffset = 0; PCSTR pszIterTemplate = pszHomedirTemplate; DWORD dwBytesAllocated = 0; DWORD dwNetBIOSDomainNameLength = 0; DWORD dwSamAccountNameLength = 0; DWORD dwHomedirPrefixLength = 0; PSTR pszHostName = NULL; DWORD dwHostNameLength = 0; CHAR szEscapedPercent[2] = "%"; DWORD dwEscapedPercentLength = 0; BAIL_ON_INVALID_STRING(pszHomedirTemplate); BAIL_ON_INVALID_STRING(pszNetBIOSDomainName); BAIL_ON_INVALID_STRING(pszSamAccountName); if (strstr(pszHomedirTemplate, "%H")) { dwError = AD_GetHomedirPrefixPath(pState, &pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHomedirPrefix); dwHomedirPrefixLength = strlen(pszHomedirPrefix); } if (strstr(pszHomedirTemplate, "%L")) { dwError = LsaDnsGetHostInfo(&pszHostName); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHostName); dwHostNameLength = strlen(pszHostName); } if (strstr(pszHomedirTemplate, "%%")) { dwEscapedPercentLength = strlen(szEscapedPercent); } dwNetBIOSDomainNameLength = strlen(pszNetBIOSDomainName); dwSamAccountNameLength = strlen(pszSamAccountName); // Handle common case where we might use all replacements. dwBytesAllocated = (strlen(pszHomedirTemplate) + dwNetBIOSDomainNameLength + dwSamAccountNameLength + dwHomedirPrefixLength + dwHostNameLength + dwEscapedPercentLength + 1); dwError = LwAllocateMemory( sizeof(CHAR) * dwBytesAllocated, (PVOID*)&pszHomedir); BAIL_ON_LSA_ERROR(dwError); while (pszIterTemplate[0]) { // Do not count the terminating NULL as "available". DWORD dwBytesRemaining = dwBytesAllocated - dwOffset - 1; PCSTR pszInsert = NULL; DWORD dwInsertLength = 0; BOOLEAN bNeedUpper = FALSE; BOOLEAN bNeedLower = FALSE; LSA_ASSERT(dwOffset < dwBytesAllocated); if (pszIterTemplate[0] == '%') { switch (pszIterTemplate[1]) { case 'D': pszInsert = pszNetBIOSDomainName; dwInsertLength = dwNetBIOSDomainNameLength; bNeedUpper = TRUE; break; case 'U': pszInsert = pszSamAccountName; dwInsertLength = dwSamAccountNameLength; bNeedLower = TRUE; break; case 'H': pszInsert = pszHomedirPrefix; dwInsertLength = dwHomedirPrefixLength; break; case 'L': pszInsert = pszHostName; dwInsertLength = dwHostNameLength; break; case '%': pszInsert = szEscapedPercent; dwInsertLength = dwEscapedPercentLength; break; default: dwError = LW_ERROR_INVALID_HOMEDIR_TEMPLATE; BAIL_ON_LSA_ERROR(dwError); } LSA_ASSERT(!(bNeedUpper && bNeedLower)); pszIterTemplate += 2; } else { PCSTR pszEnd = strchr(pszIterTemplate, '%'); if (!pszEnd) { dwInsertLength = strlen(pszIterTemplate); } else { dwInsertLength = pszEnd - pszIterTemplate; } pszInsert = pszIterTemplate; pszIterTemplate += dwInsertLength; } if (dwBytesRemaining < dwInsertLength) { // We will increment by at least a minimum amount. DWORD dwAllocate = LSA_MAX(dwInsertLength - dwBytesRemaining, 64); PSTR pszNewHomedir = NULL; dwError = LwReallocMemory( pszHomedir, (PVOID*)&pszNewHomedir, dwBytesAllocated + dwAllocate); BAIL_ON_LSA_ERROR(dwError); pszHomedir = pszNewHomedir; dwBytesAllocated += dwAllocate; } memcpy(pszHomedir + dwOffset, pszInsert, dwInsertLength); if (bNeedUpper) { LwStrnToUpper(pszHomedir + dwOffset, dwInsertLength); } else if (bNeedLower) { LwStrnToLower(pszHomedir + dwOffset, dwInsertLength); } dwOffset += dwInsertLength; } // We should still have enough room for NULL. LSA_ASSERT(dwOffset < dwBytesAllocated); pszHomedir[dwOffset] = 0; dwOffset++; *ppszHomedir = pszHomedir; cleanup: LW_SAFE_FREE_STRING(pszHomedirPrefix); LW_SAFE_FREE_STRING(pszHostName); return dwError; error: *ppszHomedir = NULL; LW_SAFE_FREE_MEMORY(pszHomedir); goto cleanup; }
DWORD CaptureOutputWithStderr( PCSTR pCommand, PCSTR* ppArgs, PSTR* ppOutput, int *pExitCode ) { DWORD error = ERROR_SUCCESS; size_t bufferCapacity = 1024; ssize_t inBuffer = 0; ssize_t readCount = 0; int pipeFds[2] = { -1, -1 }; pid_t pid = -1; int status = 0; PSTR pTempOutput = NULL; // Do not free PSTR pNewOutput = NULL; if (ppOutput != NULL) { *ppOutput = NULL; } if (pipe(pipeFds)) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } pid = fork(); if (pid < 0) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } else if (pid == 0) { // Child process if (dup2(pipeFds[1], STDOUT_FILENO) < 0) { abort(); } if (dup2(pipeFds[1], STDERR_FILENO) < 0) { abort(); } if (close(pipeFds[0])) { abort(); } if (close(pipeFds[1])) { abort(); } execvp(pCommand, (char **)ppArgs); abort(); } if (close(pipeFds[1])) { pipeFds[1] = -1; error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } pipeFds[1] = -1; error = LwAllocateMemory(bufferCapacity, (PVOID*) &pTempOutput); BAIL_ON_LSA_ERROR(error); while ((readCount = read(pipeFds[0], pTempOutput + inBuffer, bufferCapacity - inBuffer)) > 0) { inBuffer += readCount; if (inBuffer == bufferCapacity) { bufferCapacity *= 2; error = LwReallocMemory( pTempOutput, (PVOID*)&pNewOutput, bufferCapacity); BAIL_ON_LSA_ERROR(error); pTempOutput = pNewOutput; } } if (readCount < 0) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } if (close(pipeFds[0]) < 0) { pipeFds[0] = -1; error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } pipeFds[0] = -1; if (waitpid(pid, &status, 0) != pid) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } if (ppOutput != NULL) { *ppOutput = pTempOutput; pTempOutput = NULL; } if (pExitCode != NULL) { *pExitCode = WEXITSTATUS(status); } else if (status) { error = ERROR_BAD_COMMAND; BAIL_ON_LSA_ERROR(error); } cleanup: if (pipeFds[0] >= 0) { close(pipeFds[0]); } if (pipeFds[1] >= 0) { close(pipeFds[1]); } LW_SAFE_FREE_STRING(pTempOutput); return error; }