signing.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/auth/signing.h>
  6. #include <aws/auth/credentials.h>
  7. #include <aws/auth/private/aws_signing.h>
  8. #include <aws/io/uri.h>
  9. /*
  10. * Aws signing implementation
  11. */
  12. static int s_aws_last_error_or_unknown(void) {
  13. int last_error = aws_last_error();
  14. if (last_error == AWS_ERROR_SUCCESS) {
  15. last_error = AWS_ERROR_UNKNOWN;
  16. }
  17. return last_error;
  18. }
  19. static void s_perform_signing(struct aws_signing_state_aws *state) {
  20. struct aws_signing_result *result = NULL;
  21. if (state->error_code != AWS_ERROR_SUCCESS) {
  22. goto done;
  23. }
  24. if (aws_credentials_is_anonymous(state->config.credentials)) {
  25. result = &state->result;
  26. goto done;
  27. }
  28. if (aws_signing_build_canonical_request(state)) {
  29. state->error_code = s_aws_last_error_or_unknown();
  30. AWS_LOGF_ERROR(
  31. AWS_LS_AUTH_SIGNING,
  32. "(id=%p) Signing failed to build canonical request via algorithm %s, error %d(%s)",
  33. (void *)state->signable,
  34. aws_signing_algorithm_to_string(state->config.algorithm),
  35. state->error_code,
  36. aws_error_debug_str(state->error_code));
  37. goto done;
  38. }
  39. AWS_LOGF_INFO(
  40. AWS_LS_AUTH_SIGNING,
  41. "(id=%p) Signing successfully built canonical request for algorithm %s, with contents \n" PRInSTR "\n",
  42. (void *)state->signable,
  43. aws_signing_algorithm_to_string(state->config.algorithm),
  44. AWS_BYTE_BUF_PRI(state->canonical_request));
  45. if (aws_signing_build_string_to_sign(state)) {
  46. state->error_code = s_aws_last_error_or_unknown();
  47. AWS_LOGF_ERROR(
  48. AWS_LS_AUTH_SIGNING,
  49. "(id=%p) Signing failed to build string-to-sign via algorithm %s, error %d(%s)",
  50. (void *)state->signable,
  51. aws_signing_algorithm_to_string(state->config.algorithm),
  52. state->error_code,
  53. aws_error_debug_str(state->error_code));
  54. goto done;
  55. }
  56. AWS_LOGF_INFO(
  57. AWS_LS_AUTH_SIGNING,
  58. "(id=%p) Signing successfully built string-to-sign via algorithm %s, with contents \n" PRInSTR "\n",
  59. (void *)state->signable,
  60. aws_signing_algorithm_to_string(state->config.algorithm),
  61. AWS_BYTE_BUF_PRI(state->string_to_sign));
  62. if (aws_signing_build_authorization_value(state)) {
  63. state->error_code = s_aws_last_error_or_unknown();
  64. AWS_LOGF_ERROR(
  65. AWS_LS_AUTH_SIGNING,
  66. "(id=%p) Signing failed to build final authorization value via algorithm %s",
  67. (void *)state->signable,
  68. aws_signing_algorithm_to_string(state->config.algorithm));
  69. goto done;
  70. }
  71. result = &state->result;
  72. done:
  73. state->on_complete(result, state->error_code, state->userdata);
  74. aws_signing_state_destroy(state);
  75. }
  76. static void s_aws_signing_on_get_credentials(struct aws_credentials *credentials, int error_code, void *user_data) {
  77. struct aws_signing_state_aws *state = user_data;
  78. if (!credentials) {
  79. if (error_code == AWS_ERROR_SUCCESS) {
  80. error_code = AWS_ERROR_UNKNOWN;
  81. }
  82. /* Log the credentials sourcing error */
  83. AWS_LOGF_ERROR(
  84. AWS_LS_AUTH_SIGNING,
  85. "(id=%p) Credentials Provider failed to source credentials with error %d(%s)",
  86. (void *)state->signable,
  87. error_code,
  88. aws_error_debug_str(error_code));
  89. state->error_code = AWS_AUTH_SIGNING_NO_CREDENTIALS;
  90. } else {
  91. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC &&
  92. !aws_credentials_is_anonymous(credentials)) {
  93. state->config.credentials = aws_credentials_new_ecc_from_aws_credentials(state->allocator, credentials);
  94. if (state->config.credentials == NULL) {
  95. state->error_code = AWS_AUTH_SIGNING_NO_CREDENTIALS;
  96. }
  97. } else {
  98. state->config.credentials = credentials;
  99. aws_credentials_acquire(credentials);
  100. }
  101. }
  102. s_perform_signing(state);
  103. }
  104. int aws_sign_request_aws(
  105. struct aws_allocator *allocator,
  106. const struct aws_signable *signable,
  107. const struct aws_signing_config_base *base_config,
  108. aws_signing_complete_fn *on_complete,
  109. void *userdata) {
  110. AWS_PRECONDITION(base_config);
  111. if (base_config->config_type != AWS_SIGNING_CONFIG_AWS) {
  112. return aws_raise_error(AWS_AUTH_SIGNING_MISMATCHED_CONFIGURATION);
  113. }
  114. const struct aws_signing_config_aws *config = (void *)base_config;
  115. struct aws_signing_state_aws *signing_state =
  116. aws_signing_state_new(allocator, config, signable, on_complete, userdata);
  117. if (!signing_state) {
  118. return AWS_OP_ERR;
  119. }
  120. if (signing_state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
  121. if (signing_state->config.credentials != NULL &&
  122. !aws_credentials_is_anonymous(signing_state->config.credentials)) {
  123. /*
  124. * If these are regular credentials, try to derive ecc-based ones
  125. */
  126. if (aws_credentials_get_ecc_key_pair(signing_state->config.credentials) == NULL) {
  127. struct aws_credentials *ecc_credentials =
  128. aws_credentials_new_ecc_from_aws_credentials(allocator, signing_state->config.credentials);
  129. aws_credentials_release(signing_state->config.credentials);
  130. signing_state->config.credentials = ecc_credentials;
  131. if (signing_state->config.credentials == NULL) {
  132. goto on_error;
  133. }
  134. }
  135. }
  136. }
  137. bool can_sign_immediately = signing_state->config.credentials != NULL;
  138. if (can_sign_immediately) {
  139. s_perform_signing(signing_state);
  140. } else {
  141. if (aws_credentials_provider_get_credentials(
  142. signing_state->config.credentials_provider, s_aws_signing_on_get_credentials, signing_state)) {
  143. goto on_error;
  144. }
  145. }
  146. return AWS_OP_SUCCESS;
  147. on_error:
  148. aws_signing_state_destroy(signing_state);
  149. return AWS_OP_ERR;
  150. }