Microsoft.Web.RedisSessionStateProvider not saving value - asp.net-mvc

Problem
A session value is not being retrieved in a Razor view and is causing faulty logic.
Environment
Redis sentinel with sentinel on web servers but only a single redis master and single redis slave. The redis connection string is pointing to both master and slave.
Code
In a controller before the view:
var fooLocal = fooMapper.Map(fooDbCall.GetFromDb(fooValue));
if (fooLocal != null)
{
Session["FooSession"] = fooLocal.fooProperty;
}
else
{
Session["FooSession"] = false;
}
In the view
#if (fooRazorVal == 123)
{
// show some stuff
}
else if (!((bool?)Session["FooSession"] ?? false) && (fooRazorVal2 == 456))
{
// show error message
}
else
{
// show other stuff
}
Result
The error message is shown even when an account in question has been walked back through the code and database to verify it should not be false let alone null. Other session values are stored and retrieved fine or else you wouldn't even make it this far in my process.
Investigation
As I mentioned, all other code bits and the database have been verified. I added a logging class and there are lots of entries like so:
[Info]GetItemFromSessionStore => Session Id: ctps3urcqwm0tpezo5bbmqzj, Session provider object: 4686063 => Can not lock, Someone else has lock and lockId is 636901606595110722
[Info]GetItemFromSessionStore => Session Id: ctps3urcqwm0tpezo5bbmqzj, Session provider object: 26422156 => Lock taken with lockId: 636901606595110722
[Info]GetItemFromSessionStore => Session Id: ctps3urcqwm0tpezo5bbmqzj, Session provider object: 4686063 => Can not lock, Someone else has lock and lockId is 636901606595110722
However, given the sheer number of them, I'm wondering if this is actually an error or the RedisSessionStateProvider working as intended. I did see that it uses SETNX to acquire locks. Unfortunately, I'm not well versed enough in redis semantics to know if this is causing an issue.
I did see a note on the Redis docs about this being an old approach and to use RedLock instead. However, as I understand RedLock, a single master/single slave setup is not sufficient although it does support retries so maybe it would work anyway. I'm also curious if I should roll a simple custom provider that lets StackExhange's ConnectionMultiplexer work without extra locks or custom scripts and if I do need locks to use one of the C# libraries for RedLock.

By design, Redis keys are locked during update, you don't need to lock them. Indeed, Redis uses a single thread to process commands, so each operation is atomic. Other clients are blocked during the processing of a given command, that's why you mustn't perform queries with a long execution time and you are getting this error.
To prevent that one must implement distributed lock. Distributed locks are a very useful primitive in many environments where different processes must operate with shared resources in a mutually exclusive way.
Here are the different implementation for different language.
Implementations
Here are a few links to implementations already available that can be used for reference.
• Redlock-rb (Ruby implementation). There is also a fork of Redlock-rb that adds a gem for easy distribution and perhaps more.
• Redlock-py (Python implementation).
• Aioredlock (Asyncio Python implementation).
• Redlock-php (PHP implementation).
• PHPRedisMutex (further PHP implementation)
• Redsync.go (Go implementation).
• Redisson (Java implementation).
• Redis::DistLock (Perl implementation).
• Redlock-cpp (C++ implementation).
• Redlock-cs (C#/.NET implementation).
• RedLock.net (C#/.NET implementation). Includes async and lock extension support.
• ScarletLock (C# .NET implementation with configurable datastore)
• node-redlock (NodeJS implementation). Includes support for lock extension.
See if this helps.

Related

Detect & Block Read/WriteProcessMemory calls from a Driver

Hi i'm relativly new to kernel programming (i've got a lot of c++ development experience though) and have a goal that i want to achieve:
Detecting and conditionally blocking attempts from userland programs to write or read to specific memory addresses located in my own userland process. This has to be done from a driver.
I've setup a development enviorment (virtual machine running the latest windows 10 + virtualkd + windbg) and already successfully deployed a small kmdf test driver via the visual studio integration (over lan).
So my question is now:
How do i detect/intercept Read/WriteProcessMemory calls to my ring3 application? Simply blocking handles isn't enough here.
It would be nice if some one could point me into the right direction either by linking (a non outdated) example or just by telling me how to do this.
Update:
Read a lot about filter drivers and hooking Windows Apis from kernel mode, but i really dont want to mess with Patchguard and dont really know how to filter RPM calls from userland. Its not important to protect my program from drivers, only from ring3 applications.
Thank you :)
This code from here should do the trick.
OB_PREOP_CALLBACK_STATUS PreCallback(PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation)
{
UNREFERENCED_PARAMETER(RegistrationContext);
PEPROCESS OpenedProcess = (PEPROCESS)OperationInformation->Object,
CurrentProcess = PsGetCurrentProcess();
PsLookupProcessByProcessId(ProtectedProcess, &ProtectedProcessProcess); // Getting the PEPROCESS using the PID
PsLookupProcessByProcessId(Lsass, &LsassProcess); // Getting the PEPROCESS using the PID
PsLookupProcessByProcessId(Csrss1, &Csrss1Process); // Getting the PEPROCESS using the PID
PsLookupProcessByProcessId(Csrss2, &Csrss2Process); // Getting the PEPROCESS using the PID
if (OpenedProcess == Csrss1Process) // Making sure to not strip csrss's Handle, will cause BSOD
return OB_PREOP_SUCCESS;
if (OpenedProcess == Csrss2Process) // Making sure to not strip csrss's Handle, will cause BSOD
return OB_PREOP_SUCCESS;
if (OpenedProcess == CurrentProcess) // make sure the driver isnt getting stripped ( even though we have a second check )
return OB_PREOP_SUCCESS;
if (OpenedProcess == ProtectedProcess) // Making sure that the game can open a process handle to itself
return OB_PREOP_SUCCESS;
if (OperationInformation->KernelHandle) // allow drivers to get a handle
return OB_PREOP_SUCCESS;
// PsGetProcessId((PEPROCESS)OperationInformation->Object) equals to the created handle's PID, so if the created Handle equals to the protected process's PID, strip
if (PsGetProcessId((PEPROCESS)OperationInformation->Object) == ProtectedProcess)
{
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) // striping handle
{
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = (SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION);
}
else
{
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = (SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION);
}
return OB_PREOP_SUCCESS;
}
}
This code, once registered with ObRegisterCallback, will detect when a new handle is created to your protected process and will kill it if it's not coming from Lsass, Csrss, or itself. This is to prevent blue screens from critical process being denied a handle to
your application.

Particular - ServiceControl is always Stopped

I installed Service Control(V1.20.0) recently to my QA server, I install it using ServiceControl Management Utility , I didn’t change the default values, I didn’t move DB location.
I was able to browse to the RavenDB when I am in maintenance mode.
The particular endpoints are created, I also have non-expired license.
This is what i found in the db log file
Microsoft.Isam.Esent.Interop.EsentInvalidInstanceException: Invalid
instance handle at Microsoft.Isam.Esent.Interop.Api.Check(Int32
err) in
C:\Work\ravendb\SharedLibs\Sources\managedesent-61618\EsentInterop\Api.cs:line
2739 at
Microsoft.Isam.Esent.Interop.Api.JetBeginSession(JET_INSTANCE
instance, JET_SESID& sesid, String username, String password) in
C:\Work\ravendb\SharedLibs\Sources\managedesent-61618\EsentInterop\Api.cs:line
823 at
Raven.Storage.Esent.StorageActions.DocumentStorageActions..ctor(JET_INSTANCE
instance, String database, TableColumnsCache tableColumnsCache,
OrderedPartCollection`1 documentCodecs, IUuidGenerator uuidGenerator,
IDocumentCacher cacher, EsentTransactionContext transactionContext,
TransactionalStorage transactionalStorage) in
c:\Builds\RavenDB-Stable-2.5\Raven.Database\Storage\Esent\StorageActions\General.cs:line
76
With the amazing help of Particular team, I was able to solve the issue. In my case the problem was I have created the Particular.ServiceControl queue manually. And it needs to be transnational, this was the error i was getting in event viewer:
Queue must be transactional if you configure your endpoint to be
transactional
Deleting the queue, and let Service Control Management tool take care of creating all necessary queues.

Using Neo4j with React JS

Can we use graph database neo4j with react js? If not so is there any alternate option for including graph database in react JS?
Easily, all you need is neo4j-driver: https://www.npmjs.com/package/neo4j-driver
Here is the most simplistic usage:
neo4j.js
//import { v1 as neo4j } from 'neo4j-driver'
const neo4j = require('neo4j-driver').v1
const driver = neo4j.driver('bolt://localhost', neo4j.auth.basic('username', 'password'))
const session = driver.session()
session
.run(`
MATCH (n:Node)
RETURN n AS someName
`)
.then((results) => {
results.records.forEach((record) => console.log(record.get('someName')))
session.close()
driver.close()
})
It is best practice to close the session always after you get the data. It is inexpensive and lightweight.
It is best practice to only close the driver session once your program is done (like Mongo DB). You will see extreme errors if you close the driver at a bad time, which is incredibly important to note if you are beginner. You will see errors like 'connection to server closed', etc. In async code, for example, if you run a query and close the driver before the results are parsed, you will have a bad time.
You can see in my example that I close the driver after, but only to illustrate proper cleanup. If you run this code in a standalone JS file to test, you will see node.js hangs after the query and you need to press CTRL + C to exit. Adding driver.close() fixes that. Normally, the driver is not closed until the program exits/crashes, which is never in a Backend API, and not until the user logs out in the Frontend.
Knowing this now, you are off to a great start.
Remember, session.close() immediately every time, and be careful with the driver.close().
You could put this code in a React component or action creator easily and render the data.
You will find it no different than hooking up and working with Axios.
You can run statements in a transaction also, which is beneficial for writelocking affected nodes. You should research that thoroughly first, but transaction flow is like this:
const session = driver.session()
const tx = session.beginTransaction()
tx
.run(query)
.then(// same as normal)
.catch(// errors)
// the difference is you can chain multiple transactions:
const tx1 = await tx.run().then()
// use results
const tx2 = await tx.run().then()
// then, once you are ready to commit the changes:
if (results.good !== true) {
tx.rollback()
session.close()
throw error
}
await tx.commit()
session.close()
const finalResults = { tx1, tx2 }
return finalResults
// in my experience, you have to await tx.commit
// in async/await syntax conditions, otherwise it may not commit properly
// that operation is not instant
tl;dr;
Yes, you can!
You are mixing two different technologies together. Neo4j is graph database and React.js is framework for front-end.
You can connect to Neo4j from JavaScript - http://neo4j.com/developer/javascript/
Interesting topic. I am using the driver in a React App and recently experienced some issues. I am closing the session every time a lifecycle hook completes like in your example. When there where more intensive queries I would see a timeout error. Going back to my setup decided to experiment by closing the driver in some more expensive queries and it looks like (still need more testing) the crashes are gone.
If you are deploying a real-world application I would urge you to think about Authentication and Authorization when using a DB-React setup only as you would have to store username/password of the neo4j server in the client. I am looking into options of having the Neo4J server issuing a token and receiving it for Authorization but the best practice is for sure to have a Node.js server in the middle with something like Passport to handle Authentication.
So, all in all, maybe the best scenario is to only use the driver in Node and have the browser always communicating with the Node server using axios...

How to disable Rack-Mini-Profiler temporarily?

I'm using rack mini profiler in rails just fine, but during some coding sessions especially where I'm working on a lot of different client side code, it gets in the way. (mainly in my client side debugging tools network graphs, etc.)
I'm trying to turn it off with a before filter, that also serves to see if the user is authorized to see the profile anyway, but "deauthorize" doesn't seem to do anything for me. Here's my code called as a before filter:
def miniprofiler
off = true
if off || !current_user
Rack::MiniProfiler.deauthorize_request
return
elsif current_user.role_symbols.include?(:view_page_profiles)
Rack::MiniProfiler.authorize_request
return
end
Rack::MiniProfiler.deauthorize_request
end
I also know there is a setting "Rack::MiniProfiler.config.authorization_mode" but I can't find docs on what the possible settings are, and not seeing it used in the code? Right now its telling me :allow_all, but :allow_none doesn't do anything either.
Even if I can just temporarily set a value in the dev environment file and restart the server, that would serve my purposes.
Get latest and type:
http://mysite.com?pp=disable
When you are done type
http://mysite.com?pp=enable
See ?pp=help for all the options:
Append the following to your query string:
pp=help : display this screen
pp=env : display the rack environment
pp=skip : skip mini profiler for this request
pp=no-backtrace : don't collect stack traces from all the SQL executed (sticky, use pp=normal-backtrace to enable)
pp=normal-backtrace (*) : collect stack traces from all the SQL executed and filter normally
pp=full-backtrace : enable full backtraces for SQL executed (use pp=normal-backtrace to disable)
pp=sample : sample stack traces and return a report isolating heavy usage (experimental works best with the stacktrace gem)
pp=disable : disable profiling for this session
pp=enable : enable profiling for this session (if previously disabled)
pp=profile-gc: perform gc profiling on this request, analyzes ObjectSpace generated by request (ruby 1.9.3 only)
pp=profile-gc-time: perform built-in gc profiling on this request (ruby 1.9.3 only)
You can also use Alt + p to toggle on Windows/Linux and Option + p on MacOS.
If you want the profiler to be disabled initially, and then activate on demand... add a pre-authorize callback in an initializer file like:
Rack::MiniProfiler.config.pre_authorize_cb = lambda {|env| ENV['RACK_MINI_PROFILER'] == 'on'}
then in your application controller, add a before_filter that looks for the pp param
before_filter :activate_profiler
def activate_profiler
ENV['RACK_MINI_PROFILER'] = 'on' if params['pp']
ENV['RACK_MINI_PROFILER'] = 'off' if params['pp'] == 'disabled'
end
your environment will not have RACK_MINI_PROFILER set initially, but if you want to turn it on, you can tack ?pp=enabled onto your url. Then you can disable again later (the pp=disabled will only turn it off for the current session, but setting the ENV variable to off will kill it entirely until you force it back on).

Deleting .inf and .pnf Files

I manually install my driver using an .inf file. Until now, I deleted the oem.inf and .pnf files from the inf folder to uninstall. Whenever I install a new driver I delete/uninstall the old inf and pnf files.
In my old uninstalls (by deleting .inf and .pnf files), I didn't modify or delete any registry settings.
In this case do I want to change or remove any settings from the registry (for example: devnode)?
You should use the SetupUninstallOEMInf function to uninstall the .INF (and subsequently .PNF) files. This will take care of the details. pnputil (on Vista and higher) should do the equivalent thing from the command line. However, this function will not delete drivers that are currently installed (e.g. associated with a devnode).
Why are you uninstalling the old driver first? The user might already installed your driver for at least one devnode. Why not use a Microsoft-sanctioned solution such as DpInst? It will do the work required to update the driver.
Passing SUOI_FORCEDELETE to SetupUninstallOEMInf wouldn't be a good idea, cause you'd end up with lingering .INF references in your devnodes (in the registry).
At work I wrote a utility I called DriverUninstaller that deletes the devnodes and then deleted the INFs. I only use this utility for uninstallations. Upgrades are handled by DpInst, as they should be. The flow is roughly:
Enumerate them with SetupAPI (e.g. by device class if your device class is unique)
For each devnode, call SetupDiCallClassInstaller(DIF_REMOVE, ...)
Call SetupDiBuildDriverInfoList to find all .INF files for my device
For each INF, call SetupUninstallOEMInf
If there'll be interest in this utility, I might be able to persuade my employer to open-source it :-)
As the other answer points out the API to remove drivers on Windows is the SetupUninstallOEMInf method but I figured I'd add a few important notes here:
the INF path parameter must be the file name only (must not include the full path!)
this API requires Administrator privileges (this is not much of a surprise)
on 64-bit systems, the method only works when executed in the context of a 64-bit process (ie. WOW64 doesn't work)
The SetupDiGetDriverInfoDetail API can be used to query information about the relevant INF file(s) to remove for a particular device. And the SetupDiEnumDriverInfo/SetupDiBuildDriverInfoList APIs can be used to enumerate all drivers for a particular device.
// given infFilePath - full path to inf as returned by a query using SetupDiGetDriverInfoDetail
TCHAR* infFileName = GetFileNamePart(infFilePath);
if(SetupUninstallOEMInf(pInf, SUOI_FORCEDELETE, NULL))
{
// success
}else
{
DWORD errCode = GetLastError();
if(errCode == 0x02)
{
// means that the driver INF file was not found
// most likely it was already uninstalled
}else if(errCode == 0x05)
{
// must run as administrator
}else
{
// some other error code.. handle appropriately
}
}
I've open-sourced the code for a tool I wrote to perform driver uninstalls for USB and Media/Image devices. Details here: http://mdinescu.com/software-development/30-driver-hunter-programatically-uninstall-drivers-in-windows

Resources