diff --git a/bootloader/grub.c b/bootloader/grub.c
index 2f6172e..dc35718 100644
--- a/bootloader/grub.c
+++ b/bootloader/grub.c
@@ -153,8 +153,10 @@ static inline void grubenv_update_size(struct grubenv_t *grubenv)
 
 	/* lengths of strings + '=' and '\n' characters */
 	LIST_FOREACH(grubvar, &grubenv->vars, next) {
-		size = size + strlen(grubvar->key) +
-						strlen(grubvar->value) + 2;
+		char *key = dict_entry_get_key(grubvar);
+		char *value = dict_entry_get_value(grubvar);
+
+		size = size + strlen(key) + strlen(value) + 2;
 	}
 	size += strlen(GRUBENV_HEADER);
 	grubenv->size = size;
@@ -194,10 +196,12 @@ static int grubenv_write(struct grubenv_t *grubenv)
 	strncpy(buf, GRUBENV_HEADER, strlen(GRUBENV_HEADER) + 1);
 
 	LIST_FOREACH(grubvar, &grubenv->vars, next) {
-		llen = strlen(grubvar->key) + strlen(grubvar->value) + 2;
+		char *key = dict_entry_get_key(grubvar);
+		char *value = dict_entry_get_value(grubvar);
+
+		llen = strlen(key) + strlen(value) + 2;
 		/* +1 for null termination */
-		snprintf(line, llen + 1, "%s=%s\n", grubvar->key,
-						grubvar->value);
+		snprintf(line, llen + 1, "%s=%s\n", key, value);
 		strncat(buf, line, llen);
 	}
 
@@ -237,11 +241,7 @@ cleanup:
  * allocation */
 static inline void grubenv_close(struct grubenv_t *grubenv)
 {
-	struct dict_entry *grubvar;
-
-	LIST_FOREACH(grubvar, &grubenv->vars, next) {
-		dict_remove(&grubenv->vars, grubvar->key);
-	}
+	dict_drop_db(&grubenv->vars);
 }
 
 /* I feel that '#' and '=' characters should be forbidden. Although it's not
diff --git a/corelib/installer.c b/corelib/installer.c
index e5bf895..f778d8b 100644
--- a/corelib/installer.c
+++ b/corelib/installer.c
@@ -206,11 +206,12 @@ static int prepare_boot_script(struct swupdate_cfg *cfg, const char *script)
 		return -1;
 
 	LIST_FOREACH(bootvar, &cfg->bootloader, next) {
-		if (!bootvar->key || !bootvar->value)
+		char *key = dict_entry_get_key(bootvar);
+		char *value = dict_entry_get_value(bootvar);
+
+		if (!key || !value)
 			continue;
-		snprintf(buf, sizeof(buf), "%s %s\n",
-			bootvar->key,
-			bootvar->value);
+		snprintf(buf, sizeof(buf), "%s %s\n", key, value);
 		if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) {
 			  TRACE("Error saving temporary file");
 			  ret = -1;
diff --git a/corelib/swupdate_dict.c b/corelib/swupdate_dict.c
index 2cdad47..be21ff2 100644
--- a/corelib/swupdate_dict.c
+++ b/corelib/swupdate_dict.c
@@ -2,6 +2,9 @@
  * (C) Copyright 2016
  * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
  *
+ * Copyright (C) 2018 Weidmüller Interface GmbH & Co. KG
+ * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+ *
  * SPDX-License-Identifier:     GPL-2.0-or-later
  */
 
@@ -19,7 +22,52 @@
 #include "util.h"
 #include "swupdate_dict.h"
 
-static struct dict_entry *get_entry(struct dict *dictionary, char *key)
+static int insert_list_elem(struct dict_list *list, const char *value)
+{
+	struct dict_list_elem *elem = (struct dict_list_elem *)malloc(sizeof(*elem));
+
+	if (!elem)
+		return -ENOMEM;
+
+	memset(elem, 0, sizeof(*elem));
+	elem->value = strdup(value);
+
+	LIST_INSERT_HEAD(list, elem, next);
+
+	return 0;
+}
+
+static void remove_list_elem(struct dict_list_elem *elem)
+{
+	LIST_REMOVE(elem, next);
+	free(elem->value);
+	free(elem);
+}
+
+static void remove_list(struct dict_list *list)
+{
+	struct dict_list_elem *elem;
+
+	LIST_FOREACH(elem, list, next) {
+		remove_list_elem(elem);
+	}
+}
+
+static struct dict_entry *insert_entry(struct dict *dictionary, const char *key)
+{
+	struct dict_entry *entry = (struct dict_entry *)malloc(sizeof(*entry));
+	if (!entry)
+		return NULL;
+
+	memset(entry, 0, sizeof(*entry));
+	entry->key = strdup(key);
+
+	LIST_INSERT_HEAD(dictionary, entry, next);
+
+	return entry;
+}
+
+static struct dict_entry *get_entry(struct dict *dictionary, const char *key)
 {
 	struct dict_entry *entry;
 
@@ -31,72 +79,92 @@ static struct dict_entry *get_entry(struct dict *dictionary, char *key)
 	return NULL;
 }
 
-int dict_insert_entry(struct dict *dictionary, char *key, char *value)
+static void remove_entry(struct dict_entry *entry)
 {
-	struct dict_entry *entry = (struct dict_entry *)malloc(sizeof(*entry));
+	LIST_REMOVE(entry, next);
+	free(entry->key);
+	remove_list(&entry->list);
+	free(entry);
+}
 
+char *dict_entry_get_key(struct dict_entry *entry)
+{
 	if (!entry)
-		return -ENOMEM;
+		return NULL;
 
-	memset(entry, 0, sizeof(*entry));
-	entry->key = strdup(key);
-	entry->value = strdup(value);
+	return entry->key;
+}
 
-	LIST_INSERT_HEAD(dictionary, entry, next);
+char *dict_entry_get_value(struct dict_entry *entry)
+{
+	if (!entry || !LIST_FIRST(&entry->list))
+		return NULL;
 
-	return 0;
+	return LIST_FIRST(&entry->list)->value;
 }
 
-char *dict_get_value(struct dict *dictionary, char *key)
+struct dict_list *dict_get_list(struct dict *dictionary, const char *key)
 {
 	struct dict_entry *entry = get_entry(dictionary, key);
 
 	if (!entry)
 		return NULL;
 
-	return entry->value;
+	return &entry->list;
 }
 
-int dict_set_value(struct dict *dictionary, char *key, char *value)
+char *dict_get_value(struct dict *dictionary, const char *key)
 {
 	struct dict_entry *entry = get_entry(dictionary, key);
 
-	/*
-	 * Set to new value if key is already in
-	 * dictionary
-	 */
-	if (entry) {
-		LIST_REMOVE(entry, next);
-		free(entry);
-	}
+	if (!entry)
+		return NULL;
 
-	return dict_insert_entry(dictionary, key, value);
+	return dict_entry_get_value(entry);
 }
 
-void dict_remove_entry(struct dict_entry *entry)
+int dict_insert_value(struct dict *dictionary, const char *key, const char *value)
 {
-	LIST_REMOVE(entry, next);
-	free(entry->key);
-	free(entry->value);
-	free(entry);
+	struct dict_entry *entry = get_entry(dictionary, key);
+
+	if (!entry) {
+		entry = insert_entry(dictionary, key);
+		if (!entry)
+			return -ENOMEM;
+	}
+
+	return insert_list_elem(&entry->list, value);
 }
 
-void dict_remove(struct dict *dictionary, char *key)
+int dict_set_value(struct dict *dictionary, const char *key, const char *value)
 {
+	struct dict_entry *entry = get_entry(dictionary, key);
+
+	if (entry)
+		remove_entry(entry);
 
+	entry = insert_entry(dictionary, key);
+	if (!entry)
+		return -ENOMEM;
+
+	return insert_list_elem(&entry->list, value);
+}
+
+void dict_remove(struct dict *dictionary, const char *key)
+{
 	struct dict_entry *entry = get_entry(dictionary, key);
 
 	if (!entry)
 		return;
 
-	dict_remove_entry(entry);
+	remove_entry(entry);
 }
 
 void dict_drop_db(struct dict *dictionary)
 {
-	struct dict_entry *var;
+	struct dict_entry *entry;
 
-	LIST_FOREACH(var, dictionary, next) {
-		dict_remove_entry(var);
+	LIST_FOREACH(entry, dictionary, next) {
+		remove_entry(entry);
 	}
 }
diff --git a/handlers/swuforward_handler.c b/handlers/swuforward_handler.c
index c804628..8b0c17f 100644
--- a/handlers/swuforward_handler.c
+++ b/handlers/swuforward_handler.c
@@ -292,7 +292,7 @@ static int install_remote_swu(struct img_type *img,
 	struct hnd_priv priv;
 	struct curlconn *conn;
 	int ret, still_running = 0;
-	struct dict_entry *url;
+	struct dict_list_elem *url;
 	struct curl_slist *headerlist;
 	CURLMsg *msg = NULL;
 
@@ -320,16 +320,9 @@ static int install_remote_swu(struct img_type *img,
 	priv.maxwaitms = MAX_WAIT_MS;
 	priv.size = img->size;
 
-	/*
-	 * Parse handler properties to get URLs for destination
-	 *
-	 */
-	LIST_FOREACH(url, &img->properties, next) {
+	LIST_FOREACH(url, dict_get_list(&img->properties, "url"), next) {
 		char curlheader[SWUPDATE_GENERAL_STRING_SIZE + strlen(CUSTOM_HEADER)];
 
-		if (!url->key || !url->value || strcmp(url->key, "url"))
-			continue;
-
 		conn = (struct curlconn *)calloc(1, sizeof(struct curlconn));
 		if (!conn) {
 			ERROR("FAULT: no memory");
diff --git a/include/swupdate_dict.h b/include/swupdate_dict.h
index 2cae5ca..82988ac 100644
--- a/include/swupdate_dict.h
+++ b/include/swupdate_dict.h
@@ -10,19 +10,29 @@
 
 #include <bsdqueue.h>
 
+struct dict_list_elem {
+	char *value;
+	LIST_ENTRY(dict_list_elem) next;
+};
+
+LIST_HEAD(dict_list, dict_list_elem);
+
 struct dict_entry {
 	char *key;
-	char *value;
+	struct dict_list list;
 	LIST_ENTRY(dict_entry) next;
 };
 
 LIST_HEAD(dict, dict_entry);
 
-char *dict_get_value(struct dict *dictionary, char *key);
-int dict_set_value(struct dict *dictionary, char *key, char *value);
-int dict_insert_entry(struct dict *dictionary, char *key, char *value);
-void dict_remove(struct dict *dictionary, char *key);
-void dict_remove_entry(struct dict_entry *entry);
+char *dict_entry_get_key(struct dict_entry *entry);
+char *dict_entry_get_value(struct dict_entry *entry);
+
+struct dict_list *dict_get_list(struct dict *dictionary, const char *key);
+char *dict_get_value(struct dict *dictionary, const char *key);
+int dict_set_value(struct dict *dictionary, const char *key, const char *value);
+int dict_insert_value(struct dict *dictionary, const char *key, const char *value);
+void dict_remove(struct dict *dictionary, const char *key);
 void dict_drop_db(struct dict *dictionary);
 
 #endif
diff --git a/parser/parser.c b/parser/parser.c
index 04cd549..2e9208d 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -162,7 +162,7 @@ static void add_properties(parsertype p, void *node, struct img_type *image)
 				key,
 				value
 			);
-			if (dict_insert_entry(&image->properties, key, value))
+			if (dict_insert_value(&image->properties, key, value))
 				ERROR("Property not stored, skipping...");
 
 		}
diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c
index c84de65..02ffb3a 100644
--- a/suricatta/server_hawkbit.c
+++ b/suricatta/server_hawkbit.c
@@ -1336,7 +1336,10 @@ int get_target_data_length(void)
 	struct dict_entry *entry;
 
 	LIST_FOREACH(entry, &server_hawkbit.configdata, next) {
-		len += strlen(entry->key) + strlen(entry->value) + strlen (" : ") + 6;
+		char *key = dict_entry_get_key(entry);
+		char *value = dict_entry_get_value(entry);
+
+		len += strlen(key) + strlen(value) + strlen (" : ") + 6;
 	}
 
 	return len;
@@ -1367,17 +1370,20 @@ server_op_res_t server_send_target_data(void)
 
 	char *keyvalue = NULL;
 	LIST_FOREACH(entry, &server_hawkbit.configdata, next) {
+		char *key = dict_entry_get_key(entry);
+		char *value = dict_entry_get_value(entry);
+
 		if (ENOMEM_ASPRINTF ==
 		    asprintf(&keyvalue, config_data,
 				((first) ? ' ' : ','),
-				entry->key,
-				entry->value)) {
+				key,
+				value)) {
 			ERROR("hawkBit server reply cannot be sent because of OOM.\n");
 			result = SERVER_EINIT;
 			goto cleanup;
 		}
 		first = false;
-		TRACE("KEYVALUE=%s %s %s", keyvalue, entry->key, entry->value);
+		TRACE("KEYVALUE=%s %s %s", keyvalue, key, value);
 		strcat(configData, keyvalue);
 		free(keyvalue);
 
