OpenSSL: How to supply a custom pointer to the certificate verification callback - ssl

I want to use X509_STORE_set_verify_cb_func to receive certificate validation errors. I then want to store these errors in a list and process it later after SSL_connect returned.
However my application is multithreaded and I wanted to avoid any mutex locking for this callback. Any ways to pass a "void pointer" or store this somewhere in the X509_STORE_CTX so I can store the error inside the "right" location and don't have to use a global error list and lock that while doing the SSL_connect?
Thanks

AFAIK you are indeed stuck with that - just stuff it as an entry in there under your own id. The other option is to deal with the SSL callbacks a bit more generically - see for example ssl_hook in ssl_engine_kernel.c of Apache its SSL module. While a bit more work - it gives you complete control over the entire process - and entirely in your 'own process space'.
Thanks,
Dw.

If you are using C11 or later, you can define a global thread_local variable
thread_local void * openssl_verify_context;
Then
Set openssl_verify_context before setting the callback (i.e. before X509_STORE_set_verify_cb_func).
Use openssl_verify_context in the callback.
If needed read and unset openssl_verify_context after validating the certificate (i.e. after PKCS7_dataVerify).
The advantage of this solution is you do not need to know the details of the struct behind X509_STORE_CTX (it is hidden in recent versions of OpenSSL).

Related

What information is logged by IdentityModel when ShowPii is set to true?

IdentityModelEventSource has a property called ShowPII that means that Personally Identifiable Information will be added to the logs (in relation to security). This value is used to decide when to log some OAuth2 sensitive data.
I am trying to understand what kind of Personally Identifiable Information will be logged:
Client ID? (aka Client Key, Consumer Key)
Client Secret? (aka Consumer Secret)
Json Web Tokens? (aka JWT)
Access Tokens?
Refresh Tokens?
Kerberos Tickets?
PKCE Values?
Authorization Codes?
I know it cannot get access to usernames and passwords because they are only exchanged directly with the IDP.
But but I need to know if I need to find a way to lock down my log files because it will have data that constitutes a security vulnerability.
This is possible log messages of IdentityModel: LogMessages.cs
About
I am trying to understand what kind of Personally Identifiable Information will be logged
I won't copy-paste log messages from there (especially, as they can change at any moment). You can check them yourself and decide what should be considered as the PII.
But here's an interesting example:
"IDX10615: Encryption failed. No support for: Algorithm: '{0}', SecurityKey: '{1}'."
and this is how it's used:
throw LogHelper.LogExceptionMessage(new SecurityTokenEncryptionFailedException(LogHelper.FormatInvariant(TokenLogMessages.IDX10615, encryptingCredentials.Enc, encryptingCredentials.Key)));
If you'll follow the track you'll find out that encryptingCredentials.Key will be logged if ShowPII = true and won't be logged if ShowPII = false.
Of course, depending on your use case, this particular message may never appear in your logs. And not all messages so outrageously leaky. But you never know:
your use case may change
you may be mistaken about the set of messages IdentityModel can emit for your use case
IdentityModel code may change, and you may forget to check if messages' set is still secure
So about
if I need to find a way to lock down my log files
Yes, you definitely need to.
Or better yet - don't use ShowPII = true in production for monitoring, use it only in development environment for debugging purposes.
Looking at the source, it appears that when ShowPII is on - it will do two things:
Replace all parameters passed to library-specific exceptions with their data type names
For all system exceptions - replace inner message with exception type name
In this context "library-specific" is an exception that is of type Exception and its full type name starts with "Microsoft.IdentityModel." (library defines a few)
Depending on your use case you'd see a variety of parameters that can be logged with custom exceptions. A quick search for FormatInvariant yields quite a few for your consideration.
Again, depending on how you use it, you might get a better idea of what the error messages are by looking through relevant LogMessages.cs file on your specific namespace.
P.S.: on a side note, it appears that default ShowPII setting is GDPR-compliant

Geode region[key] get triggers region listener create event

Using Geode 1.2 and 9.1 Pivotal native client the following code:
IRegion<string, IPdxInstance> r = cache.GetRegion<string, IPdxInstance>("myRegion");
return r[key];
then triggers an AfterCreate event for myRegion. Why does that happen when no data is created, only read?
Same here, never used Native Client. I agreed with what #Urizen suspected - you are calling r[key] from an instance of Geode that doesn't have the entry, so it pulls the data from other instance, which "create" the entry locally.
You have a few options here:
Performing an interest registration for the instance you are initiating the call using registerAllKeys() (doc here). There is a catch here: (might not be applicable for native client), in Java API, you have an option to register interest with an InterestResultPolicy. If you use KEYS_VALUES, you will load all data to local from remote on startup WITHOUT triggering afterCreate callback. If you choose KEYS only or NONE, you will likely have similar problem.
You can check for boolean flag remoteOrigin in EntryEvent. If it is false, it is purely local. In a non-WAN setup, this should be enough to distinguish your local operation from remotely initiated operation (be it a cache syncing or a genuine creation initiated by other cache). Vaguely remembering WAN works a bit different here.
I've never used the Native Client but, at a first glance, it should be expected for the afterCreate event to be invoked on the client side as the entry is actually being created on the local cache. What I mean is that the entry might exists on the server but, internally, the client needs to retrieve it from the server, and then create it locally (thus invoking the afterCreate for the locally installed CacheListener). Makes sense?.

Keeping SAP's RFC data for consecutive calls of RFC using JCO

I was wondering if it was possible to keep an RFC called via JCO opened in SAP memory so I can cache stuff, this is the scenario I have in mind:
Suppose a simple function increments a number. The function starts with 0, so the first time I call it with import parameter 1 it should return 1.
The second time I call it, it should return 2 and so on.
Is this possible with JCO?
If I have the function object and make two successive calls it always return 1.
Can I do what I'm depicting?
Designing an application around the stability of a certain connection is almost never a good idea (unless you're building a stability monitoring software). Build your software so that it just works, no matter how often the connection is closed and re-opened and no matter how often the session is initialized and destroyed on the server side. You may want to persist some state using the database, or you may need to (or want to) use the shared memory mechanisms provided by the system. All of this is inconsequential for the RFC handling itself.
Note, however, that you may need to ensure that a sequence of calls happen in a single context or "business transaction". See this question and my answer for an example. These contexts are short-lived and allow for what you probably intended to get in the first place - just be aware that you should not design your application so that it has to keep these contexts alive for minutes or hours.
The answer is yes. In order to make it work, you need to implement two tasks:
The ABAP code needs to store its variable in the ABAP session memory. A variable in the function group's global section will do that. Or alternatively you could use the standard ABAP technique "EXPORT TO MEMORY/IMPORT FROM MEMORY".
JCo needs to keep the user session between calls. By default, JCo resets the backend-side user session after every call, which of course destroys all data stored in that user session memory. In order to prevent it, you need to use JCoContext.begin() and JCoContext.end() to get a stateful RFC connection that keeps the user session alive on backend side.
Sample code:
JCoDestination dest = ...
JCoFunction func = ...
try{
JCoContext.begin(dest);
func.execute(dest); // Will return "1"
func.execute(dest); // Will return "2"
}
catch (JCoException e){
// Handle network problems, ABAP exceptions, SYSTEM_FAILUREs
}
finally{
// Make sure to release the stateful connection, otherwise you have
// a resource-leak in your program and on backend side!
JCoContext.end(dest);
}

Can We initilize Winsock in DLL_DETACH ? actulay i want to send some data when a process get terminated(DLL_DETACH)

Can We initialize Win sock in DLL_DETACH ? actulay i want to send some data when a process get terminated(DLL_DETACH)
DLL_DETACH is actually DLL_PROCESS_DETACH.
It is possible (i don't think that's any mechanism to prevent it) but it's not recommended.
WSAStartup lies in ws2_32.dll. Here's a fragment from DllMain official doc (Remarks section):
Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.
Also, from WSAStartup official doc (same Remarks section):
The WSAStartup function typically leads to protocol-specific helper DLLs being loaded. As a result, the WSAStartup function should not be called from the DllMain function in a application DLL. This can potentially cause deadlocks. For more information, please see the DLL Main Function.
As an alternative sending the data (including the overhead of initializing the socket engine, creating the connection, and uninitializing the socket engine) could be achieved at the end of main (WinMain).
Calling WSAStartup() in DllMain() will result in a deadlock due to the loader lock. WSAStartup() can result in DLLs being loaded.
A better solution would be to install a service that can do the sending for. Talk to the service from DllMain() using your preferred interprocess comms method (shared memory, named pipes, etc).

Why is Mage_Persistent breaking /api/wsdl?soap

I get the following error within Magento CE 1.6.1.0
Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: Cannot send session cookie - headers already sent by (output started at /home/dev/env/var/www/user/dev/wdcastaging/lib/Zend/Controller/Response/Abstract.php:586) in /home/dev/env/var/www/user/dev/wdcastaging/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php on line 119
when accessing /api/soap/?wsdl
Apparently, a session_start() is being attempted after the entire contents of the WSDL file have already been output, resulting in the error.
Why is magento attempting to start a session after outputting all the datums? I'm glad you asked. So it looks like controller_front_send_response_after is being hooked by Mage_Persistent in order to call synchronizePersistentInfo(), which in turn ends up getting that session_start() to fire.
The interesting thing is that this wasn't always happening, initially the WSDL loaded just fine for me, initially I racked my brains to try and see what customization may have been made to our install to cause this, but the tracing I've done seems to indicate that this is all happening entirely inside of core.
We have also experienced a tiny bit of (completely unrelated) strangeness with Mage_Persistent which makes me a little more willing to throw my hands up at this point and SO it.
I've done a bit of searching on SO and have found some questions related to the whole "headers already sent" thing in general, but not this specific case.
Any thoughts?
Oh, and the temporary workaround I have in place is simply disabling Mage_Persistent via the persistent/options/enable config data. I also did a little bit of digging as to whether it might be possible to observe an event in order to disable this module only for the WSDL controller (since that seems to be the only one having problems), but it looks like that module relies exclusively on this config flag to determine it's enabled status.
UPDATE: Bug has been reported: http://www.magentocommerce.com/bug-tracking/issue?issue=13370
I'd report this is a bug to the Magento team. The Magento API controllers all route through standard Magento action controller objects, and all these objects inherit from the Mage_Api_Controller_Action class. This class has a preDispatch method
class Mage_Api_Controller_Action extends Mage_Core_Controller_Front_Action
{
public function preDispatch()
{
$this->getLayout()->setArea('adminhtml');
Mage::app()->setCurrentStore('admin');
$this->setFlag('', self::FLAG_NO_START_SESSION, 1); // Do not start standart session
parent::preDispatch();
return $this;
}
//...
}
which includes setting a flag to ensure normal session handling doesn't start for API methods.
$this->setFlag('', self::FLAG_NO_START_SESSION, 1);
So, it sounds like there's code in synchronizePersistentInf that assumes the existence of a session object, and when it uses it the session is initialized, resulting in the error you've seen. Normally, this isn't a problem as every other controller has initialized a session at this point, but the API controllers explicitly turns it off.
As far as fixes go, your best bet (and probably the quick answer you'll get from Magento support) will be to disable the persistant cart feature for the default configuration setting, but then enable it for specific stores that need it. This will let carts
Coming up with a fix on your own is going to be uncharted territory, and I can't think of a way to do it that isn't terribly hacky/unstable. The most straight forward way would be a class rewrite on the synchronizePersistentInf that calls it's parent method unless you've detected this is an API request.
This answer is not meant to replace the existing answer. But I wanted to drop some code in here in case someone runs into this issue, and comments don't really allow for code formatting.
I went with a simple local code pool override of Mage_Persistent_Model_Observer_Session to exit out of the function for any URL routes that are within /api/*
Not expecting this fix to need to be very long-lived or upgrade-friendly, b/c I'm expecting them to fix this in the next release or so.
public function synchronizePersistentInfo(Varien_Event_Observer $observer)
{
...
if ($request->getRouteName() == 'api') {
return;
}
...
}