From 70a84df4cc493afe93f5434877b0e66d1d3d0036 Mon Sep 17 00:00:00 2001 From: Kidong Kim Date: Fri, 10 May 2013 17:59:48 +0900 Subject: [PATCH] merge back from tizen_2.1_smack --- CMakeLists.txt | 1 + packaging/security-server.spec | 2 + src/CMakeLists.txt | 5 + src/client/security-server-client.c | 148 +++++++++- src/communication/security-server-comm.c | 262 +++++++++++++++-- src/include/security-server-comm.h | 21 +- src/include/security-server-common.h | 3 +- src/include/security-server-rules-revoker.h | 31 ++ src/include/security-server-system-observer.h | 34 +++ src/include/security-server.h | 21 ++ src/include/smack-check.h | 7 + src/security-serverd | 1 - src/server/security-server-cookie.c | 390 +++++++++++++------------- src/server/security-server-main.c | 354 ++++++++++++++++++----- src/server/security-server-password.c | 7 +- src/server/security-server-rules-revoker.c | 132 +++++++++ src/server/security-server-system-observer.c | 141 ++++++++++ src/util/smack-check.c | 9 + 18 files changed, 1269 insertions(+), 300 deletions(-) create mode 100644 src/include/security-server-rules-revoker.h create mode 100644 src/include/security-server-system-observer.h create mode 100644 src/server/security-server-rules-revoker.c create mode 100644 src/server/security-server-system-observer.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 740aa89..c970c45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/packaging/security-server.spec b/packaging/security-server.spec index c1d8d56..df34f09 100644 --- a/packaging/security-server.spec +++ b/packaging/security-server.spec @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 15466cc..258ea12 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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}) diff --git a/src/client/security-server-client.c b/src/client/security-server-client.c index 68e83a0..6550946 100644 --- a/src/client/security-server-client.c +++ b/src/client/security-server-client.c @@ -29,6 +29,7 @@ #include #include +#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; +} diff --git a/src/communication/security-server-comm.c b/src/communication/security-server-comm.c index 682fb0e..695c1e8 100644 --- a/src/communication/security-server-comm.c +++ b/src/communication/security-server-comm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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//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; +} + diff --git a/src/include/security-server-comm.h b/src/include/security-server-comm.h index 8f2de9a..e30303e 100644 --- a/src/include/security-server-comm.h +++ b/src/include/security-server-comm.h @@ -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 diff --git a/src/include/security-server-common.h b/src/include/security-server-common.h index 9350bba..afc7c24 100644 --- a/src/include/security-server-common.h +++ b/src/include/security-server-common.h @@ -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 index 0000000..bafe25c --- /dev/null +++ b/src/include/security-server-rules-revoker.h @@ -0,0 +1,31 @@ +/* + * security-server + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bumjin Im + * + * 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 + +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 index 0000000..33ac12b --- /dev/null +++ b/src/include/security-server-system-observer.h @@ -0,0 +1,34 @@ +/* + * security-server + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bumjin Im + * + * 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 + +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_ diff --git a/src/include/security-server.h b/src/include/security-server.h index b927c89..6e960ca 100644 --- a/src/include/security-server.h +++ b/src/include/security-server.h @@ -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 diff --git a/src/include/smack-check.h b/src/include/smack-check.h index bb6dedb..8540a6d 100644 --- a/src/include/smack-check.h +++ b/src/include/smack-check.h @@ -28,4 +28,11 @@ 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_ diff --git a/src/security-serverd b/src/security-serverd index 36344cc..48fbefc 100644 --- a/src/security-serverd +++ b/src/security-serverd @@ -2,4 +2,3 @@ # start secure-storage server /usr/bin/security-server & -set_pmon -p security-server diff --git a/src/server/security-server-cookie.c b/src/server/security-server-cookie.c index 25ce19d..fca106d 100644 --- a/src/server/security-server-cookie.c +++ b/src/server/security-server-cookie.c @@ -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 */ diff --git a/src/server/security-server-main.c b/src/server/security-server-main.c index cd44fa9..5235d3c 100644 --- a/src/server/security-server-main.c +++ b/src/server/security-server-main.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -34,11 +35,19 @@ #include #include #include +#include + +#include +#include +#include #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//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) { diff --git a/src/server/security-server-password.c b/src/server/security-server-password.c index c2fb0b8..df0f1e5 100644 --- a/src/server/security-server-password.c +++ b/src/server/security-server-password.c @@ -30,7 +30,6 @@ #include #include #include -#include #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 index 0000000..aea19d1 --- /dev/null +++ b/src/server/security-server-rules-revoker.c @@ -0,0 +1,132 @@ +/* + * security-server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bumjin Im + * + * 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 +#include +#include +#include + +#include + +#include + +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 index 0000000..e8c641c --- /dev/null +++ b/src/server/security-server-system-observer.c @@ -0,0 +1,141 @@ +/* + * security-server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Bumjin Im + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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; +} + diff --git a/src/util/smack-check.c b/src/util/smack-check.c index 1794b29..61aaf41 100644 --- a/src/util/smack-check.c +++ b/src/util/smack-check.c @@ -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 + +} -- 2.7.4