20 #include "awssignaturev3.h"
21 #include "awssignaturev3_p.h"
23 #include "awsendpoint.h"
28 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
29 #include "qmessageauthenticationcode.h"
31 #include <QMessageAuthenticationCode>
62 const QNetworkAccessManager::Operation operation,
63 QNetworkRequest &request,
const QByteArray &data)
const
69 if ((d->isHttps(request)) && (!request.hasRawHeader(
"x-amz-nonce"))) {
70 request.setRawHeader(
"x-amz-nonce", QUuid::createUuid().toByteArray().mid(1,36));
73 d->setDateHeader(request);
74 d->setAuthorizationHeader(credentials, operation, request, data);
123 case QCryptographicHash::Sha1:
return "HmacSHA1";
124 case QCryptographicHash::Sha256:
return "HmacSHA256";
126 Q_ASSERT_X(
false, Q_FUNC_INFO,
"invalid algorithm");
127 return "invalid-algorithm";
149 const QNetworkAccessManager::Operation operation,
150 QNetworkRequest &request,
const QByteArray &payload)
const
153 QByteArray signedHeaders;
154 QByteArray stringToSign =
canonicalRequest(operation, request, payload, &signedHeaders);
156 stringToSign = QCryptographicHash::hash(stringToSign,
hashAlgorithm);
158 const QByteArray signature = QMessageAuthenticationCode::hash(
163 QByteArray((
isHttps(request)) ?
"AWS3-HTTPS " :
"AWS3 ") +
164 "AWSAccessKeyId=" + credentials.
accessKeyId().toUtf8() +
","
166 ((!
isHttps(request)) ?
"SignedHeaders=" + signedHeaders +
',' :
"") +
167 "Signature=" + signature.toBase64();
194 QByteArray header = headerName.toLower() +
':';
195 const QByteArray trimmedHeaderValue = headerValue.trimmed();
196 bool isInQuotes =
false;
197 char previousChar =
'\0';
198 for (
int index = 0; index < trimmedHeaderValue.size(); ++index) {
199 char thisChar = trimmedHeaderValue.at(index);
202 if ((thisChar ==
'"') && (previousChar !=
'\\'))
205 if ((thisChar ==
'"') && (previousChar !=
'\\')) {
207 }
else if (isspace(thisChar)) {
208 while ((index < trimmedHeaderValue.size()-1) &&
209 (isspace(trimmedHeaderValue.at(index+1))))
213 previousChar = thisChar;
243 Q_CHECK_PTR(signedHeaders);
244 signedHeaders->clear();
252 QMap<QByteArray,QByteArray> headers;
253 foreach (
const QByteArray &rawHeader, request.rawHeaderList()) {
254 headers.insert(rawHeader.toLower(), request.rawHeader(rawHeader));
257 headers.insert(
"host", request.url().host().toUtf8());
261 for (QMap<QByteArray,QByteArray>::const_iterator iter = headers.constBegin(); iter != headers.constEnd(); ++iter) {
266 if ((iter.key() ==
"host") || (iter.key().startsWith(
"x-amz-"))) {
268 if (!signedHeaders->isEmpty()) *signedHeaders +=
';';
269 *signedHeaders += iter.key();
293 const QNetworkRequest &request,
const QByteArray &payload,
294 QByteArray *
const signedHeaders)
const
298 Q_ASSERT((request.hasRawHeader(
"x-amz-date")) || (request.hasRawHeader(
"Date")));
299 QByteArray
canonicalRequest = request.rawHeader(request.hasRawHeader(
"x-amz-date") ?
"x-amz-date" :
"Date");
300 if (request.hasRawHeader(
"x-amz-nonce")) {
301 canonicalRequest += request.rawHeader(
"x-amz-nonce");
307 return httpMethod(operation).toUtf8() +
'\n' +
323 return (request.url().scheme() == QLatin1String(
"https"));
341 const QNetworkAccessManager::Operation operation,
342 QNetworkRequest &request,
const QByteArray &payload)
const
344 Q_ASSERT(!request.hasRawHeader(
"Authorization"));
360 Q_ASSERT(dateTime.timeSpec() == Qt::UTC);
361 if (!request.hasRawHeader(
"x-amz-date")) {
362 request.setRawHeader(
"x-amz-date", dateTime.toString(QLatin1String(
"ddd, dd MMM yyyy hh:mm:ss 'GMT'")).toUtf8());
virtual void sign(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &data=QByteArray()) const
Sign an AWS request.
void setAuthorizationHeader(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload) const
Set authorization header on a network request.
AwsSignatureV3(const QCryptographicHash::Algorithm hashAlgorithm=QCryptographicHash::Sha256)
Constructs a new AwsSignatureV3 object.
QByteArray authorizationHeaderValue(const AwsAbstractCredentials &credentials, const QNetworkAccessManager::Operation operation, QNetworkRequest &request, const QByteArray &payload) const
Create an AWS V3 Signature authorization header value.
Private implementation for AwsAbstractSignature.
QByteArray canonicalQuery(const QUrlQuery &query) const
Create an AWS Signature canonical query.
virtual QString secretKey() const =0
AWS secret access key for this credentials object.
AwsSignatureV3Private(const QCryptographicHash::Algorithm hashAlgorithm, AwsSignatureV3 *const q)
Constructs a new AwsSignatureV3Private object.
Interface class for providing AWS credentials.
QByteArray canonicalHeader(const QByteArray &headerName, const QByteArray &headerValue) const
Create an AWS V3 Signature canonical header string.
Private implementation for AwsSignatureV3.
QByteArray algorithmDesignation(const QCryptographicHash::Algorithm algorithm) const
Create an AWS V3 Signature algorithm designation.
QByteArray canonicalHeaders(const QNetworkRequest &request, QByteArray *const signedHeaders) const
Create an AWS V3 Signature canonical headers string.
virtual QString accessKeyId() const =0
AWS access key ID for this credentials object.
void setDateHeader(QNetworkRequest &request, const QDateTime &dateTime=QDateTime::currentDateTimeUtc()) const
Set the AWS custom date header.
QByteArray canonicalRequest(const QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload, QByteArray *const signedHeaders) const
Create an AWS V3 Signature canonical request.
Implements AWS Signature Version 3.
virtual int version() const
AWS Signature version implemented by this class.
static bool isHttps(const QNetworkRequest &request)
Does a request use the HTTPS scheme?
const QCryptographicHash::Algorithm hashAlgorithm
Hash algorithm to use when signing.
QString httpMethod(const QNetworkAccessManager::Operation operation) const
Create an AWS Signature request method string.
Interface class for providing AWS signatures.
QString canonicalPath(const QUrl &url) const
Create an AWS Signature canonical path.