<commit_before>/*
Wayland Security Module - Default Backend
Copyright (C) 2014 <NAME> & <NAME>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA	02110-1301	USA
*/

#include <sys/types.h>
#include <malloc.h>

#include <libwsm.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <wayland-util.h>
#include "config-parser.h"

#include "debug.h"

#define TMP_PREFIX					 	"../data/"
#define WSM_DEFAULT_POLICY_DIR			TMP_PREFIX"security/wsm/default"
#define WSM_DEFAULT_POLICY_PER_USER_DIR	TMP_PREFIX"security/wsm/per-user/default"

#define WSM_DEFAULT_DEFAULT_PATH		"*"
#define WSM_DEFAULT_DEFAULT_UID			-1

#define WSM_SCREENSHOT "WSM_SCREENSHOT"
#define WSM_SCREENSHARING "WSM_SCREENSHARING"
#define WSM_VIRTUAL_KEYBOARD "WSM_VIRTUAL_KEYBOARD"
#define WSM_VIRTUAL_POINTING "WSM_VIRTUAL_POINTING"
#define WSM_GLOBAL_KEYBOARD_SEQUENCE "WSM_GLOBAL_KEYBOARD_SEQUENCE"
#define WSM_FORWARD_RESERVED_KEYBOARD_SEQUENCE "WSM_FORWARD_RESERVED_KEYBOARD_SEQUENCE"
#define WSM_CLIPBOARD_COPY "WSM_CLIPBOARD_COPY"
#define WSM_CLIPBOARD_PASTE "WSM_CLIPBOARD_PASTE"


struct wsm_default_t {
	/* Name of the current compositor */
	char *compositor_name;

	/* List of policies for each application and UID */
	struct wl_list app_policies;
};

static struct wsm_default_t *_wsm_default_global = NULL;

struct wsm_default_client_t{
	/* Executable */
	wsm_client_info_t		*parent;
	char			 		*exe_path;
	pid_t			 		 pid;
	uid_t			 		 euid;
	struct weston_config	*policy;
};

struct wsm_app_policy_t {
	unsigned int		 	 version;
	char					*exe_path;
	signed long				 uid;		/* Can be -1 for the default UID */
	struct weston_config	*config;
	struct wl_list		 	 link;
};

struct wsm_cap_t {
	const char	 	*cap_name;
	struct wl_list	 objects; /* wsm_objperm_t */
	struct wl_list	 link;
};

struct wsm_objperm_t {
	const char	 	*object;
	const char	 	*permission;
	struct wl_list	 link;
};

struct wsm_default_client_t *wsm_default_client_lookup(int socket);
struct wsm_default_client_t *wsm_default_client_new(int socket);
void wsm_default_client_delete(struct wsm_default_client_t *app);
void wsm_default_client_change_permission(struct wsm_default_client_t *app, const char *cap_name, void *object, void *permission);

struct wsm_app_policy_t *wsm_app_policy_new(struct wsm_default_t *global, const char *path, const signed long uid, short * const existed);
void wsm_app_policy_register(struct wsm_default_t *global, struct wsm_app_policy_t *policy);
void wsm_app_policy_free(struct wsm_app_policy_t *policy);
struct wsm_app_policy_t *wsm_app_policy_lookup(struct wsm_default_t *global, const char *exe_path, const signed long uid);

int _string_starts_with(const char *str, const char *prefix)
{
	size_t pre_len = strlen(prefix);
	size_t str_len = strlen(str);

	if (pre_len > str_len)
		return 0;
	else
		return (strncmp(prefix, str, pre_len) == 0);
}

static int _string_ends_with(const char *str, const char *suffix)
{
	size_t suf_len = strlen(suffix);
	size_t str_len = strlen(str);

	if (suf_len > str_len)
		return 0;
	else
	{
		size_t delta = str_len - suf_len;
		return (strncmp(suffix, str+delta, suf_len) == 0);
	}
}

struct wsm_app_policy_t *wsm_app_policy_new(struct wsm_default_t *global, const char *path, const signed long uid, short * const existed)
{
	if (path == NULL)
		return NULL;

	// Factorising for later, will set to 1 when a policy is found to exist
	if (existed)
		*existed=0;

	struct weston_config *config;
	struct weston_config_section *section;
	char *exe_path = NULL;

	config = weston_config_parse(path);
	if (config != NULL) {
		DEBUG("Default Backend: wsm_app_policy_new: Using config file '%s'\n", weston_config_get_full_path(config));
	} else {
		DEBUG("Default Backend: wsm_app_policy_new: Could not parse policy file '%s'.\n", path);
	}
	section = weston_config_get_section(config, "Wayland Security Entry", NULL, NULL);
	weston_config_section_get_string(section, "Exec", &exe_path, NULL);

	if (!exe_path) {
		DEBUG("Default Backend: wsm_app_policy_new: Policy file '%s' is missing an executable path and will be discarded.\n", path);
		weston_config_destroy(config);
		return NULL;
	}

	struct wsm_app_policy_t *existing;

	if ((existing = wsm_app_policy_lookup(global, exe_path, uid)) != NULL)
	{
		DEBUG("Default Backend: wsm_app_policy_new: Found an existing policy for '%s;%ld'.\n", exe_path, uid);
		if (existed)<commit_msg>Improved the code that verifies the Exec line in policy loading to refuse obvious non-absolute paths and better inform the user about errors<commit_after>/*
Wayland Security Module - Default Backend
Copyright (C) 2014 <NAME> & <NAME>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA	02110-1301	USA
*/

#include <sys/types.h>
#include <malloc.h>

#include <libwsm.h>
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <wayland-util.h>
#include "config-parser.h"

#include "debug.h"

#define TMP_PREFIX					 	"../data/"
#define WSM_DEFAULT_POLICY_DIR			TMP_PREFIX"security/wsm/default"
#define WSM_DEFAULT_POLICY_PER_USER_DIR	TMP_PREFIX"security/wsm/per-user/default"

#define WSM_DEFAULT_DEFAULT_PATH		"*"
#define WSM_DEFAULT_DEFAULT_UID			-1

#define WSM_SCREENSHOT "WSM_SCREENSHOT"
#define WSM_SCREENSHARING "WSM_SCREENSHARING"
#define WSM_VIRTUAL_KEYBOARD "WSM_VIRTUAL_KEYBOARD"
#define WSM_VIRTUAL_POINTING "WSM_VIRTUAL_POINTING"
#define WSM_GLOBAL_KEYBOARD_SEQUENCE "WSM_GLOBAL_KEYBOARD_SEQUENCE"
#define WSM_FORWARD_RESERVED_KEYBOARD_SEQUENCE "WSM_FORWARD_RESERVED_KEYBOARD_SEQUENCE"
#define WSM_CLIPBOARD_COPY "WSM_CLIPBOARD_COPY"
#define WSM_CLIPBOARD_PASTE "WSM_CLIPBOARD_PASTE"


struct wsm_default_t {
	/* Name of the current compositor */
	char *compositor_name;

	/* List of policies for each application and UID */
	struct wl_list app_policies;
};

static struct wsm_default_t *_wsm_default_global = NULL;

struct wsm_default_client_t{
	/* Executable */
	wsm_client_info_t		*parent;
	char			 		*exe_path;
	pid_t			 		 pid;
	uid_t			 		 euid;
	struct weston_config	*policy;
};

struct wsm_app_policy_t {
	unsigned int		 	 version;
	char					*exe_path;
	signed long				 uid;		/* Can be -1 for the default UID */
	struct weston_config	*config;
	struct wl_list		 	 link;
};

struct wsm_cap_t {
	const char	 	*cap_name;
	struct wl_list	 objects; /* wsm_objperm_t */
	struct wl_list	 link;
};

struct wsm_objperm_t {
	const char	 	*object;
	const char	 	*permission;
	struct wl_list	 link;
};

struct wsm_default_client_t *wsm_default_client_lookup(int socket);
struct wsm_default_client_t *wsm_default_client_new(int socket);
void wsm_default_client_delete(struct wsm_default_client_t *app);
void wsm_default_client_change_permission(struct wsm_default_client_t *app, const char *cap_name, void *object, void *permission);

struct wsm_app_policy_t *wsm_app_policy_new(struct wsm_default_t *global, const char *path, const signed long uid, short * const existed);
void wsm_app_policy_register(struct wsm_default_t *global, struct wsm_app_policy_t *policy);
void wsm_app_policy_free(struct wsm_app_policy_t *policy);
struct wsm_app_policy_t *wsm_app_policy_lookup(struct wsm_default_t *global, const char *exe_path, const signed long uid);

static int _string_starts_with(const char *str, const char *prefix)
{
	size_t pre_len = strlen(prefix);
	size_t str_len = strlen(str);

	if (pre_len > str_len)
		return 0;
	else
		return (strncmp(prefix, str, pre_len) == 0);
}

static int _string_ends_with(const char *str, const char *suffix)
{
	size_t suf_len = strlen(suffix);
	size_t str_len = strlen(str);

	if (suf_len > str_len)
		return 0;
	else
	{
		size_t delta = str_len - suf_len;
		return (strncmp(suffix, str+delta, suf_len) == 0);
	}
}

struct wsm_app_policy_t *wsm_app_policy_new(struct wsm_default_t *global, const char *path, const signed long uid, short * const existed)
{
	if (path == NULL)
		return NULL;

	// Factorising for later, will set to 1 when a policy is found to exist
	if (existed)
		*existed=0;

	struct weston_config *config;
	struct weston_config_section *section;
	char *exe_path = NULL;

	config = weston_config_parse(path);
	if (config != NULL) {
		DEBUG("Default Backend: wsm_app_policy_new: Using config file '%s'\n", weston_config_get_full_path(config));
	} else {
		DEBUG("Default Backend: wsm_app_policy_new: Could not parse policy file '%s'.\n", path);
	}
	section = weston_config_get_section(config, "Wayland Security Entry", NULL, NULL);
	weston_config_section_get_string(section, "Exec", &exe_path, NULL);

	if (!exe_path) {
		DEBUG("Default Backend: wsm_app_policy_new: Policy file '%s' is missing an executable path and will be discarded.\n", path);
		weston_config_destroy(config);
		return NULL;
	}

	if (!_string_starts_with(exe_path, "/") && strcmp(exe_path, WSM_DEFAULT_DEFAULT_PATH)) {
		DEBUG("Default Backend: wsm_app_policy_new: Policy file '%s' 's executable path should be an absolute path or the wildcard '%s' (which matches all executables).\n", path, WSM_DEFAULT_DEFAULT_PATH);
		free(exe_path);
		weston_config_destroy(config);
		return NULL;
	}

	struct wsm_app_policy_t *existing;

	if ((existing = wsm_app_policy_lookup(global, exe_path, uid)) != NULL)
	{
		DEBUG("Default Backend: wsm_app_policy_new: Found an existing policy for '%s;%ld'.\n", exe_path, uid);
		if (existed)
{'fraction_non_alphanumeric': 0.09003578828404596, 'fraction_numerical': 0.004708984742889433, 'mean_word_length': 5.431859479103574, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2243486', 'n_tokens_mistral': 3997, 'n_tokens_neox': 3807, 'n_words': 1078}