diff --git a/Makefile.am b/Makefile.am index f92808d3..d075342e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -167,7 +167,8 @@ eap_sources = src/eap.c src/eap.h src/eap-private.h \ src/simauth.h src/simauth.c \ src/watchlist.h src/watchlist.c \ src/eap-tls-common.h src/eap-tls-common.c \ - src/mschaputil.h src/mschaputil.c + src/mschaputil.h src/mschaputil.c \ + src/erpcache.h src/erpcache.c if DAEMON libexec_PROGRAMS += src/iwd diff --git a/src/erpcache.c b/src/erpcache.c new file mode 100644 index 00000000..73aa8c5e --- /dev/null +++ b/src/erpcache.c @@ -0,0 +1,166 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "erpcache.h" + +#define ERP_DEFAULT_KEY_LIFETIME 86400000000 + +struct erp_cache_entry { + char *id; + void *emsk; + size_t emsk_len; + void *session_id; + size_t session_len; + char *erp_domain; + char *ssid; + uint64_t expire_time; +}; + +static struct l_queue *key_cache; + +static void destroy_entry(void *data) +{ + struct erp_cache_entry *entry = data; + + l_free(entry->id); + l_free(entry->emsk); + l_free(entry->session_id); + l_free(entry->ssid); + + if (entry->erp_domain) + l_free(entry->erp_domain); + + l_free(entry); +} + +void erp_add_key(const char *id, const void *session_id, + size_t session_len, const void *emsk, size_t emsk_len, + const char *ssid, const char *erp_domain) +{ + struct erp_cache_entry *entry; + + if (!unlikely(id || session_id || emsk)) + return; + + entry = l_new(struct erp_cache_entry, 1); + + entry->id = l_strdup(id); + entry->emsk = l_memdup(emsk, emsk_len); + entry->emsk_len = emsk_len; + entry->session_id = l_memdup(session_id, session_len); + entry->session_len = session_len; + entry->ssid = l_strdup(ssid); + entry->expire_time = l_time_offset(l_time_now(), + ERP_DEFAULT_KEY_LIFETIME); + + if (erp_domain) + entry->erp_domain = l_strdup(erp_domain); + + l_queue_push_head(key_cache, entry); +} + +static struct erp_cache_entry *find_keycache(const char *id, const char *ssid) +{ + const struct l_queue_entry *entry; + + for (entry = l_queue_get_entries(key_cache); entry; + entry = entry->next) { + struct erp_cache_entry *cache = entry->data; + + if (l_time_after(l_time_now(), cache->expire_time)) { + l_queue_remove(key_cache, cache); + destroy_entry(cache); + continue; + } + + if (id) { + if (strcmp(cache->id, id)) + continue; + } else if (ssid) { + if (strcmp(cache->ssid, ssid)) + continue; + } else + return NULL; + + return cache; + } + + return NULL; +} + +void erp_remove_key(const char *id) +{ + struct erp_cache_entry *entry = find_keycache(id, NULL); + + if (!entry) + return; + + l_queue_remove(key_cache, entry); + + destroy_entry(entry); +} + +bool erp_find_key_by_identity(const char *id, void *session, + size_t *session_len, void *emsk, size_t *emsk_len, + const char **erp_domain) +{ + struct erp_cache_entry *cache = find_keycache(id, NULL); + + if (!cache) + return false; + + memcpy(emsk, cache->emsk, cache->emsk_len); + *emsk_len = cache->emsk_len; + memcpy(session, cache->session_id, cache->session_len); + *session_len = cache->session_len; + *erp_domain = cache->erp_domain; + + return true; +} + +bool erp_has_key_for_ssid(const char *ssid) +{ + return find_keycache(NULL, ssid) != NULL; +} + +bool erp_has_key_for_identity(const char *id) +{ + return find_keycache(id, NULL) != NULL; +} + +void erp_init(void) +{ + key_cache = l_queue_new(); +} + +void erp_exit(void) +{ + l_queue_destroy(key_cache, destroy_entry); +} diff --git a/src/erpcache.h b/src/erpcache.h new file mode 100644 index 00000000..0b05fbea --- /dev/null +++ b/src/erpcache.h @@ -0,0 +1,38 @@ +/* + * + * Wireless daemon for Linux + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +void erp_add_key(const char *id, const void *session_id, size_t session_len, + const void *emsk, size_t emsk_len, + const char *ssid, const char *erp_domain); + +void erp_remove_key(const char *id); + +bool erp_find_key_by_identity(const char *id, void *session, + size_t *session_len, void *emsk, size_t *emsk_len, + const char **erp_domain); + +bool erp_has_key_for_ssid(const char *ssid); + +bool erp_has_key_for_identity(const char *id); + +void erp_init(void); +void erp_exit(void);