static DWORD LocalFindAttribute( PDIRECTORY_ENTRY pEntry, PWSTR pwszAttrName, PDIRECTORY_ATTRIBUTE* ppAttr ) { DWORD dwError = 0; PDIRECTORY_ATTRIBUTE pAttr = NULL; DWORD iAttr = 0; for (; iAttr < pEntry->ulNumAttributes; iAttr++) { pAttr = &pEntry->pAttributes[iAttr]; if (!wc16scasecmp(pAttr->pwszName, pwszAttrName)) { break; } pAttr = NULL; } if (!pAttr) { dwError = LW_ERROR_NO_SUCH_ATTRIBUTE; BAIL_ON_LSA_ERROR(dwError); } *ppAttr = pAttr; cleanup: return dwError; error: *ppAttr = NULL; goto cleanup; }
NTSTATUS SamrSrvLookupDomain( /* [in] */ handle_t hBinding, /* [in] */ CONNECT_HANDLE hConn, /* [in] */ UNICODE_STRING *domain_name, /* [out] */ SID **ppSid ) { CHAR szDnToken[] = "DC"; wchar_t wszFilter[] = L"%ws=%u AND %ws=\'%ws\'"; NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = 0; PCONNECT_CONTEXT pConnCtx = NULL; PWSTR pwszBase = NULL; WCHAR wszAttrObjectClass[] = DS_ATTR_OBJECT_CLASS; WCHAR wszAttrDomain[] = DS_ATTR_DOMAIN; WCHAR wszAttrObjectSID[] = DS_ATTR_OBJECT_SID; DWORD dwObjectClass = DS_OBJECT_CLASS_DOMAIN; WCHAR wszBuiltinDomainName[] = SAMR_BUILTIN_DOMAIN_NAME; PWSTR pwszDomainName = NULL; DWORD dwBaseLen = 0; DWORD dwScope = 0; PWSTR pwszFilter = NULL; DWORD dwFilterLen = 0; PWSTR wszAttributes[2]; PDIRECTORY_ENTRY pEntries = NULL; DWORD dwCount = 0; PDIRECTORY_ATTRIBUTE pAttr = NULL; PATTRIBUTE_VALUE pAttrVal = NULL; PSID pDomainSid = NULL; BAIL_ON_INVALID_PARAMETER(ppSid); BAIL_ON_INVALID_PARAMETER(domain_name); memset(wszAttributes, 0, sizeof(wszAttributes)); pConnCtx = (PCONNECT_CONTEXT)hConn; if (pConnCtx == NULL || pConnCtx->Type != SamrContextConnect) { ntStatus = STATUS_INVALID_HANDLE; BAIL_ON_NTSTATUS_ERROR(ntStatus); } ntStatus = SamrSrvGetFromUnicodeString(&pwszDomainName, domain_name); BAIL_ON_NO_MEMORY(pwszDomainName); if (!wc16scasecmp(pwszDomainName, wszBuiltinDomainName)) { dwObjectClass = DS_OBJECT_CLASS_BUILTIN_DOMAIN; } dwBaseLen = domain_name->MaximumLength + ((sizeof(szDnToken) + 2) * sizeof(WCHAR)); dwFilterLen = (sizeof(wszAttrObjectClass) - 1) + 10 + (sizeof(wszAttrDomain) - 1) + domain_name->Length + sizeof(wszFilter); ntStatus = SamrSrvAllocateMemory(OUT_PPVOID(&pwszFilter), dwFilterLen); BAIL_ON_NTSTATUS_ERROR(ntStatus); if (sw16printfw(pwszFilter, dwFilterLen/sizeof(WCHAR), wszFilter, wszAttrObjectClass, dwObjectClass, wszAttrDomain, pwszDomainName) < 0) { ntStatus = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(ntStatus); } wszAttributes[0] = wszAttrObjectSID; wszAttributes[1] = NULL; dwError = DirectorySearch(pConnCtx->hDirectory, pwszBase, dwScope, pwszFilter, wszAttributes, FALSE, &pEntries, &dwCount); BAIL_ON_LSA_ERROR(dwError); if (dwCount == 1) { dwError = DirectoryGetEntryAttributeSingle(pEntries, &pAttr); BAIL_ON_LSA_ERROR(dwError); dwError = DirectoryGetAttributeValue(pAttr, &pAttrVal); BAIL_ON_LSA_ERROR(dwError); if (pAttrVal->Type == DIRECTORY_ATTR_TYPE_UNICODE_STRING) { ntStatus = SamrSrvAllocateSidFromWC16String( &pDomainSid, pAttrVal->data.pwszStringValue); BAIL_ON_NTSTATUS_ERROR(ntStatus); } else { ntStatus = STATUS_INTERNAL_ERROR; BAIL_ON_NTSTATUS_ERROR(ntStatus); } } else if (dwCount == 0) { ntStatus = STATUS_NO_SUCH_DOMAIN; BAIL_ON_NTSTATUS_ERROR(ntStatus); } else { ntStatus = STATUS_INTERNAL_ERROR; BAIL_ON_NTSTATUS_ERROR(ntStatus); } *ppSid = pDomainSid; cleanup: if (pwszBase) { SamrSrvFreeMemory(pwszBase); } if (pwszDomainName) { SamrSrvFreeMemory(pwszDomainName); } if (pwszFilter) { SamrSrvFreeMemory(pwszFilter); } if (pEntries) { DirectoryFreeEntries(pEntries, dwCount); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: if (pDomainSid) { SamrSrvFreeMemory(&pDomainSid); } *ppSid = NULL; goto cleanup; }
static DWORD SamDbBuildSqlQuery( PSAM_DIRECTORY_CONTEXT pDirectoryContext, PWSTR pwszFilter, PWSTR wszAttributes[], ULONG ulAttributesOnly, PSTR* ppszQuery, PBOOLEAN pbMembersAttrExists, PSAM_DB_COLUMN_VALUE* ppColumnValueList ) { DWORD dwError = 0; BOOLEAN bMembersAttrExists = FALSE; DWORD dwQueryLen = 0; DWORD dwColNamesLen = 0; DWORD dwNumAttrs = 0; PSTR pszQuery = NULL; PSTR pszQueryCursor = NULL; PSTR pszCursor = NULL; PSTR pszFilter = NULL; PSAM_DB_COLUMN_VALUE pColumnValueList = NULL; PSAM_DB_COLUMN_VALUE pIter = NULL; if (pwszFilter) { dwError = LwWc16sToMbs( pwszFilter, &pszFilter); BAIL_ON_SAMDB_ERROR(dwError); LwStripWhitespace(pszFilter, TRUE, TRUE); } while (wszAttributes[dwNumAttrs]) { PWSTR pwszAttrName = wszAttributes[dwNumAttrs]; wchar16_t wszMembersAttrName[] = SAM_DB_DIR_ATTR_MEMBERS; if (!wc16scasecmp(pwszAttrName, &wszMembersAttrName[0])) { bMembersAttrExists = TRUE; } else { PSAM_DB_COLUMN_VALUE pColumnValue = NULL; PSAM_DB_ATTRIBUTE_MAP pAttrMap = NULL; dwError = SamDbAttributeLookupByName( pDirectoryContext->pAttrLookup, pwszAttrName, &pAttrMap); BAIL_ON_SAMDB_ERROR(dwError); if (!pAttrMap->bIsQueryable) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_SAMDB_ERROR(dwError); } dwError = DirectoryAllocateMemory( sizeof(SAM_DB_COLUMN_VALUE), (PVOID*)&pColumnValue); BAIL_ON_SAMDB_ERROR(dwError); pColumnValue->pAttrMap = pAttrMap; pColumnValue->pNext = pColumnValueList; pColumnValueList = pColumnValue; pColumnValue = NULL; if (dwColNamesLen) { dwColNamesLen += sizeof(SAM_DB_SEARCH_QUERY_FIELD_SEPARATOR)-1; } dwColNamesLen += strlen(&pAttrMap->szDbColumnName[0]); } dwNumAttrs++; } dwQueryLen = sizeof(SAM_DB_SEARCH_QUERY_PREFIX) - 1; dwQueryLen += dwColNamesLen; dwQueryLen += sizeof(SAM_DB_SEARCH_QUERY_FROM) - 1; if (pszFilter && *pszFilter) { dwQueryLen += sizeof(SAM_DB_SEARCH_QUERY_WHERE) - 1; dwQueryLen += strlen(pszFilter); } dwQueryLen += sizeof(SAM_DB_SEARCH_QUERY_SUFFIX) - 1; dwQueryLen++; dwError = DirectoryAllocateMemory( dwQueryLen, (PVOID*)&pszQuery); BAIL_ON_SAMDB_ERROR(dwError); pColumnValueList = SamDbReverseColumnValueList(pColumnValueList); pszQueryCursor = pszQuery; dwColNamesLen = 0; pszCursor = SAM_DB_SEARCH_QUERY_PREFIX; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; } for (pIter = pColumnValueList; pIter; pIter = pIter->pNext) { if (dwColNamesLen) { pszCursor = SAM_DB_SEARCH_QUERY_FIELD_SEPARATOR; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; dwColNamesLen++; } } pszCursor = &pIter->pAttrMap->szDbColumnName[0]; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; dwColNamesLen++; } } pszCursor = SAM_DB_SEARCH_QUERY_FROM; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; } if (pszFilter && *pszFilter) { pszCursor = SAM_DB_SEARCH_QUERY_WHERE; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; } pszCursor = pszFilter; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; } } pszCursor = SAM_DB_SEARCH_QUERY_SUFFIX; while (pszCursor && *pszCursor) { *pszQueryCursor++ = *pszCursor++; } *ppszQuery = pszQuery; *pbMembersAttrExists = bMembersAttrExists; *ppColumnValueList = pColumnValueList; cleanup: DIRECTORY_FREE_STRING(pszFilter); return dwError; error: *ppszQuery = NULL; *pbMembersAttrExists = FALSE; *ppColumnValueList = NULL; DIRECTORY_FREE_STRING(pszQuery); if (pColumnValueList) { SamDbFreeColumnValueList(pColumnValueList); } goto cleanup; }
/** * @brief Get Local Share path based on Windows path * When migrating shares, we want to create all shares under the * folder where our C$ is set to. * * The Likewise CIFS code maps C$ itself to /. * * For instance, if the remote share was at the physical path * C:\likewise, and our default share path was "/lwcifs", we would map * the remote path "C:\likewise" to "C:\lwcifs\likewise". * */ DWORD LwTaskGetLocalSharePathW( PWSTR pwszSharePathWindows, PWSTR* ppwszSharePathLocal ) { DWORD dwError = 0; wchar16_t wszBackslash[] = {'\\', 0}; wchar16_t wszFwdslash[] = {'/', 0}; wchar16_t wszColon[] = {':', 0}; size_t sSharePathWindowsLen = 0; size_t sRequiredLen = 0; size_t sFSPrefixLen = 3; // length("C:\"); PWSTR pwszPathReadCursor = pwszSharePathWindows; PWSTR pwszPathWriteCursor = NULL; PWSTR pwszSharePathLocal = NULL; PWSTR pwszDefaultSharePath = NULL; if (IsNullOrEmptyString(pwszSharePathWindows)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LW_TASK_ERROR(dwError); } pwszDefaultSharePath = gLwTaskGlobals.pwszDefaultSharePath; while (!IsNullOrEmptyString(pwszDefaultSharePath) && ((*pwszDefaultSharePath == wszBackslash[0]) || (*pwszDefaultSharePath == wszFwdslash[0]))) { pwszDefaultSharePath++; } if (IsNullOrEmptyString(pwszDefaultSharePath)) { dwError = LwAllocateWc16String( &pwszSharePathLocal, pwszSharePathWindows); BAIL_ON_LW_TASK_ERROR(dwError); goto done; } sSharePathWindowsLen = wc16slen(pwszSharePathWindows); if (((pwszSharePathWindows[1] != wszColon[0]) && !(pwszSharePathWindows[2] == wszBackslash[0] || pwszSharePathWindows[2] == wszFwdslash[0]))) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LW_TASK_ERROR(dwError); } else { pwszPathReadCursor += sFSPrefixLen; } if ((wc16slen(pwszPathReadCursor) >= wc16slen(pwszDefaultSharePath)) && !wc16scasecmp(pwszPathReadCursor, pwszDefaultSharePath)) { // Already have the required prefix ? dwError = LwAllocateWc16String( &pwszSharePathLocal, pwszSharePathWindows); BAIL_ON_LW_TASK_ERROR(dwError); goto done; } sRequiredLen = (wc16slen(pwszSharePathWindows) + wc16slen(pwszDefaultSharePath) + 2 )* sizeof(wchar16_t); dwError = LwAllocateMemory(sRequiredLen, (PVOID*)&pwszSharePathLocal); BAIL_ON_LW_TASK_ERROR(dwError); pwszPathWriteCursor = pwszSharePathLocal; pwszPathReadCursor = pwszSharePathWindows; memcpy( (PBYTE)pwszPathWriteCursor, (PBYTE)pwszPathReadCursor, sFSPrefixLen * sizeof(wchar16_t)); pwszPathWriteCursor += sFSPrefixLen; pwszPathReadCursor += sFSPrefixLen; memcpy( (PBYTE)pwszPathWriteCursor, (PBYTE)pwszDefaultSharePath, wc16slen(pwszDefaultSharePath) * sizeof(wchar16_t)); pwszPathWriteCursor += wc16slen(pwszDefaultSharePath); *pwszPathWriteCursor++ = wszBackslash[0]; memcpy( (PBYTE)pwszPathWriteCursor, (PBYTE)pwszPathReadCursor, wc16slen(pwszPathReadCursor) * sizeof(wchar16_t)); pwszPathWriteCursor = pwszSharePathLocal; while (!IsNullOrEmptyString(pwszPathWriteCursor)) { if (*pwszPathWriteCursor == wszFwdslash[0]) { *pwszPathWriteCursor = wszBackslash[0]; } pwszPathWriteCursor++; } done: *ppwszSharePathLocal = pwszSharePathLocal; cleanup: return dwError; error: *ppwszSharePathLocal = NULL; LW_SAFE_FREE_MEMORY(pwszSharePathLocal); goto cleanup; }
DWORD SamDbGetObjectClass( DIRECTORY_MOD Modifications[], SAMDB_OBJECT_CLASS* pObjectClass ) { DWORD dwError = 0; SAMDB_OBJECT_CLASS objectClass = SAMDB_OBJECT_CLASS_UNKNOWN; wchar16_t pwszObjectClassAttr[] = SAM_DB_DIR_ATTR_OBJECT_CLASS; DWORD dwNumMods = 0; while (Modifications[dwNumMods].pwszAttrName && Modifications[dwNumMods].pAttrValues) { if (!wc16scasecmp(&pwszObjectClassAttr[0], Modifications[dwNumMods].pwszAttrName)) { PATTRIBUTE_VALUE pAttrValue = NULL; if (Modifications[dwNumMods].ulNumValues != 1) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_SAMDB_ERROR(dwError); } pAttrValue = &Modifications[dwNumMods].pAttrValues[0]; if (pAttrValue->Type != DIRECTORY_ATTR_TYPE_INTEGER) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_SAMDB_ERROR(dwError); } switch (pAttrValue->data.ulValue) { case SAMDB_OBJECT_CLASS_DOMAIN: case SAMDB_OBJECT_CLASS_BUILTIN_DOMAIN: case SAMDB_OBJECT_CLASS_CONTAINER: case SAMDB_OBJECT_CLASS_LOCAL_GROUP: case SAMDB_OBJECT_CLASS_LOCALGRP_MEMBER: case SAMDB_OBJECT_CLASS_USER: objectClass = pAttrValue->data.ulValue; break; default: dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_SAMDB_ERROR(dwError); break; } break; } dwNumMods++; } *pObjectClass = objectClass; cleanup: return dwError; error: *pObjectClass = SAMDB_OBJECT_CLASS_UNKNOWN; goto cleanup; }