Ejemplo n.º 1
0
NTSTATUS
SqliteOpenKeyInternal(
	IN HANDLE handle,
    IN PCWSTR pwszFullKeyName, // Full Key Path
    IN ACCESS_MASK AccessDesired,
    OUT OPTIONAL PREG_KEY_HANDLE* ppKeyHandle
    )
{
	NTSTATUS status = STATUS_SUCCESS;
	PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)handle;
    BOOLEAN bInLock = FALSE;

    BAIL_ON_NT_INVALID_STRING(pwszFullKeyName);

    BAIL_ON_NT_INVALID_POINTER(handle);

    if (!pServerState->pToken)
    {
        status = RegSrvCreateAccessToken(pServerState->peerUID,
                                         pServerState->peerGID,
                                         &pServerState->pToken);
        BAIL_ON_NT_STATUS(status);
    }

    LWREG_LOCK_MUTEX(bInLock, &gActiveKeyList.mutex);

    // pServerState->pToken should be created at this point
    status = SqliteOpenKeyInternal_inlock(handle,
    		                              pwszFullKeyName,
    		                              AccessDesired,
    		                              ppKeyHandle);
    BAIL_ON_NT_STATUS(status);

cleanup:
    LWREG_UNLOCK_MUTEX(bInLock, &gActiveKeyList.mutex);

    return status;

error:
    goto cleanup;
}
Ejemplo n.º 2
0
/* Create a new key, if the key exists already,
 * open the existing key
 */
NTSTATUS
SqliteCreateKeyInternal(
    IN OPTIONAL HANDLE handle,
    IN PREG_KEY_CONTEXT pParentKeyCtx,
    IN PWSTR pwszFullKeyName, // Full Key Path
    IN ACCESS_MASK AccessDesired,
    IN OPTIONAL PSECURITY_DESCRIPTOR_RELATIVE pSecDescRel,
    IN ULONG ulSecDescLength,
    OUT OPTIONAL PREG_KEY_HANDLE* ppKeyHandle,
    OUT OPTIONAL PDWORD pdwDisposition
    )
{
	NTSTATUS status = STATUS_SUCCESS;
    PREG_DB_KEY pRegEntry = NULL;
    PREG_KEY_HANDLE pKeyHandle = NULL;
    PREG_KEY_CONTEXT pKeyCtx = NULL;
    BOOLEAN bInLock = FALSE;
    PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)handle;
    PSECURITY_DESCRIPTOR_RELATIVE pSecDescRelToSet = NULL;
    ULONG ulSecDescLengthToSet = 0;
    DWORD dwDisposition = 0;

    // Full key path
    BAIL_ON_NT_INVALID_STRING(pwszFullKeyName);

    // when starting up lwregd pServerState is NULL and
    // creating root key can skip ACL check
    if (pServerState && !pServerState->pToken)
    {
        status = RegSrvCreateAccessToken(pServerState->peerUID,
                                         pServerState->peerGID,
                                         &pServerState->pToken);
        BAIL_ON_NT_STATUS(status);
    }

    LWREG_LOCK_MUTEX(bInLock, &gActiveKeyList.mutex);

	status = SqliteOpenKeyInternal_inlock(
			        handle,
			        pwszFullKeyName, // Full Key Path
	                AccessDesired,
	                &pKeyHandle);
	if (!status)
	{
		dwDisposition = REG_OPENED_EXISTING_KEY;

		goto done;
	}
	else if (STATUS_OBJECT_NAME_NOT_FOUND == status)
	{
		status = 0;
	}
	BAIL_ON_NT_STATUS(status);

	// Root Key has to be created with a given SD
	if (!pParentKeyCtx && !pSecDescRel)
	{
		status = STATUS_INTERNAL_ERROR;
		BAIL_ON_NT_STATUS(status);
	}

	// ACL check
	// Get key's security descriptor
	// Inherit from its direct parent or given by caller
	if (!pSecDescRel || !ulSecDescLength)
	{
		BAIL_ON_INVALID_KEY_CONTEXT(pParentKeyCtx);

		status = SqliteCacheKeySecurityDescriptor(pParentKeyCtx);
		BAIL_ON_NT_STATUS(status);

		pSecDescRelToSet = pParentKeyCtx->pSecurityDescriptor;
		ulSecDescLengthToSet = pParentKeyCtx->ulSecDescLength;
	}
	else
	{
		pSecDescRelToSet = pSecDescRel;
		ulSecDescLengthToSet = ulSecDescLength;
	}

	// Make sure SD has at least owner information
	if (!RtlValidRelativeSecurityDescriptor(pSecDescRelToSet,
			                                ulSecDescLengthToSet,
			                                OWNER_SECURITY_INFORMATION))
	{
		status = STATUS_INVALID_SECURITY_DESCR;
		BAIL_ON_NT_STATUS(status);
	}

	// Create key with SD
	status = RegDbCreateKey(ghCacheConnection,
							pwszFullKeyName,
							pSecDescRelToSet,
							ulSecDescLengthToSet,
							&pRegEntry);
	BAIL_ON_NT_STATUS(status);

    if (pParentKeyCtx)
	{
	    SqliteCacheResetParentKeySubKeyInfo_inlock(pParentKeyCtx->pwszKeyName);
	}

	status = SqliteCreateKeyContext(pRegEntry, &pKeyCtx);
	BAIL_ON_NT_STATUS(status);

	// Cache this new key in gActiveKeyList
	status = SqliteCacheInsertActiveKey_inlock(pKeyCtx);
	BAIL_ON_NT_STATUS(status);

	status = SqliteCreateKeyHandle(pServerState ? pServerState->pToken : NULL,
	                               AccessDesired,
	                               pKeyCtx,
	                               &pKeyHandle);
	BAIL_ON_NT_STATUS(status);
	pKeyCtx = NULL;

	dwDisposition = REG_CREATED_NEW_KEY;

done:
    if (ppKeyHandle)
	{
		*ppKeyHandle = pKeyHandle;
	}
	else
	{
		SqliteSafeFreeKeyHandle_inlock(pKeyHandle);
	}

    if (pdwDisposition)
    {
    	*pdwDisposition =  dwDisposition;
    }

cleanup:

    SqliteReleaseKeyContext_inlock(pKeyCtx);

    LWREG_UNLOCK_MUTEX(bInLock, &gActiveKeyList.mutex);

    RegDbSafeFreeEntryKey(&pRegEntry);

    return status;

error:

    if (ppKeyHandle)
    {
	    *ppKeyHandle = NULL;
    }

    SqliteSafeFreeKeyHandle_inlock(pKeyHandle);

    goto cleanup;
}
Ejemplo n.º 3
0
NTSTATUS
MemOpenKeyEx(
    IN HANDLE Handle,
    IN HKEY hKey,
    IN OPTIONAL PCWSTR pwszSubKey,
    IN DWORD ulOptions,
    IN ACCESS_MASK AccessDesired,
    OUT PHKEY phkResult
    )
{
    NTSTATUS status = 0;
    PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE)hKey;
    PREG_KEY_HANDLE *phKeyResult = (PREG_KEY_HANDLE *)phkResult;
    PMEMREG_NODE pSubKey = NULL;
    REG_DB_CONNECTION regDbConn = {0};
    PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)Handle;
    BOOLEAN bInLock = FALSE;

    if (!pServerState->pToken)
    {
        status = RegSrvCreateAccessToken(pServerState->peerUID,
                                         pServerState->peerGID,
                                         &pServerState->pToken);
        BAIL_ON_NT_STATUS(status);
    }

    LWREG_LOCK_RWMUTEX_SHARED(bInLock, &MemRegRoot()->lock);
    if (!hKey)
    {
        // Search for specified root key. If NULL, return HKTM.
        status = MemDbOpenKey(
                     Handle,
                     NULL,
                     pwszSubKey,
                     AccessDesired,
                     &pSubKey);
        BAIL_ON_NT_STATUS(status);
    }
    else if (pKeyHandle->pKey->hNode)
    {
        regDbConn.pMemReg = pKeyHandle->pKey->hNode;
        status = MemDbOpenKey(
                     Handle,
                     &regDbConn,
                     pwszSubKey,
                     AccessDesired,
                     &pSubKey);
        BAIL_ON_NT_STATUS(status);
    }

    if (phKeyResult)
    {
        status = _MemCreateHkeyReply(
                     pSubKey,
                     phkResult);
        BAIL_ON_NT_STATUS(status);
    }


cleanup:
    LWREG_UNLOCK_RWMUTEX(bInLock, &MemRegRoot()->lock);
    return status;

error:
    goto cleanup;
}
Ejemplo n.º 4
0
NTSTATUS
SqliteGetValueAttributes_Internal(
    IN HANDLE hRegConnection,
    IN HKEY hKey,
    IN OPTIONAL PCWSTR pwszSubKey,
    IN PCWSTR pValueName,
    IN OPTIONAL REG_DATA_TYPE dwType,
    // Whether bail or not in case there is no value attributes
    IN BOOLEAN bDoBail,
    OUT OPTIONAL PLWREG_CURRENT_VALUEINFO* ppCurrentValue,
    OUT OPTIONAL PLWREG_VALUE_ATTRIBUTES* ppValueAttributes
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PWSTR pwszValueName = NULL;
    PREG_DB_VALUE_ATTRIBUTES pRegEntry = NULL;
    PREG_DB_VALUE pRegValueEntry = NULL;
    BOOLEAN bIsWrongType = FALSE;
    wchar16_t wszEmptyValueName[] = REG_EMPTY_VALUE_NAME_W;
    PWSTR pwszKeyNameWithSubKey = NULL;
    PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE)hKey;
    PREG_KEY_CONTEXT pKeyCtx = NULL;
    PREG_KEY_HANDLE pKeyHandleInUse = NULL;
    PREG_KEY_CONTEXT pKeyCtxInUse = NULL;
    PLWREG_CURRENT_VALUEINFO pCurrentValue = NULL;
    BOOLEAN bInDbLock = FALSE;
    BOOLEAN bInLock = FALSE;
    PSTR pszError = NULL;
    PREG_DB_CONNECTION pConn = (PREG_DB_CONNECTION)ghCacheConnection;
    PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)hRegConnection;

    BAIL_ON_NT_INVALID_POINTER(pKeyHandle);
    pKeyCtx = pKeyHandle->pKey;
    BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtx);

    if (!ppCurrentValue && !ppValueAttributes)
    {
        status = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(status);
    }

    if (pwszSubKey)
    {
        status = LwRtlWC16StringAllocatePrintfW(
                        &pwszKeyNameWithSubKey,
                        L"%ws\\%ws",
                        pKeyCtx->pwszKeyName,
                        pwszSubKey);
        BAIL_ON_NT_STATUS(status);
    }

    if (!pServerState->pToken)
    {
        status = RegSrvCreateAccessToken(pServerState->peerUID,
                                         pServerState->peerGID,
                                         &pServerState->pToken);
        BAIL_ON_NT_STATUS(status);
    }

    LWREG_LOCK_MUTEX(bInLock, &gActiveKeyList.mutex);

    ENTER_SQLITE_LOCK(&pConn->lock, bInDbLock);

    status = sqlite3_exec(
                    pConn->pDb,
                    "begin;",
                    NULL,
                    NULL,
                    &pszError);
    BAIL_ON_SQLITE3_ERROR(status, pszError);

    // pServerState->pToken should be created at this point
    status = SqliteOpenKeyInternal_inlock_inDblock(
                              hRegConnection,
                              pwszSubKey ? pwszKeyNameWithSubKey : pKeyCtx->pwszKeyName,
                              KEY_QUERY_VALUE,
                              &pKeyHandleInUse);
    BAIL_ON_NT_STATUS(status);

    // ACL check
    status = RegSrvAccessCheckKeyHandle(pKeyHandleInUse, KEY_QUERY_VALUE);
    BAIL_ON_NT_STATUS(status);

    pKeyCtxInUse = pKeyHandleInUse->pKey;
    BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtxInUse);

    status = LwRtlWC16StringDuplicate(&pwszValueName, !pValueName ? wszEmptyValueName : pValueName);
    BAIL_ON_NT_STATUS(status);

    // Optionally get value
    if (ppCurrentValue)
    {
        status = RegDbGetKeyValue_inlock(
                                  ghCacheConnection,
                                  pKeyCtxInUse->qwId,
                                  pwszValueName,
                                  dwType,
                                  &bIsWrongType,
                                  &pRegValueEntry);
        if (!status)
        {
            status = LW_RTL_ALLOCATE((PVOID*)&pCurrentValue,
                                      LWREG_CURRENT_VALUEINFO,
                                      sizeof(*pCurrentValue));
            BAIL_ON_NT_STATUS(status);

            pCurrentValue->cbData = pRegValueEntry->dwValueLen;
            pCurrentValue->dwType = pRegValueEntry->type;

            if (pCurrentValue->cbData)
            {
                status = LW_RTL_ALLOCATE((PVOID*)&pCurrentValue->pvData,
                                         VOID,
                                         pCurrentValue->cbData);
                BAIL_ON_NT_STATUS(status);

                memcpy(pCurrentValue->pvData, pRegValueEntry->pValue, pCurrentValue->cbData);
            }
        }
        else if (LW_STATUS_OBJECT_NAME_NOT_FOUND ==  status)
        {
            status = 0;
        }
        BAIL_ON_NT_STATUS(status);
    }

    // Get value attributes
    if (ppValueAttributes)
    {
        status = RegDbGetValueAttributes_inlock(
                                         ghCacheConnection,
                                         pKeyCtxInUse->qwId,
                                         pwszValueName,
                                         REG_NONE,
                                         &bIsWrongType,
                                         &pRegEntry);
        if (!bDoBail && LW_STATUS_OBJECT_NAME_NOT_FOUND == status)
        {
            status = LW_RTL_ALLOCATE((PVOID*)&pRegEntry,
                                     REG_DB_VALUE_ATTRIBUTES,
                                     sizeof(*pRegEntry));
            BAIL_ON_NT_STATUS(status);
        }
        BAIL_ON_NT_STATUS(status);
    }

    status = sqlite3_exec(
                    pConn->pDb,
                    "end",
                    NULL,
                    NULL,
                    &pszError);
    BAIL_ON_SQLITE3_ERROR(status, pszError);

    REG_LOG_VERBOSE("Registry::sqldb.c SqliteGetValueAttributes_Internal() finished");

    if (ppCurrentValue)
    {
        *ppCurrentValue = pCurrentValue;
        pCurrentValue = NULL;
    }

    if (ppValueAttributes)
    {
        *ppValueAttributes = pRegEntry->pValueAttributes;
        pRegEntry->pValueAttributes = NULL;
    }

cleanup:

    LEAVE_SQLITE_LOCK(&pConn->lock, bInDbLock);

    LWREG_UNLOCK_MUTEX(bInLock, &gActiveKeyList.mutex);

    SqliteSafeFreeKeyHandle(pKeyHandleInUse);
    LWREG_SAFE_FREE_MEMORY(pwszValueName);
    LWREG_SAFE_FREE_MEMORY(pwszKeyNameWithSubKey);
    RegDbSafeFreeEntryValue(&pRegValueEntry);

    RegSafeFreeCurrentValueInfo(&pCurrentValue);
    RegDbSafeFreeEntryValueAttributes(&pRegEntry);

    return status;

error:
    if (pszError)
    {
        sqlite3_free(pszError);
    }
    sqlite3_exec(pConn->pDb,
                 "rollback",
                 NULL,
                 NULL,
                 NULL);

    if (ppCurrentValue)
    {
        *ppCurrentValue = NULL;
    }

    if (ppValueAttributes)
    {
        *ppValueAttributes  = NULL;
    }

    goto cleanup;
}
Ejemplo n.º 5
0
NTSTATUS
MemCreateKeyEx(
    IN HANDLE Handle,
    IN HKEY hKey,
    IN PCWSTR pSubKey,
    IN DWORD dwReserved,
    IN OPTIONAL PWSTR pClass,
    IN DWORD dwOptions,
    IN ACCESS_MASK AccessDesired,
    IN OPTIONAL PSECURITY_DESCRIPTOR_RELATIVE pSecDescRel,
    IN ULONG ulSecDescLength,
    OUT PHKEY phkResult,
    OUT OPTIONAL PDWORD pdwDisposition
    )
{
    NTSTATUS status = 0;
    PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE)hKey;
    PMEMREG_NODE hRootKey = NULL;
    PMEMREG_NODE hSubKey = NULL;
    REG_DB_CONNECTION regDbConn = {0};
    PWSTR pwszRootKey = NULL;
    PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)Handle;
    ACCESS_MASK AccessGranted = 0;
    PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = NULL;
    DWORD SecurityDescriptorLen = 0;
    BOOLEAN bInLock = FALSE;

    LWREG_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &MemRegRoot()->lock);
    if (!hKey)
    {
        status = LwRtlWC16StringAllocateFromCString(
                     &pwszRootKey,
                     HKEY_THIS_MACHINE);
        BAIL_ON_NT_STATUS(status);

        // Search for specified root key. If NULL, return HKTM.
        status = MemDbOpenKey(
                     Handle,
                     NULL,
                     pwszRootKey,
                     AccessDesired,
                     &hRootKey);
        BAIL_ON_NT_STATUS(status);
        regDbConn.pMemReg = hRootKey;
    }
    else
    {
        regDbConn.pMemReg = pKeyHandle->pKey->hNode;
    }

    if (!pServerState->pToken)
    {
        status = RegSrvCreateAccessToken(pServerState->peerUID,
                                         pServerState->peerGID,
                                         &pServerState->pToken);
        BAIL_ON_NT_STATUS(status);
    }

    if (pSecDescRel)
    {
        SecurityDescriptor = pSecDescRel;
        SecurityDescriptorLen = ulSecDescLength;
    }
    else
    {
        SecurityDescriptor =
            pKeyHandle->pKey->hNode->pNodeSd->SecurityDescriptor;
        SecurityDescriptorLen =
            pKeyHandle->pKey->hNode->pNodeSd->SecurityDescriptorLen;
    }

    if (SecurityDescriptor)
    {
        status = RegSrvAccessCheckKey(pServerState->pToken,
                                      SecurityDescriptor,
                                      SecurityDescriptorLen,
                                      AccessDesired,
                                      &AccessGranted);
    }

    if (STATUS_NO_TOKEN == status)
    {
        status = 0;
        AccessGranted = 0;
    }
    BAIL_ON_NT_STATUS(status);

    status = MemDbCreateKeyEx(
                 Handle,  // Access token is on this handle
                 &regDbConn,
                 pSubKey,
                 0, // IN DWORD dwReserved
                 NULL, // IN OPTIONAL PWSTR pClass
                 0, //IN DWORD dwOptions
                 AccessDesired, // IN ACCESS_MASK
                 pSecDescRel, // IN OPTIONAL
                 ulSecDescLength, // IN ULONG
                 &hSubKey,
                 pdwDisposition);
    BAIL_ON_NT_STATUS(status);

    status = _MemCreateHkeyReply(hSubKey, phkResult);
    BAIL_ON_NT_STATUS(status);

    pKeyHandle->AccessGranted = AccessGranted;
    hSubKey->NodeRefCount++;

    MemDbExportEntryChanged();

cleanup:
    LWREG_UNLOCK_RWMUTEX(bInLock, &MemRegRoot()->lock);
    LWREG_SAFE_FREE_MEMORY(pwszRootKey);
    return status;

error:
    if (hRootKey)
    {
        // Close open root key
    }
    goto cleanup;
}