/* 
 * - User Access Control
 *
 * Copyright 2009-2018 by AVM GmbH <info@avm.de>
 *
 * This software contains free software; you can redistribute it and/or modify it under the terms 
 * of the GNU General Public License ("License") as published by the Free Software Foundation 
 * (version 2 of the License). This software 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 copy of the License you received along with this software for more details.
 *
 */
#ifndef AVMACL2_AVM_ACL_H
#define AVMACL2_AVM_ACL_H

#ifdef __cplusplus
extern "C" {
#endif

/* this is the common path prefix of all real paths (linux file system view) that can be accessed */
#define AVM_ACL_COMMON_REAL_PREFIX "/var/media/ftp"

#define AVM_ACL_USER_ID_OFFSET     (1000) /**< internal user ID offset for mapping of boxusers ID to avm acl users ID */

struct acl_string_list
{
	struct acl_string_list *next;
	char *s;
};


/** \addtogroup avmaclstateless
 *  @{
 */

/** @enum avm_acl_mode AVM access control mode */
enum avm_acl_mode {
	avm_acl_mode_unknown,
	avm_acl_mode_smb,
	avm_acl_mode_ftp,
	avm_acl_mode_http,
};

/**
 * Evaluate the access rights for the given path.
 *
 * @param mode
 * @param username
 * @param path file system path
 * @param access_from_internet LAN access if 0 else WAN access
 * @param [out] pwrite_access 1 if write access is allowed
 *
 * @retval 0 on parameter error
 * @retval 0 if no user logged in
 * @retval 0 if path is empty and getcwd() failed
 * @retval 0 if realpath failed or empty
 * @retval 0 if path is not allowed
 * @retval 0 if path is blocked
 * @retval 1 if used by smbd and trying to read $IPC.
 * @retval 1 if path is allowed
 */
int avm_acl_is_allowed_path(enum avm_acl_mode mode, const char *username, const char *path, int access_from_internet, int *pwrite_access);

/**
 * Evaluate the access rights for the given path.
 *
 * @param mode
 * @param uid user ID
 * @param path file system path
 * @param access_from_internet LAN access if 0 else WAN access
 * @param [out] pwrite_access 1 if write access is allowed
 *
 * @retval 0 on parameter error
 * @retval 0 if no user logged in
 * @retval 0 if path is empty and getcwd() failed
 * @retval 0 if realpath failed or empty
 * @retval 0 if path is not allowed
 * @retval 0 if path is blocked
 * @retval 1 if used by smbd and trying to read $IPC.
 * @retval 1 if path is allowed
 */
int avm_acl_is_allowed_path_uid(enum avm_acl_mode mode, unsigned uid, const char *path, int access_from_internet, int *pwrite_access);

/**
 * Create list of all real file system paths with read access for a user with its username.
 *
 * @param mode
 * @param username
 * @param access_from_internet
 *
 * @return NULL on failure e.g. invalid user name
 */
struct acl_string_list *avm_acl_user_get_all_real_paths_with_read_access(enum avm_acl_mode mode, const char *username, int access_from_internet);

/**
 * Create list of all real file system paths with read access for a user with its user ID.
 *
 * @param mode
 * @param uid
 * @param access_from_internet
 *
 * @return NULL on failure e.g. invalid uid
 */
struct acl_string_list *avm_acl_user_get_all_real_paths_with_read_access_uid(enum avm_acl_mode mode, unsigned uid, int access_from_internet);

/** @}*/

/** \addtogroup avmaclglobalcontext
 *  @{
 */

/**
 * Login in with given user name.
 * Returns -1 if no username is given.
 * Returns -1 if no access for given user name.
 * Returns  0 if some access is configured for given user.
 * Internally allocated resources are freed on failure.
 *
 * @param username may be NULL
 * @param access_from_internet 0 for (W)LAN access else WAN access
 *
 * @retval 0 on success
 * @retval -1 on failure
 */
int acl_set_user_context(char *username, int access_from_internet);

/**
 * Login in with given user ID.
 * Returns -1 if invalid user ID is given.
 * Returns -1 if no access for given user ID.
 * Returns  0 if some access is configured for given user ID.
 * Internally allocated resources are freed on failure.
 *
 * @param uid user ID
 * @param access_from_internet 0 for (W)LAN access else WAN access
 *
 * @retval 0 on success
 * @retval -1 on failure
 */
int acl_set_user_context_uid(unsigned uid, int access_from_internet);

/**
 * Set write and read rights for "/" root directory.
 * for internal admin tasks ("root access")
 *
 * @return 0
 */
int acl_set_full_access_user_context(void);

char *acl_get_user_common_real_dir(void);

/**
 * Check if access to a given real path is allowed for the client
 * all path components must exist.
 *
 * @param path complete file system path
 * @param pwrite_access out parameter 1 if write access else 0
 *
 * @retval 0 on parameter error
 * @retval 0 if no user logged in
 * @retval 0 if path is empty and getcwd() failed
 * @retval 0 if realpath failed or empty
 * @retval 0 if path is not allowed
 * @retval 0 if path is blocked
 * @retval 1 if used by smbd and trying to read $IPC.
 * @retval 1 if path is allowed
 */
int acl_is_allowed_path(const char *path, int *pwrite_access);

void acl_set_samba_mode(void);

void acl_reconfig(void);

int acl_force_secured_internet_access(void);

/**
 * get all real file system paths the current user has at least read access to
 * the caller must free the list
 */
struct acl_string_list *acl_get_user_all_real_paths_with_read_access(void);

/** @}*/

/**
 * Free list of real paths.
 *
 * @param pp list of real paths, NULL after call
 */
void avm_acl_string_list_free(struct acl_string_list **pp);

#ifdef __cplusplus
}
#endif

#endif /* !AVMACL2_AVM_ACL_H */