diff options
Diffstat (limited to 'storage/maria/libmarias3/src/response.c')
-rw-r--r-- | storage/maria/libmarias3/src/response.c | 512 |
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; +} |