merge back from tizen_2.1_smack
authorKidong Kim <kd0228.kim@samsung.com>
Fri, 10 May 2013 08:59:48 +0000 (17:59 +0900)
committerKidong Kim <kd0228.kim@samsung.com>
Fri, 10 May 2013 08:59:48 +0000 (17:59 +0900)
18 files changed:
CMakeLists.txt
packaging/security-server.spec
src/CMakeLists.txt
src/client/security-server-client.c
src/communication/security-server-comm.c
src/include/security-server-comm.h
src/include/security-server-common.h
src/include/security-server-rules-revoker.h [new file with mode: 0644]
src/include/security-server-system-observer.h [new file with mode: 0644]
src/include/security-server.h
src/include/smack-check.h
src/security-serverd
src/server/security-server-cookie.c
src/server/security-server-main.c
src/server/security-server-password.c
src/server/security-server-rules-revoker.c [new file with mode: 0644]
src/server/security-server-system-observer.c [new file with mode: 0644]
src/util/smack-check.c

index 740aa89..c970c45 100644 (file)
@@ -54,6 +54,7 @@ ADD_DEFINITIONS("-Wextra")                      # Generate even more extra warni
 
 STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}")
 ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"")
+ADD_DEFINITIONS( -DSMACK_ENABLED )
 
 SET(TARGET_SECURITY_SERVER "security-server")
 SET(TARGET_SECURITY_CLIENT "security-server-client")
index c1d8d56..df34f09 100644 (file)
@@ -19,6 +19,8 @@ BuildRequires: pkgconfig(libsmack)
 Requires(preun):  systemd
 Requires(post):   systemd
 Requires(postun): systemd
+BuildRequires: pkgconfig(libprivilege-control)
+
 %description
 Security server and utilities
 
index 15466cc..258ea12 100644 (file)
@@ -2,6 +2,7 @@ PKG_CHECK_MODULES(SECURITY_SERVER_DEP
     dlog
     openssl
     libsmack
+    libprivilege-control
     REQUIRED
     )
 
@@ -13,6 +14,9 @@ SET(SECURITY_SERVER_SOURCES
     ${SECURITY_SERVER_PATH}/server/security-server-main.c
     ${SECURITY_SERVER_PATH}/server/security-server-password.c
     ${SECURITY_SERVER_PATH}/util/security-server-util-common.c
+    ${SECURITY_SERVER_PATH}/server/security-server-system-observer.c
+    ${SECURITY_SERVER_PATH}/server/security-server-rules-revoker.c
+    ${SECURITY_SERVER_PATH}/util/smack-check.c
     )
 
 SET_SOURCE_FILES_PROPERTIES(
@@ -39,6 +43,7 @@ SET(SECURITY_CLIENT_VERSION ${SECURITY_CLIENT_VERSION_MAJOR}.0.1)
 SET(SECURITY_CLIENT_SOURCES
     ${SECURITY_SERVER_PATH}/client/security-server-client.c
     ${SECURITY_SERVER_PATH}/communication/security-server-comm.c
+    ${SECURITY_SERVER_PATH}/util/smack-check.c
     )
 
 ADD_LIBRARY(${TARGET_SECURITY_CLIENT} SHARED ${SECURITY_CLIENT_SOURCES})
index 68e83a0..6550946 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/smack.h>
 #include <fcntl.h>
 
+#include "smack-check.h"
 #include "security-server.h"
 #include "security-server-common.h"
 #include "security-server-comm.h"
@@ -396,7 +397,7 @@ int security_server_check_privilege_by_cookie(const char *cookie,
         olen = strlen(object);
         alen = strlen(access_rights);
 
-        if (olen > MAX_OBJECT_LABEL_LEN || alen > MAX_MODE_STR_LEN)
+        if (olen > SMACK_LABEL_LEN || alen > MAX_MODE_STR_LEN)
        {
                retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
                goto error;
@@ -453,6 +454,12 @@ int security_server_check_privilege_by_sockfd(int sockfd,
                                               const char *object,
                                               const char *access_rights)
 {
+    if (!smack_check())
+    {
+        SEC_SVR_DBG("%s","No SMACK support on device");
+        return SECURITY_SERVER_API_SUCCESS;
+    }
+
     char *subject;
     int ret;
     ret = smack_new_label_from_socket(sockfd, &subject);
@@ -461,8 +468,9 @@ int security_server_check_privilege_by_sockfd(int sockfd,
         return SECURITY_SERVER_API_ERROR_SERVER_ERROR;
     }
     ret = smack_have_access(subject, object, access_rights);
-    SEC_SVR_DBG("check by sockfd, subject >%s< object >%s< rights >%s< ====> %d",
-                subject, object, access_rights, ret);
+    SEC_SVR_DBG("SMACK have access returned %d", ret);
+    SEC_SVR_DBG("SS_SMACK: subject=%s, object=%s, access=%s, result=%d", subject, object, access_rights, ret);
+
     free(subject);
     if (ret == 1)
     {
@@ -1024,7 +1032,7 @@ SECURITY_SERVER_API
 char * security_server_get_smacklabel_cookie(const char * cookie)
 {
     char * label = NULL;
-    int sockfd = -1, retval, pid = -1;
+    int sockfd = -1, retval;
     response_header hdr;
 
     if(cookie == NULL)
@@ -1094,18 +1102,134 @@ error:
     return NULL;
 }
 
-       SECURITY_SERVER_API
+SECURITY_SERVER_API
 char * security_server_get_smacklabel_sockfd(int fd)
 {
-       char * label = NULL;
+    char * label = NULL;
 
-       if(smack_new_label_from_socket(fd, &label) != 0)
-       {
-               SEC_SVR_DBG("Client ERROR: Unable to get socket SMACK label");
-               return NULL;
-       }
+    if (!smack_check())
+    {
+        SEC_SVR_DBG("%s","No SMACK support on device");
+        label = (char*) malloc(1);
+        if (label) label[0] = '\0';
+        return label;
+    }
+
+    if (smack_new_label_from_socket(fd, &label) != 0)
+    {
+        SEC_SVR_DBG("Client ERROR: Unable to get socket SMACK label");
+        return NULL;
+    }
 
-       return label;
+    return label;
 }
 
+SECURITY_SERVER_API
+int security_server_app_give_access(const char *customer_label, int customer_pid)
+{
+    int sockfd = -1, retval;
+    response_header hdr;
+
+    retval = connect_to_server(&sockfd);
+    if(retval != SECURITY_SERVER_SUCCESS)
+    {
+        /* Error on socket */
+        goto out;
+    }
+
+    retval = send_app_give_access(sockfd, customer_label, customer_pid);
+    if(retval != SECURITY_SERVER_SUCCESS)
+    {
+        /* Error on socket */
+        SEC_SVR_DBG("Client: Send failed: %d", retval);
+        goto out;
+    }
+
+    retval = recv_generic_response(sockfd, &hdr);
+
+    retval = return_code_to_error_code(hdr.return_code);
+    if(hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE) {
+        SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+    } else if (hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_APP_GIVE_ACCESS_RESPONSE) {
+        SEC_SVR_DBG("Client: Wrong response type.");
+        retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+    }
+out:
+    if(sockfd > 0)
+        close(sockfd);
+
+    return convert_to_public_error_code(retval);
+}
+
+SECURITY_SERVER_API
+int security_server_check_privilege_by_pid(int pid, const char *object, const char *access_rights)
+{
+    //This function check SMACK privilege betwen subject and object.
+    //Subject is identified by PID number, object is function parameter.
+
+    int sockfd = -1;
+    int retval;
+    response_header hdr;
+
+    //check for input PID param
+    if (pid < 0) {
+        retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+        goto error;
+    }
+
+    SEC_SVR_DBG("%s","Check privilige by PID called");
+    SEC_SVR_DBG("%s %d","PID", pid);
+    SEC_SVR_DBG("%s %s", "OBJECT:", object);
+    SEC_SVR_DBG("%s %s", "ACCESS_RIGHTS", access_rights);
+
+    //check if able to connect
+    retval = connect_to_server(&sockfd);
+    if (retval != SECURITY_SERVER_SUCCESS)
+        goto error;
+
+    //send request
+    retval = send_pid_privilege_request(sockfd, pid, object, access_rights);
+    if (retval != SECURITY_SERVER_SUCCESS) {
+        /* Error on socket */
+        SEC_SVR_DBG("Client: Send failed: %d", retval);
+        goto error;
+    }
+
+    //get response
+    retval = recv_pid_privilege_response(sockfd, &hdr);
+
+    //convert error code
+    retval = return_code_to_error_code(hdr.return_code);
+
+    //check if frame has correct MSG_ID
+    if (hdr.basic_hdr.msg_id != SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_RESPONSE) {
+        if (hdr.basic_hdr.msg_id == SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE) {
+            /* There must be some error */
+            SEC_SVR_DBG("Client: Error has been received. return code:%d", hdr.return_code);
+        }
+        else {
+            /* Something wrong with response */
+            SEC_SVR_DBG("Client ERROR: Unexpected error occurred:%d", retval);
+            retval = SECURITY_SERVER_ERROR_BAD_RESPONSE;
+        }
+        goto error;
+    }
+
+    //debug info about checking result
+    
+    if (hdr.return_code == SECURITY_SERVER_RETURN_CODE_SUCCESS) {
+        SEC_SVR_DBG("%s","Client: There is privilege match");
+        retval = SECURITY_SERVER_SUCCESS;
+    } else {
+        SEC_SVR_DBG("%s","Client: There is no privilege match");
+        retval = SECURITY_SERVER_ERROR_ACCESS_DENIED;
+    }
+
+error:
+    if(sockfd > 0)
+        close(sockfd);
+
+    retval = convert_to_public_error_code(retval);
+    return retval;
+}
 
index 682fb0e..695c1e8 100644 (file)
@@ -22,6 +22,7 @@
 #include <sys/poll.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/smack.h>
@@ -228,27 +229,33 @@ int create_new_socket(int *sockfd)
                goto error;
        }
 
-       if(smack_fsetlabel(localsockfd, "@", SMACK_LABEL_IPOUT) != 0)
-       {
-               SEC_SVR_DBG("%s", "SMACK labeling failed");
-               if(errno != EOPNOTSUPP)
+       // If SMACK is present we have to label our sockets regardless of SMACK_ENABLED flag
+       if (smack_runtime_check()) {
+               if(smack_fsetlabel(localsockfd, "@", SMACK_LABEL_IPOUT) != 0)
                {
-                       retval = SECURITY_SERVER_ERROR_SOCKET;
-            close(localsockfd);
-                       localsockfd = -1;
-                       goto error;
+                       SEC_SVR_DBG("%s", "SMACK labeling failed");
+                       if(errno != EOPNOTSUPP)
+                       {
+                               retval = SECURITY_SERVER_ERROR_SOCKET;
+                               close(localsockfd);
+                               localsockfd = -1;
+                               goto error;
+                       }
                }
-       }
-       if(smack_fsetlabel(localsockfd, "*", SMACK_LABEL_IPIN) != 0)
-       {       SEC_SVR_DBG("%s", "SMACK labeling failed");
-               if(errno != EOPNOTSUPP)
-               {
-                       retval = SECURITY_SERVER_ERROR_SOCKET;
-            close(localsockfd);
-                       localsockfd = -1;
-                       goto error;
+               if(smack_fsetlabel(localsockfd, "*", SMACK_LABEL_IPIN) != 0)
+               {       SEC_SVR_DBG("%s", "SMACK labeling failed");
+                       if(errno != EOPNOTSUPP)
+                       {
+                               retval = SECURITY_SERVER_ERROR_SOCKET;
+                               close(localsockfd);
+                               localsockfd = -1;
+                               goto error;
+                       }
                }
        }
+       else {
+               SEC_SVR_DBG("SMACK is not available. Sockets won't be labeled.");
+       }
 
        /* Make socket as non blocking */
        if((flags = fcntl(localsockfd, F_GETFL, 0)) < 0 ||
@@ -1183,6 +1190,99 @@ int send_smack_request(int sock_fd, const char * cookie)
        return SECURITY_SERVER_SUCCESS;
 }
 
+//VERSION:      0x01
+//MSG_ID:       0x1f (SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_REQUEST)
+//DATA_SIZE:    strlen(object) + 1 + strlen(access_rights) + 1
+int send_pid_privilege_request(int sockfd, int pid, const char *object, const char *access_rights)
+{
+    //header structure
+    basic_header hdr;
+    int retval;
+    int message_size;
+    //buffer for data
+    char * buff = NULL;
+    int offset = 0;
+
+    if (pid < 0) {
+        SEC_SVR_DBG("%s", "Error input param");
+        retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+        goto error;
+    }
+
+    if (object == NULL) {
+        SEC_SVR_DBG("%s", "Error input param");
+        retval = SECURITY_SERVER_ERROR_INPUT_PARAM;
+        goto error;
+    }
+
+    //allocate buffer
+    //+1 for the '\0' at string end
+
+    message_size = sizeof(int) + strlen(object) + 1 + strlen(access_rights) + 1;
+    buff = (char *)malloc(message_size + sizeof(hdr));
+    if (buff == NULL) {
+        SEC_SVR_DBG("%s", "malloc() error");
+        retval = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+        goto error;
+    }
+
+    //clear buffer
+    bzero(buff, message_size + sizeof(hdr));
+
+    //create header
+    hdr.version = SECURITY_SERVER_MSG_VERSION;
+    //MSG_ID
+    hdr.msg_id = SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_REQUEST;
+    //set message size without header (data size)
+    hdr.msg_len = message_size;
+
+    //copy message fields to buffer
+    offset = 0;
+    memcpy(&buff[offset], &hdr, sizeof(hdr));
+    offset += sizeof(hdr);
+    //add PID
+    memcpy(&buff[offset], &pid, sizeof(pid));
+    offset += sizeof(pid);
+    //add *object with NULL at the end
+    memcpy(&buff[offset], object, strlen(object));
+    offset += strlen(object);
+    buff[offset] = 0;
+    offset += 1;
+    //add *access_rights with NULL at the end
+    memcpy(&buff[offset], access_rights, strlen(access_rights));
+    offset += strlen(access_rights);
+    buff[offset] = 0;
+
+    //check pool
+    retval = check_socket_poll(sockfd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+    if (retval == SECURITY_SERVER_ERROR_POLL) {
+        SEC_SVR_DBG("%s", "poll() error");
+        retval = SECURITY_SERVER_ERROR_SEND_FAILED;
+        goto error;
+
+    }
+    if (retval == SECURITY_SERVER_ERROR_TIMEOUT) {
+        SEC_SVR_DBG("%s", "poll() timeout");
+        retval = SECURITY_SERVER_ERROR_SEND_FAILED;
+        goto error;
+    }
+
+    //send message
+    retval = TEMP_FAILURE_RETRY(write(sockfd, buff, message_size + sizeof(hdr)));
+    if (retval < message_size) {
+        //error on write
+        SEC_SVR_DBG("Error on write(): %d", retval);
+        retval = SECURITY_SERVER_ERROR_SEND_FAILED;
+        goto error;
+    }
+    retval = SECURITY_SERVER_SUCCESS;
+error:
+    if (buff != NULL)
+        free(buff);
+
+    return retval;
+}
+
 /* Send PID check request message to security server *
  *
  * Message format
@@ -1980,6 +2080,61 @@ int recv_smack_request(int sockfd, unsigned char *requested_cookie)
        return SECURITY_SERVER_SUCCESS;
 }
 
+int recv_pid_privilege_request(int sockfd, int datasize, int * pid, char ** object, char ** access_rights)
+{
+    int retval;
+    char * buff = NULL;
+    int object_size = 0;
+    int access_rights_size = 0;
+
+    buff = (char *)malloc(datasize);
+    if (buff == NULL)
+        return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+
+    //receive all data to buffer
+    retval = TEMP_FAILURE_RETRY(read(sockfd, buff, datasize));
+       if (retval < datasize) {
+               SEC_SVR_DBG("Received data size is too small: %d / %d", retval, datasize);
+               retval =  SECURITY_SERVER_ERROR_RECV_FAILED;
+        goto error;
+       }
+
+    //getPID
+    memcpy(pid, buff, sizeof(int));
+
+    //get object
+    while (buff[sizeof(int) + object_size] != '\0') {
+        object_size++;
+
+        if (object_size > datasize) {
+            SEC_SVR_DBG("%s", "Wrong object_size");
+            retval = SECURITY_SERVER_ERROR_UNKNOWN;
+            goto error;
+        }
+    }
+    object_size++; //for '\0' at end
+
+    *object = (char *)malloc(object_size);
+    memcpy(*object, buff + sizeof(int), object_size);
+
+    //get access_rights
+    access_rights_size = datasize - sizeof(int) - object_size;
+    *access_rights = (char *)malloc(access_rights_size);
+    memcpy(*access_rights, buff + sizeof(int) + object_size, access_rights_size);
+
+    SEC_SVR_DBG("%s %d", "Received PID:", *pid);
+    SEC_SVR_DBG("%s %s", "Received object:", *object);
+    SEC_SVR_DBG("%s %s", "Received privileges:", *access_rights);
+
+    retval = SECURITY_SERVER_SUCCESS;
+
+error:
+    if (buff != NULL)
+        free(buff);
+
+       return retval;
+}
+
 /* Receive pid request packet body */
 /* Table argv and content will be freed by function caller */
 int recv_launch_tool_request(int sockfd, int argc, char *argv[])
@@ -2211,6 +2366,18 @@ int recv_smack_response(int sockfd, response_header *hdr, char * label)
        return SECURITY_SERVER_SUCCESS;
 }
 
+int recv_pid_privilege_response(int sockfd, response_header *hdr)
+{
+    int retval;
+
+    retval = recv_generic_response(sockfd, hdr);
+
+    if (retval != SECURITY_SERVER_SUCCESS)
+        return return_code_to_error_code(hdr->return_code);
+
+    return SECURITY_SERVER_SUCCESS;
+}
+
 int recv_pid_response(int sockfd, response_header *hdr, int *pid)
 {
        int retval;
@@ -2397,8 +2564,6 @@ int get_client_gid_list(int sockfd, int ** privileges)
     //for read socket options
     struct ucred socopt;
     unsigned int socoptSize = sizeof(socopt);
-    //privileges to be returned
-    int privilegesSize;
     //buffer for store /proc/<PID>/status filepath
     const int PATHSIZE = 24;
     char path[PATHSIZE];
@@ -2439,8 +2604,7 @@ int get_client_gid_list(int sockfd, int ** privileges)
     //search for line beginning with "Groups:"
     while(strncmp(fileLine, "Groups:", 7) != 0)
     {
-        ret = fgets(fileLine, LINESIZE, fp);
-        if(ret == NULL)
+        if(NULL == fgets(fileLine, LINESIZE, fp))
         {
             SEC_SVR_DBG("%s", "Error on fgets");
             fclose(fp);
@@ -2558,3 +2722,59 @@ int free_argv(char **argv, int argc)
        return SECURITY_SERVER_SUCCESS;
 }
 
+int send_app_give_access(int sock_fd, const char* customer_label, int customer_pid)
+{
+    basic_header hdr;
+    unsigned char *buff = NULL;
+    size_t total_len = 0;
+    size_t msg_len = 0;
+
+    msg_len = strlen(customer_label);
+    total_len = sizeof(hdr) + sizeof(int) + msg_len;
+
+    buff = malloc(total_len);
+    if (!buff) {
+        SEC_SVR_DBG("%s", "Error: failed on malloc()");
+        return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+    }
+
+    hdr.version = SECURITY_SERVER_MSG_VERSION;
+    hdr.msg_id = SECURITY_SERVER_MSG_TYPE_APP_GIVE_ACCESS_REQUEST;
+    hdr.msg_len = (unsigned short)total_len;
+
+    memcpy(buff, &hdr, sizeof(hdr));
+    memcpy(buff + sizeof(hdr), &customer_pid, sizeof(int));
+    memcpy(buff + sizeof(hdr) + sizeof(int), customer_label, msg_len);
+
+    /* Check poll */
+    int retval = check_socket_poll(sock_fd, POLLOUT, SECURITY_SERVER_SOCKET_TIMEOUT_MILISECOND);
+    if(retval == SECURITY_SERVER_ERROR_POLL)
+    {
+        SEC_SVR_DBG("%s", "poll() error");
+        retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+        goto error;
+    }
+
+    if(retval == SECURITY_SERVER_ERROR_TIMEOUT)
+    {
+        SEC_SVR_DBG("%s", "poll() timeout");
+        retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+        goto error;
+    }
+
+    /* Send to server */
+    retval = TEMP_FAILURE_RETRY(write(sock_fd, buff, total_len));
+    if(retval != (int)total_len)
+    {
+        /* Write error */
+        SEC_SVR_DBG("Error on write(): %d", retval);
+        retval =  SECURITY_SERVER_ERROR_SEND_FAILED;
+        goto error;
+    }
+    retval = SECURITY_SERVER_SUCCESS;
+
+error:
+    free(buff);
+    return retval;
+}
+
index 8f2de9a..e30303e 100644 (file)
@@ -69,6 +69,10 @@ typedef struct
 #define SECURITY_SERVER_MSG_TYPE_SET_PWD_VALIDITY_RESPONSE   0x1c
 #define SECURITY_SERVER_MSG_TYPE_SMACK_REQUEST         0x1d
 #define SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE        0x1e
+#define SECURITY_SERVER_MSG_TYPE_APP_GIVE_ACCESS_REQUEST 0x1f
+#define SECURITY_SERVER_MSG_TYPE_APP_GIVE_ACCESS_RESPONSE 0x20
+#define SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_REQUEST    0x21
+#define SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_RESPONSE   0x22
 #define SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE      0xff
 
 /* Return code */
@@ -122,13 +126,19 @@ int recv_check_privilege_new_request(int sockfd,
                                      char *object_label,
                                      char *access_rights);
 int send_pid_request(int sock_fd, const char*cookie);
-int recv_pid_response(int sockfd, response_header *hdr, int *pid);
 int recv_pid_request(int sockfd, unsigned char *requested_cookie);
 int send_pid(int sockfd, int pid);
+int recv_pid_response(int sockfd, response_header *hdr, int *pid);
+
 int send_smack_request(int sockfd, const char * cookie);
-int recv_smack_response(int sockfd, response_header *hdr, char * label);
 int recv_smack_request(int sockfd, unsigned char *requested_cookie);
 int send_smack(int sockfd, char * label);
+int recv_smack_response(int sockfd, response_header *hdr, char * label);
+
+int send_pid_privilege_request(int sockfd, int pid, const char *object, const char *access_rights);
+int recv_pid_privilege_request(int sockfd, int datasize, int * pid, char ** object, char ** access_rights);
+int recv_pid_privilege_response(int sockfdi, response_header *hdr);
+
 int send_launch_tool_request(int sock_fd, int argc, const char **argv);
 int recv_generic_response(int sockfd, response_header *hdr);
 int recv_launch_tool_request(int sockfd, int argc, char *argv[]);
@@ -141,5 +151,12 @@ int send_set_pwd_max_challenge_request(int sock_fd, const unsigned int max_chall
 int send_chk_pwd_request(int sock_fd, const char*challenge);
 int check_socket_poll(int sockfd, int event, int timeout);
 int free_argv(char **argv, int argc);
+int send_valid_pwd_request(int sock_fd);
+int send_reset_pwd_request(int sock_fd,
+                           const char*new_pwd,
+                           const unsigned int max_challenge,
+                           const unsigned int valid_period_in_days);
+int send_set_pwd_history_request(int sock_fd, int num);
+int send_app_give_access(int sock_df, const char *customer_label, int customer_pid);
 
 #endif
index 9350bba..afc7c24 100644 (file)
@@ -72,9 +72,8 @@
 #define SECURITY_SERVER_HISTORY_FILE_NAME      "history"
 #define SECURITY_SERVER_MAX_PASSWORD_LEN               32
 #define SECURITY_SERVER_HASHED_PWD_LEN                 32  /* SHA256 */
-#define SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_SECOND       1        /* Deprecated. Will be removed. */
+#define SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_SECOND          1        /* Deprecated. Will be removed. */
 #define SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_MICROSECOND  500000   /* = 500 milliseconds */
-
 #define SECURITY_SERVER_MAX_PASSWORD_HISTORY   50
 #define SECURITY_SERVER_NUM_THREADS                    10
 
diff --git a/src/include/security-server-rules-revoker.h b/src/include/security-server-rules-revoker.h
new file mode 100644 (file)
index 0000000..bafe25c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+#ifndef _SECURITY_SERVER_RULES_REVOKER_H_
+#define _SECURITY_SERVER_RULES_REVOKER_H_
+
+#include <linux/cn_proc.h>
+
+void rules_revoker_init(void);
+int rules_revoker_add(int pid, const char *subject, const char *object);
+void rules_revoker_callback(const struct proc_event *event);
+
+#endif // _SECURITY_SERVER_RULES_REVOKER_H_
+
diff --git a/src/include/security-server-system-observer.h b/src/include/security-server-system-observer.h
new file mode 100644 (file)
index 0000000..33ac12b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  security-server
+ *
+ *  Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+#ifndef _SECURITY_SERVER_SYSTEM_OBSERVER_H_
+#define _SECURITY_SERVER_SYSTEM_OBSERVER_H_
+
+#include <linux/cn_proc.h>
+
+typedef void (*system_observer_callback)(const struct proc_event *);
+
+typedef struct system_observer_config_t {
+    system_observer_callback event_callback;
+} system_observer_config;
+
+void* system_observer_main(void *data);
+
+#endif // _SECURITY_SERVER_SYSTEM_OBSERVER_H_
index b927c89..6e960ca 100644 (file)
@@ -1012,6 +1012,27 @@ char * security_server_get_smacklabel_cookie(const char *cookie);
  */
 char * security_server_get_smacklabel_sockfd(int fd);
 
+/*
+ * This function will give permissions "rwxat" from
+ * (subject) customer_label to caller process (object).
+ * Object label will be extracted from socket.
+ * */
+int security_server_app_give_access(const char* customer_label, int customer_pid);
+
+/*
+ * This function allows middleware to check priviliges of process with specified PID.
+ * Service is able to check proces acces to the specified object label with specified
+ * access rights.
+ * 
+ * \param[in] PID number of process to be checked
+ * \param[in] SMACK object label
+ * \param[in] SMACK access rights to be checked
+ *
+ * \return Privilege confirm or error code
+ * SECURITY_SERVER_SUCCESS - on succes
+ */
+int security_server_check_privilege_by_pid(int pid, const char *object, const char *access_rights);
+
 #ifdef __cplusplus
 }
 #endif
index bb6dedb..8540a6d 100644 (file)
 
 int smack_runtime_check(void);
 
+/*
+ * A very simple runtime check for SMACK on the platform
+ * Returns 1 if SMACK is present, 0 otherwise. If SMACK_ENABLED is not defined
+ * It returns 0.
+ */
+int smack_check(void);
+
 #endif // _SMACK_CHECK_H_
index 36344cc..48fbefc 100644 (file)
@@ -2,4 +2,3 @@
 
 # start secure-storage server
 /usr/bin/security-server &
-set_pmon -p security-server
index 25ce19d..fca106d 100644 (file)
@@ -74,7 +74,7 @@ cookie_list *delete_cookie_item(cookie_list *cookie)
        {
                cookie->prev->next = NULL;
        }
-       
+
        free_cookie_item(cookie);
        return retval;
 }
@@ -289,36 +289,41 @@ cookie_list *search_cookie_new(const cookie_list *c_list,
                                const char *object,
                                const char *access_rights)
 {
-       cookie_list *current = (cookie_list *)c_list, *retval = NULL;
-        int ret;
-       int i;
-
-       /* Search from the list */
-       while(current != NULL)
-       {
-               /* print_cookie(current);*/
-               /* PID must be same */
-               current = garbage_collection(current);
-               if(current == NULL)
-                       break;
-
-               if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
-               {
-                       SEC_SVR_DBG("%s", "cookie has been found");
+    cookie_list *current = (cookie_list *)c_list, *retval = NULL;
+    int ret;
+
+    /* Search from the list */
+    while(current != NULL)
+    {
+        /* print_cookie(current);*/
+        /* PID must be same */
+        current = garbage_collection(current);
+        if(current == NULL)
+            break;
+
+        if(memcmp(current->cookie, cookie, SECURITY_SERVER_COOKIE_LEN) == 0)
+        {
+            SEC_SVR_DBG("%s", "cookie has been found");
+            if (smack_check())
+            {
+                ret = smack_have_access(current->smack_label, object, access_rights);
+                SEC_SVR_DBG("SMACK have access returned %d", ret);
+                SEC_SVR_DBG("SS_SMACK: subject=%s, object=%s, access=%s, result=%d", current->smack_label, object, access_rights, ret);
 
-                                ret = smack_have_access(current->smack_label, object, access_rights);
-          SEC_SVR_DBG("smack_have_access, subject >%s< object >%s< access >%s< ===> %d",
-                    current->smack_label, object, access_rights, ret);
-                                if (ret == 1)
-                                {
-                                        retval = current;
-                                        goto finish;
-                                }
-               }
-               current = current->next;
-       }
+                if (ret == 1)
+                {
+                    retval = current;
+                    goto finish;
+                }
+            } else {
+                retval = current;
+                goto finish;
+            }
+        }
+        current = current->next;
+    }
 finish:
-       return retval;
+    return retval;
 }
 
 
@@ -355,179 +360,182 @@ error:
 /* Create a cookie item from PID */
 cookie_list *create_cookie_item(int pid, int sockfd, cookie_list *c_list)
 {
-       int ret, tempint;
-       cookie_list *added = NULL, *current = NULL;
-       char path[24], *exe = NULL;
-       char *buf = NULL, inputed, *tempptr = NULL;
-       char delim[] = ": ", *token = NULL;
-       int *permissions = NULL, perm_num = 1, cnt, i, *tempperm = NULL;
-        char *smack_label = NULL;
-       FILE *fp = NULL;
-
-       current = search_existing_cookie(pid, c_list);
-       if(current != NULL)
-       {
-               /* There is a cookie for this process already */
-               added = current;
-               SEC_SVR_DBG("%s", "Existing cookie found");
-               goto error;
-       }
+    int ret, tempint;
+    cookie_list *added = NULL, *current = NULL;
+    char path[24], *exe = NULL;
+    char *buf = NULL, inputed, *tempptr = NULL;
+    char delim[] = ": ", *token = NULL;
+    int *permissions = NULL, perm_num = 1, cnt, i, *tempperm = NULL;
+    char *smack_label = NULL;
+    FILE *fp = NULL;
+
+    current = search_existing_cookie(pid, c_list);
+    if(current != NULL)
+    {
+        /* There is a cookie for this process already */
+        added = current;
+        SEC_SVR_DBG("%s", "Existing cookie found");
+        goto error;
+    }
 
-       /* Read executable name of the PID from proc fs */
+    /* Read command line of the PID from proc fs */
     exe = (char *)read_exe_path_from_proc(pid);
-       if(exe == NULL)
-       {
-               SEC_SVR_DBG("Error on reading /proc/%d/exe", pid);
-               goto error;
-       }
-
-       /*
-        * modified by security part
-        *  - get gid from /etc/group
-        */
-       /* Read group info of the PID from proc fs - /proc/[PID]/status */
-       snprintf(path, sizeof(path), "/proc/%d/status", pid);
-       fp = fopen(path, "r");
-
-       /* Find the line which starts with 'Groups:' */
-       i = 0;
-       
-       while(1)
-       {
-               buf = (char*)malloc(sizeof(char) * 128);
-               if(buf == NULL)
-               {
-                       SEC_SVR_DBG("%s", "Error on malloc()");
-                       goto error;
-               }
-               memset(buf, 0x00, 128);
-               cnt = 128;
-
-               /* get one line from /proc/[PID]/status */
-               while(1)
-               {
-                       tempint = fgetc(fp);
-                       inputed = (char)tempint;
-                       if(tempint == EOF)
-                               goto out_of_while;
-                       else if(inputed == '\n')
-                       {
-                               buf[i] = '\0';
-                               break;
-                       }
-                       else if((i == cnt) && (inputed != '\n'))
-                       {
-                               tempptr = (char*)realloc(buf, sizeof(char) * (i + 128));
-                               if(tempptr == NULL)
-                               {
-                                       SEC_SVR_DBG("%s", "Error on realloc()");
-                                       goto error;
-                               }
-                               buf = tempptr;
-                               buf[i++] = inputed;
-                               cnt = i + 128;
-                       }
-                       else
-                               buf[i++] = inputed;
-               }
-               i = 0;
-
-               /* find 'Groups:' */
-               if(strncmp(buf, "Groups:", 7) == 0)
-               {
-                       /* get gid from the line and insert to 'permissions' array */
-                       token = strtok(buf, delim); // first string is "Groups"
-                       while((token = strtok(NULL, delim)))
-                       {
-                               tempperm = realloc(permissions, sizeof(int) * perm_num);
-                               if(tempperm == NULL)
-                               {
-                                       SEC_SVR_DBG("%s", "Error on realloc()");
-                                       goto error;
-                               }
-                               permissions = tempperm;
-                               errno = 0;
-                               permissions[perm_num - 1] = strtoul(token, 0, 10);
-                               if (errno != 0)
-                               {
-                                       SEC_SVR_DBG("cannot change string to integer [%s]", token);
-                                       ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
-                                       goto error;
-                               }
-                               perm_num++;
-                       }
-                       perm_num--;
+    if(exe == NULL)
+    {
+        SEC_SVR_DBG("Error on reading /proc/%d/exe", pid);
+        goto error;
+    }
 
-                       /* goto out of while loop */
-                       break;
-               }
-               if(buf != NULL)
-               {
-                       free(buf);
-                       buf = NULL;
-               }
-       }
+    /*
+     * modified by security part
+     *  - get gid from /etc/group
+     */
+    /* Read group info of the PID from proc fs - /proc/[PID]/status */
+    snprintf(path, sizeof(path), "/proc/%d/status", pid);
+    fp = fopen(path, "r");
+
+    /* Find the line which starts with 'Groups:' */
+    i = 0;
+
+    while(1)
+    {
+        buf = (char*)malloc(sizeof(char) * 128);
+        if(buf == NULL)
+        {
+            SEC_SVR_DBG("%s", "Error on malloc()");
+            goto error;
+        }
+        memset(buf, 0x00, 128);
+        cnt = 128;
+
+        /* get one line from /proc/[PID]/status */
+        while(1)
+        {
+            tempint = fgetc(fp);
+            inputed = (char)tempint;
+            if(tempint == EOF)
+                goto out_of_while;
+            else if(inputed == '\n')
+            {
+                buf[i] = '\0';
+                break;
+            }
+            else if((i == cnt) && (inputed != '\n'))
+            {
+                tempptr = (char*)realloc(buf, sizeof(char) * (i + 128));
+                if(tempptr == NULL)
+                {
+                    SEC_SVR_DBG("%s", "Error on realloc()");
+                    goto error;
+                }
+                buf = tempptr;
+                buf[i++] = inputed;
+                cnt = i + 128;
+            }
+            else
+                buf[i++] = inputed;
+        }
+        i = 0;
+
+        /* find 'Groups:' */
+        if(strncmp(buf, "Groups:", 7) == 0)
+        {
+            /* get gid from the line and insert to 'permissions' array */
+            token = strtok(buf, delim); // first string is "Groups"
+            while((token = strtok(NULL, delim)))
+            {
+                tempperm = realloc(permissions, sizeof(int) * perm_num);
+                if(tempperm == NULL)
+                {
+                    SEC_SVR_DBG("%s", "Error on realloc()");
+                    goto error;
+                }
+                permissions = tempperm;
+                errno = 0;
+                permissions[perm_num - 1] = strtoul(token, 0, 10);
+                if (errno != 0)
+                {
+                    SEC_SVR_DBG("cannot change string to integer [%s]", token);
+                    ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+                    goto error;
+                }
+                perm_num++;
+            }
+            perm_num--;
+
+            /* goto out of while loop */
+            break;
+        }
+        if(buf != NULL)
+        {
+            free(buf);
+            buf = NULL;
+        }
+    }
 out_of_while:
-               
-       /* Each group ID is stored in each line of the file */
-//     while(fgets(permline, sizeof(permline), fp) != NULL)
-//     {
-//             permissions = realloc(permissions, sizeof(int) * perm_num);
-//             if(permissions == NULL)
-//             {
-//                     SEC_SVR_DBG("%s", "Error on realloc()");
-//                     goto error;
-//             }
-//             permissions[perm_num -1] = strtoul(permline, 0, 10);
-//             perm_num++;
-//     }
-//     perm_num--;
-       /*
-        * modifying end
-        */
-
-       /* Go to last cookie from the list */
-       current = c_list;
-       while(current->next != NULL)
-       {
-               current = current->next;
-       }
 
-       /* Create a new one and assign values */
-       added = malloc(sizeof(cookie_list));
-       if(added == NULL)
-               goto error;
+    /* Each group ID is stored in each line of the file */
+    // while(fgets(permline, sizeof(permline), fp) != NULL)
+    // {
+    //         permissions = realloc(permissions, sizeof(int) * perm_num);
+    //         if(permissions == NULL)
+    //         {
+    //                 SEC_SVR_DBG("%s", "Error on realloc()");
+    //                 goto error;
+    //         }
+    //         permissions[perm_num -1] = strtoul(permline, 0, 10);
+    //         perm_num++;
+    // }
+    // perm_num--;
+    /*
+     * modifying end
+     */
+
+    /* Go to last cookie from the list */
+    current = c_list;
+    while(current->next != NULL)
+    {
+        current = current->next;
+    }
 
-       ret = generate_random_cookie(added->cookie, SECURITY_SERVER_COOKIE_LEN);
-       if(ret != SECURITY_SERVER_SUCCESS)
-       {
-               SEC_SVR_DBG("Error on making random cookie: %d", ret);
-               free(added);
-               added = NULL;
-               goto error;
-       }
+    /* Create a new one and assign values */
+    added = malloc(sizeof(cookie_list));
+    if(added == NULL)
+        goto error;
+
+    ret = generate_random_cookie(added->cookie, SECURITY_SERVER_COOKIE_LEN);
+    if(ret != SECURITY_SERVER_SUCCESS)
+    {
+        SEC_SVR_DBG("Error on making random cookie: %d", ret);
+        free(added);
+        added = NULL;
+        goto error;
+    }
 
-        /* Check SMACK label */
+    /* Check SMACK label */
+    if (smack_check())
+    {
         ret = smack_new_label_from_socket(sockfd, &smack_label);
         if (ret != 0)
-       {
-               SEC_SVR_DBG("Error checking peer label: %d", ret);
-               free(added);
-               added = NULL;
-               goto error;
-       }
+        {
+            SEC_SVR_DBG("Error checking peer label: %d", ret);
+            free(added);
+            added = NULL;
+            goto error;
+        }
+    }
 
        added->path_len = strlen(exe);
        added->path = calloc(1, strlen(exe));
        memcpy(added->path, exe, strlen(exe));
 
-       added->permission_len = perm_num;
-       added->pid = pid;
-       added->permissions = permissions;
-       added->smack_label = smack_label;
-       added->prev = current;
-       current->next = added;
-       added->next = NULL;
+    added->permission_len = perm_num;
+    added->pid = pid;
+    added->permissions = permissions;
+    added->smack_label = smack_label;
+    added->prev = current;
+    current->next = added;
+    added->next = NULL;
 
 error:
        if(exe != NULL)
@@ -537,10 +545,10 @@ error:
        if(buf != NULL)
                free(buf);
 
-       if(added == NULL && permissions != NULL)
-               free(permissions);
+    if(added == NULL && permissions != NULL)
+        free(permissions);
 
-       return added;
+    return added;
 }
 
 /* Check stored default cookie, if it's not exist make a new one and store it */
index cd44fa9..5235d3c 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/smack.h>
 #include <errno.h>
 #include <signal.h>
 #include <pthread.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
+#include <poll.h>
+
+#include <privilege-control.h>
+#include <security-server-system-observer.h>
+#include <security-server-rules-revoker.h>
 
 #include "security-server-cookie.h"
 #include "security-server-common.h"
 #include "security-server-password.h"
 #include "security-server-comm.h"
+#include "smack-check.h"
+
+const char * const LABEL_SECURITY_SERVER_API_DATA_SHARE = "security-server::api-data-share";
 
 /* Set cookie as a global variable */
 cookie_list *c_list;
@@ -50,6 +59,10 @@ struct security_server_thread_param {
        int thread_status;
 };
 
+int process_app_get_access_request(int sockfd, size_t msg_len);
+static int netlink_enabled = 1; /* prevent memory leaks when netlink is disabled */
+
+
 /************************************************************************************************/
 /* Just for test. This code must be removed on release */
 #include "security-server-util.h"
@@ -482,7 +495,7 @@ error:
 int process_check_privilege_new_request(int sockfd)
 {
        /* Authenticate client */
-       int retval, client_pid, requested_privilege;
+       int retval, client_pid;
        unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
        cookie_list *search_result = NULL;
         char object_label[MAX_OBJECT_LABEL_LEN+1];
@@ -806,33 +819,29 @@ int process_smack_request(int sockfd)
     cookie_list *search_result = NULL;
     //handler for SMACK label
     char * label = NULL;
-    //buffer for storing file path
-    const int BUFFSIZE = 30;
-    char path[BUFFSIZE];
-    int fd;
 
-       /* Authenticate client */
-       retval = authenticate_client_middleware(sockfd, &client_pid);
-       if(retval != SECURITY_SERVER_SUCCESS)
-       {
-               SEC_SVR_DBG("%s", "Client Authentication Failed");
-               retval = send_generic_response(sockfd,
-                               SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
-                               SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
-               if(retval != SECURITY_SERVER_SUCCESS)
-               {
-                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
-               }
-               goto error;
-       }
+    /* Authenticate client */
+    retval = authenticate_client_middleware(sockfd, &client_pid);
+    if(retval != SECURITY_SERVER_SUCCESS)
+    {
+        SEC_SVR_DBG("%s", "Client Authentication Failed");
+        retval = send_generic_response(sockfd,
+          SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
+          SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+        if(retval != SECURITY_SERVER_SUCCESS)
+        {
+            SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+        }
+        goto error;
+    }
 
     retval = recv_smack_request(sockfd, requested_cookie);
     if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
     {
         SEC_SVR_DBG("%s", "Receiving request failed");
         retval = send_generic_response(sockfd,
-            SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
-            SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+          SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
+          SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
         if(retval != SECURITY_SERVER_SUCCESS)
         {
             SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
@@ -860,67 +869,137 @@ int process_smack_request(int sockfd)
         SEC_SVR_DBG("We found the cookie and pid:%d", search_result->pid);
         SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
 
-        //clearing buffer
-        memset(path, 0x00, BUFFSIZE);
-
-        //preparing file path
-        snprintf(path, BUFFSIZE, "/proc/%d/attr/current", search_result->pid);
-        SEC_SVR_DBG("Path to file: %s\n", path);
+        label = search_result->smack_label;
 
-        //allocation place for label
-        label = calloc(SMACK_LABEL_LEN, 1);
-        if(NULL == label)
+        if (NULL == label)
         {
-            SEC_SVR_DBG("Client ERROR: Memory allocation error");
-            goto error;
+            SEC_SVR_DBG("%s", "No SMACK support on device - returning empty label");
+            label = "";
         }
 
-        //clearing buffer for label
-        memset(label, 0x00, SMACK_LABEL_LEN);
+        SEC_SVR_DBG("Read label is: %s\n", label);
+
+        retval = send_smack(sockfd, label);
 
-        //opening file /proc/<pid>/attr/curent with SMACK label
-        fd = open(path, O_RDONLY);
-        if(fd < 0)
+        if(retval != SECURITY_SERVER_SUCCESS)
         {
-            SEC_SVR_DBG("Client ERROR: Unable to open file in /proc");
+            SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+        }
+    }
+    else
+    {
+        /* It's not exist */
+        SEC_SVR_DBG("%s", "Could not find the cookie");
+        retval = send_generic_response(sockfd,
+          SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
+          SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
+        if(retval != SECURITY_SERVER_SUCCESS)
+        {
+            SEC_SVR_DBG("ERROR: Cannot send SMACK label response: %d", retval);
+        }
+    }
+error:
+    return retval;
+}
+
+int process_pid_privilege_check(int sockfd, int datasize)
+{
+    //In this function we parsing received PID privilege check request
+    int retval;
+    int client_pid;
+    int pid;
+    char * object = NULL;
+    char * access_rights = NULL;
+    unsigned char return_code;
+    //file descriptor
+    int fd = -1;
+    const int B_SIZE = 64;
+    char buff[B_SIZE];
+
+    //authenticate client
+    retval = authenticate_client_middleware(sockfd, &client_pid);
+
+    if (retval != SECURITY_SERVER_SUCCESS) {
+        SEC_SVR_DBG("%s", "Client Authentication Failed");
+        retval = send_generic_response(sockfd,
+            SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_RESPONSE,
+            SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
+
+        if (retval != SECURITY_SERVER_SUCCESS)
+            SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+
+        goto error;
+    }
+
+    //receive request
+    retval = recv_pid_privilege_request(sockfd, datasize, &pid, &object, &access_rights);
+
+    if (retval == SECURITY_SERVER_ERROR_RECV_FAILED) {
+        SEC_SVR_DBG("%s", "Receiving request failed");
+        retval = send_generic_response(sockfd,
+            SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_RESPONSE,
+            SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
+
+        if (retval != SECURITY_SERVER_SUCCESS)
+            SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
+
+        goto error;
+    }
+
+    bzero(buff, B_SIZE);
+    if (smack_check()) {
+        //get SMACK label of process
+        snprintf(buff, B_SIZE, "/proc/%d/attr/current", pid);
+
+        fd = open(buff, O_RDONLY, 0644);
+        if (fd < 0) {
+            SEC_SVR_DBG("%s", "Error open()");
+            retval = SECURITY_SERVER_ERROR_UNKNOWN;
             goto error;
         }
 
-        //reading label from file, it is NOT NULL TERMINATED
-        retval = read(fd, label, SMACK_LABEL_LEN);
-        close(fd);
-        if(retval < 0)
-        {
-            SEC_SVR_DBG("Client ERROR: Unable to read from file");
+        bzero(buff, B_SIZE);
+        retval = read(fd, buff, B_SIZE);
+        if (retval < 0) {
+            SEC_SVR_DBG("%s", "Error read()");
+            retval = SECURITY_SERVER_ERROR_UNKNOWN;
             goto error;
         }
 
-        SEC_SVR_DBG("Readed label is: %s\n", label);
+        //now we have SMACK label in buff and we call libsmack
+        SEC_SVR_DBG("Subject label of client PID %d is: %s", pid, buff);
+        retval = smack_have_access(buff, object, access_rights);
+        SEC_SVR_DBG("SMACK have access returned %d", retval);
+    } else {
+        SEC_SVR_DBG("SMACK is not available. Subject label has not been read.");
+        retval = 1;
+    }
 
-               retval = send_smack(sockfd, label);
+    SEC_SVR_DBG("SS_SMACK: caller_pid=%d, subject=%s, object=%s, access=%s, result=%d", pid, buff, object, access_rights, retval);
+
+    if (retval == 1)   //there is permission
+        return_code = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+    else                //there is no permission
+        return_code = SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED;
+
+    //send response
+    retval = send_generic_response(sockfd,
+            SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_RESPONSE,
+            return_code);
+
+    if (retval != SECURITY_SERVER_SUCCESS)
+        SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
 
-               if(retval != SECURITY_SERVER_SUCCESS)
-               {
-                       SEC_SVR_DBG("ERROR: Cannot send generic response: %d", retval);
-               }
-       }
-       else
-       {
-               /* It's not exist */
-               SEC_SVR_DBG("%s", "Could not find the cookie");
-               retval = send_generic_response(sockfd,
-                               SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
-                               SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
-               if(retval != SECURITY_SERVER_SUCCESS)
-               {
-                       SEC_SVR_DBG("ERROR: Cannot send SMACK label response: %d", retval);
-               }
-       }
 error:
-    if(NULL != label)
-        free(label);
+    if (fd >= 0)
+        close(fd);
 
-       return retval;
+    if (object != NULL)
+        free(object);
+    if (access_rights != NULL)
+        free(access_rights);
+
+    return retval; 
 }
 
 int process_tool_request(int client_sockfd, int server_sockfd)
@@ -1027,10 +1106,27 @@ error:
     return retval;
 }
 
+int client_has_access(int sockfd, const char *object) {
+    char *label = NULL;
+    int ret = 0;
+
+    if (smack_check())
+    {
+
+        if(smack_new_label_from_socket(sockfd, &label))
+            return 0;
+
+        if (0 >= (ret = smack_have_access(label, object, "rw")))
+            ret = 0;
+    }
+    free(label);
+    return ret;
+}
+
 void *security_server_thread(void *param)
 {
        int client_sockfd = -1, client_uid, client_pid;
-       int server_sockfd, retval, argcnum;
+       int server_sockfd, retval;
        basic_header basic_hdr;
        struct security_server_thread_param *my_param;
 
@@ -1104,6 +1200,12 @@ void *security_server_thread(void *param)
                        process_smack_request(client_sockfd);
                        break;
 
+        case SECURITY_SERVER_MSG_TYPE_CHECK_PID_PRIVILEGE_REQUEST:
+                       SEC_SVR_DBG("%s", "PID privilege check request received");
+            //pass data size to function
+                       process_pid_privilege_check(client_sockfd, basic_hdr.msg_len);
+                       break;
+
                case SECURITY_SERVER_MSG_TYPE_TOOL_REQUEST:
                        SEC_SVR_DBG("%s", "launch tool request received");
                        process_tool_request(client_sockfd, server_sockfd);
@@ -1144,6 +1246,18 @@ void *security_server_thread(void *param)
             process_set_pwd_validity_request(client_sockfd);
             break;
 
+        case SECURITY_SERVER_MSG_TYPE_APP_GIVE_ACCESS_REQUEST:
+            if (client_has_access(client_sockfd, LABEL_SECURITY_SERVER_API_DATA_SHARE)) {
+                SEC_SVR_DBG("%s", "Server: app give access request received");
+                process_app_get_access_request(client_sockfd,
+                    basic_hdr.msg_len - sizeof(basic_hdr));
+            } else {
+                SEC_SVR_DBG("%s", "Server: app give access request received (API DENIED - request will not proceed)");
+                send_generic_response(client_sockfd,
+                    SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
+                    SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED);
+            }
+            break;
 /************************************************************************************************/
 /* Just for test. This code must be removed on release */
                case SECURITY_SERVER_MSG_TYPE_GET_ALL_COOKIES_REQUEST:
@@ -1331,6 +1445,97 @@ error:
     pthread_exit(NULL);
 }
 
+ssize_t read_wrapper(int sockfd, void *buffer, size_t len) {
+    unsigned char *buff = (unsigned char *)buffer;
+    ssize_t done = 0;
+    while(done < (int)len) {
+        struct pollfd fds = { sockfd, POLLIN, 0};
+        if (0 >= poll(&fds, 1, 1000))
+            break;
+        ssize_t ret = read(sockfd, buff+done, len-done);
+        if (0 < ret) {
+            done += ret;
+            continue;
+        }
+        if (0 == ret)
+            break;
+        if (-1 == ret && EAGAIN != errno && EINTR != errno)
+            break;
+    }
+    return done;
+}
+
+int process_app_get_access_request(int sockfd, size_t msg_len)
+{
+    char *message_buffer = NULL;
+    char *client_label = NULL;
+    char *provider_label = NULL;
+    int ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
+    int send_message_id = SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE;
+    int send_error_id = SECURITY_SERVER_RETURN_CODE_SERVER_ERROR;
+    int client_pid = 0;
+
+    message_buffer = malloc(msg_len+1);
+    if (!message_buffer)
+        return SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
+    message_buffer[msg_len] = 0;
+
+    ssize_t retval = read_wrapper(sockfd, message_buffer, msg_len);
+
+    if (retval < (ssize_t)msg_len) {
+        SEC_SVR_DBG("%s", "Error in read. Message too short");
+        send_error_id = SECURITY_SERVER_RETURN_CODE_BAD_REQUEST;
+        ret = SECURITY_SERVER_ERROR_BAD_REQUEST;
+        goto error;
+    }
+
+    memcpy(&client_pid, message_buffer, sizeof(int));
+    client_label = message_buffer + sizeof(int);
+
+    if (smack_check()) {
+        if (0 != smack_new_label_from_socket(sockfd, &provider_label)) {
+            SEC_SVR_DBG("%s", "Error in smack_new_label_from_socket");
+            goto error;
+        }
+
+        if (PC_OPERATION_SUCCESS != app_give_access(client_label, provider_label, "rwxat")) {
+            SEC_SVR_DBG("%s", "Error in app_give_access");
+            goto error;
+        }
+    }
+
+    ret = SECURITY_SERVER_SUCCESS;
+    send_message_id = SECURITY_SERVER_MSG_TYPE_APP_GIVE_ACCESS_RESPONSE;
+    send_error_id = SECURITY_SERVER_RETURN_CODE_SUCCESS;
+
+    if (!netlink_enabled) {
+        SEC_SVR_DBG("Netlink not supported: Garbage collector inactive.");
+        goto error;
+    }
+
+    if (smack_check()) {
+        if (0 != rules_revoker_add(client_pid, client_label, provider_label))
+            SEC_SVR_DBG("%s", "Error in rules_revoker_add.");
+    }
+
+error:
+    retval = send_generic_response(sockfd, send_message_id, send_error_id);
+    if(retval != SECURITY_SERVER_SUCCESS)
+        SEC_SVR_DBG("Server ERROR: Cannot send response: %d", retval);
+
+    free(message_buffer);
+    free(provider_label);
+    return ret;
+}
+
+void *system_observer_main_thread(void *data) {
+    system_observer_main(data);
+    SEC_SVR_DBG("%s", "System observer: exit. No garbage collector support.");
+    netlink_enabled = 0;
+    pthread_detach(pthread_self());
+    pthread_exit(NULL);
+}
+
 int main(int argc, char* argv[])
 {
     int res;
@@ -1339,6 +1544,21 @@ int main(int argc, char* argv[])
     (void)argc;
     (void)argv;
 
+    // create observer thread only if smack is enabled
+    if (smack_check()) {
+        pthread_t system_observer;
+        system_observer_config so_config;
+        so_config.event_callback = rules_revoker_callback;
+
+        res = pthread_create(&system_observer, NULL, system_observer_main_thread, (void*)&so_config);
+
+        if (res != 0)
+            return -1;
+    }
+    else {
+        SEC_SVR_DBG("SMACK is not available. Observer thread disabled.");
+    }
+
     res = pthread_create(&main_thread, NULL, security_server_main_thread, NULL);
     if (res == 0)
     {
index c2fb0b8..df0f1e5 100644 (file)
@@ -30,7 +30,6 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <openssl/sha.h>
-#include <unistd.h>
 
 #include "security-server-password.h"
 
@@ -428,7 +427,6 @@ int check_history(const unsigned char *requested_pwd)
 {
        unsigned char history_pwd[SECURITY_SERVER_HASHED_PWD_LEN];
        char path[255];
-       unsigned int max_history;
        int num, history_count, fd, file_count, retval;
        int retval2 = SECURITY_SERVER_SUCCESS;
        struct dirent **mydirent;
@@ -572,12 +570,12 @@ int set_password(const unsigned char *requested_new_pwd, const unsigned int atte
 
 int check_retry(const struct timeval cur_try)
 {
-       int retval, interval_sec, interval_usec;
+       int interval_sec, interval_usec;
        interval_sec = cur_try.tv_sec - prev_try.tv_sec;
        interval_usec = cur_try.tv_usec - prev_try.tv_usec;
        prev_try = cur_try;
        if(interval_sec == 0
-               && interval_usec > SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_MICROSECOND)
+               && interval_usec > SECURITY_SERVER_PASSWORD_RETRY_TIMEOUT_MICROSECOND)
                return SECURITY_SERVER_SUCCESS;
 
        if(interval_sec > 0)
@@ -1580,3 +1578,4 @@ int process_set_pwd_validity_request(int sockfd)
 error:
     return retval;
 }
+
diff --git a/src/server/security-server-rules-revoker.c b/src/server/security-server-rules-revoker.c
new file mode 100644 (file)
index 0000000..aea19d1
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * security-server
+ *
+ *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+#include <pthread.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <privilege-control.h>
+
+#include <security-server-rules-revoker.h>
+
+static pthread_mutex_t tree_mutex;
+static void *tree_root = NULL;
+
+typedef struct tree_info_t {
+    int pid;
+    char *subject;
+    char *object;
+} tree_info;
+
+static int tree_cmp(const void *first, const void *second) {
+    return (((tree_info*)first)->pid) - (((tree_info*)second)->pid);
+}
+
+static int tree_info_push(tree_info *node) {
+    int ret = 0;
+    pthread_mutex_lock(&tree_mutex);
+
+    if (NULL != tfind(node, &tree_root, tree_cmp)) {
+        ret = -1;
+        goto end;
+    }
+
+    tsearch(node, &tree_root, tree_cmp);
+end:
+    pthread_mutex_unlock(&tree_mutex);
+    return ret;
+}
+
+
+static int tree_info_add(int pid, const char *subject_param, const char *object_param) {
+    tree_info *node = malloc(sizeof(tree_info));
+    char *subject = strdup(subject_param);
+    char *object = strdup(object_param);
+
+    if (!node || !subject || !object)
+        goto error;
+
+    node->pid = pid;
+    node->subject = subject;
+    node->object = object;
+
+    if (0 == tree_info_push(node))
+        return 0;
+
+error:
+    free(node);
+    free(subject);
+    free(object);
+    return -1;
+}
+
+static tree_info* tree_info_pop_new(int pid) {
+    tree_info search, *node = NULL;
+    void *wtf;
+    search.pid = pid;
+
+    pthread_mutex_lock(&tree_mutex);
+
+    wtf = tfind(&search, &tree_root, tree_cmp);
+    if (!wtf)
+        goto end;
+
+    node = *(tree_info**)wtf;
+    if (!node)
+        goto end;
+
+    tdelete(node, &tree_root, tree_cmp);
+end:
+    pthread_mutex_unlock(&tree_mutex);
+    return node;
+}
+
+static int rules_revoker_pid(int pid) {
+    tree_info *node = NULL;
+    int ret = 0;
+
+    node = tree_info_pop_new(pid);
+    if (!node)
+        return 0;
+
+    if (PC_OPERATION_SUCCESS != app_revoke_access(node->subject, node->object))
+        ret = -1;
+
+    free(node->subject);
+    free(node->object);
+    free(node);
+    return ret;
+}
+
+void rules_revoker_init(void) {
+   pthread_mutex_init(&tree_mutex, NULL);
+}
+
+int rules_revoker_add(int pid, const char *subject, const char *object) {
+    return tree_info_add(pid, subject, object);
+}
+
+void rules_revoker_callback(const struct proc_event *event) {
+    if (PROC_EVENT_EXIT != event->what)
+        return;
+    rules_revoker_pid(event->event_data.exit.process_pid);
+}
+
diff --git a/src/server/security-server-system-observer.c b/src/server/security-server-system-observer.c
new file mode 100644 (file)
index 0000000..e8c641c
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * security-server
+ *
+ *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ *
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/connector.h>
+#include <linux/cn_proc.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <security-server-common.h>
+#include <security-server-system-observer.h>
+
+#define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
+                     sizeof(int))
+
+static int nl_sock;
+
+int connect_to_netlink()
+{
+    struct sockaddr_nl sa_nl; /* netlink interface info */
+    char buff[NL_MESSAGE_SIZE];
+    struct nlmsghdr *hdr; /* for telling netlink what we want */
+    struct cn_msg *msg;   /* the actual connector message */
+
+    /* connect to netlink socket */
+    nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+
+    if (-1 == nl_sock) {
+        SEC_SVR_DBG("socket failed: %s", strerror(errno));
+        return SECURITY_SERVER_ERROR_SOCKET;
+    }
+
+    bzero(&sa_nl, sizeof(sa_nl));
+    sa_nl.nl_family = AF_NETLINK;
+    sa_nl.nl_groups = CN_IDX_PROC;
+    sa_nl.nl_pid    = getpid();
+
+    if (-1 == bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl))) {
+        SEC_SVR_DBG("bind failed: %s", strerror(errno));
+        close(nl_sock);
+        return SECURITY_SERVER_ERROR_SOCKET;
+    }
+
+    /* Fill header */
+    hdr = (struct nlmsghdr *)buff;
+    hdr->nlmsg_len = NL_MESSAGE_SIZE;
+    hdr->nlmsg_type = NLMSG_DONE;
+    hdr->nlmsg_flags = 0;
+    hdr->nlmsg_seq = 0;
+    hdr->nlmsg_pid = getpid();
+
+    /* Fill message */
+    msg = (struct cn_msg *)NLMSG_DATA(hdr);
+    msg->id.idx = CN_IDX_PROC;  /* Connecting to process information */
+    msg->id.val = CN_VAL_PROC;
+    msg->seq = 0;
+    msg->ack = 0;
+    msg->flags = 0;
+    msg->len = sizeof(int);
+    *(int*)msg->data = PROC_CN_MCAST_LISTEN;
+
+    if (-1 == send(nl_sock, hdr, hdr->nlmsg_len, 0)) {
+        SEC_SVR_DBG("send failed: %s", strerror(errno));
+        close(nl_sock);
+        return SECURITY_SERVER_ERROR_SOCKET;
+    }
+
+    return SECURITY_SERVER_SUCCESS;
+}
+
+void handle_events(system_observer_config *data)
+{
+    char buff[CONNECTOR_MAX_MSG_SIZE];
+    struct nlmsghdr *hdr;
+    struct proc_event *event;
+
+    fd_set fds;
+
+    while (1) {
+        FD_ZERO(&fds);
+        FD_SET(nl_sock, &fds);
+
+        if (0 > select(nl_sock + 1, &fds, NULL, NULL, NULL)) {
+            SEC_SVR_DBG("select failed: %s", strerror(errno));
+            return ;
+        }
+
+        /* If there were no events detected, return */
+        if (! FD_ISSET(nl_sock, &fds)) {
+            return ;
+        }
+
+        /* if there are events, make calls */
+        if (-1 == recv(nl_sock, buff, sizeof(buff), 0)) {
+            SEC_SVR_DBG("recv failed: %s", strerror(errno));
+            return ;
+        }
+
+        hdr = (struct nlmsghdr *)buff;
+
+        if (NLMSG_ERROR == hdr->nlmsg_type) {
+            SEC_SVR_DBG("%s", "NLMSG_ERROR");
+        } else if (NLMSG_DONE == hdr->nlmsg_type) {
+            event = (struct proc_event *)((struct cn_msg *)NLMSG_DATA(hdr))->data;
+            if (data->event_callback)
+                (data->event_callback)(event);
+        }
+    }
+}
+
+void* system_observer_main(void *data) {
+    if (SECURITY_SERVER_SUCCESS == connect_to_netlink()) {
+        handle_events((system_observer_config *)data);
+        close(nl_sock);
+    }
+    return NULL;
+}
+
index 1794b29..61aaf41 100644 (file)
@@ -23,3 +23,12 @@ int smack_runtime_check(void)
     return smack_present;
 }
 
+int smack_check(void)
+{
+#ifndef SMACK_ENABLED
+    return 0;
+#else
+    return smack_runtime_check();
+#endif
+
+}