PRIVILEGE_CONSUMER
} privilege_type;
+typedef enum {
+ CERT_UNCHECKED,
+ CERT_MATCH,
+ CERT_MISMATCH
+} cert_status_type;
+
int convert_to_tizen_error(datacontrol_error_e error);
int datacontrol_check_privilege(privilege_type check_type);
+int datacontrol_check_cert(const char *provider_id, bool is_map,
+ const char *consumer_appid);
#ifdef __cplusplus
}
#include <gio/gio.h>
#include <bundle.h>
#include "data_control_types.h"
+#include "data_control_internal.h"
#ifndef _APPFW_DATA_CONTROL_INTERNAL_H_
#define _APPFW_DATA_CONTROL_INTERNAL_H_
return ret;
}
-int __provider_process(bundle *b, int fd)
+int __provider_process(bundle *b, int fd, const char *consumer_appid)
{
+ int ret;
int len = 0;
const char **arg_list = NULL;
const char **column_list = NULL;
datacontrol_h provider = NULL;
int provider_req_id = 0;
int *key = NULL;
+ bool is_map;
+ char *provider_id;
+ char *caller_appid;
bundle *value = NULL;
const char *request_type = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE);
/* Get the request type */
datacontrol_request_type type = atoi(request_type);
if (type >= DATACONTROL_TYPE_SQL_SELECT && type <= DATACONTROL_TYPE_SQL_BULK_INSERT) {
+ is_map = false;
if (provider_sql_cb == NULL) {
LOGE("SQL callback is not registered.");
return DATACONTROL_ERROR_INVALID_PARAMETER;
}
} else if (type >= DATACONTROL_TYPE_MAP_GET && type <= DATACONTROL_TYPE_MAP_BULK_ADD) {
+ is_map = true;
if (provider_map_cb == NULL) {
LOGE("Map callback is not registered.");
return DATACONTROL_ERROR_INVALID_PARAMETER;
return DATACONTROL_ERROR_INVALID_PARAMETER;
}
+ caller_appid = (char *)bundle_get_val(b, AUL_K_CALLER_APPID);
+ if (caller_appid && strncmp(caller_appid,
+ consumer_appid, strlen(consumer_appid)) != 0) {
+ LOGE("The passed appid(%s) is different from the registered appid(%s).",
+ caller_appid, consumer_appid);
+ return DATACONTROL_ERROR_NONE;
+ }
+
+ provider_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER);
+ ret = datacontrol_check_cert(provider_id, is_map, consumer_appid);
+ if (ret != DATA_CONTROL_ERROR_NONE) {
+ if (ret == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+ LOGE("The consumer (%s) is not signed with the same certificate",
+ consumer_appid);
+ return DATACONTROL_ERROR_NONE;
+ } else {
+ return DATACONTROL_ERROR_IO_ERROR;
+ }
+ }
+
arg_list = bundle_get_str_array(b, OSP_K_ARG, &len);
provider = malloc(sizeof(struct datacontrol_s));
}
/* Set the provider ID */
- provider->provider_id = (char *)bundle_get_val(b, OSP_K_DATACONTROL_PROVIDER);
+ provider->provider_id = provider_id;
/* Set the data ID */
provider->data_id = (char *)arg_list[PACKET_INDEX_DATAID];
{
char *buf = NULL;
int data_len;
+ char *consumer_appid = (char *)data;
guint nb;
gint fd = g_io_channel_unix_get_fd(channel);
}
kb = bundle_decode_raw((bundle_raw *)buf, data_len);
- if (__provider_process(kb, fd) != DATACONTROL_ERROR_NONE) {
+ if (__provider_process(kb, fd, consumer_appid) != DATACONTROL_ERROR_NONE) {
bundle_free(kb);
goto error;
}
return retval;
error:
- if (((char *)data) != NULL)
- g_hash_table_remove(__socket_pair_hash, (char *)data);
+ if (consumer_appid != NULL)
+ g_hash_table_remove(__socket_pair_hash, consumer_appid);
if (buf)
free(buf);
return result;
}
+static int __check_consumer_cert(const char *provider_id,
+ const char *consumer_appid,
+ datacontrol_data_change_type_e type)
+{
+ bool is_map;
+
+ if (consumer_appid == NULL)
+ return DATACONTROL_ERROR_IO_ERROR;
+
+ if (type >= DATACONTROL_DATA_CHANGE_SQL_UPDATE &&
+ type <= DATACONTROL_DATA_CHANGE_SQL_DELETE)
+ is_map = false;
+ else
+ is_map = true;
+
+ return datacontrol_check_cert(provider_id, is_map, consumer_appid);
+}
+
int datacontrol_provider_send_data_change_noti(
datacontrol_h provider,
datacontrol_data_change_type_e type,
consumer_iter = g_list_first(__noti_consumer_app_list);
for (; consumer_iter != NULL; consumer_iter = consumer_iter->next) {
consumer_info = (datacontrol_consumer_info *)consumer_iter->data;
+ if (__check_consumer_cert(provider->provider_id,
+ consumer_info->appid,
+ type) != DATACONTROL_ERROR_NONE)
+ continue;
result = __send_signal_to_consumer(
provider,
consumer_info->unique_id,
#include <fcntl.h>
#include <cynara-client.h>
#include <stdio.h>
+#include <pkgmgr-info.h>
+#include <aul.h>
#include "data_control_internal.h"
#define _LOGE(fmt, arg...) LOGE(fmt, ##arg)
#define _LOGD(fmt, arg...) LOGD(fmt, ##arg)
+#define CHECKED_CACHE_SIZE 10
+
+struct datacontrol_cert_info {
+ cert_status_type sql;
+ cert_status_type map;
+ time_t time;
+};
+
+static GHashTable *__checked_provider_hash;
+static GHashTable *__checked_consumer_hash;
int datacontrol_check_privilege(privilege_type check_type)
{
-
cynara *p_cynara = NULL;
int fd = 0;
return ret;
}
+static char *__get_victim(GHashTable *hash)
+{
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+ time_t time = 0;
+ char *victim_key = NULL;
+
+ g_hash_table_iter_init(&iter, hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ struct datacontrol_cert_info *info = (struct datacontrol_cert_info *)value;
+ if (time == 0 || time > info->time) {
+ time = info->time;
+ victim_key = key;
+ }
+ }
+
+ return victim_key;
+}
+
+static void _insert_hash(GHashTable *hash, const char *key,
+ bool is_map, cert_status_type status)
+{
+ struct datacontrol_cert_info *cert_info;
+ char *victim_key;
+
+ if (g_hash_table_size(hash) > CHECKED_CACHE_SIZE) {
+ victim_key = __get_victim(hash);
+ if (victim_key)
+ g_hash_table_remove(hash, victim_key);
+ }
+
+ cert_info = (struct datacontrol_cert_info *)calloc(1,
+ sizeof(struct datacontrol_cert_info));
+
+ if (is_map)
+ cert_info->map = status;
+ else
+ cert_info->sql = status;
+
+ time(&cert_info->time);
+
+ g_hash_table_insert(hash, strdup(key), cert_info);
+}
+
+int datacontrol_check_cert(const char *provider_id, bool is_map,
+ const char *consumer_appid)
+{
+ int ret;
+ bool is_trusted;
+ bool is_update = false;
+ char *provider_appid;
+ char appid[255];
+ GHashTable *hash_table;
+ struct datacontrol_cert_info *cert_info;
+ cert_status_type *status;
+ pkgmgrinfo_cert_compare_result_type_e res;
+
+ if (consumer_appid == NULL) {
+ if (__checked_provider_hash == NULL)
+ __checked_provider_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
+ hash_table = __checked_provider_hash;
+ } else {
+ if (__checked_consumer_hash == NULL)
+ __checked_consumer_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
+ hash_table = __checked_consumer_hash;
+ }
+
+ cert_info = g_hash_table_lookup(hash_table, provider_id);
+
+ if (cert_info) {
+ status = is_map ? &cert_info->map : &cert_info->sql;
+
+ if (*status == CERT_MATCH)
+ return DATA_CONTROL_ERROR_NONE;
+ else if (*status == CERT_MISMATCH)
+ return DATA_CONTROL_ERROR_PERMISSION_DENIED;
+
+ is_update = true;
+ }
+
+ ret = pkgmgrinfo_appinfo_usr_get_datacontrol_trusted_info(provider_id,
+ is_map ? "Map" : "Sql", getuid(), &provider_appid, &is_trusted);
+ if (ret != PMINFO_R_OK) {
+ LOGE("unable to get data control information: %d", ret);
+ return DATA_CONTROL_ERROR_IO_ERROR;
+ }
+
+ if (!is_trusted) {
+ if (is_update)
+ *status = CERT_MATCH;
+ else
+ _insert_hash(hash_table, provider_id, is_map, CERT_MATCH);
+ free(provider_appid);
+ return DATA_CONTROL_ERROR_NONE;
+ }
+
+ if (!consumer_appid) {
+ ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
+ if (ret != AUL_R_OK) {
+ LOGE("Failed to get appid: %d", ret);
+ free(provider_appid);
+ return DATA_CONTROL_ERROR_IO_ERROR;
+ }
+ consumer_appid = appid;
+ }
+
+ ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(provider_appid,
+ consumer_appid, getuid(), &res);
+ if (ret < 0) {
+ LOGE("certificate check [%d] failed!", ret);
+ free(provider_appid);
+ return DATA_CONTROL_ERROR_IO_ERROR;
+ }
+ if (res != PMINFO_CERT_COMPARE_MATCH) {
+ LOGE("certificate mismatch. provider : %s consumer %s",
+ provider_appid, consumer_appid);
+ if (is_update)
+ *status = CERT_MISMATCH;
+ else
+ _insert_hash(hash_table, provider_id, is_map, CERT_MISMATCH);
+ free(provider_appid);
+ return DATA_CONTROL_ERROR_PERMISSION_DENIED;
+ }
+
+ if (is_update)
+ *status = CERT_MATCH;
+ else
+ _insert_hash(hash_table, provider_id, is_map, CERT_MATCH);
+
+ free(provider_appid);
+
+ return DATA_CONTROL_ERROR_NONE;
+}
+
int convert_to_tizen_error(datacontrol_error_e error)
{
switch (error) {
default:
return error;
}
-}
\ No newline at end of file
+}
EXPORT_API int data_control_map_get(data_control_h provider, const char *key, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || key == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_map_get_with_page(data_control_h provider, const char *key, int *request_id, int page_number, int count_per_page)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || key == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_map_set(data_control_h provider, const char *key, const char *old_value, const char *new_value, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || key == NULL ||
+ old_value == NULL || new_value == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_map_add(data_control_h provider, const char *key, const char *value, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || key == NULL || value == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_map_remove(data_control_h provider, const char *key, const char *value, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || key == NULL || value == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_map_add_bulk_data(data_control_h provider, data_control_bulk_data_h bulk_data_h, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
#include "data_control_noti.h"
#include "data-control-noti.h"
+struct data_control_s {
+ char *provider_id;
+ char *data_id;
+};
+
EXPORT_API int data_control_add_data_change_cb(
data_control_h provider,
data_control_data_change_cb callback,
void *result_cb_user_data,
int *callback_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
if (callback == NULL || provider == NULL || callback_id == NULL)
return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
+ if (retval == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+ } else if (retval != DATA_CONTROL_ERROR_NONE) {
+ return retval;
+ }
+
return datacontrol_add_data_change_cb(
(datacontrol_h)provider,
callback,
EXPORT_API int data_control_remove_data_change_cb(data_control_h provider, int callback_id)
{
+ int retval;
+
if (callback_id < 1 || provider == NULL)
return DATA_CONTROL_ERROR_INVALID_PARAMETER;
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
+ retval = datacontrol_check_cert(provider->provider_id, true, NULL);
+ if (retval == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+ } else if (retval != DATA_CONTROL_ERROR_NONE) {
+ return retval;
+ }
+
return datacontrol_remove_data_change_cb((datacontrol_h)provider, callback_id);
}
EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider, data_control_bulk_data_h bulk_data_h, int *request_id)
{
+ int retval;
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_sql_insert(data_control_h provider, const bundle *insert_data, int *request_id)
{
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || insert_data == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_sql_delete(data_control_h provider, const char *where, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_sql_select(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || column_list == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_sql_select_with_page(data_control_h provider, char **column_list, int column_count, const char *where, const char *order, int page_number, int count_per_page, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL || column_list == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;
EXPORT_API int data_control_sql_update(data_control_h provider, const bundle *update_data, const char *where, int *request_id)
{
- int retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ int retval;
+
+ if (provider == NULL || provider->provider_id == NULL ||
+ provider->data_id == NULL ||
+ update_data == NULL || where == NULL) {
+ _LOGE("Invalid parameter");
+ return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+ }
+
+ retval = datacontrol_check_privilege(PRIVILEGE_CONSUMER);
+ if (retval != DATA_CONTROL_ERROR_NONE)
+ return retval;
+
+ retval = datacontrol_check_cert(provider->provider_id, false, NULL);
if (retval != DATA_CONTROL_ERROR_NONE)
return retval;