1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5
6 #include <aws/auth/signing_result.h>
7
8 #include <aws/common/byte_buf.h>
9 #include <aws/common/string.h>
10
11 #define INITIAL_SIGNING_RESULT_PROPERTIES_SIZE 10
12 #define INITIAL_SIGNING_RESULT_PROPERTY_LISTS_TABLE_SIZE 10
13 #define INITIAL_SIGNING_RESULT_PROPERTY_LIST_SIZE 10
14
s_aws_signing_result_property_clean_up(struct aws_signing_result_property * pair)15 static void s_aws_signing_result_property_clean_up(struct aws_signing_result_property *pair) {
16 aws_string_destroy(pair->name);
17 aws_string_destroy(pair->value);
18 }
19
s_aws_hash_callback_property_list_destroy(void * value)20 static void s_aws_hash_callback_property_list_destroy(void *value) {
21 struct aws_array_list *property_list = value;
22
23 size_t property_count = aws_array_list_length(property_list);
24 for (size_t i = 0; i < property_count; ++i) {
25 struct aws_signing_result_property property;
26 AWS_ZERO_STRUCT(property);
27
28 if (aws_array_list_get_at(property_list, &property, i)) {
29 continue;
30 }
31
32 s_aws_signing_result_property_clean_up(&property);
33 }
34
35 struct aws_allocator *allocator = property_list->alloc;
36 aws_array_list_clean_up(property_list);
37
38 aws_mem_release(allocator, property_list);
39 }
40
aws_signing_result_init(struct aws_signing_result * result,struct aws_allocator * allocator)41 int aws_signing_result_init(struct aws_signing_result *result, struct aws_allocator *allocator) {
42 AWS_ZERO_STRUCT(*result);
43
44 result->allocator = allocator;
45 if (aws_hash_table_init(
46 &result->properties,
47 allocator,
48 INITIAL_SIGNING_RESULT_PROPERTIES_SIZE,
49 aws_hash_string,
50 aws_hash_callback_string_eq,
51 aws_hash_callback_string_destroy,
52 aws_hash_callback_string_destroy) ||
53 aws_hash_table_init(
54 &result->property_lists,
55 allocator,
56 INITIAL_SIGNING_RESULT_PROPERTY_LISTS_TABLE_SIZE,
57 aws_hash_string,
58 aws_hash_callback_string_eq,
59 aws_hash_callback_string_destroy,
60 s_aws_hash_callback_property_list_destroy)) {
61 goto on_error;
62 }
63
64 return AWS_OP_SUCCESS;
65
66 on_error:
67
68 aws_signing_result_clean_up(result);
69
70 return AWS_OP_ERR;
71 }
72
aws_signing_result_clean_up(struct aws_signing_result * result)73 void aws_signing_result_clean_up(struct aws_signing_result *result) {
74 aws_hash_table_clean_up(&result->properties);
75 aws_hash_table_clean_up(&result->property_lists);
76 }
77
aws_signing_result_set_property(struct aws_signing_result * result,const struct aws_string * property_name,const struct aws_byte_cursor * property_value)78 int aws_signing_result_set_property(
79 struct aws_signing_result *result,
80 const struct aws_string *property_name,
81 const struct aws_byte_cursor *property_value) {
82
83 struct aws_string *name = NULL;
84 struct aws_string *value = NULL;
85
86 name = aws_string_new_from_string(result->allocator, property_name);
87 value = aws_string_new_from_array(result->allocator, property_value->ptr, property_value->len);
88 if (name == NULL || value == NULL) {
89 goto on_error;
90 }
91
92 if (aws_hash_table_put(&result->properties, name, value, NULL)) {
93 goto on_error;
94 }
95
96 return AWS_OP_SUCCESS;
97
98 on_error:
99
100 aws_string_destroy(name);
101 aws_string_destroy(value);
102
103 return AWS_OP_ERR;
104 }
105
aws_signing_result_get_property(const struct aws_signing_result * result,const struct aws_string * property_name,struct aws_string ** out_property_value)106 int aws_signing_result_get_property(
107 const struct aws_signing_result *result,
108 const struct aws_string *property_name,
109 struct aws_string **out_property_value) {
110
111 struct aws_hash_element *element = NULL;
112 aws_hash_table_find(&result->properties, property_name, &element);
113
114 *out_property_value = NULL;
115 if (element != NULL) {
116 *out_property_value = element->value;
117 }
118
119 return AWS_OP_SUCCESS;
120 }
121
s_get_or_create_property_list(struct aws_signing_result * result,const struct aws_string * list_name)122 static struct aws_array_list *s_get_or_create_property_list(
123 struct aws_signing_result *result,
124 const struct aws_string *list_name) {
125 struct aws_hash_element *element = NULL;
126 aws_hash_table_find(&result->property_lists, list_name, &element);
127
128 if (element != NULL) {
129 return element->value;
130 }
131
132 struct aws_array_list *properties = aws_mem_acquire(result->allocator, sizeof(struct aws_array_list));
133 if (properties == NULL) {
134 return NULL;
135 }
136
137 AWS_ZERO_STRUCT(*properties);
138 struct aws_string *name_copy = aws_string_new_from_string(result->allocator, list_name);
139 if (name_copy == NULL) {
140 goto on_error;
141 }
142
143 if (aws_array_list_init_dynamic(
144 properties,
145 result->allocator,
146 INITIAL_SIGNING_RESULT_PROPERTY_LIST_SIZE,
147 sizeof(struct aws_signing_result_property))) {
148 goto on_error;
149 }
150
151 if (aws_hash_table_put(&result->property_lists, name_copy, properties, NULL)) {
152 goto on_error;
153 }
154
155 return properties;
156
157 on_error:
158
159 aws_string_destroy(name_copy);
160 aws_array_list_clean_up(properties);
161 aws_mem_release(result->allocator, properties);
162
163 return NULL;
164 }
165
aws_signing_result_append_property_list(struct aws_signing_result * result,const struct aws_string * list_name,const struct aws_byte_cursor * property_name,const struct aws_byte_cursor * property_value)166 int aws_signing_result_append_property_list(
167 struct aws_signing_result *result,
168 const struct aws_string *list_name,
169 const struct aws_byte_cursor *property_name,
170 const struct aws_byte_cursor *property_value) {
171
172 struct aws_array_list *properties = s_get_or_create_property_list(result, list_name);
173 if (properties == NULL) {
174 return AWS_OP_ERR;
175 }
176
177 struct aws_string *name = NULL;
178 struct aws_string *value = NULL;
179
180 name = aws_string_new_from_array(result->allocator, property_name->ptr, property_name->len);
181 value = aws_string_new_from_array(result->allocator, property_value->ptr, property_value->len);
182
183 struct aws_signing_result_property property;
184 property.name = name;
185 property.value = value;
186
187 if (aws_array_list_push_back(properties, &property)) {
188 goto on_error;
189 }
190
191 return AWS_OP_SUCCESS;
192
193 on_error:
194
195 aws_string_destroy(name);
196 aws_string_destroy(value);
197
198 return AWS_OP_ERR;
199 }
200
aws_signing_result_get_property_list(const struct aws_signing_result * result,const struct aws_string * list_name,struct aws_array_list ** out_list)201 void aws_signing_result_get_property_list(
202 const struct aws_signing_result *result,
203 const struct aws_string *list_name,
204 struct aws_array_list **out_list) {
205
206 *out_list = NULL;
207
208 struct aws_hash_element *element = NULL;
209 aws_hash_table_find(&result->property_lists, list_name, &element);
210
211 if (element != NULL) {
212 *out_list = element->value;
213 }
214 }
215
aws_signing_result_get_property_value_in_property_list(const struct aws_signing_result * result,const struct aws_string * list_name,const struct aws_string * property_name,struct aws_string ** out_value)216 void aws_signing_result_get_property_value_in_property_list(
217 const struct aws_signing_result *result,
218 const struct aws_string *list_name,
219 const struct aws_string *property_name,
220 struct aws_string **out_value) {
221
222 *out_value = NULL;
223
224 struct aws_array_list *property_list = NULL;
225 aws_signing_result_get_property_list(result, list_name, &property_list);
226 if (property_list == NULL) {
227 return;
228 }
229
230 size_t pair_count = aws_array_list_length(property_list);
231 for (size_t i = 0; i < pair_count; ++i) {
232 struct aws_signing_result_property pair;
233 AWS_ZERO_STRUCT(pair);
234 if (aws_array_list_get_at(property_list, &pair, i)) {
235 continue;
236 }
237
238 if (pair.name == NULL) {
239 continue;
240 }
241
242 if (aws_string_eq_ignore_case(property_name, pair.name)) {
243 *out_value = pair.value;
244 break;
245 }
246 }
247 }
248