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")
Requires(preun): systemd
Requires(post): systemd
Requires(postun): systemd
+BuildRequires: pkgconfig(libprivilege-control)
+
%description
Security server and utilities
dlog
openssl
libsmack
+ libprivilege-control
REQUIRED
)
${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(
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})
#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"
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;
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);
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)
{
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)
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;
+}
#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>
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 ||
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
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[])
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;
//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];
//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);
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;
+}
+
#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 */
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[]);
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
#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
--- /dev/null
+/*
+ * 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_
+
--- /dev/null
+/*
+ * 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_
*/
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
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_
# start secure-storage server
/usr/bin/security-server &
-set_pmon -p security-server
{
cookie->prev->next = NULL;
}
-
+
free_cookie_item(cookie);
return retval;
}
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;
}
/* 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)
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 */
#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;
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"
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];
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);
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)
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;
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);
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:
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;
(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)
{
#include <unistd.h>
#include <fcntl.h>
#include <openssl/sha.h>
-#include <unistd.h>
#include "security-server-password.h"
{
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;
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)
error:
return retval;
}
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
return smack_present;
}
+int smack_check(void)
+{
+#ifndef SMACK_ENABLED
+ return 0;
+#else
+ return smack_runtime_check();
+#endif
+
+}