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.