1 /*
2   Licensed to the Apache Software Foundation (ASF) under one
3   or more contributor license agreements.  See the NOTICE file
4   distributed with this work for additional information
5   regarding copyright ownership.  The ASF licenses this file
6   to you under the Apache License, Version 2.0 (the
7   "License"); you may not use this file except in compliance
8   with the License.  You may obtain a copy of the License at
9 
10   http://www.apache.org/licenses/LICENSE-2.0
11 
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   See the License for the specific language governing permissions and
16   limitations under the License.
17 */
18 
19 /**
20  * @file aws_auth_v4.h
21  * @brief AWS Auth v4 signing utility.
22  * @see aws_auth_v4.cc
23  */
24 
25 #pragma once
26 
27 #include <algorithm> /* transform() */
28 #include <cstddef>   /* size_t */
29 #include <string>    /* std::string */
30 #include <sstream>   /* std::stringstream */
31 #include <map>       /* std::map */
32 #include <set>       /* std::set */
33 
34 #include <ts/ts.h>
35 
36 typedef std::string String;
37 typedef std::set<std::string> StringSet;
38 typedef std::map<std::string, std::string> StringMap;
39 typedef std::multimap<std::string, std::string> HeaderMultiMap;
40 
41 class HeaderIterator;
42 
43 class TsInterface
44 {
45 public:
~TsInterface()46   virtual ~TsInterface(){};
47   virtual const char *getMethod(int *length) = 0;
48   virtual const char *getHost(int *length)   = 0;
49   virtual const char *getPath(int *length)   = 0;
50   virtual const char *getQuery(int *length)  = 0;
51   virtual HeaderIterator headerBegin()       = 0;
52   virtual HeaderIterator headerEnd()         = 0;
53 };
54 
55 #ifdef AWS_AUTH_V4_UNIT_TEST
56 #include "unit_tests/test_aws_auth_v4.h"
57 #else
58 #include "aws_auth_v4_wrap.h"
59 #endif
60 
61 /* S3 auth v4 utility API */
62 
63 static const String X_AMZ_CONTENT_SHA256 = "x-amz-content-sha256";
64 static const String X_AMX_DATE           = "x-amz-date";
65 static const String X_AMZ_SECURITY_TOKEN = "x-amz-security-token";
66 static const String X_AMZ                = "x-amz-";
67 static const String CONTENT_TYPE         = "content-type";
68 static const String HOST                 = "host";
69 
70 String trimWhiteSpaces(const String &s);
71 
72 template <typename ContainerType>
73 void
74 commaSeparateString(ContainerType &ss, const String &input, bool trim = true, bool lowerCase = true)
75 {
76   std::istringstream istr(input);
77   String token;
78 
79   while (std::getline(istr, token, ',')) {
trimWhiteSpaces(token)80     token = trim ? trimWhiteSpaces(token) : token;
81     if (lowerCase) {
82       std::transform(token.begin(), token.end(), token.begin(), ::tolower);
83     }
84     ss.insert(ss.end(), token);
85   }
86 }
87 
88 class AwsAuthV4
89 {
90 public:
91   AwsAuthV4(TsInterface &api, time_t *now, bool signPayload, const char *awsAccessKeyId, size_t awsAccessKeyIdLen,
92             const char *awsSecretAccessKey, size_t awsSecretAccessKeyLen, const char *awsService, size_t awsServiceLen,
93             const StringSet &includedHeaders, const StringSet &excludedHeaders, const StringMap &regionMap);
94   const char *getDateTime(size_t *dateTimeLen);
95   String getPayloadHash();
96   String getAuthorizationHeader();
97 
98 private:
99   TsInterface &_api;
100   char _dateTime[sizeof "20170428T010203Z"];
101   bool _signPayload               = false;
102   const char *_awsAccessKeyId     = nullptr;
103   size_t _awsAccessKeyIdLen       = 0;
104   const char *_awsSecretAccessKey = nullptr;
105   size_t _awsSecretAccessKeyLen   = 0;
106   const char *_awsService         = nullptr;
107   size_t _awsServiceLen           = 0;
108 
109   const StringSet &_includedHeaders;
110   const StringSet &_excludedHeaders;
111   const StringMap &_regionMap;
112 };
113