[SATDEVKIT-2522]Security issues handled
[sdk/target/sdbd.git] / src / plugin.c
index 7ef796f..3c2533c 100644 (file)
@@ -17,7 +17,8 @@
 #include <string.h>
 #include <dlfcn.h>
 
-#define TRACE_TAG TRACE_SDB
+//#define TRACE_TAG TRACE_SDB
+#define LOG_TAG "SDBD_TRACE_SDB"
 #include "log.h"
 
 #include "sdb.h"
@@ -27,7 +28,7 @@
 #include "plugin.h"
 #include "sdbd_plugin.h"
 
-static void* plugin_handle = NULL;
+void* g_plugin_handle = NULL;
 
 PLUGIN_INIT plugin_init_proc = NULL;
 PLUGIN_SYNCHRONOUS_CMD_PROC plugin_sync_proc = NULL;
@@ -35,6 +36,14 @@ PLUGIN_ASYNCHRONOUS_CMD_PROC plugin_async_proc = NULL;
 
 hashtable* plugin_cmd_hashtable = NULL;
 
+char* extcmd = NULL;
+
+typedef struct _async_parameter {
+    int cmd;
+    parameters* in;
+    int out_fd;
+} async_parameter;
+
 // handler of event to be detected by plugin
 int plugin_event_handler ( int event_type, parameters* data )
 {
@@ -67,7 +76,10 @@ int plugin_event_handler ( int event_type, parameters* data )
 static int plugin_register_command ( int command, priority cmd_priority )
 {
     if ( plugin_cmd_hashtable ) {
-        hashtable_put ( plugin_cmd_hashtable, command, cmd_priority );
+        int ret = hashtable_put ( plugin_cmd_hashtable, command, cmd_priority );
+        D ("register plugin command : cmd(%d), result(%d)\n", command, ret);
+    } else {
+        I ("hashtable is not created\n");
     }
     return 0;
 }
@@ -80,28 +92,28 @@ static int load_plugin_not_default()
     plugin_sync_proc = NULL;
     plugin_async_proc = NULL;
 
-    plugin_handle = dlopen ( PLUGIN_PATH, RTLD_NOW );
-    if ( plugin_handle == NULL ) {
-        D ( "failed to dlopen(%s). error: %s\n", PLUGIN_PATH, dlerror() );
+    g_plugin_handle = dlopen ( PLUGIN_PATH, RTLD_NOW );
+    if ( g_plugin_handle == NULL ) {
+        E ( "failed to dlopen(%s). error: %s\n", PLUGIN_PATH, dlerror() );
         return 0;
     }
 
-    plugin_init_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_INIT );
+    plugin_init_proc = dlsym ( g_plugin_handle, PLUGIN_PROC_NAME_INIT );
     if ( plugin_init_proc == NULL ) {
-        D ( "failed to get the sdbd plugin init function. error: %s\n", dlerror() );
-        dlclose ( plugin_handle );
-        plugin_handle = NULL;
+        E ( "failed to get the sdbd plugin init function. error: %s\n", dlerror() );
+        dlclose ( g_plugin_handle );
+        g_plugin_handle = NULL;
         return 0;
     }
 
     // if there is no implementation of plugin_sync_proc and plugin_async_proc,
     // then use default_plugin_sync_proc and default_plugin_async_proc
-    plugin_sync_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_SYNC_CMD );
+    plugin_sync_proc = dlsym ( g_plugin_handle, PLUGIN_PROC_NAME_SYNC_CMD );
     if ( plugin_sync_proc == NULL ) {
         plugin_sync_proc = default_plugin_sync_proc;
     }
 
-    plugin_async_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_ASYNC_CMD );
+    plugin_async_proc = dlsym ( g_plugin_handle, PLUGIN_PROC_NAME_ASYNC_CMD );
     if ( plugin_async_proc == NULL ) {
         plugin_async_proc = default_plugin_async_proc;
     }
@@ -109,6 +121,42 @@ static int load_plugin_not_default()
     return 1;
 }
 
+void readxml() {
+    char * buffer = NULL;
+    long length;
+    size_t result;
+    FILE * fptr = fopen(PLUGIN_XML_PATH, "rb");
+
+    if (fptr == NULL) {
+        E("failed to open commands.xml\n");
+        return;
+    }
+
+    fseek(fptr, 0, SEEK_END);
+    length = ftell(fptr);
+    if (length <= 0) {
+        E("commands.xml is empty\n");
+        fclose(fptr);
+        return;
+    }
+    fseek(fptr, 0, SEEK_SET);
+    buffer = malloc(length);
+    if (buffer) {
+        result = fread(buffer, 1, length, fptr);
+        if (result != length) {
+            E("xml file read error\n");
+            free(buffer);
+            fclose(fptr);
+            return;
+        }
+    }
+    fclose(fptr);
+    if (buffer) {
+        D("command xml data: %s\n", buffer);
+        extcmd = buffer;
+    }
+}
+
 void load_sdbd_plugin()
 {
     int ret;
@@ -122,11 +170,12 @@ void load_sdbd_plugin()
         plugin_sync_proc = default_plugin_sync_proc;
         plugin_async_proc = default_plugin_async_proc;
 
-        D ( "using default plugin interface.\n" );
+        I ( "using default plugin interface.\n" );
     } else {
         D ( "using sdbd plugin interface.(%s)\n", PLUGIN_PATH );
 
         plugin_init_proc ( plugin_event_handler, plugin_register_command );
+        readxml();
     }
 
     // use default plugin feature for the commands or events that are not supported by plugin
@@ -140,9 +189,14 @@ void unload_sdbd_plugin()
         plugin_cmd_hashtable = NULL;
     }
 
-    if ( plugin_handle ) {
-        dlclose ( plugin_handle );
-        plugin_handle = NULL;
+    if ( g_plugin_handle ) {
+        dlclose ( g_plugin_handle );
+        g_plugin_handle = NULL;
+    }
+
+    if (extcmd) {
+        free(extcmd);
+        extcmd = NULL;
     }
 }
 
@@ -155,34 +209,163 @@ int is_supported_by_plugin ( int cmd )
     if ( plugin_cmd_hashtable ) {
         int value;
         ret = hashtable_get ( plugin_cmd_hashtable, cmd, &value );
+        D ("get from hashtable : cmd(%d), result(%d)\n", cmd, ret);
+    } else {
+        D ("hashtable is not created\n");
     }
 
     return ret;
 }
 
-static int request_sync_cmd ( int cmd, parameters* in, parameters* out )
+int request_sync_cmd ( int cmd, parameters* in, parameters* out )
 {
     int ret, pr;
 
     out->number_of_parameter = 0;
     out->array_of_parameter = NULL;
 
-    ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
-    if ( ret == 1 ) {
-        // supported by plugin
-        ret = plugin_sync_proc ( cmd, in, out );
-        if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
-            // not supported by plugin
-            ret = default_plugin_sync_proc ( cmd, in, out );
-        }
+    if ( plugin_cmd_hashtable ) {
+       ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
+       if ( ret == 1 ) {
+               // supported by plugin
+               ret = plugin_sync_proc ( cmd, in, out );
+               if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
+                       // not supported by plugin
+                       ret = default_plugin_sync_proc ( cmd, in, out );
+               }
+       } else {
+               // not supported by plugin
+               ret = default_plugin_sync_proc ( cmd, in, out );
+       }
     } else {
-        // not supported by plugin
-        ret = default_plugin_sync_proc ( cmd, in, out );
+       ret = default_plugin_sync_proc ( cmd, in, out );
     }
 
     return ret;
 }
 
+static void request_async_cmd ( int cmd, parameters* in, int out_fd )
+{
+    int ret, pr;
+
+    if ( plugin_cmd_hashtable ) {
+       ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
+       if ( ret == 1 ) {
+               // supported by plugin
+               ret = plugin_async_proc ( cmd, in, out_fd );
+               if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
+                       // not supported by plugin
+                       ret = default_plugin_async_proc ( cmd, in, out_fd );
+               }
+       } else {
+               // not supported by plugin
+               ret = default_plugin_async_proc ( cmd, in, out_fd );
+       }
+    } else {
+       ret = default_plugin_async_proc ( cmd, in, out_fd );
+    }
+
+    release_parameters(in);
+    free(in);
+    sdb_close(out_fd);
+}
+
+static void *async_proc_bootstrap_func(void *x)
+{
+    async_parameter *p = x;
+    request_async_cmd(p->cmd, p->in, p->out_fd);
+    free(p);
+    return 0;
+}
+
+static int create_async_proc_thread( int cmd, parameters* in )
+{
+    async_parameter* async_param;
+    sdb_thread_t t;
+    int s[2];
+
+    if (sdb_socketpair(s)) {
+        release_parameters(in);
+        free(in);
+        E("cannot create async proc socket pair\n");
+        return -1;
+    }
+
+    async_param = (async_parameter*)malloc(sizeof(async_parameter));
+    if (async_param == NULL) {
+        release_parameters(in);
+        free(in);
+        fatal("cannot allocate async_parameter");
+        return -1;
+    }
+
+    async_param->cmd = cmd;
+    async_param->in = in;
+    async_param->out_fd = s[1];
+
+    if (sdb_thread_create(&t, async_proc_bootstrap_func, async_param)) {
+        free(async_param);
+        sdb_close(s[0]);
+        sdb_close(s[1]);
+        release_parameters(in);
+        free(in);
+        E("cannot create async proc thread\n");
+        return -1;
+    }
+
+    D("async proc thread started, %d:%d\n",s[0], s[1]);
+    return s[0];
+}
+
+static void *async_proc_extcmd_bootstrap_func(void *x)
+{
+    async_parameter *p = x;
+    plugin_async_proc(p->cmd, p->in, p->out_fd);
+    release_parameters(p->in);
+    free(p->in);
+    sdb_close(p->out_fd);
+    free(p);
+    return 0;
+}
+
+int create_async_extcmd_proc_thread( int cmd, parameters* in )
+{
+    async_parameter* async_param;
+    sdb_thread_t t;
+    int s[2];
+
+    if (sdb_socketpair(s)) {
+        release_parameters(in);
+        free(in);
+        E("cannot create extcmd async proc socket pair\n");
+        return -1;
+    }
+
+    async_param = (async_parameter*)malloc(sizeof(async_parameter));
+    if (async_param == NULL) {
+        release_parameters(in);
+        free(in);
+        fatal("cannot allocate async_parameter");
+        return -1;
+    }
+
+    async_param->cmd = cmd;
+    async_param->in = in;
+    async_param->out_fd = s[1];
+
+    if (sdb_thread_create(&t, async_proc_extcmd_bootstrap_func, async_param)) {
+        free(async_param);
+        sdb_close(s[0]);
+        sdb_close(s[1]);
+        release_parameters(in);
+        free(in);
+        E("cannot create extcmd async proc thread\n");
+        return -1;
+    }
+
+    D("extcmd async proc thread started, %d:%d\n",s[0], s[1]);
+    return s[0];
+}
 
 // return 1 if succeed to get capability from plugin
 // return 0 otherwise
@@ -194,15 +377,25 @@ int request_capability_to_plugin ( int cap, char* out_buf, unsigned int out_len
 
     in.number_of_parameter = 1;
     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+    if (in.array_of_parameter == NULL) {
+        E("failed to allocate memory for the parameter\n");
+        return success;
+    }
     in.array_of_parameter[0].type = type_int32;
     in.array_of_parameter[0].v_int32 = cap;
 
+    D ("requested capability : %d\n", cap);
+
     ret = request_sync_cmd ( PLUGIN_SYNC_CMD_CAPABILITY, &in, &out );
     if ( ret == PLUGIN_CMD_SUCCESS ) {
-        strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
-        out_buf[out_len - 1] = '\0';
-        success = 1;
+       if(out.array_of_parameter[0].v_string.data != NULL) {
+               strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
+               out_buf[out_len - 1] = '\0';
+               success = 1;
+       }
         release_parameters ( &out );
+
+        D ("request capability success : %s\n", out_buf);
     }
 
     release_parameters ( &in );
@@ -220,6 +413,10 @@ int request_validity_to_plugin ( int cmd, const char* in_buf )
     if ( in_buf != NULL ) {
         in.number_of_parameter = 1;
         in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in.array_of_parameter == NULL) {
+            D("failed to allocate memory for the parameter\n");
+            return success;
+        }
         in.array_of_parameter[0].type = type_string;
         in.array_of_parameter[0].v_string.length = strlen ( in_buf );
         in.array_of_parameter[0].v_string.data = strdup ( in_buf );
@@ -228,10 +425,53 @@ int request_validity_to_plugin ( int cmd, const char* in_buf )
         in.array_of_parameter = NULL;
     }
 
+    D ("requested validity : %d, %s\n", cmd, in_buf);
+
     ret = request_sync_cmd ( cmd, &in, &out );
     if ( ret == PLUGIN_CMD_SUCCESS ) {
         success = ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_VALID ) ? 1 : 0;
         release_parameters ( &out );
+
+        D ("request validity success : %d\n", success);
+    }
+
+    release_parameters ( &in );
+    return success;
+}
+
+// return 1 if allowed by plugin (valid)
+// return 0 if disallowed by plugin (invalid)
+int request_extcmd_validity_to_plugin ( int cmd, const char* in_buf)
+{
+    int success = 0;
+    int ret;
+    parameters in, out;
+
+    if ( in_buf != NULL ) {
+        in.number_of_parameter = 1;
+        in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in.array_of_parameter == NULL) {
+            D("failed to allocate memory for the parameter\n");
+            return success;
+        }
+        in.array_of_parameter[0].type = type_string;
+        in.array_of_parameter[0].v_string.length = strlen ( in_buf );
+        in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+    } else {
+        in.number_of_parameter = 0;
+        in.array_of_parameter = NULL;
+    }
+
+    D ("requested validity : %d, %s\n", cmd, in_buf);
+
+    out.number_of_parameter = 0;
+    out.array_of_parameter = NULL;
+    ret = plugin_sync_proc ( cmd, &in, &out );
+    if ( ret == PLUGIN_CMD_SUCCESS ) {
+        success = ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_VALID ) ? 1 : 0;
+        release_parameters ( &out );
+
+        D ("request validity success : %d\n", success);
     }
 
     release_parameters ( &in );
@@ -246,17 +486,68 @@ int request_conversion_to_plugin ( int cmd, const char* in_buf, char* out_buf, u
     int ret;
     parameters in, out;
 
-    in.number_of_parameter = 1;
-    in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
-    in.array_of_parameter[0].type = type_string;
-    in.array_of_parameter[0].v_string.length = strlen ( in_buf );
-    in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+    if ( in_buf != NULL ) {
+        in.number_of_parameter = 1;
+        in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in.array_of_parameter == NULL) {
+            E("failed to allocate memory for the parameter\n");
+            return success;
+        }
+        in.array_of_parameter[0].type = type_string;
+        in.array_of_parameter[0].v_string.length = strlen ( in_buf );
+        in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+    } else {
+        in.number_of_parameter = 0;
+        in.array_of_parameter = NULL;
+    }
 
     ret = request_sync_cmd ( cmd, &in, &out );
     if ( ret == PLUGIN_CMD_SUCCESS ) {
-        strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
-        out_buf[out_len - 1] = '\0';
-        success = 1;
+       if(out.array_of_parameter[0].v_string.data != NULL) {
+               strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
+               out_buf[out_len - 1] = '\0';
+               success = 1;
+       }
+        release_parameters ( &out );
+    }
+
+    release_parameters ( &in );
+    return success;
+}
+
+// return 1 if succeed to convert
+// return 0 otherwise
+int request_extcmd_conversion_to_plugin ( int cmd, const char* in_buf, char* out_buf, unsigned int out_len )
+{
+    int success = 0;
+    int ret;
+    parameters in, out;
+
+    if ( in_buf != NULL ) {
+        in.number_of_parameter = 1;
+        in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in.array_of_parameter == NULL) {
+            E("failed to allocate memory for the parameter\n");
+            return success;
+        }
+        in.array_of_parameter[0].type = type_string;
+        in.array_of_parameter[0].v_string.length = strlen ( in_buf );
+        in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+    } else {
+        in.number_of_parameter = 0;
+        in.array_of_parameter = NULL;
+    }
+
+    out.number_of_parameter = 0;
+    out.array_of_parameter = NULL;
+
+    ret = plugin_sync_proc ( cmd, &in, &out );
+    if ( ret == PLUGIN_CMD_SUCCESS ) {
+       if(out.array_of_parameter[0].v_string.data != NULL) {
+               strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
+               out_buf[out_len - 1] = '\0';
+               success = 1;
+       }
         release_parameters ( &out );
     }
 
@@ -275,6 +566,10 @@ int request_lock_state_to_plugin ( int lock_type )
 
     in.number_of_parameter = 1;
     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+    if (in.array_of_parameter == NULL) {
+        E("failed to allocate memory for the parameter\n");
+        return result;
+    }
     in.array_of_parameter[0].type = type_int32;
     in.array_of_parameter[0].v_int32 = lock_type;
 
@@ -293,3 +588,108 @@ int request_lock_state_to_plugin ( int lock_type )
 
     return result;
 }
+
+// return 1 if shell command handled by plugin (handle)
+// return 0 if shell command not handled by plugin (not handle)
+int request_handlecmd_to_plugin ( int cmd, const char* in_buf )
+{
+    int success = 0;
+    int ret;
+    parameters in, out;
+
+    if ( in_buf != NULL ) {
+        in.number_of_parameter = 1;
+        in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in.array_of_parameter == NULL) {
+            D("failed to allocate memory for the parameter\n");
+            return success;
+        }
+        in.array_of_parameter[0].type = type_string;
+        in.array_of_parameter[0].v_string.length = strlen ( in_buf );
+        in.array_of_parameter[0].v_string.data = strdup ( in_buf );
+    } else {
+        in.number_of_parameter = 0;
+        in.array_of_parameter = NULL;
+    }
+
+    D ("requested command handling : %d, %s\n", cmd, in_buf);
+
+    ret = request_sync_cmd ( cmd, &in, &out );
+    if ( ret == PLUGIN_CMD_SUCCESS ) {
+        success = ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_HANDLE ) ? 1 : 0;
+        release_parameters ( &out );
+
+        D ("request command handling success : %d\n", success);
+    }
+
+    release_parameters ( &in );
+    return success;
+}
+
+int request_shellcmd_to_plugin ( const char* in_buf )
+{
+    parameters* in;
+    int fd;
+
+    in = (parameters*)malloc(sizeof(parameters));
+    if (in == NULL) {
+        E("failed to allocate memory for the parameters\n");
+        return -1;
+    }
+
+    if ( in_buf != NULL ) {
+        in->number_of_parameter = 1;
+        in->array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in->array_of_parameter == NULL) {
+            free(in);
+            E("failed to allocate memory for the parameter\n");
+            return -1;
+        }
+        in->array_of_parameter[0].type = type_string;
+        in->array_of_parameter[0].v_string.length = strlen ( in_buf );
+        in->array_of_parameter[0].v_string.data = strdup ( in_buf );
+    } else {
+        in->number_of_parameter = 0;
+        in->array_of_parameter = NULL;
+    }
+
+    fd = create_async_proc_thread( PLUGIN_ASYNC_CMD_HANDLEBYPLUGIN_SERVICE, in );
+
+    return fd;
+}
+
+// return nonnegative integer that is a socket descriptor for communication
+//        with async proc thread if success to create async proc thread
+// return -1 if failed to create async proc thread
+int request_appcmd_to_plugin ( const char* in_buf )
+{
+    parameters* in;
+    int fd;
+
+    in = (parameters*)malloc(sizeof(parameters));
+    if (in == NULL) {
+        E("failed to allocate memory for the parameters\n");
+        return -1;
+    }
+
+    if ( in_buf != NULL ) {
+        in->number_of_parameter = 1;
+        in->array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
+        if (in->array_of_parameter == NULL) {
+            free(in);
+            E("failed to allocate memory for the parameter\n");
+            return -1;
+        }
+        in->array_of_parameter[0].type = type_string;
+        in->array_of_parameter[0].v_string.length = strlen ( in_buf );
+        in->array_of_parameter[0].v_string.data = strdup ( in_buf );
+    } else {
+        in->number_of_parameter = 0;
+        in->array_of_parameter = NULL;
+    }
+
+    fd = create_async_proc_thread( PLUGIN_ASYNC_CMD_APPCMD_SERVICE, in );
+
+    return fd;
+}
+