From 5f55d9d4d14635678e7f582215e3642de2e232a4 Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Mon, 6 May 2024 02:08:31 +0200 Subject: new ecp directory and vconn server --- ecp/server/acl.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 ecp/server/acl.c (limited to 'ecp/server/acl.c') diff --git a/ecp/server/acl.c b/ecp/server/acl.c new file mode 100644 index 0000000..d8cdc6e --- /dev/null +++ b/ecp/server/acl.c @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "server.h" +#include "acl.h" + +static SRVConfig *srv_config; + +static ecp_ht_table_t *acl_keys = NULL; +static ecp_ht_table_t *acl_keys_dir = NULL; +static pthread_mutex_t acl_li_mutex; +static pthread_rwlock_t acl_ht_rwlock; +static ACLItem *acl_head = NULL; +static ACLItem *acl_head_dir = NULL; +static int acl_mark = 0; + +ACLItem *acl_create_item(void) { + ACLItem *ret = NULL; + + ret = malloc(sizeof(ACLItem)); + if (ret == NULL) return ret; + memset(&ret->key, 0, sizeof(ret->key)); + ret->key_cnt = 0; + ret->next = NULL; + + return ret; +} + +void acl_destroy_item(ACLItem *item) { + free(item); +} + +void acl_destroy_list(ACLItem *head) { + ACLItem *acl_next; + + while (head) { + acl_next = head->next; + acl_destroy_item(head); + head = acl_next; + } +} + +static int _add_key(ecp_ecdh_public_t *public, uint8_t capabilities) { + int rv; + + if ((acl_keys == NULL) || (acl_keys_dir == NULL)) return ECP_ERR; + + if ((srv_config->capabilities & ECP_DIR_CAP_DIR) || (srv_config->capabilities & capabilities & ECP_DIR_CAP_VCONN)) { + /* directory server accepts all connections + vconn server accepts connections only from other vconn servers */ + rv = ecp_ht_insert_uniq(acl_keys, public, &acl_mark); + if (rv && (rv != ECP_ERR_DUP)) return rv; + } + if (srv_config->capabilities & capabilities & ECP_DIR_CAP_DIR) { + rv = ecp_ht_insert_uniq(acl_keys_dir, public, &acl_mark); + if (rv && (rv != ECP_ERR_DUP)) return rv; + } + + return ECP_OK; +} + +static int _read_file(int fd, ACLItem *head) { + ecp_ecdh_public_t public; + int rv; + + if (head == NULL) return ECP_ERR_ALLOC; + + while (head->next) { + head = head->next; + } + + while(ecp_util_read_key(fd, &public, NULL) == ECP_OK) { + if (head->key_cnt == ACL_MAX_KEY) { + head->next = acl_create_item(); + if (head->next == NULL) return ECP_ERR_ALLOC; + head = head->next; + } + memcpy(&head->key[head->key_cnt], &public, sizeof(head->key[head->key_cnt])); + head->key_cnt++; + } + + return ECP_OK; +} + +static int _li2ht(ACLItem *head, int is_dir) { + int i; + int rv; + + while (head) { + for (i=0; ikey_cnt; i++) { + rv = _add_key(&head->key[i], is_dir ? ECP_DIR_CAP_DIR : 0); + if (rv) return rv; + } + head = head->next; + } + + return ECP_OK; +} + +int acl_add_key(ECPDirItem *dir_item) { + int rv; + + pthread_rwlock_wrlock(&acl_ht_rwlock); + rv = _add_key(&dir_item->node.key_perma.public, dir_item->capabilities); + pthread_rwlock_unlock(&acl_ht_rwlock); + + return rv; +} + +int acl_inlist(ecp_ecdh_public_t *public) { + void *item = NULL; + + pthread_rwlock_rdlock(&acl_ht_rwlock); + if (acl_keys) item = ecp_ht_search(acl_keys, public); + pthread_rwlock_unlock(&acl_ht_rwlock); + + return (item != NULL); +} + +int acl_dir_inlist(ecp_ecdh_public_t *public) { + void *item = NULL; + + pthread_rwlock_rdlock(&acl_ht_rwlock); + if (acl_keys_dir) item = ecp_ht_search(acl_keys_dir, public); + pthread_rwlock_unlock(&acl_ht_rwlock); + + return (item != NULL); +} + +int acl_reset_ht(void) { + int rv = ECP_OK; + + pthread_rwlock_wrlock(&acl_ht_rwlock); + if (acl_keys) ecp_ht_destroy(acl_keys); + if (acl_keys_dir) ecp_ht_destroy(acl_keys_dir); + acl_keys = ecp_ht_create_keys(); + acl_keys_dir = ecp_ht_create_keys(); + if ((acl_keys == NULL) || (acl_keys_dir == NULL)) rv = ECP_ERR_ALLOC; + pthread_rwlock_unlock(&acl_ht_rwlock); + + return rv; +} + +int acl_load_ht(void) { + int rv = ECP_OK; + int _rv; + + pthread_mutex_lock(&acl_li_mutex); + pthread_rwlock_wrlock(&acl_ht_rwlock); + + _rv = _li2ht(acl_head, 0); + if (_rv) rv = ECP_ERR; + _rv = _li2ht(acl_head_dir, 1); + if (_rv) rv = ECP_ERR; + + pthread_rwlock_unlock(&acl_ht_rwlock); + pthread_mutex_unlock(&acl_li_mutex); + + return rv; +} + +int acl_load(void) { + ACLItem *acl_new = NULL; + ACLItem *acl_dir_new = NULL; + int fd = -1; + int fd_dir = -1; + int rv = ECP_OK; + int _rv; + + if ((srv_config->acl_fn == NULL) && (srv_config->acl_fn_dir == NULL)) return ECP_OK; + + if (srv_config->acl_fn) { + fd = open(srv_config->acl_fn, O_RDONLY); + if (fd < 0) { + LOG(LOG_ERR, "acl_load: unable to open: %s\n", srv_config->acl_fn); + return ECP_ERR; + } + } + + if (srv_config->acl_fn_dir) { + fd_dir = open(srv_config->acl_fn_dir, O_RDONLY); + if (fd_dir < 0) { + LOG(LOG_ERR, "acl_load: unable to open: %s\n", srv_config->acl_fn_dir); + close(fd); + return ECP_ERR; + } + } + + pthread_mutex_lock(&acl_li_mutex); + if (fd >= 0) { + acl_new = acl_create_item(); + rv = _read_file(fd, acl_new); + if (rv) { + LOG(LOG_ERR, "acl_load: read from file: %s err:%d\n", srv_config->acl_fn, rv); + acl_destroy_list(acl_new); + goto load_fin; + } + } + + if (fd_dir >= 0) { + acl_dir_new = acl_create_item(); + rv = _read_file(fd_dir, acl_dir_new); + if (rv) { + LOG(LOG_ERR, "acl_load: read from file: %s err:%d\n", srv_config->acl_fn_dir, rv); + acl_destroy_list(acl_dir_new); + acl_destroy_list(acl_new); + goto load_fin; + } + } + if (acl_new) { + acl_destroy_list(acl_head); + acl_head = acl_new; + } + if (acl_dir_new) { + acl_destroy_list(acl_head_dir); + acl_head_dir = acl_dir_new; + } + + pthread_rwlock_wrlock(&acl_ht_rwlock); + if (acl_new) { + _rv = _li2ht(acl_new, 0); + if (_rv) rv = ECP_ERR; + } + if (acl_dir_new) { + _rv = _li2ht(acl_dir_new, 1); + if (_rv) rv = ECP_ERR; + } + + pthread_rwlock_unlock(&acl_ht_rwlock); + +load_fin: + pthread_mutex_unlock(&acl_li_mutex); + + close(fd_dir); + close(fd); + + return rv; +} + +int acl_init(void) { + int rv; + + srv_config = srv_get_config(); + + rv = pthread_mutex_init(&acl_li_mutex, NULL); + if (rv) return ECP_ERR; + + rv = pthread_rwlock_init(&acl_ht_rwlock, NULL); + if (rv) { + pthread_mutex_destroy(&acl_li_mutex); + return ECP_ERR; + } + + acl_keys = ecp_ht_create_keys(); + acl_keys_dir = ecp_ht_create_keys(); + if ((acl_keys == NULL) || (acl_keys_dir == NULL)) { + pthread_rwlock_destroy(&acl_ht_rwlock); + pthread_mutex_destroy(&acl_li_mutex); + if (acl_keys_dir) ecp_ht_destroy(acl_keys_dir); + if (acl_keys) ecp_ht_destroy(acl_keys); + return ECP_ERR_ALLOC; + } + + return ECP_OK; +} -- cgit v1.2.3