<commit_before>/*
 * security-server
 *
 *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Contact: <NAME> <<EMAIL>>
 *
 *  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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/smack.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/smack.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;
pthread_mutex_t cookie_mutex;
int thread_status[SECURITY_SERVER_NUM_THREADS];
struct security_server_thread_param {
	int client_sockfd;
	int server_sockfd;
	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"
/************************************************************************************************/

#if 0
void printhex(unsigned char *data, int size)
{
	int i;
	for(i=0;i<size;i++)
	{
		if(data[i] < 0xF)
			printf("0");

		printf("%X ", data[i]);
		if(((i+1) % 16) == 0 && i != 0)
			printf("\n");
	}
	printf("\n");
}

void print_cookie(cookie_list *list)
{
	int i;
	printf("%s", "cookie:\n");
	printhex(list->cookie, SECURITY_SERVER_COOKIE_LEN);
	printf("path_len: %d\n", list->path ? strlen(list->path) : 0);
	printf("permission_len: %d\n", list->permission_len);
	printf("PID: %d\n", list->pid);
	printf("path: %s\n", list->path);
	printf("%s", "permissions: ");
	for(i=0;i<list->permission_len;i++)
	{
		printf("%d ", list->permissions[i]);
	}
	printf("%s", "\n");
	printf("prev: %p\n", list->prev);
	printf("next: %p\n", list->next);
}
#endif

/* Object name is actually name of a Group ID *
 * This function opens /etc/group file and search group ID and
 * returns the string */
int search_object_name(int gid, char *obj, int obj_size)
{
	FILE *fp = NULL;
	char *linebuf = NULL, *token = NULL, *token2, *tempstr = NULL;
	int ret = 0, tmp_gid, bufsize;
	fp = fopen("/etc/group", "r");
	if(fp == NULL)
	{
		/* cannot open /etc/group */
		SEC_SVR_ERR("%s", "Cannot open /etc/group");
		return SECURITY_SERVER_ERROR_FILE_OPERATION;
	}

	linebuf = malloc(128);
	bufsize = 128;
	if(linebuf == NULL)
	{
		ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
		SEC_SVR_ERR("%s", "cannot malloc()");
		goto error;
	}

	bzero(linebuf, bufsize);
	ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT;
	while(fgets(linebuf, bufsize, fp) != NULL)
	{
		while(linebuf[bufsize -2] != 0)
		{
			linebuf[bufsize -1] = (char) fgetc(fp);
			tempstr = realloc(linebuf, bufsize + 128);
			if(tempstr == NULL)
			{
				ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
				goto error;
			}
			linebuf = tempstr;
			bzero(linebuf + bufsize, 128);
			fgets(linebuf + bufsize, 128, fp);
			bufsize += 128;
		}

		token = strtok(linebuf, ":");	/* group name */
		if(token == NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}
		token2 = strtok(NULL, ":");	/* group password */
		if(token2== NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}
		token2 = strtok(NULL, ":");	/* gid */
		if(token2 == NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}

		errno = 0;
		tmp_gid = strtoul(token2, 0, 10);
		if (errno != 0)
		{
			SEC_SVR_ERR("cannot change string to integer [%s]", token2);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}

		if(tmp_gid == gid)
		{
			/* We found it */
			if((int)strlen(token) > obj_size)
			{
				ret = SECURITY_SERVER_ERROR_BUFFER_TOO_SMALL;
				SEC_SVR_ERR("buffer is too small. %d --> %d", obj_size, strlen(token));
				goto error;
			}
			strncpy(obj, token, strlen(token));
			obj[strlen(token)] = 0;
			ret = SECURITY_SERVER_SUCCESS;
			break;
		}
		bzero(linebuf, bufsize);
	}

error:
	if(linebuf != NULL)
		free(linebuf);
	if(fp != NULL)
		fclose(fp);
	return ret;
}

/* Search GID from group name *
 * This function opens /etc/group and search group name by given gid */
int search_gid(const char *obj)
{
	FILE *fp = NULL;
	char *linebuf = NULL, *token = NULL, *token2, *tempstr = NULL;
	int ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT, tmp_gid, bufsize;

	SEC_SVR_DBG("Searching for object %s", obj);

	fp = fopen("/etc/group", "r");
	if(fp == NULL)
	{
		/* cannot open /etc/group */
		SEC_SVR_ERR("%s", "cannot open /etc/group");
		return SECURITY_SERVER_ERROR_FILE_OPERATION;
	}

	linebuf = malloc(128);
	bufsize = 128;
	if(linebuf == NULL)
	{
		ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
		SEC_SVR_ERR("%s", "Out Of Memory");
		goto error;
	}

	bzero(linebuf, bufsize);
	while(fgets(linebuf, bufsize, fp) != NULL)
	{
		while(linebuf[bufsize -2] != 0 )
		{
			linebuf[bufsize -1] = (char) fgetc(fp);
			tempstr = realloc(linebuf, bufsize + 128);
			if(tempstr == NULL)
			{
				ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
				goto error;
			}
			linebuf = tempstr;
			bzero(linebuf + bufsize, 128);
			fgets(linebuf + bufsize, 128, fp);
			bufsize += 128;
		}

		token = strtok(linebuf, ":");	/* group name */
		token2 = strtok(NULL, ":");	/* group password */
		token2 = strtok(NULL, ":");	/* gid */
		if(token2 == NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}
		errno = 0;
		tmp_gid = strtoul(token2, 0, 10);
		if ( errno != 0 )
		{
			SEC_SVR_ERR("cannot change string to integer [%s]", token2);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}

		if(strcmp(obj, token) == 0)
		{
			/* We found it */
			ret = tmp_gid;
			SEC_SVR_DBG("GID of %s is found: %d", obj, ret);
			break;
		}
		bzero(linebuf, bufsize);
	}

error:
	if(linebuf != NULL)
		free(linebuf);
	if(fp != NULL)
		fclose(fp);
	return ret;
}

/* Signal handler for processes */
static void security_server_sig_child(int signo, siginfo_t *info, void *data)
{
    int status;
    pid_t child_pid;
    pid_t child_pgid;

    (void)signo;
    (void)data;

    child_pgid = getpgid(info->si_pid);
    SEC_SVR_DBG("Signal handler: dead_pid=%d, pgid=%d",info->si_pid,child_pgid);

    while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if(child_pid == child_pgid)
            killpg(child_pgid,SIGKILL);
    }

    return;
}

/* Execute a debugging tool by fork() and execve() */
int execute_debug_tool(int argc, char *const *argv, int server_sockfd, int client_sockfd)
{
    int ret, i;
    SEC_SVR_DBG("%s", "Executing tool");

    (void)argc;

    ret = fork();
    if(ret == 0)
    {
        close(client_sockfd);
        close(server_sockfd);
        setsid();

        for(i=0;i<_NSIG;i++)
            signal(i, SIG_DFL);

        ret = execv(argv[0], argv);
        if(ret == -1)
        {
            SEC_SVR_ERR("Error:Failed to execute [%d]", errno);
            exit(-1);
        }
    }
    if(ret < 0)
    {
        SEC_SVR_ERR("Error: Failed to fork [%d]", errno);
        return SECURITY_SERVER_ERROR_SERVER_ERROR;
    }
    return SECURITY_SERVER_SUCCESS;
}

int process_cookie_request(int sockfd)
{
	int retval, client_pid, client_uid;
	cookie_list *created_cookie = NULL;

	/* Authenticate client */
	retval = authenticate_client_application(sockfd, &client_pid, &client_uid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}
	/* If client application is root process, just respond default cookie */
    /*
	if( client_uid == 0)
	{
		SEC_SVR_DBG("%s", "Requested application is a root process");
		created_cookie = c_list;
		if(c_list == NULL)
		{
			SEC_SVR_DBG("%s", "Cannot read default cookie");
			goto error;
		}
	}
	else
	{
    */
        //TODO: Remove above code if there will be no crashes without it
        //All process should be treaded the same
		/* Create a new cookie. or find existing one */
		pthread_mutex_lock(&cookie_mutex);
		created_cookie = create_cookie_item(client_pid, sockfd, c_list);
		pthread_mutex_unlock(&cookie_mutex);
		if(created_cookie == NULL)
		{
			SEC_SVR_ERR("%s","Cannot create a cookie");
			goto error;
		}

    //let others know if this cookie belongs to root process
    if(client_uid == 0)
        created_cookie->is_roots_process = 1;
    else
        created_cookie->is_roots_process = 0;

	//}
	/* send cookie as response */
	retval = send_cookie(sockfd, created_cookie->cookie);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
	}
        SEC_SVR_DBG("Server: Cookie created for client PID %d LABEL >%s<",
                    created_cookie->pid,
                    (created_cookie->smack_label)?(created_cookie->smack_label):"NULL");

	SEC_SVR_DBG("%s", "Server: Cookie has been sent to client");

error:
	return retval;
}

int process_check_privilege_request(int sockfd)
{
	/* Authenticate client */
	int retval, client_pid, requested_privilege;
    int privileges[1];
	unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
	cookie_list *search_result = NULL;

	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

	retval = recv_check_privilege_request(sockfd,
				requested_cookie, &requested_privilege);
	if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

	if(requested_privilege < 1)
	{
		SEC_SVR_ERR("Requiring bad privilege [%d]", requested_privilege);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Search cookie list */
	pthread_mutex_lock(&cookie_mutex);
    privileges[0] = requested_privilege;
	search_result = search_cookie(c_list, requested_cookie, privileges, 1);
	pthread_mutex_unlock(&cookie_mutex);
	if(search_result != NULL)
	{
		/* We found */
		SEC_SVR_DBG("We found the cookie with %d privilege and pid:%d", requested_privilege, client_pid);
		SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
	else
	{
		/* It's not exist */
		SEC_SVR_ERR("Could not find the cookie with %d privilege", requested_privilege);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
error:
	return retval;
}

int process_check_privilege_new_request(int sockfd)
{
	/* Authenticate client */
	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];
        char access_rights[MAX_MODE_STR_LEN+1];

	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

        retval = recv_check_privilege_new_request(
                     sockfd, requested_cookie, object_label, access_rights);
	if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd, 
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

	/* Search cookie list */
	pthread_mutex_lock(&cookie_mutex);
	search_result = search_cookie_new(c_list, requested_cookie, object_label, access_rights);
	pthread_mutex_unlock(&cookie_mutex);

	if(search_result != NULL)
    {
		/* We found */
		SEC_SVR_DBG("We found the cookie with %s rights and pid:%d", access_rights, client_pid);
		SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
		retval = send_generic_response(sockfd, 
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE, 
				SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
	else
	{
		/* It's not exist */
		SEC_SVR_ERR("Could not find the cookie with %s rights", access_rights);
		retval = send_generic_response(sockfd, 
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE, 
				SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
error:
	return retval;


}

int process_object_name_request(int sockfd)
{
	int retval, client_pid, requested_privilege;
	char object_name[SECURITY_SERVER_MAX_OBJ_NAME];

	/* Authenticate client */
	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Receive GID */
	retval = TEMP_FAILURE_RETRY(read(sockfd, &requested_privilege, sizeof(requested_privilege)));
	if (retval < (int)sizeof(requested_privilege))
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Search from /etc/group */
	retval = search_object_name(requested_privilege,
			object_name,
			SECURITY_SERVER_MAX_OBJ_NAME);
	if (retval == SECURITY_SERVER_ERROR_NO_SUCH_OBJECT)
	{
		/* It's not exist */
		SEC_SVR_ERR("There is no such object for gid [%d]", requested_privilege);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		/* Error occurred */
		SEC_SVR_ERR("Error on searching object name [%d]", retval);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* We found */
	SEC_SVR_DBG("We found object: %s", object_name);
	retval = send_object_name(sockfd, object_name);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
	}

error:
	return retval;
}

int process_gid_request(int sockfd, int msg_len)
{
	int retval, client_pid;
	char object_name[SECURITY_SERVER_MAX_OBJ_NAME];
	/* Authenticate client as middleware daemon */
	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client authentication failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	if(msg_len >= SECURITY_SERVER_MAX_OBJ_NAME)
	{
		/* Too big ojbect name */
		SEC_SVR_ERR("%s", "Object name is too big");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Receive group name */
	retval = TEMP_FAILURE_RETRY(read(sockfd, object_name, msg_len));
	if (retval < msg_len )
	{
		SEC_SVR_ERR("%s", "Failed to read object name");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}
	object_name[msg_len] = 0;

	/* Search /etc/group for the given group name */
	retval = search_gid(object_name);
	if (retval == SECURITY_SERVER_ERROR_NO_SUCH_OBJECT)
	{
		/* Not exist */
		SEC_SVR_ERR("The object [%s] is not exist", object_name);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	if(retval < 0)
	{
		/* Error occurred */
		SEC_SVR_ERR("Cannot send the response. %d", retval);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}

		goto error;
	}
	/* We found */
	retval = send_gid(sockfd, retval);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("ERROR: Cannot gid response: %d", retval);
	}
error:
	return retval;
}

int process_pid_request(int sockfd)
{
	int retval, client_pid;
	unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
    int * privileges = NULL;
	cookie_list *search_result = NULL;

	/* Authenticate client */
	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	retval = recv_pid_request(sockfd, requested_cookie);
	if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

    retval = get_client_gid_list(sockfd, &privileges);
    if(retval < 0)
    {
        SEC_SVR_ERR("ERROR: Cannot get GID list");
        goto error;
    }

    /* Search cookie list */
    pthread_mutex_lock(&cookie_mutex);
    search_result = search_cookie(c_list, requested_cookie, privileges, retval);
    pthread_mutex_unlock(&cookie_mutex);

    free(privileges);

	if(search_result != NULL)
	{
		/* We found */
		SEC_SVR_DBG("We found the cookie and pid:%d", search_result->pid);
		SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
		retval = send_pid(sockfd, search_result->pid);

		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
	else
	{
		/* It's not exist */
		SEC_SVR_ERR("%s", "Could not find the cookie");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send pid response: %d", retval);
		}
	}
error:
	return retval;
}

int process_smack_request(int sockfd)
{
    int retval, client_pid;
    int * privileges = NULL;
    unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
    cookie_list *search_result = NULL;
    //handler for SMACK label
    char * label = NULL;

    /* Authenticate client */
    retval = authenticate_client_middleware(sockfd, &client_pid);
    if(retval != SECURITY_SERVER_SUCCESS)
    {
        SEC_SVR_ERR("%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_ERR("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_ERR("%s", "Receiving request failed");
        retval = send_generic_response(sockfd,
          SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
          SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
        if(retval != SECURITY_SERVER_SUCCESS)
        {
            SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
        }
        goto error;
    }

    retval = get_client_gid_list(sockfd, &privileges);
    if(retval < 0)
    {
        SEC_SVR_ERR("ERROR: Cannot get GID list");
        goto error;
    }

    /* Search cookie list */
    pthread_mutex_lock(&cookie_mutex);
    search_result = search_cookie(c_list, requested_cookie, privileges, retval);
    pthread_mutex_unlock(&cookie_mutex);

    free(privileges);

    if(search_result != NULL)
    {
        /* We found */
        SEC_SVR_DBG("We found the cookie and pid:%d", search_result->pid);
        SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");

        label = search_result->smack_label;

        if (NULL == label)
        {
            SEC_SVR_DBG("%s", "No SMACK support on device - returning empty label");
            label = "";
        }

        SEC_SVR_DBG("Read label is: %s\n", label);

        retval = send_smack(sockfd, label);

        if(retval != SECURITY_SERVER_SUCCESS)
        {
            SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
        }
    }
    else
    {
        /* It's not exist */
        SEC_SVR_ERR("%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_ERR("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;<commit_msg>Thread synchronisation fixed. Proper cookie copying.<commit_after>/*
 * security-server
 *
 *  Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Contact: <NAME> <<EMAIL>>
 *
 *  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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/smack.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/smack.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;
pthread_mutex_t cookie_mutex;
int thread_status[SECURITY_SERVER_NUM_THREADS];
struct security_server_thread_param {
	int client_sockfd;
	int server_sockfd;
	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"
/************************************************************************************************/

#if 0
void printhex(unsigned char *data, int size)
{
	int i;
	for(i=0;i<size;i++)
	{
		if(data[i] < 0xF)
			printf("0");

		printf("%X ", data[i]);
		if(((i+1) % 16) == 0 && i != 0)
			printf("\n");
	}
	printf("\n");
}

void print_cookie(cookie_list *list)
{
	int i;
	printf("%s", "cookie:\n");
	printhex(list->cookie, SECURITY_SERVER_COOKIE_LEN);
	printf("path_len: %d\n", list->path ? strlen(list->path) : 0);
	printf("permission_len: %d\n", list->permission_len);
	printf("PID: %d\n", list->pid);
	printf("path: %s\n", list->path);
	printf("%s", "permissions: ");
	for(i=0;i<list->permission_len;i++)
	{
		printf("%d ", list->permissions[i]);
	}
	printf("%s", "\n");
	printf("prev: %p\n", list->prev);
	printf("next: %p\n", list->next);
}
#endif

/* Object name is actually name of a Group ID *
 * This function opens /etc/group file and search group ID and
 * returns the string */
int search_object_name(int gid, char *obj, int obj_size)
{
	FILE *fp = NULL;
	char *linebuf = NULL, *token = NULL, *token2, *tempstr = NULL;
	int ret = 0, tmp_gid, bufsize;
	fp = fopen("/etc/group", "r");
	if(fp == NULL)
	{
		/* cannot open /etc/group */
		SEC_SVR_ERR("%s", "Cannot open /etc/group");
		return SECURITY_SERVER_ERROR_FILE_OPERATION;
	}

	linebuf = malloc(128);
	bufsize = 128;
	if(linebuf == NULL)
	{
		ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
		SEC_SVR_ERR("%s", "cannot malloc()");
		goto error;
	}

	bzero(linebuf, bufsize);
	ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT;
	while(fgets(linebuf, bufsize, fp) != NULL)
	{
		while(linebuf[bufsize -2] != 0)
		{
			linebuf[bufsize -1] = (char) fgetc(fp);
			tempstr = realloc(linebuf, bufsize + 128);
			if(tempstr == NULL)
			{
				ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
				goto error;
			}
			linebuf = tempstr;
			bzero(linebuf + bufsize, 128);
			fgets(linebuf + bufsize, 128, fp);
			bufsize += 128;
		}

		token = strtok(linebuf, ":");	/* group name */
		if(token == NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}
		token2 = strtok(NULL, ":");	/* group password */
		if(token2== NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}
		token2 = strtok(NULL, ":");	/* gid */
		if(token2 == NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}

		errno = 0;
		tmp_gid = strtoul(token2, 0, 10);
		if (errno != 0)
		{
			SEC_SVR_ERR("cannot change string to integer [%s]", token2);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}

		if(tmp_gid == gid)
		{
			/* We found it */
			if((int)strlen(token) > obj_size)
			{
				ret = SECURITY_SERVER_ERROR_BUFFER_TOO_SMALL;
				SEC_SVR_ERR("buffer is too small. %d --> %d", obj_size, strlen(token));
				goto error;
			}
			strncpy(obj, token, strlen(token));
			obj[strlen(token)] = 0;
			ret = SECURITY_SERVER_SUCCESS;
			break;
		}
		bzero(linebuf, bufsize);
	}

error:
	if(linebuf != NULL)
		free(linebuf);
	if(fp != NULL)
		fclose(fp);
	return ret;
}

/* Search GID from group name *
 * This function opens /etc/group and search group name by given gid */
int search_gid(const char *obj)
{
	FILE *fp = NULL;
	char *linebuf = NULL, *token = NULL, *token2, *tempstr = NULL;
	int ret = SECURITY_SERVER_ERROR_NO_SUCH_OBJECT, tmp_gid, bufsize;

	SEC_SVR_DBG("Searching for object %s", obj);

	fp = fopen("/etc/group", "r");
	if(fp == NULL)
	{
		/* cannot open /etc/group */
		SEC_SVR_ERR("%s", "cannot open /etc/group");
		return SECURITY_SERVER_ERROR_FILE_OPERATION;
	}

	linebuf = malloc(128);
	bufsize = 128;
	if(linebuf == NULL)
	{
		ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
		SEC_SVR_ERR("%s", "Out Of Memory");
		goto error;
	}

	bzero(linebuf, bufsize);
	while(fgets(linebuf, bufsize, fp) != NULL)
	{
		while(linebuf[bufsize -2] != 0 )
		{
			linebuf[bufsize -1] = (char) fgetc(fp);
			tempstr = realloc(linebuf, bufsize + 128);
			if(tempstr == NULL)
			{
				ret = SECURITY_SERVER_ERROR_OUT_OF_MEMORY;
				goto error;
			}
			linebuf = tempstr;
			bzero(linebuf + bufsize, 128);
			fgets(linebuf + bufsize, 128, fp);
			bufsize += 128;
		}

		token = strtok(linebuf, ":");	/* group name */
		token2 = strtok(NULL, ":");	/* group password */
		token2 = strtok(NULL, ":");	/* gid */
		if(token2 == NULL)
		{
			SEC_SVR_ERR("/etc/group is not valid. cannot find gid: [%s]", linebuf);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}
		errno = 0;
		tmp_gid = strtoul(token2, 0, 10);
		if ( errno != 0 )
		{
			SEC_SVR_ERR("cannot change string to integer [%s]", token2);
			ret = SECURITY_SERVER_ERROR_SERVER_ERROR;
			goto error;
		}

		if(strcmp(obj, token) == 0)
		{
			/* We found it */
			ret = tmp_gid;
			SEC_SVR_DBG("GID of %s is found: %d", obj, ret);
			break;
		}
		bzero(linebuf, bufsize);
	}

error:
	if(linebuf != NULL)
		free(linebuf);
	if(fp != NULL)
		fclose(fp);
	return ret;
}

/* Signal handler for processes */
static void security_server_sig_child(int signo, siginfo_t *info, void *data)
{
    int status;
    pid_t child_pid;
    pid_t child_pgid;

    (void)signo;
    (void)data;

    child_pgid = getpgid(info->si_pid);
    SEC_SVR_DBG("Signal handler: dead_pid=%d, pgid=%d",info->si_pid,child_pgid);

    while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if(child_pid == child_pgid)
            killpg(child_pgid,SIGKILL);
    }

    return;
}

/* Execute a debugging tool by fork() and execve() */
int execute_debug_tool(int argc, char *const *argv, int server_sockfd, int client_sockfd)
{
    int ret, i;
    SEC_SVR_DBG("%s", "Executing tool");

    (void)argc;

    ret = fork();
    if(ret == 0)
    {
        close(client_sockfd);
        close(server_sockfd);
        setsid();

        for(i=0;i<_NSIG;i++)
            signal(i, SIG_DFL);

        ret = execv(argv[0], argv);
        if(ret == -1)
        {
            SEC_SVR_ERR("Error:Failed to execute [%d]", errno);
            exit(-1);
        }
    }
    if(ret < 0)
    {
        SEC_SVR_ERR("Error: Failed to fork [%d]", errno);
        return SECURITY_SERVER_ERROR_SERVER_ERROR;
    }
    return SECURITY_SERVER_SUCCESS;
}

int process_cookie_request(int sockfd)
{
	int retval, client_pid, client_uid;
	cookie_list *created_cookie = NULL;
	unsigned char cookie[SECURITY_SERVER_COOKIE_LEN];
	pid_t cookie_pid;
	char* cookie_label = NULL;

	/* Authenticate client */
	retval = authenticate_client_application(sockfd, &client_pid, &client_uid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GENERIC_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}
	/* If client application is root process, just respond default cookie */
    /*
	if( client_uid == 0)
	{
		SEC_SVR_DBG("%s", "Requested application is a root process");
		created_cookie = c_list;
		if(c_list == NULL)
		{
			SEC_SVR_DBG("%s", "Cannot read default cookie");
			goto error;
		}
	}
	else
	{
    */
        //TODO: Remove above code if there will be no crashes without it
        //All process should be treaded the same

	/* Create a new cookie. or find existing one */
	pthread_mutex_lock(&cookie_mutex);
	created_cookie = create_cookie_item(client_pid, sockfd, c_list);
	if(created_cookie == NULL)
	{
		pthread_mutex_unlock(&cookie_mutex);
		SEC_SVR_ERR("%s","Cannot create a cookie");
		goto error;
	}

	//let others know if this cookie belongs to root process
	if(client_uid == 0)
		created_cookie->is_roots_process = 1;
	else
		created_cookie->is_roots_process = 0;
	memcpy(cookie, created_cookie->cookie, SECURITY_SERVER_COOKIE_LEN);
	cookie_pid = created_cookie->pid;
	if (created_cookie->smack_label)
		cookie_label = strdup(created_cookie->smack_label);
	else
		cookie_label = strdup("NULL");
	pthread_mutex_unlock(&cookie_mutex);

	//}
	/* send cookie as response */
	retval = send_cookie(sockfd, cookie);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
	}
	SEC_SVR_DBG("Server: Cookie created for client PID %d LABEL >%s<",
				cookie_pid, cookie_label);

	SEC_SVR_DBG("%s", "Server: Cookie has been sent to client");
	free(cookie_label);

error:
	return retval;
}

int process_check_privilege_request(int sockfd)
{
	/* Authenticate client */
	int retval, client_pid, requested_privilege;
    int privileges[1];
	unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
	cookie_list *search_result = NULL;

	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

	retval = recv_check_privilege_request(sockfd,
				requested_cookie, &requested_privilege);
	if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

	if(requested_privilege < 1)
	{
		SEC_SVR_ERR("Requiring bad privilege [%d]", requested_privilege);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Search cookie list */
	pthread_mutex_lock(&cookie_mutex);
    privileges[0] = requested_privilege;
	search_result = search_cookie(c_list, requested_cookie, privileges, 1);
	pthread_mutex_unlock(&cookie_mutex);
	if(search_result != NULL)
	{
		/* We found */
		SEC_SVR_DBG("We found the cookie with %d privilege and pid:%d", requested_privilege, client_pid);
		SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
	else
	{
		/* It's not exist */
		SEC_SVR_ERR("Could not find the cookie with %d privilege", requested_privilege);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
error:
	return retval;
}

int process_check_privilege_new_request(int sockfd)
{
	/* Authenticate client */
	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];
        char access_rights[MAX_MODE_STR_LEN+1];

	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

        retval = recv_check_privilege_new_request(
                     sockfd, requested_cookie, object_label, access_rights);
	if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd, 
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;;
	}

	/* Search cookie list */
	pthread_mutex_lock(&cookie_mutex);
	search_result = search_cookie_new(c_list, requested_cookie, object_label, access_rights);
	pthread_mutex_unlock(&cookie_mutex);

	if(search_result != NULL)
    {
		/* We found */
		SEC_SVR_DBG("We found the cookie with %s rights and pid:%d", access_rights, client_pid);
		SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
		retval = send_generic_response(sockfd, 
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE, 
				SECURITY_SERVER_RETURN_CODE_ACCESS_GRANTED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
	else
	{
		/* It's not exist */
		SEC_SVR_ERR("Could not find the cookie with %s rights", access_rights);
		retval = send_generic_response(sockfd, 
				SECURITY_SERVER_MSG_TYPE_CHECK_PRIVILEGE_NEW_RESPONSE, 
				SECURITY_SERVER_RETURN_CODE_ACCESS_DENIED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
error:
	return retval;


}

int process_object_name_request(int sockfd)
{
	int retval, client_pid, requested_privilege;
	char object_name[SECURITY_SERVER_MAX_OBJ_NAME];

	/* Authenticate client */
	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Receive GID */
	retval = TEMP_FAILURE_RETRY(read(sockfd, &requested_privilege, sizeof(requested_privilege)));
	if (retval < (int)sizeof(requested_privilege))
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Search from /etc/group */
	retval = search_object_name(requested_privilege,
			object_name,
			SECURITY_SERVER_MAX_OBJ_NAME);
	if (retval == SECURITY_SERVER_ERROR_NO_SUCH_OBJECT)
	{
		/* It's not exist */
		SEC_SVR_ERR("There is no such object for gid [%d]", requested_privilege);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		/* Error occurred */
		SEC_SVR_ERR("Error on searching object name [%d]", retval);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_OBJECT_NAME_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* We found */
	SEC_SVR_DBG("We found object: %s", object_name);
	retval = send_object_name(sockfd, object_name);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
	}

error:
	return retval;
}

int process_gid_request(int sockfd, int msg_len)
{
	int retval, client_pid;
	char object_name[SECURITY_SERVER_MAX_OBJ_NAME];
	/* Authenticate client as middleware daemon */
	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client authentication failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	if(msg_len >= SECURITY_SERVER_MAX_OBJ_NAME)
	{
		/* Too big ojbect name */
		SEC_SVR_ERR("%s", "Object name is too big");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	/* Receive group name */
	retval = TEMP_FAILURE_RETRY(read(sockfd, object_name, msg_len));
	if (retval < msg_len )
	{
		SEC_SVR_ERR("%s", "Failed to read object name");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}
	object_name[msg_len] = 0;

	/* Search /etc/group for the given group name */
	retval = search_gid(object_name);
	if (retval == SECURITY_SERVER_ERROR_NO_SUCH_OBJECT)
	{
		/* Not exist */
		SEC_SVR_ERR("The object [%s] is not exist", object_name);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_NO_SUCH_OBJECT);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	if(retval < 0)
	{
		/* Error occurred */
		SEC_SVR_ERR("Cannot send the response. %d", retval);
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_GID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_SERVER_ERROR);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}

		goto error;
	}
	/* We found */
	retval = send_gid(sockfd, retval);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("ERROR: Cannot gid response: %d", retval);
	}
error:
	return retval;
}

int process_pid_request(int sockfd)
{
	int retval, client_pid;
	unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
    int * privileges = NULL;
	cookie_list *search_result = NULL;
	pid_t cookie_pid = 0;

	/* Authenticate client */
	retval = authenticate_client_middleware(sockfd, &client_pid);
	if(retval != SECURITY_SERVER_SUCCESS)
	{
		SEC_SVR_ERR("%s", "Client Authentication Failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_AUTHENTICATION_FAILED);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

	retval = recv_pid_request(sockfd, requested_cookie);
	if(retval == SECURITY_SERVER_ERROR_RECV_FAILED)
	{
		SEC_SVR_ERR("%s", "Receiving request failed");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
		goto error;
	}

    retval = get_client_gid_list(sockfd, &privileges);
    if(retval < 0)
    {
        SEC_SVR_ERR("ERROR: Cannot get GID list");
        goto error;
    }

	/* Search cookie list */
	pthread_mutex_lock(&cookie_mutex);
	search_result = search_cookie(c_list, requested_cookie, privileges, retval);
	if(search_result)
		cookie_pid = search_result->pid;
	pthread_mutex_unlock(&cookie_mutex);

	free(privileges);

	if(search_result != NULL)
	{
		/* We found */
		SEC_SVR_DBG("We found the cookie and pid:%d", cookie_pid);
		SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
		retval = send_pid(sockfd, cookie_pid);

		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
		}
	}
	else
	{
		/* It's not exist */
		SEC_SVR_ERR("%s", "Could not find the cookie");
		retval = send_generic_response(sockfd,
				SECURITY_SERVER_MSG_TYPE_PID_RESPONSE,
				SECURITY_SERVER_RETURN_CODE_NO_SUCH_COOKIE);
		if(retval != SECURITY_SERVER_SUCCESS)
		{
			SEC_SVR_ERR("ERROR: Cannot send pid response: %d", retval);
		}
	}
error:
	return retval;
}

int process_smack_request(int sockfd)
{
    int retval, client_pid;
    int * privileges = NULL;
    unsigned char requested_cookie[SECURITY_SERVER_COOKIE_LEN];
    cookie_list *search_result = NULL;
    //handler for SMACK label
    char * label = NULL;

    /* Authenticate client */
    retval = authenticate_client_middleware(sockfd, &client_pid);
    if(retval != SECURITY_SERVER_SUCCESS)
    {
        SEC_SVR_ERR("%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_ERR("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_ERR("%s", "Receiving request failed");
        retval = send_generic_response(sockfd,
          SECURITY_SERVER_MSG_TYPE_SMACK_RESPONSE,
          SECURITY_SERVER_RETURN_CODE_BAD_REQUEST);
        if(retval != SECURITY_SERVER_SUCCESS)
        {
            SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
        }
        goto error;
    }

    retval = get_client_gid_list(sockfd, &privileges);
    if(retval < 0)
    {
        SEC_SVR_ERR("ERROR: Cannot get GID list");
        goto error;
    }

	/* Search cookie list */
	pthread_mutex_lock(&cookie_mutex);
	search_result = search_cookie(c_list, requested_cookie, privileges, retval);
	if (search_result) {
		if (search_result->smack_label)
			label = strdup(search_result->smack_label);
		else {
			SEC_SVR_DBG("%s", "No SMACK support on device - returning empty label");
			label = strdup("");
		}
	}
	pthread_mutex_unlock(&cookie_mutex);

	free(privileges);

    if(search_result != NULL)
    {
        /* We found */
        SEC_SVR_DBG("We found the cookie and pid:%d", search_result->pid);
        SEC_SVR_DBG("%s", "Cookie comparison succeeded. Access granted.");
        SEC_SVR_DBG("Read label is: %s\n", label);

        retval = send_smack(sockfd, label);

        if(retval != SECURITY_SERVER_SUCCESS)
        {
            SEC_SVR_ERR("ERROR: Cannot send generic response: %d", retval);
        }
    }
    else
    {
        /* It's not exist */
        SEC_SVR_ERR("%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_ERR("ERROR: Cannot send SMACK label response: %d", retval);
        }
    }
    free(label);
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;
{'fraction_non_alphanumeric': 0.12567064813001763, 'fraction_numerical': 0.004523203446250245, 'mean_word_length': 4.189087583824426, 'pattern_counts': {'":': 12, '<': 73, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5304620', 'n_tokens_mistral': 19802, 'n_tokens_neox': 18332, 'n_words': 3906}