Correct closing DBus connection - c

Could you explain how to close DBus connection correctly/ Below is my variant:
int P_dbus_proto_init(DBusConnection **dbus_conn, const char *name, dbus_MessageHandler mh, int num_rules, const char **rules)
{
int rc = 0;
DBusError dbus_err;
dbus_error_init(&dbus_err);
*dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_err);
if (dbus_error_is_set(&dbus_err))
{
FILTER_LOG_ERROR("Connection Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
rc = dbus_bus_request_name(*dbus_conn, name, DBUS_NAME_FLAG_REPLACE_EXISTING, &dbus_err);
if (dbus_error_is_set(&dbus_err) || (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != rc))
{
FILTER_LOG_ERROR("Connection Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
dbus_connection_add_filter(*dbus_conn, mh, NULL, NULL);
if (dbus_error_is_set(&dbus_err))
{
FILTER_LOG_ERROR("Add Filter Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
for(int i = 0; i < num_rules; i++)
{
dbus_bus_add_match(*dbus_conn, rules[i], &dbus_err);
if (dbus_error_is_set(&dbus_err))
{
FILTER_LOG_ERROR("Match Error (%s)\n", dbus_err.message);
dbus_error_free(&dbus_err);
return -1;
}
}
return 0;
}
static const char* rules[] = {
"interface='acl_management.method'",
};
And how I use it:
DBusConnection *dbus_conn;
if (P_dbus_proto_init(&dbus_conn, "com.bla-bla-bla.acl", P_dbus_proto_job, 1, rules) == 0)
{
while (dbus_connection_read_write_dispatch(dbus_conn, 5000))
{
if(p_ctx->execute.n_nl_exit_app == 0) //My app can be terminated by n_nl_exit_app flag
{
break;
}
}
dbus_connection_close(dbus_conn);// Should I do it or not?
dbus_connection_unref(dbus_conn);// Should I do it or not?
}
From dbus.freedesktop.org docs I cannot understand how to do it correctly. I can terminate my app by turn on 'n_nl_exit_app' flag - should I call dbus_connection_closein this case?

Related

How do I read a dbus array of dicts with the c api sd-bus?

I am try to read a dbus data structure that looks like this a{sv} with sd-bus but when i use the code down below i can only read one of the 8 dicts.
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
int main ()
{
sd_bus *bus = NULL;
sd_bus_error err = SD_BUS_ERROR_NULL;
sd_bus_message *msg = NULL;
char const *sign;
int signi = 0;
int error;
sd_bus_default_user (&bus);
sd_bus_get_property (bus,
"org.mpris.MediaPlayer2.plasma-browser-integration",
"/org/mpris/MediaPlayer2",
"org.mpris.MediaPlayer2.Player",
"Metadata", &err, &msg, "a{sv}");
sign = sd_bus_message_get_signature (msg, signi);
error = sd_bus_message_enter_container (msg, SD_BUS_TYPE_ARRAY, "{sv}");
while (error =
sd_bus_message_enter_container (msg, SD_BUS_TYPE_DICT_ENTRY,
"sv") > 0) {
const char *key;
sd_bus_message_read_basic (msg, SD_BUS_TYPE_STRING, &key);
sign = sd_bus_message_get_signature (msg, signi);
printf ("returned: %s \n", key);
sd_bus_message_exit_container (msg);
}
sd_bus_message_exit_container (msg);
if (err._need_free != 0) {
printf ("%d \n", error);
printf ("returned error: %s\n", err.message);
}
else {
printf ("%s", sign);
}
sd_bus_error_free (&err);
sd_bus_unref (bus);
return 0;
}
I have looked up the function sd_bus_message_enter_container on hotexamples.com and all of them seemed to have while more than one loop around the function that enters the dict it seemed to me that this would loop an tell it had all of the values but this dose not seem to work i also tried using the loop with the function that entered the array and that did not work. another way that tried is to run a for loop that cycled 8 times after that i tried to look for other solutions and there are none that i can see. i also use the documtation on freedesktops web site (https://www.freedesktop.org/software/systemd/man/sd-bus.html) i have it working with gdbus but as far as i understand that is depreciated. how come this is not working i don't understand.
Thank you in advance for your help.
I did not realise that I had to read each value otherwise it will throw an error and if you don't want to there is a skip function.
this is the code that worked
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <stdbool.h>
#include <string.h>
int bus_print_property(const char *name, sd_bus_message *property) {
char type;
const char *contents;
int r;
r = sd_bus_message_peek_type(property, &type, &contents);
if (r < 0)
return r;
switch (type) {
case SD_BUS_TYPE_STRING: {
const char *s;
r = sd_bus_message_read_basic(property, type, &s);
if (r < 0)
return r;
printf("%s=%s\n", name, s);
return 1;
}
case SD_BUS_TYPE_BOOLEAN: {
bool b;
r = sd_bus_message_read_basic(property, type, &b);
if (r < 0)
return r;
printf("%s\n", name);
return 1;
}
case SD_BUS_TYPE_INT64: {
int64_t i64;
r = sd_bus_message_read_basic(property, type, &i64);
if (r < 0)
return r;
printf("%s=%i\n", name, (int) i64);
return 1;
}
case SD_BUS_TYPE_INT32: {
int32_t i;
r = sd_bus_message_read_basic(property, type, &i);
if (r < 0)
return r;
printf("%s=%i\n", name, (int) i);
return 1;
}
case SD_BUS_TYPE_OBJECT_PATH:{
const char *p;
r = sd_bus_message_read_basic(property, type, &p);
if (r < 0)
return r;
printf("%s=%s\n", name, p);
return 1;
}
case SD_BUS_TYPE_DOUBLE: {
double d;
r = sd_bus_message_read_basic(property, type, &d);
if (r < 0)
return r;
printf("%s=%g\n", name, d);
return 1;
}
case SD_BUS_TYPE_ARRAY:
if (strcmp(contents, "s")==0) {
bool first = true;
const char *str;
r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
if (r < 0)
return r;
while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
if (first)
printf("%s=", name);
printf("%s%s", first ? "" : " ", str);
first = false;
}
if (r < 0)
return r;
if (first )
printf("%s=", name);
if (!first )
puts("");
r = sd_bus_message_exit_container(property);
if (r < 0)
return r;
return 1;
} else {
printf("array unreadable");
return 0;
}
break;
}
return 0;
}
int main()
{
sd_bus* bus = NULL;
sd_bus_error err = SD_BUS_ERROR_NULL;
sd_bus_message *msg = NULL;
int error;
sd_bus_default_user(&bus);
sd_bus_get_property(bus,
"org.mpris.MediaPlayer2.plasma-browser-integration",
"/org/mpris/MediaPlayer2",
"org.mpris.MediaPlayer2.Player",
"Metadata",
&err,&msg,"a{sv}");
error = sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY, "{sv}");
if (error < 0)
return error;
while ((error = sd_bus_message_enter_container(msg, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
const char *name;
const char *contents;
error = sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, &name);
if (error < 0)
return error;
error = sd_bus_message_peek_type(msg, NULL, &contents);
if (error < 0)
return error;
error = sd_bus_message_enter_container(msg, SD_BUS_TYPE_VARIANT, contents);
if (error < 0)
return error;
error = bus_print_property(name, msg);
if (error < 0)
return error;
if (error == 0) {
printf("%s=[unprintable]\n", name);
/* skip what we didn't read */
error = sd_bus_message_skip(msg, contents);
if (error < 0)
return error;
}
error = sd_bus_message_exit_container(msg);
if (error < 0)
return error;
error = sd_bus_message_exit_container(msg);
if (error < 0)
return error;
}
if (error < 0)
return error;
error = sd_bus_message_exit_container(msg);
if (error < 0)
return error;
if(err._need_free!=0){
printf("%d \n",error);
printf("returned error: %s\n",err.message);
}else{
}
sd_bus_error_free(&err);
sd_bus_unref(bus);
return 0;
}

How to add function for mqtt server authentication

How can I add the functions for username and password to authen mqtt broker.
The original file has not section for authentication. How can I adding function for username and password in authentication mqtt server?
This file has mqtt.h that is sitting parameters (such as hotsname, port, etc.). and I have added parameter for username and password in mqtt.h following this
struct mqtt_handle_s {
// Public members
char *host;
int port;
char *username;
char *password;
char *client_id;
mqtt_on_connect_t on_connect;
mqtt_on_message_t on_message;
// Private members
struct mosquitto *client;
char *topic_list;
size_t topic_size;
};
and then how can I adding the function for running that parameter to using in mqtt server authentication?
the main code is following..
#mqtt.c full code.
#if defined(_WIN32)
#include <windows.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "app_log.h"
#include "mqtt.h"
// Check if libmosquitto version is at least 1.5.7
#if LIBMOSQUITTO_VERSION_NUMBER < 1005007
#warning Untested libmosquitto version!
#endif
#define QOS 1
#define KEEPALIVE_INTERVAL_SEC 30
#define LOOP_TIMEOUT_MS 1
#define LOG_MASK MOSQ_LOG_NONE
static void mqtt_on_connect(struct mosquitto *mosq, void *obj, int rc);
static void mqtt_on_disconnect(struct mosquitto *mosq, void *obj, int rc);
static void mqtt_on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message);
static void mqtt_on_log(struct mosquitto *mosq, void *obj, int level, const char *str);
static const char * mqtt_err2str(int rc);
mqtt_status_t mqtt_init(mqtt_handle_t *handle)
{
mqtt_status_t ret = MQTT_SUCCESS;
int rc = MOSQ_ERR_ERRNO; // return code if mosquitto_new() fails
struct mosquitto *mosq;
mosquitto_lib_init();
mosq = mosquitto_new(handle->client_id, true, handle);
if (mosq != NULL) {
mosquitto_connect_callback_set(mosq, mqtt_on_connect);
mosquitto_disconnect_callback_set(mosq, mqtt_on_disconnect);
mosquitto_message_callback_set(mosq, mqtt_on_message);
mosquitto_log_callback_set(mosq, mqtt_on_log);
rc = mosquitto_connect(mosq, handle->host, handle->port, KEEPALIVE_INTERVAL_SEC);
}
if (rc != MOSQ_ERR_SUCCESS) {
app_log("MQTT init failed: '%s'\n", mqtt_err2str(rc));
ret = MQTT_ERROR_CONNECT;
handle->client = NULL;
if (mosq != NULL) {
mosquitto_destroy(mosq);
}
} else {
handle->client = mosq;
}
handle->topic_list = NULL;
handle->topic_size = 0;
return ret;
}
mqtt_status_t mqtt_publish(mqtt_handle_t *handle, const char *topic, const char *payload)
{
mqtt_status_t ret = MQTT_SUCCESS;
int rc;
int mid;
if (handle->client != NULL) {
rc = mosquitto_publish(handle->client, &mid, topic, strlen(payload), payload, QOS, false);
if (rc != MOSQ_ERR_SUCCESS) {
app_log("MQTT publish attempt failed: '%s'\n", mqtt_err2str(rc));
ret = MQTT_ERROR_PUBLISH;
}
} else {
ret = MQTT_ERROR_PUBLISH;
}
return ret;
}
mqtt_status_t mqtt_step(mqtt_handle_t *handle)
{
mqtt_status_t ret = MQTT_SUCCESS;
int rc;
if (handle->client != NULL) {
rc = mosquitto_loop(handle->client, LOOP_TIMEOUT_MS, 1);
if (rc != MOSQ_ERR_SUCCESS) {
app_log("MQTT loop failed: '%s'\n", mqtt_err2str(rc));
ret = MQTT_ERROR_STEP;
}
} else {
ret = MQTT_ERROR_STEP;
}
return ret;
}
mqtt_status_t mqtt_subscribe(mqtt_handle_t *handle, const char *topic)
{
mqtt_status_t ret = MQTT_SUCCESS;
int rc;
size_t topic_size;
if (handle->client != NULL) {
// Try to subscribe to topic.
rc = mosquitto_subscribe(handle->client, NULL, topic, QOS);
if ((rc != MOSQ_ERR_SUCCESS) && (rc != MOSQ_ERR_NO_CONN)) {
app_log("MQTT subscribe attempt failed to topic '%s': '%s'\n", topic, mqtt_err2str(rc));
ret = MQTT_ERROR_SUBSCRIBE;
}
// Append topic to topic list.
topic_size = strlen(topic) + 1;
handle->topic_list = realloc(handle->topic_list, handle->topic_size + topic_size);
if (handle->topic_list == NULL) {
app_log("MQTT failed to append topic to topic list.\n");
ret = MQTT_ERROR_SUBSCRIBE;
} else {
strcpy(&handle->topic_list[handle->topic_size], topic);
handle->topic_size += topic_size;
}
} else {
ret = MQTT_ERROR_SUBSCRIBE;
}
return ret;
}
mqtt_status_t mqtt_deinit(mqtt_handle_t *handle)
{
int rc;
if (handle->client != NULL) {
rc = mosquitto_disconnect(handle->client);
if (rc != MOSQ_ERR_SUCCESS) {
app_log("MQTT failed to disconnect: '%s', continue deinit.\n", mqtt_err2str(rc));
}
mosquitto_destroy(handle->client);
mosquitto_lib_cleanup();
if (handle->topic_list != NULL) {
free(handle->topic_list);
}
}
return MQTT_SUCCESS;
}
static void mqtt_on_connect(struct mosquitto *mosq, void *obj, int rc)
{
mqtt_handle_t *handle = (mqtt_handle_t *)obj;
size_t topic_start = 0;
char *topic;
int ret = MOSQ_ERR_SUCCESS;
app_log("MQTT connect status '%s'\n", mosquitto_connack_string(rc));
if (rc == 0) {
if (handle->on_connect != NULL) {
handle->on_connect(handle);
}
while (topic_start < handle->topic_size) {
topic = &handle->topic_list[topic_start];
ret = mosquitto_subscribe(mosq, NULL, topic, QOS);
topic_start += strlen(topic) + 1;
if (ret != MOSQ_ERR_SUCCESS) {
app_log("MQTT subscribe attempt failed to topic '%s': '%s'\n", topic, mqtt_err2str(ret));
}
}
}
}
static void mqtt_on_disconnect(struct mosquitto *mosq, void *obj, int rc)
{
int ret;
app_log("MQTT disconnected with reason '%d'\n", rc);
if (rc != 0) {
ret = mosquitto_reconnect(mosq);
app_log("MQTT reconnection attempt with status '%s'\n", mqtt_err2str(ret));
}
}
static void mqtt_on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
{
mqtt_handle_t *handle = (mqtt_handle_t *)obj;
char *payload;
if (handle->on_message != NULL) {
payload = malloc(message->payloadlen + 1);
if (NULL == payload) {
app_log("MQTT failed to allocate payload buffer.\n");
} else {
memcpy(payload, message->payload, message->payloadlen);
// Make sure that payload is NULL terminated.
payload[message->payloadlen] = 0;
handle->on_message(handle, message->topic, payload);
free(payload);
}
}
}
static void mqtt_on_log(struct mosquitto *mosq, void *obj, int level, const char *str)
{
if (level & LOG_MASK) {
app_log("MQTT log (%d): %s\n", level, str);
}
}
#if defined(_WIN32)
static const char * mqtt_err2str(int rc)
{
char *ret = NULL;
static char err_str[256];
if (MOSQ_ERR_ERRNO == rc) {
// Make sure to have a default output if FormatMessage fails
// or if error code is not available in errno.
strncpy(err_str, "Unknown system error", sizeof(err_str));
if (errno != 0) {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, // dwFlags
NULL, // lpSource
errno, // dwMessageId
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // dwLanguageId
err_str, // lpBuffer
sizeof(err_str), // nSize
NULL); // Arguments
}
// Make sure that err_str is NULL terminated.
err_str[sizeof(err_str) - 1] = 0;
ret = err_str;
} else {
ret = (char *)mosquitto_strerror(rc);
}
return ret;
}
#else
static const char * mqtt_err2str(int rc)
{
return (MOSQ_ERR_ERRNO == rc) ? strerror(errno) : mosquitto_strerror(rc);
}
#endif // _WIN32

Serial number enumeration failed when we cast Descriptor+Descriptor->SerialNumberOffset

I have a kernel driver which is used to find the serial number of storage devices, but there is an issue with the driver.
Descriptor->SerialNumberOffset is 103
but (LPCSTR)(UINT_PTR)Descriptor+(DWORD32)Descriptor->SerialNumberOffset is NULL
here is my code
NTSTATUS GetDeviceTypeAndUniqueID(IN PDEVICE_OBJECT StorageStackDeviceObject, cwDevices *lDeviceTypeArg, char *pszUidArg)
{
DWORRD lDeviceType=0;
STORAGE_PROPERTY_QUERY Query;
STORAGE_DEVICE_DESCRIPTOR Buffer[4];
NTSTATUS Status = STATUS_SUCCESS;
ULONG uBusType=BusTypeUnknown;
PSTORAGE_DEVICE_DESCRIPTOR Descriptor=NULL;
PIRP NewIrp2=NULL;
PIO_STACK_LOCATION NextIrpStack=NULL;
IO_STATUS_BLOCK IoStatus;
char szSptr[2]={'_','\0'};
Query.PropertyId = StorageDeviceProperty;// first set the query properties
Query.QueryType = PropertyStandardQuery;
lDeviceType=0;
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
{
return STATUS_SUCCESS;
}
if(StorageStackDeviceObject == NULL)
{
return STATUS_SUCCESS;
}
if((StorageStackDeviceObject->DeviceType != FILE_DEVICE_DISK) &&
(StorageStackDeviceObject->DeviceType != FILE_DEVICE_CD_ROM)&&
(StorageStackDeviceObject->DeviceType != FILE_DEVICE_DVD)&&
(StorageStackDeviceObject->DeviceType !=FILE_DEVICE_TAPE) )
{
return STATUS_SUCCESS;
}
KeInitializeEvent(&WaitEvent_newIrp, NotificationEvent, TRUE);// initialize the waitable event
__try
{
NewIrp2=IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY, StorageStackDeviceObject,
(PVOID)&Query,sizeof(STORAGE_PROPERTY_QUERY),
(PVOID)Buffer,sizeof(STORAGE_DEVICE_DESCRIPTOR)*4,
FALSE,&WaitEvent_newIrp,&IoStatus);
if(NewIrp2==NULL)
{
return STATUS_SUCCESS;
}
Status = IoCallDriver(StorageStackDeviceObject, NewIrp2);// send this irp to the storage device
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&WaitEvent_newIrp, Executive, KernelMode, FALSE, NULL);
Status =IoStatus.Status;
}
}
__finally
{
if(NT_SUCCESS(Status))
{
if (NT_SUCCESS(Status))
{
if(Buffer!=NULL)
{
char szStart[256];
Descriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Buffer;
uBusType = Descriptor->BusType; //Get the bus type.
if(Descriptor->SerialNumberOffset!=0)//Is Valid SerialNumberOffset, returns 103
{
strcpy(szStart,(char*)(UINT_PTR)Descriptor+(DWORD32)Descriptor->SerialNumberOffset);
//szStart is null
}
}
NewIrp2 = NULL;
}
}
}
}
please share how to solve this
you mistake in OutputBufferLength - why you decide that sizeof(STORAGE_DEVICE_DESCRIPTOR)*4 is enough ? why not 5* sizeof(STORAGE_DEVICE_DESCRIPTOR) for example ? really what OutputBufferLength must be is unknown - you need call this query in loop and compare your current OutputBufferLength with STORAGE_DEVICE_DESCRIPTOR.Size - if OutputBufferLength < STORAGE_DEVICE_DESCRIPTOR.Size - you must again send IOCTL_STORAGE_QUERY_PROPERTY with OutputBufferLength = STORAGE_DEVICE_DESCRIPTOR.Size. the code can be look like.
STORAGE_PROPERTY_QUERY spq = { StorageDeviceProperty, PropertyStandardQuery };
union {
PVOID buf;
PSTR psz;
PSTORAGE_DEVICE_DESCRIPTOR psdd;
};
ULONG size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 0x100;
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (buf = ExAllocatePool(PagedPool, size))
{
switch (status = (NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb,
IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), buf, size)))
{
case STATUS_SUCCESS:
case STATUS_BUFFER_OVERFLOW:
if (psdd->Version == sizeof(STORAGE_DEVICE_DESCRIPTOR))
{
if (psdd->Size > size)
{
size = psdd->Size;
status = STATUS_BUFFER_OVERFLOW;
}
else
{
if (psdd->SerialNumberOffset)
{
DbgPrint("SerialNumber = %s\n", psz + psdd->SerialNumberOffset);
}
}
}
else
{
status = STATUS_INVALID_PARAMETER;
}
break;
}
ExFreePool(buf);
}
} while (status == STATUS_BUFFER_OVERFLOW);
in place NtDeviceIoControlFile we of course can use IoBuildDeviceIoControlRequest + IoCallDriver - this nothing change and unrelated to problem

How to set l2tp preshared key?

I need to create RASENTRY for L2TP with pre-shared key set. So far, I can see that entry has somewhat correct flags, but no key is set, unfortunately.
Here is code:
int common_ras_manager_create_entry(const char* server_address, const char* username, const char* password, MY_VPN_CONNECTION_TYPE connection_type, const char* preshared_key)
{
DWORD EntryInfoSize = 0;
DWORD DeviceInfoSize = 0;
DWORD Ret;
LPRASENTRY lpRasEntry;
LPBYTE lpDeviceInfo;
// Get buffer sizing information for a default phonebook entry
if ((Ret = RasGetEntryProperties(NULL, "", NULL, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)
{
if (Ret != ERROR_BUFFER_TOO_SMALL)
{
printf("RasGetEntryProperties sizing failed with error %d\n", Ret);
return Ret;
}
}
lpRasEntry = (LPRASENTRY) GlobalAlloc(GPTR, EntryInfoSize);
if (DeviceInfoSize == 0)
lpDeviceInfo = NULL;
else
lpDeviceInfo = (LPBYTE) GlobalAlloc(GPTR, DeviceInfoSize);
// Get default phonebook entry
lpRasEntry->dwSize = sizeof(RASENTRY);
if ((Ret = RasGetEntryProperties(NULL, "", lpRasEntry, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)
{
printf("RasGetEntryProperties failed with error %d\n", Ret);
return Ret;
}
// Validate new phonebook name "Testentry"
if ((Ret = RasValidateEntryName(NULL, APP_NAME)) != ERROR_SUCCESS)
{
printf("RasValidateEntryName failed with error %d\n", Ret);
if (Ret != ERROR_ALREADY_EXISTS)
return Ret;
}
LPRASDEVINFO ras_devices;
DWORD cb =sizeof(RASDEVINFO);
DWORD cbDevices = 0;
ras_devices = (LPRASDEVINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
if (NULL == ras_devices)
{
printf("HeapAlloc failed.\n");
return ERROR_OUTOFMEMORY;
}
ras_devices->dwSize = sizeof(RASDEVINFO);
if ((Ret = RasEnumDevices(ras_devices, &cb, &cbDevices)) != ERROR_SUCCESS)
{
printf("RasEnumDevices failed with error %d\n", Ret);
switch(Ret)
{
case ERROR_BUFFER_TOO_SMALL:
printf("buffer too small");
HeapFree(GetProcessHeap(), 0, (LPVOID)ras_devices);
ras_devices = (LPRASDEVINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
if (NULL == ras_devices)
{
printf("HeapAlloc failed.\n");
return ERROR_OUTOFMEMORY;
}
ras_devices->dwSize = sizeof(RASDEVINFO);
Ret = RasEnumDevices(ras_devices, &cb, &cbDevices);
if (ERROR_SUCCESS == Ret)
{
//fSuccess = TRUE;
}
else
{
printf("RasEnumDevices failed again: Error = %d\n", Ret);
return Ret;
//goto done;
}
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("ERROR_NOT_ENOUGH_MEMORY");
return Ret;
break;
case ERROR_INVALID_PARAMETER:
printf("ERROR_INVALID_PARAMETER");
return Ret;
break;
case ERROR_INVALID_USER_BUFFER:
printf("ERROR_INVALID_USER_BUFFER");
return Ret;
break;
}
}
DWORD dwVpnStrategy = 0;
char device_name_mask[5];
strcpy(device_name_mask, "");
gboolean preshared_key_valid = 0;
switch(connection_type)
{
case PPTP:
strcpy(device_name_mask, "PPTP");
dwVpnStrategy = VS_PptpOnly;
break;
case L2TP:
if (preshared_key == 0 || strlen(preshared_key) == 0)
{
printf("CRITICAL: preshared key not set.");
return 1;
}
else
{
preshared_key_valid = TRUE;
}
strcpy(device_name_mask, "L2TP");
dwVpnStrategy = VS_L2tpOnly;
break;
}
int i =0;
for (i = 0; i < cbDevices; i++)
{
RASDEVINFO r = ras_devices[i];
if (strstr(r.szDeviceName, device_name_mask))
{
break;
}
}
//lpRasEntry->dwfOptions |= RASEO_SpecificIpAddr;
//lpRasEntry->szLocalPhoneNumber = RASDT_Vpn;
lpRasEntry->dwfNetProtocols |= RASNP_Ip;
lpRasEntry->dwFramingProtocol = RASFP_Ppp;
lstrcpy(lpRasEntry->szDeviceType, RASDT_Vpn);
lstrcpy(lpRasEntry->szDeviceName, ras_devices[i].szDeviceName);
lstrcpy(lpRasEntry->szLocalPhoneNumber, server_address);
lpRasEntry->dwVpnStrategy = dwVpnStrategy; // VS_PptpOnly; VS_SstpOnly
if (preshared_key_valid)
{
L2TP_CONFIG_DATA* data = GlobalAlloc(GPTR, sizeof(L2TP_CONFIG_DATA));
lpRasEntry->dwfOptions2 |= RASEO2_UsePreSharedKey;
data->dwOffsetKey = 16;
memcpy((PBYTE)data + data->dwOffsetKey, preshared_key, strlen(preshared_key));
data->dwAuthType =L2TP_IPSEC_AUTH_PRESHAREDKEY;
RasSetCustomAuthData(NULL, APP_NAME, data, sizeof(L2TP_CONFIG_DATA));
}
if ((Ret = RasSetEntryProperties(NULL, APP_NAME, lpRasEntry, EntryInfoSize, lpDeviceInfo, DeviceInfoSize)) != 0)
{
printf("RasSetEntryProperties failed with error %d\n", Ret);
return Ret;
}
//if ((Ret = RasSetCredentials(NULL, lpRasEntry.))
}
I cant find where is buffer to fill for pre-shared key.
Following code works fine.
// l2tp
if (preshared_key_valid)
{
RASCREDENTIALS ras_cre_psk = {0};
ras_cre_psk.dwSize = sizeof(ras_cre_psk);
ras_cre_psk.dwMask = 0x00000010; //RASCM_PreSharedKey;
wcscpy(ras_cre_psk.szPassword, preshared_key);
if ((Ret = RasSetCredentials(NULL, APP_NAME, &ras_cre_psk, FALSE)))
{
printf("RasSetCredentials failed with error %d\n", Ret);
return Ret;
}
}

"bad packet length" error after updating to OpenSSL 0.9.8.zf

I was using OpenSSL version 0.9.8h in an Android project. I update it to the 0.9.8.zf version but now it doesn't work.
The two functions that highlight the problem are initialize_client_ctx and initialize_client_ctx. When I call SSL_connect I get an SSL_ERROR_SSL error value. By checking details I retrieve a "bad packet length" error (error:14092073:SSL routines:SSL3_GET_SERVER_HELLO:bad packet length).
The point in the code is indicated in a comment. The code works well with the previous version. I attach also a Wireshark capture file. Any ideas?
SSL_CTX *initialize_client_ctx(const char *keyfile, const char *certfile,
const char *password, int transport)
{
SSL_METHOD *meth = NULL;
X509 *cert = NULL;
SSL_CTX *ctx;
if (transport == IPPROTO_UDP) {
meth = DTLSv1_client_method();
} else if (transport == IPPROTO_TCP) {
meth = TLSv1_client_method();
} else {
return NULL;
}
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
//print ... Couldn't create SSL_CTX
return NULL;
}
if (password[0] != '\0') {
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) password);
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
}
if (tls_client_local_cn_name[0] != '\0') {
cert = _tls_set_certificate(ctx, tls_client_local_cn_name);
}
if (cert==NULL && certfile[0] != '\0') {
//print several warnings....
}
if (cert!=NULL)
{
X509_free(cert);
cert = NULL;
}
/* Load the CAs we trust */
{
char *caFile = 0, *caFolder = 0;
int fd = open(eXosip_tls_ctx_params.root_ca_cert, O_RDONLY);
if (fd >= 0) {
struct stat fileStat;
if (fstat(fd, &fileStat) < 0) {
} else {
if (S_ISDIR(fileStat.st_mode)) {
caFolder = eXosip_tls_ctx_params.root_ca_cert;
} else {
caFile = eXosip_tls_ctx_params.root_ca_cert;
}
}
close(fd);
}
{
int verify_mode = SSL_VERIFY_PEER;
SSL_CTX_set_verify(ctx, verify_mode, &verify_cb);
SSL_CTX_set_verify_depth(ctx, ex_verify_depth + 1);
}
}
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_CIPHER_SERVER_PREFERENCE);
if(!SSL_CTX_set_cipher_list(ctx,"ALL")) {
//print ... set_cipher_list: cannot set anonymous DH cipher
SSL_CTX_free(ctx);
return NULL;
}
return ctx;
}
static int _tls_tl_ssl_connect_socket(struct socket_tab *sockinfo)
{
X509 *cert;
BIO *sbio;
int res;
if (sockinfo->ssl_ctx == NULL) {
sockinfo->ssl_ctx =
initialize_client_ctx(eXosip_tls_ctx_params.client.priv_key,
eXosip_tls_ctx_params.client.cert,
eXosip_tls_ctx_params.client.priv_key_pw,
IPPROTO_TCP);
sockinfo->ssl_conn = SSL_new(sockinfo->ssl_ctx);
if (sockinfo->ssl_conn == NULL) {
return -1;
}
sbio = BIO_new_socket(sockinfo->socket, BIO_NOCLOSE);
if (sbio == NULL) {
return -1;
}
SSL_set_bio(sockinfo->ssl_conn, sbio, sbio);
}
do {
struct timeval tv;
int fd;
fd_set readfds;
res = SSL_connect(sockinfo->ssl_conn);
res = SSL_get_error(sockinfo->ssl_conn, res);
if (res == SSL_ERROR_NONE) {
//printf... SSL_connect succeeded
break;
}
if (res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE) {
//<-- here there is a problem res == SSL_ERROR_SSL
//print ERR_reason_error_string(ERR_get_error()));
//print ERR_error_string(ERR_get_error(), NULL));
return -1;
}
tv.tv_sec = SOCKET_TIMEOUT / 1000;
tv.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
//retry the connection
fd = SSL_get_fd(sockinfo->ssl_conn);
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
res = select(fd + 1, &readfds, NULL, NULL, &tv);
if (res < 0) {
//print error
return -1;
} else if (res > 0) {
//print...connetrion done!
} else {
//socket timeout, no data to read
return 1;
}
} while (!SSL_is_init_finished(sockinfo->ssl_conn));
if (SSL_is_init_finished(sockinfo->ssl_conn)) {
//print.. SSL_is_init_finished done
} else {
//print.. failed
}
cert = SSL_get_peer_certificate(sockinfo->ssl_conn);
if (cert != 0) {
int cert_err;
tls_dump_cert_info("tls_connect: remote certificate: ", cert);
cert_err = SSL_get_verify_result(sockinfo->ssl_conn);
if (cert_err != X509_V_OK) {
//print... Failed to verify remote certificate
tls_dump_verification_failure(cert_err);
if (eXosip_tls_ctx_params.server.cert[0] != '\0') {
X509_free(cert);
return -1;
} else if (cert_err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
&& cert_err != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
&& cert_err != X509_V_ERR_CRL_HAS_EXPIRED
&& cert_err != X509_V_ERR_CERT_HAS_EXPIRED
&& cert_err != X509_V_ERR_CERT_REVOKED
&& cert_err != X509_V_ERR_CERT_UNTRUSTED
&& cert_err != X509_V_ERR_CERT_REJECTED) {
X509_free(cert);
return -1;
}
}
X509_free(cert);
} else {
//print .. No certificate received
/* X509_free is not necessary because no cert-object was created -> cert == NULL */
if (eXosip_tls_ctx_params.server.cert[0] == '\0') {
#ifdef ENABLE_ADH
/* how can we guess a user want ADH... specific APIs.. */
sockinfo->ssl_state = 3;
return 0;
#endif
}
return -1;
}
sockinfo->ssl_state = 3;
return 0;
}
SOLVED Thanks to Eric Tsui that helps me to figure out the problem. The 'hello' that I receive from the server in the handshake has zero length. To solve this I modified the file openssl/ssl/s3_clnt.c in the following way (toggling off the length control):
diff -ur ./s3_clnt.c ./original/s3_clnt.c
--- submodules/externals/openssl/ssl/s3_clnt.c 2015-06-29 14:59:56.723462992 +0200
+++ ../../opensslOrig/s3_clnt.c 2015-06-29 15:00:22.487464221 +0200
## -868,12 +868,14 ##
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
if (p != (d + n)) {
/* wrong packet length */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
goto f_err;
}
+#endif
return (1);
f_err:

Resources