I am working with the OpenSSL library's X509 certificate class, and I need to query the "key usage" extension.
After abandoning OpenSSL's vapourware "documentation", some shot-in-the-dark web searching eventually revealed that I needed to call
X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx)
and searching through the objects.h header revealed the proper NID.
Problem is, this call returns a pointer to void, which apparently can point to a variety of structs depending upon what extension one has asked for.
Since none of these appear to be documented, one is left without a way to figure out how to parse what the function returns.
Can anyone point me to a document that actually talks about this, instead of just listing things I can find out for myself (the function profile, which file it comes from, etc)?
The easiest solutions to read the key usage seems to be
X509* x509_cert = ...
// without X509_check_ca x509_cert->ex_kusage always returns 0 (no idea why)
int ca = X509_check_ca(x509_cert);
unsigned long usage = x509_cert->ex_kusage;
The resulting values are defined in opensc/pkcs15-init.h
SC_PKCS15INIT_X509_DIGITAL_SIGNATURE 0x0080UL
SC_PKCS15INIT_X509_NON_REPUDIATION 0x0040UL
SC_PKCS15INIT_X509_KEY_ENCIPHERMENT 0x0020UL
SC_PKCS15INIT_X509_DATA_ENCIPHERMENT 0x0010UL
SC_PKCS15INIT_X509_KEY_AGREEMENT 0x0008UL
SC_PKCS15INIT_X509_KEY_CERT_SIGN 0x0004UL
SC_PKCS15INIT_X509_CRL_SIGN 0x0002UL
I came to that soultion by finding the following code of an openssl source file
/* Handle key usage */
if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
if(usage->length > 0) {
x->ex_kusage = usage->data[0];
if(usage->length > 1)
x->ex_kusage |= usage->data[1] << 8;
} else x->ex_kusage = 0;
x->ex_flags |= EXFLAG_KUSAGE;
ASN1_BIT_STRING_free(usage);
}
The second parameter (nid) determines the returned type.
Looking at this code:
http://opengrok.creo.hu/dragonfly/xref/src/crypto/openssl-0.9/crypto/x509v3/v3_purp.c#X509_check_purpose
It appears that for the key usage NID, it returns a ASN1_BIT_STRING. (line 361).
Related
In a C++ program I am trying to set a custom comparison function for a Berkeley DB, using the Db::set_bt_function member function (the DB is opened as a BTREE type). My code works fine when I'm not changing the comparison function; I can put and get keys/values using Db::put and Db::get.
To try the set_bt_function method, I defined my own "lexicographic comparison" as follows:
int compkeys(Db *db, const Dbt *dbt1, const Dbt *dbt2, size_t *locp) {
size_t s = dbt1->get_size() > dbt2->get_size() ? dbt2->get_size() : dbt1->get_size();
int c = std::memcmp(dbt1->get_data(), dbt2->get_data(), s);
if(c != 0) return c;
if(dbt1->get_size() < dbt2->get_size()) return -1;
if(dbt1->get_size() > dbt2->get_size()) return 1;
return 0;
}
So this should lead to exactly the same behavior as my reference code, when the comparison function isn't changed, since by default Berkeley DB uses lexicographical order.
Yet, when using this comparison function, Db::get doesn't work anymore. It returns -30999 (DB_BUFFER_SMALL).
Here is what I am doing to get the value associated with a given key:
Db* _dbm = ... /* DB is open */
std::vector<char> mykey;
... /* mykey is set to some content */
Dbt db_key((void*)(mykey.data()), uint32_t(mykey.size()));
Dbt db_data;
db_key.set_flags(DB_DBT_USERMEM);
db_data.set_flags(DB_DBT_MALLOC);
int status = _dbm->get(NULL, &db_key, &db_data, 0);
... /* check status, do something with db_data */
free(db_data.get_data());
Any idea why this code works when I'm not setting the comparison function, and doesn't when I am?
Note: if I access key/values using a cursor (Dbc::get) I don't have this issue.
The DB_BUFFER_SMALL error in this case is complaining about your db_key Dbt. You need to call db_key.set_ulen(uint32_t(mykey.size())) to tell BDB how much space you've allocated to hold the keys that come out of the database.
Things get a little weirder when you're using a custom comparison function. You can have data in the key that's not part of the compare - and not in the key that you passed in to get(). For this reason, BDB returns the key it found in the database in your db_key.
When setting the ulen, make it large enough to hold any key that can come back from the database. You may find that it's saner to just keep a char array on the stack to deal with this key in/out behavior.
I have build a set C++ containing classes on top of the BluetoothAPIs apis.
I can enumerate open handles to services, characteristics and descriptors. I can read characteristic values. The issue that I have is that I cannot write to a characteristic value.
Below is the code use to write the characteristic value
void BleGattCharacteristic::setValue(UCHAR * data, ULONG size){
if (pGattCharacteristic->IsSignedWritable || pGattCharacteristic->IsWritable || pGattCharacteristic->IsWritableWithoutResponse)
{
size_t required_size = sizeof(BTH_LE_GATT_CHARACTERISTIC_VALUE) + size;
PBTH_LE_GATT_CHARACTERISTIC_VALUE gatt_value = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)malloc(required_size);
ZeroMemory(gatt_value, required_size);
gatt_value->DataSize = (ULONG)size;
memcpy(gatt_value->Data, data, size);
HRESULT hr = BluetoothGATTSetCharacteristicValue(bleDeviceContext.getBleServiceHandle(), pGattCharacteristic, gatt_value, NULL, BLUETOOTH_GATT_FLAG_NONE);
free(gatt_value);
if (HRESULT_FROM_WIN32(S_OK) != hr)
{
stringstream msg;
msg << "Unable to write the characeristic value. Reason: ["
<< Util.getLastError(hr) << "]";
throw BleException(msg.str());
}
}
else
{
throw BleException("characteristic is not writable");
}}
The call to bleDeviceContext.getBleServiceHandle() returns the open handle to the device info service.
pGattCharacteristics is the pointer to the characteristic to write too. It was opened with a call to BluetoothGATTGetCharacteristics.
I have tried different combinations of the flags with no difference in the return code.
I have also tried using the handle to the device not to the service. In that case I get an ERROR_INVALID_FUNCTION return error code.
I would appreciate any pointers as to what I am doing wrong or what other possible options I could try.
1- You have to use the Service Handle, right.
2- I don't know how you designed your class, and then how you allocate some memory for the Characteristic's Value itself.
What I do (to be sure to have enough and proper memory for Value's data):
a) at init of the Value object, call ::BluetoothGATTGetCharacteristicValue twice, to get the needed size and then actually allocate some internal memory for it.
b) when using it, set the inner memory to what it may , then call ::BluetoothGATTSetCharacteristicValue
hr=::BluetoothGATTSetCharacteristicValue(
handle,
(PBTH_LE_GATT_CHARACTERISTIC)Characteristic,
value,//actually a (PBTH_LE_GATT_CHARACTERISTIC_VALUE) to allocated memory
0,//BTH_LE_GATT_RELIABLE_WRITE_CONTEXT ReliableWriteContext,
BLUETOOTH_GATT_FLAG_NONE)
So a few things:
typedef struct _BTH_LE_GATT_CHARACTERISTIC_VALUE {
ULONG DataSize;
UCHAR Data[];
} BTH_LE_GATT_CHARACTERISTIC_VALUE, *PBTH_LE_GATT_CHARACTERISTIC_VALUE;
is how the data structure used in the parameter CharacteristicValue is defined. Please note that Data is NOT an allocated array, but rather a pointer. So accessing Data[0] is undefined behavior and could be accessing anywhere in memory. Rather you need to do gatt_value.Data = &data; setting the pointer to the address of the input parameter.
Secondly the documentation is quite clear as to why you might get ERROR_INVALID_FUNCTION; if another reliable write is already pending then this write will fail. You should consider retry logic in that case.
As for E_INVALIDARG I'd assume it's related to the undefined behavior but I'd check after fixing the other issues previously mentioned.
I made my MFC application a drop target by deriving the class CDropTarget from COleDropTarget and overriding all necessary functions. Everything works as expected. However, the return value of OnDrop() confuses me. Its description reads:
Nonzero if the drop is successful; otherwise 0.
I don't understand what "successful" means if multiple files are dropped on my application.
For example, consider the following implementation:
BOOL CDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObj, DROPEFFECT tDropEffect, CPoint tPoint)
{
// I left out declaration/definition of hDrop and path for reasons of clarity.
[...]
UINT numHandledFiles = 0;
// Determine the number of dropped files.
UINT numDroppedFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
// Iterate over all dropped files.
for (UINT n = 0; n < numDroppedFiles; n++)
{
// Get the path of the current file from the HDROP structure.
if (DragQueryFile(hDrop, n, path, PATH_MAX) > 0)
{
// Try to handle each dropped file in my function handleFile().
// It returns true if a file could be handled and false otherwise.
// (The latter happens if a file with the wrong type was dropped.)
if (handleFile(path))
numHandledFiles++;
}
}
return ? // See description below.
}
Now assume that my function handleFile() can only handle .png files
and that multiple files with different file types are dropped on my application at once.
How do I replace return ? in the above code correctly? I see two options:
return numHandledFiles > 0; // At least one file could be handled.
And:
return numHandledFiles == numDroppedFiles; // All files could be handled.
I tried both, but when dropping files from Windows Explorer or Total Commander on my application,
I don't notice any difference at all. What effect does the return value have?
When reading MFC documentation leaves you puzzled you should turn to the Windows SDK documentation, as recommended in the link you provided: "For more information, see IDropTarget::Drop in the Windows SDK.":
On return, must contain one of the DROPEFFECT flags, which indicates what the result of the drop operation would be.
Note that IDropTarget::Drop more closely resembles COleDropTarget::OnDropEx, which you should be implementing instead of COleDropTarget::OnDrop. There is no strict rule for the case you describe. However, the DROPEFFECT should match application behavior (i.e. accept or reject).
I am trying to create custom tcl channel and use it to get the output of tcl Interpreter. I added the implementation of few function of Tcl_ChannelType but I am getting segfault.
#include <tcl.h>
#include <iostream>
int driverBlockModeProc(ClientData instanceData, int mode) {
std::cout << "driverBlockModeProc\n";
return 0;
}
int driverCloseProc(ClientData instanceData, Tcl_Interp *interp) {
std::cout << "driverCloseProc\n";
return 0;
}
int driverInputProc(ClientData instanceData, char* buf, int bufSize, int *errorCodePtr) {
std::cout << "driverInputProc\n";
return 0;
}
int driverOutputProc(ClientData instanceData, const char* buf, int toWrite, int *errorCodePtr) {
std::cout << "driverOutputProc\n";
return 0;
}
int main() {
Tcl_ChannelType *typePtr = new Tcl_ChannelType;
typePtr->blockModeProc = driverBlockModeProc;
typePtr->outputProc = driverOutputProc;
typePtr->closeProc = driverCloseProc;
typePtr->inputProc = driverInputProc;
typePtr->seekProc = NULL;
typePtr->setOptionProc = NULL;
typePtr->getOptionProc = NULL;
typePtr->watchProc = NULL;
typePtr->getHandleProc = NULL;
typePtr->close2Proc = NULL;
typePtr->blockModeProc = NULL;
typePtr->flushProc = NULL;
typePtr->handlerProc = NULL;
typePtr->wideSeekProc = NULL;
typePtr->threadActionProc = NULL;
ClientData data = new char[200];
Tcl_CreateChannel(typePtr, "im_chanel", data, TCL_WRITABLE | TCL_READABLE);
}
I cant debug the segfault because its source are not available. I think the segfault is because a function is called which is NULL. I only need to use the channel to get the output of interpreter. Which functions I needn't implement here and is it right direction to solve the problem.
You're advised to download the source to Tcl when working at this level. I'm not sure what version you're using, but all official distributions of the source going back a very long way are on the SourceForge file distribution system; pick the exact match for the version you've got.
Creating a custom channel driver is not easy. There's a significant amount of complexity involved, and it isn't especially well-documented what “methods” within the channel driver type are mandatory and what are optional. (They're not C++ methods in a class — Tcl is pure C code for reasons too long to go into here — but they function in a conceptually similar way.)
If we look at the documentation for Tcl_CreateChannel, we see (quite a long way down that page) a definition of the channel type structure. The channel type structure should be statically allocated (Tcl's implementation assumes very strongly that it never changes location) and the following fields must be set to something meaningful:
typeName — This is the name of the channel type, useful for debugging!
version — This is the version of the channel type; you should set it to the latest version supported by your target source level. (You're recommended to use at least TCL_CHANNEL_VERSION_2 or things get rather more complex.)
closeProc or close2Proc — Channels must be closeable, but you have two choices for ways to do it. Bidirectional channels ought to use the close2Proc, but aren't strictly required to.
inputProc — Only needed if you're reading; take care to handle this correctly.
outputProc — Only needed if you're writing; take care to handle this correctly.
watchProc — Called to tell the channel driver to install itself into the event system so as to receive suitable events (as instructed by the supplied bitmask). Channels that don't have backing OS handles use timer events, or simply never actually generate events (in which case they'll never become readable or writable from the perspective of fileevent).
Looking at your code, I see that you're missing a watchProc. I know it's hard to see (not many people write channel drivers, to be honest, so the documentation isn't very hard “tested”) but it's really necessary.
Here's my problem.
I am trying to get raw input from attached devices. I am using the information on MSDN to figure it out, but it's been very difficult for me to make sense of some of it.
I believe I have successfully created a RAWINPUTDEVICE object and registered a device with RegisterRawInputDevices(). Now I am trying to figure out how to use the GetRawInputDeviceList() and GetRawInputDeviceInfo() functions. The big trouble is trying to understand the parameters they take, which includes a RAWINPUTDEVICELIST object, a HANDLE, a LPVOID, and a PUINT.
What are those variables and how do I use them?
Here's what I've gotten to work:
Important stuff in the header file:
#include <Windows.h>
#include <Winuser.h>
Important thing in the CPP file:
// I do not know where I found this not what it does, but it fixed some errors
// that I could not solve. MSDN did not mention it.
#pragma comment(lib, "user32.lib")
And the stuff that works, and the thing that does not:
RAWINPUTDEVICE rid[1];
rid[0].usUsagePage = 1;
rid[0].usUsage = 6;
rid[0].dwFlags = 0;
rid[0].hwndTarget = NULL;
// awesomeSauce returned true, so it works
bool awesomeSauce = RegisterRawInputDevices(rid, 1, sizeof(RAWINPUTDEVICE) );
// Nothing past this point works
UINT numDevices = GetRawInputDeviceList(NULL, NULL, sizeof(RAWINPUTDEVICELIST));
How do continue?
I am a little bit rusty at C++, and what you see here is pretty much the sum of my knowledge with raw input. I do not know if it will effect anything, but I am using C++/CLI, not regular C++. How do I go from this, to getting some kind of unbuffered raw input (preferably from the keyboard)?
Edit:
Most examples I find have a switch statement. I don't understand how it works though. I have something like this:
UINT msg; // How does this work?
switch(msg)
{
case WM_CREATE:
executeCase = 1;
break;
case WM_INPUT:
executeCase = 2;
break;
}
How does the msg variable work? How can I create and assign one correctly?
According to the MSDN page for GetRawInputDeviceList, here's the documentation for the first parameter (which you're passing as null):
An array of RAWINPUTDEVICELIST structures for the devices attached to the system. If NULL, the number of devices are returned in *puiNumDevices.
And here's the documentation for the return value:
If the function is successful, the return value is the number of devices stored in the buffer pointed to by pRawInputDeviceList.
You're passing null for the first parameter, and expecting the number of devices to be present in the return from the method. The documentation doesn't say it will do that.
Pass an actual variable for the second parameter, and read that instead of the return code.
If that doesn't solve your problem, please be more specific with "this is the thing that doesn't work". Tell us how it doesn't work: does it throw an exception, is there an error return code, does a black hole open up and swallow your computer whole?
Edit
In your comment, you're still storing the return value in numDevices. Also, you're using the second parameter as an array. An array of length 1 is basically the same thing, but it'd be better to think of it as a pointer to an integer.
Here's a copy of the sample code from the MSDN page, with my comments added in. Give this a try.
UINT nDevices;
PRAWINPUTDEVICELIST pRawInputDeviceList;
// Pass a null pointer to find out how many devices there are.
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVCELIST)) != 0) { Error();}
// Now, malloc the needed storage, based on the output parameter, NOT the return value.
if ((pRawInputDeviceList = malloc(sizeof(RAWINPUTDEVICELIST) * nDevices)) == NULL) {Error();}
// Finally, call for real, passing in the newly allocated buffer.
if (GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST)) == (-1) {Error();}
// after the job, free the RAWINPUTDEVICELIST
free(pRawInputDeviceList);