summaryrefslogtreecommitdiffstats
path: root/storage/maria/libmarias3/src/response.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/maria/libmarias3/src/response.c')
-rw-r--r--storage/maria/libmarias3/src/response.c512
1 files changed, 512 insertions, 0 deletions
diff --git a/storage/maria/libmarias3/src/response.c b/storage/maria/libmarias3/src/response.c
new file mode 100644
index 00000000..4e976aba
--- /dev/null
+++ b/storage/maria/libmarias3/src/response.c
@@ -0,0 +1,512 @@
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * Copyright 2019 MariaDB Corporation Ab. 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 Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "common.h"
+
+#include "xml.h"
+
+char *parse_error_message(const char *data, size_t length)
+{
+ struct xml_document *doc = NULL;
+ struct xml_node *node = NULL;
+ struct xml_node *child = NULL;
+ struct xml_node *root = NULL;
+
+ uint64_t node_it = 0;
+
+ if (!data || !length)
+ {
+ return NULL;
+ }
+
+ doc = xml_parse_document((uint8_t*)data, length);
+
+ if (!doc)
+ {
+ return NULL;
+ }
+
+ root = xml_document_root(doc);
+
+ // First node is Error
+ child = xml_node_child(root, node_it);
+ // IAM / STS This will be Error and we need next child
+ if (!xml_node_name_cmp(child, "Error"))
+ {
+ node = xml_node_child(child, node_it);
+ }
+ else
+ {
+ node = child;
+ child = root;
+ }
+
+ if (!node)
+ {
+ xml_document_free(doc, false);
+ return NULL;
+ }
+
+ while(node)
+ {
+ if (!xml_node_name_cmp(node, "Message"))
+ {
+ struct xml_string *content = xml_node_content(node);
+ uint8_t *message = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, message, xml_string_length(content));
+ xml_document_free(doc, false);
+ return (char *)message;
+ }
+
+ node_it++;
+ node = xml_node_child(child, node_it);
+ }
+
+ xml_document_free(doc, false);
+ return NULL;
+}
+
+static ms3_list_st *get_next_list_ptr(struct ms3_list_container_st *container)
+{
+ ms3_list_st *new_alloc = NULL;
+ struct ms3_pool_alloc_list_st *new_pool_next = NULL;
+ struct ms3_pool_alloc_list_st *new_pool_prev = NULL;
+ ms3_list_st *ret = NULL;
+ if (container->pool_free == 0)
+ {
+ new_alloc = (ms3_list_st*)ms3_cmalloc(sizeof(ms3_list_st) * 1024);
+ new_pool_next = (struct ms3_pool_alloc_list_st*)ms3_cmalloc(sizeof(struct ms3_pool_alloc_list_st));
+
+ if (!new_alloc || !new_pool_next)
+ {
+ ms3debug("List realloc OOM");
+ return NULL;
+ }
+
+ new_pool_prev = container->pool_list;
+ container->pool_list = new_pool_next;
+ if (new_pool_prev)
+ {
+ container->pool_list->prev = new_pool_prev;
+ }
+ else
+ {
+ container->pool_list->prev = NULL;
+ }
+ container->pool_list->pool = new_alloc;
+
+ container->pool_free = 1024;
+ if (!container->start)
+ {
+ container->start = new_alloc;
+ }
+ container->pool = container->next = new_alloc;
+ }
+ else
+ {
+ container->next++;
+ }
+ ret = container->next;
+ container->pool_free--;
+ return ret;
+}
+
+uint8_t parse_list_response(const char *data, size_t length, struct ms3_list_container_st *list_container,
+ uint8_t list_version,
+ char **continuation)
+{
+ struct xml_document *doc;
+ struct xml_node *root;
+ struct xml_node *node;
+ struct xml_node *child;
+ char *filename = NULL;
+ char *filesize = NULL;
+ char *filedate = NULL;
+ size_t size = 0;
+ struct tm ttmp = {0};
+ time_t tout = 0;
+ bool truncated = false;
+ const char *last_key = NULL;
+ ms3_list_st *nextptr = NULL, *lastptr = list_container->next;
+ uint64_t node_it = 0;
+
+ // Empty list
+ if (!data || !length)
+ {
+ return 0;
+ }
+
+ doc = xml_parse_document((uint8_t*)data, length);
+
+ if (!doc)
+ {
+ return MS3_ERR_RESPONSE_PARSE;
+ }
+
+ /* For version 1:
+ * If IsTruncated is set, get the last key in the list, this will be used as
+ * "marker" in the next request.
+ * For version 2:
+ * If NextContinuationToken is set, use this for the next request
+ *
+ * We use the "continuation" return value for both
+ */
+
+ root = xml_document_root(doc);
+ // First node is ListBucketResponse
+ node = xml_node_child(root, 0);
+
+ do
+ {
+ if (!xml_node_name_cmp(node, "NextContinuationToken"))
+ {
+ struct xml_string *content = xml_node_content(node);
+ *continuation = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)*continuation, xml_string_length(content));
+ continue;
+ }
+
+ if (list_version == 1)
+ {
+ if (!xml_node_name_cmp(node, "IsTruncated"))
+ {
+ struct xml_string *content = xml_node_content(node);
+ char *trunc_value = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)trunc_value, xml_string_length(content));
+
+ if (!strcmp(trunc_value, "true"))
+ {
+ truncated = true;
+ }
+
+ ms3_cfree(trunc_value);
+ continue;
+ }
+ }
+
+ if (!xml_node_name_cmp(node, "Contents"))
+ {
+ bool skip = false;
+ uint64_t child_it = 0;
+ // Found contents
+ child = xml_node_child(node, 0);
+
+ do
+ {
+ if (!xml_node_name_cmp(child, "Key"))
+ {
+ struct xml_string *content = xml_node_content(child);
+ filename = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)filename, xml_string_length(content));
+
+ ms3debug("Filename: %s", filename);
+
+ if (filename[strlen((const char *)filename) - 1] == '/')
+ {
+ skip = true;
+ ms3_cfree(filename);
+ break;
+ }
+
+ continue;
+ }
+
+ if (!xml_node_name_cmp(child, "Size"))
+ {
+ struct xml_string *content = xml_node_content(child);
+ filesize = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)filesize, xml_string_length(content));
+
+ ms3debug("Size: %s", filesize);
+ size = strtoull((const char *)filesize, NULL, 10);
+ ms3_cfree(filesize);
+ continue;
+ }
+
+ if (!xml_node_name_cmp(child, "LastModified"))
+ {
+ struct xml_string *content = xml_node_content(child);
+ filedate = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)filedate, xml_string_length(content));
+
+ ms3debug("Date: %s", filedate);
+ strptime((const char *)filedate, "%Y-%m-%dT%H:%M:%SZ", &ttmp);
+ tout = mktime(&ttmp);
+ ms3_cfree(filedate);
+ continue;
+ }
+ }
+ while ((child = xml_node_child(node, ++child_it)));
+
+ if (!skip)
+ {
+ nextptr = get_next_list_ptr(list_container);
+ nextptr->next = NULL;
+
+ if (lastptr)
+ {
+ lastptr->next = nextptr;
+ }
+ lastptr = nextptr;
+
+ if (filename)
+ {
+ nextptr->key = (char *)filename;
+
+ if (list_version == 1)
+ {
+ last_key = nextptr->key;
+ }
+ }
+ else
+ {
+ nextptr->key = NULL;
+ }
+
+ nextptr->length = size;
+ nextptr->created = tout;
+ }
+
+ continue;
+ }
+
+ if (!xml_node_name_cmp(node, "CommonPrefixes"))
+ {
+ child = xml_node_child(node, 0);
+
+ if (!xml_node_name_cmp(child, "Prefix"))
+ {
+ struct xml_string *content = xml_node_content(child);
+ filename = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)filename, xml_string_length(content));
+
+ ms3debug("Filename: %s", filename);
+ nextptr = get_next_list_ptr(list_container);
+ nextptr->next = NULL;
+
+ if (lastptr)
+ {
+ lastptr->next = nextptr;
+ }
+ lastptr = nextptr;
+
+ nextptr->key = (char *)filename;
+ nextptr->length = 0;
+ nextptr->created = 0;
+ }
+ }
+
+ }
+ while ((node = xml_node_child(root, ++node_it)));
+
+ if (list_version == 1 && truncated && last_key)
+ {
+ *continuation = ms3_cstrdup(last_key);
+ }
+
+ xml_document_free(doc, false);
+ return 0;
+}
+
+uint8_t parse_role_list_response(const char *data, size_t length, char *role_name, char *arn, char **continuation)
+{
+ struct xml_document *doc;
+ struct xml_node *root;
+ struct xml_node *list_role_result;
+ struct xml_node *child;
+ struct xml_node *roles;
+ struct xml_node *member;
+
+ char *response_role_name = NULL;
+ char *response_role_arn = NULL;
+ uint64_t node_it = 0;
+
+ // Empty list
+ if (!data || !length)
+ {
+ return 0;
+ }
+
+ doc = xml_parse_document((uint8_t*)data, length);
+
+ if (!doc)
+ {
+ return MS3_ERR_RESPONSE_PARSE;
+ }
+
+ root = xml_document_root(doc);
+ // First node is listRoleResponse
+ list_role_result = xml_node_child(root, 0);
+ child = xml_node_child(list_role_result, 0);
+
+ do
+ {
+
+ if (!xml_node_name_cmp(child, "Marker"))
+ {
+ struct xml_string *content = xml_node_content(child);
+ *continuation = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)*continuation, xml_string_length(content));
+ continue;
+ }
+
+ if (!xml_node_name_cmp(child, "Roles"))
+ {
+ uint64_t child_it = 0;
+ // Found contents
+ roles = xml_node_child(child, 0);
+ do
+ {
+ // go down one more child to get members
+ uint64_t roles_it = 0;
+ member = xml_node_child(roles, 0);
+ do
+ {
+ if (!xml_node_name_cmp(member, "RoleName"))
+ {
+ struct xml_string *content = xml_node_content(member);
+ response_role_name = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)response_role_name, xml_string_length(content));
+ continue;
+ }
+ if (!xml_node_name_cmp(member, "Arn"))
+ {
+ struct xml_string *content = xml_node_content(member);
+ response_role_arn = ms3_cmalloc(xml_string_length(content) + 1);
+ xml_string_copy(content, (uint8_t*)response_role_arn, xml_string_length(content));
+ continue;
+ }
+ }
+ while ((member = xml_node_child(roles, ++roles_it)));
+ if (!strcmp(response_role_name, role_name))
+ {
+ ms3debug("Role Found ARN = %s",response_role_arn);
+ sprintf(arn, "%s", response_role_arn);
+ ms3_cfree(response_role_name);
+ ms3_cfree(response_role_arn);
+ xml_document_free(doc, false);
+ return MS3_ERR_NONE;
+ }
+ ms3_cfree(response_role_name);
+ ms3_cfree(response_role_arn);
+ }
+ while ((roles = xml_node_child(child, ++child_it)));
+ }
+ }
+ while ((child = xml_node_child(list_role_result, ++node_it)));
+
+ xml_document_free(doc, false);
+ return MS3_ERR_NOT_FOUND;
+}
+
+uint8_t parse_assume_role_response(const char *data, size_t length, char *assume_role_key, char *assume_role_secret, char *assume_role_token)
+{
+ struct xml_document *doc;
+ struct xml_node *root;
+ struct xml_node *assume_role_result;
+ struct xml_node *child;
+ struct xml_node *credentials;
+ uint64_t node_it = 0;
+
+ // Empty list
+ if (!data || !length)
+ {
+ return 0;
+ }
+
+ doc = xml_parse_document((uint8_t*)data, length);
+
+ if (!doc)
+ {
+ return MS3_ERR_RESPONSE_PARSE;
+ }
+
+ root = xml_document_root(doc);
+ // First node is AssumeRoleResponse
+ assume_role_result = xml_node_child(root, 0);
+ child = xml_node_child(assume_role_result, 0);
+
+ do
+ {
+ if (!xml_node_name_cmp(child, "Credentials"))
+ {
+ uint64_t child_it = 0;
+ // Found contents
+ credentials = xml_node_child(child, 0);
+ do
+ {
+ if (!xml_node_name_cmp(credentials, "AccessKeyId"))
+ {
+ struct xml_string *content = xml_node_content(credentials);
+ size_t content_length = xml_string_length(content);
+ assume_role_key[0] = '\0';
+
+ if (content_length >= 128)
+ {
+ ms3debug("AccessKeyId error length = %zu", content_length);
+ xml_document_free(doc, false);
+ return MS3_ERR_AUTH_ROLE;
+ }
+ xml_string_copy(content, (uint8_t*)assume_role_key, content_length);
+
+ continue;
+ }
+ if (!xml_node_name_cmp(credentials, "SecretAccessKey"))
+ {
+ struct xml_string *content = xml_node_content(credentials);
+ size_t content_length = xml_string_length(content);
+ assume_role_secret[0] = '\0';
+
+ if (content_length >= 1024)
+ {
+ ms3debug("SecretAccessKey error length = %zu", content_length);
+ xml_document_free(doc, false);
+ return MS3_ERR_AUTH_ROLE;
+ }
+ xml_string_copy(content, (uint8_t*)assume_role_secret, content_length);
+
+ continue;
+ }
+ if (!xml_node_name_cmp(credentials, "SessionToken"))
+ {
+ struct xml_string *content = xml_node_content(credentials);
+ size_t content_length = xml_string_length(content);
+ assume_role_token[0] = '\0';
+
+ if (content_length >= 2048)
+ {
+ ms3debug("SessionToken error length = %zu", content_length);
+ xml_document_free(doc, false);
+ return MS3_ERR_AUTH_ROLE;
+ }
+ xml_string_copy(content, (uint8_t*)assume_role_token, content_length);
+
+ continue;
+ }
+ }
+ while ((credentials = xml_node_child(child, ++child_it)));
+ }
+ }
+ while ((child = xml_node_child(assume_role_result, ++node_it)));
+
+ xml_document_free(doc, false);
+
+ return MS3_ERR_NONE;
+}